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 
ASTResultSynthesizer(ASTConsumer * passthrough,Target & target)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 
~ASTResultSynthesizer()47 ASTResultSynthesizer::~ASTResultSynthesizer()
48 {
49 }
50 
51 void
Initialize(ASTContext & Context)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
TransformTopLevelDecl(Decl * D)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
HandleTopLevelDecl(DeclGroupRef D)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
SynthesizeFunctionResult(FunctionDecl * FunDecl)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
SynthesizeObjCMethodResult(ObjCMethodDecl * MethodDecl)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
SynthesizeBodyResult(CompoundStmt * Body,DeclContext * DC)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
HandleTranslationUnit(ASTContext & Ctx)422 ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
423 {
424     if (m_passthrough)
425         m_passthrough->HandleTranslationUnit(Ctx);
426 }
427 
428 void
RecordPersistentTypes(DeclContext * FunDeclCtx)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
MaybeRecordPersistentType(TypeDecl * D)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
HandleTagDeclDefinition(TagDecl * D)469 ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
470 {
471     if (m_passthrough)
472         m_passthrough->HandleTagDeclDefinition(D);
473 }
474 
475 void
CompleteTentativeDefinition(VarDecl * D)476 ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
477 {
478     if (m_passthrough)
479         m_passthrough->CompleteTentativeDefinition(D);
480 }
481 
482 void
HandleVTable(CXXRecordDecl * RD,bool DefinitionRequired)483 ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired)
484 {
485     if (m_passthrough)
486         m_passthrough->HandleVTable(RD, DefinitionRequired);
487 }
488 
489 void
PrintStats()490 ASTResultSynthesizer::PrintStats()
491 {
492     if (m_passthrough)
493         m_passthrough->PrintStats();
494 }
495 
496 void
InitializeSema(Sema & S)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
ForgetSema()506 ASTResultSynthesizer::ForgetSema()
507 {
508     m_sema = NULL;
509 
510     if (m_passthrough_sema)
511         m_passthrough_sema->ForgetSema();
512 }
513