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