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