ClangUserExpression.cpp revision 65dafa8344c8c018e346dd331a7782081a896239
165dafa8344c8c018e346dd331a7782081a896239Sean Callanan//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
265dafa8344c8c018e346dd331a7782081a896239Sean Callanan//
365dafa8344c8c018e346dd331a7782081a896239Sean Callanan//                     The LLVM Compiler Infrastructure
465dafa8344c8c018e346dd331a7782081a896239Sean Callanan//
565dafa8344c8c018e346dd331a7782081a896239Sean Callanan// This file is distributed under the University of Illinois Open Source
665dafa8344c8c018e346dd331a7782081a896239Sean Callanan// License. See LICENSE.TXT for details.
765dafa8344c8c018e346dd331a7782081a896239Sean Callanan//
865dafa8344c8c018e346dd331a7782081a896239Sean Callanan//===----------------------------------------------------------------------===//
965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
1065dafa8344c8c018e346dd331a7782081a896239Sean Callanan// C Includes
1165dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include <stdio.h>
1265dafa8344c8c018e346dd331a7782081a896239Sean Callanan#if HAVE_SYS_TYPES_H
1365dafa8344c8c018e346dd331a7782081a896239Sean Callanan#  include <sys/types.h>
1465dafa8344c8c018e346dd331a7782081a896239Sean Callanan#endif
1565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
1665dafa8344c8c018e346dd331a7782081a896239Sean Callanan// C++ Includes
1765dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include <cstdlib>
1865dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include <string>
1965dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include <map>
2065dafa8344c8c018e346dd331a7782081a896239Sean Callanan
2165dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Core/ConstString.h"
2265dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Core/Log.h"
2365dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Core/StreamString.h"
2465dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Expression/ClangExpressionDeclMap.h"
2565dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Expression/ClangExpressionParser.h"
2665dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Expression/ClangFunction.h"
2765dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Expression/ASTResultSynthesizer.h"
2865dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Expression/ClangUserExpression.h"
2965dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Host/Host.h"
3065dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Target/ExecutionContext.h"
3165dafa8344c8c018e346dd331a7782081a896239Sean Callanan#include "lldb/Target/Target.h"
3265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
3365dafa8344c8c018e346dd331a7782081a896239Sean Callananusing namespace lldb_private;
3465dafa8344c8c018e346dd331a7782081a896239Sean Callanan
3565dafa8344c8c018e346dd331a7782081a896239Sean CallananClangUserExpression::ClangUserExpression (const char *expr) :
3665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_expr_text(expr),
3765dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_jit_addr(LLDB_INVALID_ADDRESS)
3865dafa8344c8c018e346dd331a7782081a896239Sean Callanan{
3965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    StreamString m_transformed_stream;
4065dafa8344c8c018e346dd331a7782081a896239Sean Callanan
4165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_transformed_stream.Printf("extern \"C\" void %s(void *___clang_arg) { %s; }\n",
4265dafa8344c8c018e346dd331a7782081a896239Sean Callanan                                FunctionName(),
4365dafa8344c8c018e346dd331a7782081a896239Sean Callanan                                m_expr_text.c_str());
4465dafa8344c8c018e346dd331a7782081a896239Sean Callanan
4565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_transformed_text = m_transformed_stream.GetData();
4665dafa8344c8c018e346dd331a7782081a896239Sean Callanan}
4765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
4865dafa8344c8c018e346dd331a7782081a896239Sean Callananclang::ASTConsumer *
4965dafa8344c8c018e346dd331a7782081a896239Sean CallananClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
5065dafa8344c8c018e346dd331a7782081a896239Sean Callanan{
5165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    return new ASTResultSynthesizer(passthrough);
5265dafa8344c8c018e346dd331a7782081a896239Sean Callanan}
5365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
5465dafa8344c8c018e346dd331a7782081a896239Sean Callananbool
5565dafa8344c8c018e346dd331a7782081a896239Sean CallananClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
5665dafa8344c8c018e346dd331a7782081a896239Sean Callanan{
5765dafa8344c8c018e346dd331a7782081a896239Sean Callanan    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
5865dafa8344c8c018e346dd331a7782081a896239Sean Callanan
5965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    ////////////////////////////////////
6065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    // Set up the target and compiler
6165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //
6265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
6365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    Target *target = exe_ctx.target;
6465dafa8344c8c018e346dd331a7782081a896239Sean Callanan
6565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (!target)
6665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
6765dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.PutCString ("error: invalid target\n");
6865dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
6965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
7065dafa8344c8c018e346dd331a7782081a896239Sean Callanan
7165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    ConstString target_triple;
7265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
7365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    target->GetTargetTriple (target_triple);
7465dafa8344c8c018e346dd331a7782081a896239Sean Callanan
7565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (!target_triple)
7665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        target_triple = Host::GetTargetTriple ();
7765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
7865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (!target_triple)
7965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
8065dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.PutCString ("error: invalid target triple\n");
8165dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
8265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
8365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
8465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //////////////////////////
8565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    // Parse the expression
8665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //
8765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
8865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
8965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
9065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    ClangExpressionParser parser(target_triple.GetCString(), *this);
9165dafa8344c8c018e346dd331a7782081a896239Sean Callanan
9265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    unsigned num_errors = parser.Parse (error_stream);
9365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
9465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (num_errors)
9565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
9665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
9765dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
9865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
9965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
10065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    ///////////////////////////////////////////////
10165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    // Convert the output of the parser to DWARF
10265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //
10365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
10465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_dwarf_opcodes.reset(new StreamString);
10565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
10665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
10765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
10865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_local_variables.reset(new ClangExpressionVariableStore());
10965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
11065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    Error dwarf_error = parser.MakeDWARF ();
11165dafa8344c8c018e346dd331a7782081a896239Sean Callanan
11265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (dwarf_error.Success())
11365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
11465dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (log)
11565dafa8344c8c018e346dd331a7782081a896239Sean Callanan            log->Printf("Code can be interpreted.");
11665dafa8344c8c018e346dd331a7782081a896239Sean Callanan
11765dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return true;
11865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
11965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
12065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //////////////////////////////////
12165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    // JIT the output of the parser
12265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    //
12365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
12465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    m_dwarf_opcodes.reset();
12565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
12665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    Error jit_error = parser.MakeJIT (m_jit_addr, exe_ctx);
12765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
12865dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (jit_error.Success())
12965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
13065dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (log)
13165dafa8344c8c018e346dd331a7782081a896239Sean Callanan        {
13265dafa8344c8c018e346dd331a7782081a896239Sean Callanan            log->Printf("Code can be run in the target.");
13365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
13465dafa8344c8c018e346dd331a7782081a896239Sean Callanan            StreamString disassembly_stream;
13565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
13665dafa8344c8c018e346dd331a7782081a896239Sean Callanan            Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);
13765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
13865dafa8344c8c018e346dd331a7782081a896239Sean Callanan            if (!err.Success())
13965dafa8344c8c018e346dd331a7782081a896239Sean Callanan            {
14065dafa8344c8c018e346dd331a7782081a896239Sean Callanan                log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
14165dafa8344c8c018e346dd331a7782081a896239Sean Callanan            }
14265dafa8344c8c018e346dd331a7782081a896239Sean Callanan            else
14365dafa8344c8c018e346dd331a7782081a896239Sean Callanan            {
14465dafa8344c8c018e346dd331a7782081a896239Sean Callanan                log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
14565dafa8344c8c018e346dd331a7782081a896239Sean Callanan            }
14665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        }
14765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
14865dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return true;
14965dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
15065dafa8344c8c018e346dd331a7782081a896239Sean Callanan    else
15165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
15265dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
15365dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
15465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
15565dafa8344c8c018e346dd331a7782081a896239Sean Callanan}
15665dafa8344c8c018e346dd331a7782081a896239Sean Callanan
15765dafa8344c8c018e346dd331a7782081a896239Sean Callananbool
15865dafa8344c8c018e346dd331a7782081a896239Sean CallananClangUserExpression::Execute (Stream &error_stream,
15965dafa8344c8c018e346dd331a7782081a896239Sean Callanan                              ExecutionContext &exe_ctx,
16065dafa8344c8c018e346dd331a7782081a896239Sean Callanan                              ClangExpressionVariable *&result)
16165dafa8344c8c018e346dd331a7782081a896239Sean Callanan{
16265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
16365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
16465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (m_dwarf_opcodes.get())
16565dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
16665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        // TODO execute the JITted opcodes
16765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
16865dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.Printf("We don't currently support executing DWARF expressions");
16965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
17065dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
17165dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
17265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    else if (m_jit_addr != LLDB_INVALID_ADDRESS)
17365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
17465dafa8344c8c018e346dd331a7782081a896239Sean Callanan        lldb::addr_t struct_address;
17565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
17665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        Error materialize_error;
17765dafa8344c8c018e346dd331a7782081a896239Sean Callanan
17865dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
17965dafa8344c8c018e346dd331a7782081a896239Sean Callanan        {
18065dafa8344c8c018e346dd331a7782081a896239Sean Callanan            error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString("unknown error"));
18165dafa8344c8c018e346dd331a7782081a896239Sean Callanan            return false;
18265dafa8344c8c018e346dd331a7782081a896239Sean Callanan        }
18365dafa8344c8c018e346dd331a7782081a896239Sean Callanan
18465dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (log)
18565dafa8344c8c018e346dd331a7782081a896239Sean Callanan        {
18665dafa8344c8c018e346dd331a7782081a896239Sean Callanan            log->Printf("Function address  : 0x%llx", (uint64_t)m_jit_addr);
18765dafa8344c8c018e346dd331a7782081a896239Sean Callanan            log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
18865dafa8344c8c018e346dd331a7782081a896239Sean Callanan
18965dafa8344c8c018e346dd331a7782081a896239Sean Callanan            StreamString args;
19065dafa8344c8c018e346dd331a7782081a896239Sean Callanan
19165dafa8344c8c018e346dd331a7782081a896239Sean Callanan            Error dump_error;
19265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
19365dafa8344c8c018e346dd331a7782081a896239Sean Callanan            if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
19465dafa8344c8c018e346dd331a7782081a896239Sean Callanan            {
19565dafa8344c8c018e346dd331a7782081a896239Sean Callanan                log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
19665dafa8344c8c018e346dd331a7782081a896239Sean Callanan            }
19765dafa8344c8c018e346dd331a7782081a896239Sean Callanan            else
19865dafa8344c8c018e346dd331a7782081a896239Sean Callanan            {
19965dafa8344c8c018e346dd331a7782081a896239Sean Callanan                log->Printf("Structure contents:\n%s", args.GetData());
20065dafa8344c8c018e346dd331a7782081a896239Sean Callanan            }
20165dafa8344c8c018e346dd331a7782081a896239Sean Callanan        }
20265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
20365dafa8344c8c018e346dd331a7782081a896239Sean Callanan        ClangFunction::ExecutionResults execution_result =
20465dafa8344c8c018e346dd331a7782081a896239Sean Callanan        ClangFunction::ExecuteFunction (exe_ctx, m_jit_addr, struct_address, true, true, 10000, error_stream);
20565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
20665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (execution_result != ClangFunction::eExecutionCompleted)
20765dafa8344c8c018e346dd331a7782081a896239Sean Callanan        {
20865dafa8344c8c018e346dd331a7782081a896239Sean Callanan            const char *result_name;
20965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
21065dafa8344c8c018e346dd331a7782081a896239Sean Callanan            switch (execution_result)
21165dafa8344c8c018e346dd331a7782081a896239Sean Callanan            {
21265dafa8344c8c018e346dd331a7782081a896239Sean Callanan                case ClangFunction::eExecutionCompleted:
21365dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    result_name = "eExecutionCompleted";
21465dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    break;
21565dafa8344c8c018e346dd331a7782081a896239Sean Callanan                case ClangFunction::eExecutionDiscarded:
21665dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    result_name = "eExecutionDiscarded";
21765dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    break;
21865dafa8344c8c018e346dd331a7782081a896239Sean Callanan                case ClangFunction::eExecutionInterrupted:
21965dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    result_name = "eExecutionInterrupted";
22065dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    break;
22165dafa8344c8c018e346dd331a7782081a896239Sean Callanan                case ClangFunction::eExecutionSetupError:
22265dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    result_name = "eExecutionSetupError";
22365dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    break;
22465dafa8344c8c018e346dd331a7782081a896239Sean Callanan                case ClangFunction::eExecutionTimedOut:
22565dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    result_name = "eExecutionTimedOut";
22665dafa8344c8c018e346dd331a7782081a896239Sean Callanan                    break;
22765dafa8344c8c018e346dd331a7782081a896239Sean Callanan            }
22865dafa8344c8c018e346dd331a7782081a896239Sean Callanan
22965dafa8344c8c018e346dd331a7782081a896239Sean Callanan            error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
23065dafa8344c8c018e346dd331a7782081a896239Sean Callanan            return false;
23165dafa8344c8c018e346dd331a7782081a896239Sean Callanan        }
23265dafa8344c8c018e346dd331a7782081a896239Sean Callanan
23365dafa8344c8c018e346dd331a7782081a896239Sean Callanan        Error expr_error;
23465dafa8344c8c018e346dd331a7782081a896239Sean Callanan
23565dafa8344c8c018e346dd331a7782081a896239Sean Callanan        if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
23665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        {
23765dafa8344c8c018e346dd331a7782081a896239Sean Callanan            error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
23865dafa8344c8c018e346dd331a7782081a896239Sean Callanan            return false;
23965dafa8344c8c018e346dd331a7782081a896239Sean Callanan        }
24065dafa8344c8c018e346dd331a7782081a896239Sean Callanan
24165dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return true;
24265dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
24365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    else
24465dafa8344c8c018e346dd331a7782081a896239Sean Callanan    {
24565dafa8344c8c018e346dd331a7782081a896239Sean Callanan        error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
24665dafa8344c8c018e346dd331a7782081a896239Sean Callanan        return false;
24765dafa8344c8c018e346dd331a7782081a896239Sean Callanan    }
24865dafa8344c8c018e346dd331a7782081a896239Sean Callanan}
24965dafa8344c8c018e346dd331a7782081a896239Sean Callanan
25065dafa8344c8c018e346dd331a7782081a896239Sean CallananStreamString &
25165dafa8344c8c018e346dd331a7782081a896239Sean CallananClangUserExpression::DwarfOpcodeStream ()
25265dafa8344c8c018e346dd331a7782081a896239Sean Callanan{
25365dafa8344c8c018e346dd331a7782081a896239Sean Callanan    if (!m_dwarf_opcodes.get())
25465dafa8344c8c018e346dd331a7782081a896239Sean Callanan        m_dwarf_opcodes.reset(new StreamString());
25565dafa8344c8c018e346dd331a7782081a896239Sean Callanan
25665dafa8344c8c018e346dd331a7782081a896239Sean Callanan    return *m_dwarf_opcodes.get();
25765dafa8344c8c018e346dd331a7782081a896239Sean Callanan}
258