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