summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Commands/CommandObjectCall.cpp11
-rw-r--r--lldb/source/Commands/CommandObjectExpression.cpp186
-rw-r--r--lldb/source/Expression/ASTResultSynthesizer.cpp (renamed from lldb/source/Expression/ClangResultSynthesizer.cpp)30
-rw-r--r--lldb/source/Expression/ASTStructExtractor.cpp191
-rw-r--r--lldb/source/Expression/ClangExpression.cpp748
-rw-r--r--lldb/source/Expression/ClangExpressionParser.cpp640
-rw-r--r--lldb/source/Expression/ClangFunction.cpp363
-rw-r--r--lldb/source/Expression/ClangUserExpression.cpp257
-rw-r--r--lldb/source/Expression/IRForTarget.cpp10
-rw-r--r--lldb/source/Expression/IRToDWARF.cpp16
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp4
11 files changed, 1260 insertions, 1196 deletions
diff --git a/lldb/source/Commands/CommandObjectCall.cpp b/lldb/source/Commands/CommandObjectCall.cpp
index b3dfc533b16..fe0ee534437 100644
--- a/lldb/source/Commands/CommandObjectCall.cpp
+++ b/lldb/source/Commands/CommandObjectCall.cpp
@@ -263,15 +263,8 @@ CommandObjectCall::Execute
ClangFunction::ExecutionResults return_status;
Value return_value;
- if (m_options.use_abi)
- {
- return_status = clang_fun.ExecuteFunctionWithABI(exe_ctx, errors, return_value);
- }
- else
- {
- bool stop_others = true;
- return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
- }
+ bool stop_others = true;
+ return_status = clang_fun.ExecuteFunction(exe_ctx, errors, stop_others, NULL, return_value);
// Now figure out what to do with the return value.
if (return_status == ClangFunction::eExecutionSetupError)
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp
index af1041002b6..b29c0c7777d 100644
--- a/lldb/source/Commands/CommandObjectExpression.cpp
+++ b/lldb/source/Commands/CommandObjectExpression.cpp
@@ -16,10 +16,8 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/InputReader.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionVariable.h"
-#include "lldb/Expression/ClangPersistentVariables.h"
+#include "lldb/Expression/ClangUserExpression.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Expression/DWARFExpression.h"
#include "lldb/Host/Host.h"
@@ -192,192 +190,22 @@ bool
CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream &output_stream, Stream &error_stream,
CommandReturnObject *result)
{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- ////////////////////////////////////
- // Set up the target and compiler
- //
-
- Target *target = m_exe_ctx.target;
-
- if (!target)
- {
- error_stream.PutCString ("error: invalid target\n");
- return false;
- }
+ ClangUserExpression user_expression (expr);
- ConstString target_triple;
-
- target->GetTargetTriple (target_triple);
-
- if (!target_triple)
- target_triple = Host::GetTargetTriple ();
-
- if (!target_triple)
+ if (!user_expression.Parse (error_stream, m_exe_ctx))
{
- error_stream.PutCString ("error: invalid target triple\n");
+ error_stream.Printf ("Couldn't parse the expresssion");
return false;
}
- ClangExpressionDeclMap expr_decl_map (&m_exe_ctx);
- ClangExpression clang_expr (target_triple.AsCString (), &expr_decl_map);
-
- //////////////////////////
- // Parse the expression
- //
-
- unsigned num_errors;
-
- if (bare)
- num_errors = clang_expr.ParseBareExpression (llvm::StringRef (expr), error_stream);
- else
- num_errors = clang_expr.ParseExpression (expr, error_stream, true);
-
- if (num_errors)
- {
- error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
- return false;
- }
-
- ///////////////////////////////////////////////
- // Convert the output of the parser to DWARF
- //
-
- StreamString dwarf_opcodes;
- dwarf_opcodes.SetByteOrder (eByteOrderHost);
- dwarf_opcodes.GetFlags ().Set (Stream::eBinary);
-
- ClangExpressionVariableList expr_local_vars;
-
- bool success;
- bool canInterpret = false;
-
- ClangExpressionVariable *expr_result = 0;
- Error expr_error;
-
- canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes);
-
- if (canInterpret)
- {
- if (log)
- log->Printf("Code can be interpreted.");
- success = true;
- }
- else
- {
- if (log)
- log->Printf("Code cannot be interpreted and must be run in the target.");
- success = clang_expr.PrepareIRForTarget ();
- }
-
- if (!success)
- {
- error_stream.PutCString ("error: expression couldn't be converted to IR\n");
- return false;
- }
+ ClangExpressionVariable *expr_result;
- if (canInterpret)
+ if (!user_expression.Execute (error_stream, m_exe_ctx, expr_result))
{
- // TODO interpret IR
+ error_stream.Printf ("Couldn't execute the expresssion");
return false;
}
- else
- {
- if (!clang_expr.JITFunction ())
- {
- error_stream.PutCString ("error: IR could not be JIT compiled\n");
- return false;
- }
- if (!clang_expr.WriteJITCode (m_exe_ctx))
- {
- error_stream.PutCString ("error: JIT code could not be written to the target\n");
- return false;
- }
-
- lldb::addr_t function_address(clang_expr.GetFunctionAddress ());
-
- if (function_address == LLDB_INVALID_ADDRESS)
- {
- error_stream.PutCString ("JIT compiled code's address couldn't be found\n");
- return false;
- }
-
- lldb::addr_t struct_address;
-
- if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, expr_error))
- {
- error_stream.Printf ("Couldn't materialize struct: %s\n", expr_error.AsCString("unknown error"));
- return false;
- }
-
- if (log)
- {
- log->Printf("Function address : 0x%llx", (uint64_t)function_address);
- log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
-
- StreamString insns;
-
- Error err = clang_expr.DisassembleFunction(insns, m_exe_ctx);
-
- if (!err.Success())
- {
- log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
- }
- else
- {
- log->Printf("Function disassembly:\n%s", insns.GetData());
- }
-
- StreamString args;
-
- if (!expr_decl_map.DumpMaterializedStruct(&m_exe_ctx, args, err))
- {
- log->Printf("Couldn't extract variable values : %s", err.AsCString("unknown error"));
- }
- else
- {
- log->Printf("Structure contents:\n%s", args.GetData());
- }
- }
-
- ClangFunction::ExecutionResults execution_result =
- ClangFunction::ExecuteFunction (m_exe_ctx, function_address, struct_address, true, true, 10000, error_stream);
-
- if (execution_result != ClangFunction::eExecutionCompleted)
- {
- const char *result_name;
-
- switch (execution_result)
- {
- case ClangFunction::eExecutionCompleted:
- result_name = "eExecutionCompleted";
- break;
- case ClangFunction::eExecutionDiscarded:
- result_name = "eExecutionDiscarded";
- break;
- case ClangFunction::eExecutionInterrupted:
- result_name = "eExecutionInterrupted";
- break;
- case ClangFunction::eExecutionSetupError:
- result_name = "eExecutionSetupError";
- break;
- case ClangFunction::eExecutionTimedOut:
- result_name = "eExecutionTimedOut";
- break;
- }
-
- error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
- return false;
- }
-
- if (!expr_decl_map.Dematerialize(&m_exe_ctx, expr_result, expr_error))
- {
- error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
- return false;
- }
- }
-
if (expr_result)
{
StreamString ss;
diff --git a/lldb/source/Expression/ClangResultSynthesizer.cpp b/lldb/source/Expression/ASTResultSynthesizer.cpp
index b3922ee5ce4..b3790f2cae5 100644
--- a/lldb/source/Expression/ClangResultSynthesizer.cpp
+++ b/lldb/source/Expression/ASTResultSynthesizer.cpp
@@ -1,4 +1,4 @@
-//===-- ClangResultSynthesizer.cpp ------------------------------*- C++ -*-===//
+//===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -20,13 +20,13 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include "lldb/Core/Log.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
using namespace llvm;
using namespace clang;
using namespace lldb_private;
-ClangResultSynthesizer::ClangResultSynthesizer(ASTConsumer *passthrough) :
+ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough) :
m_ast_context (NULL),
m_passthrough (passthrough),
m_passthrough_sema (NULL),
@@ -39,12 +39,12 @@ ClangResultSynthesizer::ClangResultSynthesizer(ASTConsumer *passthrough) :
m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
}
-ClangResultSynthesizer::~ClangResultSynthesizer()
+ASTResultSynthesizer::~ASTResultSynthesizer()
{
}
void
-ClangResultSynthesizer::Initialize(ASTContext &Context)
+ASTResultSynthesizer::Initialize(ASTContext &Context)
{
m_ast_context = &Context;
@@ -53,7 +53,7 @@ ClangResultSynthesizer::Initialize(ASTContext &Context)
}
void
-ClangResultSynthesizer::TransformTopLevelDecl(Decl* D)
+ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
{
LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
@@ -81,7 +81,7 @@ ClangResultSynthesizer::TransformTopLevelDecl(Decl* D)
}
void
-ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
+ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
{
DeclGroupRef::iterator decl_iterator;
@@ -99,7 +99,7 @@ ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
}
bool
-ClangResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
+ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
{
ASTContext &Ctx(*m_ast_context);
@@ -210,42 +210,42 @@ ClangResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
}
void
-ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
+ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
{
if (m_passthrough)
m_passthrough->HandleTranslationUnit(Ctx);
}
void
-ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
+ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
{
if (m_passthrough)
m_passthrough->HandleTagDeclDefinition(D);
}
void
-ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
+ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
{
if (m_passthrough)
m_passthrough->CompleteTentativeDefinition(D);
}
void
-ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
+ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
{
if (m_passthrough)
m_passthrough->HandleVTable(RD, DefinitionRequired);
}
void
-ClangResultSynthesizer::PrintStats()
+ASTResultSynthesizer::PrintStats()
{
if (m_passthrough)
m_passthrough->PrintStats();
}
void
-ClangResultSynthesizer::InitializeSema(Sema &S)
+ASTResultSynthesizer::InitializeSema(Sema &S)
{
m_sema = &S;
m_action = reinterpret_cast<Action*>(m_sema);
@@ -255,7 +255,7 @@ ClangResultSynthesizer::InitializeSema(Sema &S)
}
void
-ClangResultSynthesizer::ForgetSema()
+ASTResultSynthesizer::ForgetSema()
{
m_sema = NULL;
m_action = NULL;
diff --git a/lldb/source/Expression/ASTStructExtractor.cpp b/lldb/source/Expression/ASTStructExtractor.cpp
new file mode 100644
index 00000000000..84a97c8e5df
--- /dev/null
+++ b/lldb/source/Expression/ASTStructExtractor.cpp
@@ -0,0 +1,191 @@
+//===-- ASTStructExtractor.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "stdlib.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclGroup.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/RecordLayout.h"
+#include "clang/AST/Stmt.h"
+#include "clang/Parse/Action.h"
+#include "clang/Parse/Parser.h"
+#include "clang/Parse/Scope.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Expression/ASTStructExtractor.h"
+
+using namespace llvm;
+using namespace clang;
+using namespace lldb_private;
+
+ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough,
+ const char *struct_name,
+ ClangFunction &function) :
+ m_ast_context (NULL),
+ m_passthrough (passthrough),
+ m_passthrough_sema (NULL),
+ m_sema (NULL),
+ m_action (NULL),
+ m_struct_name (struct_name),
+ m_function (function)
+{
+ if (!m_passthrough)
+ return;
+
+ m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
+}
+
+ASTStructExtractor::~ASTStructExtractor()
+{
+}
+
+void
+ASTStructExtractor::Initialize(ASTContext &Context)
+{
+ m_ast_context = &Context;
+
+ if (m_passthrough)
+ m_passthrough->Initialize(Context);
+}
+
+void
+ASTStructExtractor::ExtractFromFunctionDecl(FunctionDecl *F)
+{
+ DeclarationName struct_name(&m_ast_context->Idents.get(m_struct_name.c_str()));
+ RecordDecl::lookup_result struct_lookup = F->lookup(struct_name);
+
+ if (struct_lookup.first == struct_lookup.second)
+ return;
+
+ RecordDecl *struct_decl = dyn_cast<RecordDecl>(*(struct_lookup.first));
+
+ if (!struct_decl)
+ return;
+
+ const ASTRecordLayout* struct_layout(&m_ast_context->getASTRecordLayout (struct_decl));
+
+ if (!struct_layout)
+ return;
+
+ m_function.m_struct_size = struct_layout->getSize() / 8; // Clang returns sizes in bits.
+ m_function.m_return_offset = struct_layout->getFieldOffset(struct_layout->getFieldCount() - 1) / 8;
+ m_function.m_return_size = (struct_layout->getDataSize() / 8) - m_function.m_return_offset;
+
+ for (unsigned field_index = 0, num_fields = struct_layout->getFieldCount();
+ field_index < num_fields;
+ ++field_index)
+ {
+ m_function.m_member_offsets.push_back(struct_layout->getFieldOffset(field_index) / 8);
+ }
+
+ m_function.m_struct_valid = true;
+}
+
+void
+ASTStructExtractor::ExtractFromTopLevelDecl(Decl* D)
+{
+ LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
+
+ if (linkage_spec_decl)
+ {
+ RecordDecl::decl_iterator decl_iterator;
+
+ for (decl_iterator = linkage_spec_decl->decls_begin();
+ decl_iterator != linkage_spec_decl->decls_end();
+ ++decl_iterator)
+ {
+ ExtractFromTopLevelDecl(*decl_iterator);
+ }
+ }
+
+ FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
+
+ if (m_ast_context &&
+ function_decl &&
+ !m_function.m_wrapper_function_name.compare(function_decl->getNameAsCString()))
+ {
+ ExtractFromFunctionDecl(function_decl);
+ }
+}
+
+void
+ASTStructExtractor::HandleTopLevelDecl(DeclGroupRef D)
+{
+ DeclGroupRef::iterator decl_iterator;
+
+ for (decl_iterator = D.begin();
+ decl_iterator != D.end();
+ ++decl_iterator)
+ {
+ Decl *decl = *decl_iterator;
+
+ ExtractFromTopLevelDecl(decl);
+ }
+
+ if (m_passthrough)
+ m_passthrough->HandleTopLevelDecl(D);
+}
+
+void
+ASTStructExtractor::HandleTranslationUnit(ASTContext &Ctx)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTranslationUnit(Ctx);
+}
+
+void
+ASTStructExtractor::HandleTagDeclDefinition(TagDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->HandleTagDeclDefinition(D);
+}
+
+void
+ASTStructExtractor::CompleteTentativeDefinition(VarDecl *D)
+{
+ if (m_passthrough)
+ m_passthrough->CompleteTentativeDefinition(D);
+}
+
+void
+ASTStructExtractor::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
+{
+ if (m_passthrough)
+ m_passthrough->HandleVTable(RD, DefinitionRequired);
+}
+
+void
+ASTStructExtractor::PrintStats()
+{
+ if (m_passthrough)
+ m_passthrough->PrintStats();
+}
+
+void
+ASTStructExtractor::InitializeSema(Sema &S)
+{
+ m_sema = &S;
+ m_action = reinterpret_cast<Action*>(m_sema);
+
+ if (m_passthrough_sema)
+ m_passthrough_sema->InitializeSema(S);
+}
+
+void
+ASTStructExtractor::ForgetSema()
+{
+ m_sema = NULL;
+ m_action = NULL;
+
+ if (m_passthrough_sema)
+ m_passthrough_sema->ForgetSema();
+}
diff --git a/lldb/source/Expression/ClangExpression.cpp b/lldb/source/Expression/ClangExpression.cpp
deleted file mode 100644
index 416bd3e3733..00000000000
--- a/lldb/source/Expression/ClangExpression.cpp
+++ /dev/null
@@ -1,748 +0,0 @@
-//===-- ClangExpression.cpp -------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-// C Includes
-#include <stdio.h>
-#if HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-// C++ Includes
-#include <cstdlib>
-#include <string>
-#include <map>
-
-// Other libraries and framework includes
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/ExternalASTSource.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Version.h"
-#include "clang/Checker/FrontendActions.h"
-#include "clang/CodeGen/CodeGenAction.h"
-#include "clang/CodeGen/ModuleBuilder.h"
-#include "clang/Driver/CC1Options.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/FrontendActions.h"
-#include "clang/Frontend/FrontendDiagnostic.h"
-#include "clang/Frontend/FrontendPluginRegistry.h"
-#include "clang/Frontend/TextDiagnosticBuffer.h"
-#include "clang/Frontend/TextDiagnosticPrinter.h"
-#include "clang/Frontend/VerifyDiagnosticsClient.h"
-#include "clang/Lex/Preprocessor.h"
-#include "clang/Rewrite/FrontendActions.h"
-#include "clang/Sema/ParseAST.h"
-#include "clang/Sema/SemaConsumer.h"
-#include "llvm/ExecutionEngine/ExecutionEngine.h"
-#include "llvm/ExecutionEngine/JIT.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/System/DynamicLibrary.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Signals.h"
-#include "llvm/Target/TargetRegistry.h"
-#include "llvm/Target/TargetSelect.h"
-
-// Project includes
-#include "lldb/Core/Log.h"
-#include "lldb/Core/ClangForward.h"
-#include "lldb/Core/DataBufferHeap.h"
-#include "lldb/Core/Disassembler.h"
-#include "lldb/Expression/ClangExpression.h"
-#include "lldb/Expression/ClangASTSource.h"
-#include "lldb/Expression/ClangResultSynthesizer.h"
-#include "lldb/Expression/IRForTarget.h"
-#include "lldb/Expression/IRToDWARF.h"
-#include "lldb/Symbol/ClangASTContext.h"
-#include "lldb/Expression/RecordingMemoryManager.h"
-#include "lldb/Target/ExecutionContext.h"
-#include "lldb/Target/Process.h"
-#include "lldb/Target/Target.h"
-
-#include "lldb/Core/StreamString.h"
-#include "lldb/Host/Mutex.h"
-
-
-using namespace lldb_private;
-using namespace clang;
-using namespace llvm;
-
-
-//===----------------------------------------------------------------------===//
-// Utility Methods
-//===----------------------------------------------------------------------===//
-
-std::string GetBuiltinIncludePath(const char *Argv0) {
- llvm::sys::Path P =
- llvm::sys::Path::GetMainExecutable(Argv0,
- (void*)(intptr_t) GetBuiltinIncludePath);
-
- if (!P.isEmpty()) {
- P.eraseComponent(); // Remove /clang from foo/bin/clang
- P.eraseComponent(); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- P.appendComponent("lib");
- P.appendComponent("clang");
- P.appendComponent(CLANG_VERSION_STRING);
- P.appendComponent("include");
- }
-
- return P.str();
-}
-
-
-//===----------------------------------------------------------------------===//
-// Main driver
-//===----------------------------------------------------------------------===//
-
-static void LLVMErrorHandler(void *UserData, const std::string &Message) {
- Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
-
- Diags.Report(diag::err_fe_error_backend) << Message;
-
- // We cannot recover from llvm errors.
- exit(1);
-}
-
-static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
- using namespace clang::frontend;
-
- switch (CI.getFrontendOpts().ProgramAction) {
- default:
- llvm_unreachable("Invalid program action!");
-
- case ASTDump: return new ASTDumpAction();
- case ASTPrint: return new ASTPrintAction();
- case ASTPrintXML: return new ASTPrintXMLAction();
- case ASTView: return new ASTViewAction();
- case BoostCon: return new BoostConAction();
- case DumpRawTokens: return new DumpRawTokensAction();
- case DumpTokens: return new DumpTokensAction();
- case EmitAssembly: return new EmitAssemblyAction();
- case EmitBC: return new EmitBCAction();
- case EmitHTML: return new HTMLPrintAction();
- case EmitLLVM: return new EmitLLVMAction();
- case EmitLLVMOnly: return new EmitLLVMOnlyAction();
- case EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
- case EmitObj: return new EmitObjAction();
- case FixIt: return new FixItAction();
- case GeneratePCH: return new GeneratePCHAction();
- case GeneratePTH: return new GeneratePTHAction();
- case InheritanceView: return new InheritanceViewAction();
- case InitOnly: return new InitOnlyAction();
- case ParseSyntaxOnly: return new SyntaxOnlyAction();
-
- case PluginAction: {
- for (FrontendPluginRegistry::iterator it =
- FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
- it != ie; ++it) {
- if (it->getName() == CI.getFrontendOpts().ActionName) {
- llvm::OwningPtr<PluginASTAction> P(it->instantiate());
- if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
- return 0;
- return P.take();
- }
- }
-
- CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
- << CI.getFrontendOpts().ActionName;
- return 0;
- }
-
- case PrintDeclContext: return new DeclContextPrintAction();
- case PrintPreamble: return new PrintPreambleAction();
- case PrintPreprocessedInput: return new PrintPreprocessedAction();
- case RewriteMacros: return new RewriteMacrosAction();
- case RewriteObjC: return new RewriteObjCAction();
- case RewriteTest: return new RewriteTestAction();
- case RunAnalysis: return new AnalysisAction();
- case RunPreprocessorOnly: return new PreprocessOnlyAction();
- }
-}
-
-static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
- // Create the underlying action.
- FrontendAction *Act = CreateFrontendBaseAction(CI);
- if (!Act)
- return 0;
-
- // If there are any AST files to merge, create a frontend action
- // adaptor to perform the merge.
- if (!CI.getFrontendOpts().ASTMergeFiles.empty())
- Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
- CI.getFrontendOpts().ASTMergeFiles.size());
-
- return Act;
-}
-
-//----------------------------------------------------------------------
-// ClangExpression constructor
-//----------------------------------------------------------------------
-ClangExpression::ClangExpression(const char *target_triple,
- ClangExpressionDeclMap *decl_map) :
- m_target_triple (),
- m_decl_map (decl_map),
- m_clang_ap (),
- m_code_generator_ptr (NULL),
- m_jit_mm_ptr (NULL),
- m_execution_engine (),
- m_jitted_functions ()
-{
- if (target_triple && target_triple[0])
- m_target_triple = target_triple;
- else
- m_target_triple = llvm::sys::getHostTriple();
-}
-
-
-//----------------------------------------------------------------------
-// Destructor
-//----------------------------------------------------------------------
-ClangExpression::~ClangExpression()
-{
- if (m_code_generator_ptr && !m_execution_engine.get())
- delete m_code_generator_ptr;
-}
-
-bool
-ClangExpression::CreateCompilerInstance ()
-{
- // Initialize targets first, so that --version shows registered targets.
- static struct InitializeLLVM {
- InitializeLLVM() {
- llvm::InitializeAllTargets();
- llvm::InitializeAllAsmPrinters();
- }
- } InitializeLLVM;
-
- // 1. Create a new compiler instance.
- m_clang_ap.reset(new CompilerInstance());
- m_clang_ap->setLLVMContext(new LLVMContext());
-
- // 2. Set options.
-
- // Parse expressions as Objective C++ regardless of context.
- // Our hook into Clang's lookup mechanism only works in C++.
- m_clang_ap->getLangOpts().CPlusPlus = true;
- m_clang_ap->getLangOpts().ObjC1 = true;
- m_clang_ap->getLangOpts().ThreadsafeStatics = false;
- m_clang_ap->getLangOpts().AccessControl = false; // Debuggers get universal access
- m_clang_ap->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
-
- // Set CodeGen options
- m_clang_ap->getCodeGenOpts().EmitDeclMetadata = true;
- m_clang_ap->getCodeGenOpts().InstrumentFunctions = false;
-
- // Disable some warnings.
- m_clang_ap->getDiagnosticOpts().Warnings.push_back("no-unused-value");
-
- // Set the target triple.
- m_clang_ap->getTargetOpts().Triple = m_target_triple;
-
- // 3. Set up various important bits of infrastructure.
-
- m_clang_ap->createDiagnostics(0, 0);
-
- // Create the target instance.
- m_clang_ap->setTarget(TargetInfo::CreateTargetInfo(m_clang_ap->getDiagnostics(),
- m_clang_ap->getTargetOpts()));
- if (!m_clang_ap->hasTarget())
- {
- m_clang_ap.reset();
- return false;
- }
-
- // Inform the target of the language options
- //
- // FIXME: We shouldn't need to do this, the target should be immutable once
- // created. This complexity should be lifted elsewhere.
- m_clang_ap->getTarget().setForcedLangOptions(m_clang_ap->getLangOpts());
-
- return m_clang_ap.get();
-}
-
-Mutex &
-ClangExpression::GetClangMutex ()
-{
- static Mutex g_clang_mutex(Mutex::eMutexTypeRecursive); // Control access to the clang compiler
- return g_clang_mutex;
-}
-
-
-clang::ASTContext *
-ClangExpression::GetASTContext ()
-{
- CompilerInstance *compiler_instance = GetCompilerInstance();
- if (compiler_instance)
- return &compiler_instance->getASTContext();
- return NULL;
-}
-
-unsigned
-ClangExpression::ParseExpression (const char *expr_text,
- Stream &stream,
- bool add_result_var)
-{
- // HACK: for now we have to make a function body around our expression
- // since there is no way to parse a single expression line in LLVM/Clang.
- std::string func_expr("extern \"C\" void ___clang_expr(void *___clang_arg)\n{\n\t");
- func_expr.append(expr_text);
- func_expr.append(";\n}");
- return ParseBareExpression (func_expr, stream, add_result_var);
-
-}
-
-unsigned
-ClangExpression::ParseBareExpression (llvm::StringRef expr_text,
- Stream &stream,
- bool add_result_var)
-{
- Mutex::Locker locker(GetClangMutex ());
-
- TextDiagnosticBuffer text_diagnostic_buffer;
-
- if (!CreateCompilerInstance ())
- {
- stream.Printf("error: couldn't create compiler instance\n");
- return 1;
- }
-
- // This code is matched below by a setClient to NULL.
- // We cannot return out of this code without doing that.
- m_clang_ap->getDiagnostics().setClient(&text_diagnostic_buffer);
- text_diagnostic_buffer.FlushDiagnostics (m_clang_ap->getDiagnostics());
-
- MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__);
-
- if (!m_clang_ap->hasSourceManager())
- m_clang_ap->createSourceManager();
-
- m_clang_ap->createFileManager();
- m_clang_ap->createPreprocessor();
-
- // Build the ASTContext. Most of this we inherit from the
- // CompilerInstance, but we also want to give the context
- // an ExternalASTSource.
- SelectorTable selector_table;
- std::auto_ptr<Builtin::Context> builtin_ap(new Builtin::Context(m_clang_ap->getTarget()));
- ASTContext *Context = new ASTContext(m_clang_ap->getLangOpts(),
- m_clang_ap->getSourceManager(),
- m_clang_ap->getTarget(),
- m_clang_ap->getPreprocessor().getIdentifierTable(),
- selector_table,
- *builtin_ap.get(),
- 0);
-
- llvm::OwningPtr<ExternalASTSource> ASTSource(new ClangASTSource(*Context, *m_decl_map));
-
- if (m_decl_map)
- {
- Context->setExternalSource(ASTSource);
- }
-
- m_clang_ap->setASTContext(Context);
-
- FileID memory_buffer_file_id = m_clang_ap->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
- std::string module_name("test_func");
- text_diagnostic_buffer.BeginSourceFile(m_clang_ap->getLangOpts(), &m_clang_ap->getPreprocessor());
-
- if (m_code_generator_ptr)
- delete m_code_generator_ptr;
-
- m_code_generator_ptr = CreateLLVMCodeGen(m_clang_ap->getDiagnostics(),
- module_name,
- m_clang_ap->getCodeGenOpts(),
- m_clang_ap->getLLVMContext());
-
-
- // - CodeGeneration ASTConsumer (include/clang/ModuleBuilder.h), which will be passed in when you call...
- // - Call clang::ParseAST (in lib/Sema/ParseAST.cpp) to parse the buffer. The CodeGenerator will generate code for __dbg_expr.
- // - Once ParseAST completes, you can grab the llvm::Module from the CodeGenerator, which will have an llvm::Function you can hand off to the JIT.
-
- if (add_result_var)
- {
- ClangResultSynthesizer result_synthesizer(m_code_generator_ptr);
- ParseAST(m_clang_ap->getPreprocessor(), &result_synthesizer, m_clang_ap->getASTContext());
- }
- else
- {
- ParseAST(m_clang_ap->getPreprocessor(), m_code_generator_ptr, m_clang_ap->getASTContext());
- }
-
-
- text_diagnostic_buffer.EndSourceFile();
-
- //compiler_instance->getASTContext().getTranslationUnitDecl()->dump();
-
- //if (compiler_instance->getFrontendOpts().ShowStats) {
- // compiler_instance->getFileManager().PrintStats();
- // fprintf(stderr, "\n");
- //}
-
- // This code resolves the setClient above.
- m_clang_ap->getDiagnostics().setClient(0);
-
- TextDiagnosticBuffer::const_iterator diag_iterator;
-
- int num_errors = 0;
-
-#ifdef COUNT_WARNINGS_AND_ERRORS
- int num_warnings = 0;
-
- for (diag_iterator = text_diagnostic_buffer.warn_begin();
- diag_iterator != text_diagnostic_buffer.warn_end();
- ++diag_iterator)
- num_warnings++;
-
- for (diag_iterator = text_diagnostic_buffer.err_begin();
- diag_iterator != text_diagnostic_buffer.err_end();
- ++diag_iterator)
- num_errors++;
-
- if (num_warnings || num_errors)
- {
- if (num_warnings)
- stream.Printf("%u warning%s%s", num_warnings, (num_warnings == 1 ? "" : "s"), (num_errors ? " and " : ""));
- if (num_errors)
- stream.Printf("%u error%s", num_errors, (num_errors == 1 ? "" : "s"));
- stream.Printf("\n");
- }
-#endif
-
- for (diag_iterator = text_diagnostic_buffer.warn_begin();
- diag_iterator != text_diagnostic_buffer.warn_end();
- ++diag_iterator)
- stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
-
- num_errors = 0;
-
- for (diag_iterator = text_diagnostic_buffer.err_begin();
- diag_iterator != text_diagnostic_buffer.err_end();
- ++diag_iterator)
- {
- num_errors++;
- stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
- }
-
- return num_errors;
-}
-
-bool
-ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &expr_local_variable_list,
- StreamString &dwarf_opcode_strm)
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- llvm::Module *module = m_code_generator_ptr->GetModule();
-
- if (!module)
- {
- if (log)
- log->Printf("IR doesn't contain a module");
-
- return 1;
- }
-
- IRToDWARF ir_to_dwarf(expr_local_variable_list, m_decl_map, dwarf_opcode_strm);
-
- return ir_to_dwarf.runOnModule(*module);
-}
-
-bool
-ClangExpression::PrepareIRForTarget ()
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- llvm::Module *module = m_code_generator_ptr->GetModule();
-
- if (!module)
- {
- if (log)
- log->Printf("IR doesn't contain a module");
-
- return 1;
- }
-
- llvm::Triple target_triple = m_clang_ap->getTarget().getTriple();
-
- std::string err;
-
- const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, err);
-
- if (!target)
- {
- if (log)
- log->Printf("Couldn't find a target for %s", m_target_triple.c_str());
-
- return 1;
- }
-
- std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
-
- IRForTarget ir_for_target(m_decl_map, target_machine->getTargetData());
-
- return ir_for_target.runOnModule(*module);
-}
-
-bool
-ClangExpression::JITFunction (const char *name)
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- llvm::Module *module = m_code_generator_ptr->GetModule();
-
- if (module)
- {
- std::string error;
-
- if (m_jit_mm_ptr == NULL)
- m_jit_mm_ptr = new RecordingMemoryManager();
-
- //llvm::InitializeNativeTarget();
-
- if (log)
- {
- const char *relocation_model_string;
-
- switch (llvm::TargetMachine::getRelocationModel())
- {
- case llvm::Reloc::Default:
- relocation_model_string = "Default";
- break;
- case llvm::Reloc::Static:
- relocation_model_string = "Static";
- break;
- case llvm::Reloc::PIC_:
- relocation_model_string = "PIC_";
- break;
- case llvm::Reloc::DynamicNoPIC:
- relocation_model_string = "DynamicNoPIC";
- break;
- }
-
- log->Printf("Target machine's relocation model: %s", relocation_model_string);
- }
-
- if (m_execution_engine.get() == 0)
- m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module,
- &error,
- m_jit_mm_ptr,
- CodeGenOpt::Default,
- true,
- CodeModel::Small)); // set to small so RIP-relative relocations work in PIC
-
- m_execution_engine->DisableLazyCompilation();
- llvm::Function *function = module->getFunction (llvm::StringRef (name));
-
- // We don't actually need the function pointer here, this just forces it to get resolved.
- void *fun_ptr = m_execution_engine->getPointerToFunction(function);
- // Note, you probably won't get here on error, since the LLVM JIT tends to just
- // exit on error at present... So be careful.
- if (fun_ptr == 0)
- return false;
- m_jitted_functions.push_back(ClangExpression::JittedFunction(name, (lldb::addr_t) fun_ptr));
-
- }
- return true;
-}
-
-bool
-ClangExpression::WriteJITCode (const ExecutionContext &exc_context)
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- if (m_jit_mm_ptr == NULL)
- return false;
-
- if (exc_context.process == NULL)
- return false;
-
- // Look over the regions allocated for the function compiled. The JIT
- // tries to allocate the functions & stubs close together, so we should try to
- // write them that way too...
- // For now I only write functions with no stubs, globals, exception tables,
- // etc. So I only need to write the functions.
-
- size_t alloc_size = 0;
- std::map<uint8_t *, uint8_t *>::iterator fun_pos, fun_end = m_jit_mm_ptr->m_functions.end();
- for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
- {
- alloc_size += (*fun_pos).second - (*fun_pos).first;
- }
-
- Error error;
- lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, error);
-
- if (target_addr == LLDB_INVALID_ADDRESS)
- return false;
-
- lldb::addr_t cursor = target_addr;
- for (fun_pos = m_jit_mm_ptr->m_functions.begin(); fun_pos != fun_end; fun_pos++)
- {
- if (log)
- log->Printf("Reading [%p-%p] from m_functions", fun_pos->first, fun_pos->second);
-
- lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
- lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
- size_t size = lend - lstart;
- exc_context.process->WriteMemory(cursor, (void *) lstart, size, error);
- m_jit_mm_ptr->AddToLocalToRemoteMap (lstart, size, cursor);
- cursor += size;
- }
-
- std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
- for (pos = m_jitted_functions.begin(); pos != end; pos++)
- {
- (*pos).m_remote_addr = m_jit_mm_ptr->GetRemoteAddressForLocal ((*pos).m_local_addr);
- }
- return true;
-}
-
-lldb::addr_t
-ClangExpression::GetFunctionAddress (const char *name)
-{
- std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
- for (pos = m_jitted_functions.begin(); pos < end; pos++)
- {
- if (strcmp ((*pos).m_name.c_str(), name) == 0)
- return (*pos).m_remote_addr;
- }
- return LLDB_INVALID_ADDRESS;
-}
-
-Error
-ClangExpression::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, const char *name)
-{
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
-
- Error ret;
-
- ret.Clear();
-
- lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
- lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
-
- std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
-
- for (pos = m_jitted_functions.begin(); pos < end; pos++)
- {
- if (strcmp(pos->m_name.c_str(), name) == 0)
- {
- func_local_addr = pos->m_local_addr;
- func_remote_addr = pos->m_remote_addr;
- }
- }
-
- if (func_local_addr == LLDB_INVALID_ADDRESS)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
- return ret;
- }
-
- if(log)
- log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
-
- std::pair <lldb::addr_t, lldb::addr_t> func_range;
-
- func_range = m_jit_mm_ptr->GetRemoteRangeForLocal(func_local_addr);
-
- if (func_range.first == 0 && func_range.second == 0)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
- return ret;
- }
-
- if(log)
- log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
-
- if (!exe_ctx.target)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the target");
- }
-
- lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
-
- Error err;
- exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
-
- if (!err.Success())
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
- return ret;
- }
-
- ArchSpec arch(exe_ctx.target->GetArchitecture());
-
- Disassembler *disassembler = Disassembler::FindPlugin(arch);
-
- if (disassembler == NULL)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
- return ret;
- }
-
- if (!exe_ctx.process)
- {
- ret.SetErrorToGenericError();
- ret.SetErrorString("Couldn't find the process");
- return ret;
- }
-
- DataExtractor extractor(buffer_sp,
- exe_ctx.process->GetByteOrder(),
- exe_ctx.target->GetArchitecture().GetAddressByteSize());
-
- if(log)
- {
- log->Printf("Function data has contents:");
- extractor.PutToLog (log,
- 0,
- extractor.GetByteSize(),
- func_remote_addr,
- 16,
- DataExtractor::TypeUInt8);
- }
-
- disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
-
- Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
-
- uint32_t bytes_offset = 0;
-
- for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize();
- instruction_index < num_instructions;
- ++instruction_index)
- {
- Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
- Address addr(NULL, func_remote_addr + bytes_offset);
- instruction->Dump (&stream,
- &addr,
- &extractor,
- bytes_offset,
- exe_ctx,
- true);
- stream.PutChar('\n');
- bytes_offset += instruction->GetByteSize();
- }
-
- return ret;
-}
diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp
new file mode 100644
index 00000000000..05c237afdb9
--- /dev/null
+++ b/lldb/source/Expression/ClangExpressionParser.cpp
@@ -0,0 +1,640 @@
+//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/ClangExpressionParser.h"
+
+#include "lldb/Core/ArchSpec.h"
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/Disassembler.h"
+#include "lldb/Core/Stream.h"
+#include "lldb/Expression/ClangASTSource.h"
+#include "lldb/Expression/ClangExpression.h"
+#include "lldb/Expression/IRForTarget.h"
+#include "lldb/Expression/IRToDWARF.h"
+#include "lldb/Expression/RecordingMemoryManager.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/ExternalASTSource.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Basic/Version.h"
+#include "clang/Checker/FrontendActions.h"
+#include "clang/CodeGen/CodeGenAction.h"
+#include "clang/CodeGen/ModuleBuilder.h"
+#include "clang/Driver/CC1Options.h"
+#include "clang/Driver/OptTable.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/FrontendPluginRegistry.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/VerifyDiagnosticsClient.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Rewrite/FrontendActions.h"
+#include "clang/Sema/ParseAST.h"
+#include "clang/Sema/SemaConsumer.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
+#include "llvm/ExecutionEngine/JIT.h"
+#include "llvm/Module.h"
+#include "llvm/LLVMContext.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/DynamicLibrary.h"
+#include "llvm/System/Host.h"
+#include "llvm/System/Signals.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
+
+using namespace clang;
+using namespace llvm;
+using namespace lldb_private;
+
+//===----------------------------------------------------------------------===//
+// Utility Methods for Clang
+//===----------------------------------------------------------------------===//
+
+std::string GetBuiltinIncludePath(const char *Argv0) {
+ llvm::sys::Path P =
+ llvm::sys::Path::GetMainExecutable(Argv0,
+ (void*)(intptr_t) GetBuiltinIncludePath);
+
+ if (!P.isEmpty()) {
+ P.eraseComponent(); // Remove /clang from foo/bin/clang
+ P.eraseComponent(); // Remove /bin from foo/bin
+
+ // Get foo/lib/clang/<version>/include
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ P.appendComponent("include");
+ }
+
+ return P.str();
+}
+
+
+//===----------------------------------------------------------------------===//
+// Main driver for Clang
+//===----------------------------------------------------------------------===//
+
+static void LLVMErrorHandler(void *UserData, const std::string &Message) {
+ Diagnostic &Diags = *static_cast<Diagnostic*>(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // We cannot recover from llvm errors.
+ exit(1);
+}
+
+static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
+ using namespace clang::frontend;
+
+ switch (CI.getFrontendOpts().ProgramAction) {
+ default:
+ llvm_unreachable("Invalid program action!");
+
+ case ASTDump: return new ASTDumpAction();
+ case ASTPrint: return new ASTPrintAction();
+ case ASTPrintXML: return new ASTPrintXMLAction();
+ case ASTView: return new ASTViewAction();
+ case BoostCon: return new BoostConAction();
+ case DumpRawTokens: return new DumpRawTokensAction();
+ case DumpTokens: return new DumpTokensAction();
+ case EmitAssembly: return new EmitAssemblyAction();
+ case EmitBC: return new EmitBCAction();
+ case EmitHTML: return new HTMLPrintAction();
+ case EmitLLVM: return new EmitLLVMAction();
+ case EmitLLVMOnly: return new EmitLLVMOnlyAction();
+ case EmitCodeGenOnly: return new EmitCodeGenOnlyAction();
+ case EmitObj: return new EmitObjAction();
+ case FixIt: return new FixItAction();
+ case GeneratePCH: return new GeneratePCHAction();
+ case GeneratePTH: return new GeneratePTHAction();
+ case InheritanceView: return new InheritanceViewAction();
+ case InitOnly: return new InitOnlyAction();
+ case ParseSyntaxOnly: return new SyntaxOnlyAction();
+
+ case PluginAction: {
+ for (FrontendPluginRegistry::iterator it =
+ FrontendPluginRegistry::begin(), ie = FrontendPluginRegistry::end();
+ it != ie; ++it) {
+ if (it->getName() == CI.getFrontendOpts().ActionName) {
+ llvm::OwningPtr<PluginASTAction> P(it->instantiate());
+ if (!P->ParseArgs(CI, CI.getFrontendOpts().PluginArgs))
+ return 0;
+ return P.take();
+ }
+ }
+
+ CI.getDiagnostics().Report(diag::err_fe_invalid_plugin_name)
+ << CI.getFrontendOpts().ActionName;
+ return 0;
+ }
+
+ case PrintDeclContext: return new DeclContextPrintAction();
+ case PrintPreamble: return new PrintPreambleAction();
+ case PrintPreprocessedInput: return new PrintPreprocessedAction();
+ case RewriteMacros: return new RewriteMacrosAction();
+ case RewriteObjC: return new RewriteObjCAction();
+ case RewriteTest: return new RewriteTestAction();
+ case RunAnalysis: return new AnalysisAction();
+ case RunPreprocessorOnly: return new PreprocessOnlyAction();
+ }
+}
+
+static FrontendAction *CreateFrontendAction(CompilerInstance &CI) {
+ // Create the underlying action.
+ FrontendAction *Act = CreateFrontendBaseAction(CI);
+ if (!Act)
+ return 0;
+
+ // If there are any AST files to merge, create a frontend action
+ // adaptor to perform the merge.
+ if (!CI.getFrontendOpts().ASTMergeFiles.empty())
+ Act = new ASTMergeAction(Act, &CI.getFrontendOpts().ASTMergeFiles[0],
+ CI.getFrontendOpts().ASTMergeFiles.size());
+
+ return Act;
+}
+
+//===----------------------------------------------------------------------===//
+// Implementation of ClangExpressionParser
+//===----------------------------------------------------------------------===//
+
+ClangExpressionParser::ClangExpressionParser(const char *target_triple,
+ ClangExpression &expr) :
+ m_expr(expr),
+ m_target_triple (),
+ m_compiler (),
+ m_code_generator (NULL),
+ m_execution_engine (),
+ m_jitted_functions ()
+{
+ // Initialize targets first, so that --version shows registered targets.
+ static struct InitializeLLVM {
+ InitializeLLVM() {
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllAsmPrinters();
+ }
+ } InitializeLLVM;
+
+ if (target_triple && target_triple[0])
+ m_target_triple = target_triple;
+ else
+ m_target_triple = llvm::sys::getHostTriple();
+
+ // 1. Create a new compiler instance.
+ m_compiler.reset(new CompilerInstance());
+ m_compiler->setLLVMContext(new LLVMContext());
+
+ // 2. Set options.
+
+ // Parse expressions as Objective C++ regardless of context.
+ // Our hook into Clang's lookup mechanism only works in C++.
+ m_compiler->getLangOpts().CPlusPlus = true;
+ m_compiler->getLangOpts().ObjC1 = true;
+ m_compiler->getLangOpts().ThreadsafeStatics = false;
+ m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access
+ m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name
+
+ // Set CodeGen options
+ m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
+ m_compiler->getCodeGenOpts().InstrumentFunctions = false;
+
+ // Disable some warnings.
+ m_compiler->getDiagnosticOpts().Warnings.push_back("no-unused-value");
+
+ // Set the target triple.
+ m_compiler->getTargetOpts().Triple = m_target_triple;
+
+ // 3. Set up various important bits of infrastructure.
+ m_compiler->createDiagnostics(0, 0);
+
+ // Create the target instance.
+ m_compiler->setTarget(TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(),
+ m_compiler->getTargetOpts()));
+
+ assert (m_compiler->hasTarget());
+
+ // Inform the target of the language options
+ //
+ // FIXME: We shouldn't need to do this, the target should be immutable once
+ // created. This complexity should be lifted elsewhere.
+ m_compiler->getTarget().setForcedLangOptions(m_compiler->getLangOpts());
+
+ // 4. Set up the diagnostic buffer for reporting errors
+
+ m_diagnostic_buffer.reset(new clang::TextDiagnosticBuffer);
+ m_compiler->getDiagnostics().setClient(m_diagnostic_buffer.get());
+
+ // 5. Set up the source management objects inside the compiler
+
+ if (!m_compiler->hasSourceManager())
+ m_compiler->createSourceManager();
+
+ m_compiler->createFileManager();
+ m_compiler->createPreprocessor();
+
+ // 6. Most of this we get from the CompilerInstance, but we
+ // also want to give the context an ExternalASTSource.
+ SelectorTable selector_table;
+ m_builtin_context.reset(new Builtin::Context(m_compiler->getTarget()));
+
+ std::auto_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(),
+ m_compiler->getSourceManager(),
+ m_compiler->getTarget(),
+ m_compiler->getPreprocessor().getIdentifierTable(),
+ selector_table,
+ *m_builtin_context.get(),
+ 0));
+
+ ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
+
+ if (decl_map)
+ {
+ OwningPtr<clang::ExternalASTSource> ast_source(new ClangASTSource(*ast_context, *decl_map));
+ ast_context->setExternalSource(ast_source);
+ }
+
+ m_compiler->setASTContext(ast_context.release());
+
+ std::string module_name("___clang_module");
+
+ m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(),
+ module_name,
+ m_compiler->getCodeGenOpts(),
+ m_compiler->getLLVMContext()));
+}
+
+ClangExpressionParser::~ClangExpressionParser()
+{
+}
+
+unsigned
+ClangExpressionParser::Parse (Stream &stream)
+{
+ m_diagnostic_buffer->FlushDiagnostics (m_compiler->getDiagnostics());
+
+ MemoryBuffer *memory_buffer = MemoryBuffer::getMemBufferCopy(m_expr.Text(), __FUNCTION__);
+ FileID memory_buffer_file_id = m_compiler->getSourceManager().createMainFileIDForMemBuffer (memory_buffer);
+
+ m_diagnostic_buffer->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor());
+
+ ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get());
+
+ if (ast_transformer)
+ ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext());
+ else
+ ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext());
+
+ m_diagnostic_buffer->EndSourceFile();
+
+ TextDiagnosticBuffer::const_iterator diag_iterator;
+
+ int num_errors = 0;
+
+ for (diag_iterator = m_diagnostic_buffer->warn_begin();
+ diag_iterator != m_diagnostic_buffer->warn_end();
+ ++diag_iterator)
+ stream.Printf("warning: %s\n", (*diag_iterator).second.c_str());
+
+ num_errors = 0;
+
+ for (diag_iterator = m_diagnostic_buffer->err_begin();
+ diag_iterator != m_diagnostic_buffer->err_end();
+ ++diag_iterator)
+ {
+ num_errors++;
+ stream.Printf("error: %s\n", (*diag_iterator).second.c_str());
+ }
+
+ return num_errors;
+}
+
+Error
+ClangExpressionParser::MakeDWARF ()
+{
+ Error err;
+
+ llvm::Module *module = m_code_generator->GetModule();
+
+ if (!module)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("IR doesn't contain a module");
+ return err;
+ }
+
+ ClangExpressionVariableStore *local_variables = m_expr.LocalVariables();
+ ClangExpressionDeclMap *decl_map = m_expr.DeclMap();
+
+ if (!local_variables)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Can't convert an expression without a VariableList to DWARF");
+ return err;
+ }
+
+ if (!decl_map)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Can't convert an expression without a DeclMap to DWARF");
+ return err;
+ }
+
+ IRToDWARF ir_to_dwarf(*local_variables, decl_map, m_expr.DwarfOpcodeStream());
+
+ if (!ir_to_dwarf.runOnModule(*module))
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't convert the expression to DWARF");
+ return err;
+ }
+
+ err.Clear();
+ return err;
+}
+
+Error
+ClangExpressionParser::MakeJIT (lldb::addr_t &func_addr, ExecutionContext &exe_ctx)
+{
+ Error err;
+
+ llvm::Module *module = m_code_generator->ReleaseModule();
+
+ if (!module)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("IR doesn't contain a module");
+ return err;
+ }
+
+ ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL
+
+ if (decl_map)
+ {
+ std::string target_error;
+
+ const llvm::Target *target = llvm::TargetRegistry::lookupTarget(m_target_triple, target_error);
+
+ if (!target)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't find a target for %s", m_target_triple.c_str());
+ return err;
+ }
+
+ std::auto_ptr<llvm::TargetMachine> target_machine(target->createTargetMachine(m_target_triple, ""));
+
+ IRForTarget ir_for_target(decl_map, target_machine->getTargetData(), m_expr.FunctionName());
+
+ if (!ir_for_target.runOnModule(*module))
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't convert the expression to DWARF");
+ return err;
+ }
+ }
+
+ m_jit_mm = new RecordingMemoryManager();
+
+ std::string error_string;
+
+ m_execution_engine.reset(llvm::ExecutionEngine::createJIT (module,
+ &error_string,
+ m_jit_mm,
+ CodeGenOpt::Default,
+ true,
+ CodeModel::Small));
+
+ if (!m_execution_engine.get())
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
+ return err;
+ }
+
+ m_execution_engine->DisableLazyCompilation();
+
+ llvm::Function *function = module->getFunction (m_expr.FunctionName());
+
+ // We don't actually need the function pointer here, this just forces it to get resolved.
+
+ void *fun_ptr = m_execution_engine->getPointerToFunction(function);
+
+ // Errors usually cause failures in the JIT, but if we're lucky we get here.
+
+ if (!fun_ptr)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't JIT the function");
+ return err;
+ }
+
+ m_jitted_functions.push_back (ClangExpressionParser::JittedFunction(m_expr.FunctionName(), (lldb::addr_t)fun_ptr));
+
+ ExecutionContext &exc_context(exe_ctx);
+
+ if (exc_context.process == NULL)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorString("Couldn't write the JIT compiled code into the target because there is no target");
+ return err;
+ }
+
+ // Look over the regions allocated for the function compiled. The JIT
+ // tries to allocate the functions & stubs close together, so we should try to
+ // write them that way too...
+ // For now I only write functions with no stubs, globals, exception tables,
+ // etc. So I only need to write the functions.
+
+ size_t alloc_size = 0;
+
+ std::map<uint8_t *, uint8_t *>::iterator fun_pos = m_jit_mm->m_functions.begin();
+ std::map<uint8_t *, uint8_t *>::iterator fun_end = m_jit_mm->m_functions.end();
+
+ for (; fun_pos != fun_end; ++fun_pos)
+ alloc_size += (*fun_pos).second - (*fun_pos).first;
+
+ Error alloc_error;
+ lldb::addr_t target_addr = exc_context.process->AllocateMemory (alloc_size, lldb::ePermissionsReadable|lldb::ePermissionsExecutable, alloc_error);
+
+ if (target_addr == LLDB_INVALID_ADDRESS)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't allocate memory for the JITted function: %s", alloc_error.AsCString("unknown error"));
+ return err;
+ }
+
+ lldb::addr_t cursor = target_addr;
+
+ for (fun_pos = m_jit_mm->m_functions.begin(); fun_pos != fun_end; fun_pos++)
+ {
+ lldb::addr_t lstart = (lldb::addr_t) (*fun_pos).first;
+ lldb::addr_t lend = (lldb::addr_t) (*fun_pos).second;
+ size_t size = lend - lstart;
+
+ Error write_error;
+
+ if (exc_context.process->WriteMemory(cursor, (void *) lstart, size, write_error) != size)
+ {
+ err.SetErrorToGenericError();
+ err.SetErrorStringWithFormat("Couldn't copy JITted function into the target: %s", write_error.AsCString("unknown error"));
+ return err;
+ }
+
+ m_jit_mm->AddToLocalToRemoteMap (lstart, size, cursor);
+ cursor += size;
+ }
+
+ std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+
+ for (pos = m_jitted_functions.begin(); pos != end; pos++)
+ {
+ (*pos).m_remote_addr = m_jit_mm->GetRemoteAddressForLocal ((*pos).m_local_addr);
+
+ if (!(*pos).m_name.compare(m_expr.FunctionName()))
+ func_addr = (*pos).m_remote_addr;
+ }
+
+ err.Clear();
+ return err;
+}
+
+Error
+ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ const char *name = m_expr.FunctionName();
+
+ Error ret;
+
+ ret.Clear();
+
+ lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
+ lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
+
+ std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
+
+ for (pos = m_jitted_functions.begin(); pos < end; pos++)
+ {
+ if (strcmp(pos->m_name.c_str(), name) == 0)
+ {
+ func_local_addr = pos->m_local_addr;
+ func_remote_addr = pos->m_remote_addr;
+ }
+ }
+
+ if (func_local_addr == LLDB_INVALID_ADDRESS)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
+ return ret;
+ }
+
+ if(log)
+ log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
+
+ std::pair <lldb::addr_t, lldb::addr_t> func_range;
+
+ func_range = m_jit_mm->GetRemoteRangeForLocal(func_local_addr);
+
+ if (func_range.first == 0 && func_range.second == 0)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
+ return ret;
+ }
+
+ if(log)
+ log->Printf("Function's code range is [0x%llx-0x%llx]", func_range.first, func_range.second);
+
+ if (!exe_ctx.target)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the target");
+ }
+
+ lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second - func_remote_addr, 0));
+
+ Error err;
+ exe_ctx.process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
+
+ if (!err.Success())
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
+ return ret;
+ }
+
+ ArchSpec arch(exe_ctx.target->GetArchitecture());
+
+ Disassembler *disassembler = Disassembler::FindPlugin(arch);
+
+ if (disassembler == NULL)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.AsCString());
+ return ret;
+ }
+
+ if (!exe_ctx.process)
+ {
+ ret.SetErrorToGenericError();
+ ret.SetErrorString("Couldn't find the process");
+ return ret;
+ }
+
+ DataExtractor extractor(buffer_sp,
+ exe_ctx.process->GetByteOrder(),
+ exe_ctx.target->GetArchitecture().GetAddressByteSize());
+
+ if(log)
+ {
+ log->Printf("Function data has contents:");
+ extractor.PutToLog (log,
+ 0,
+ extractor.GetByteSize(),
+ func_remote_addr,
+ 16,
+ DataExtractor::TypeUInt8);
+ }
+
+ disassembler->DecodeInstructions(extractor, 0, UINT32_MAX);
+
+ Disassembler::InstructionList &instruction_list = disassembler->GetInstructionList();
+
+ uint32_t bytes_offset = 0;
+
+ for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize();
+ instruction_index < num_instructions;
+ ++instruction_index)
+ {
+ Disassembler::Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index);
+ Address addr(NULL, func_remote_addr + bytes_offset);
+ instruction->Dump (&stream,
+ &addr,
+ &extractor,
+ bytes_offset,
+ exe_ctx,
+ true);
+ stream.PutChar('\n');
+ bytes_offset += instruction->GetByteSize();
+ }
+
+ return ret;
+}
diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp
index 5d3e4c8ca0d..be107ca8eb0 100644
--- a/lldb/source/Expression/ClangFunction.cpp
+++ b/lldb/source/Expression/ClangFunction.cpp
@@ -22,6 +22,8 @@
#include "llvm/Module.h"
// Project includes
+#include "lldb/Expression/ASTStructExtractor.h"
+#include "lldb/Expression/ClangExpressionParser.h"
#include "lldb/Expression/ClangFunction.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Core/DataExtractor.h"
@@ -40,11 +42,12 @@
#include "lldb/Core/Log.h"
using namespace lldb_private;
+
//----------------------------------------------------------------------
// ClangFunction constructor
//----------------------------------------------------------------------
ClangFunction::ClangFunction(const char *target_triple, ClangASTContext *ast_context, void *return_qualtype, const Address& functionAddress, const ValueList &arg_value_list) :
- ClangExpression (target_triple, NULL),
+ m_target_triple (target_triple),
m_function_ptr (NULL),
m_function_addr (functionAddress),
m_function_return_qual_type(return_qualtype),
@@ -53,18 +56,14 @@ ClangFunction::ClangFunction(const char *target_triple, ClangASTContext *ast_con
m_wrapper_struct_name ("__lldb_caller_struct"),
m_wrapper_function_addr (),
m_wrapper_args_addrs (),
- m_struct_layout (NULL),
m_arg_values (arg_value_list),
- m_value_struct_size (0),
- m_return_offset(0),
- m_return_size (0),
m_compiled (false),
m_JITted (false)
{
}
ClangFunction::ClangFunction(const char *target_triple, Function &function, ClangASTContext *ast_context, const ValueList &arg_value_list) :
- ClangExpression (target_triple, NULL),
+ m_target_triple (target_triple),
m_function_ptr (&function),
m_function_addr (),
m_function_return_qual_type (),
@@ -73,11 +72,7 @@ ClangFunction::ClangFunction(const char *target_triple, Function &function, Clan
m_wrapper_struct_name ("__lldb_caller_struct"),
m_wrapper_function_addr (),
m_wrapper_args_addrs (),
- m_struct_layout (NULL),
m_arg_values (arg_value_list),
- m_value_struct_size (0),
- m_return_offset (0),
- m_return_size (0),
m_compiled (false),
m_JITted (false)
{
@@ -95,154 +90,125 @@ ClangFunction::~ClangFunction()
unsigned
ClangFunction::CompileFunction (Stream &errors)
{
+ if (m_compiled)
+ return 0;
+
// FIXME: How does clang tell us there's no return value? We need to handle that case.
unsigned num_errors = 0;
- if (!m_compiled)
+ std::string return_type_str = ClangASTContext::GetTypeName(m_function_return_qual_type);
+
+ // Cons up the function we're going to wrap our call in, then compile it...
+ // We declare the function "extern "C"" because the compiler might be in C++
+ // mode which would mangle the name and then we couldn't find it again...
+ m_wrapper_function_text.clear();
+ m_wrapper_function_text.append ("extern \"C\" void ");
+ m_wrapper_function_text.append (m_wrapper_function_name);
+ m_wrapper_function_text.append (" (void *input)\n{\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" \n {\n");
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" (*fn_ptr) (");
+
+ // Get the number of arguments. If we have a function type and it is prototyped,
+ // trust that, otherwise use the values we were given.
+
+ // FIXME: This will need to be extended to handle Variadic functions. We'll need
+ // to pull the defined arguments out of the function, then add the types from the
+ // arguments list for the variable arguments.
+
+ uint32_t num_args = UINT32_MAX;
+ bool trust_function = false;
+ // GetArgumentCount returns -1 for an unprototyped function.
+ if (m_function_ptr)
{
- std::string return_type_str = ClangASTContext::GetTypeName(m_function_return_qual_type);
-
- // Cons up the function we're going to wrap our call in, then compile it...
- // We declare the function "extern "C"" because the compiler might be in C++
- // mode which would mangle the name and then we couldn't find it again...
- std::string expression;
- expression.append ("extern \"C\" void ");
- expression.append (m_wrapper_function_name);
- expression.append (" (void *input)\n{\n struct ");
- expression.append (m_wrapper_struct_name);
- expression.append (" \n {\n");
- expression.append (" ");
- expression.append (return_type_str);
- expression.append (" (*fn_ptr) (");
-
- // Get the number of arguments. If we have a function type and it is prototyped,
- // trust that, otherwise use the values we were given.
-
- // FIXME: This will need to be extended to handle Variadic functions. We'll need
- // to pull the defined arguments out of the function, then add the types from the
- // arguments list for the variable arguments.
-
- uint32_t num_args = UINT32_MAX;
- bool trust_function = false;
- // GetArgumentCount returns -1 for an unprototyped function.
- if (m_function_ptr)
- {
- int num_func_args = m_function_ptr->GetArgumentCount();
- if (num_func_args >= 0)
- trust_function = true;
- else
- num_args = num_func_args;
- }
+ int num_func_args = m_function_ptr->GetArgumentCount();
+ if (num_func_args >= 0)
+ trust_function = true;
+ else
+ num_args = num_func_args;
+ }
- if (num_args == UINT32_MAX)
- num_args = m_arg_values.GetSize();
+ if (num_args == UINT32_MAX)
+ num_args = m_arg_values.GetSize();
- std::string args_buffer; // This one stores the definition of all the args in "struct caller".
- std::string args_list_buffer; // This one stores the argument list called from the structure.
- for (size_t i = 0; i < num_args; i++)
- {
- const char *type_string;
- std::string type_stdstr;
+ std::string args_buffer; // This one stores the definition of all the args in "struct caller".
+ std::string args_list_buffer; // This one stores the argument list called from the structure.
+ for (size_t i = 0; i < num_args; i++)
+ {
+ const char *type_string;
+ std::string type_stdstr;
- if (trust_function)
+ if (trust_function)
+ {
+ type_string = m_function_ptr->GetArgumentTypeAtIndex(i).GetName().AsCString();
+ }
+ else
+ {
+ Value *arg_value = m_arg_values.GetValueAtIndex(i);
+ void *clang_qual_type = arg_value->GetOpaqueClangQualType ();
+ if (clang_qual_type != NULL)
{
- type_string = m_function_ptr->GetArgumentTypeAtIndex(i).GetName().AsCString();
+ type_stdstr = ClangASTContext::GetTypeName(clang_qual_type);
+ type_string = type_stdstr.c_str();
}
else
- {
- Value *arg_value = m_arg_values.GetValueAtIndex(i);
- void *clang_qual_type = arg_value->GetOpaqueClangQualType ();
- if (clang_qual_type != NULL)
- {
- type_stdstr = ClangASTContext::GetTypeName(clang_qual_type);
- type_string = type_stdstr.c_str();
- }
- else
- {
- errors.Printf("Could not determine type of input value %d.", i);
- return 1;
- }
+ {
+ errors.Printf("Could not determine type of input value %d.", i);
+ return 1;
}
+ }
+ m_wrapper_function_text.append (type_string);
+ if (i < num_args - 1)
+ m_wrapper_function_text.append (", ");
- expression.append (type_string);
- if (i < num_args - 1)
- expression.append (", ");
-
- char arg_buf[32];
- args_buffer.append (" ");
- args_buffer.append (type_string);
- snprintf(arg_buf, 31, "arg_%zd", i);
- args_buffer.push_back (' ');
- args_buffer.append (arg_buf);
- args_buffer.append (";\n");
-
- args_list_buffer.append ("__lldb_fn_data->");
- args_list_buffer.append (arg_buf);
- if (i < num_args - 1)
- args_list_buffer.append (", ");
-
- }
- expression.append (");\n"); // Close off the function calling prototype.
-
- expression.append (args_buffer);
-
- expression.append (" ");
- expression.append (return_type_str);
- expression.append (" return_value;");
- expression.append ("\n };\n struct ");
- expression.append (m_wrapper_struct_name);
- expression.append ("* __lldb_fn_data = (struct ");
- expression.append (m_wrapper_struct_name);
- expression.append (" *) input;\n");
-
- expression.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
- expression.append (args_list_buffer);
- expression.append (");\n}\n");
-
- Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
- if (log)
- log->Printf ("Expression: \n\n%s\n\n", expression.c_str());
-
- // Okay, now compile this expression:
- num_errors = ParseBareExpression (expression.c_str(), errors);
- m_compiled = (num_errors == 0);
-
- if (m_compiled)
- {
- using namespace clang;
- CompilerInstance *compiler_instance = GetCompilerInstance();
- ASTContext &ast_context = compiler_instance->getASTContext();
+ char arg_buf[32];
+ args_buffer.append (" ");
+ args_buffer.append (type_string);
+ snprintf(arg_buf, 31, "arg_%zd", i);
+ args_buffer.push_back (' ');
+ args_buffer.append (arg_buf);
+ args_buffer.append (";\n");
- DeclarationName wrapper_func_name(&ast_context.Idents.get(m_wrapper_function_name.c_str()));
- FunctionDecl::lookup_result func_lookup = ast_context.getTranslationUnitDecl()->lookup(wrapper_func_name);
- if (func_lookup.first == func_lookup.second)
- return false;
+ args_list_buffer.append ("__lldb_fn_data->");
+ args_list_buffer.append (arg_buf);
+ if (i < num_args - 1)
+ args_list_buffer.append (", ");
- FunctionDecl *wrapper_func = dyn_cast<FunctionDecl> (*(func_lookup.first));
- if (!wrapper_func)
- return false;
+ }
+ m_wrapper_function_text.append (");\n"); // Close off the function calling prototype.
- DeclarationName wrapper_struct_name(&ast_context.Idents.get(m_wrapper_struct_name.c_str()));
- RecordDecl::lookup_result struct_lookup = wrapper_func->lookup(wrapper_struct_name);
- if (struct_lookup.first == struct_lookup.second)
- return false;
+ m_wrapper_function_text.append (args_buffer);
- RecordDecl *wrapper_struct = dyn_cast<RecordDecl>(*(struct_lookup.first));
+ m_wrapper_function_text.append (" ");
+ m_wrapper_function_text.append (return_type_str);
+ m_wrapper_function_text.append (" return_value;");
+ m_wrapper_function_text.append ("\n };\n struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append ("* __lldb_fn_data = (struct ");
+ m_wrapper_function_text.append (m_wrapper_struct_name);
+ m_wrapper_function_text.append (" *) input;\n");
- if (!wrapper_struct)
- return false;
+ m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr (");
+ m_wrapper_function_text.append (args_list_buffer);
+ m_wrapper_function_text.append (");\n}\n");
- m_struct_layout = &ast_context.getASTRecordLayout (wrapper_struct);
- if (!m_struct_layout)
- {
- m_compiled = false;
- return 1;
- }
- m_return_offset = m_struct_layout->getFieldOffset(m_struct_layout->getFieldCount() - 1);
- m_return_size = (m_struct_layout->getDataSize() - m_return_offset)/8;
- }
- }
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
+ if (log)
+ log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str());
+
+ // Okay, now compile this expression
+
+ m_parser.reset(new ClangExpressionParser(m_target_triple.c_str(), *this));
+
+ num_errors = m_parser->Parse (errors);
+
+ m_compiled = (num_errors == 0);
+
+ if (!m_compiled)
+ return num_errors;
return num_errors;
}
@@ -252,24 +218,18 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors)
{
Process *process = exe_ctx.process;
- if (process == NULL)
+ if (!process)
+ return false;
+
+ if (!m_compiled)
return false;
- if (!m_JITted)
- {
- // Next we should JIT it and insert the result into the target program.
- if (!JITFunction (m_wrapper_function_name.c_str()))
- return false;
-
- if (!WriteJITCode (exe_ctx))
- return false;
-
- m_JITted = true;
- }
-
- // Next get the call address for the function:
- m_wrapper_function_addr = GetFunctionAddress (m_wrapper_function_name.c_str());
- if (m_wrapper_function_addr == LLDB_INVALID_ADDRESS)
+ if (m_JITted)
+ return true;
+
+ Error jit_error = m_parser->MakeJIT(m_wrapper_function_addr, exe_ctx);
+
+ if (!jit_error.Success())
return false;
return true;
@@ -286,12 +246,14 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &
bool
ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors)
{
- // Otherwise, allocate space for the argument passing struct, and write it.
- // We use the information in the expression parser AST to
- // figure out how to do this...
- // We should probably transcode this in this object so we can ditch the compiler instance
- // and all its associated data, and just keep the JITTed bytes.
-
+ // All the information to reconstruct the struct is provided by the
+ // StructExtractor.
+ if (!m_struct_valid)
+ {
+ errors.Printf("Argument information was not correctly parsed, so the function cannot be called.");
+ return false;
+ }
+
Error error;
using namespace clang;
ExecutionResults return_value = eExecutionSetupError;
@@ -300,12 +262,10 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &
if (process == NULL)
return return_value;
-
- uint64_t struct_size = m_struct_layout->getSize()/8; // Clang returns sizes in bytes.
-
+
if (args_addr_ref == LLDB_INVALID_ADDRESS)
{
- args_addr_ref = process->AllocateMemory(struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
+ args_addr_ref = process->AllocateMemory(m_struct_size, lldb::ePermissionsReadable|lldb::ePermissionsWritable, error);
if (args_addr_ref == LLDB_INVALID_ADDRESS)
return false;
m_wrapper_args_addrs.push_back (args_addr_ref);
@@ -323,7 +283,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &
// Make a data extractor and put the address into the right byte order & size.
uint64_t fun_addr = function_address.GetLoadAddress(exe_ctx.process);
- int first_offset = m_struct_layout->getFieldOffset(0)/8;
+ int first_offset = m_member_offsets[0];
process->WriteMemory(args_addr_ref + first_offset, &fun_addr, 8, error);
// FIXME: We will need to extend this for Variadic functions.
@@ -341,7 +301,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &
{
// FIXME: We should sanity check sizes.
- int offset = m_struct_layout->getFieldOffset(i+1)/8; // Clang sizes are in bytes.
+ int offset = m_member_offsets[i+1]; // Clang sizes are in bytes.
Value *arg_value = arg_values.GetValueAtIndex(i);
// FIXME: For now just do scalars:
@@ -419,7 +379,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg
data_buffer.resize(m_return_size);
Process *process = exe_ctx.process;
Error error;
- size_t bytes_read = process->ReadMemory(args_addr + m_return_offset/8, &data_buffer.front(), m_return_size, error);
+ size_t bytes_read = process->ReadMemory(args_addr + m_return_offset, &data_buffer.front(), m_return_size, error);
if (bytes_read == 0)
{
@@ -717,69 +677,8 @@ ClangFunction::ExecuteFunction(
return eExecutionCompleted;
}
-ClangFunction::ExecutionResults
-ClangFunction::ExecuteFunctionWithABI(ExecutionContext &exe_ctx, Stream &errors, Value &results)
+clang::ASTConsumer *
+ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough)
{
- // FIXME: Use the errors Stream for better error reporting.
- using namespace clang;
- ExecutionResults return_value = eExecutionSetupError;
-
- Process *process = exe_ctx.process;
-
- if (process == NULL)
- {
- errors.Printf("Can't call a function without a process.");
- return return_value;
- }
-
- //unsigned int num_args = m_arg_values.GetSize();
- //unsigned int arg_index;
-
- //for (arg_index = 0; arg_index < num_args; ++arg_index)
- // m_arg_values.GetValueAtIndex(arg_index)->ResolveValue(&exe_ctx, GetASTContext());
-
- ThreadPlan *call_plan = exe_ctx.thread->QueueThreadPlanForCallFunction (false,
- m_function_addr,
- m_arg_values,
- true);
- if (call_plan == NULL)
- return return_value;
-
- call_plan->SetPrivate(true);
-
- // We need to call the function synchronously, so spin waiting for it to return.
- // If we get interrupted while executing, we're going to lose our context, and
- // won't be able to gather the result at this point.
-
- process->Resume ();
-
- while (1)
- {
- lldb::EventSP event_sp;
-
- // Now wait for the process to stop again:
- // FIXME: Probably want a time out.
- lldb::StateType stop_state = process->WaitForStateChangedEvents (NULL, event_sp);
- if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
- continue;
-
- if (exe_ctx.thread->IsThreadPlanDone (call_plan))
- {
- return_value = eExecutionCompleted;
- break;
- }
- else if (exe_ctx.thread->WasThreadPlanDiscarded (call_plan))
- {
- return_value = eExecutionDiscarded;
- break;
- }
- else
- {
- return_value = eExecutionInterrupted;
- break;
- }
-
- }
-
- return eExecutionCompleted;
+ return new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this);
}
diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp
new file mode 100644
index 00000000000..afd94bbd6a8
--- /dev/null
+++ b/lldb/source/Expression/ClangUserExpression.cpp
@@ -0,0 +1,257 @@
+//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+#include <stdio.h>
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+
+// C++ Includes
+#include <cstdlib>
+#include <string>
+#include <map>
+
+#include "lldb/Core/ConstString.h"
+#include "lldb/Core/Log.h"
+#include "lldb/Core/StreamString.h"
+#include "lldb/Expression/ClangExpressionDeclMap.h"
+#include "lldb/Expression/ClangExpressionParser.h"
+#include "lldb/Expression/ClangFunction.h"
+#include "lldb/Expression/ASTResultSynthesizer.h"
+#include "lldb/Expression/ClangUserExpression.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb_private;
+
+ClangUserExpression::ClangUserExpression (const char *expr) :
+ m_expr_text(expr),
+ m_jit_addr(LLDB_INVALID_ADDRESS)
+{
+ StreamString m_transformed_stream;
+
+ m_transformed_stream.Printf("extern \"C\" void %s(void *___clang_arg) { %s; }\n",
+ FunctionName(),
+ m_expr_text.c_str());
+
+ m_transformed_text = m_transformed_stream.GetData();
+}
+
+clang::ASTConsumer *
+ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough)
+{
+ return new ASTResultSynthesizer(passthrough);
+}
+
+bool
+ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ ////////////////////////////////////
+ // Set up the target and compiler
+ //
+
+ Target *target = exe_ctx.target;
+
+ if (!target)
+ {
+ error_stream.PutCString ("error: invalid target\n");
+ return false;
+ }
+
+ ConstString target_triple;
+
+ target->GetTargetTriple (target_triple);
+
+ if (!target_triple)
+ target_triple = Host::GetTargetTriple ();
+
+ if (!target_triple)
+ {
+ error_stream.PutCString ("error: invalid target triple\n");
+ return false;
+ }
+
+ //////////////////////////
+ // Parse the expression
+ //
+
+ m_expr_decl_map.reset(new ClangExpressionDeclMap(&exe_ctx));
+
+ ClangExpressionParser parser(target_triple.GetCString(), *this);
+
+ unsigned num_errors = parser.Parse (error_stream);
+
+ if (num_errors)
+ {
+ error_stream.Printf ("error: %d errors parsing expression\n", num_errors);
+ return false;
+ }
+
+ ///////////////////////////////////////////////
+ // Convert the output of the parser to DWARF
+ //
+
+ m_dwarf_opcodes.reset(new StreamString);
+ m_dwarf_opcodes->SetByteOrder (lldb::eByteOrderHost);
+ m_dwarf_opcodes->GetFlags ().Set (Stream::eBinary);
+
+ m_local_variables.reset(new ClangExpressionVariableStore());
+
+ Error dwarf_error = parser.MakeDWARF ();
+
+ if (dwarf_error.Success())
+ {
+ if (log)
+ log->Printf("Code can be interpreted.");
+
+ return true;
+ }
+
+ //////////////////////////////////
+ // JIT the output of the parser
+ //
+
+ m_dwarf_opcodes.reset();
+
+ Error jit_error = parser.MakeJIT (m_jit_addr, exe_ctx);
+
+ if (jit_error.Success())
+ {
+ if (log)
+ {
+ log->Printf("Code can be run in the target.");
+
+ StreamString disassembly_stream;
+
+ Error err = parser.DisassembleFunction(disassembly_stream, exe_ctx);
+
+ if (!err.Success())
+ {
+ log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
+ }
+ else
+ {
+ log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
+ }
+ }
+
+ return true;
+ }
+ else
+ {
+ error_stream.Printf ("error: expression can't be interpreted or run\n", num_errors);
+ return false;
+ }
+}
+
+bool
+ClangUserExpression::Execute (Stream &error_stream,
+ ExecutionContext &exe_ctx,
+ ClangExpressionVariable *&result)
+{
+ Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
+
+ if (m_dwarf_opcodes.get())
+ {
+ // TODO execute the JITted opcodes
+
+ error_stream.Printf("We don't currently support executing DWARF expressions");
+
+ return false;
+ }
+ else if (m_jit_addr != LLDB_INVALID_ADDRESS)
+ {
+ lldb::addr_t struct_address;
+
+ Error materialize_error;
+
+ if (!m_expr_decl_map->Materialize(&exe_ctx, struct_address, materialize_error))
+ {
+ error_stream.Printf("Couldn't materialize struct: %s\n", materialize_error.AsCString("unknown error"));
+ return false;
+ }
+
+ if (log)
+ {
+ log->Printf("Function address : 0x%llx", (uint64_t)m_jit_addr);
+ log->Printf("Structure address : 0x%llx", (uint64_t)struct_address);
+
+ StreamString args;
+
+ Error dump_error;
+
+ if (!m_expr_decl_map->DumpMaterializedStruct(&exe_ctx, args, dump_error))
+ {
+ log->Printf("Couldn't extract variable values : %s", dump_error.AsCString("unknown error"));
+ }
+ else
+ {
+ log->Printf("Structure contents:\n%s", args.GetData());
+ }
+ }
+
+ ClangFunction::ExecutionResults execution_result =
+ ClangFunction::ExecuteFunction (exe_ctx, m_jit_addr, struct_address, true, true, 10000, error_stream);
+
+ if (execution_result != ClangFunction::eExecutionCompleted)
+ {
+ const char *result_name;
+
+ switch (execution_result)
+ {
+ case ClangFunction::eExecutionCompleted:
+ result_name = "eExecutionCompleted";
+ break;
+ case ClangFunction::eExecutionDiscarded:
+ result_name = "eExecutionDiscarded";
+ break;
+ case ClangFunction::eExecutionInterrupted:
+ result_name = "eExecutionInterrupted";
+ break;
+ case ClangFunction::eExecutionSetupError:
+ result_name = "eExecutionSetupError";
+ break;
+ case ClangFunction::eExecutionTimedOut:
+ result_name = "eExecutionTimedOut";
+ break;
+ }
+
+ error_stream.Printf ("Couldn't execute function; result was %s\n", result_name);
+ return false;
+ }
+
+ Error expr_error;
+
+ if (!m_expr_decl_map->Dematerialize(&exe_ctx, result, expr_error))
+ {
+ error_stream.Printf ("Couldn't dematerialize struct : %s\n", expr_error.AsCString("unknown error"));
+ return false;
+ }
+
+ return true;
+ }
+ else
+ {
+ error_stream.Printf("Expression can't be run; neither DWARF nor a JIT compiled function are present");
+ return false;
+ }
+}
+
+StreamString &
+ClangUserExpression::DwarfOpcodeStream ()
+{
+ if (!m_dwarf_opcodes.get())
+ m_dwarf_opcodes.reset(new StreamString());
+
+ return *m_dwarf_opcodes.get();
+}
diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp
index c14891b160c..d74302c7299 100644
--- a/lldb/source/Expression/IRForTarget.cpp
+++ b/lldb/source/Expression/IRForTarget.cpp
@@ -31,11 +31,13 @@ using namespace llvm;
static char ID;
IRForTarget::IRForTarget(lldb_private::ClangExpressionDeclMap *decl_map,
- const TargetData *target_data) :
+ const TargetData *target_data,
+ const char *func_name) :
ModulePass(&ID),
m_decl_map(decl_map),
m_target_data(target_data),
- m_sel_registerName(NULL)
+ m_sel_registerName(NULL),
+ m_func_name(func_name)
{
}
@@ -910,12 +912,12 @@ IRForTarget::runOnModule(Module &M)
{
lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
- Function* function = M.getFunction(StringRef("___clang_expr"));
+ Function* function = M.getFunction(StringRef(m_func_name.c_str()));
if (!function)
{
if (log)
- log->Printf("Couldn't find ___clang_expr() in the module");
+ log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
return false;
}
diff --git a/lldb/source/Expression/IRToDWARF.cpp b/lldb/source/Expression/IRToDWARF.cpp
index 121a47c171e..b158da6c1f5 100644
--- a/lldb/source/Expression/IRToDWARF.cpp
+++ b/lldb/source/Expression/IRToDWARF.cpp
@@ -26,13 +26,15 @@ using namespace llvm;
static char ID;
-IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableList &variable_list,
+IRToDWARF::IRToDWARF(lldb_private::ClangExpressionVariableStore &local_vars,
lldb_private::ClangExpressionDeclMap *decl_map,
- lldb_private::StreamString &strm) :
+ lldb_private::StreamString &strm,
+ const char *func_name) :
ModulePass(&ID),
- m_variable_list(variable_list),
+ m_local_vars(local_vars),
m_decl_map(decl_map),
- m_strm(strm)
+ m_strm(strm),
+ m_func_name(func_name)
{
}
@@ -171,14 +173,14 @@ IRToDWARF::runOnModule(Module &M)
{
lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS);
- llvm::Function* function = M.getFunction(StringRef("___clang_expr"));
+ llvm::Function* function = M.getFunction(StringRef(m_func_name.c_str()));
if (!function)
{
if (log)
- log->Printf("Couldn't find ___clang_expr() in the module");
+ log->Printf("Couldn't find %s() in the module", m_func_name.c_str());
- return 1;
+ return false;
}
Relocator relocator;
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index db5cb65f42e..eaf886f76ad 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -16,7 +16,7 @@
#include "../Commands/CommandObjectApropos.h"
#include "../Commands/CommandObjectArgs.h"
#include "../Commands/CommandObjectBreakpoint.h"
-#include "../Commands/CommandObjectCall.h"
+//#include "../Commands/CommandObjectCall.h"
#include "../Commands/CommandObjectDelete.h"
#include "../Commands/CommandObjectDisassemble.h"
#include "../Commands/CommandObjectExpression.h"
@@ -207,7 +207,7 @@ CommandInterpreter::LoadCommandDictionary ()
m_command_dict["append"] = CommandObjectSP (new CommandObjectAppend ());
m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos ());
m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this));
- m_command_dict["call"] = CommandObjectSP (new CommandObjectCall ());
+ //m_command_dict["call"] = CommandObjectSP (new CommandObjectCall ());
m_command_dict["commands"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this));
m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble ());
m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression ());
OpenPOWER on IntegriCloud