slang_rs_object_ref_count.cpp revision a858cb6f3d9223d65bf73e1230c6324ded4095f6
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_rs.h" 28#include "slang_rs_export_type.h" 29 30namespace slang { 31 32clang::FunctionDecl *RSObjectRefCount::Scope:: 33 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType - 34 RSExportPrimitiveType::FirstRSObjectType + 1]; 35clang::FunctionDecl *RSObjectRefCount::Scope:: 36 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType - 37 RSExportPrimitiveType::FirstRSObjectType + 1]; 38 39void RSObjectRefCount::Scope::GetRSRefCountingFunctions( 40 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 assert((FD->getNumParams() == 2) && 61 "Invalid rsSetObject function prototype (# params)"); 62 RSObjectFD = RSSetObjectFD; 63 } else if (FD->getName() == "rsClearObject") { 64 assert((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 assert(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 assert(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 145// This class visits a compound statement and inserts the StmtList containing 146// destructors in proper locations. This includes inserting them before any 147// return statement in any sub-block, at the end of the logical enclosing 148// scope (compound statement), and/or before any break/continue statement that 149// would resume outside the declared scope. We will not handle the case for 150// goto statements that leave a local scope. 151// TODO(srhines): Make this work properly for break/continue. 152class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> { 153 private: 154 clang::ASTContext &mC; 155 std::list<clang::Stmt*> &mStmtList; 156 bool mTopLevel; 157 public: 158 DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList); 159 void VisitStmt(clang::Stmt *S); 160 void VisitCompoundStmt(clang::CompoundStmt *CS); 161}; 162 163DestructorVisitor::DestructorVisitor(clang::ASTContext &C, 164 std::list<clang::Stmt*> &StmtList) 165 : mC(C), 166 mStmtList(StmtList), 167 mTopLevel(true) { 168 return; 169} 170 171void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) { 172 if (!CS->body_empty()) { 173 AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel); 174 mTopLevel = false; 175 VisitStmt(CS); 176 } 177 return; 178} 179 180void DestructorVisitor::VisitStmt(clang::Stmt *S) { 181 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 182 I != E; 183 I++) { 184 if (clang::Stmt *Child = *I) { 185 Visit(Child); 186 } 187 } 188 return; 189} 190 191static int ArrayDim(clang::VarDecl *VD) { 192 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 193 194 if (!T || !T->isArrayType()) { 195 return 0; 196 } 197 198 const clang::ConstantArrayType *CAT = 199 static_cast<const clang::ConstantArrayType *>(T); 200 return static_cast<int>(CAT->getSize().getSExtValue()); 201} 202 203static clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD, 204 const clang::Type *T, 205 clang::FunctionDecl *ClearObjectFD) { 206 clang::ASTContext &C = VD->getASTContext(); 207 clang::SourceRange Range = VD->getQualifierRange(); 208 clang::SourceLocation Loc = Range.getEnd(); 209 210 clang::Stmt *StmtArray[2] = {NULL}; 211 int StmtCtr = 0; 212 213 int NumArrayElements = ArrayDim(VD); 214 if (NumArrayElements <= 0) { 215 return NULL; 216 } 217 218 // Example destructor loop for "rs_font fontArr[10];" 219 // 220 // (CompoundStmt 221 // (DeclStmt "int rsIntIter") 222 // (ForStmt 223 // (BinaryOperator 'int' '=' 224 // (DeclRefExpr 'int' Var='rsIntIter') 225 // (IntegerLiteral 'int' 0)) 226 // (BinaryOperator 'int' '<' 227 // (DeclRefExpr 'int' Var='rsIntIter') 228 // (IntegerLiteral 'int' 10) 229 // NULL << CondVar >> 230 // (UnaryOperator 'int' postfix '++' 231 // (DeclRefExpr 'int' Var='rsIntIter')) 232 // (CallExpr 'void' 233 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 234 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 235 // (UnaryOperator 'rs_font *' prefix '&' 236 // (ArraySubscriptExpr 'rs_font':'rs_font' 237 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay> 238 // (DeclRefExpr 'rs_font [10]' Var='fontArr')) 239 // (DeclRefExpr 'int' Var='rsIntIter'))))))) 240 241 // Create helper variable for iterating through elements 242 clang::IdentifierInfo& II = C.Idents.get("rsIntIter"); 243 clang::VarDecl *IIVD = 244 clang::VarDecl::Create(C, 245 VD->getDeclContext(), 246 Loc, 247 &II, 248 C.IntTy, 249 C.getTrivialTypeSourceInfo(C.IntTy), 250 clang::SC_None, 251 clang::SC_None); 252 clang::Decl *IID = (clang::Decl *)IIVD; 253 254 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1); 255 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc); 256 257 // Form the actual destructor loop 258 // for (Init; Cond; Inc) 259 // RSClearObjectCall; 260 261 // Init -> "rsIntIter = 0" 262 clang::DeclRefExpr *RefrsIntIter = 263 clang::DeclRefExpr::Create(C, 264 NULL, 265 Range, 266 IIVD, 267 Loc, 268 C.IntTy); 269 270 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, 271 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc); 272 273 clang::BinaryOperator *Init = 274 new(C) clang::BinaryOperator(RefrsIntIter, 275 Int0, 276 clang::BO_Assign, 277 C.IntTy, 278 Loc); 279 280 // Cond -> "rsIntIter < NumArrayElements" 281 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C, 282 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc); 283 284 clang::BinaryOperator *Cond = 285 new(C) clang::BinaryOperator(RefrsIntIter, 286 NumArrayElementsExpr, 287 clang::BO_LT, 288 C.IntTy, 289 Loc); 290 291 // Inc -> "rsIntIter++" 292 clang::UnaryOperator *Inc = 293 new(C) clang::UnaryOperator(RefrsIntIter, 294 clang::UO_PostInc, 295 C.IntTy, 296 Loc); 297 298 // Body -> "rsClearObject(&VD[rsIntIter]);" 299 // Destructor loop operates on individual array elements 300 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 301 clang::QualType ClearObjectFDArgType = 302 ClearObjectFD->getParamDecl(0)->getOriginalType(); 303 304 const clang::Type *VT = RSExportType::GetTypeOfDecl(VD); 305 clang::DeclRefExpr *RefRSVar = 306 clang::DeclRefExpr::Create(C, 307 NULL, 308 Range, 309 VD, 310 Loc, 311 VT->getCanonicalTypeInternal()); 312 313 clang::Expr *RefRSVarPtr = 314 clang::ImplicitCastExpr::Create(C, 315 C.getPointerType(T->getCanonicalTypeInternal()), 316 clang::CK_ArrayToPointerDecay, 317 RefRSVar, 318 NULL, 319 clang::VK_RValue); 320 321 clang::Expr *RefRSVarPtrSubscript = 322 new(C) clang::ArraySubscriptExpr(RefRSVarPtr, 323 RefrsIntIter, 324 T->getCanonicalTypeInternal(), 325 VD->getLocation()); 326 327 clang::Expr *AddrRefRSVarPtrSubscript = 328 new(C) clang::UnaryOperator(RefRSVarPtrSubscript, 329 clang::UO_AddrOf, 330 ClearObjectFDArgType, 331 VD->getLocation()); 332 333 clang::Expr *RefRSClearObjectFD = 334 clang::DeclRefExpr::Create(C, 335 NULL, 336 Range, 337 ClearObjectFD, 338 Loc, 339 ClearObjectFDType); 340 341 clang::Expr *RSClearObjectFP = 342 clang::ImplicitCastExpr::Create(C, 343 C.getPointerType(ClearObjectFDType), 344 clang::CK_FunctionToPointerDecay, 345 RefRSClearObjectFD, 346 NULL, 347 clang::VK_RValue); 348 349 clang::CallExpr *RSClearObjectCall = 350 new(C) clang::CallExpr(C, 351 RSClearObjectFP, 352 &AddrRefRSVarPtrSubscript, 353 1, 354 ClearObjectFD->getCallResultType(), 355 Loc); 356 357 clang::ForStmt *DestructorLoop = 358 new(C) clang::ForStmt(C, 359 Init, 360 Cond, 361 NULL, // no condVar 362 Inc, 363 RSClearObjectCall, 364 Loc, 365 Loc, 366 Loc); 367 368 StmtArray[StmtCtr++] = DestructorLoop; 369 assert(StmtCtr == 2); 370 371 clang::CompoundStmt *CS = 372 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc); 373 374 return CS; 375} 376 377} // namespace 378 379void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 380 std::list<clang::Stmt*> RSClearObjectCalls; 381 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 382 E = mRSO.end(); 383 I != E; 384 I++) { 385 clang::Stmt *S = ClearRSObject(*I); 386 if (S) { 387 RSClearObjectCalls.push_back(S); 388 } 389 } 390 if (RSClearObjectCalls.size() > 0) { 391 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls); 392 DV.Visit(mCS); 393 } 394 return; 395} 396 397clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) { 398 bool IsArrayType = false; 399 clang::ASTContext &C = VD->getASTContext(); 400 clang::SourceLocation Loc = VD->getLocation(); 401 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 402 403 // Loop through array types to get to base type 404 while (T && T->isArrayType()) { 405 T = T->getArrayElementTypeNoTypeQual(); 406 IsArrayType = true; 407 } 408 409 RSExportPrimitiveType::DataType DT = 410 RSExportPrimitiveType::GetRSSpecificType(T); 411 412 assert((RSExportPrimitiveType::IsRSObjectType(DT)) && 413 "Should be RS object"); 414 415 // Find the rsClearObject() for VD of RS object type DT 416 clang::FunctionDecl *ClearObjectFD = 417 RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)]; 418 assert((ClearObjectFD != NULL) && 419 "rsClearObject doesn't cover all RS object types"); 420 421 if (IsArrayType) { 422 return ClearArrayRSObject(VD, T, ClearObjectFD); 423 } 424 425 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 426 clang::QualType ClearObjectFDArgType = 427 ClearObjectFD->getParamDecl(0)->getOriginalType(); 428 429 // Example destructor for "rs_font localFont;" 430 // 431 // (CallExpr 'void' 432 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 433 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 434 // (UnaryOperator 'rs_font *' prefix '&' 435 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont'))) 436 437 // Reference expr to target RS object variable 438 clang::DeclRefExpr *RefRSVar = 439 clang::DeclRefExpr::Create(C, 440 NULL, 441 VD->getQualifierRange(), 442 VD, 443 Loc, 444 T->getCanonicalTypeInternal()); 445 446 // Get address of RSObject in VD 447 clang::Expr *AddrRefRSVar = 448 new(C) clang::UnaryOperator(RefRSVar, 449 clang::UO_AddrOf, 450 ClearObjectFDArgType, 451 Loc); 452 453 clang::Expr *RefRSClearObjectFD = 454 clang::DeclRefExpr::Create(C, 455 NULL, 456 ClearObjectFD->getQualifierRange(), 457 ClearObjectFD, 458 ClearObjectFD->getLocation(), 459 ClearObjectFDType); 460 461 clang::Expr *RSClearObjectFP = 462 clang::ImplicitCastExpr::Create(C, 463 C.getPointerType(ClearObjectFDType), 464 clang::CK_FunctionToPointerDecay, 465 RefRSClearObjectFD, 466 NULL, 467 clang::VK_RValue); 468 469 clang::CallExpr *RSClearObjectCall = 470 new(C) clang::CallExpr(C, 471 RSClearObjectFP, 472 &AddrRefRSVar, 473 1, 474 ClearObjectFD->getCallResultType(), 475 clang::SourceLocation()); 476 477 return RSClearObjectCall; 478} 479 480bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) { 481 bool IsArrayType = false; 482 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 483 484 // Loop through array types to get to base type 485 while (T && T->isArrayType()) { 486 T = T->getArrayElementTypeNoTypeQual(); 487 IsArrayType = true; 488 } 489 490 RSExportPrimitiveType::DataType DT = 491 RSExportPrimitiveType::GetRSSpecificType(T); 492 493 if (DT == RSExportPrimitiveType::DataTypeUnknown) { 494 return false; 495 } 496 497 if (VD->hasInit()) { 498 // TODO(srhines): Update the reference count of RS object in initializer. 499 // This can potentially be done as part of the assignment pass. 500 } else { 501 clang::Expr *ZeroInitializer = 502 CreateZeroInitializerForRSSpecificType(DT, 503 VD->getASTContext(), 504 VD->getLocation()); 505 506 if (ZeroInitializer) { 507 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 508 VD->setInit(ZeroInitializer); 509 } 510 } 511 512 return RSExportPrimitiveType::IsRSObjectType(DT); 513} 514 515clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 516 RSExportPrimitiveType::DataType DT, 517 clang::ASTContext &C, 518 const clang::SourceLocation &Loc) { 519 clang::Expr *Res = NULL; 520 switch (DT) { 521 case RSExportPrimitiveType::DataTypeRSElement: 522 case RSExportPrimitiveType::DataTypeRSType: 523 case RSExportPrimitiveType::DataTypeRSAllocation: 524 case RSExportPrimitiveType::DataTypeRSSampler: 525 case RSExportPrimitiveType::DataTypeRSScript: 526 case RSExportPrimitiveType::DataTypeRSMesh: 527 case RSExportPrimitiveType::DataTypeRSProgramFragment: 528 case RSExportPrimitiveType::DataTypeRSProgramVertex: 529 case RSExportPrimitiveType::DataTypeRSProgramRaster: 530 case RSExportPrimitiveType::DataTypeRSProgramStore: 531 case RSExportPrimitiveType::DataTypeRSFont: { 532 // (ImplicitCastExpr 'nullptr_t' 533 // (IntegerLiteral 0))) 534 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 535 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 536 clang::Expr *CastToNull = 537 clang::ImplicitCastExpr::Create(C, 538 C.NullPtrTy, 539 clang::CK_IntegralToPointer, 540 Int0, 541 NULL, 542 clang::VK_RValue); 543 544 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc); 545 break; 546 } 547 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 548 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 549 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 550 // RS matrix is not completely an RS object. They hold data by themselves. 551 // (InitListExpr rs_matrix2x2 552 // (InitListExpr float[4] 553 // (FloatingLiteral 0) 554 // (FloatingLiteral 0) 555 // (FloatingLiteral 0) 556 // (FloatingLiteral 0))) 557 clang::QualType FloatTy = C.FloatTy; 558 // Constructor sets value to 0.0f by default 559 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 560 clang::FloatingLiteral *Float0Val = 561 clang::FloatingLiteral::Create(C, 562 Val, 563 /* isExact = */true, 564 FloatTy, 565 Loc); 566 567 unsigned N = 0; 568 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 569 N = 2; 570 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 571 N = 3; 572 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 573 N = 4; 574 575 // Directly allocate 16 elements instead of dynamically allocate N*N 576 clang::Expr *InitVals[16]; 577 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++) 578 InitVals[i] = Float0Val; 579 clang::Expr *InitExpr = 580 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc); 581 InitExpr->setType(C.getConstantArrayType(FloatTy, 582 llvm::APInt(32, 4), 583 clang::ArrayType::Normal, 584 /* EltTypeQuals = */0)); 585 586 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc); 587 break; 588 } 589 case RSExportPrimitiveType::DataTypeUnknown: 590 case RSExportPrimitiveType::DataTypeFloat16: 591 case RSExportPrimitiveType::DataTypeFloat32: 592 case RSExportPrimitiveType::DataTypeFloat64: 593 case RSExportPrimitiveType::DataTypeSigned8: 594 case RSExportPrimitiveType::DataTypeSigned16: 595 case RSExportPrimitiveType::DataTypeSigned32: 596 case RSExportPrimitiveType::DataTypeSigned64: 597 case RSExportPrimitiveType::DataTypeUnsigned8: 598 case RSExportPrimitiveType::DataTypeUnsigned16: 599 case RSExportPrimitiveType::DataTypeUnsigned32: 600 case RSExportPrimitiveType::DataTypeUnsigned64: 601 case RSExportPrimitiveType::DataTypeBoolean: 602 case RSExportPrimitiveType::DataTypeUnsigned565: 603 case RSExportPrimitiveType::DataTypeUnsigned5551: 604 case RSExportPrimitiveType::DataTypeUnsigned4444: 605 case RSExportPrimitiveType::DataTypeMax: { 606 assert(false && "Not RS object type!"); 607 } 608 // No default case will enable compiler detecting the missing cases 609 } 610 611 return Res; 612} 613 614void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 615 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 616 I != E; 617 I++) { 618 clang::Decl *D = *I; 619 if (D->getKind() == clang::Decl::Var) { 620 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 621 if (InitializeRSObject(VD)) 622 getCurrentScope()->addRSObject(VD); 623 } 624 } 625 return; 626} 627 628void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 629 if (!CS->body_empty()) { 630 // Push a new scope 631 Scope *S = new Scope(CS); 632 mScopeStack.push(S); 633 634 VisitStmt(CS); 635 636 // Destroy the scope 637 // TODO(srhines): Update reference count of the RS object refenced by 638 // getCurrentScope(). 639 assert((getCurrentScope() == S) && "Corrupted scope stack!"); 640 S->InsertLocalVarDestructors(); 641 mScopeStack.pop(); 642 delete S; 643 } 644 return; 645} 646 647void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 648 // TODO(srhines): Update reference count 649 return; 650} 651 652void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 653 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 654 I != E; 655 I++) { 656 if (clang::Stmt *Child = *I) { 657 Visit(Child); 658 } 659 } 660 return; 661} 662 663} // namespace slang 664