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