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 } 513