slang_rs_object_ref_count.cpp revision 1bdd4978caabcdc9489bdcb7f1cd6087340699e8
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 "clang/AST/DeclGroup.h" 20#include "clang/AST/Expr.h" 21#include "clang/AST/OperationKinds.h" 22#include "clang/AST/Stmt.h" 23#include "clang/AST/StmtVisitor.h" 24 25#include "slang_rs.h" 26#include "slang_rs_export_type.h" 27 28using namespace slang; 29 30clang::FunctionDecl *RSObjectRefCount::Scope:: 31 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType - 32 RSExportPrimitiveType::FirstRSObjectType + 1]; 33clang::FunctionDecl *RSObjectRefCount::Scope:: 34 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType - 35 RSExportPrimitiveType::FirstRSObjectType + 1]; 36 37void RSObjectRefCount::Scope::GetRSRefCountingFunctions( 38 clang::ASTContext &C) { 39 for (unsigned i = 0; 40 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*)); 41 i++) { 42 RSSetObjectFD[i] = NULL; 43 RSClearObjectFD[i] = NULL; 44 } 45 46 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl(); 47 48 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(), 49 E = TUDecl->decls_end(); I != E; I++) { 50 if ((I->getKind() >= clang::Decl::firstFunction) && 51 (I->getKind() <= clang::Decl::lastFunction)) { 52 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I); 53 54 // points to RSSetObjectFD or RSClearObjectFD 55 clang::FunctionDecl **RSObjectFD; 56 57 if (FD->getName() == "rsSetObject") { 58 assert((FD->getNumParams() == 2) && 59 "Invalid rsSetObject function prototype (# params)"); 60 RSObjectFD = RSSetObjectFD; 61 } else if (FD->getName() == "rsClearObject") { 62 assert((FD->getNumParams() == 1) && 63 "Invalid rsClearObject function prototype (# params)"); 64 RSObjectFD = RSClearObjectFD; 65 } 66 else { 67 continue; 68 } 69 70 const clang::ParmVarDecl *PVD = FD->getParamDecl(0); 71 clang::QualType PVT = PVD->getOriginalType(); 72 // The first parameter must be a pointer like rs_allocation* 73 assert(PVT->isPointerType() && 74 "Invalid rs{Set,Clear}Object function prototype (pointer param)"); 75 76 // The rs object type passed to the FD 77 clang::QualType RST = PVT->getPointeeType(); 78 RSExportPrimitiveType::DataType DT = 79 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr()); 80 assert(RSExportPrimitiveType::IsRSObjectType(DT) 81 && "must be RS object type"); 82 83 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD; 84 } 85 } 86} 87 88void RSObjectRefCount::Scope::AppendToCompoundStatement( 89 clang::ASTContext& C, std::list<clang::Expr*> &ExprList) { 90 // Destructor code will be inserted before any return statement. 91 // Any subsequent statements in the compound statement are then placed 92 // after our new code. 93 // TODO: This should also handle the case of goto/break/continue. 94 clang::CompoundStmt::body_iterator bI = mCS->body_begin(); 95 clang::CompoundStmt::body_iterator bE = mCS->body_end(); 96 97 unsigned OldStmtCount = 0; 98 for ( ; bI != bE; bI++) { 99 OldStmtCount++; 100 } 101 102 unsigned NewExprCount = ExprList.size(); 103 104 clang::Stmt **StmtList; 105 StmtList = new clang::Stmt*[OldStmtCount+NewExprCount]; 106 107 unsigned UpdatedStmtCount = 0; 108 for (bI = mCS->body_begin(); bI != bE; bI++) { 109 if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) { 110 break; 111 } 112 StmtList[UpdatedStmtCount++] = *bI; 113 } 114 115 std::list<clang::Expr*>::const_iterator E = ExprList.end(); 116 for (std::list<clang::Expr*>::const_iterator I = ExprList.begin(), 117 E = ExprList.end(); 118 I != E; 119 I++) { 120 StmtList[UpdatedStmtCount++] = *I; 121 } 122 123 // Pick up anything left over after a return statement 124 for ( ; bI != bE; bI++) { 125 StmtList[UpdatedStmtCount++] = *bI; 126 } 127 128 mCS->setStmts(C, StmtList, UpdatedStmtCount); 129 assert(UpdatedStmtCount == (OldStmtCount + NewExprCount)); 130 131 delete [] StmtList; 132 133 return; 134} 135 136void RSObjectRefCount::Scope::InsertLocalVarDestructors() { 137 std::list<clang::Expr*> RSClearObjectCalls; 138 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(), 139 E = mRSO.end(); 140 I != E; 141 I++) { 142 clang::Expr *E = ClearRSObject(*I); 143 if (E) { 144 RSClearObjectCalls.push_back(E); 145 } 146 } 147 if (RSClearObjectCalls.size() > 0) { 148 clang::ASTContext &C = (*mRSO.begin())->getASTContext(); 149 AppendToCompoundStatement(C, RSClearObjectCalls); 150 // TODO: This should also be extended to append destructors to any 151 // further nested scope (we need another visitor here from within the 152 // current compound statement in case they call return/goto). 153 } 154 return; 155} 156 157clang::Expr *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) { 158 clang::ASTContext &C = VD->getASTContext(); 159 clang::SourceLocation Loc = VD->getLocation(); 160 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 161 RSExportPrimitiveType::DataType DT = 162 RSExportPrimitiveType::GetRSSpecificType(T); 163 164 assert((RSExportPrimitiveType::IsRSObjectType(DT)) && 165 "Should be RS object"); 166 167 // Find the rsClearObject() for VD of RS object type DT 168 clang::FunctionDecl *ClearObjectFD = 169 RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)]; 170 assert((ClearObjectFD != NULL) && 171 "rsClearObject doesn't cover all RS object types"); 172 173 clang::QualType ClearObjectFDType = ClearObjectFD->getType(); 174 clang::QualType ClearObjectFDArgType = 175 ClearObjectFD->getParamDecl(0)->getOriginalType(); 176 177 // We generate a call to rsClearObject passing &VD as the parameter 178 // (CallExpr 'void' 179 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay> 180 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject')) 181 // (UnaryOperator 'rs_font *' prefix '&' 182 // (DeclRefExpr 'rs_font':'rs_font' Var='[var name]'))) 183 184 // Reference expr to target RS object variable 185 clang::DeclRefExpr *RefRSVar = 186 clang::DeclRefExpr::Create(C, 187 NULL, 188 VD->getQualifierRange(), 189 VD, 190 Loc, 191 T->getCanonicalTypeInternal(), 192 NULL); 193 194 // Get address of RSObject in VD 195 clang::Expr *AddrRefRSVar = 196 new (C) clang::UnaryOperator(RefRSVar, 197 clang::UO_AddrOf, 198 ClearObjectFDArgType, 199 Loc); 200 201 clang::Expr *RefRSClearObjectFD = 202 clang::DeclRefExpr::Create(C, 203 NULL, 204 ClearObjectFD->getQualifierRange(), 205 ClearObjectFD, 206 ClearObjectFD->getLocation(), 207 ClearObjectFDType, 208 NULL); 209 210 clang::Expr *RSClearObjectFP = 211 clang::ImplicitCastExpr::Create(C, 212 C.getPointerType(ClearObjectFDType), 213 clang::CK_FunctionToPointerDecay, 214 RefRSClearObjectFD, 215 NULL, 216 clang::VK_RValue); 217 218 clang::CallExpr *RSClearObjectCall = 219 new (C) clang::CallExpr(C, 220 RSClearObjectFP, 221 &AddrRefRSVar, 222 1, 223 ClearObjectFD->getCallResultType(), 224 clang::SourceLocation()); 225 226 return RSClearObjectCall; 227} 228 229bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) { 230 const clang::Type *T = RSExportType::GetTypeOfDecl(VD); 231 RSExportPrimitiveType::DataType DT = 232 RSExportPrimitiveType::GetRSSpecificType(T); 233 234 if (DT == RSExportPrimitiveType::DataTypeUnknown) 235 return false; 236 237 if (VD->hasInit()) { 238 // TODO: Update the reference count of RS object in initializer. 239 // This can potentially be done as part of the assignment pass. 240 } else { 241 clang::Expr *ZeroInitializer = 242 CreateZeroInitializerForRSSpecificType(DT, 243 VD->getASTContext(), 244 VD->getLocation()); 245 246 if (ZeroInitializer) { 247 ZeroInitializer->setType(T->getCanonicalTypeInternal()); 248 VD->setInit(ZeroInitializer); 249 } 250 } 251 252 return RSExportPrimitiveType::IsRSObjectType(DT); 253} 254 255clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType( 256 RSExportPrimitiveType::DataType DT, 257 clang::ASTContext &C, 258 const clang::SourceLocation &Loc) { 259 clang::Expr *Res = NULL; 260 switch (DT) { 261 case RSExportPrimitiveType::DataTypeRSElement: 262 case RSExportPrimitiveType::DataTypeRSType: 263 case RSExportPrimitiveType::DataTypeRSAllocation: 264 case RSExportPrimitiveType::DataTypeRSSampler: 265 case RSExportPrimitiveType::DataTypeRSScript: 266 case RSExportPrimitiveType::DataTypeRSMesh: 267 case RSExportPrimitiveType::DataTypeRSProgramFragment: 268 case RSExportPrimitiveType::DataTypeRSProgramVertex: 269 case RSExportPrimitiveType::DataTypeRSProgramRaster: 270 case RSExportPrimitiveType::DataTypeRSProgramStore: 271 case RSExportPrimitiveType::DataTypeRSFont: { 272 // (ImplicitCastExpr 'nullptr_t' 273 // (IntegerLiteral 0))) 274 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0); 275 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc); 276 clang::Expr *CastToNull = 277 clang::ImplicitCastExpr::Create(C, 278 C.NullPtrTy, 279 clang::CK_IntegralToPointer, 280 Int0, 281 NULL, 282 clang::VK_RValue); 283 284 Res = new (C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc); 285 break; 286 } 287 case RSExportPrimitiveType::DataTypeRSMatrix2x2: 288 case RSExportPrimitiveType::DataTypeRSMatrix3x3: 289 case RSExportPrimitiveType::DataTypeRSMatrix4x4: { 290 // RS matrix is not completely an RS object. They hold data by themselves. 291 // (InitListExpr rs_matrix2x2 292 // (InitListExpr float[4] 293 // (FloatingLiteral 0) 294 // (FloatingLiteral 0) 295 // (FloatingLiteral 0) 296 // (FloatingLiteral 0))) 297 clang::QualType FloatTy = C.FloatTy; 298 // Constructor sets value to 0.0f by default 299 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy)); 300 clang::FloatingLiteral *Float0Val = 301 clang::FloatingLiteral::Create(C, 302 Val, 303 /* isExact = */true, 304 FloatTy, 305 Loc); 306 307 unsigned N = 0; 308 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2) 309 N = 2; 310 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3) 311 N = 3; 312 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4) 313 N = 4; 314 315 // Directly allocate 16 elements instead of dynamically allocate N*N 316 clang::Expr *InitVals[16]; 317 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++) 318 InitVals[i] = Float0Val; 319 clang::Expr *InitExpr = 320 new (C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc); 321 InitExpr->setType(C.getConstantArrayType(FloatTy, 322 llvm::APInt(32, 4), 323 clang::ArrayType::Normal, 324 /* EltTypeQuals = */0)); 325 326 Res = new (C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc); 327 break; 328 } 329 case RSExportPrimitiveType::DataTypeUnknown: 330 case RSExportPrimitiveType::DataTypeFloat16: 331 case RSExportPrimitiveType::DataTypeFloat32: 332 case RSExportPrimitiveType::DataTypeFloat64: 333 case RSExportPrimitiveType::DataTypeSigned8: 334 case RSExportPrimitiveType::DataTypeSigned16: 335 case RSExportPrimitiveType::DataTypeSigned32: 336 case RSExportPrimitiveType::DataTypeSigned64: 337 case RSExportPrimitiveType::DataTypeUnsigned8: 338 case RSExportPrimitiveType::DataTypeUnsigned16: 339 case RSExportPrimitiveType::DataTypeUnsigned32: 340 case RSExportPrimitiveType::DataTypeUnsigned64: 341 case RSExportPrimitiveType::DataTypeBoolean: 342 case RSExportPrimitiveType::DataTypeUnsigned565: 343 case RSExportPrimitiveType::DataTypeUnsigned5551: 344 case RSExportPrimitiveType::DataTypeUnsigned4444: 345 case RSExportPrimitiveType::DataTypeMax: { 346 assert(false && "Not RS object type!"); 347 } 348 // No default case will enable compiler detecting the missing cases 349 } 350 351 return Res; 352} 353 354void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) { 355 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end(); 356 I != E; 357 I++) { 358 clang::Decl *D = *I; 359 if (D->getKind() == clang::Decl::Var) { 360 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D); 361 if (InitializeRSObject(VD)) 362 getCurrentScope()->addRSObject(VD); 363 } 364 } 365 return; 366} 367 368void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) { 369 if (!CS->body_empty()) { 370 // Push a new scope 371 Scope *S = new Scope(CS); 372 mScopeStack.push(S); 373 374 VisitStmt(CS); 375 376 // Destroy the scope 377 // TODO: Update reference count of the RS object refenced by 378 // getCurrentScope(). 379 assert((getCurrentScope() == S) && "Corrupted scope stack!"); 380 S->InsertLocalVarDestructors(); 381 mScopeStack.pop(); 382 delete S; 383 } 384 return; 385} 386 387void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) { 388 // TODO: Update reference count 389 return; 390} 391 392void RSObjectRefCount::VisitStmt(clang::Stmt *S) { 393 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end(); 394 I != E; 395 I++) { 396 if (clang::Stmt *Child = *I) { 397 Visit(Child); 398 } 399 } 400 return; 401} 402 403 404