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