blob: b81dd96a6c42aa9feadb6413df04470da12af5bb [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
Stephen Hines4464d822010-11-11 16:45:08 -080089namespace {
90
91static void AppendToCompoundStatement(clang::ASTContext& C,
92 clang::CompoundStmt *CS,
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -080093 std::list<clang::Stmt*> &StmtList,
Stephen Hines4464d822010-11-11 16:45:08 -080094 bool InsertAtEndOfBlock) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080095 // 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.
Stephen Hinese639eb52010-11-08 19:27:20 -080098 // TODO(srhines): This should also handle the case of goto/break/continue.
Stephen Hines4464d822010-11-11 16:45:08 -080099
100 clang::CompoundStmt::body_iterator bI = CS->body_begin();
Stephen Hines1bdd4972010-11-08 17:35:08 -0800101
102 unsigned OldStmtCount = 0;
Stephen Hines03981a32010-12-14 19:45:49 -0800103 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
Stephen Hines1bdd4972010-11-08 17:35:08 -0800104 OldStmtCount++;
105 }
106
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800107 unsigned NewStmtCount = StmtList.size();
Stephen Hines1bdd4972010-11-08 17:35:08 -0800108
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800109 clang::Stmt **UpdatedStmtList;
110 UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800111
112 unsigned UpdatedStmtCount = 0;
Stephen Hines4464d822010-11-11 16:45:08 -0800113 bool FoundReturn = false;
Stephen Hines03981a32010-12-14 19:45:49 -0800114 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
Stephen Hines1bdd4972010-11-08 17:35:08 -0800115 if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
Stephen Hines4464d822010-11-11 16:45:08 -0800116 FoundReturn = true;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800117 break;
118 }
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800119 UpdatedStmtList[UpdatedStmtCount++] = *bI;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800120 }
121
Stephen Hines4464d822010-11-11 16:45:08 -0800122 // 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) {
Stephen Hines03981a32010-12-14 19:45:49 -0800125 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
126 for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
127 I != StmtList.end();
Stephen Hines4464d822010-11-11 16:45:08 -0800128 I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800129 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800130 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800131 }
132
133 // Pick up anything left over after a return statement
Stephen Hines03981a32010-12-14 19:45:49 -0800134 for ( ; bI != CS->body_end(); bI++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800135 UpdatedStmtList[UpdatedStmtCount++] = *bI;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800136 }
137
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800138 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800139
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800140 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800141
142 return;
143}
144
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800145// This class visits a compound statement and inserts the StmtList containing
Stephen Hines4464d822010-11-11 16:45:08 -0800146// destructors in proper locations. This includes inserting them before any
147// return statement in any sub-block, at the end of the logical enclosing
148// scope (compound statement), and/or before any break/continue statement that
149// would resume outside the declared scope. We will not handle the case for
150// goto statements that leave a local scope.
151// TODO(srhines): Make this work properly for break/continue.
152class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
153 private:
154 clang::ASTContext &mC;
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800155 std::list<clang::Stmt*> &mStmtList;
Stephen Hines4464d822010-11-11 16:45:08 -0800156 bool mTopLevel;
157 public:
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800158 DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
Stephen Hines4464d822010-11-11 16:45:08 -0800159 void VisitStmt(clang::Stmt *S);
160 void VisitCompoundStmt(clang::CompoundStmt *CS);
161};
162
163DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800164 std::list<clang::Stmt*> &StmtList)
Stephen Hines4464d822010-11-11 16:45:08 -0800165 : mC(C),
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800166 mStmtList(StmtList),
Stephen Hines4464d822010-11-11 16:45:08 -0800167 mTopLevel(true) {
168 return;
169}
170
171void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
172 if (!CS->body_empty()) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800173 AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
Stephen Hines4464d822010-11-11 16:45:08 -0800174 mTopLevel = false;
175 VisitStmt(CS);
176 }
177 return;
178}
179
180void DestructorVisitor::VisitStmt(clang::Stmt *S) {
181 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
182 I != E;
183 I++) {
184 if (clang::Stmt *Child = *I) {
185 Visit(Child);
186 }
187 }
188 return;
189}
190
Stephen Hines03981a32010-12-14 19:45:49 -0800191static int ArrayDim(clang::VarDecl *VD) {
192 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
193
194 if (!T || !T->isArrayType()) {
195 return 0;
196 }
197
198 const clang::ConstantArrayType *CAT =
199 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800200 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800201}
202
203static clang::Stmt *ClearArrayRSObject(clang::VarDecl *VD,
204 const clang::Type *T,
205 clang::FunctionDecl *ClearObjectFD) {
206 clang::ASTContext &C = VD->getASTContext();
207 clang::SourceRange Range = VD->getQualifierRange();
208 clang::SourceLocation Loc = Range.getEnd();
209
210 clang::Stmt *StmtArray[2] = {NULL};
211 int StmtCtr = 0;
212
213 int NumArrayElements = ArrayDim(VD);
214 if (NumArrayElements <= 0) {
215 return NULL;
216 }
217
218 // Example destructor loop for "rs_font fontArr[10];"
219 //
220 // (CompoundStmt
221 // (DeclStmt "int rsIntIter")
222 // (ForStmt
223 // (BinaryOperator 'int' '='
224 // (DeclRefExpr 'int' Var='rsIntIter')
225 // (IntegerLiteral 'int' 0))
226 // (BinaryOperator 'int' '<'
227 // (DeclRefExpr 'int' Var='rsIntIter')
228 // (IntegerLiteral 'int' 10)
229 // NULL << CondVar >>
230 // (UnaryOperator 'int' postfix '++'
231 // (DeclRefExpr 'int' Var='rsIntIter'))
232 // (CallExpr 'void'
233 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
234 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
235 // (UnaryOperator 'rs_font *' prefix '&'
236 // (ArraySubscriptExpr 'rs_font':'rs_font'
237 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
238 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
239 // (DeclRefExpr 'int' Var='rsIntIter')))))))
240
241 // Create helper variable for iterating through elements
242 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
243 clang::VarDecl *IIVD =
244 clang::VarDecl::Create(C,
245 VD->getDeclContext(),
246 Loc,
247 &II,
248 C.IntTy,
249 C.getTrivialTypeSourceInfo(C.IntTy),
250 clang::SC_None,
251 clang::SC_None);
252 clang::Decl *IID = (clang::Decl *)IIVD;
253
254 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
255 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
256
257 // Form the actual destructor loop
258 // for (Init; Cond; Inc)
259 // RSClearObjectCall;
260
261 // Init -> "rsIntIter = 0"
262 clang::DeclRefExpr *RefrsIntIter =
263 clang::DeclRefExpr::Create(C,
264 NULL,
265 Range,
266 IIVD,
267 Loc,
268 C.IntTy);
269
270 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
271 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
272
273 clang::BinaryOperator *Init =
274 new(C) clang::BinaryOperator(RefrsIntIter,
275 Int0,
276 clang::BO_Assign,
277 C.IntTy,
278 Loc);
279
280 // Cond -> "rsIntIter < NumArrayElements"
281 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
282 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
283
284 clang::BinaryOperator *Cond =
285 new(C) clang::BinaryOperator(RefrsIntIter,
286 NumArrayElementsExpr,
287 clang::BO_LT,
288 C.IntTy,
289 Loc);
290
291 // Inc -> "rsIntIter++"
292 clang::UnaryOperator *Inc =
293 new(C) clang::UnaryOperator(RefrsIntIter,
294 clang::UO_PostInc,
295 C.IntTy,
296 Loc);
297
298 // Body -> "rsClearObject(&VD[rsIntIter]);"
299 // Destructor loop operates on individual array elements
300 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
301 clang::QualType ClearObjectFDArgType =
302 ClearObjectFD->getParamDecl(0)->getOriginalType();
303
304 const clang::Type *VT = RSExportType::GetTypeOfDecl(VD);
305 clang::DeclRefExpr *RefRSVar =
306 clang::DeclRefExpr::Create(C,
307 NULL,
308 Range,
309 VD,
310 Loc,
311 VT->getCanonicalTypeInternal());
312
313 clang::Expr *RefRSVarPtr =
314 clang::ImplicitCastExpr::Create(C,
315 C.getPointerType(T->getCanonicalTypeInternal()),
316 clang::CK_ArrayToPointerDecay,
317 RefRSVar,
318 NULL,
319 clang::VK_RValue);
320
321 clang::Expr *RefRSVarPtrSubscript =
322 new(C) clang::ArraySubscriptExpr(RefRSVarPtr,
323 RefrsIntIter,
324 T->getCanonicalTypeInternal(),
325 VD->getLocation());
326
327 clang::Expr *AddrRefRSVarPtrSubscript =
328 new(C) clang::UnaryOperator(RefRSVarPtrSubscript,
329 clang::UO_AddrOf,
330 ClearObjectFDArgType,
331 VD->getLocation());
332
333 clang::Expr *RefRSClearObjectFD =
334 clang::DeclRefExpr::Create(C,
335 NULL,
336 Range,
337 ClearObjectFD,
338 Loc,
339 ClearObjectFDType);
340
341 clang::Expr *RSClearObjectFP =
342 clang::ImplicitCastExpr::Create(C,
343 C.getPointerType(ClearObjectFDType),
344 clang::CK_FunctionToPointerDecay,
345 RefRSClearObjectFD,
346 NULL,
347 clang::VK_RValue);
348
349 clang::CallExpr *RSClearObjectCall =
350 new(C) clang::CallExpr(C,
351 RSClearObjectFP,
352 &AddrRefRSVarPtrSubscript,
353 1,
354 ClearObjectFD->getCallResultType(),
355 Loc);
356
357 clang::ForStmt *DestructorLoop =
358 new(C) clang::ForStmt(C,
359 Init,
360 Cond,
361 NULL, // no condVar
362 Inc,
363 RSClearObjectCall,
364 Loc,
365 Loc,
366 Loc);
367
368 StmtArray[StmtCtr++] = DestructorLoop;
369 assert(StmtCtr == 2);
370
371 clang::CompoundStmt *CS =
372 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
373
374 return CS;
375}
376
Stephen Hines4464d822010-11-11 16:45:08 -0800377} // namespace
378
Stephen Hines1bdd4972010-11-08 17:35:08 -0800379void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800380 std::list<clang::Stmt*> RSClearObjectCalls;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800381 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
382 E = mRSO.end();
383 I != E;
384 I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800385 clang::Stmt *E = ClearRSObject(*I);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800386 if (E) {
387 RSClearObjectCalls.push_back(E);
388 }
389 }
390 if (RSClearObjectCalls.size() > 0) {
Stephen Hines4464d822010-11-11 16:45:08 -0800391 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
392 DV.Visit(mCS);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800393 }
394 return;
395}
396
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800397clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
Stephen Hines03981a32010-12-14 19:45:49 -0800398 bool IsArrayType = false;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800399 clang::ASTContext &C = VD->getASTContext();
400 clang::SourceLocation Loc = VD->getLocation();
401 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -0800402
403 // Loop through array types to get to base type
404 while (T && T->isArrayType()) {
405 T = T->getArrayElementTypeNoTypeQual();
406 IsArrayType = true;
407 }
408
Stephen Hines1bdd4972010-11-08 17:35:08 -0800409 RSExportPrimitiveType::DataType DT =
410 RSExportPrimitiveType::GetRSSpecificType(T);
411
412 assert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
413 "Should be RS object");
414
415 // Find the rsClearObject() for VD of RS object type DT
416 clang::FunctionDecl *ClearObjectFD =
417 RSClearObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)];
418 assert((ClearObjectFD != NULL) &&
419 "rsClearObject doesn't cover all RS object types");
420
Stephen Hines03981a32010-12-14 19:45:49 -0800421 if (IsArrayType) {
422 return ClearArrayRSObject(VD, T, ClearObjectFD);
423 }
424
Stephen Hines1bdd4972010-11-08 17:35:08 -0800425 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
426 clang::QualType ClearObjectFDArgType =
427 ClearObjectFD->getParamDecl(0)->getOriginalType();
428
Stephen Hines03981a32010-12-14 19:45:49 -0800429 // Example destructor for "rs_font localFont;"
430 //
Stephen Hines1bdd4972010-11-08 17:35:08 -0800431 // (CallExpr 'void'
432 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
433 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
434 // (UnaryOperator 'rs_font *' prefix '&'
Stephen Hines03981a32010-12-14 19:45:49 -0800435 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
Stephen Hines1bdd4972010-11-08 17:35:08 -0800436
437 // Reference expr to target RS object variable
438 clang::DeclRefExpr *RefRSVar =
439 clang::DeclRefExpr::Create(C,
440 NULL,
441 VD->getQualifierRange(),
442 VD,
443 Loc,
Stephen Hines03981a32010-12-14 19:45:49 -0800444 T->getCanonicalTypeInternal());
Stephen Hines1bdd4972010-11-08 17:35:08 -0800445
446 // Get address of RSObject in VD
447 clang::Expr *AddrRefRSVar =
Stephen Hinese639eb52010-11-08 19:27:20 -0800448 new(C) clang::UnaryOperator(RefRSVar,
449 clang::UO_AddrOf,
450 ClearObjectFDArgType,
451 Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800452
453 clang::Expr *RefRSClearObjectFD =
454 clang::DeclRefExpr::Create(C,
455 NULL,
456 ClearObjectFD->getQualifierRange(),
457 ClearObjectFD,
458 ClearObjectFD->getLocation(),
Stephen Hines03981a32010-12-14 19:45:49 -0800459 ClearObjectFDType);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800460
461 clang::Expr *RSClearObjectFP =
462 clang::ImplicitCastExpr::Create(C,
463 C.getPointerType(ClearObjectFDType),
464 clang::CK_FunctionToPointerDecay,
465 RefRSClearObjectFD,
466 NULL,
467 clang::VK_RValue);
468
469 clang::CallExpr *RSClearObjectCall =
Stephen Hinese639eb52010-11-08 19:27:20 -0800470 new(C) clang::CallExpr(C,
471 RSClearObjectFP,
472 &AddrRefRSVar,
473 1,
474 ClearObjectFD->getCallResultType(),
475 clang::SourceLocation());
Stephen Hines1bdd4972010-11-08 17:35:08 -0800476
477 return RSClearObjectCall;
478}
479
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700480bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
Stephen Hines2d095042010-11-12 18:13:56 -0800481 bool IsArrayType = false;
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700482 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -0800483
484 // Loop through array types to get to base type
485 while (T && T->isArrayType()) {
486 T = T->getArrayElementTypeNoTypeQual();
487 IsArrayType = true;
488 }
489
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700490 RSExportPrimitiveType::DataType DT =
491 RSExportPrimitiveType::GetRSSpecificType(T);
492
Stephen Hines2d095042010-11-12 18:13:56 -0800493 if (DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700494 return false;
Stephen Hines2d095042010-11-12 18:13:56 -0800495 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700496
497 if (VD->hasInit()) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800498 // TODO(srhines): Update the reference count of RS object in initializer.
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700499 // This can potentially be done as part of the assignment pass.
500 } else {
501 clang::Expr *ZeroInitializer =
502 CreateZeroInitializerForRSSpecificType(DT,
503 VD->getASTContext(),
504 VD->getLocation());
505
506 if (ZeroInitializer) {
507 ZeroInitializer->setType(T->getCanonicalTypeInternal());
508 VD->setInit(ZeroInitializer);
509 }
510 }
511
Stephen Hines03981a32010-12-14 19:45:49 -0800512 return RSExportPrimitiveType::IsRSObjectType(DT);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700513}
514
515clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
516 RSExportPrimitiveType::DataType DT,
517 clang::ASTContext &C,
518 const clang::SourceLocation &Loc) {
519 clang::Expr *Res = NULL;
520 switch (DT) {
521 case RSExportPrimitiveType::DataTypeRSElement:
522 case RSExportPrimitiveType::DataTypeRSType:
523 case RSExportPrimitiveType::DataTypeRSAllocation:
524 case RSExportPrimitiveType::DataTypeRSSampler:
525 case RSExportPrimitiveType::DataTypeRSScript:
526 case RSExportPrimitiveType::DataTypeRSMesh:
527 case RSExportPrimitiveType::DataTypeRSProgramFragment:
528 case RSExportPrimitiveType::DataTypeRSProgramVertex:
529 case RSExportPrimitiveType::DataTypeRSProgramRaster:
530 case RSExportPrimitiveType::DataTypeRSProgramStore:
531 case RSExportPrimitiveType::DataTypeRSFont: {
532 // (ImplicitCastExpr 'nullptr_t'
533 // (IntegerLiteral 0)))
534 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
535 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
536 clang::Expr *CastToNull =
537 clang::ImplicitCastExpr::Create(C,
538 C.NullPtrTy,
539 clang::CK_IntegralToPointer,
540 Int0,
541 NULL,
542 clang::VK_RValue);
543
Stephen Hinese639eb52010-11-08 19:27:20 -0800544 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700545 break;
546 }
547 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
548 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
549 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
550 // RS matrix is not completely an RS object. They hold data by themselves.
551 // (InitListExpr rs_matrix2x2
552 // (InitListExpr float[4]
553 // (FloatingLiteral 0)
554 // (FloatingLiteral 0)
555 // (FloatingLiteral 0)
556 // (FloatingLiteral 0)))
557 clang::QualType FloatTy = C.FloatTy;
558 // Constructor sets value to 0.0f by default
559 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
560 clang::FloatingLiteral *Float0Val =
561 clang::FloatingLiteral::Create(C,
562 Val,
563 /* isExact = */true,
564 FloatTy,
565 Loc);
566
567 unsigned N = 0;
568 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
569 N = 2;
570 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
571 N = 3;
572 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
573 N = 4;
574
575 // Directly allocate 16 elements instead of dynamically allocate N*N
576 clang::Expr *InitVals[16];
577 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
578 InitVals[i] = Float0Val;
579 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -0800580 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700581 InitExpr->setType(C.getConstantArrayType(FloatTy,
582 llvm::APInt(32, 4),
583 clang::ArrayType::Normal,
584 /* EltTypeQuals = */0));
585
Stephen Hinese639eb52010-11-08 19:27:20 -0800586 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700587 break;
588 }
589 case RSExportPrimitiveType::DataTypeUnknown:
590 case RSExportPrimitiveType::DataTypeFloat16:
591 case RSExportPrimitiveType::DataTypeFloat32:
592 case RSExportPrimitiveType::DataTypeFloat64:
593 case RSExportPrimitiveType::DataTypeSigned8:
594 case RSExportPrimitiveType::DataTypeSigned16:
595 case RSExportPrimitiveType::DataTypeSigned32:
596 case RSExportPrimitiveType::DataTypeSigned64:
597 case RSExportPrimitiveType::DataTypeUnsigned8:
598 case RSExportPrimitiveType::DataTypeUnsigned16:
599 case RSExportPrimitiveType::DataTypeUnsigned32:
600 case RSExportPrimitiveType::DataTypeUnsigned64:
601 case RSExportPrimitiveType::DataTypeBoolean:
602 case RSExportPrimitiveType::DataTypeUnsigned565:
603 case RSExportPrimitiveType::DataTypeUnsigned5551:
604 case RSExportPrimitiveType::DataTypeUnsigned4444:
605 case RSExportPrimitiveType::DataTypeMax: {
606 assert(false && "Not RS object type!");
607 }
608 // No default case will enable compiler detecting the missing cases
609 }
610
611 return Res;
612}
613
614void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
615 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
616 I != E;
617 I++) {
618 clang::Decl *D = *I;
619 if (D->getKind() == clang::Decl::Var) {
620 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
621 if (InitializeRSObject(VD))
622 getCurrentScope()->addRSObject(VD);
623 }
624 }
625 return;
626}
627
628void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
629 if (!CS->body_empty()) {
630 // Push a new scope
631 Scope *S = new Scope(CS);
632 mScopeStack.push(S);
633
634 VisitStmt(CS);
635
636 // Destroy the scope
Stephen Hinese639eb52010-11-08 19:27:20 -0800637 // TODO(srhines): Update reference count of the RS object refenced by
638 // getCurrentScope().
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700639 assert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -0800640 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700641 mScopeStack.pop();
642 delete S;
643 }
644 return;
645}
646
647void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinese639eb52010-11-08 19:27:20 -0800648 // TODO(srhines): Update reference count
Stephen Hines4b32ffd2010-11-05 18:47:11 -0700649 return;
650}
651
652void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
653 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
654 I != E;
655 I++) {
656 if (clang::Stmt *Child = *I) {
657 Visit(Child);
658 }
659 }
660 return;
661}
662
Stephen Hinese639eb52010-11-08 19:27:20 -0800663} // namespace slang