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