blob: 9e813bab2945a87c1cbc5068fc59f3e824836387 [file] [log] [blame]
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001/*
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
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <list>
20
Stephen Hines4b32ffd2010-11-05 18:47:11 -070021#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
Stephen Hinese639eb52010-11-08 19:27:20 -080030namespace slang {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070031
Stephen Hines1bdd4972010-11-08 17:35:08 -080032clang::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;
Stephen Hinese639eb52010-11-08 19:27:20 -080067 } else {
Stephen Hines1bdd4972010-11-08 17:35:08 -080068 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.
Stephen Hinese639eb52010-11-08 19:27:20 -080094 // TODO(srhines): This should also handle the case of goto/break/continue.
Stephen Hines1bdd4972010-11-08 17:35:08 -080095 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);
Stephen Hinese639eb52010-11-08 19:27:20 -0800151 // TODO(srhines): This should also be extended to append destructors to any
Stephen Hines1bdd4972010-11-08 17:35:08 -0800152 // 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 =
Stephen Hinese639eb52010-11-08 19:27:20 -0800197 new(C) clang::UnaryOperator(RefRSVar,
198 clang::UO_AddrOf,
199 ClearObjectFDArgType,
200 Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800201
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 =
Stephen Hinese639eb52010-11-08 19:27:20 -0800220 new(C) clang::CallExpr(C,
221 RSClearObjectFP,
222 &AddrRefRSVar,
223 1,
224 ClearObjectFD->getCallResultType(),
225 clang::SourceLocation());
Stephen Hines1bdd4972010-11-08 17:35:08 -0800226
227 return RSClearObjectCall;
228}
229
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700230bool 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()) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800239 // TODO(srhines): Update the reference count of RS object in initializer.
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700240 // 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
Stephen Hinese639eb52010-11-08 19:27:20 -0800285 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700286 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 =
Stephen Hinese639eb52010-11-08 19:27:20 -0800321 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700322 InitExpr->setType(C.getConstantArrayType(FloatTy,
323 llvm::APInt(32, 4),
324 clang::ArrayType::Normal,
325 /* EltTypeQuals = */0));
326
Stephen Hinese639eb52010-11-08 19:27:20 -0800327 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700328 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
Stephen Hinese639eb52010-11-08 19:27:20 -0800378 // TODO(srhines): Update reference count of the RS object refenced by
379 // getCurrentScope().
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700380 assert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -0800381 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700382 mScopeStack.pop();
383 delete S;
384 }
385 return;
386}
387
388void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800389 // TODO(srhines): Update reference count
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700390 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
Stephen Hinese639eb52010-11-08 19:27:20 -0800404} // namespace slang