1/* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "slang_rs_object_ref_count.h" 18 19#include <list> 20 21#include "clang/AST/DeclGroup.h" 22#include "clang/AST/Expr.h" 23#include "clang/AST/NestedNameSpecifier.h" 24#include "clang/AST/OperationKinds.h" 25#include "clang/AST/Stmt.h" 26#include "clang/AST/StmtVisitor.h" 27 28#include "slang_assert.h" 29#include "slang_rs.h" 30#include "slang_rs_ast_replace.h" 31#include "slang_rs_export_type.h" 32 33namespace slang { 34 35clang::FunctionDecl *RSObjectRefCount:: 36 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType - 37 RSExportPrimitiveType::FirstRSObjectType + 1]; 38clang::FunctionDecl *RSObjectRefCount:: 39 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType - 40 RSExportPrimitiveType::FirstRSObjectType + 1]; 41 42void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) { 43 for (unsigned i = 0; 44 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*)); 45 i++) { 46 RSSetObjectFD[i] = NULL; 47 RSClearObjectFD[i] = NULL; 48 } 49 50 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 51 52 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(), 53 E = TUDecl->decls_end(); I != E; I++) { 54 if ((I->getKind() >= clang::Decl::firstFunction) && 55 (I->getKind() <= clang::Decl::lastFunction)) { 56 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I); 57 58 // points to RSSetObjectFD or RSClearObjectFD 59 clang::FunctionDecl **RSObjectFD; 60 61 if (FD->getName() == "rsSetObject") { 62 slangAssert((FD->getNumParams() == 2) && 63 "Invalid rsSetObject function prototype (# params)"); 64 RSObjectFD = RSSetObjectFD; 65 } else if (FD->getName() == "rsClearObject") { 66 slangAssert((FD->getNumParams() == 1) && 67 "Invalid rsClearObject function prototype (# params)"); 68 RSObjectFD = RSClearObjectFD; 69 } else { 70 continue; 71 } 72 73 const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 74 clang::QualType PVT = PVD->getOriginalType(); 75 // The first parameter must be a pointer like rs_allocation* 76 slangAssert(PVT->isPointerType() && 77 "Invalid rs{Set,Clear}Object function prototype (pointer param)"); 78 79 // The rs object type passed to the FD 80 clang::QualType RST = PVT->getPointeeType(); 81 RSExportPrimitiveType::DataType DT = 82 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr()); 83 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT) 84 && "must be RS object type"); 85 86 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD; 87 } 88 } 89} 90 91namespace { 92 93// This function constructs a new CompoundStmt from the input StmtList. 94static clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C, 95 std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) { 96 unsigned NewStmtCount = StmtList.size(); 97 unsigned CompoundStmtCount = 0; 98 99 clang::Stmt **CompoundStmtList; 100 CompoundStmtList = new clang::Stmt*[NewStmtCount]; 101 102 std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 103 std::list<clang::Stmt*>::const_iterator E = StmtList.end(); 104 for ( ; I != E; I++) { 105 CompoundStmtList[CompoundStmtCount++] = *I; 106 } 107 slangAssert(CompoundStmtCount == NewStmtCount); 108 109 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 110 C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc); 111 112 delete [] CompoundStmtList; 113 114 return CS; 115} 116 117static void AppendAfterStmt(clang::ASTContext &C, 118 clang::CompoundStmt *CS, 119 clang::Stmt *S, 120 std::list<clang::Stmt*> &StmtList) { 121 slangAssert(CS); 122 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 123 clang::CompoundStmt::body_iterator bE = CS->body_end(); 124 clang::Stmt **UpdatedStmtList = 125 new clang::Stmt*[CS->size() + StmtList.size()]; 126 127 unsigned UpdatedStmtCount = 0; 128 unsigned Once = 0; 129 for ( ; bI != bE; bI++) { 130 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) { 131 // If we come across a return here, we don't have anything we can 132 // reasonably replace. We should have already inserted our destructor 133 // code in the proper spot, so we just clean up and return. 134 delete [] UpdatedStmtList; 135 136 return; 137 } 138 139 UpdatedStmtList[UpdatedStmtCount++] = *bI; 140 141 if ((*bI == S) && !Once) { 142 Once++; 143 std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 144 std::list<clang::Stmt*>::const_iterator E = StmtList.end(); 145 for ( ; I != E; I++) { 146 UpdatedStmtList[UpdatedStmtCount++] = *I; 147 } 148 } 149 } 150 slangAssert(Once <= 1); 151 152 // When S is NULL, we are appending to the end of the CompoundStmt. 153 if (!S) { 154 slangAssert(Once == 0); 155 std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 156 std::list<clang::Stmt*>::const_iterator E = StmtList.end(); 157 for ( ; I != E; I++) { 158 UpdatedStmtList[UpdatedStmtCount++] = *I; 159 } 160 } 161 162 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 163 164 delete [] UpdatedStmtList; 165 166 return; 167} 168 169// This class visits a compound statement and inserts DtorStmt 170// in proper locations. This includes inserting it before any 171// return statement in any sub-block, at the end of the logical enclosing 172// scope (compound statement), and/or before any break/continue statement that 173// would resume outside the declared scope. We will not handle the case for 174// goto statements that leave a local scope. 175// 176// To accomplish these goals, it collects a list of sub-Stmt's that 177// correspond to scope exit points. It then uses an RSASTReplace visitor to 178// transform the AST, inserting appropriate destructors before each of those 179// sub-Stmt's (and also before the exit of the outermost containing Stmt for 180// the scope). 181class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> { 182 private: 183 clang::ASTContext &mCtx; 184 185 // The loop depth of the currently visited node. 186 int mLoopDepth; 187 188 // The switch statement depth of the currently visited node. 189 // Note that this is tracked separately from the loop depth because 190 // SwitchStmt-contained ContinueStmt's should have destructors for the 191 // corresponding loop scope. 192 int mSwitchDepth; 193 194 // The outermost statement block that we are currently visiting. 195 // This should always be a CompoundStmt. 196 clang::Stmt *mOuterStmt; 197 198 // The destructor to execute for this scope/variable. 199 clang::Stmt* mDtorStmt; 200 201 // The stack of statements which should be replaced by a compound statement 202 // containing the new destructor call followed by the original Stmt. 203 std::stack<clang::Stmt*> mReplaceStmtStack; 204 205 // The source location for the variable declaration that we are trying to 206 // insert destructors for. Note that InsertDestructors() will not generate 207 // destructor calls for source locations that occur lexically before this 208 // location. 209 clang::SourceLocation mVarLoc; 210 211 public: 212 DestructorVisitor(clang::ASTContext &C, 213 clang::Stmt* OuterStmt, 214 clang::Stmt* DtorStmt, 215 clang::SourceLocation VarLoc); 216 217 // This code walks the collected list of Stmts to replace and actually does 218 // the replacement. It also finishes up by appending the destructor to the 219 // current outermost CompoundStmt. 220 void InsertDestructors() { 221 clang::Stmt *S = NULL; 222 clang::SourceManager &SM = mCtx.getSourceManager(); 223 std::list<clang::Stmt *> StmtList; 224 StmtList.push_back(mDtorStmt); 225 226 while (!mReplaceStmtStack.empty()) { 227 S = mReplaceStmtStack.top(); 228 mReplaceStmtStack.pop(); 229 230 // Skip all source locations that occur before the variable's 231 // declaration, since it won't have been initialized yet. 232 if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) { 233 continue; 234 } 235 236 StmtList.push_back(S); 237 clang::CompoundStmt *CS = 238 BuildCompoundStmt(mCtx, StmtList, S->getLocEnd()); 239 StmtList.pop_back(); 240 241 RSASTReplace R(mCtx); 242 R.ReplaceStmt(mOuterStmt, S, CS); 243 } 244 clang::CompoundStmt *CS = 245 llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt); 246 slangAssert(CS); 247 AppendAfterStmt(mCtx, CS, NULL, StmtList); 248 } 249 250 void VisitStmt(clang::Stmt *S); 251 void VisitCompoundStmt(clang::CompoundStmt *CS); 252 253 void VisitBreakStmt(clang::BreakStmt *BS); 254 void VisitCaseStmt(clang::CaseStmt *CS); 255 void VisitContinueStmt(clang::ContinueStmt *CS); 256 void VisitDefaultStmt(clang::DefaultStmt *DS); 257 void VisitDoStmt(clang::DoStmt *DS); 258 void VisitForStmt(clang::ForStmt *FS); 259 void VisitIfStmt(clang::IfStmt *IS); 260 void VisitReturnStmt(clang::ReturnStmt *RS); 261 void VisitSwitchCase(clang::SwitchCase *SC); 262 void VisitSwitchStmt(clang::SwitchStmt *SS); 263 void VisitWhileStmt(clang::WhileStmt *WS); 264}; 265 266DestructorVisitor::DestructorVisitor(clang::ASTContext &C, 267 clang::Stmt *OuterStmt, 268 clang::Stmt *DtorStmt, 269 clang::SourceLocation VarLoc) 270 : mCtx(C), 271 mLoopDepth(0), 272 mSwitchDepth(0), 273 mOuterStmt(OuterStmt), 274 mDtorStmt(DtorStmt), 275 mVarLoc(VarLoc) { 276 return; 277} 278 279void DestructorVisitor::VisitStmt(clang::Stmt *S) { 280 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 281 I != E; 282 I++) { 283 if (clang::Stmt *Child = *I) { 284 Visit(Child); 285 } 286 } 287 return; 288} 289 290void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) { 291 VisitStmt(CS); 292 return; 293} 294 295void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) { 296 VisitStmt(BS); 297 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) { 298 mReplaceStmtStack.push(BS); 299 } 300 return; 301} 302 303void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) { 304 VisitStmt(CS); 305 return; 306} 307 308void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) { 309 VisitStmt(CS); 310 if (mLoopDepth == 0) { 311 // Switch statements can have nested continues. 312 mReplaceStmtStack.push(CS); 313 } 314 return; 315} 316 317void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) { 318 VisitStmt(DS); 319 return; 320} 321 322void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) { 323 mLoopDepth++; 324 VisitStmt(DS); 325 mLoopDepth--; 326 return; 327} 328 329void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) { 330 mLoopDepth++; 331 VisitStmt(FS); 332 mLoopDepth--; 333 return; 334} 335 336void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) { 337 VisitStmt(IS); 338 return; 339} 340 341void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) { 342 mReplaceStmtStack.push(RS); 343 return; 344} 345 346void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) { 347 slangAssert(false && "Both case and default have specialized handlers"); 348 VisitStmt(SC); 349 return; 350} 351 352void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) { 353 mSwitchDepth++; 354 VisitStmt(SS); 355 mSwitchDepth--; 356 return; 357} 358 359void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) { 360 mLoopDepth++; 361 VisitStmt(WS); 362 mLoopDepth--; 363 return; 364} 365 366clang::Expr *ClearSingleRSObject(clang::ASTContext &C, 367 clang::Expr *RefRSVar, 368 clang::SourceLocation Loc) { 369 slangAssert(RefRSVar); 370 const clang::Type *T = RefRSVar->getType().getTypePtr(); 371 slangAssert(!T->isArrayType() && 372 "Should not be destroying arrays with this function"); 373 374 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T); 375 slangAssert((ClearObjectFD != NULL) && 376 "rsClearObject doesn't cover all RS object types"); 377 378 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 379 clang::QualType ClearObjectFDArgType = 380 ClearObjectFD->getParamDecl(0)->getOriginalType(); 381 382 // Example destructor for "rs_font localFont;" 383 // 384 // (CallExpr 'void' 385 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 386 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 387 // (UnaryOperator 'rs_font *' prefix '&' 388 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont'))) 389 390 // Get address of targeted RS object 391 clang::Expr *AddrRefRSVar = 392 new(C) clang::UnaryOperator(RefRSVar, 393 clang::UO_AddrOf, 394 ClearObjectFDArgType, 395 clang::VK_RValue, 396 clang::OK_Ordinary, 397 Loc); 398 399 clang::Expr *RefRSClearObjectFD = 400 clang::DeclRefExpr::Create(C, 401 clang::NestedNameSpecifierLoc(), 402 clang::SourceLocation(), 403 ClearObjectFD, 404 false, 405 ClearObjectFD->getLocation(), 406 ClearObjectFDType, 407 clang::VK_RValue, 408 NULL); 409 410 clang::Expr *RSClearObjectFP = 411 clang::ImplicitCastExpr::Create(C, 412 C.getPointerType(ClearObjectFDType), 413 clang::CK_FunctionToPointerDecay, 414 RefRSClearObjectFD, 415 NULL, 416 clang::VK_RValue); 417 418 llvm::SmallVector<clang::Expr*, 1> ArgList; 419 ArgList.push_back(AddrRefRSVar); 420 421 clang::CallExpr *RSClearObjectCall = 422 new(C) clang::CallExpr(C, 423 RSClearObjectFP, 424 ArgList, 425 ClearObjectFD->getCallResultType(), 426 clang::VK_RValue, 427 Loc); 428 429 return RSClearObjectCall; 430} 431 432static int ArrayDim(const clang::Type *T) { 433 if (!T || !T->isArrayType()) { 434 return 0; 435 } 436 437 const clang::ConstantArrayType *CAT = 438 static_cast<const clang::ConstantArrayType *>(T); 439 return static_cast<int>(CAT->getSize().getSExtValue()); 440} 441 442static clang::Stmt *ClearStructRSObject( 443 clang::ASTContext &C, 444 clang::DeclContext *DC, 445 clang::Expr *RefRSStruct, 446 clang::SourceLocation StartLoc, 447 clang::SourceLocation Loc); 448 449static clang::Stmt *ClearArrayRSObject( 450 clang::ASTContext &C, 451 clang::DeclContext *DC, 452 clang::Expr *RefRSArr, 453 clang::SourceLocation StartLoc, 454 clang::SourceLocation Loc) { 455 const clang::Type *BaseType = RefRSArr->getType().getTypePtr(); 456 slangAssert(BaseType->isArrayType()); 457 458 int NumArrayElements = ArrayDim(BaseType); 459 // Actually extract out the base RS object type for use later 460 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 461 462 clang::Stmt *StmtArray[2] = {NULL}; 463 int StmtCtr = 0; 464 465 if (NumArrayElements <= 0) { 466 return NULL; 467 } 468 469 // Example destructor loop for "rs_font fontArr[10];" 470 // 471 // (CompoundStmt 472 // (DeclStmt "int rsIntIter") 473 // (ForStmt 474 // (BinaryOperator 'int' '=' 475 // (DeclRefExpr 'int' Var='rsIntIter') 476 // (IntegerLiteral 'int' 0)) 477 // (BinaryOperator 'int' '<' 478 // (DeclRefExpr 'int' Var='rsIntIter') 479 // (IntegerLiteral 'int' 10) 480 // NULL << CondVar >> 481 // (UnaryOperator 'int' postfix '++' 482 // (DeclRefExpr 'int' Var='rsIntIter')) 483 // (CallExpr 'void' 484 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 485 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 486 // (UnaryOperator 'rs_font *' prefix '&' 487 // (ArraySubscriptExpr 'rs_font':'rs_font' 488 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay> 489 // (DeclRefExpr 'rs_font [10]' Var='fontArr')) 490 // (DeclRefExpr 'int' Var='rsIntIter'))))))) 491 492 // Create helper variable for iterating through elements 493 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 494 clang::VarDecl *IIVD = 495 clang::VarDecl::Create(C, 496 DC, 497 StartLoc, 498 Loc, 499 &II, 500 C.IntTy, 501 C.getTrivialTypeSourceInfo(C.IntTy), 502 clang::SC_None); 503 clang::Decl *IID = (clang::Decl *)IIVD; 504 505 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 506 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 507 508 // Form the actual destructor loop 509 // for (Init; Cond; Inc) 510 // RSClearObjectCall; 511 512 // Init -> "rsIntIter = 0" 513 clang::DeclRefExpr *RefrsIntIter = 514 clang::DeclRefExpr::Create(C, 515 clang::NestedNameSpecifierLoc(), 516 clang::SourceLocation(), 517 IIVD, 518 false, 519 Loc, 520 C.IntTy, 521 clang::VK_RValue, 522 NULL); 523 524 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 525 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 526 527 clang::BinaryOperator *Init = 528 new(C) clang::BinaryOperator(RefrsIntIter, 529 Int0, 530 clang::BO_Assign, 531 C.IntTy, 532 clang::VK_RValue, 533 clang::OK_Ordinary, 534 Loc, 535 false); 536 537 // Cond -> "rsIntIter < NumArrayElements" 538 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 539 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 540 541 clang::BinaryOperator *Cond = 542 new(C) clang::BinaryOperator(RefrsIntIter, 543 NumArrayElementsExpr, 544 clang::BO_LT, 545 C.IntTy, 546 clang::VK_RValue, 547 clang::OK_Ordinary, 548 Loc, 549 false); 550 551 // Inc -> "rsIntIter++" 552 clang::UnaryOperator *Inc = 553 new(C) clang::UnaryOperator(RefrsIntIter, 554 clang::UO_PostInc, 555 C.IntTy, 556 clang::VK_RValue, 557 clang::OK_Ordinary, 558 Loc); 559 560 // Body -> "rsClearObject(&VD[rsIntIter]);" 561 // Destructor loop operates on individual array elements 562 563 clang::Expr *RefRSArrPtr = 564 clang::ImplicitCastExpr::Create(C, 565 C.getPointerType(BaseType->getCanonicalTypeInternal()), 566 clang::CK_ArrayToPointerDecay, 567 RefRSArr, 568 NULL, 569 clang::VK_RValue); 570 571 clang::Expr *RefRSArrPtrSubscript = 572 new(C) clang::ArraySubscriptExpr(RefRSArrPtr, 573 RefrsIntIter, 574 BaseType->getCanonicalTypeInternal(), 575 clang::VK_RValue, 576 clang::OK_Ordinary, 577 Loc); 578 579 RSExportPrimitiveType::DataType DT = 580 RSExportPrimitiveType::GetRSSpecificType(BaseType); 581 582 clang::Stmt *RSClearObjectCall = NULL; 583 if (BaseType->isArrayType()) { 584 RSClearObjectCall = 585 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc); 586 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 587 RSClearObjectCall = 588 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc); 589 } else { 590 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc); 591 } 592 593 clang::ForStmt *DestructorLoop = 594 new(C) clang::ForStmt(C, 595 Init, 596 Cond, 597 NULL, // no condVar 598 Inc, 599 RSClearObjectCall, 600 Loc, 601 Loc, 602 Loc); 603 604 StmtArray[StmtCtr++] = DestructorLoop; 605 slangAssert(StmtCtr == 2); 606 607 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 608 C, llvm::makeArrayRef(StmtArray, StmtCtr), Loc, Loc); 609 610 return CS; 611} 612 613static unsigned CountRSObjectTypes(clang::ASTContext &C, 614 const clang::Type *T, 615 clang::SourceLocation Loc) { 616 slangAssert(T); 617 unsigned RSObjectCount = 0; 618 619 if (T->isArrayType()) { 620 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc); 621 } 622 623 RSExportPrimitiveType::DataType DT = 624 RSExportPrimitiveType::GetRSSpecificType(T); 625 if (DT != RSExportPrimitiveType::DataTypeUnknown) { 626 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0); 627 } 628 629 if (T->isUnionType()) { 630 clang::RecordDecl *RD = T->getAsUnionType()->getDecl(); 631 RD = RD->getDefinition(); 632 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 633 FE = RD->field_end(); 634 FI != FE; 635 FI++) { 636 const clang::FieldDecl *FD = *FI; 637 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 638 if (CountRSObjectTypes(C, FT, Loc)) { 639 slangAssert(false && "can't have unions with RS object types!"); 640 return 0; 641 } 642 } 643 } 644 645 if (!T->isStructureType()) { 646 return 0; 647 } 648 649 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 650 RD = RD->getDefinition(); 651 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 652 FE = RD->field_end(); 653 FI != FE; 654 FI++) { 655 const clang::FieldDecl *FD = *FI; 656 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 657 if (CountRSObjectTypes(C, FT, Loc)) { 658 // Sub-structs should only count once (as should arrays, etc.) 659 RSObjectCount++; 660 } 661 } 662 663 return RSObjectCount; 664} 665 666static clang::Stmt *ClearStructRSObject( 667 clang::ASTContext &C, 668 clang::DeclContext *DC, 669 clang::Expr *RefRSStruct, 670 clang::SourceLocation StartLoc, 671 clang::SourceLocation Loc) { 672 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr(); 673 674 slangAssert(!BaseType->isArrayType()); 675 676 // Structs should show up as unknown primitive types 677 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) == 678 RSExportPrimitiveType::DataTypeUnknown); 679 680 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc); 681 slangAssert(FieldsToDestroy != 0); 682 683 unsigned StmtCount = 0; 684 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy]; 685 for (unsigned i = 0; i < FieldsToDestroy; i++) { 686 StmtArray[i] = NULL; 687 } 688 689 // Populate StmtArray by creating a destructor for each RS object field 690 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl(); 691 RD = RD->getDefinition(); 692 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 693 FE = RD->field_end(); 694 FI != FE; 695 FI++) { 696 // We just look through all field declarations to see if we find a 697 // declaration for an RS object type (or an array of one). 698 bool IsArrayType = false; 699 clang::FieldDecl *FD = *FI; 700 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 701 const clang::Type *OrigType = FT; 702 while (FT && FT->isArrayType()) { 703 FT = FT->getArrayElementTypeNoTypeQual(); 704 IsArrayType = true; 705 } 706 707 if (RSExportPrimitiveType::IsRSObjectType(FT)) { 708 clang::DeclAccessPair FoundDecl = 709 clang::DeclAccessPair::make(FD, clang::AS_none); 710 clang::MemberExpr *RSObjectMember = 711 clang::MemberExpr::Create(C, 712 RefRSStruct, 713 false, 714 clang::NestedNameSpecifierLoc(), 715 clang::SourceLocation(), 716 FD, 717 FoundDecl, 718 clang::DeclarationNameInfo(), 719 NULL, 720 OrigType->getCanonicalTypeInternal(), 721 clang::VK_RValue, 722 clang::OK_Ordinary); 723 724 slangAssert(StmtCount < FieldsToDestroy); 725 726 if (IsArrayType) { 727 StmtArray[StmtCount++] = ClearArrayRSObject(C, 728 DC, 729 RSObjectMember, 730 StartLoc, 731 Loc); 732 } else { 733 StmtArray[StmtCount++] = ClearSingleRSObject(C, 734 RSObjectMember, 735 Loc); 736 } 737 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) { 738 // In this case, we have a nested struct. We may not end up filling all 739 // of the spaces in StmtArray (sub-structs should handle themselves 740 // with separate compound statements). 741 clang::DeclAccessPair FoundDecl = 742 clang::DeclAccessPair::make(FD, clang::AS_none); 743 clang::MemberExpr *RSObjectMember = 744 clang::MemberExpr::Create(C, 745 RefRSStruct, 746 false, 747 clang::NestedNameSpecifierLoc(), 748 clang::SourceLocation(), 749 FD, 750 FoundDecl, 751 clang::DeclarationNameInfo(), 752 NULL, 753 OrigType->getCanonicalTypeInternal(), 754 clang::VK_RValue, 755 clang::OK_Ordinary); 756 757 if (IsArrayType) { 758 StmtArray[StmtCount++] = ClearArrayRSObject(C, 759 DC, 760 RSObjectMember, 761 StartLoc, 762 Loc); 763 } else { 764 StmtArray[StmtCount++] = ClearStructRSObject(C, 765 DC, 766 RSObjectMember, 767 StartLoc, 768 Loc); 769 } 770 } 771 } 772 773 slangAssert(StmtCount > 0); 774 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 775 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc); 776 777 delete [] StmtArray; 778 779 return CS; 780} 781 782static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C, 783 clang::Expr *DstExpr, 784 clang::Expr *SrcExpr, 785 clang::SourceLocation StartLoc, 786 clang::SourceLocation Loc) { 787 const clang::Type *T = DstExpr->getType().getTypePtr(); 788 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T); 789 slangAssert((SetObjectFD != NULL) && 790 "rsSetObject doesn't cover all RS object types"); 791 792 clang::QualType SetObjectFDType = SetObjectFD->getType(); 793 clang::QualType SetObjectFDArgType[2]; 794 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 795 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 796 797 clang::Expr *RefRSSetObjectFD = 798 clang::DeclRefExpr::Create(C, 799 clang::NestedNameSpecifierLoc(), 800 clang::SourceLocation(), 801 SetObjectFD, 802 false, 803 Loc, 804 SetObjectFDType, 805 clang::VK_RValue, 806 NULL); 807 808 clang::Expr *RSSetObjectFP = 809 clang::ImplicitCastExpr::Create(C, 810 C.getPointerType(SetObjectFDType), 811 clang::CK_FunctionToPointerDecay, 812 RefRSSetObjectFD, 813 NULL, 814 clang::VK_RValue); 815 816 llvm::SmallVector<clang::Expr*, 2> ArgList; 817 ArgList.push_back(new(C) clang::UnaryOperator(DstExpr, 818 clang::UO_AddrOf, 819 SetObjectFDArgType[0], 820 clang::VK_RValue, 821 clang::OK_Ordinary, 822 Loc)); 823 ArgList.push_back(SrcExpr); 824 825 clang::CallExpr *RSSetObjectCall = 826 new(C) clang::CallExpr(C, 827 RSSetObjectFP, 828 ArgList, 829 SetObjectFD->getCallResultType(), 830 clang::VK_RValue, 831 Loc); 832 833 return RSSetObjectCall; 834} 835 836static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 837 clang::Expr *LHS, 838 clang::Expr *RHS, 839 clang::SourceLocation StartLoc, 840 clang::SourceLocation Loc); 841 842/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C, 843 clang::Expr *DstArr, 844 clang::Expr *SrcArr, 845 clang::SourceLocation StartLoc, 846 clang::SourceLocation Loc) { 847 clang::DeclContext *DC = NULL; 848 const clang::Type *BaseType = DstArr->getType().getTypePtr(); 849 slangAssert(BaseType->isArrayType()); 850 851 int NumArrayElements = ArrayDim(BaseType); 852 // Actually extract out the base RS object type for use later 853 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 854 855 clang::Stmt *StmtArray[2] = {NULL}; 856 int StmtCtr = 0; 857 858 if (NumArrayElements <= 0) { 859 return NULL; 860 } 861 862 // Create helper variable for iterating through elements 863 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 864 clang::VarDecl *IIVD = 865 clang::VarDecl::Create(C, 866 DC, 867 StartLoc, 868 Loc, 869 &II, 870 C.IntTy, 871 C.getTrivialTypeSourceInfo(C.IntTy), 872 clang::SC_None, 873 clang::SC_None); 874 clang::Decl *IID = (clang::Decl *)IIVD; 875 876 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 877 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 878 879 // Form the actual loop 880 // for (Init; Cond; Inc) 881 // RSSetObjectCall; 882 883 // Init -> "rsIntIter = 0" 884 clang::DeclRefExpr *RefrsIntIter = 885 clang::DeclRefExpr::Create(C, 886 clang::NestedNameSpecifierLoc(), 887 IIVD, 888 Loc, 889 C.IntTy, 890 clang::VK_RValue, 891 NULL); 892 893 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 894 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 895 896 clang::BinaryOperator *Init = 897 new(C) clang::BinaryOperator(RefrsIntIter, 898 Int0, 899 clang::BO_Assign, 900 C.IntTy, 901 clang::VK_RValue, 902 clang::OK_Ordinary, 903 Loc); 904 905 // Cond -> "rsIntIter < NumArrayElements" 906 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 907 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 908 909 clang::BinaryOperator *Cond = 910 new(C) clang::BinaryOperator(RefrsIntIter, 911 NumArrayElementsExpr, 912 clang::BO_LT, 913 C.IntTy, 914 clang::VK_RValue, 915 clang::OK_Ordinary, 916 Loc); 917 918 // Inc -> "rsIntIter++" 919 clang::UnaryOperator *Inc = 920 new(C) clang::UnaryOperator(RefrsIntIter, 921 clang::UO_PostInc, 922 C.IntTy, 923 clang::VK_RValue, 924 clang::OK_Ordinary, 925 Loc); 926 927 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);" 928 // Loop operates on individual array elements 929 930 clang::Expr *DstArrPtr = 931 clang::ImplicitCastExpr::Create(C, 932 C.getPointerType(BaseType->getCanonicalTypeInternal()), 933 clang::CK_ArrayToPointerDecay, 934 DstArr, 935 NULL, 936 clang::VK_RValue); 937 938 clang::Expr *DstArrPtrSubscript = 939 new(C) clang::ArraySubscriptExpr(DstArrPtr, 940 RefrsIntIter, 941 BaseType->getCanonicalTypeInternal(), 942 clang::VK_RValue, 943 clang::OK_Ordinary, 944 Loc); 945 946 clang::Expr *SrcArrPtr = 947 clang::ImplicitCastExpr::Create(C, 948 C.getPointerType(BaseType->getCanonicalTypeInternal()), 949 clang::CK_ArrayToPointerDecay, 950 SrcArr, 951 NULL, 952 clang::VK_RValue); 953 954 clang::Expr *SrcArrPtrSubscript = 955 new(C) clang::ArraySubscriptExpr(SrcArrPtr, 956 RefrsIntIter, 957 BaseType->getCanonicalTypeInternal(), 958 clang::VK_RValue, 959 clang::OK_Ordinary, 960 Loc); 961 962 RSExportPrimitiveType::DataType DT = 963 RSExportPrimitiveType::GetRSSpecificType(BaseType); 964 965 clang::Stmt *RSSetObjectCall = NULL; 966 if (BaseType->isArrayType()) { 967 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript, 968 SrcArrPtrSubscript, 969 StartLoc, Loc); 970 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 971 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript, 972 SrcArrPtrSubscript, 973 StartLoc, Loc); 974 } else { 975 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript, 976 SrcArrPtrSubscript, 977 StartLoc, Loc); 978 } 979 980 clang::ForStmt *DestructorLoop = 981 new(C) clang::ForStmt(C, 982 Init, 983 Cond, 984 NULL, // no condVar 985 Inc, 986 RSSetObjectCall, 987 Loc, 988 Loc, 989 Loc); 990 991 StmtArray[StmtCtr++] = DestructorLoop; 992 slangAssert(StmtCtr == 2); 993 994 clang::CompoundStmt *CS = 995 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 996 997 return CS; 998} */ 999 1000static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 1001 clang::Expr *LHS, 1002 clang::Expr *RHS, 1003 clang::SourceLocation StartLoc, 1004 clang::SourceLocation Loc) { 1005 clang::QualType QT = LHS->getType(); 1006 const clang::Type *T = QT.getTypePtr(); 1007 slangAssert(T->isStructureType()); 1008 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T)); 1009 1010 // Keep an extra slot for the original copy (memcpy) 1011 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1; 1012 1013 unsigned StmtCount = 0; 1014 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet]; 1015 for (unsigned i = 0; i < FieldsToSet; i++) { 1016 StmtArray[i] = NULL; 1017 } 1018 1019 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 1020 RD = RD->getDefinition(); 1021 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1022 FE = RD->field_end(); 1023 FI != FE; 1024 FI++) { 1025 bool IsArrayType = false; 1026 clang::FieldDecl *FD = *FI; 1027 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1028 const clang::Type *OrigType = FT; 1029 1030 if (!CountRSObjectTypes(C, FT, Loc)) { 1031 // Skip to next if we don't have any viable RS object types 1032 continue; 1033 } 1034 1035 clang::DeclAccessPair FoundDecl = 1036 clang::DeclAccessPair::make(FD, clang::AS_none); 1037 clang::MemberExpr *DstMember = 1038 clang::MemberExpr::Create(C, 1039 LHS, 1040 false, 1041 clang::NestedNameSpecifierLoc(), 1042 clang::SourceLocation(), 1043 FD, 1044 FoundDecl, 1045 clang::DeclarationNameInfo(), 1046 NULL, 1047 OrigType->getCanonicalTypeInternal(), 1048 clang::VK_RValue, 1049 clang::OK_Ordinary); 1050 1051 clang::MemberExpr *SrcMember = 1052 clang::MemberExpr::Create(C, 1053 RHS, 1054 false, 1055 clang::NestedNameSpecifierLoc(), 1056 clang::SourceLocation(), 1057 FD, 1058 FoundDecl, 1059 clang::DeclarationNameInfo(), 1060 NULL, 1061 OrigType->getCanonicalTypeInternal(), 1062 clang::VK_RValue, 1063 clang::OK_Ordinary); 1064 1065 if (FT->isArrayType()) { 1066 FT = FT->getArrayElementTypeNoTypeQual(); 1067 IsArrayType = true; 1068 } 1069 1070 RSExportPrimitiveType::DataType DT = 1071 RSExportPrimitiveType::GetRSSpecificType(FT); 1072 1073 if (IsArrayType) { 1074 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics(); 1075 DiagEngine.Report( 1076 clang::FullSourceLoc(Loc, C.getSourceManager()), 1077 DiagEngine.getCustomDiagID( 1078 clang::DiagnosticsEngine::Error, 1079 "Arrays of RS object types within structures cannot be copied")); 1080 // TODO(srhines): Support setting arrays of RS objects 1081 // StmtArray[StmtCount++] = 1082 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1083 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 1084 StmtArray[StmtCount++] = 1085 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1086 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) { 1087 StmtArray[StmtCount++] = 1088 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1089 } else { 1090 slangAssert(false); 1091 } 1092 } 1093 1094 slangAssert(StmtCount < FieldsToSet); 1095 1096 // We still need to actually do the overall struct copy. For simplicity, 1097 // we just do a straight-up assignment (which will still preserve all 1098 // the proper RS object reference counts). 1099 clang::BinaryOperator *CopyStruct = 1100 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, 1101 clang::VK_RValue, clang::OK_Ordinary, Loc, 1102 false); 1103 StmtArray[StmtCount++] = CopyStruct; 1104 1105 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 1106 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc); 1107 1108 delete [] StmtArray; 1109 1110 return CS; 1111} 1112 1113} // namespace 1114 1115void RSObjectRefCount::Scope::ReplaceRSObjectAssignment( 1116 clang::BinaryOperator *AS) { 1117 1118 clang::QualType QT = AS->getType(); 1119 1120 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1121 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 1122 1123 clang::SourceLocation Loc = AS->getExprLoc(); 1124 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc(); 1125 clang::Stmt *UpdatedStmt = NULL; 1126 1127 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) { 1128 // By definition, this is a struct assignment if we get here 1129 UpdatedStmt = 1130 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc); 1131 } else { 1132 UpdatedStmt = 1133 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc); 1134 } 1135 1136 RSASTReplace R(C); 1137 R.ReplaceStmt(mCS, AS, UpdatedStmt); 1138 return; 1139} 1140 1141void RSObjectRefCount::Scope::AppendRSObjectInit( 1142 clang::VarDecl *VD, 1143 clang::DeclStmt *DS, 1144 RSExportPrimitiveType::DataType DT, 1145 clang::Expr *InitExpr) { 1146 slangAssert(VD); 1147 1148 if (!InitExpr) { 1149 return; 1150 } 1151 1152 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1153 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 1154 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD( 1155 RSExportPrimitiveType::DataTypeRSFont)->getLocation(); 1156 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD( 1157 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart(); 1158 1159 if (DT == RSExportPrimitiveType::DataTypeIsStruct) { 1160 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1161 clang::DeclRefExpr *RefRSVar = 1162 clang::DeclRefExpr::Create(C, 1163 clang::NestedNameSpecifierLoc(), 1164 clang::SourceLocation(), 1165 VD, 1166 false, 1167 Loc, 1168 T->getCanonicalTypeInternal(), 1169 clang::VK_RValue, 1170 NULL); 1171 1172 clang::Stmt *RSSetObjectOps = 1173 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc); 1174 1175 std::list<clang::Stmt*> StmtList; 1176 StmtList.push_back(RSSetObjectOps); 1177 AppendAfterStmt(C, mCS, DS, StmtList); 1178 return; 1179 } 1180 1181 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT); 1182 slangAssert((SetObjectFD != NULL) && 1183 "rsSetObject doesn't cover all RS object types"); 1184 1185 clang::QualType SetObjectFDType = SetObjectFD->getType(); 1186 clang::QualType SetObjectFDArgType[2]; 1187 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 1188 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 1189 1190 clang::Expr *RefRSSetObjectFD = 1191 clang::DeclRefExpr::Create(C, 1192 clang::NestedNameSpecifierLoc(), 1193 clang::SourceLocation(), 1194 SetObjectFD, 1195 false, 1196 Loc, 1197 SetObjectFDType, 1198 clang::VK_RValue, 1199 NULL); 1200 1201 clang::Expr *RSSetObjectFP = 1202 clang::ImplicitCastExpr::Create(C, 1203 C.getPointerType(SetObjectFDType), 1204 clang::CK_FunctionToPointerDecay, 1205 RefRSSetObjectFD, 1206 NULL, 1207 clang::VK_RValue); 1208 1209 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1210 clang::DeclRefExpr *RefRSVar = 1211 clang::DeclRefExpr::Create(C, 1212 clang::NestedNameSpecifierLoc(), 1213 clang::SourceLocation(), 1214 VD, 1215 false, 1216 Loc, 1217 T->getCanonicalTypeInternal(), 1218 clang::VK_RValue, 1219 NULL); 1220 1221 llvm::SmallVector<clang::Expr*, 2> ArgList; 1222 ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar, 1223 clang::UO_AddrOf, 1224 SetObjectFDArgType[0], 1225 clang::VK_RValue, 1226 clang::OK_Ordinary, 1227 Loc)); 1228 ArgList.push_back(InitExpr); 1229 1230 clang::CallExpr *RSSetObjectCall = 1231 new(C) clang::CallExpr(C, 1232 RSSetObjectFP, 1233 ArgList, 1234 SetObjectFD->getCallResultType(), 1235 clang::VK_RValue, 1236 Loc); 1237 1238 std::list<clang::Stmt*> StmtList; 1239 StmtList.push_back(RSSetObjectCall); 1240 AppendAfterStmt(C, mCS, DS, StmtList); 1241 1242 return; 1243} 1244 1245void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 1246 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 1247 E = mRSO.end(); 1248 I != E; 1249 I++) { 1250 clang::VarDecl *VD = *I; 1251 clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext()); 1252 if (RSClearObjectCall) { 1253 DestructorVisitor DV((*mRSO.begin())->getASTContext(), 1254 mCS, 1255 RSClearObjectCall, 1256 VD->getSourceRange().getBegin()); 1257 DV.Visit(mCS); 1258 DV.InsertDestructors(); 1259 } 1260 } 1261 return; 1262} 1263 1264clang::Stmt *RSObjectRefCount::Scope::ClearRSObject( 1265 clang::VarDecl *VD, 1266 clang::DeclContext *DC) { 1267 slangAssert(VD); 1268 clang::ASTContext &C = VD->getASTContext(); 1269 clang::SourceLocation Loc = VD->getLocation(); 1270 clang::SourceLocation StartLoc = VD->getInnerLocStart(); 1271 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1272 1273 // Reference expr to target RS object variable 1274 clang::DeclRefExpr *RefRSVar = 1275 clang::DeclRefExpr::Create(C, 1276 clang::NestedNameSpecifierLoc(), 1277 clang::SourceLocation(), 1278 VD, 1279 false, 1280 Loc, 1281 T->getCanonicalTypeInternal(), 1282 clang::VK_RValue, 1283 NULL); 1284 1285 if (T->isArrayType()) { 1286 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc); 1287 } 1288 1289 RSExportPrimitiveType::DataType DT = 1290 RSExportPrimitiveType::GetRSSpecificType(T); 1291 1292 if (DT == RSExportPrimitiveType::DataTypeUnknown || 1293 DT == RSExportPrimitiveType::DataTypeIsStruct) { 1294 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc); 1295 } 1296 1297 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) && 1298 "Should be RS object"); 1299 1300 return ClearSingleRSObject(C, RefRSVar, Loc); 1301} 1302 1303bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD, 1304 RSExportPrimitiveType::DataType *DT, 1305 clang::Expr **InitExpr) { 1306 slangAssert(VD && DT && InitExpr); 1307 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1308 1309 // Loop through array types to get to base type 1310 while (T && T->isArrayType()) { 1311 T = T->getArrayElementTypeNoTypeQual(); 1312 } 1313 1314 bool DataTypeIsStructWithRSObject = false; 1315 *DT = RSExportPrimitiveType::GetRSSpecificType(T); 1316 1317 if (*DT == RSExportPrimitiveType::DataTypeUnknown) { 1318 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) { 1319 *DT = RSExportPrimitiveType::DataTypeIsStruct; 1320 DataTypeIsStructWithRSObject = true; 1321 } else { 1322 return false; 1323 } 1324 } 1325 1326 bool DataTypeIsRSObject = false; 1327 if (DataTypeIsStructWithRSObject) { 1328 DataTypeIsRSObject = true; 1329 } else { 1330 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT); 1331 } 1332 *InitExpr = VD->getInit(); 1333 1334 if (!DataTypeIsRSObject && *InitExpr) { 1335 // If we already have an initializer for a matrix type, we are done. 1336 return DataTypeIsRSObject; 1337 } 1338 1339 clang::Expr *ZeroInitializer = 1340 CreateZeroInitializerForRSSpecificType(*DT, 1341 VD->getASTContext(), 1342 VD->getLocation()); 1343 1344 if (ZeroInitializer) { 1345 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 1346 VD->setInit(ZeroInitializer); 1347 } 1348 1349 return DataTypeIsRSObject; 1350} 1351 1352clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 1353 RSExportPrimitiveType::DataType DT, 1354 clang::ASTContext &C, 1355 const clang::SourceLocation &Loc) { 1356 clang::Expr *Res = NULL; 1357 switch (DT) { 1358 case RSExportPrimitiveType::DataTypeIsStruct: 1359 case RSExportPrimitiveType::DataTypeRSElement: 1360 case RSExportPrimitiveType::DataTypeRSType: 1361 case RSExportPrimitiveType::DataTypeRSAllocation: 1362 case RSExportPrimitiveType::DataTypeRSSampler: 1363 case RSExportPrimitiveType::DataTypeRSScript: 1364 case RSExportPrimitiveType::DataTypeRSMesh: 1365 case RSExportPrimitiveType::DataTypeRSPath: 1366 case RSExportPrimitiveType::DataTypeRSProgramFragment: 1367 case RSExportPrimitiveType::DataTypeRSProgramVertex: 1368 case RSExportPrimitiveType::DataTypeRSProgramRaster: 1369 case RSExportPrimitiveType::DataTypeRSProgramStore: 1370 case RSExportPrimitiveType::DataTypeRSFont: { 1371 // (ImplicitCastExpr 'nullptr_t' 1372 // (IntegerLiteral 0))) 1373 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 1374 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 1375 clang::Expr *CastToNull = 1376 clang::ImplicitCastExpr::Create(C, 1377 C.NullPtrTy, 1378 clang::CK_IntegralToPointer, 1379 Int0, 1380 NULL, 1381 clang::VK_RValue); 1382 1383 llvm::SmallVector<clang::Expr*, 1>InitList; 1384 InitList.push_back(CastToNull); 1385 1386 Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc); 1387 break; 1388 } 1389 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 1390 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 1391 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 1392 // RS matrix is not completely an RS object. They hold data by themselves. 1393 // (InitListExpr rs_matrix2x2 1394 // (InitListExpr float[4] 1395 // (FloatingLiteral 0) 1396 // (FloatingLiteral 0) 1397 // (FloatingLiteral 0) 1398 // (FloatingLiteral 0))) 1399 clang::QualType FloatTy = C.FloatTy; 1400 // Constructor sets value to 0.0f by default 1401 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 1402 clang::FloatingLiteral *Float0Val = 1403 clang::FloatingLiteral::Create(C, 1404 Val, 1405 /* isExact = */true, 1406 FloatTy, 1407 Loc); 1408 1409 unsigned N = 0; 1410 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 1411 N = 2; 1412 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 1413 N = 3; 1414 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 1415 N = 4; 1416 unsigned N_2 = N * N; 1417 1418 // Assume we are going to be allocating 16 elements, since 4x4 is max. 1419 llvm::SmallVector<clang::Expr*, 16> InitVals; 1420 for (unsigned i = 0; i < N_2; i++) 1421 InitVals.push_back(Float0Val); 1422 clang::Expr *InitExpr = 1423 new(C) clang::InitListExpr(C, Loc, InitVals, Loc); 1424 InitExpr->setType(C.getConstantArrayType(FloatTy, 1425 llvm::APInt(32, N_2), 1426 clang::ArrayType::Normal, 1427 /* EltTypeQuals = */0)); 1428 llvm::SmallVector<clang::Expr*, 1> InitExprVec; 1429 InitExprVec.push_back(InitExpr); 1430 1431 Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc); 1432 break; 1433 } 1434 case RSExportPrimitiveType::DataTypeUnknown: 1435 case RSExportPrimitiveType::DataTypeFloat16: 1436 case RSExportPrimitiveType::DataTypeFloat32: 1437 case RSExportPrimitiveType::DataTypeFloat64: 1438 case RSExportPrimitiveType::DataTypeSigned8: 1439 case RSExportPrimitiveType::DataTypeSigned16: 1440 case RSExportPrimitiveType::DataTypeSigned32: 1441 case RSExportPrimitiveType::DataTypeSigned64: 1442 case RSExportPrimitiveType::DataTypeUnsigned8: 1443 case RSExportPrimitiveType::DataTypeUnsigned16: 1444 case RSExportPrimitiveType::DataTypeUnsigned32: 1445 case RSExportPrimitiveType::DataTypeUnsigned64: 1446 case RSExportPrimitiveType::DataTypeBoolean: 1447 case RSExportPrimitiveType::DataTypeUnsigned565: 1448 case RSExportPrimitiveType::DataTypeUnsigned5551: 1449 case RSExportPrimitiveType::DataTypeUnsigned4444: 1450 case RSExportPrimitiveType::DataTypeMax: { 1451 slangAssert(false && "Not RS object type!"); 1452 } 1453 // No default case will enable compiler detecting the missing cases 1454 } 1455 1456 return Res; 1457} 1458 1459void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 1460 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1461 I != E; 1462 I++) { 1463 clang::Decl *D = *I; 1464 if (D->getKind() == clang::Decl::Var) { 1465 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 1466 RSExportPrimitiveType::DataType DT = 1467 RSExportPrimitiveType::DataTypeUnknown; 1468 clang::Expr *InitExpr = NULL; 1469 if (InitializeRSObject(VD, &DT, &InitExpr)) { 1470 // We need to zero-init all RS object types (including matrices), ... 1471 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr); 1472 // ... but, only add to the list of RS objects if we have some 1473 // non-matrix RS object fields. 1474 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), 1475 VD->getLocation())) { 1476 getCurrentScope()->addRSObject(VD); 1477 } 1478 } 1479 } 1480 } 1481 return; 1482} 1483 1484void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 1485 if (!CS->body_empty()) { 1486 // Push a new scope 1487 Scope *S = new Scope(CS); 1488 mScopeStack.push(S); 1489 1490 VisitStmt(CS); 1491 1492 // Destroy the scope 1493 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!"); 1494 S->InsertLocalVarDestructors(); 1495 mScopeStack.pop(); 1496 delete S; 1497 } 1498 return; 1499} 1500 1501void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 1502 clang::QualType QT = AS->getType(); 1503 1504 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) { 1505 getCurrentScope()->ReplaceRSObjectAssignment(AS); 1506 } 1507 1508 return; 1509} 1510 1511void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 1512 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 1513 I != E; 1514 I++) { 1515 if (clang::Stmt *Child = *I) { 1516 Visit(Child); 1517 } 1518 } 1519 return; 1520} 1521 1522// This function walks the list of global variables and (potentially) creates 1523// a single global static destructor function that properly decrements 1524// reference counts on the contained RS object types. 1525clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() { 1526 Init(); 1527 1528 clang::DeclContext *DC = mCtx.getTranslationUnitDecl(); 1529 clang::SourceLocation loc; 1530 1531 llvm::StringRef SR(".rs.dtor"); 1532 clang::IdentifierInfo &II = mCtx.Idents.get(SR); 1533 clang::DeclarationName N(&II); 1534 clang::FunctionProtoType::ExtProtoInfo EPI; 1535 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy, 1536 llvm::ArrayRef<clang::QualType>(), EPI); 1537 clang::FunctionDecl *FD = NULL; 1538 1539 // Generate rsClearObject() call chains for every global variable 1540 // (whether static or extern). 1541 std::list<clang::Stmt *> StmtList; 1542 for (clang::DeclContext::decl_iterator I = DC->decls_begin(), 1543 E = DC->decls_end(); I != E; I++) { 1544 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I); 1545 if (VD) { 1546 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) { 1547 if (!FD) { 1548 // Only create FD if we are going to use it. 1549 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, NULL, 1550 clang::SC_None); 1551 } 1552 // Make sure to create any helpers within the function's DeclContext, 1553 // not the one associated with the global translation unit. 1554 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD); 1555 StmtList.push_back(RSClearObjectCall); 1556 } 1557 } 1558 } 1559 1560 // Nothing needs to be destroyed, so don't emit a dtor. 1561 if (StmtList.empty()) { 1562 return NULL; 1563 } 1564 1565 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc); 1566 1567 FD->setBody(CS); 1568 1569 return FD; 1570} 1571 1572} // namespace slang 1573