Home | History | Annotate | Download | only in Expression
      1 //===-- ASTResultSynthesizer.cpp --------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "stdlib.h"
     11 #include "clang/AST/ASTContext.h"
     12 #include "clang/AST/Decl.h"
     13 #include "clang/AST/DeclCXX.h"
     14 #include "clang/AST/DeclGroup.h"
     15 #include "clang/AST/DeclObjC.h"
     16 #include "clang/AST/Expr.h"
     17 #include "clang/AST/Stmt.h"
     18 #include "clang/Parse/Parser.h"
     19 #include "clang/Sema/SemaDiagnostic.h"
     20 #include "llvm/Support/Casting.h"
     21 #include "llvm/Support/raw_ostream.h"
     22 #include "lldb/Core/Log.h"
     23 #include "lldb/Expression/ClangPersistentVariables.h"
     24 #include "lldb/Expression/ASTResultSynthesizer.h"
     25 #include "lldb/Symbol/ClangASTContext.h"
     26 #include "lldb/Symbol/ClangASTImporter.h"
     27 #include "lldb/Target/Target.h"
     28 
     29 using namespace llvm;
     30 using namespace clang;
     31 using namespace lldb_private;
     32 
     33 ASTResultSynthesizer::ASTResultSynthesizer(ASTConsumer *passthrough,
     34                                            Target &target) :
     35     m_ast_context (NULL),
     36     m_passthrough (passthrough),
     37     m_passthrough_sema (NULL),
     38     m_target (target),
     39     m_sema (NULL)
     40 {
     41     if (!m_passthrough)
     42         return;
     43 
     44     m_passthrough_sema = dyn_cast<SemaConsumer>(passthrough);
     45 }
     46 
     47 ASTResultSynthesizer::~ASTResultSynthesizer()
     48 {
     49 }
     50 
     51 void
     52 ASTResultSynthesizer::Initialize(ASTContext &Context)
     53 {
     54     m_ast_context = &Context;
     55 
     56     if (m_passthrough)
     57         m_passthrough->Initialize(Context);
     58 }
     59 
     60 void
     61 ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
     62 {
     63     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
     64 
     65     if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
     66     {
     67         if (log && log->GetVerbose())
     68         {
     69             if (named_decl->getIdentifier())
     70                 log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
     71             else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
     72                 log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
     73             else
     74                 log->Printf("TransformTopLevelDecl(<complex>)");
     75         }
     76 
     77     }
     78 
     79     if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
     80     {
     81         RecordDecl::decl_iterator decl_iterator;
     82 
     83         for (decl_iterator = linkage_spec_decl->decls_begin();
     84              decl_iterator != linkage_spec_decl->decls_end();
     85              ++decl_iterator)
     86         {
     87             TransformTopLevelDecl(*decl_iterator);
     88         }
     89     }
     90     else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
     91     {
     92         if (m_ast_context &&
     93             !method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
     94         {
     95             RecordPersistentTypes(method_decl);
     96             SynthesizeObjCMethodResult(method_decl);
     97         }
     98     }
     99     else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
    100     {
    101         if (m_ast_context &&
    102             !function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
    103         {
    104             RecordPersistentTypes(function_decl);
    105             SynthesizeFunctionResult(function_decl);
    106         }
    107     }
    108 }
    109 
    110 bool
    111 ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
    112 {
    113     DeclGroupRef::iterator decl_iterator;
    114 
    115     for (decl_iterator = D.begin();
    116          decl_iterator != D.end();
    117          ++decl_iterator)
    118     {
    119         Decl *decl = *decl_iterator;
    120 
    121         TransformTopLevelDecl(decl);
    122     }
    123 
    124     if (m_passthrough)
    125         return m_passthrough->HandleTopLevelDecl(D);
    126     return true;
    127 }
    128 
    129 bool
    130 ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
    131 {
    132     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    133 
    134     if (!m_sema)
    135         return false;
    136 
    137     FunctionDecl *function_decl = FunDecl;
    138 
    139     if (!function_decl)
    140         return false;
    141 
    142     if (log && log->GetVerbose())
    143     {
    144         std::string s;
    145         raw_string_ostream os(s);
    146 
    147         function_decl->print(os);
    148 
    149         os.flush();
    150 
    151         log->Printf ("Untransformed function AST:\n%s", s.c_str());
    152     }
    153 
    154     Stmt *function_body = function_decl->getBody();
    155     CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
    156 
    157     bool ret = SynthesizeBodyResult (compound_stmt,
    158                                      function_decl);
    159 
    160     if (log && log->GetVerbose())
    161     {
    162         std::string s;
    163         raw_string_ostream os(s);
    164 
    165         function_decl->print(os);
    166 
    167         os.flush();
    168 
    169         log->Printf ("Transformed function AST:\n%s", s.c_str());
    170     }
    171 
    172     return ret;
    173 }
    174 
    175 bool
    176 ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
    177 {
    178     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    179 
    180     if (!m_sema)
    181         return false;
    182 
    183     if (!MethodDecl)
    184         return false;
    185 
    186     if (log && log->GetVerbose())
    187     {
    188         std::string s;
    189         raw_string_ostream os(s);
    190 
    191         MethodDecl->print(os);
    192 
    193         os.flush();
    194 
    195         log->Printf ("Untransformed method AST:\n%s", s.c_str());
    196     }
    197 
    198     Stmt *method_body = MethodDecl->getBody();
    199 
    200     if (!method_body)
    201         return false;
    202 
    203     CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
    204 
    205     bool ret = SynthesizeBodyResult (compound_stmt,
    206                                      MethodDecl);
    207 
    208     if (log && log->GetVerbose())
    209     {
    210         std::string s;
    211         raw_string_ostream os(s);
    212 
    213         MethodDecl->print(os);
    214 
    215         os.flush();
    216 
    217         log->Printf("Transformed method AST:\n%s", s.c_str());
    218     }
    219 
    220     return ret;
    221 }
    222 
    223 bool
    224 ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
    225                                             DeclContext *DC)
    226 {
    227     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    228 
    229     ASTContext &Ctx(*m_ast_context);
    230 
    231     if (!Body)
    232         return false;
    233 
    234     if (Body->body_empty())
    235         return false;
    236 
    237     Stmt **last_stmt_ptr = Body->body_end() - 1;
    238     Stmt *last_stmt = *last_stmt_ptr;
    239 
    240     while (dyn_cast<NullStmt>(last_stmt))
    241     {
    242         if (last_stmt_ptr != Body->body_begin())
    243         {
    244             last_stmt_ptr--;
    245             last_stmt = *last_stmt_ptr;
    246         }
    247         else
    248         {
    249             return false;
    250         }
    251     }
    252 
    253     Expr *last_expr = dyn_cast<Expr>(last_stmt);
    254 
    255     if (!last_expr)
    256         // No auxiliary variable necessary; expression returns void
    257         return true;
    258 
    259     // In C++11, last_expr can be a LValueToRvalue implicit cast.  Strip that off if that's the
    260     // case.
    261 
    262     do {
    263         ImplicitCastExpr *implicit_cast = dyn_cast<ImplicitCastExpr>(last_expr);
    264 
    265         if (!implicit_cast)
    266             break;
    267 
    268         if (implicit_cast->getCastKind() != CK_LValueToRValue)
    269             break;
    270 
    271         last_expr = implicit_cast->getSubExpr();
    272     } while (0);
    273 
    274     // is_lvalue is used to record whether the expression returns an assignable Lvalue or an
    275     // Rvalue.  This is relevant because they are handled differently.
    276     //
    277     // For Lvalues
    278     //
    279     //   - In AST result synthesis (here!) the expression E is transformed into an initialization
    280     //     T *$__lldb_expr_result_ptr = &E.
    281     //
    282     //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    283     //     passed into the expression.
    284     //
    285     //   - In IR transformations, reads and writes to $__lldb_expr_result_ptr are redirected at
    286     //     an entry in the struct ($__lldb_arg) passed into the expression.  (Other persistent
    287     //     variables are treated similarly, having been materialized as references, but in those
    288     //     cases the value of the reference itself is never modified.)
    289     //
    290     //   - During materialization, $0 (the result persistent variable) is ignored.
    291     //
    292     //   - During dematerialization, $0 is marked up as a load address with value equal to the
    293     //     contents of the structure entry.
    294     //
    295     // For Rvalues
    296     //
    297     //   - In AST result synthesis the expression E is transformed into an initialization
    298     //     static T $__lldb_expr_result = E.
    299     //
    300     //   - In structure allocation, a pointer-sized slot is allocated in the struct that is to be
    301     //     passed into the expression.
    302     //
    303     //   - In IR transformations, an instruction is inserted at the beginning of the function to
    304     //     dereference the pointer resident in the slot.  Reads and writes to $__lldb_expr_result
    305     //     are redirected at that dereferenced version.  Guard variables for the static variable
    306     //     are excised.
    307     //
    308     //   - During materialization, $0 (the result persistent variable) is populated with the location
    309     //     of a newly-allocated area of memory.
    310     //
    311     //   - During dematerialization, $0 is ignored.
    312 
    313     bool is_lvalue =
    314         (last_expr->getValueKind() == VK_LValue || last_expr->getValueKind() == VK_XValue) &&
    315         (last_expr->getObjectKind() == OK_Ordinary);
    316 
    317     QualType expr_qual_type = last_expr->getType();
    318     const clang::Type *expr_type = expr_qual_type.getTypePtr();
    319 
    320     if (!expr_type)
    321         return false;
    322 
    323     if (expr_type->isVoidType())
    324         return true;
    325 
    326     if (log)
    327     {
    328         std::string s = expr_qual_type.getAsString();
    329 
    330         log->Printf("Last statement is an %s with type: %s", (is_lvalue ? "lvalue" : "rvalue"), s.c_str());
    331     }
    332 
    333     clang::VarDecl *result_decl = NULL;
    334 
    335     if (is_lvalue)
    336     {
    337         IdentifierInfo *result_ptr_id;
    338 
    339         if (expr_type->isFunctionType())
    340             result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result"); // functions actually should be treated like function pointers
    341         else
    342             result_ptr_id = &Ctx.Idents.get("$__lldb_expr_result_ptr");
    343 
    344         m_sema->RequireCompleteType(SourceLocation(), expr_qual_type, clang::diag::err_incomplete_type);
    345 
    346         QualType ptr_qual_type;
    347 
    348         if (expr_qual_type->getAs<ObjCObjectType>() != NULL)
    349             ptr_qual_type = Ctx.getObjCObjectPointerType(expr_qual_type);
    350         else
    351             ptr_qual_type = Ctx.getPointerType(expr_qual_type);
    352 
    353         result_decl = VarDecl::Create(Ctx,
    354                                       DC,
    355                                       SourceLocation(),
    356                                       SourceLocation(),
    357                                       result_ptr_id,
    358                                       ptr_qual_type,
    359                                       NULL,
    360                                       SC_Static);
    361 
    362         if (!result_decl)
    363             return false;
    364 
    365         ExprResult address_of_expr = m_sema->CreateBuiltinUnaryOp(SourceLocation(), UO_AddrOf, last_expr);
    366 
    367         m_sema->AddInitializerToDecl(result_decl, address_of_expr.take(), true, false);
    368     }
    369     else
    370     {
    371         IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
    372 
    373         result_decl = VarDecl::Create(Ctx,
    374                                       DC,
    375                                       SourceLocation(),
    376                                       SourceLocation(),
    377                                       &result_id,
    378                                       expr_qual_type,
    379                                       NULL,
    380                                       SC_Static);
    381 
    382         if (!result_decl)
    383             return false;
    384 
    385         m_sema->AddInitializerToDecl(result_decl, last_expr, true, false);
    386     }
    387 
    388     DC->addDecl(result_decl);
    389 
    390     ///////////////////////////////
    391     // call AddInitializerToDecl
    392     //
    393 
    394     //m_sema->AddInitializerToDecl(result_decl, last_expr);
    395 
    396     /////////////////////////////////
    397     // call ConvertDeclToDeclGroup
    398     //
    399 
    400     Sema::DeclGroupPtrTy result_decl_group_ptr;
    401 
    402     result_decl_group_ptr = m_sema->ConvertDeclToDeclGroup(result_decl);
    403 
    404     ////////////////////////
    405     // call ActOnDeclStmt
    406     //
    407 
    408     StmtResult result_initialization_stmt_result(m_sema->ActOnDeclStmt(result_decl_group_ptr,
    409                                                                        SourceLocation(),
    410                                                                        SourceLocation()));
    411 
    412     ////////////////////////////////////////////////
    413     // replace the old statement with the new one
    414     //
    415 
    416     *last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
    417 
    418     return true;
    419 }
    420 
    421 void
    422 ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
    423 {
    424     if (m_passthrough)
    425         m_passthrough->HandleTranslationUnit(Ctx);
    426 }
    427 
    428 void
    429 ASTResultSynthesizer::RecordPersistentTypes(DeclContext *FunDeclCtx)
    430 {
    431     typedef DeclContext::specific_decl_iterator<TypeDecl> TypeDeclIterator;
    432 
    433     for (TypeDeclIterator i = TypeDeclIterator(FunDeclCtx->decls_begin()),
    434          e = TypeDeclIterator(FunDeclCtx->decls_end());
    435          i != e;
    436          ++i)
    437     {
    438         MaybeRecordPersistentType(*i);
    439     }
    440 }
    441 
    442 void
    443 ASTResultSynthesizer::MaybeRecordPersistentType(TypeDecl *D)
    444 {
    445     if (!D->getIdentifier())
    446         return;
    447 
    448     StringRef name = D->getName();
    449 
    450     if (name.size() == 0 || name[0] != '$')
    451         return;
    452 
    453     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    454 
    455     ConstString name_cs(name.str().c_str());
    456 
    457     if (log)
    458         log->Printf ("Recording persistent type %s\n", name_cs.GetCString());
    459 
    460     Decl *D_scratch = m_target.GetClangASTImporter()->DeportDecl(m_target.GetScratchClangASTContext()->getASTContext(),
    461                                                                  m_ast_context,
    462                                                                  D);
    463 
    464     if (TypeDecl *TypeDecl_scratch = dyn_cast<TypeDecl>(D_scratch))
    465         m_target.GetPersistentVariables().RegisterPersistentType(name_cs, TypeDecl_scratch);
    466 }
    467 
    468 void
    469 ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
    470 {
    471     if (m_passthrough)
    472         m_passthrough->HandleTagDeclDefinition(D);
    473 }
    474 
    475 void
    476 ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
    477 {
    478     if (m_passthrough)
    479         m_passthrough->CompleteTentativeDefinition(D);
    480 }
    481 
    482 void
    483 ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
    484 {
    485     if (m_passthrough)
    486         m_passthrough->HandleVTable(RD, DefinitionRequired);
    487 }
    488 
    489 void
    490 ASTResultSynthesizer::PrintStats()
    491 {
    492     if (m_passthrough)
    493         m_passthrough->PrintStats();
    494 }
    495 
    496 void
    497 ASTResultSynthesizer::InitializeSema(Sema &S)
    498 {
    499     m_sema = &S;
    500 
    501     if (m_passthrough_sema)
    502         m_passthrough_sema->InitializeSema(S);
    503 }
    504 
    505 void
    506 ASTResultSynthesizer::ForgetSema()
    507 {
    508     m_sema = NULL;
    509 
    510     if (m_passthrough_sema)
    511         m_passthrough_sema->ForgetSema();
    512 }
    513