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 
31 using namespace llvm;
32 using namespace clang;
33 using namespace lldb_private;
34 
35 ASTResultSynthesizer::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 
49 ASTResultSynthesizer::~ASTResultSynthesizer()
50 {
51 }
52 
53 void
54 ASTResultSynthesizer::Initialize(ASTContext &Context)
55 {
56     m_ast_context = &Context;
57 
58     if (m_passthrough)
59         m_passthrough->Initialize(Context);
60 }
61 
62 void
63 ASTResultSynthesizer::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 
112 bool
113 ASTResultSynthesizer::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 
131 bool
132 ASTResultSynthesizer::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 
177 bool
178 ASTResultSynthesizer::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 
225 bool
226 ASTResultSynthesizer::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 
423 void
424 ASTResultSynthesizer::HandleTranslationUnit(ASTContext &Ctx)
425 {
426     if (m_passthrough)
427         m_passthrough->HandleTranslationUnit(Ctx);
428 }
429 
430 void
431 ASTResultSynthesizer::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 
444 void
445 ASTResultSynthesizer::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 
470 void
471 ASTResultSynthesizer::HandleTagDeclDefinition(TagDecl *D)
472 {
473     if (m_passthrough)
474         m_passthrough->HandleTagDeclDefinition(D);
475 }
476 
477 void
478 ASTResultSynthesizer::CompleteTentativeDefinition(VarDecl *D)
479 {
480     if (m_passthrough)
481         m_passthrough->CompleteTentativeDefinition(D);
482 }
483 
484 void
485 ASTResultSynthesizer::HandleVTable(CXXRecordDecl *RD)
486 {
487     if (m_passthrough)
488         m_passthrough->HandleVTable(RD);
489 }
490 
491 void
492 ASTResultSynthesizer::PrintStats()
493 {
494     if (m_passthrough)
495         m_passthrough->PrintStats();
496 }
497 
498 void
499 ASTResultSynthesizer::InitializeSema(Sema &S)
500 {
501     m_sema = &S;
502 
503     if (m_passthrough_sema)
504         m_passthrough_sema->InitializeSema(S);
505 }
506 
507 void
508 ASTResultSynthesizer::ForgetSema()
509 {
510     m_sema = NULL;
511 
512     if (m_passthrough_sema)
513         m_passthrough_sema->ForgetSema();
514 }
515