diff options
author | Sean Callanan <scallanan@apple.com> | 2010-07-01 20:08:22 +0000 |
---|---|---|
committer | Sean Callanan <scallanan@apple.com> | 2010-07-01 20:08:22 +0000 |
commit | 116be5347ef9a97e8c82d77279deaaebe8c8266f (patch) | |
tree | 314b36654c293ac78fa65edb8495b60bea4b6301 /lldb/source | |
parent | 329d202362313eda5a29e59bf0e039232ef1e565 (diff) | |
download | bcm5719-llvm-116be5347ef9a97e8c82d77279deaaebe8c8266f.tar.gz bcm5719-llvm-116be5347ef9a97e8c82d77279deaaebe8c8266f.zip |
Added a SemaConsumer that transforms the ASTs for
an expression, adding code to put the value of the
last expression (if there is one) into a variable
and write the address of that variable to a global
pointer.
llvm-svn: 107419
Diffstat (limited to 'lldb/source')
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 2 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpression.cpp | 88 | ||||
-rw-r--r-- | lldb/source/Expression/ClangResultSynthesizer.cpp | 341 |
3 files changed, 394 insertions, 37 deletions
diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index e98303c739e..64106eda2d0 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -233,7 +233,7 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream if (bare) num_errors = clang_expr.ParseBareExpression (llvm::StringRef (expr), error_stream); else - num_errors = clang_expr.ParseExpression (expr, error_stream); + num_errors = clang_expr.ParseExpression (expr, error_stream, m_options.use_ir); if (num_errors) { diff --git a/lldb/source/Expression/ClangExpression.cpp b/lldb/source/Expression/ClangExpression.cpp index b249584ee20..fc8cebe8385 100644 --- a/lldb/source/Expression/ClangExpression.cpp +++ b/lldb/source/Expression/ClangExpression.cpp @@ -38,6 +38,7 @@ #include "clang/Frontend/VerifyDiagnosticsClient.h" #include "clang/Lex/Preprocessor.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" @@ -53,6 +54,7 @@ #include "lldb/Core/Log.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangASTSource.h" +#include "lldb/Expression/ClangResultSynthesizer.h" #include "lldb/Expression/ClangStmtVisitor.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Expression/RecordingMemoryManager.h" @@ -279,19 +281,23 @@ ClangExpression::GetASTContext () } unsigned -ClangExpression::ParseExpression (const char *expr_text, Stream &stream) +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("void ___clang_expr()\n{\n\t"); + std::string func_expr("extern \"C\" void ___clang_expr()\n{\n\t"); func_expr.append(expr_text); func_expr.append(";\n}"); - return ParseBareExpression (func_expr, stream); + return ParseBareExpression (func_expr, stream, add_result_var); } unsigned -ClangExpression::ParseBareExpression (llvm::StringRef expr_text, Stream &stream) +ClangExpression::ParseBareExpression (llvm::StringRef expr_text, + Stream &stream, + bool add_result_var) { Mutex::Locker locker(GetClangMutex ()); @@ -354,7 +360,17 @@ ClangExpression::ParseBareExpression (llvm::StringRef expr_text, Stream &stream) // - 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. - ParseAST(m_clang_ap->getPreprocessor(), m_code_generator_ptr, m_clang_ap->getASTContext()); + + 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(); @@ -413,7 +429,6 @@ ClangExpression::ParseBareExpression (llvm::StringRef expr_text, Stream &stream) return num_errors; } - static FrontendAction * CreateFrontendAction(CompilerInstance &CI) { @@ -471,41 +486,42 @@ ClangExpression::ConvertIRToDWARF (ClangExpressionVariableList &excpr_local_vari return 1; } - llvm::Module::iterator fi; - - for (fi = module->begin(); - fi != module->end(); - ++fi) + llvm::Function* function = module->getFunction(StringRef("___clang_expr")); + + if (!function) { - llvm::Function &function = *fi; - if (log) - log->Printf("IR for %s:", function.getName().str().c_str()); + log->Printf("Couldn't find ___clang_expr() in the module"); + + return 1; + } + + if (log) + log->Printf("IR for %s:", function->getName().str().c_str()); + + llvm::Function::iterator bbi; + + for (bbi = function->begin(); + bbi != function->end(); + ++bbi) + { + llvm::BasicBlock &bb = *bbi; - llvm::Function::iterator bbi; + llvm::BasicBlock::iterator ii; - for (bbi = function.begin(); - bbi != function.end(); - ++bbi) + for (ii = bb.begin(); + ii != bb.end(); + ++ii) { - llvm::BasicBlock &bb = *bbi; - - llvm::BasicBlock::iterator ii; - - for (ii = bb.begin(); - ii != bb.end(); - ++ii) - { - llvm::Instruction &inst = *ii; - - std::string s; - llvm::raw_string_ostream os(s); - - inst.print(os); - - if (log) - log->Printf(" %s", s.c_str()); - } + llvm::Instruction &inst = *ii; + + std::string s; + llvm::raw_string_ostream os(s); + + inst.print(os); + + if (log) + log->Printf(" %s", s.c_str()); } } diff --git a/lldb/source/Expression/ClangResultSynthesizer.cpp b/lldb/source/Expression/ClangResultSynthesizer.cpp new file mode 100644 index 00000000000..3a5769b7f3b --- /dev/null +++ b/lldb/source/Expression/ClangResultSynthesizer.cpp @@ -0,0 +1,341 @@ +//===-- ClangResultSynthesizer.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/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/ClangResultSynthesizer.h" + +using namespace llvm; +using namespace clang; +using namespace lldb_private; + +ClangResultSynthesizer::ClangResultSynthesizer(ASTConsumer *passthrough) : + m_passthrough(passthrough), + m_passthrough_sema(NULL), + m_sema(NULL), + m_ast_context(NULL) +{ + if (!m_passthrough) + return; + + m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough); +} + +ClangResultSynthesizer::~ClangResultSynthesizer() +{ +} + +void +ClangResultSynthesizer::Initialize(ASTContext &Context) +{ + m_ast_context = &Context; + + if (m_passthrough) + m_passthrough->Initialize(Context); +} + +void +ClangResultSynthesizer::TransformTopLevelDecl(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) + { + TransformTopLevelDecl(*decl_iterator); + } + } + + FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D); + + if (m_ast_context && + function_decl && + !strcmp(function_decl->getNameAsCString(), + "___clang_expr")) + { + SynthesizeResult(*m_ast_context, function_decl); + } +} + +void +ClangResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D) +{ + DeclGroupRef::iterator decl_iterator; + + for (decl_iterator = D.begin(); + decl_iterator != D.end(); + ++decl_iterator) + { + Decl *decl = *decl_iterator; + + TransformTopLevelDecl(decl); + } + + if (m_passthrough) + m_passthrough->HandleTopLevelDecl(D); +} + +bool +ClangResultSynthesizer::SynthesizeResult (ASTContext &Ctx, + FunctionDecl *FunDecl) +{ + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); + + if (!m_sema) + return false; + + FunctionDecl *function_decl = FunDecl; + + if (!function_decl) + return false; + + Stmt *function_body = function_decl->getBody(); + CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body); + + if (!compound_stmt) + return false; + + if (compound_stmt->body_empty()) + return false; + + Stmt **last_stmt_ptr = compound_stmt->body_end() - 1; + Stmt *last_stmt = *last_stmt_ptr; + + Expr *last_expr = dyn_cast<Expr>(last_stmt); + + if (!last_expr) + // No auxiliary variable necessary; expression returns void + return true; + + QualType expr_qual_type = last_expr->getType(); + clang::Type *expr_type = expr_qual_type.getTypePtr(); + + if (!expr_type) + return false; + + if (expr_type->isVoidType()) + return true; + + if (log) + { + std::string s = expr_qual_type.getAsString(); + + log->Printf("Last statement's type: %s", s.c_str()); + } + + IdentifierInfo &result_id = Ctx.Idents.get("___clang_expr_result"); + + DeclContext *decl_context = function_decl->getDeclContext(); + + clang::VarDecl *result_decl = VarDecl::Create(Ctx, + function_decl, + SourceLocation(), + &result_id, + expr_qual_type, + NULL, + VarDecl::Static, + VarDecl::Static); + + if (!result_decl) + return false; + + function_decl->addDecl(result_decl); + + /////////////////////////////// + // call AddInitializerToDecl + // + + Parser::DeclPtrTy result_decl_ptr; + result_decl_ptr.set(result_decl); + + m_action->AddInitializerToDecl(result_decl_ptr, Parser::ExprArg(*m_action, last_expr)); + + ///////////////////////////////// + // call ConvertDeclToDeclGroup + // + + Parser::DeclGroupPtrTy result_decl_group_ptr; + + result_decl_group_ptr = m_action->ConvertDeclToDeclGroup(result_decl_ptr); + + //////////////////////// + // call ActOnDeclStmt + // + + Parser::OwningStmtResult result_initialization_stmt_result(m_action->ActOnDeclStmt(result_decl_group_ptr, + SourceLocation(), + SourceLocation())); + + + /////////////////////////////////////////////// + // Synthesize external void pointer variable + // + + IdentifierInfo &result_ptr_id = Ctx.Idents.get("___clang_expr_result_ptr"); + + clang::VarDecl *result_ptr_decl = VarDecl::Create(Ctx, + decl_context, + SourceLocation(), + &result_ptr_id, + Ctx.VoidPtrTy, + NULL, + VarDecl::Extern, + VarDecl::Extern); + + ///////////////////////////////////////////// + // Build a DeclRef for the result variable + // + + DeclRefExpr *result_decl_ref_expr = DeclRefExpr::Create(Ctx, + NULL, + SourceRange(), + result_decl, + SourceLocation(), + expr_qual_type); + + /////////////////////// + // call ActOnUnaryOp + // + + Scope my_scope(NULL, (Scope::BlockScope | Scope::FnScope | Scope::DeclScope)); + + Parser::DeclPtrTy result_ptr_decl_ptr; + result_ptr_decl_ptr.set(result_ptr_decl); + + Parser::OwningExprResult addressof_expr_result(m_action->ActOnUnaryOp(&my_scope, + SourceLocation(), + tok::amp, + Parser::ExprArg(*m_action, result_decl_ref_expr))); + + //////////////////////////////////////////// + // Build a DeclRef for the result pointer + // + + DeclRefExpr *result_ptr_decl_ref_expr = DeclRefExpr::Create(Ctx, + NULL, + SourceRange(), + result_ptr_decl, + SourceLocation(), + Ctx.VoidPtrTy); + + //////////////////////// + // call ActOnBinaryOp + // + + Parser::OwningExprResult assignment_expr_result(m_action->ActOnBinOp(&my_scope, + SourceLocation(), + tok::equal, + Parser::ExprArg(*m_action, result_ptr_decl_ref_expr), + Parser::ExprArg(*m_action, addressof_expr_result.take()))); + + //////////////////////////// + // call ActOnCompoundStmt + // + + void *stmts[2]; + + stmts[0] = result_initialization_stmt_result.take(); + stmts[1] = assignment_expr_result.take(); + + Parser::OwningStmtResult compound_stmt_result(m_action->ActOnCompoundStmt(SourceLocation(), + SourceLocation(), + Parser::MultiStmtArg(*m_action, stmts, 2), + false)); + + //////////////////////////////////////////////// + // replace the old statement with the new one + // + + *last_stmt_ptr = reinterpret_cast<Stmt*>(compound_stmt_result.take()); + + if (log) + { + std::string s; + raw_string_ostream os(s); + + function_decl->print(os); + + os.flush(); + + log->Printf("Transformed function AST:\n%s", s.c_str()); + } + + return true; +} + +void +ClangResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx) +{ + if (m_passthrough) + m_passthrough->HandleTranslationUnit(Ctx); +} + +void +ClangResultSynthesizer::HandleTagDeclDefinition(TagDecl *D) +{ + if (m_passthrough) + m_passthrough->HandleTagDeclDefinition(D); +} + +void +ClangResultSynthesizer::CompleteTentativeDefinition(VarDecl *D) +{ + if (m_passthrough) + m_passthrough->CompleteTentativeDefinition(D); +} + +void +ClangResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired) +{ + if (m_passthrough) + m_passthrough->HandleVTable(RD, DefinitionRequired); +} + +void +ClangResultSynthesizer::PrintStats() +{ + if (m_passthrough) + m_passthrough->PrintStats(); +} + +void +ClangResultSynthesizer::InitializeSema(Sema &S) +{ + m_sema = &S; + m_action = reinterpret_cast<Action*>(m_sema); + + if (m_passthrough_sema) + m_passthrough_sema->InitializeSema(S); +} + +void +ClangResultSynthesizer::ForgetSema() +{ + m_sema = NULL; + m_action = NULL; + + if (m_passthrough_sema) + m_passthrough_sema->ForgetSema(); +} |