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