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