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