slang_rs_object_ref_count.cpp revision cc887ba8fe42cca706caae636932ae6a61a30ed2
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 the StmtList containing 173// destructors in proper locations. This includes inserting them 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 &mC; 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 list of destructors to execute for this scope. 202 std::list<clang::Stmt*> &mStmtList; 203 204 // The stack of statements which should be replaced by a compound statement 205 // containing the new destructor calls followed by the original Stmt. 206 std::stack<clang::Stmt*> mReplaceStmtStack; 207 208 public: 209 DestructorVisitor(clang::ASTContext &C, 210 clang::Stmt* OuterStmt, 211 std::list<clang::Stmt*> &StmtList); 212 213 // This code walks the collected list of Stmts to replace and actually does 214 // the replacement. It also finishes up by appending appropriate destructors 215 // to the current outermost CompoundStmt. 216 void InsertDestructors() { 217 clang::Stmt *S = NULL; 218 while (!mReplaceStmtStack.empty()) { 219 S = mReplaceStmtStack.top(); 220 mReplaceStmtStack.pop(); 221 222 mStmtList.push_back(S); 223 clang::CompoundStmt *CS = 224 BuildCompoundStmt(mC, mStmtList, S->getLocEnd()); 225 mStmtList.pop_back(); 226 227 RSASTReplace R(mC); 228 R.ReplaceStmt(mOuterStmt, S, CS); 229 } 230 clang::CompoundStmt *CS = dyn_cast<clang::CompoundStmt>(mOuterStmt); 231 slangAssert(CS); 232 if (CS) { 233 AppendAfterStmt(mC, CS, NULL, mStmtList); 234 } 235 } 236 237 void VisitStmt(clang::Stmt *S); 238 void VisitCompoundStmt(clang::CompoundStmt *CS); 239 240 void VisitBreakStmt(clang::BreakStmt *BS); 241 void VisitCaseStmt(clang::CaseStmt *CS); 242 void VisitContinueStmt(clang::ContinueStmt *CS); 243 void VisitDefaultStmt(clang::DefaultStmt *DS); 244 void VisitDoStmt(clang::DoStmt *DS); 245 void VisitForStmt(clang::ForStmt *FS); 246 void VisitIfStmt(clang::IfStmt *IS); 247 void VisitReturnStmt(clang::ReturnStmt *RS); 248 void VisitSwitchCase(clang::SwitchCase *SC); 249 void VisitSwitchStmt(clang::SwitchStmt *SS); 250 void VisitWhileStmt(clang::WhileStmt *WS); 251}; 252 253DestructorVisitor::DestructorVisitor(clang::ASTContext &C, 254 clang::Stmt *OuterStmt, 255 std::list<clang::Stmt*> &StmtList) 256 : mC(C), 257 mLoopDepth(0), 258 mSwitchDepth(0), 259 mOuterStmt(OuterStmt), 260 mStmtList(StmtList) { 261 return; 262} 263 264void DestructorVisitor::VisitStmt(clang::Stmt *S) { 265 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 266 I != E; 267 I++) { 268 if (clang::Stmt *Child = *I) { 269 Visit(Child); 270 } 271 } 272 return; 273} 274 275void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) { 276 VisitStmt(CS); 277 return; 278} 279 280void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) { 281 VisitStmt(BS); 282 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) { 283 mReplaceStmtStack.push(BS); 284 } 285 return; 286} 287 288void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) { 289 VisitStmt(CS); 290 return; 291} 292 293void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) { 294 VisitStmt(CS); 295 if (mLoopDepth == 0) { 296 // Switch statements can have nested continues. 297 mReplaceStmtStack.push(CS); 298 } 299 return; 300} 301 302void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) { 303 VisitStmt(DS); 304 return; 305} 306 307void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) { 308 mLoopDepth++; 309 VisitStmt(DS); 310 mLoopDepth--; 311 return; 312} 313 314void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) { 315 mLoopDepth++; 316 VisitStmt(FS); 317 mLoopDepth--; 318 return; 319} 320 321void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) { 322 VisitStmt(IS); 323 return; 324} 325 326void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) { 327 mReplaceStmtStack.push(RS); 328 return; 329} 330 331void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) { 332 slangAssert(false && "Both case and default have specialized handlers"); 333 VisitStmt(SC); 334 return; 335} 336 337void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) { 338 mSwitchDepth++; 339 VisitStmt(SS); 340 mSwitchDepth--; 341 return; 342} 343 344void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) { 345 mLoopDepth++; 346 VisitStmt(WS); 347 mLoopDepth--; 348 return; 349} 350 351clang::Expr *ClearSingleRSObject(clang::ASTContext &C, 352 clang::Expr *RefRSVar, 353 clang::SourceLocation Loc) { 354 slangAssert(RefRSVar); 355 const clang::Type *T = RefRSVar->getType().getTypePtr(); 356 slangAssert(!T->isArrayType() && 357 "Should not be destroying arrays with this function"); 358 359 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T); 360 slangAssert((ClearObjectFD != NULL) && 361 "rsClearObject doesn't cover all RS object types"); 362 363 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 364 clang::QualType ClearObjectFDArgType = 365 ClearObjectFD->getParamDecl(0)->getOriginalType(); 366 367 // Example destructor for "rs_font localFont;" 368 // 369 // (CallExpr 'void' 370 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 371 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 372 // (UnaryOperator 'rs_font *' prefix '&' 373 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont'))) 374 375 // Get address of targeted RS object 376 clang::Expr *AddrRefRSVar = 377 new(C) clang::UnaryOperator(RefRSVar, 378 clang::UO_AddrOf, 379 ClearObjectFDArgType, 380 clang::VK_RValue, 381 clang::OK_Ordinary, 382 Loc); 383 384 clang::Expr *RefRSClearObjectFD = 385 clang::DeclRefExpr::Create(C, 386 clang::NestedNameSpecifierLoc(), 387 ClearObjectFD, 388 ClearObjectFD->getLocation(), 389 ClearObjectFDType, 390 clang::VK_RValue, 391 NULL); 392 393 clang::Expr *RSClearObjectFP = 394 clang::ImplicitCastExpr::Create(C, 395 C.getPointerType(ClearObjectFDType), 396 clang::CK_FunctionToPointerDecay, 397 RefRSClearObjectFD, 398 NULL, 399 clang::VK_RValue); 400 401 clang::CallExpr *RSClearObjectCall = 402 new(C) clang::CallExpr(C, 403 RSClearObjectFP, 404 &AddrRefRSVar, 405 1, 406 ClearObjectFD->getCallResultType(), 407 clang::VK_RValue, 408 Loc); 409 410 return RSClearObjectCall; 411} 412 413static int ArrayDim(const clang::Type *T) { 414 if (!T || !T->isArrayType()) { 415 return 0; 416 } 417 418 const clang::ConstantArrayType *CAT = 419 static_cast<const clang::ConstantArrayType *>(T); 420 return static_cast<int>(CAT->getSize().getSExtValue()); 421} 422 423static clang::Stmt *ClearStructRSObject( 424 clang::ASTContext &C, 425 clang::DeclContext *DC, 426 clang::Expr *RefRSStruct, 427 clang::SourceLocation SourceLoc, 428 clang::SourceLocation Loc); 429 430static clang::Stmt *ClearArrayRSObject( 431 clang::ASTContext &C, 432 clang::DeclContext *DC, 433 clang::Expr *RefRSArr, 434 clang::SourceLocation StartLoc, 435 clang::SourceLocation Loc) { 436 const clang::Type *BaseType = RefRSArr->getType().getTypePtr(); 437 slangAssert(BaseType->isArrayType()); 438 439 int NumArrayElements = ArrayDim(BaseType); 440 // Actually extract out the base RS object type for use later 441 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 442 443 clang::Stmt *StmtArray[2] = {NULL}; 444 int StmtCtr = 0; 445 446 if (NumArrayElements <= 0) { 447 return NULL; 448 } 449 450 // Example destructor loop for "rs_font fontArr[10];" 451 // 452 // (CompoundStmt 453 // (DeclStmt "int rsIntIter") 454 // (ForStmt 455 // (BinaryOperator 'int' '=' 456 // (DeclRefExpr 'int' Var='rsIntIter') 457 // (IntegerLiteral 'int' 0)) 458 // (BinaryOperator 'int' '<' 459 // (DeclRefExpr 'int' Var='rsIntIter') 460 // (IntegerLiteral 'int' 10) 461 // NULL << CondVar >> 462 // (UnaryOperator 'int' postfix '++' 463 // (DeclRefExpr 'int' Var='rsIntIter')) 464 // (CallExpr 'void' 465 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 466 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 467 // (UnaryOperator 'rs_font *' prefix '&' 468 // (ArraySubscriptExpr 'rs_font':'rs_font' 469 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay> 470 // (DeclRefExpr 'rs_font [10]' Var='fontArr')) 471 // (DeclRefExpr 'int' Var='rsIntIter'))))))) 472 473 // Create helper variable for iterating through elements 474 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 475 clang::VarDecl *IIVD = 476 clang::VarDecl::Create(C, 477 DC, 478 StartLoc, 479 Loc, 480 &II, 481 C.IntTy, 482 C.getTrivialTypeSourceInfo(C.IntTy), 483 clang::SC_None, 484 clang::SC_None); 485 clang::Decl *IID = (clang::Decl *)IIVD; 486 487 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 488 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 489 490 // Form the actual destructor loop 491 // for (Init; Cond; Inc) 492 // RSClearObjectCall; 493 494 // Init -> "rsIntIter = 0" 495 clang::DeclRefExpr *RefrsIntIter = 496 clang::DeclRefExpr::Create(C, 497 clang::NestedNameSpecifierLoc(), 498 IIVD, 499 Loc, 500 C.IntTy, 501 clang::VK_RValue, 502 NULL); 503 504 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 505 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 506 507 clang::BinaryOperator *Init = 508 new(C) clang::BinaryOperator(RefrsIntIter, 509 Int0, 510 clang::BO_Assign, 511 C.IntTy, 512 clang::VK_RValue, 513 clang::OK_Ordinary, 514 Loc); 515 516 // Cond -> "rsIntIter < NumArrayElements" 517 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 518 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 519 520 clang::BinaryOperator *Cond = 521 new(C) clang::BinaryOperator(RefrsIntIter, 522 NumArrayElementsExpr, 523 clang::BO_LT, 524 C.IntTy, 525 clang::VK_RValue, 526 clang::OK_Ordinary, 527 Loc); 528 529 // Inc -> "rsIntIter++" 530 clang::UnaryOperator *Inc = 531 new(C) clang::UnaryOperator(RefrsIntIter, 532 clang::UO_PostInc, 533 C.IntTy, 534 clang::VK_RValue, 535 clang::OK_Ordinary, 536 Loc); 537 538 // Body -> "rsClearObject(&VD[rsIntIter]);" 539 // Destructor loop operates on individual array elements 540 541 clang::Expr *RefRSArrPtr = 542 clang::ImplicitCastExpr::Create(C, 543 C.getPointerType(BaseType->getCanonicalTypeInternal()), 544 clang::CK_ArrayToPointerDecay, 545 RefRSArr, 546 NULL, 547 clang::VK_RValue); 548 549 clang::Expr *RefRSArrPtrSubscript = 550 new(C) clang::ArraySubscriptExpr(RefRSArrPtr, 551 RefrsIntIter, 552 BaseType->getCanonicalTypeInternal(), 553 clang::VK_RValue, 554 clang::OK_Ordinary, 555 Loc); 556 557 RSExportPrimitiveType::DataType DT = 558 RSExportPrimitiveType::GetRSSpecificType(BaseType); 559 560 clang::Stmt *RSClearObjectCall = NULL; 561 if (BaseType->isArrayType()) { 562 RSClearObjectCall = 563 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc); 564 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 565 RSClearObjectCall = 566 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc); 567 } else { 568 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc); 569 } 570 571 clang::ForStmt *DestructorLoop = 572 new(C) clang::ForStmt(C, 573 Init, 574 Cond, 575 NULL, // no condVar 576 Inc, 577 RSClearObjectCall, 578 Loc, 579 Loc, 580 Loc); 581 582 StmtArray[StmtCtr++] = DestructorLoop; 583 slangAssert(StmtCtr == 2); 584 585 clang::CompoundStmt *CS = 586 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 587 588 return CS; 589} 590 591static unsigned CountRSObjectTypes(const clang::Type *T) { 592 slangAssert(T); 593 unsigned RSObjectCount = 0; 594 595 if (T->isArrayType()) { 596 return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual()); 597 } 598 599 RSExportPrimitiveType::DataType DT = 600 RSExportPrimitiveType::GetRSSpecificType(T); 601 if (DT != RSExportPrimitiveType::DataTypeUnknown) { 602 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0); 603 } 604 605 if (!T->isStructureType()) { 606 return 0; 607 } 608 609 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 610 RD = RD->getDefinition(); 611 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 612 FE = RD->field_end(); 613 FI != FE; 614 FI++) { 615 const clang::FieldDecl *FD = *FI; 616 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 617 if (CountRSObjectTypes(FT)) { 618 // Sub-structs should only count once (as should arrays, etc.) 619 RSObjectCount++; 620 } 621 } 622 623 return RSObjectCount; 624} 625 626static clang::Stmt *ClearStructRSObject( 627 clang::ASTContext &C, 628 clang::DeclContext *DC, 629 clang::Expr *RefRSStruct, 630 clang::SourceLocation StartLoc, 631 clang::SourceLocation Loc) { 632 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr(); 633 634 slangAssert(!BaseType->isArrayType()); 635 636 // Structs should show up as unknown primitive types 637 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) == 638 RSExportPrimitiveType::DataTypeUnknown); 639 640 unsigned FieldsToDestroy = CountRSObjectTypes(BaseType); 641 642 unsigned StmtCount = 0; 643 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy]; 644 for (unsigned i = 0; i < FieldsToDestroy; i++) { 645 StmtArray[i] = NULL; 646 } 647 648 // Populate StmtArray by creating a destructor for each RS object field 649 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl(); 650 RD = RD->getDefinition(); 651 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 652 FE = RD->field_end(); 653 FI != FE; 654 FI++) { 655 // We just look through all field declarations to see if we find a 656 // declaration for an RS object type (or an array of one). 657 bool IsArrayType = false; 658 clang::FieldDecl *FD = *FI; 659 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 660 const clang::Type *OrigType = FT; 661 while (FT && FT->isArrayType()) { 662 FT = FT->getArrayElementTypeNoTypeQual(); 663 IsArrayType = true; 664 } 665 666 if (RSExportPrimitiveType::IsRSObjectType(FT)) { 667 clang::DeclAccessPair FoundDecl = 668 clang::DeclAccessPair::make(FD, clang::AS_none); 669 clang::MemberExpr *RSObjectMember = 670 clang::MemberExpr::Create(C, 671 RefRSStruct, 672 false, 673 clang::NestedNameSpecifierLoc(), 674 FD, 675 FoundDecl, 676 clang::DeclarationNameInfo(), 677 NULL, 678 OrigType->getCanonicalTypeInternal(), 679 clang::VK_RValue, 680 clang::OK_Ordinary); 681 682 slangAssert(StmtCount < FieldsToDestroy); 683 684 if (IsArrayType) { 685 StmtArray[StmtCount++] = ClearArrayRSObject(C, 686 DC, 687 RSObjectMember, 688 StartLoc, 689 Loc); 690 } else { 691 StmtArray[StmtCount++] = ClearSingleRSObject(C, 692 RSObjectMember, 693 Loc); 694 } 695 } else if (FT->isStructureType() && CountRSObjectTypes(FT)) { 696 // In this case, we have a nested struct. We may not end up filling all 697 // of the spaces in StmtArray (sub-structs should handle themselves 698 // with separate compound statements). 699 clang::DeclAccessPair FoundDecl = 700 clang::DeclAccessPair::make(FD, clang::AS_none); 701 clang::MemberExpr *RSObjectMember = 702 clang::MemberExpr::Create(C, 703 RefRSStruct, 704 false, 705 clang::NestedNameSpecifierLoc(), 706 FD, 707 FoundDecl, 708 clang::DeclarationNameInfo(), 709 NULL, 710 OrigType->getCanonicalTypeInternal(), 711 clang::VK_RValue, 712 clang::OK_Ordinary); 713 714 if (IsArrayType) { 715 StmtArray[StmtCount++] = ClearArrayRSObject(C, 716 DC, 717 RSObjectMember, 718 StartLoc, 719 Loc); 720 } else { 721 StmtArray[StmtCount++] = ClearStructRSObject(C, 722 DC, 723 RSObjectMember, 724 StartLoc, 725 Loc); 726 } 727 } 728 } 729 730 slangAssert(StmtCount > 0); 731 clang::CompoundStmt *CS = 732 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 733 734 delete [] StmtArray; 735 736 return CS; 737} 738 739static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C, 740 clang::Diagnostic *Diags, 741 clang::Expr *DstExpr, 742 clang::Expr *SrcExpr, 743 clang::SourceLocation StartLoc, 744 clang::SourceLocation Loc) { 745 const clang::Type *T = DstExpr->getType().getTypePtr(); 746 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T); 747 slangAssert((SetObjectFD != NULL) && 748 "rsSetObject doesn't cover all RS object types"); 749 750 clang::QualType SetObjectFDType = SetObjectFD->getType(); 751 clang::QualType SetObjectFDArgType[2]; 752 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 753 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 754 755 clang::Expr *RefRSSetObjectFD = 756 clang::DeclRefExpr::Create(C, 757 clang::NestedNameSpecifierLoc(), 758 SetObjectFD, 759 Loc, 760 SetObjectFDType, 761 clang::VK_RValue, 762 NULL); 763 764 clang::Expr *RSSetObjectFP = 765 clang::ImplicitCastExpr::Create(C, 766 C.getPointerType(SetObjectFDType), 767 clang::CK_FunctionToPointerDecay, 768 RefRSSetObjectFD, 769 NULL, 770 clang::VK_RValue); 771 772 clang::Expr *ArgList[2]; 773 ArgList[0] = new(C) clang::UnaryOperator(DstExpr, 774 clang::UO_AddrOf, 775 SetObjectFDArgType[0], 776 clang::VK_RValue, 777 clang::OK_Ordinary, 778 Loc); 779 ArgList[1] = SrcExpr; 780 781 clang::CallExpr *RSSetObjectCall = 782 new(C) clang::CallExpr(C, 783 RSSetObjectFP, 784 ArgList, 785 2, 786 SetObjectFD->getCallResultType(), 787 clang::VK_RValue, 788 Loc); 789 790 return RSSetObjectCall; 791} 792 793static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 794 clang::Diagnostic *Diags, 795 clang::Expr *LHS, 796 clang::Expr *RHS, 797 clang::SourceLocation StartLoc, 798 clang::SourceLocation Loc); 799 800static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C, 801 clang::Diagnostic *Diags, 802 clang::Expr *DstArr, 803 clang::Expr *SrcArr, 804 clang::SourceLocation StartLoc, 805 clang::SourceLocation Loc) { 806 clang::DeclContext *DC = NULL; 807 const clang::Type *BaseType = DstArr->getType().getTypePtr(); 808 slangAssert(BaseType->isArrayType()); 809 810 int NumArrayElements = ArrayDim(BaseType); 811 // Actually extract out the base RS object type for use later 812 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 813 814 clang::Stmt *StmtArray[2] = {NULL}; 815 int StmtCtr = 0; 816 817 if (NumArrayElements <= 0) { 818 return NULL; 819 } 820 821 // Create helper variable for iterating through elements 822 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 823 clang::VarDecl *IIVD = 824 clang::VarDecl::Create(C, 825 DC, 826 StartLoc, 827 Loc, 828 &II, 829 C.IntTy, 830 C.getTrivialTypeSourceInfo(C.IntTy), 831 clang::SC_None, 832 clang::SC_None); 833 clang::Decl *IID = (clang::Decl *)IIVD; 834 835 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 836 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 837 838 // Form the actual loop 839 // for (Init; Cond; Inc) 840 // RSSetObjectCall; 841 842 // Init -> "rsIntIter = 0" 843 clang::DeclRefExpr *RefrsIntIter = 844 clang::DeclRefExpr::Create(C, 845 clang::NestedNameSpecifierLoc(), 846 IIVD, 847 Loc, 848 C.IntTy, 849 clang::VK_RValue, 850 NULL); 851 852 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 853 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 854 855 clang::BinaryOperator *Init = 856 new(C) clang::BinaryOperator(RefrsIntIter, 857 Int0, 858 clang::BO_Assign, 859 C.IntTy, 860 clang::VK_RValue, 861 clang::OK_Ordinary, 862 Loc); 863 864 // Cond -> "rsIntIter < NumArrayElements" 865 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 866 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 867 868 clang::BinaryOperator *Cond = 869 new(C) clang::BinaryOperator(RefrsIntIter, 870 NumArrayElementsExpr, 871 clang::BO_LT, 872 C.IntTy, 873 clang::VK_RValue, 874 clang::OK_Ordinary, 875 Loc); 876 877 // Inc -> "rsIntIter++" 878 clang::UnaryOperator *Inc = 879 new(C) clang::UnaryOperator(RefrsIntIter, 880 clang::UO_PostInc, 881 C.IntTy, 882 clang::VK_RValue, 883 clang::OK_Ordinary, 884 Loc); 885 886 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);" 887 // Loop operates on individual array elements 888 889 clang::Expr *DstArrPtr = 890 clang::ImplicitCastExpr::Create(C, 891 C.getPointerType(BaseType->getCanonicalTypeInternal()), 892 clang::CK_ArrayToPointerDecay, 893 DstArr, 894 NULL, 895 clang::VK_RValue); 896 897 clang::Expr *DstArrPtrSubscript = 898 new(C) clang::ArraySubscriptExpr(DstArrPtr, 899 RefrsIntIter, 900 BaseType->getCanonicalTypeInternal(), 901 clang::VK_RValue, 902 clang::OK_Ordinary, 903 Loc); 904 905 clang::Expr *SrcArrPtr = 906 clang::ImplicitCastExpr::Create(C, 907 C.getPointerType(BaseType->getCanonicalTypeInternal()), 908 clang::CK_ArrayToPointerDecay, 909 SrcArr, 910 NULL, 911 clang::VK_RValue); 912 913 clang::Expr *SrcArrPtrSubscript = 914 new(C) clang::ArraySubscriptExpr(SrcArrPtr, 915 RefrsIntIter, 916 BaseType->getCanonicalTypeInternal(), 917 clang::VK_RValue, 918 clang::OK_Ordinary, 919 Loc); 920 921 RSExportPrimitiveType::DataType DT = 922 RSExportPrimitiveType::GetRSSpecificType(BaseType); 923 924 clang::Stmt *RSSetObjectCall = NULL; 925 if (BaseType->isArrayType()) { 926 RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript, 927 SrcArrPtrSubscript, 928 StartLoc, Loc); 929 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 930 RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript, 931 SrcArrPtrSubscript, 932 StartLoc, Loc); 933 } else { 934 RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript, 935 SrcArrPtrSubscript, 936 StartLoc, Loc); 937 } 938 939 clang::ForStmt *DestructorLoop = 940 new(C) clang::ForStmt(C, 941 Init, 942 Cond, 943 NULL, // no condVar 944 Inc, 945 RSSetObjectCall, 946 Loc, 947 Loc, 948 Loc); 949 950 StmtArray[StmtCtr++] = DestructorLoop; 951 slangAssert(StmtCtr == 2); 952 953 clang::CompoundStmt *CS = 954 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 955 956 return CS; 957} 958 959static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 960 clang::Diagnostic *Diags, 961 clang::Expr *LHS, 962 clang::Expr *RHS, 963 clang::SourceLocation StartLoc, 964 clang::SourceLocation Loc) { 965 clang::QualType QT = LHS->getType(); 966 const clang::Type *T = QT.getTypePtr(); 967 slangAssert(T->isStructureType()); 968 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T)); 969 970 // Keep an extra slot for the original copy (memcpy) 971 unsigned FieldsToSet = CountRSObjectTypes(T) + 1; 972 973 unsigned StmtCount = 0; 974 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet]; 975 for (unsigned i = 0; i < FieldsToSet; i++) { 976 StmtArray[i] = NULL; 977 } 978 979 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 980 RD = RD->getDefinition(); 981 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 982 FE = RD->field_end(); 983 FI != FE; 984 FI++) { 985 bool IsArrayType = false; 986 clang::FieldDecl *FD = *FI; 987 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 988 const clang::Type *OrigType = FT; 989 990 if (!CountRSObjectTypes(FT)) { 991 // Skip to next if we don't have any viable RS object types 992 continue; 993 } 994 995 clang::DeclAccessPair FoundDecl = 996 clang::DeclAccessPair::make(FD, clang::AS_none); 997 clang::MemberExpr *DstMember = 998 clang::MemberExpr::Create(C, 999 LHS, 1000 false, 1001 clang::NestedNameSpecifierLoc(), 1002 FD, 1003 FoundDecl, 1004 clang::DeclarationNameInfo(), 1005 NULL, 1006 OrigType->getCanonicalTypeInternal(), 1007 clang::VK_RValue, 1008 clang::OK_Ordinary); 1009 1010 clang::MemberExpr *SrcMember = 1011 clang::MemberExpr::Create(C, 1012 RHS, 1013 false, 1014 clang::NestedNameSpecifierLoc(), 1015 FD, 1016 FoundDecl, 1017 clang::DeclarationNameInfo(), 1018 NULL, 1019 OrigType->getCanonicalTypeInternal(), 1020 clang::VK_RValue, 1021 clang::OK_Ordinary); 1022 1023 if (FT->isArrayType()) { 1024 FT = FT->getArrayElementTypeNoTypeQual(); 1025 IsArrayType = true; 1026 } 1027 1028 RSExportPrimitiveType::DataType DT = 1029 RSExportPrimitiveType::GetRSSpecificType(FT); 1030 1031 if (IsArrayType) { 1032 Diags->Report(clang::FullSourceLoc(Loc, C.getSourceManager()), 1033 Diags->getCustomDiagID(clang::Diagnostic::Error, 1034 "Arrays of RS object types within structures cannot be copied")); 1035 // TODO(srhines): Support setting arrays of RS objects 1036 // StmtArray[StmtCount++] = 1037 // CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, StartLoc, Loc); 1038 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 1039 StmtArray[StmtCount++] = 1040 CreateStructRSSetObject(C, Diags, DstMember, SrcMember, 1041 StartLoc, Loc); 1042 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) { 1043 StmtArray[StmtCount++] = 1044 CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, 1045 StartLoc, Loc); 1046 } else { 1047 slangAssert(false); 1048 } 1049 } 1050 1051 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet); 1052 1053 // We still need to actually do the overall struct copy. For simplicity, 1054 // we just do a straight-up assignment (which will still preserve all 1055 // the proper RS object reference counts). 1056 clang::BinaryOperator *CopyStruct = 1057 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, 1058 clang::VK_RValue, clang::OK_Ordinary, Loc); 1059 StmtArray[StmtCount++] = CopyStruct; 1060 1061 clang::CompoundStmt *CS = 1062 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 1063 1064 delete [] StmtArray; 1065 1066 return CS; 1067} 1068 1069} // namespace 1070 1071void RSObjectRefCount::Scope::ReplaceRSObjectAssignment( 1072 clang::BinaryOperator *AS, 1073 clang::Diagnostic *Diags) { 1074 1075 clang::QualType QT = AS->getType(); 1076 1077 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1078 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 1079 1080 clang::SourceLocation Loc = AS->getExprLoc(); 1081 clang::SourceLocation StartLoc = AS->getExprLoc(); 1082 clang::Stmt *UpdatedStmt = NULL; 1083 1084 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) { 1085 // By definition, this is a struct assignment if we get here 1086 UpdatedStmt = 1087 CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), 1088 StartLoc, Loc); 1089 } else { 1090 UpdatedStmt = 1091 CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), 1092 StartLoc, Loc); 1093 } 1094 1095 RSASTReplace R(C); 1096 R.ReplaceStmt(mCS, AS, UpdatedStmt); 1097 return; 1098} 1099 1100void RSObjectRefCount::Scope::AppendRSObjectInit( 1101 clang::Diagnostic *Diags, 1102 clang::VarDecl *VD, 1103 clang::DeclStmt *DS, 1104 RSExportPrimitiveType::DataType DT, 1105 clang::Expr *InitExpr) { 1106 slangAssert(VD); 1107 1108 if (!InitExpr) { 1109 return; 1110 } 1111 1112 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 1113 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 1114 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD( 1115 RSExportPrimitiveType::DataTypeRSFont)->getLocation(); 1116 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD( 1117 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart(); 1118 1119 if (DT == RSExportPrimitiveType::DataTypeIsStruct) { 1120 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1121 clang::DeclRefExpr *RefRSVar = 1122 clang::DeclRefExpr::Create(C, 1123 clang::NestedNameSpecifierLoc(), 1124 VD, 1125 Loc, 1126 T->getCanonicalTypeInternal(), 1127 clang::VK_RValue, 1128 NULL); 1129 1130 clang::Stmt *RSSetObjectOps = 1131 CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, StartLoc, Loc); 1132 1133 std::list<clang::Stmt*> StmtList; 1134 StmtList.push_back(RSSetObjectOps); 1135 AppendAfterStmt(C, mCS, DS, StmtList); 1136 return; 1137 } 1138 1139 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT); 1140 slangAssert((SetObjectFD != NULL) && 1141 "rsSetObject doesn't cover all RS object types"); 1142 1143 clang::QualType SetObjectFDType = SetObjectFD->getType(); 1144 clang::QualType SetObjectFDArgType[2]; 1145 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 1146 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 1147 1148 clang::Expr *RefRSSetObjectFD = 1149 clang::DeclRefExpr::Create(C, 1150 clang::NestedNameSpecifierLoc(), 1151 SetObjectFD, 1152 Loc, 1153 SetObjectFDType, 1154 clang::VK_RValue, 1155 NULL); 1156 1157 clang::Expr *RSSetObjectFP = 1158 clang::ImplicitCastExpr::Create(C, 1159 C.getPointerType(SetObjectFDType), 1160 clang::CK_FunctionToPointerDecay, 1161 RefRSSetObjectFD, 1162 NULL, 1163 clang::VK_RValue); 1164 1165 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1166 clang::DeclRefExpr *RefRSVar = 1167 clang::DeclRefExpr::Create(C, 1168 clang::NestedNameSpecifierLoc(), 1169 VD, 1170 Loc, 1171 T->getCanonicalTypeInternal(), 1172 clang::VK_RValue, 1173 NULL); 1174 1175 clang::Expr *ArgList[2]; 1176 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar, 1177 clang::UO_AddrOf, 1178 SetObjectFDArgType[0], 1179 clang::VK_RValue, 1180 clang::OK_Ordinary, 1181 Loc); 1182 ArgList[1] = InitExpr; 1183 1184 clang::CallExpr *RSSetObjectCall = 1185 new(C) clang::CallExpr(C, 1186 RSSetObjectFP, 1187 ArgList, 1188 2, 1189 SetObjectFD->getCallResultType(), 1190 clang::VK_RValue, 1191 Loc); 1192 1193 std::list<clang::Stmt*> StmtList; 1194 StmtList.push_back(RSSetObjectCall); 1195 AppendAfterStmt(C, mCS, DS, StmtList); 1196 1197 return; 1198} 1199 1200void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 1201 std::list<clang::Stmt*> RSClearObjectCalls; 1202 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 1203 E = mRSO.end(); 1204 I != E; 1205 I++) { 1206 clang::Stmt *S = ClearRSObject(*I); 1207 if (S) { 1208 RSClearObjectCalls.push_back(S); 1209 } 1210 } 1211 if (RSClearObjectCalls.size() > 0) { 1212 DestructorVisitor DV((*mRSO.begin())->getASTContext(), 1213 mCS, 1214 RSClearObjectCalls); 1215 DV.Visit(mCS); 1216 DV.InsertDestructors(); 1217 } 1218 return; 1219} 1220 1221clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) { 1222 slangAssert(VD); 1223 clang::ASTContext &C = VD->getASTContext(); 1224 clang::DeclContext *DC = VD->getDeclContext(); 1225 clang::SourceLocation Loc = VD->getLocation(); 1226 clang::SourceLocation StartLoc = VD->getInnerLocStart(); 1227 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1228 1229 // Reference expr to target RS object variable 1230 clang::DeclRefExpr *RefRSVar = 1231 clang::DeclRefExpr::Create(C, 1232 clang::NestedNameSpecifierLoc(), 1233 VD, 1234 Loc, 1235 T->getCanonicalTypeInternal(), 1236 clang::VK_RValue, 1237 NULL); 1238 1239 if (T->isArrayType()) { 1240 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc); 1241 } 1242 1243 RSExportPrimitiveType::DataType DT = 1244 RSExportPrimitiveType::GetRSSpecificType(T); 1245 1246 if (DT == RSExportPrimitiveType::DataTypeUnknown || 1247 DT == RSExportPrimitiveType::DataTypeIsStruct) { 1248 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc); 1249 } 1250 1251 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) && 1252 "Should be RS object"); 1253 1254 return ClearSingleRSObject(C, RefRSVar, Loc); 1255} 1256 1257bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD, 1258 RSExportPrimitiveType::DataType *DT, 1259 clang::Expr **InitExpr) { 1260 slangAssert(VD && DT && InitExpr); 1261 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1262 1263 // Loop through array types to get to base type 1264 while (T && T->isArrayType()) { 1265 T = T->getArrayElementTypeNoTypeQual(); 1266 } 1267 1268 bool DataTypeIsStructWithRSObject = false; 1269 *DT = RSExportPrimitiveType::GetRSSpecificType(T); 1270 1271 if (*DT == RSExportPrimitiveType::DataTypeUnknown) { 1272 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) { 1273 *DT = RSExportPrimitiveType::DataTypeIsStruct; 1274 DataTypeIsStructWithRSObject = true; 1275 } else { 1276 return false; 1277 } 1278 } 1279 1280 bool DataTypeIsRSObject = false; 1281 if (DataTypeIsStructWithRSObject) { 1282 DataTypeIsRSObject = true; 1283 } else { 1284 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT); 1285 } 1286 *InitExpr = VD->getInit(); 1287 1288 if (!DataTypeIsRSObject && *InitExpr) { 1289 // If we already have an initializer for a matrix type, we are done. 1290 return DataTypeIsRSObject; 1291 } 1292 1293 clang::Expr *ZeroInitializer = 1294 CreateZeroInitializerForRSSpecificType(*DT, 1295 VD->getASTContext(), 1296 VD->getLocation()); 1297 1298 if (ZeroInitializer) { 1299 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 1300 VD->setInit(ZeroInitializer); 1301 } 1302 1303 return DataTypeIsRSObject; 1304} 1305 1306clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 1307 RSExportPrimitiveType::DataType DT, 1308 clang::ASTContext &C, 1309 const clang::SourceLocation &Loc) { 1310 clang::Expr *Res = NULL; 1311 switch (DT) { 1312 case RSExportPrimitiveType::DataTypeIsStruct: 1313 case RSExportPrimitiveType::DataTypeRSElement: 1314 case RSExportPrimitiveType::DataTypeRSType: 1315 case RSExportPrimitiveType::DataTypeRSAllocation: 1316 case RSExportPrimitiveType::DataTypeRSSampler: 1317 case RSExportPrimitiveType::DataTypeRSScript: 1318 case RSExportPrimitiveType::DataTypeRSMesh: 1319 case RSExportPrimitiveType::DataTypeRSProgramFragment: 1320 case RSExportPrimitiveType::DataTypeRSProgramVertex: 1321 case RSExportPrimitiveType::DataTypeRSProgramRaster: 1322 case RSExportPrimitiveType::DataTypeRSProgramStore: 1323 case RSExportPrimitiveType::DataTypeRSFont: { 1324 // (ImplicitCastExpr 'nullptr_t' 1325 // (IntegerLiteral 0))) 1326 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 1327 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 1328 clang::Expr *CastToNull = 1329 clang::ImplicitCastExpr::Create(C, 1330 C.NullPtrTy, 1331 clang::CK_IntegralToPointer, 1332 Int0, 1333 NULL, 1334 clang::VK_RValue); 1335 1336 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc); 1337 break; 1338 } 1339 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 1340 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 1341 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 1342 // RS matrix is not completely an RS object. They hold data by themselves. 1343 // (InitListExpr rs_matrix2x2 1344 // (InitListExpr float[4] 1345 // (FloatingLiteral 0) 1346 // (FloatingLiteral 0) 1347 // (FloatingLiteral 0) 1348 // (FloatingLiteral 0))) 1349 clang::QualType FloatTy = C.FloatTy; 1350 // Constructor sets value to 0.0f by default 1351 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 1352 clang::FloatingLiteral *Float0Val = 1353 clang::FloatingLiteral::Create(C, 1354 Val, 1355 /* isExact = */true, 1356 FloatTy, 1357 Loc); 1358 1359 unsigned N = 0; 1360 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 1361 N = 2; 1362 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 1363 N = 3; 1364 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 1365 N = 4; 1366 1367 // Directly allocate 16 elements instead of dynamically allocate N*N 1368 clang::Expr *InitVals[16]; 1369 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++) 1370 InitVals[i] = Float0Val; 1371 clang::Expr *InitExpr = 1372 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc); 1373 InitExpr->setType(C.getConstantArrayType(FloatTy, 1374 llvm::APInt(32, 4), 1375 clang::ArrayType::Normal, 1376 /* EltTypeQuals = */0)); 1377 1378 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc); 1379 break; 1380 } 1381 case RSExportPrimitiveType::DataTypeUnknown: 1382 case RSExportPrimitiveType::DataTypeFloat16: 1383 case RSExportPrimitiveType::DataTypeFloat32: 1384 case RSExportPrimitiveType::DataTypeFloat64: 1385 case RSExportPrimitiveType::DataTypeSigned8: 1386 case RSExportPrimitiveType::DataTypeSigned16: 1387 case RSExportPrimitiveType::DataTypeSigned32: 1388 case RSExportPrimitiveType::DataTypeSigned64: 1389 case RSExportPrimitiveType::DataTypeUnsigned8: 1390 case RSExportPrimitiveType::DataTypeUnsigned16: 1391 case RSExportPrimitiveType::DataTypeUnsigned32: 1392 case RSExportPrimitiveType::DataTypeUnsigned64: 1393 case RSExportPrimitiveType::DataTypeBoolean: 1394 case RSExportPrimitiveType::DataTypeUnsigned565: 1395 case RSExportPrimitiveType::DataTypeUnsigned5551: 1396 case RSExportPrimitiveType::DataTypeUnsigned4444: 1397 case RSExportPrimitiveType::DataTypeMax: { 1398 slangAssert(false && "Not RS object type!"); 1399 } 1400 // No default case will enable compiler detecting the missing cases 1401 } 1402 1403 return Res; 1404} 1405 1406void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 1407 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1408 I != E; 1409 I++) { 1410 clang::Decl *D = *I; 1411 if (D->getKind() == clang::Decl::Var) { 1412 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 1413 RSExportPrimitiveType::DataType DT = 1414 RSExportPrimitiveType::DataTypeUnknown; 1415 clang::Expr *InitExpr = NULL; 1416 if (InitializeRSObject(VD, &DT, &InitExpr)) { 1417 getCurrentScope()->addRSObject(VD); 1418 getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr); 1419 } 1420 } 1421 } 1422 return; 1423} 1424 1425void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 1426 if (!CS->body_empty()) { 1427 // Push a new scope 1428 Scope *S = new Scope(CS); 1429 mScopeStack.push(S); 1430 1431 VisitStmt(CS); 1432 1433 // Destroy the scope 1434 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!"); 1435 S->InsertLocalVarDestructors(); 1436 mScopeStack.pop(); 1437 delete S; 1438 } 1439 return; 1440} 1441 1442void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 1443 clang::QualType QT = AS->getType(); 1444 1445 if (CountRSObjectTypes(QT.getTypePtr())) { 1446 getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags); 1447 } 1448 1449 return; 1450} 1451 1452void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 1453 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 1454 I != E; 1455 I++) { 1456 if (clang::Stmt *Child = *I) { 1457 Visit(Child); 1458 } 1459 } 1460 return; 1461} 1462 1463} // namespace slang 1464