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