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