slang_rs_object_ref_count.cpp revision 9ae18b2bbee0b08afd400542e863dd665ff76059
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] = NULL; 46 RSClearObjectFD[i] = NULL; 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 NULL, 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 = 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} 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 != NULL) && 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 NULL); 395 396 clang::Expr *RSClearObjectFP = 397 clang::ImplicitCastExpr::Create(C, 398 C.getPointerType(ClearObjectFDType), 399 clang::CK_FunctionToPointerDecay, 400 RefRSClearObjectFD, 401 NULL, 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] = {NULL}; 449 int StmtCtr = 0; 450 451 if (NumArrayElements <= 0) { 452 return NULL; 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 // NULL << 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 NULL); 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 NULL, 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 = NULL; 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 NULL, // 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] = NULL; 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::NestedNameSpecifierLoc(), 699 clang::SourceLocation(), 700 FD, 701 FoundDecl, 702 clang::DeclarationNameInfo(), 703 NULL, 704 OrigType->getCanonicalTypeInternal(), 705 clang::VK_RValue, 706 clang::OK_Ordinary); 707 708 slangAssert(StmtCount < FieldsToDestroy); 709 710 if (IsArrayType) { 711 StmtArray[StmtCount++] = ClearArrayRSObject(C, 712 DC, 713 RSObjectMember, 714 StartLoc, 715 Loc); 716 } else { 717 StmtArray[StmtCount++] = ClearSingleRSObject(C, 718 RSObjectMember, 719 Loc); 720 } 721 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) { 722 // In this case, we have a nested struct. We may not end up filling all 723 // of the spaces in StmtArray (sub-structs should handle themselves 724 // with separate compound statements). 725 clang::DeclAccessPair FoundDecl = 726 clang::DeclAccessPair::make(FD, clang::AS_none); 727 clang::MemberExpr *RSObjectMember = 728 clang::MemberExpr::Create(C, 729 RefRSStruct, 730 false, 731 clang::NestedNameSpecifierLoc(), 732 clang::SourceLocation(), 733 FD, 734 FoundDecl, 735 clang::DeclarationNameInfo(), 736 NULL, 737 OrigType->getCanonicalTypeInternal(), 738 clang::VK_RValue, 739 clang::OK_Ordinary); 740 741 if (IsArrayType) { 742 StmtArray[StmtCount++] = ClearArrayRSObject(C, 743 DC, 744 RSObjectMember, 745 StartLoc, 746 Loc); 747 } else { 748 StmtArray[StmtCount++] = ClearStructRSObject(C, 749 DC, 750 RSObjectMember, 751 StartLoc, 752 Loc); 753 } 754 } 755 } 756 757 slangAssert(StmtCount > 0); 758 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 759 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc); 760 761 delete [] StmtArray; 762 763 return CS; 764} 765 766static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C, 767 clang::Expr *DstExpr, 768 clang::Expr *SrcExpr, 769 clang::SourceLocation StartLoc, 770 clang::SourceLocation Loc) { 771 const clang::Type *T = DstExpr->getType().getTypePtr(); 772 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T); 773 slangAssert((SetObjectFD != NULL) && 774 "rsSetObject doesn't cover all RS object types"); 775 776 clang::QualType SetObjectFDType = SetObjectFD->getType(); 777 clang::QualType SetObjectFDArgType[2]; 778 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 779 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 780 781 clang::Expr *RefRSSetObjectFD = 782 clang::DeclRefExpr::Create(C, 783 clang::NestedNameSpecifierLoc(), 784 clang::SourceLocation(), 785 SetObjectFD, 786 false, 787 Loc, 788 SetObjectFDType, 789 clang::VK_RValue, 790 NULL); 791 792 clang::Expr *RSSetObjectFP = 793 clang::ImplicitCastExpr::Create(C, 794 C.getPointerType(SetObjectFDType), 795 clang::CK_FunctionToPointerDecay, 796 RefRSSetObjectFD, 797 NULL, 798 clang::VK_RValue); 799 800 llvm::SmallVector<clang::Expr*, 2> ArgList; 801 ArgList.push_back(new(C) clang::UnaryOperator(DstExpr, 802 clang::UO_AddrOf, 803 SetObjectFDArgType[0], 804 clang::VK_RValue, 805 clang::OK_Ordinary, 806 Loc)); 807 ArgList.push_back(SrcExpr); 808 809 clang::CallExpr *RSSetObjectCall = 810 new(C) clang::CallExpr(C, 811 RSSetObjectFP, 812 ArgList, 813 SetObjectFD->getCallResultType(), 814 clang::VK_RValue, 815 Loc); 816 817 return RSSetObjectCall; 818} 819 820static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 821 clang::Expr *LHS, 822 clang::Expr *RHS, 823 clang::SourceLocation StartLoc, 824 clang::SourceLocation Loc); 825 826/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C, 827 clang::Expr *DstArr, 828 clang::Expr *SrcArr, 829 clang::SourceLocation StartLoc, 830 clang::SourceLocation Loc) { 831 clang::DeclContext *DC = NULL; 832 const clang::Type *BaseType = DstArr->getType().getTypePtr(); 833 slangAssert(BaseType->isArrayType()); 834 835 int NumArrayElements = ArrayDim(BaseType); 836 // Actually extract out the base RS object type for use later 837 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 838 839 clang::Stmt *StmtArray[2] = {NULL}; 840 int StmtCtr = 0; 841 842 if (NumArrayElements <= 0) { 843 return NULL; 844 } 845 846 // Create helper variable for iterating through elements 847 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 848 clang::VarDecl *IIVD = 849 clang::VarDecl::Create(C, 850 DC, 851 StartLoc, 852 Loc, 853 &II, 854 C.IntTy, 855 C.getTrivialTypeSourceInfo(C.IntTy), 856 clang::SC_None, 857 clang::SC_None); 858 clang::Decl *IID = (clang::Decl *)IIVD; 859 860 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 861 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 862 863 // Form the actual loop 864 // for (Init; Cond; Inc) 865 // RSSetObjectCall; 866 867 // Init -> "rsIntIter = 0" 868 clang::DeclRefExpr *RefrsIntIter = 869 clang::DeclRefExpr::Create(C, 870 clang::NestedNameSpecifierLoc(), 871 IIVD, 872 Loc, 873 C.IntTy, 874 clang::VK_RValue, 875 NULL); 876 877 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 878 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 879 880 clang::BinaryOperator *Init = 881 new(C) clang::BinaryOperator(RefrsIntIter, 882 Int0, 883 clang::BO_Assign, 884 C.IntTy, 885 clang::VK_RValue, 886 clang::OK_Ordinary, 887 Loc); 888 889 // Cond -> "rsIntIter < NumArrayElements" 890 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 891 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 892 893 clang::BinaryOperator *Cond = 894 new(C) clang::BinaryOperator(RefrsIntIter, 895 NumArrayElementsExpr, 896 clang::BO_LT, 897 C.IntTy, 898 clang::VK_RValue, 899 clang::OK_Ordinary, 900 Loc); 901 902 // Inc -> "rsIntIter++" 903 clang::UnaryOperator *Inc = 904 new(C) clang::UnaryOperator(RefrsIntIter, 905 clang::UO_PostInc, 906 C.IntTy, 907 clang::VK_RValue, 908 clang::OK_Ordinary, 909 Loc); 910 911 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);" 912 // Loop operates on individual array elements 913 914 clang::Expr *DstArrPtr = 915 clang::ImplicitCastExpr::Create(C, 916 C.getPointerType(BaseType->getCanonicalTypeInternal()), 917 clang::CK_ArrayToPointerDecay, 918 DstArr, 919 NULL, 920 clang::VK_RValue); 921 922 clang::Expr *DstArrPtrSubscript = 923 new(C) clang::ArraySubscriptExpr(DstArrPtr, 924 RefrsIntIter, 925 BaseType->getCanonicalTypeInternal(), 926 clang::VK_RValue, 927 clang::OK_Ordinary, 928 Loc); 929 930 clang::Expr *SrcArrPtr = 931 clang::ImplicitCastExpr::Create(C, 932 C.getPointerType(BaseType->getCanonicalTypeInternal()), 933 clang::CK_ArrayToPointerDecay, 934 SrcArr, 935 NULL, 936 clang::VK_RValue); 937 938 clang::Expr *SrcArrPtrSubscript = 939 new(C) clang::ArraySubscriptExpr(SrcArrPtr, 940 RefrsIntIter, 941 BaseType->getCanonicalTypeInternal(), 942 clang::VK_RValue, 943 clang::OK_Ordinary, 944 Loc); 945 946 DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType); 947 948 clang::Stmt *RSSetObjectCall = NULL; 949 if (BaseType->isArrayType()) { 950 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript, 951 SrcArrPtrSubscript, 952 StartLoc, Loc); 953 } else if (DT == DataTypeUnknown) { 954 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript, 955 SrcArrPtrSubscript, 956 StartLoc, Loc); 957 } else { 958 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript, 959 SrcArrPtrSubscript, 960 StartLoc, Loc); 961 } 962 963 clang::ForStmt *DestructorLoop = 964 new(C) clang::ForStmt(C, 965 Init, 966 Cond, 967 NULL, // no condVar 968 Inc, 969 RSSetObjectCall, 970 Loc, 971 Loc, 972 Loc); 973 974 StmtArray[StmtCtr++] = DestructorLoop; 975 slangAssert(StmtCtr == 2); 976 977 clang::CompoundStmt *CS = 978 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 979 980 return CS; 981} */ 982 983static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 984 clang::Expr *LHS, 985 clang::Expr *RHS, 986 clang::SourceLocation StartLoc, 987 clang::SourceLocation Loc) { 988 clang::QualType QT = LHS->getType(); 989 const clang::Type *T = QT.getTypePtr(); 990 slangAssert(T->isStructureType()); 991 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T)); 992 993 // Keep an extra slot for the original copy (memcpy) 994 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1; 995 996 unsigned StmtCount = 0; 997 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet]; 998 for (unsigned i = 0; i < FieldsToSet; i++) { 999 StmtArray[i] = NULL; 1000 } 1001 1002 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 1003 RD = RD->getDefinition(); 1004 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 1005 FE = RD->field_end(); 1006 FI != FE; 1007 FI++) { 1008 bool IsArrayType = false; 1009 clang::FieldDecl *FD = *FI; 1010 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 1011 const clang::Type *OrigType = FT; 1012 1013 if (!CountRSObjectTypes(C, FT, Loc)) { 1014 // Skip to next if we don't have any viable RS object types 1015 continue; 1016 } 1017 1018 clang::DeclAccessPair FoundDecl = 1019 clang::DeclAccessPair::make(FD, clang::AS_none); 1020 clang::MemberExpr *DstMember = 1021 clang::MemberExpr::Create(C, 1022 LHS, 1023 false, 1024 clang::NestedNameSpecifierLoc(), 1025 clang::SourceLocation(), 1026 FD, 1027 FoundDecl, 1028 clang::DeclarationNameInfo(), 1029 NULL, 1030 OrigType->getCanonicalTypeInternal(), 1031 clang::VK_RValue, 1032 clang::OK_Ordinary); 1033 1034 clang::MemberExpr *SrcMember = 1035 clang::MemberExpr::Create(C, 1036 RHS, 1037 false, 1038 clang::NestedNameSpecifierLoc(), 1039 clang::SourceLocation(), 1040 FD, 1041 FoundDecl, 1042 clang::DeclarationNameInfo(), 1043 NULL, 1044 OrigType->getCanonicalTypeInternal(), 1045 clang::VK_RValue, 1046 clang::OK_Ordinary); 1047 1048 if (FT->isArrayType()) { 1049 FT = FT->getArrayElementTypeNoTypeQual(); 1050 IsArrayType = true; 1051 } 1052 1053 DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT); 1054 1055 if (IsArrayType) { 1056 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics(); 1057 DiagEngine.Report( 1058 clang::FullSourceLoc(Loc, C.getSourceManager()), 1059 DiagEngine.getCustomDiagID( 1060 clang::DiagnosticsEngine::Error, 1061 "Arrays of RS object types within structures cannot be copied")); 1062 // TODO(srhines): Support setting arrays of RS objects 1063 // StmtArray[StmtCount++] = 1064 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1065 } else if (DT == DataTypeUnknown) { 1066 StmtArray[StmtCount++] = 1067 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1068 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) { 1069 StmtArray[StmtCount++] = 1070 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc); 1071 } else { 1072 slangAssert(false); 1073 } 1074 } 1075 1076 slangAssert(StmtCount < FieldsToSet); 1077 1078 // We still need to actually do the overall struct copy. For simplicity, 1079 // we just do a straight-up assignment (which will still preserve all 1080 // the proper RS object reference counts). 1081 clang::BinaryOperator *CopyStruct = 1082 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, 1083 clang::VK_RValue, clang::OK_Ordinary, Loc, 1084 false); 1085 StmtArray[StmtCount++] = CopyStruct; 1086 1087 clang::CompoundStmt *CS = new(C) clang::CompoundStmt( 1088 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc); 1089 1090 delete [] StmtArray; 1091 1092 return CS; 1093} 1094 1095} // namespace 1096 1097void RSObjectRefCount::Scope::ReplaceRSObjectAssignment( 1098 clang::BinaryOperator *AS) { 1099 1100 clang::QualType QT = AS->getType(); 1101 1102 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1103 DataTypeRSAllocation)->getASTContext(); 1104 1105 clang::SourceLocation Loc = AS->getExprLoc(); 1106 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc(); 1107 clang::Stmt *UpdatedStmt = NULL; 1108 1109 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) { 1110 // By definition, this is a struct assignment if we get here 1111 UpdatedStmt = 1112 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc); 1113 } else { 1114 UpdatedStmt = 1115 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc); 1116 } 1117 1118 RSASTReplace R(C); 1119 R.ReplaceStmt(mCS, AS, UpdatedStmt); 1120} 1121 1122void RSObjectRefCount::Scope::AppendRSObjectInit( 1123 clang::VarDecl *VD, 1124 clang::DeclStmt *DS, 1125 DataType DT, 1126 clang::Expr *InitExpr) { 1127 slangAssert(VD); 1128 1129 if (!InitExpr) { 1130 return; 1131 } 1132 1133 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1134 DataTypeRSAllocation)->getASTContext(); 1135 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD( 1136 DataTypeRSAllocation)->getLocation(); 1137 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD( 1138 DataTypeRSAllocation)->getInnerLocStart(); 1139 1140 if (DT == DataTypeIsStruct) { 1141 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1142 clang::DeclRefExpr *RefRSVar = 1143 clang::DeclRefExpr::Create(C, 1144 clang::NestedNameSpecifierLoc(), 1145 clang::SourceLocation(), 1146 VD, 1147 false, 1148 Loc, 1149 T->getCanonicalTypeInternal(), 1150 clang::VK_RValue, 1151 NULL); 1152 1153 clang::Stmt *RSSetObjectOps = 1154 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc); 1155 1156 std::list<clang::Stmt*> StmtList; 1157 StmtList.push_back(RSSetObjectOps); 1158 AppendAfterStmt(C, mCS, DS, StmtList); 1159 return; 1160 } 1161 1162 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT); 1163 slangAssert((SetObjectFD != NULL) && 1164 "rsSetObject doesn't cover all RS object types"); 1165 1166 clang::QualType SetObjectFDType = SetObjectFD->getType(); 1167 clang::QualType SetObjectFDArgType[2]; 1168 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 1169 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 1170 1171 clang::Expr *RefRSSetObjectFD = 1172 clang::DeclRefExpr::Create(C, 1173 clang::NestedNameSpecifierLoc(), 1174 clang::SourceLocation(), 1175 SetObjectFD, 1176 false, 1177 Loc, 1178 SetObjectFDType, 1179 clang::VK_RValue, 1180 NULL); 1181 1182 clang::Expr *RSSetObjectFP = 1183 clang::ImplicitCastExpr::Create(C, 1184 C.getPointerType(SetObjectFDType), 1185 clang::CK_FunctionToPointerDecay, 1186 RefRSSetObjectFD, 1187 NULL, 1188 clang::VK_RValue); 1189 1190 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1191 clang::DeclRefExpr *RefRSVar = 1192 clang::DeclRefExpr::Create(C, 1193 clang::NestedNameSpecifierLoc(), 1194 clang::SourceLocation(), 1195 VD, 1196 false, 1197 Loc, 1198 T->getCanonicalTypeInternal(), 1199 clang::VK_RValue, 1200 NULL); 1201 1202 llvm::SmallVector<clang::Expr*, 2> ArgList; 1203 ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar, 1204 clang::UO_AddrOf, 1205 SetObjectFDArgType[0], 1206 clang::VK_RValue, 1207 clang::OK_Ordinary, 1208 Loc)); 1209 ArgList.push_back(InitExpr); 1210 1211 clang::CallExpr *RSSetObjectCall = 1212 new(C) clang::CallExpr(C, 1213 RSSetObjectFP, 1214 ArgList, 1215 SetObjectFD->getCallResultType(), 1216 clang::VK_RValue, 1217 Loc); 1218 1219 std::list<clang::Stmt*> StmtList; 1220 StmtList.push_back(RSSetObjectCall); 1221 AppendAfterStmt(C, mCS, DS, StmtList); 1222} 1223 1224void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 1225 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 1226 E = mRSO.end(); 1227 I != E; 1228 I++) { 1229 clang::VarDecl *VD = *I; 1230 clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext()); 1231 if (RSClearObjectCall) { 1232 DestructorVisitor DV((*mRSO.begin())->getASTContext(), 1233 mCS, 1234 RSClearObjectCall, 1235 VD->getSourceRange().getBegin()); 1236 DV.Visit(mCS); 1237 DV.InsertDestructors(); 1238 } 1239 } 1240} 1241 1242clang::Stmt *RSObjectRefCount::Scope::ClearRSObject( 1243 clang::VarDecl *VD, 1244 clang::DeclContext *DC) { 1245 slangAssert(VD); 1246 clang::ASTContext &C = VD->getASTContext(); 1247 clang::SourceLocation Loc = VD->getLocation(); 1248 clang::SourceLocation StartLoc = VD->getInnerLocStart(); 1249 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1250 1251 // Reference expr to target RS object variable 1252 clang::DeclRefExpr *RefRSVar = 1253 clang::DeclRefExpr::Create(C, 1254 clang::NestedNameSpecifierLoc(), 1255 clang::SourceLocation(), 1256 VD, 1257 false, 1258 Loc, 1259 T->getCanonicalTypeInternal(), 1260 clang::VK_RValue, 1261 NULL); 1262 1263 if (T->isArrayType()) { 1264 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc); 1265 } 1266 1267 DataType DT = RSExportPrimitiveType::GetRSSpecificType(T); 1268 1269 if (DT == DataTypeUnknown || 1270 DT == DataTypeIsStruct) { 1271 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc); 1272 } 1273 1274 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) && 1275 "Should be RS object"); 1276 1277 return ClearSingleRSObject(C, RefRSVar, Loc); 1278} 1279 1280bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD, 1281 DataType *DT, 1282 clang::Expr **InitExpr) { 1283 slangAssert(VD && DT && InitExpr); 1284 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1285 1286 // Loop through array types to get to base type 1287 while (T && T->isArrayType()) { 1288 T = T->getArrayElementTypeNoTypeQual(); 1289 } 1290 1291 bool DataTypeIsStructWithRSObject = false; 1292 *DT = RSExportPrimitiveType::GetRSSpecificType(T); 1293 1294 if (*DT == DataTypeUnknown) { 1295 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) { 1296 *DT = DataTypeIsStruct; 1297 DataTypeIsStructWithRSObject = true; 1298 } else { 1299 return false; 1300 } 1301 } 1302 1303 bool DataTypeIsRSObject = false; 1304 if (DataTypeIsStructWithRSObject) { 1305 DataTypeIsRSObject = true; 1306 } else { 1307 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT); 1308 } 1309 *InitExpr = VD->getInit(); 1310 1311 if (!DataTypeIsRSObject && *InitExpr) { 1312 // If we already have an initializer for a matrix type, we are done. 1313 return DataTypeIsRSObject; 1314 } 1315 1316 clang::Expr *ZeroInitializer = 1317 CreateZeroInitializerForRSSpecificType(*DT, 1318 VD->getASTContext(), 1319 VD->getLocation()); 1320 1321 if (ZeroInitializer) { 1322 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 1323 VD->setInit(ZeroInitializer); 1324 } 1325 1326 return DataTypeIsRSObject; 1327} 1328 1329clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 1330 DataType DT, 1331 clang::ASTContext &C, 1332 const clang::SourceLocation &Loc) { 1333 clang::Expr *Res = NULL; 1334 switch (DT) { 1335 case DataTypeIsStruct: 1336 case DataTypeRSElement: 1337 case DataTypeRSType: 1338 case DataTypeRSAllocation: 1339 case DataTypeRSSampler: 1340 case DataTypeRSScript: 1341 case DataTypeRSMesh: 1342 case DataTypeRSPath: 1343 case DataTypeRSProgramFragment: 1344 case DataTypeRSProgramVertex: 1345 case DataTypeRSProgramRaster: 1346 case DataTypeRSProgramStore: 1347 case DataTypeRSFont: { 1348 // (ImplicitCastExpr 'nullptr_t' 1349 // (IntegerLiteral 0))) 1350 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 1351 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 1352 clang::Expr *CastToNull = 1353 clang::ImplicitCastExpr::Create(C, 1354 C.NullPtrTy, 1355 clang::CK_IntegralToPointer, 1356 Int0, 1357 NULL, 1358 clang::VK_RValue); 1359 1360 llvm::SmallVector<clang::Expr*, 1>InitList; 1361 InitList.push_back(CastToNull); 1362 1363 Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc); 1364 break; 1365 } 1366 case DataTypeRSMatrix2x2: 1367 case DataTypeRSMatrix3x3: 1368 case DataTypeRSMatrix4x4: { 1369 // RS matrix is not completely an RS object. They hold data by themselves. 1370 // (InitListExpr rs_matrix2x2 1371 // (InitListExpr float[4] 1372 // (FloatingLiteral 0) 1373 // (FloatingLiteral 0) 1374 // (FloatingLiteral 0) 1375 // (FloatingLiteral 0))) 1376 clang::QualType FloatTy = C.FloatTy; 1377 // Constructor sets value to 0.0f by default 1378 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 1379 clang::FloatingLiteral *Float0Val = 1380 clang::FloatingLiteral::Create(C, 1381 Val, 1382 /* isExact = */true, 1383 FloatTy, 1384 Loc); 1385 1386 unsigned N = 0; 1387 if (DT == DataTypeRSMatrix2x2) 1388 N = 2; 1389 else if (DT == DataTypeRSMatrix3x3) 1390 N = 3; 1391 else if (DT == DataTypeRSMatrix4x4) 1392 N = 4; 1393 unsigned N_2 = N * N; 1394 1395 // Assume we are going to be allocating 16 elements, since 4x4 is max. 1396 llvm::SmallVector<clang::Expr*, 16> InitVals; 1397 for (unsigned i = 0; i < N_2; i++) 1398 InitVals.push_back(Float0Val); 1399 clang::Expr *InitExpr = 1400 new(C) clang::InitListExpr(C, Loc, InitVals, Loc); 1401 InitExpr->setType(C.getConstantArrayType(FloatTy, 1402 llvm::APInt(32, N_2), 1403 clang::ArrayType::Normal, 1404 /* EltTypeQuals = */0)); 1405 llvm::SmallVector<clang::Expr*, 1> InitExprVec; 1406 InitExprVec.push_back(InitExpr); 1407 1408 Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc); 1409 break; 1410 } 1411 case DataTypeUnknown: 1412 case DataTypeFloat16: 1413 case DataTypeFloat32: 1414 case DataTypeFloat64: 1415 case DataTypeSigned8: 1416 case DataTypeSigned16: 1417 case DataTypeSigned32: 1418 case DataTypeSigned64: 1419 case DataTypeUnsigned8: 1420 case DataTypeUnsigned16: 1421 case DataTypeUnsigned32: 1422 case DataTypeUnsigned64: 1423 case DataTypeBoolean: 1424 case DataTypeUnsigned565: 1425 case DataTypeUnsigned5551: 1426 case DataTypeUnsigned4444: 1427 case DataTypeMax: { 1428 slangAssert(false && "Not RS object type!"); 1429 } 1430 // No default case will enable compiler detecting the missing cases 1431 } 1432 1433 return Res; 1434} 1435 1436void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 1437 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1438 I != E; 1439 I++) { 1440 clang::Decl *D = *I; 1441 if (D->getKind() == clang::Decl::Var) { 1442 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 1443 DataType DT = DataTypeUnknown; 1444 clang::Expr *InitExpr = NULL; 1445 if (InitializeRSObject(VD, &DT, &InitExpr)) { 1446 // We need to zero-init all RS object types (including matrices), ... 1447 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr); 1448 // ... but, only add to the list of RS objects if we have some 1449 // non-matrix RS object fields. 1450 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), 1451 VD->getLocation())) { 1452 getCurrentScope()->addRSObject(VD); 1453 } 1454 } 1455 } 1456 } 1457} 1458 1459void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 1460 if (!CS->body_empty()) { 1461 // Push a new scope 1462 Scope *S = new Scope(CS); 1463 mScopeStack.push(S); 1464 1465 VisitStmt(CS); 1466 1467 // Destroy the scope 1468 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!"); 1469 S->InsertLocalVarDestructors(); 1470 mScopeStack.pop(); 1471 delete S; 1472 } 1473} 1474 1475void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 1476 clang::QualType QT = AS->getType(); 1477 1478 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) { 1479 getCurrentScope()->ReplaceRSObjectAssignment(AS); 1480 } 1481} 1482 1483void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 1484 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 1485 I != E; 1486 I++) { 1487 if (clang::Stmt *Child = *I) { 1488 Visit(Child); 1489 } 1490 } 1491} 1492 1493// This function walks the list of global variables and (potentially) creates 1494// a single global static destructor function that properly decrements 1495// reference counts on the contained RS object types. 1496clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() { 1497 Init(); 1498 1499 clang::DeclContext *DC = mCtx.getTranslationUnitDecl(); 1500 clang::SourceLocation loc; 1501 1502 llvm::StringRef SR(".rs.dtor"); 1503 clang::IdentifierInfo &II = mCtx.Idents.get(SR); 1504 clang::DeclarationName N(&II); 1505 clang::FunctionProtoType::ExtProtoInfo EPI; 1506 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy, 1507 llvm::ArrayRef<clang::QualType>(), EPI); 1508 clang::FunctionDecl *FD = NULL; 1509 1510 // Generate rsClearObject() call chains for every global variable 1511 // (whether static or extern). 1512 std::list<clang::Stmt *> StmtList; 1513 for (clang::DeclContext::decl_iterator I = DC->decls_begin(), 1514 E = DC->decls_end(); I != E; I++) { 1515 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I); 1516 if (VD) { 1517 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) { 1518 if (!FD) { 1519 // Only create FD if we are going to use it. 1520 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, NULL, 1521 clang::SC_None); 1522 } 1523 // Make sure to create any helpers within the function's DeclContext, 1524 // not the one associated with the global translation unit. 1525 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD); 1526 StmtList.push_back(RSClearObjectCall); 1527 } 1528 } 1529 } 1530 1531 // Nothing needs to be destroyed, so don't emit a dtor. 1532 if (StmtList.empty()) { 1533 return NULL; 1534 } 1535 1536 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc); 1537 1538 FD->setBody(CS); 1539 1540 return FD; 1541} 1542 1543} // namespace slang 1544