slang_rs_object_ref_count.cpp revision 832429f6bf4592cfc2ce58f2462f1e8ecdbaaf52
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/OperationKinds.h" 24#include "clang/AST/Stmt.h" 25#include "clang/AST/StmtVisitor.h" 26 27#include "slang_assert.h" 28#include "slang_rs.h" 29#include "slang_rs_export_type.h" 30 31namespace slang { 32 33clang::FunctionDecl *RSObjectRefCount:: 34 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType - 35 RSExportPrimitiveType::FirstRSObjectType + 1]; 36clang::FunctionDecl *RSObjectRefCount:: 37 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType - 38 RSExportPrimitiveType::FirstRSObjectType + 1]; 39 40void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) { 41 for (unsigned i = 0; 42 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*)); 43 i++) { 44 RSSetObjectFD[i] = NULL; 45 RSClearObjectFD[i] = NULL; 46 } 47 48 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 49 50 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(), 51 E = TUDecl->decls_end(); I != E; I++) { 52 if ((I->getKind() >= clang::Decl::firstFunction) && 53 (I->getKind() <= clang::Decl::lastFunction)) { 54 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I); 55 56 // points to RSSetObjectFD or RSClearObjectFD 57 clang::FunctionDecl **RSObjectFD; 58 59 if (FD->getName() == "rsSetObject") { 60 slangAssert((FD->getNumParams() == 2) && 61 "Invalid rsSetObject function prototype (# params)"); 62 RSObjectFD = RSSetObjectFD; 63 } else if (FD->getName() == "rsClearObject") { 64 slangAssert((FD->getNumParams() == 1) && 65 "Invalid rsClearObject function prototype (# params)"); 66 RSObjectFD = RSClearObjectFD; 67 } else { 68 continue; 69 } 70 71 const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 72 clang::QualType PVT = PVD->getOriginalType(); 73 // The first parameter must be a pointer like rs_allocation* 74 slangAssert(PVT->isPointerType() && 75 "Invalid rs{Set,Clear}Object function prototype (pointer param)"); 76 77 // The rs object type passed to the FD 78 clang::QualType RST = PVT->getPointeeType(); 79 RSExportPrimitiveType::DataType DT = 80 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr()); 81 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT) 82 && "must be RS object type"); 83 84 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD; 85 } 86 } 87} 88 89namespace { 90 91static void AppendToCompoundStatement(clang::ASTContext& C, 92 clang::CompoundStmt *CS, 93 std::list<clang::Stmt*> &StmtList, 94 bool InsertAtEndOfBlock) { 95 // Destructor code will be inserted before any return statement. 96 // Any subsequent statements in the compound statement are then placed 97 // after our new code. 98 // TODO(srhines): This should also handle the case of goto/break/continue. 99 100 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 101 102 unsigned OldStmtCount = 0; 103 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 104 OldStmtCount++; 105 } 106 107 unsigned NewStmtCount = StmtList.size(); 108 109 clang::Stmt **UpdatedStmtList; 110 UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount]; 111 112 unsigned UpdatedStmtCount = 0; 113 bool FoundReturn = false; 114 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 115 if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) { 116 FoundReturn = true; 117 break; 118 } 119 UpdatedStmtList[UpdatedStmtCount++] = *bI; 120 } 121 122 // Always insert before a return that we found, or if we are told 123 // to insert at the end of the block 124 if (FoundReturn || InsertAtEndOfBlock) { 125 std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 126 for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin(); 127 I != StmtList.end(); 128 I++) { 129 UpdatedStmtList[UpdatedStmtCount++] = *I; 130 } 131 } 132 133 // Pick up anything left over after a return statement 134 for ( ; bI != CS->body_end(); bI++) { 135 UpdatedStmtList[UpdatedStmtCount++] = *bI; 136 } 137 138 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 139 140 delete [] UpdatedStmtList; 141 142 return; 143} 144 145static void AppendAfterStmt(clang::ASTContext& C, 146 clang::CompoundStmt *CS, 147 clang::Stmt *OldStmt, 148 clang::Stmt *NewStmt) { 149 slangAssert(CS && OldStmt && NewStmt); 150 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 151 unsigned StmtCount = 1; // Take into account new statement 152 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 153 StmtCount++; 154 } 155 156 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount]; 157 158 unsigned UpdatedStmtCount = 0; 159 unsigned Once = 0; 160 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 161 UpdatedStmtList[UpdatedStmtCount++] = *bI; 162 if (*bI == OldStmt) { 163 Once++; 164 slangAssert(Once == 1); 165 UpdatedStmtList[UpdatedStmtCount++] = NewStmt; 166 } 167 } 168 169 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 170 171 delete [] UpdatedStmtList; 172 173 return; 174} 175 176static void ReplaceInCompoundStmt(clang::ASTContext& C, 177 clang::CompoundStmt *CS, 178 clang::Stmt* OldStmt, 179 clang::Stmt* NewStmt) { 180 clang::CompoundStmt::body_iterator bI = CS->body_begin(); 181 182 unsigned StmtCount = 0; 183 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 184 StmtCount++; 185 } 186 187 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount]; 188 189 unsigned UpdatedStmtCount = 0; 190 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) { 191 if (*bI == OldStmt) { 192 UpdatedStmtList[UpdatedStmtCount++] = NewStmt; 193 } else { 194 UpdatedStmtList[UpdatedStmtCount++] = *bI; 195 } 196 } 197 198 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount); 199 200 delete [] UpdatedStmtList; 201 202 return; 203} 204 205 206// This class visits a compound statement and inserts the StmtList containing 207// destructors in proper locations. This includes inserting them before any 208// return statement in any sub-block, at the end of the logical enclosing 209// scope (compound statement), and/or before any break/continue statement that 210// would resume outside the declared scope. We will not handle the case for 211// goto statements that leave a local scope. 212// TODO(srhines): Make this work properly for break/continue. 213class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> { 214 private: 215 clang::ASTContext &mC; 216 std::list<clang::Stmt*> &mStmtList; 217 bool mTopLevel; 218 public: 219 DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList); 220 void VisitStmt(clang::Stmt *S); 221 void VisitCompoundStmt(clang::CompoundStmt *CS); 222}; 223 224DestructorVisitor::DestructorVisitor(clang::ASTContext &C, 225 std::list<clang::Stmt*> &StmtList) 226 : mC(C), 227 mStmtList(StmtList), 228 mTopLevel(true) { 229 return; 230} 231 232void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) { 233 if (!CS->body_empty()) { 234 AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel); 235 mTopLevel = false; 236 VisitStmt(CS); 237 } 238 return; 239} 240 241void DestructorVisitor::VisitStmt(clang::Stmt *S) { 242 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 243 I != E; 244 I++) { 245 if (clang::Stmt *Child = *I) { 246 Visit(Child); 247 } 248 } 249 return; 250} 251 252clang::Expr *ClearSingleRSObject(clang::ASTContext &C, 253 clang::Expr *RefRSVar, 254 clang::SourceLocation Loc) { 255 slangAssert(RefRSVar); 256 const clang::Type *T = RefRSVar->getType().getTypePtr(); 257 slangAssert(!T->isArrayType() && 258 "Should not be destroying arrays with this function"); 259 260 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T); 261 slangAssert((ClearObjectFD != NULL) && 262 "rsClearObject doesn't cover all RS object types"); 263 264 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 265 clang::QualType ClearObjectFDArgType = 266 ClearObjectFD->getParamDecl(0)->getOriginalType(); 267 268 // Example destructor for "rs_font localFont;" 269 // 270 // (CallExpr 'void' 271 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 272 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 273 // (UnaryOperator 'rs_font *' prefix '&' 274 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont'))) 275 276 // Get address of targeted RS object 277 clang::Expr *AddrRefRSVar = 278 new(C) clang::UnaryOperator(RefRSVar, 279 clang::UO_AddrOf, 280 ClearObjectFDArgType, 281 Loc); 282 283 clang::Expr *RefRSClearObjectFD = 284 clang::DeclRefExpr::Create(C, 285 NULL, 286 ClearObjectFD->getQualifierRange(), 287 ClearObjectFD, 288 ClearObjectFD->getLocation(), 289 ClearObjectFDType); 290 291 clang::Expr *RSClearObjectFP = 292 clang::ImplicitCastExpr::Create(C, 293 C.getPointerType(ClearObjectFDType), 294 clang::CK_FunctionToPointerDecay, 295 RefRSClearObjectFD, 296 NULL, 297 clang::VK_RValue); 298 299 clang::CallExpr *RSClearObjectCall = 300 new(C) clang::CallExpr(C, 301 RSClearObjectFP, 302 &AddrRefRSVar, 303 1, 304 ClearObjectFD->getCallResultType(), 305 Loc); 306 307 return RSClearObjectCall; 308} 309 310static int ArrayDim(const clang::Type *T) { 311 if (!T || !T->isArrayType()) { 312 return 0; 313 } 314 315 const clang::ConstantArrayType *CAT = 316 static_cast<const clang::ConstantArrayType *>(T); 317 return static_cast<int>(CAT->getSize().getSExtValue()); 318} 319 320static clang::Stmt *ClearStructRSObject( 321 clang::ASTContext &C, 322 clang::DeclContext *DC, 323 clang::Expr *RefRSStruct, 324 clang::SourceRange Range, 325 clang::SourceLocation Loc); 326 327static clang::Stmt *ClearArrayRSObject( 328 clang::ASTContext &C, 329 clang::DeclContext *DC, 330 clang::Expr *RefRSArr, 331 clang::SourceRange Range, 332 clang::SourceLocation Loc) { 333 const clang::Type *BaseType = RefRSArr->getType().getTypePtr(); 334 slangAssert(BaseType->isArrayType()); 335 336 int NumArrayElements = ArrayDim(BaseType); 337 // Actually extract out the base RS object type for use later 338 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 339 340 clang::Stmt *StmtArray[2] = {NULL}; 341 int StmtCtr = 0; 342 343 if (NumArrayElements <= 0) { 344 return NULL; 345 } 346 347 // Example destructor loop for "rs_font fontArr[10];" 348 // 349 // (CompoundStmt 350 // (DeclStmt "int rsIntIter") 351 // (ForStmt 352 // (BinaryOperator 'int' '=' 353 // (DeclRefExpr 'int' Var='rsIntIter') 354 // (IntegerLiteral 'int' 0)) 355 // (BinaryOperator 'int' '<' 356 // (DeclRefExpr 'int' Var='rsIntIter') 357 // (IntegerLiteral 'int' 10) 358 // NULL << CondVar >> 359 // (UnaryOperator 'int' postfix '++' 360 // (DeclRefExpr 'int' Var='rsIntIter')) 361 // (CallExpr 'void' 362 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 363 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 364 // (UnaryOperator 'rs_font *' prefix '&' 365 // (ArraySubscriptExpr 'rs_font':'rs_font' 366 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay> 367 // (DeclRefExpr 'rs_font [10]' Var='fontArr')) 368 // (DeclRefExpr 'int' Var='rsIntIter'))))))) 369 370 // Create helper variable for iterating through elements 371 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 372 clang::VarDecl *IIVD = 373 clang::VarDecl::Create(C, 374 DC, 375 Loc, 376 &II, 377 C.IntTy, 378 C.getTrivialTypeSourceInfo(C.IntTy), 379 clang::SC_None, 380 clang::SC_None); 381 clang::Decl *IID = (clang::Decl *)IIVD; 382 383 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 384 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 385 386 // Form the actual destructor loop 387 // for (Init; Cond; Inc) 388 // RSClearObjectCall; 389 390 // Init -> "rsIntIter = 0" 391 clang::DeclRefExpr *RefrsIntIter = 392 clang::DeclRefExpr::Create(C, 393 NULL, 394 Range, 395 IIVD, 396 Loc, 397 C.IntTy); 398 399 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 400 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 401 402 clang::BinaryOperator *Init = 403 new(C) clang::BinaryOperator(RefrsIntIter, 404 Int0, 405 clang::BO_Assign, 406 C.IntTy, 407 Loc); 408 409 // Cond -> "rsIntIter < NumArrayElements" 410 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 411 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 412 413 clang::BinaryOperator *Cond = 414 new(C) clang::BinaryOperator(RefrsIntIter, 415 NumArrayElementsExpr, 416 clang::BO_LT, 417 C.IntTy, 418 Loc); 419 420 // Inc -> "rsIntIter++" 421 clang::UnaryOperator *Inc = 422 new(C) clang::UnaryOperator(RefrsIntIter, 423 clang::UO_PostInc, 424 C.IntTy, 425 Loc); 426 427 // Body -> "rsClearObject(&VD[rsIntIter]);" 428 // Destructor loop operates on individual array elements 429 430 clang::Expr *RefRSArrPtr = 431 clang::ImplicitCastExpr::Create(C, 432 C.getPointerType(BaseType->getCanonicalTypeInternal()), 433 clang::CK_ArrayToPointerDecay, 434 RefRSArr, 435 NULL, 436 clang::VK_RValue); 437 438 clang::Expr *RefRSArrPtrSubscript = 439 new(C) clang::ArraySubscriptExpr(RefRSArrPtr, 440 RefrsIntIter, 441 BaseType->getCanonicalTypeInternal(), 442 Loc); 443 444 RSExportPrimitiveType::DataType DT = 445 RSExportPrimitiveType::GetRSSpecificType(BaseType); 446 447 clang::Stmt *RSClearObjectCall = NULL; 448 if (BaseType->isArrayType()) { 449 RSClearObjectCall = 450 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc); 451 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 452 RSClearObjectCall = 453 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc); 454 } else { 455 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc); 456 } 457 458 clang::ForStmt *DestructorLoop = 459 new(C) clang::ForStmt(C, 460 Init, 461 Cond, 462 NULL, // no condVar 463 Inc, 464 RSClearObjectCall, 465 Loc, 466 Loc, 467 Loc); 468 469 StmtArray[StmtCtr++] = DestructorLoop; 470 slangAssert(StmtCtr == 2); 471 472 clang::CompoundStmt *CS = 473 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 474 475 return CS; 476} 477 478static unsigned CountRSObjectTypes(const clang::Type *T) { 479 slangAssert(T); 480 unsigned RSObjectCount = 0; 481 482 if (T->isArrayType()) { 483 return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual()); 484 } 485 486 RSExportPrimitiveType::DataType DT = 487 RSExportPrimitiveType::GetRSSpecificType(T); 488 if (DT != RSExportPrimitiveType::DataTypeUnknown) { 489 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0); 490 } 491 492 if (!T->isStructureType()) { 493 return 0; 494 } 495 496 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 497 RD = RD->getDefinition(); 498 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 499 FE = RD->field_end(); 500 FI != FE; 501 FI++) { 502 const clang::FieldDecl *FD = *FI; 503 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 504 if (CountRSObjectTypes(FT)) { 505 // Sub-structs should only count once (as should arrays, etc.) 506 RSObjectCount++; 507 } 508 } 509 510 return RSObjectCount; 511} 512 513static clang::Stmt *ClearStructRSObject( 514 clang::ASTContext &C, 515 clang::DeclContext *DC, 516 clang::Expr *RefRSStruct, 517 clang::SourceRange Range, 518 clang::SourceLocation Loc) { 519 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr(); 520 521 slangAssert(!BaseType->isArrayType()); 522 523 RSExportPrimitiveType::DataType DT = 524 RSExportPrimitiveType::GetRSSpecificType(BaseType); 525 526 // Structs should show up as unknown primitive types 527 slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown); 528 529 unsigned FieldsToDestroy = CountRSObjectTypes(BaseType); 530 531 unsigned StmtCount = 0; 532 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy]; 533 for (unsigned i = 0; i < FieldsToDestroy; i++) { 534 StmtArray[i] = NULL; 535 } 536 537 // Populate StmtArray by creating a destructor for each RS object field 538 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl(); 539 RD = RD->getDefinition(); 540 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 541 FE = RD->field_end(); 542 FI != FE; 543 FI++) { 544 // We just look through all field declarations to see if we find a 545 // declaration for an RS object type (or an array of one). 546 bool IsArrayType = false; 547 clang::FieldDecl *FD = *FI; 548 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 549 const clang::Type *OrigType = FT; 550 while (FT && FT->isArrayType()) { 551 FT = FT->getArrayElementTypeNoTypeQual(); 552 IsArrayType = true; 553 } 554 555 if (RSExportPrimitiveType::IsRSObjectType(FT)) { 556 clang::DeclAccessPair FoundDecl = 557 clang::DeclAccessPair::make(FD, clang::AS_none); 558 clang::MemberExpr *RSObjectMember = 559 clang::MemberExpr::Create(C, 560 RefRSStruct, 561 false, 562 NULL, 563 Range, 564 FD, 565 FoundDecl, 566 clang::DeclarationNameInfo(), 567 NULL, 568 OrigType->getCanonicalTypeInternal()); 569 570 slangAssert(StmtCount < FieldsToDestroy); 571 572 if (IsArrayType) { 573 StmtArray[StmtCount++] = ClearArrayRSObject(C, 574 DC, 575 RSObjectMember, 576 Range, 577 Loc); 578 } else { 579 StmtArray[StmtCount++] = ClearSingleRSObject(C, 580 RSObjectMember, 581 Loc); 582 } 583 } else if (FT->isStructureType() && CountRSObjectTypes(FT)) { 584 // In this case, we have a nested struct. We may not end up filling all 585 // of the spaces in StmtArray (sub-structs should handle themselves 586 // with separate compound statements). 587 clang::DeclAccessPair FoundDecl = 588 clang::DeclAccessPair::make(FD, clang::AS_none); 589 clang::MemberExpr *RSObjectMember = 590 clang::MemberExpr::Create(C, 591 RefRSStruct, 592 false, 593 NULL, 594 Range, 595 FD, 596 FoundDecl, 597 clang::DeclarationNameInfo(), 598 NULL, 599 OrigType->getCanonicalTypeInternal()); 600 601 if (IsArrayType) { 602 StmtArray[StmtCount++] = ClearArrayRSObject(C, 603 DC, 604 RSObjectMember, 605 Range, 606 Loc); 607 } else { 608 StmtArray[StmtCount++] = ClearStructRSObject(C, 609 DC, 610 RSObjectMember, 611 Range, 612 Loc); 613 } 614 } 615 } 616 617 slangAssert(StmtCount > 0); 618 clang::CompoundStmt *CS = 619 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 620 621 delete [] StmtArray; 622 623 return CS; 624} 625 626static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C, 627 clang::Diagnostic *Diags, 628 clang::Expr *DstExpr, 629 clang::Expr *SrcExpr, 630 clang::SourceLocation Loc) { 631 const clang::Type *T = DstExpr->getType().getTypePtr(); 632 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T); 633 slangAssert((SetObjectFD != NULL) && 634 "rsSetObject doesn't cover all RS object types"); 635 636 clang::QualType SetObjectFDType = SetObjectFD->getType(); 637 clang::QualType SetObjectFDArgType[2]; 638 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 639 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 640 641 clang::Expr *RefRSSetObjectFD = 642 clang::DeclRefExpr::Create(C, 643 NULL, 644 SetObjectFD->getQualifierRange(), 645 SetObjectFD, 646 Loc, 647 SetObjectFDType); 648 649 clang::Expr *RSSetObjectFP = 650 clang::ImplicitCastExpr::Create(C, 651 C.getPointerType(SetObjectFDType), 652 clang::CK_FunctionToPointerDecay, 653 RefRSSetObjectFD, 654 NULL, 655 clang::VK_RValue); 656 657 clang::Expr *ArgList[2]; 658 ArgList[0] = new(C) clang::UnaryOperator(DstExpr, 659 clang::UO_AddrOf, 660 SetObjectFDArgType[0], 661 Loc); 662 ArgList[1] = SrcExpr; 663 664 clang::CallExpr *RSSetObjectCall = 665 new(C) clang::CallExpr(C, 666 RSSetObjectFP, 667 ArgList, 668 2, 669 SetObjectFD->getCallResultType(), 670 Loc); 671 672 return RSSetObjectCall; 673} 674 675static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 676 clang::Diagnostic *Diags, 677 clang::Expr *LHS, 678 clang::Expr *RHS, 679 clang::SourceLocation Loc); 680 681static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C, 682 clang::Diagnostic *Diags, 683 clang::Expr *DstArr, 684 clang::Expr *SrcArr, 685 clang::SourceLocation Loc) { 686 clang::DeclContext *DC = NULL; 687 clang::SourceRange Range; 688 const clang::Type *BaseType = DstArr->getType().getTypePtr(); 689 slangAssert(BaseType->isArrayType()); 690 691 int NumArrayElements = ArrayDim(BaseType); 692 // Actually extract out the base RS object type for use later 693 BaseType = BaseType->getArrayElementTypeNoTypeQual(); 694 695 clang::Stmt *StmtArray[2] = {NULL}; 696 int StmtCtr = 0; 697 698 if (NumArrayElements <= 0) { 699 return NULL; 700 } 701 702 // Create helper variable for iterating through elements 703 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 704 clang::VarDecl *IIVD = 705 clang::VarDecl::Create(C, 706 DC, 707 Loc, 708 &II, 709 C.IntTy, 710 C.getTrivialTypeSourceInfo(C.IntTy), 711 clang::SC_None, 712 clang::SC_None); 713 clang::Decl *IID = (clang::Decl *)IIVD; 714 715 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 716 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 717 718 // Form the actual loop 719 // for (Init; Cond; Inc) 720 // RSSetObjectCall; 721 722 // Init -> "rsIntIter = 0" 723 clang::DeclRefExpr *RefrsIntIter = 724 clang::DeclRefExpr::Create(C, 725 NULL, 726 Range, 727 IIVD, 728 Loc, 729 C.IntTy); 730 731 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 732 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 733 734 clang::BinaryOperator *Init = 735 new(C) clang::BinaryOperator(RefrsIntIter, 736 Int0, 737 clang::BO_Assign, 738 C.IntTy, 739 Loc); 740 741 // Cond -> "rsIntIter < NumArrayElements" 742 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 743 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 744 745 clang::BinaryOperator *Cond = 746 new(C) clang::BinaryOperator(RefrsIntIter, 747 NumArrayElementsExpr, 748 clang::BO_LT, 749 C.IntTy, 750 Loc); 751 752 // Inc -> "rsIntIter++" 753 clang::UnaryOperator *Inc = 754 new(C) clang::UnaryOperator(RefrsIntIter, 755 clang::UO_PostInc, 756 C.IntTy, 757 Loc); 758 759 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);" 760 // Loop operates on individual array elements 761 762 clang::Expr *DstArrPtr = 763 clang::ImplicitCastExpr::Create(C, 764 C.getPointerType(BaseType->getCanonicalTypeInternal()), 765 clang::CK_ArrayToPointerDecay, 766 DstArr, 767 NULL, 768 clang::VK_RValue); 769 770 clang::Expr *DstArrPtrSubscript = 771 new(C) clang::ArraySubscriptExpr(DstArrPtr, 772 RefrsIntIter, 773 BaseType->getCanonicalTypeInternal(), 774 Loc); 775 776 clang::Expr *SrcArrPtr = 777 clang::ImplicitCastExpr::Create(C, 778 C.getPointerType(BaseType->getCanonicalTypeInternal()), 779 clang::CK_ArrayToPointerDecay, 780 SrcArr, 781 NULL, 782 clang::VK_RValue); 783 784 clang::Expr *SrcArrPtrSubscript = 785 new(C) clang::ArraySubscriptExpr(SrcArrPtr, 786 RefrsIntIter, 787 BaseType->getCanonicalTypeInternal(), 788 Loc); 789 790 RSExportPrimitiveType::DataType DT = 791 RSExportPrimitiveType::GetRSSpecificType(BaseType); 792 793 clang::Stmt *RSSetObjectCall = NULL; 794 if (BaseType->isArrayType()) { 795 RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript, 796 SrcArrPtrSubscript, Loc); 797 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 798 RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript, 799 SrcArrPtrSubscript, Loc); 800 } else { 801 RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript, 802 SrcArrPtrSubscript, Loc); 803 } 804 805 clang::ForStmt *DestructorLoop = 806 new(C) clang::ForStmt(C, 807 Init, 808 Cond, 809 NULL, // no condVar 810 Inc, 811 RSSetObjectCall, 812 Loc, 813 Loc, 814 Loc); 815 816 StmtArray[StmtCtr++] = DestructorLoop; 817 slangAssert(StmtCtr == 2); 818 819 clang::CompoundStmt *CS = 820 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 821 822 return CS; 823} 824 825static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C, 826 clang::Diagnostic *Diags, 827 clang::Expr *LHS, 828 clang::Expr *RHS, 829 clang::SourceLocation Loc) { 830 clang::SourceRange Range; 831 clang::QualType QT = LHS->getType(); 832 const clang::Type *T = QT.getTypePtr(); 833 slangAssert(T->isStructureType()); 834 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T)); 835 836 // Keep an extra slot for the original copy (memcpy) 837 unsigned FieldsToSet = CountRSObjectTypes(T) + 1; 838 839 unsigned StmtCount = 0; 840 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet]; 841 for (unsigned i = 0; i < FieldsToSet; i++) { 842 StmtArray[i] = NULL; 843 } 844 845 clang::RecordDecl *RD = T->getAsStructureType()->getDecl(); 846 RD = RD->getDefinition(); 847 for (clang::RecordDecl::field_iterator FI = RD->field_begin(), 848 FE = RD->field_end(); 849 FI != FE; 850 FI++) { 851 bool IsArrayType = false; 852 clang::FieldDecl *FD = *FI; 853 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD); 854 const clang::Type *OrigType = FT; 855 856 if (!CountRSObjectTypes(FT)) { 857 // Skip to next if we don't have any viable RS object types 858 continue; 859 } 860 861 clang::DeclAccessPair FoundDecl = 862 clang::DeclAccessPair::make(FD, clang::AS_none); 863 clang::MemberExpr *DstMember = 864 clang::MemberExpr::Create(C, 865 LHS, 866 false, 867 NULL, 868 Range, 869 FD, 870 FoundDecl, 871 clang::DeclarationNameInfo(), 872 NULL, 873 OrigType->getCanonicalTypeInternal()); 874 875 clang::MemberExpr *SrcMember = 876 clang::MemberExpr::Create(C, 877 RHS, 878 false, 879 NULL, 880 Range, 881 FD, 882 FoundDecl, 883 clang::DeclarationNameInfo(), 884 NULL, 885 OrigType->getCanonicalTypeInternal()); 886 887 if (FT->isArrayType()) { 888 FT = FT->getArrayElementTypeNoTypeQual(); 889 IsArrayType = true; 890 } 891 892 RSExportPrimitiveType::DataType DT = 893 RSExportPrimitiveType::GetRSSpecificType(FT); 894 895 if (IsArrayType) { 896 Diags->Report(clang::FullSourceLoc(Loc, C.getSourceManager()), 897 Diags->getCustomDiagID(clang::Diagnostic::Error, 898 "Arrays of RS object types within structures cannot be copied")); 899 // TODO(srhines): Support setting arrays of RS objects 900 // StmtArray[StmtCount++] = 901 // CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc); 902 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) { 903 StmtArray[StmtCount++] = 904 CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc); 905 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) { 906 StmtArray[StmtCount++] = 907 CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc); 908 } else { 909 slangAssert(false); 910 } 911 } 912 913 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet); 914 915 // We still need to actually do the overall struct copy. For simplicity, 916 // we just do a straight-up assignment (which will still preserve all 917 // the proper RS object reference counts). 918 clang::BinaryOperator *CopyStruct = 919 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc); 920 StmtArray[StmtCount++] = CopyStruct; 921 922 clang::CompoundStmt *CS = 923 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc); 924 925 delete [] StmtArray; 926 927 return CS; 928} 929 930} // namespace 931 932void RSObjectRefCount::Scope::ReplaceRSObjectAssignment( 933 clang::BinaryOperator *AS, 934 clang::Diagnostic *Diags) { 935 936 clang::QualType QT = AS->getType(); 937 938 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 939 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 940 941 clang::SourceLocation Loc = AS->getExprLoc(); 942 clang::Stmt *UpdatedStmt = NULL; 943 944 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) { 945 // By definition, this is a struct assignment if we get here 946 UpdatedStmt = 947 CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc); 948 } else { 949 UpdatedStmt = 950 CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc); 951 } 952 953 ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt); 954 return; 955} 956 957void RSObjectRefCount::Scope::AppendRSObjectInit( 958 clang::Diagnostic *Diags, 959 clang::VarDecl *VD, 960 clang::DeclStmt *DS, 961 RSExportPrimitiveType::DataType DT, 962 clang::Expr *InitExpr) { 963 slangAssert(VD); 964 965 if (!InitExpr) { 966 return; 967 } 968 969 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD( 970 RSExportPrimitiveType::DataTypeRSFont)->getASTContext(); 971 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD( 972 RSExportPrimitiveType::DataTypeRSFont)->getLocation(); 973 974 if (DT == RSExportPrimitiveType::DataTypeIsStruct) { 975 // TODO(srhines): Skip struct initialization right now 976 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 977 clang::DeclRefExpr *RefRSVar = 978 clang::DeclRefExpr::Create(C, 979 NULL, 980 VD->getQualifierRange(), 981 VD, 982 Loc, 983 T->getCanonicalTypeInternal()); 984 985 clang::Stmt *RSSetObjectOps = 986 CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc); 987 988 AppendAfterStmt(C, mCS, DS, RSSetObjectOps); 989 return; 990 } 991 992 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT); 993 slangAssert((SetObjectFD != NULL) && 994 "rsSetObject doesn't cover all RS object types"); 995 996 clang::QualType SetObjectFDType = SetObjectFD->getType(); 997 clang::QualType SetObjectFDArgType[2]; 998 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType(); 999 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType(); 1000 1001 clang::Expr *RefRSSetObjectFD = 1002 clang::DeclRefExpr::Create(C, 1003 NULL, 1004 SetObjectFD->getQualifierRange(), 1005 SetObjectFD, 1006 Loc, 1007 SetObjectFDType); 1008 1009 clang::Expr *RSSetObjectFP = 1010 clang::ImplicitCastExpr::Create(C, 1011 C.getPointerType(SetObjectFDType), 1012 clang::CK_FunctionToPointerDecay, 1013 RefRSSetObjectFD, 1014 NULL, 1015 clang::VK_RValue); 1016 1017 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1018 clang::DeclRefExpr *RefRSVar = 1019 clang::DeclRefExpr::Create(C, 1020 NULL, 1021 VD->getQualifierRange(), 1022 VD, 1023 Loc, 1024 T->getCanonicalTypeInternal()); 1025 1026 clang::Expr *ArgList[2]; 1027 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar, 1028 clang::UO_AddrOf, 1029 SetObjectFDArgType[0], 1030 Loc); 1031 ArgList[1] = InitExpr; 1032 1033 clang::CallExpr *RSSetObjectCall = 1034 new(C) clang::CallExpr(C, 1035 RSSetObjectFP, 1036 ArgList, 1037 2, 1038 SetObjectFD->getCallResultType(), 1039 Loc); 1040 1041 AppendAfterStmt(C, mCS, DS, RSSetObjectCall); 1042 1043 return; 1044} 1045 1046void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 1047 std::list<clang::Stmt*> RSClearObjectCalls; 1048 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 1049 E = mRSO.end(); 1050 I != E; 1051 I++) { 1052 clang::Stmt *S = ClearRSObject(*I); 1053 if (S) { 1054 RSClearObjectCalls.push_back(S); 1055 } 1056 } 1057 if (RSClearObjectCalls.size() > 0) { 1058 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls); 1059 DV.Visit(mCS); 1060 } 1061 return; 1062} 1063 1064clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) { 1065 slangAssert(VD); 1066 clang::ASTContext &C = VD->getASTContext(); 1067 clang::DeclContext *DC = VD->getDeclContext(); 1068 clang::SourceRange Range = VD->getQualifierRange(); 1069 clang::SourceLocation Loc = VD->getLocation(); 1070 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1071 1072 // Reference expr to target RS object variable 1073 clang::DeclRefExpr *RefRSVar = 1074 clang::DeclRefExpr::Create(C, 1075 NULL, 1076 Range, 1077 VD, 1078 Loc, 1079 T->getCanonicalTypeInternal()); 1080 1081 if (T->isArrayType()) { 1082 return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc); 1083 } 1084 1085 RSExportPrimitiveType::DataType DT = 1086 RSExportPrimitiveType::GetRSSpecificType(T); 1087 1088 if (DT == RSExportPrimitiveType::DataTypeUnknown || 1089 DT == RSExportPrimitiveType::DataTypeIsStruct) { 1090 return ClearStructRSObject(C, DC, RefRSVar, Range, Loc); 1091 } 1092 1093 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) && 1094 "Should be RS object"); 1095 1096 return ClearSingleRSObject(C, RefRSVar, Loc); 1097} 1098 1099bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD, 1100 RSExportPrimitiveType::DataType *DT, 1101 clang::Expr **InitExpr) { 1102 slangAssert(VD && DT && InitExpr); 1103 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 1104 1105 // Loop through array types to get to base type 1106 while (T && T->isArrayType()) { 1107 T = T->getArrayElementTypeNoTypeQual(); 1108 } 1109 1110 bool DataTypeIsStructWithRSObject = false; 1111 *DT = RSExportPrimitiveType::GetRSSpecificType(T); 1112 1113 if (*DT == RSExportPrimitiveType::DataTypeUnknown) { 1114 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) { 1115 *DT = RSExportPrimitiveType::DataTypeIsStruct; 1116 DataTypeIsStructWithRSObject = true; 1117 } else { 1118 return false; 1119 } 1120 } 1121 1122 bool DataTypeIsRSObject = false; 1123 if (DataTypeIsStructWithRSObject) { 1124 DataTypeIsRSObject = true; 1125 } else { 1126 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT); 1127 } 1128 *InitExpr = VD->getInit(); 1129 1130 if (!DataTypeIsRSObject && *InitExpr) { 1131 // If we already have an initializer for a matrix type, we are done. 1132 return DataTypeIsRSObject; 1133 } 1134 1135 clang::Expr *ZeroInitializer = 1136 CreateZeroInitializerForRSSpecificType(*DT, 1137 VD->getASTContext(), 1138 VD->getLocation()); 1139 1140 if (ZeroInitializer) { 1141 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 1142 VD->setInit(ZeroInitializer); 1143 } 1144 1145 return DataTypeIsRSObject; 1146} 1147 1148clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 1149 RSExportPrimitiveType::DataType DT, 1150 clang::ASTContext &C, 1151 const clang::SourceLocation &Loc) { 1152 clang::Expr *Res = NULL; 1153 switch (DT) { 1154 case RSExportPrimitiveType::DataTypeIsStruct: 1155 case RSExportPrimitiveType::DataTypeRSElement: 1156 case RSExportPrimitiveType::DataTypeRSType: 1157 case RSExportPrimitiveType::DataTypeRSAllocation: 1158 case RSExportPrimitiveType::DataTypeRSSampler: 1159 case RSExportPrimitiveType::DataTypeRSScript: 1160 case RSExportPrimitiveType::DataTypeRSMesh: 1161 case RSExportPrimitiveType::DataTypeRSProgramFragment: 1162 case RSExportPrimitiveType::DataTypeRSProgramVertex: 1163 case RSExportPrimitiveType::DataTypeRSProgramRaster: 1164 case RSExportPrimitiveType::DataTypeRSProgramStore: 1165 case RSExportPrimitiveType::DataTypeRSFont: { 1166 // (ImplicitCastExpr 'nullptr_t' 1167 // (IntegerLiteral 0))) 1168 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 1169 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 1170 clang::Expr *CastToNull = 1171 clang::ImplicitCastExpr::Create(C, 1172 C.NullPtrTy, 1173 clang::CK_IntegralToPointer, 1174 Int0, 1175 NULL, 1176 clang::VK_RValue); 1177 1178 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc); 1179 break; 1180 } 1181 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 1182 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 1183 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 1184 // RS matrix is not completely an RS object. They hold data by themselves. 1185 // (InitListExpr rs_matrix2x2 1186 // (InitListExpr float[4] 1187 // (FloatingLiteral 0) 1188 // (FloatingLiteral 0) 1189 // (FloatingLiteral 0) 1190 // (FloatingLiteral 0))) 1191 clang::QualType FloatTy = C.FloatTy; 1192 // Constructor sets value to 0.0f by default 1193 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 1194 clang::FloatingLiteral *Float0Val = 1195 clang::FloatingLiteral::Create(C, 1196 Val, 1197 /* isExact = */true, 1198 FloatTy, 1199 Loc); 1200 1201 unsigned N = 0; 1202 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 1203 N = 2; 1204 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 1205 N = 3; 1206 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 1207 N = 4; 1208 1209 // Directly allocate 16 elements instead of dynamically allocate N*N 1210 clang::Expr *InitVals[16]; 1211 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++) 1212 InitVals[i] = Float0Val; 1213 clang::Expr *InitExpr = 1214 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc); 1215 InitExpr->setType(C.getConstantArrayType(FloatTy, 1216 llvm::APInt(32, 4), 1217 clang::ArrayType::Normal, 1218 /* EltTypeQuals = */0)); 1219 1220 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc); 1221 break; 1222 } 1223 case RSExportPrimitiveType::DataTypeUnknown: 1224 case RSExportPrimitiveType::DataTypeFloat16: 1225 case RSExportPrimitiveType::DataTypeFloat32: 1226 case RSExportPrimitiveType::DataTypeFloat64: 1227 case RSExportPrimitiveType::DataTypeSigned8: 1228 case RSExportPrimitiveType::DataTypeSigned16: 1229 case RSExportPrimitiveType::DataTypeSigned32: 1230 case RSExportPrimitiveType::DataTypeSigned64: 1231 case RSExportPrimitiveType::DataTypeUnsigned8: 1232 case RSExportPrimitiveType::DataTypeUnsigned16: 1233 case RSExportPrimitiveType::DataTypeUnsigned32: 1234 case RSExportPrimitiveType::DataTypeUnsigned64: 1235 case RSExportPrimitiveType::DataTypeBoolean: 1236 case RSExportPrimitiveType::DataTypeUnsigned565: 1237 case RSExportPrimitiveType::DataTypeUnsigned5551: 1238 case RSExportPrimitiveType::DataTypeUnsigned4444: 1239 case RSExportPrimitiveType::DataTypeMax: { 1240 slangAssert(false && "Not RS object type!"); 1241 } 1242 // No default case will enable compiler detecting the missing cases 1243 } 1244 1245 return Res; 1246} 1247 1248void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 1249 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 1250 I != E; 1251 I++) { 1252 clang::Decl *D = *I; 1253 if (D->getKind() == clang::Decl::Var) { 1254 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 1255 RSExportPrimitiveType::DataType DT = 1256 RSExportPrimitiveType::DataTypeUnknown; 1257 clang::Expr *InitExpr = NULL; 1258 if (InitializeRSObject(VD, &DT, &InitExpr)) { 1259 getCurrentScope()->addRSObject(VD); 1260 getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr); 1261 } 1262 } 1263 } 1264 return; 1265} 1266 1267void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 1268 if (!CS->body_empty()) { 1269 // Push a new scope 1270 Scope *S = new Scope(CS); 1271 mScopeStack.push(S); 1272 1273 VisitStmt(CS); 1274 1275 // Destroy the scope 1276 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!"); 1277 S->InsertLocalVarDestructors(); 1278 mScopeStack.pop(); 1279 delete S; 1280 } 1281 return; 1282} 1283 1284void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 1285 clang::QualType QT = AS->getType(); 1286 1287 if (CountRSObjectTypes(QT.getTypePtr())) { 1288 getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags); 1289 } 1290 1291 return; 1292} 1293 1294void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 1295 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 1296 I != E; 1297 I++) { 1298 if (clang::Stmt *Child = *I) { 1299 Visit(Child); 1300 } 1301 } 1302 return; 1303} 1304 1305} // namespace slang 1306