]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/llvm/tools/lldb/source/Expression/ASTResultSynthesizer.cpp
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / llvm / tools / lldb / source / Expression / ASTResultSynthesizer.cpp
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 }