blob: 0ee519beafb1e2d0214119c578eba04abbf979de [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
Stephen Hines6e6578a2011-02-07 18:05:48 -080027#include "slang_assert.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070028#include "slang_rs.h"
29#include "slang_rs_export_type.h"
30
Stephen Hinese639eb52010-11-08 19:27:20 -080031namespace slang {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070032
Stephen Hinesf2174cf2011-02-09 23:21:37 -080033clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080034 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
35 RSExportPrimitiveType::FirstRSObjectType + 1];
Stephen Hinesf2174cf2011-02-09 23:21:37 -080036clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080037 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
38 RSExportPrimitiveType::FirstRSObjectType + 1];
39
Stephen Hinesf2174cf2011-02-09 23:21:37 -080040void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080041 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") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080060 slangAssert((FD->getNumParams() == 2) &&
61 "Invalid rsSetObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080062 RSObjectFD = RSSetObjectFD;
63 } else if (FD->getName() == "rsClearObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080064 slangAssert((FD->getNumParams() == 1) &&
65 "Invalid rsClearObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080066 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*
Stephen Hines6e6578a2011-02-07 18:05:48 -080074 slangAssert(PVT->isPointerType() &&
75 "Invalid rs{Set,Clear}Object function prototype (pointer param)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080076
77 // The rs object type passed to the FD
78 clang::QualType RST = PVT->getPointeeType();
79 RSExportPrimitiveType::DataType DT =
80 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
Stephen Hines6e6578a2011-02-07 18:05:48 -080081 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
Stephen Hines1bdd4972010-11-08 17:35:08 -080082 && "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 Hinese79fb5e2011-02-01 19:12:43 -0800145static void AppendAfterStmt(clang::ASTContext& C,
146 clang::CompoundStmt *CS,
147 clang::Stmt *OldStmt,
148 clang::Stmt *NewStmt) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800149 slangAssert(CS && OldStmt && NewStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800150 clang::CompoundStmt::body_iterator bI = CS->body_begin();
151 unsigned StmtCount = 1; // Take into account new statement
152 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153 StmtCount++;
154 }
155
156 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157
158 unsigned UpdatedStmtCount = 0;
159 unsigned Once = 0;
160 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
161 UpdatedStmtList[UpdatedStmtCount++] = *bI;
162 if (*bI == OldStmt) {
163 Once++;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800164 slangAssert(Once == 1);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800165 UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
166 }
167 }
168
169 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
170
171 delete [] UpdatedStmtList;
172
173 return;
174}
175
176static void ReplaceInCompoundStmt(clang::ASTContext& C,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800177 clang::CompoundStmt *CS,
178 clang::Stmt* OldStmt,
179 clang::Stmt* NewStmt) {
180 clang::CompoundStmt::body_iterator bI = CS->body_begin();
181
182 unsigned StmtCount = 0;
183 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
184 StmtCount++;
185 }
186
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800187 clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
188
189 unsigned UpdatedStmtCount = 0;
190 for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
191 if (*bI == OldStmt) {
192 UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
193 } else {
194 UpdatedStmtList[UpdatedStmtCount++] = *bI;
195 }
196 }
197
198 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
199
200 delete [] UpdatedStmtList;
201
202 return;
203}
204
205
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800206// This class visits a compound statement and inserts the StmtList containing
Stephen Hines4464d822010-11-11 16:45:08 -0800207// destructors in proper locations. This includes inserting them before any
208// return statement in any sub-block, at the end of the logical enclosing
209// scope (compound statement), and/or before any break/continue statement that
210// would resume outside the declared scope. We will not handle the case for
211// goto statements that leave a local scope.
212// TODO(srhines): Make this work properly for break/continue.
213class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
214 private:
215 clang::ASTContext &mC;
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800216 std::list<clang::Stmt*> &mStmtList;
Stephen Hines4464d822010-11-11 16:45:08 -0800217 bool mTopLevel;
218 public:
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800219 DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
Stephen Hines4464d822010-11-11 16:45:08 -0800220 void VisitStmt(clang::Stmt *S);
221 void VisitCompoundStmt(clang::CompoundStmt *CS);
222};
223
224DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800225 std::list<clang::Stmt*> &StmtList)
Stephen Hines4464d822010-11-11 16:45:08 -0800226 : mC(C),
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800227 mStmtList(StmtList),
Stephen Hines4464d822010-11-11 16:45:08 -0800228 mTopLevel(true) {
229 return;
230}
231
232void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
233 if (!CS->body_empty()) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800234 AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
Stephen Hines4464d822010-11-11 16:45:08 -0800235 mTopLevel = false;
236 VisitStmt(CS);
237 }
238 return;
239}
240
241void DestructorVisitor::VisitStmt(clang::Stmt *S) {
242 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
243 I != E;
244 I++) {
245 if (clang::Stmt *Child = *I) {
246 Visit(Child);
247 }
248 }
249 return;
250}
251
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800252clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
253 clang::Expr *RefRSVar,
254 clang::SourceLocation Loc) {
255 slangAssert(RefRSVar);
256 const clang::Type *T = RefRSVar->getType().getTypePtr();
257 slangAssert(!T->isArrayType() &&
258 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800259
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800260 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
261 slangAssert((ClearObjectFD != NULL) &&
262 "rsClearObject doesn't cover all RS object types");
263
264 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
265 clang::QualType ClearObjectFDArgType =
266 ClearObjectFD->getParamDecl(0)->getOriginalType();
267
268 // Example destructor for "rs_font localFont;"
269 //
270 // (CallExpr 'void'
271 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
272 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
273 // (UnaryOperator 'rs_font *' prefix '&'
274 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
275
276 // Get address of targeted RS object
277 clang::Expr *AddrRefRSVar =
278 new(C) clang::UnaryOperator(RefRSVar,
279 clang::UO_AddrOf,
280 ClearObjectFDArgType,
281 Loc);
282
283 clang::Expr *RefRSClearObjectFD =
284 clang::DeclRefExpr::Create(C,
285 NULL,
286 ClearObjectFD->getQualifierRange(),
287 ClearObjectFD,
288 ClearObjectFD->getLocation(),
289 ClearObjectFDType);
290
291 clang::Expr *RSClearObjectFP =
292 clang::ImplicitCastExpr::Create(C,
293 C.getPointerType(ClearObjectFDType),
294 clang::CK_FunctionToPointerDecay,
295 RefRSClearObjectFD,
296 NULL,
297 clang::VK_RValue);
298
299 clang::CallExpr *RSClearObjectCall =
300 new(C) clang::CallExpr(C,
301 RSClearObjectFP,
302 &AddrRefRSVar,
303 1,
304 ClearObjectFD->getCallResultType(),
305 Loc);
306
307 return RSClearObjectCall;
308}
309
310static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800311 if (!T || !T->isArrayType()) {
312 return 0;
313 }
314
315 const clang::ConstantArrayType *CAT =
316 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800317 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800318}
319
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800320static clang::Stmt *ClearStructRSObject(
321 clang::ASTContext &C,
322 clang::DeclContext *DC,
323 clang::Expr *RefRSStruct,
324 clang::SourceRange Range,
325 clang::SourceLocation Loc);
326
327static clang::Stmt *ClearArrayRSObject(
328 clang::ASTContext &C,
329 clang::DeclContext *DC,
330 clang::Expr *RefRSArr,
331 clang::SourceRange Range,
332 clang::SourceLocation Loc) {
333 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
334 slangAssert(BaseType->isArrayType());
335
336 int NumArrayElements = ArrayDim(BaseType);
337 // Actually extract out the base RS object type for use later
338 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800339
340 clang::Stmt *StmtArray[2] = {NULL};
341 int StmtCtr = 0;
342
Stephen Hines03981a32010-12-14 19:45:49 -0800343 if (NumArrayElements <= 0) {
344 return NULL;
345 }
346
347 // Example destructor loop for "rs_font fontArr[10];"
348 //
349 // (CompoundStmt
350 // (DeclStmt "int rsIntIter")
351 // (ForStmt
352 // (BinaryOperator 'int' '='
353 // (DeclRefExpr 'int' Var='rsIntIter')
354 // (IntegerLiteral 'int' 0))
355 // (BinaryOperator 'int' '<'
356 // (DeclRefExpr 'int' Var='rsIntIter')
357 // (IntegerLiteral 'int' 10)
358 // NULL << CondVar >>
359 // (UnaryOperator 'int' postfix '++'
360 // (DeclRefExpr 'int' Var='rsIntIter'))
361 // (CallExpr 'void'
362 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
363 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
364 // (UnaryOperator 'rs_font *' prefix '&'
365 // (ArraySubscriptExpr 'rs_font':'rs_font'
366 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
367 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
368 // (DeclRefExpr 'int' Var='rsIntIter')))))))
369
370 // Create helper variable for iterating through elements
371 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
372 clang::VarDecl *IIVD =
373 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800374 DC,
Stephen Hines03981a32010-12-14 19:45:49 -0800375 Loc,
376 &II,
377 C.IntTy,
378 C.getTrivialTypeSourceInfo(C.IntTy),
379 clang::SC_None,
380 clang::SC_None);
381 clang::Decl *IID = (clang::Decl *)IIVD;
382
383 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
384 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
385
386 // Form the actual destructor loop
387 // for (Init; Cond; Inc)
388 // RSClearObjectCall;
389
390 // Init -> "rsIntIter = 0"
391 clang::DeclRefExpr *RefrsIntIter =
392 clang::DeclRefExpr::Create(C,
393 NULL,
394 Range,
395 IIVD,
396 Loc,
397 C.IntTy);
398
399 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
400 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
401
402 clang::BinaryOperator *Init =
403 new(C) clang::BinaryOperator(RefrsIntIter,
404 Int0,
405 clang::BO_Assign,
406 C.IntTy,
407 Loc);
408
409 // Cond -> "rsIntIter < NumArrayElements"
410 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
411 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
412
413 clang::BinaryOperator *Cond =
414 new(C) clang::BinaryOperator(RefrsIntIter,
415 NumArrayElementsExpr,
416 clang::BO_LT,
417 C.IntTy,
418 Loc);
419
420 // Inc -> "rsIntIter++"
421 clang::UnaryOperator *Inc =
422 new(C) clang::UnaryOperator(RefrsIntIter,
423 clang::UO_PostInc,
424 C.IntTy,
425 Loc);
426
427 // Body -> "rsClearObject(&VD[rsIntIter]);"
428 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800429
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800430 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800431 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800432 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800433 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800434 RefRSArr,
Stephen Hines03981a32010-12-14 19:45:49 -0800435 NULL,
436 clang::VK_RValue);
437
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800438 clang::Expr *RefRSArrPtrSubscript =
439 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hines03981a32010-12-14 19:45:49 -0800440 RefrsIntIter,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800441 BaseType->getCanonicalTypeInternal(),
442 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800443
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800444 RSExportPrimitiveType::DataType DT =
445 RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800446
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800447 clang::Stmt *RSClearObjectCall = NULL;
448 if (BaseType->isArrayType()) {
449 RSClearObjectCall =
450 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
451 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
452 RSClearObjectCall =
453 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
454 } else {
455 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
456 }
Stephen Hines03981a32010-12-14 19:45:49 -0800457
458 clang::ForStmt *DestructorLoop =
459 new(C) clang::ForStmt(C,
460 Init,
461 Cond,
462 NULL, // no condVar
463 Inc,
464 RSClearObjectCall,
465 Loc,
466 Loc,
467 Loc);
468
469 StmtArray[StmtCtr++] = DestructorLoop;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800470 slangAssert(StmtCtr == 2);
Stephen Hines03981a32010-12-14 19:45:49 -0800471
472 clang::CompoundStmt *CS =
473 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
474
475 return CS;
476}
477
Stephen Hines2bb67db2011-02-11 01:36:40 -0800478static unsigned CountRSObjectTypes(const clang::Type *T) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800479 slangAssert(T);
480 unsigned RSObjectCount = 0;
481
482 if (T->isArrayType()) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800483 return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800484 }
485
486 RSExportPrimitiveType::DataType DT =
487 RSExportPrimitiveType::GetRSSpecificType(T);
488 if (DT != RSExportPrimitiveType::DataTypeUnknown) {
489 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
490 }
491
492 if (!T->isStructureType()) {
493 return 0;
494 }
495
496 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
497 RD = RD->getDefinition();
498 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
499 FE = RD->field_end();
500 FI != FE;
501 FI++) {
502 const clang::FieldDecl *FD = *FI;
503 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800504 if (CountRSObjectTypes(FT)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800505 // Sub-structs should only count once (as should arrays, etc.)
506 RSObjectCount++;
507 }
508 }
509
510 return RSObjectCount;
511}
512
513static clang::Stmt *ClearStructRSObject(
514 clang::ASTContext &C,
515 clang::DeclContext *DC,
516 clang::Expr *RefRSStruct,
517 clang::SourceRange Range,
518 clang::SourceLocation Loc) {
519 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
520
521 slangAssert(!BaseType->isArrayType());
522
523 RSExportPrimitiveType::DataType DT =
524 RSExportPrimitiveType::GetRSSpecificType(BaseType);
525
526 // Structs should show up as unknown primitive types
527 slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown);
528
Stephen Hines2bb67db2011-02-11 01:36:40 -0800529 unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800530
531 unsigned StmtCount = 0;
532 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800533 for (unsigned i = 0; i < FieldsToDestroy; i++) {
534 StmtArray[i] = NULL;
535 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800536
537 // Populate StmtArray by creating a destructor for each RS object field
538 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
539 RD = RD->getDefinition();
540 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
541 FE = RD->field_end();
542 FI != FE;
543 FI++) {
544 // We just look through all field declarations to see if we find a
545 // declaration for an RS object type (or an array of one).
546 bool IsArrayType = false;
547 clang::FieldDecl *FD = *FI;
548 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
549 const clang::Type *OrigType = FT;
550 while (FT && FT->isArrayType()) {
551 FT = FT->getArrayElementTypeNoTypeQual();
552 IsArrayType = true;
553 }
554
555 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
556 clang::DeclAccessPair FoundDecl =
557 clang::DeclAccessPair::make(FD, clang::AS_none);
558 clang::MemberExpr *RSObjectMember =
559 clang::MemberExpr::Create(C,
560 RefRSStruct,
561 false,
562 NULL,
563 Range,
564 FD,
565 FoundDecl,
566 clang::DeclarationNameInfo(),
567 NULL,
568 OrigType->getCanonicalTypeInternal());
569
570 slangAssert(StmtCount < FieldsToDestroy);
571
572 if (IsArrayType) {
573 StmtArray[StmtCount++] = ClearArrayRSObject(C,
574 DC,
575 RSObjectMember,
576 Range,
577 Loc);
578 } else {
579 StmtArray[StmtCount++] = ClearSingleRSObject(C,
580 RSObjectMember,
581 Loc);
582 }
Stephen Hines2bb67db2011-02-11 01:36:40 -0800583 } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800584 // In this case, we have a nested struct. We may not end up filling all
585 // of the spaces in StmtArray (sub-structs should handle themselves
586 // with separate compound statements).
587 clang::DeclAccessPair FoundDecl =
588 clang::DeclAccessPair::make(FD, clang::AS_none);
589 clang::MemberExpr *RSObjectMember =
590 clang::MemberExpr::Create(C,
591 RefRSStruct,
592 false,
593 NULL,
594 Range,
595 FD,
596 FoundDecl,
597 clang::DeclarationNameInfo(),
598 NULL,
599 OrigType->getCanonicalTypeInternal());
600
601 if (IsArrayType) {
602 StmtArray[StmtCount++] = ClearArrayRSObject(C,
603 DC,
604 RSObjectMember,
605 Range,
606 Loc);
607 } else {
608 StmtArray[StmtCount++] = ClearStructRSObject(C,
609 DC,
610 RSObjectMember,
611 Range,
612 Loc);
613 }
614 }
615 }
616
617 slangAssert(StmtCount > 0);
618 clang::CompoundStmt *CS =
619 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
620
621 delete [] StmtArray;
622
623 return CS;
624}
625
Stephen Hines2bb67db2011-02-11 01:36:40 -0800626static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
627 clang::Diagnostic *Diags,
628 clang::Expr *DstExpr,
629 clang::Expr *SrcExpr,
630 clang::SourceLocation Loc) {
631 const clang::Type *T = DstExpr->getType().getTypePtr();
632 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800633 slangAssert((SetObjectFD != NULL) &&
634 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800635
636 clang::QualType SetObjectFDType = SetObjectFD->getType();
637 clang::QualType SetObjectFDArgType[2];
638 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
639 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
640
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800641 clang::Expr *RefRSSetObjectFD =
642 clang::DeclRefExpr::Create(C,
643 NULL,
644 SetObjectFD->getQualifierRange(),
645 SetObjectFD,
646 Loc,
647 SetObjectFDType);
648
649 clang::Expr *RSSetObjectFP =
650 clang::ImplicitCastExpr::Create(C,
651 C.getPointerType(SetObjectFDType),
652 clang::CK_FunctionToPointerDecay,
653 RefRSSetObjectFD,
654 NULL,
655 clang::VK_RValue);
656
657 clang::Expr *ArgList[2];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800658 ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800659 clang::UO_AddrOf,
660 SetObjectFDArgType[0],
661 Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800662 ArgList[1] = SrcExpr;
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800663
664 clang::CallExpr *RSSetObjectCall =
665 new(C) clang::CallExpr(C,
666 RSSetObjectFP,
667 ArgList,
668 2,
669 SetObjectFD->getCallResultType(),
670 Loc);
671
Stephen Hines2bb67db2011-02-11 01:36:40 -0800672 return RSSetObjectCall;
673}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800674
Stephen Hines2bb67db2011-02-11 01:36:40 -0800675static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
676 clang::Diagnostic *Diags,
677 clang::Expr *LHS,
678 clang::Expr *RHS,
679 clang::SourceLocation Loc);
680
681static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
682 clang::Diagnostic *Diags,
683 clang::Expr *DstArr,
684 clang::Expr *SrcArr,
685 clang::SourceLocation Loc) {
686 clang::DeclContext *DC = NULL;
687 clang::SourceRange Range;
688 const clang::Type *BaseType = DstArr->getType().getTypePtr();
689 slangAssert(BaseType->isArrayType());
690
691 int NumArrayElements = ArrayDim(BaseType);
692 // Actually extract out the base RS object type for use later
693 BaseType = BaseType->getArrayElementTypeNoTypeQual();
694
695 clang::Stmt *StmtArray[2] = {NULL};
696 int StmtCtr = 0;
697
698 if (NumArrayElements <= 0) {
699 return NULL;
700 }
701
702 // Create helper variable for iterating through elements
703 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
704 clang::VarDecl *IIVD =
705 clang::VarDecl::Create(C,
706 DC,
707 Loc,
708 &II,
709 C.IntTy,
710 C.getTrivialTypeSourceInfo(C.IntTy),
711 clang::SC_None,
712 clang::SC_None);
713 clang::Decl *IID = (clang::Decl *)IIVD;
714
715 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
716 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
717
718 // Form the actual loop
719 // for (Init; Cond; Inc)
720 // RSSetObjectCall;
721
722 // Init -> "rsIntIter = 0"
723 clang::DeclRefExpr *RefrsIntIter =
724 clang::DeclRefExpr::Create(C,
725 NULL,
726 Range,
727 IIVD,
728 Loc,
729 C.IntTy);
730
731 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
732 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
733
734 clang::BinaryOperator *Init =
735 new(C) clang::BinaryOperator(RefrsIntIter,
736 Int0,
737 clang::BO_Assign,
738 C.IntTy,
739 Loc);
740
741 // Cond -> "rsIntIter < NumArrayElements"
742 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
743 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
744
745 clang::BinaryOperator *Cond =
746 new(C) clang::BinaryOperator(RefrsIntIter,
747 NumArrayElementsExpr,
748 clang::BO_LT,
749 C.IntTy,
750 Loc);
751
752 // Inc -> "rsIntIter++"
753 clang::UnaryOperator *Inc =
754 new(C) clang::UnaryOperator(RefrsIntIter,
755 clang::UO_PostInc,
756 C.IntTy,
757 Loc);
758
759 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
760 // Loop operates on individual array elements
761
762 clang::Expr *DstArrPtr =
763 clang::ImplicitCastExpr::Create(C,
764 C.getPointerType(BaseType->getCanonicalTypeInternal()),
765 clang::CK_ArrayToPointerDecay,
766 DstArr,
767 NULL,
768 clang::VK_RValue);
769
770 clang::Expr *DstArrPtrSubscript =
771 new(C) clang::ArraySubscriptExpr(DstArrPtr,
772 RefrsIntIter,
773 BaseType->getCanonicalTypeInternal(),
774 Loc);
775
776 clang::Expr *SrcArrPtr =
777 clang::ImplicitCastExpr::Create(C,
778 C.getPointerType(BaseType->getCanonicalTypeInternal()),
779 clang::CK_ArrayToPointerDecay,
780 SrcArr,
781 NULL,
782 clang::VK_RValue);
783
784 clang::Expr *SrcArrPtrSubscript =
785 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
786 RefrsIntIter,
787 BaseType->getCanonicalTypeInternal(),
788 Loc);
789
790 RSExportPrimitiveType::DataType DT =
791 RSExportPrimitiveType::GetRSSpecificType(BaseType);
792
793 clang::Stmt *RSSetObjectCall = NULL;
794 if (BaseType->isArrayType()) {
795 RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript,
796 SrcArrPtrSubscript, Loc);
797 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
798 RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript,
799 SrcArrPtrSubscript, Loc);
800 } else {
801 RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript,
802 SrcArrPtrSubscript, Loc);
803 }
804
805 clang::ForStmt *DestructorLoop =
806 new(C) clang::ForStmt(C,
807 Init,
808 Cond,
809 NULL, // no condVar
810 Inc,
811 RSSetObjectCall,
812 Loc,
813 Loc,
814 Loc);
815
816 StmtArray[StmtCtr++] = DestructorLoop;
817 slangAssert(StmtCtr == 2);
818
819 clang::CompoundStmt *CS =
820 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
821
822 return CS;
823}
824
825static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
826 clang::Diagnostic *Diags,
827 clang::Expr *LHS,
828 clang::Expr *RHS,
829 clang::SourceLocation Loc) {
830 clang::SourceRange Range;
831 clang::QualType QT = LHS->getType();
832 const clang::Type *T = QT.getTypePtr();
833 slangAssert(T->isStructureType());
834 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
835
836 // Keep an extra slot for the original copy (memcpy)
837 unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
838
839 unsigned StmtCount = 0;
840 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
841 for (unsigned i = 0; i < FieldsToSet; i++) {
842 StmtArray[i] = NULL;
843 }
844
845 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
846 RD = RD->getDefinition();
847 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
848 FE = RD->field_end();
849 FI != FE;
850 FI++) {
851 bool IsArrayType = false;
852 clang::FieldDecl *FD = *FI;
853 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
854 const clang::Type *OrigType = FT;
855
856 if (!CountRSObjectTypes(FT)) {
857 // Skip to next if we don't have any viable RS object types
858 continue;
859 }
860
861 clang::DeclAccessPair FoundDecl =
862 clang::DeclAccessPair::make(FD, clang::AS_none);
863 clang::MemberExpr *DstMember =
864 clang::MemberExpr::Create(C,
865 LHS,
866 false,
867 NULL,
868 Range,
869 FD,
870 FoundDecl,
871 clang::DeclarationNameInfo(),
872 NULL,
873 OrigType->getCanonicalTypeInternal());
874
875 clang::MemberExpr *SrcMember =
876 clang::MemberExpr::Create(C,
877 RHS,
878 false,
879 NULL,
880 Range,
881 FD,
882 FoundDecl,
883 clang::DeclarationNameInfo(),
884 NULL,
885 OrigType->getCanonicalTypeInternal());
886
887 if (FT->isArrayType()) {
888 FT = FT->getArrayElementTypeNoTypeQual();
889 IsArrayType = true;
890 }
891
892 RSExportPrimitiveType::DataType DT =
893 RSExportPrimitiveType::GetRSSpecificType(FT);
894
895 if (IsArrayType) {
896 Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error,
897 "Arrays of RS object types within structures cannot be copied"));
898 // TODO(srhines): Support setting arrays of RS objects
899 // StmtArray[StmtCount++] =
900 // CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
901 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
902 StmtArray[StmtCount++] =
903 CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
904 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
905 StmtArray[StmtCount++] =
906 CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
907 } else {
908 slangAssert(false);
909 }
910 }
911
912 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
913
914 // We still need to actually do the overall struct copy. For simplicity,
915 // we just do a straight-up assignment (which will still preserve all
916 // the proper RS object reference counts).
917 clang::BinaryOperator *CopyStruct =
918 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc);
919 StmtArray[StmtCount++] = CopyStruct;
920
921 clang::CompoundStmt *CS =
922 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
923
924 delete [] StmtArray;
925
926 return CS;
927}
928
929} // namespace
930
931void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
932 clang::BinaryOperator *AS,
933 clang::Diagnostic *Diags) {
934
935 clang::QualType QT = AS->getType();
936
937 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
938 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
939
940 clang::SourceLocation Loc = AS->getLocEnd();
941 clang::Stmt *UpdatedStmt = NULL;
942
943 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
944 // By definition, this is a struct assignment if we get here
945 UpdatedStmt =
946 CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
947 } else {
948 UpdatedStmt =
949 CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
950 }
951
952 ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800953 return;
954}
955
956void RSObjectRefCount::Scope::AppendRSObjectInit(
Stephen Hinesa0611e62011-02-11 16:35:47 -0800957 clang::Diagnostic *Diags,
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800958 clang::VarDecl *VD,
959 clang::DeclStmt *DS,
960 RSExportPrimitiveType::DataType DT,
961 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800962 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800963
964 if (!InitExpr) {
965 return;
966 }
967
Stephen Hinesa0611e62011-02-11 16:35:47 -0800968 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
969 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
970 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
971 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
972
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800973 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
974 // TODO(srhines): Skip struct initialization right now
Stephen Hinesa0611e62011-02-11 16:35:47 -0800975 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
976 clang::DeclRefExpr *RefRSVar =
977 clang::DeclRefExpr::Create(C,
978 NULL,
979 VD->getQualifierRange(),
980 VD,
981 Loc,
982 T->getCanonicalTypeInternal());
983
984 clang::Stmt *RSSetObjectOps =
985 CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc);
986
987 AppendAfterStmt(C, mCS, DS, RSSetObjectOps);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800988 return;
989 }
990
991 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800992 slangAssert((SetObjectFD != NULL) &&
993 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800994
995 clang::QualType SetObjectFDType = SetObjectFD->getType();
996 clang::QualType SetObjectFDArgType[2];
997 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
998 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
999
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001000 clang::Expr *RefRSSetObjectFD =
1001 clang::DeclRefExpr::Create(C,
1002 NULL,
1003 SetObjectFD->getQualifierRange(),
1004 SetObjectFD,
1005 Loc,
1006 SetObjectFDType);
1007
1008 clang::Expr *RSSetObjectFP =
1009 clang::ImplicitCastExpr::Create(C,
1010 C.getPointerType(SetObjectFDType),
1011 clang::CK_FunctionToPointerDecay,
1012 RefRSSetObjectFD,
1013 NULL,
1014 clang::VK_RValue);
1015
1016 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1017 clang::DeclRefExpr *RefRSVar =
1018 clang::DeclRefExpr::Create(C,
1019 NULL,
1020 VD->getQualifierRange(),
1021 VD,
1022 Loc,
1023 T->getCanonicalTypeInternal());
1024
1025 clang::Expr *ArgList[2];
1026 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1027 clang::UO_AddrOf,
1028 SetObjectFDArgType[0],
1029 Loc);
1030 ArgList[1] = InitExpr;
1031
1032 clang::CallExpr *RSSetObjectCall =
1033 new(C) clang::CallExpr(C,
1034 RSSetObjectFP,
1035 ArgList,
1036 2,
1037 SetObjectFD->getCallResultType(),
1038 Loc);
1039
1040 AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001041
1042 return;
1043}
1044
Stephen Hines1bdd4972010-11-08 17:35:08 -08001045void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001046 std::list<clang::Stmt*> RSClearObjectCalls;
Stephen Hines1bdd4972010-11-08 17:35:08 -08001047 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1048 E = mRSO.end();
1049 I != E;
1050 I++) {
Stephen Hinesa858cb62011-01-17 12:17:51 -08001051 clang::Stmt *S = ClearRSObject(*I);
1052 if (S) {
1053 RSClearObjectCalls.push_back(S);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001054 }
1055 }
1056 if (RSClearObjectCalls.size() > 0) {
Stephen Hines4464d822010-11-11 16:45:08 -08001057 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
1058 DV.Visit(mCS);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001059 }
1060 return;
1061}
1062
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001063clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001064 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001065 clang::ASTContext &C = VD->getASTContext();
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001066 clang::DeclContext *DC = VD->getDeclContext();
1067 clang::SourceRange Range = VD->getQualifierRange();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001068 clang::SourceLocation Loc = VD->getLocation();
1069 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001070
Stephen Hines1bdd4972010-11-08 17:35:08 -08001071 // Reference expr to target RS object variable
1072 clang::DeclRefExpr *RefRSVar =
1073 clang::DeclRefExpr::Create(C,
1074 NULL,
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001075 Range,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001076 VD,
1077 Loc,
Stephen Hines03981a32010-12-14 19:45:49 -08001078 T->getCanonicalTypeInternal());
Stephen Hines1bdd4972010-11-08 17:35:08 -08001079
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001080 if (T->isArrayType()) {
1081 return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc);
1082 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001083
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001084 RSExportPrimitiveType::DataType DT =
1085 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001086
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001087 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1088 DT == RSExportPrimitiveType::DataTypeIsStruct) {
1089 return ClearStructRSObject(C, DC, RefRSVar, Range, Loc);
1090 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001091
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001092 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1093 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001094
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001095 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001096}
1097
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001098bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1099 RSExportPrimitiveType::DataType *DT,
1100 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001101 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001102 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001103
1104 // Loop through array types to get to base type
1105 while (T && T->isArrayType()) {
1106 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001107 }
1108
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001109 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001110 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001111
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001112 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001113 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1114 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001115 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001116 } else {
1117 return false;
1118 }
Stephen Hines2d095042010-11-12 18:13:56 -08001119 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001120
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001121 bool DataTypeIsRSObject = false;
1122 if (DataTypeIsStructWithRSObject) {
1123 DataTypeIsRSObject = true;
1124 } else {
1125 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1126 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001127 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001128
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001129 if (!DataTypeIsRSObject && *InitExpr) {
1130 // If we already have an initializer for a matrix type, we are done.
1131 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001132 }
1133
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001134 clang::Expr *ZeroInitializer =
1135 CreateZeroInitializerForRSSpecificType(*DT,
1136 VD->getASTContext(),
1137 VD->getLocation());
1138
1139 if (ZeroInitializer) {
1140 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1141 VD->setInit(ZeroInitializer);
1142 }
1143
1144 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001145}
1146
1147clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1148 RSExportPrimitiveType::DataType DT,
1149 clang::ASTContext &C,
1150 const clang::SourceLocation &Loc) {
1151 clang::Expr *Res = NULL;
1152 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001153 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001154 case RSExportPrimitiveType::DataTypeRSElement:
1155 case RSExportPrimitiveType::DataTypeRSType:
1156 case RSExportPrimitiveType::DataTypeRSAllocation:
1157 case RSExportPrimitiveType::DataTypeRSSampler:
1158 case RSExportPrimitiveType::DataTypeRSScript:
1159 case RSExportPrimitiveType::DataTypeRSMesh:
1160 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1161 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1162 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1163 case RSExportPrimitiveType::DataTypeRSProgramStore:
1164 case RSExportPrimitiveType::DataTypeRSFont: {
1165 // (ImplicitCastExpr 'nullptr_t'
1166 // (IntegerLiteral 0)))
1167 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1168 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1169 clang::Expr *CastToNull =
1170 clang::ImplicitCastExpr::Create(C,
1171 C.NullPtrTy,
1172 clang::CK_IntegralToPointer,
1173 Int0,
1174 NULL,
1175 clang::VK_RValue);
1176
Stephen Hinese639eb52010-11-08 19:27:20 -08001177 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001178 break;
1179 }
1180 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1181 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1182 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1183 // RS matrix is not completely an RS object. They hold data by themselves.
1184 // (InitListExpr rs_matrix2x2
1185 // (InitListExpr float[4]
1186 // (FloatingLiteral 0)
1187 // (FloatingLiteral 0)
1188 // (FloatingLiteral 0)
1189 // (FloatingLiteral 0)))
1190 clang::QualType FloatTy = C.FloatTy;
1191 // Constructor sets value to 0.0f by default
1192 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1193 clang::FloatingLiteral *Float0Val =
1194 clang::FloatingLiteral::Create(C,
1195 Val,
1196 /* isExact = */true,
1197 FloatTy,
1198 Loc);
1199
1200 unsigned N = 0;
1201 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1202 N = 2;
1203 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1204 N = 3;
1205 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1206 N = 4;
1207
1208 // Directly allocate 16 elements instead of dynamically allocate N*N
1209 clang::Expr *InitVals[16];
1210 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1211 InitVals[i] = Float0Val;
1212 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -08001213 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001214 InitExpr->setType(C.getConstantArrayType(FloatTy,
1215 llvm::APInt(32, 4),
1216 clang::ArrayType::Normal,
1217 /* EltTypeQuals = */0));
1218
Stephen Hinese639eb52010-11-08 19:27:20 -08001219 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001220 break;
1221 }
1222 case RSExportPrimitiveType::DataTypeUnknown:
1223 case RSExportPrimitiveType::DataTypeFloat16:
1224 case RSExportPrimitiveType::DataTypeFloat32:
1225 case RSExportPrimitiveType::DataTypeFloat64:
1226 case RSExportPrimitiveType::DataTypeSigned8:
1227 case RSExportPrimitiveType::DataTypeSigned16:
1228 case RSExportPrimitiveType::DataTypeSigned32:
1229 case RSExportPrimitiveType::DataTypeSigned64:
1230 case RSExportPrimitiveType::DataTypeUnsigned8:
1231 case RSExportPrimitiveType::DataTypeUnsigned16:
1232 case RSExportPrimitiveType::DataTypeUnsigned32:
1233 case RSExportPrimitiveType::DataTypeUnsigned64:
1234 case RSExportPrimitiveType::DataTypeBoolean:
1235 case RSExportPrimitiveType::DataTypeUnsigned565:
1236 case RSExportPrimitiveType::DataTypeUnsigned5551:
1237 case RSExportPrimitiveType::DataTypeUnsigned4444:
1238 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001239 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001240 }
1241 // No default case will enable compiler detecting the missing cases
1242 }
1243
1244 return Res;
1245}
1246
1247void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1248 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1249 I != E;
1250 I++) {
1251 clang::Decl *D = *I;
1252 if (D->getKind() == clang::Decl::Var) {
1253 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001254 RSExportPrimitiveType::DataType DT =
1255 RSExportPrimitiveType::DataTypeUnknown;
1256 clang::Expr *InitExpr = NULL;
1257 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001258 getCurrentScope()->addRSObject(VD);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001259 getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001260 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001261 }
1262 }
1263 return;
1264}
1265
1266void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1267 if (!CS->body_empty()) {
1268 // Push a new scope
1269 Scope *S = new Scope(CS);
1270 mScopeStack.push(S);
1271
1272 VisitStmt(CS);
1273
1274 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001275 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001276 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001277 mScopeStack.pop();
1278 delete S;
1279 }
1280 return;
1281}
1282
1283void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001284 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001285
Stephen Hines2bb67db2011-02-11 01:36:40 -08001286 if (CountRSObjectTypes(QT.getTypePtr())) {
1287 getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001288 }
1289
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001290 return;
1291}
1292
1293void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1294 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1295 I != E;
1296 I++) {
1297 if (clang::Stmt *Child = *I) {
1298 Visit(Child);
1299 }
1300 }
1301 return;
1302}
1303
Stephen Hinese639eb52010-11-08 19:27:20 -08001304} // namespace slang