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