blob: 4ae79b952cbd56f305b2aedaff844e2b72c3b2f6 [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) {
Stephen Hines832429f2011-02-25 16:05:37 -0800896 Diags->Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
897 Diags->getCustomDiagID(clang::Diagnostic::Error,
898 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -0800899 // TODO(srhines): Support setting arrays of RS objects
900 // StmtArray[StmtCount++] =
901 // CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
902 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
903 StmtArray[StmtCount++] =
904 CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
905 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
906 StmtArray[StmtCount++] =
907 CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
908 } else {
909 slangAssert(false);
910 }
911 }
912
913 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
914
915 // We still need to actually do the overall struct copy. For simplicity,
916 // we just do a straight-up assignment (which will still preserve all
917 // the proper RS object reference counts).
918 clang::BinaryOperator *CopyStruct =
919 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc);
920 StmtArray[StmtCount++] = CopyStruct;
921
922 clang::CompoundStmt *CS =
923 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
924
925 delete [] StmtArray;
926
927 return CS;
928}
929
930} // namespace
931
932void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
933 clang::BinaryOperator *AS,
934 clang::Diagnostic *Diags) {
935
936 clang::QualType QT = AS->getType();
937
938 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
939 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
940
Stephen Hines832429f2011-02-25 16:05:37 -0800941 clang::SourceLocation Loc = AS->getExprLoc();
Stephen Hines2bb67db2011-02-11 01:36:40 -0800942 clang::Stmt *UpdatedStmt = NULL;
943
944 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
945 // By definition, this is a struct assignment if we get here
946 UpdatedStmt =
947 CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
948 } else {
949 UpdatedStmt =
950 CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
951 }
952
953 ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800954 return;
955}
956
957void RSObjectRefCount::Scope::AppendRSObjectInit(
Stephen Hinesa0611e62011-02-11 16:35:47 -0800958 clang::Diagnostic *Diags,
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800959 clang::VarDecl *VD,
960 clang::DeclStmt *DS,
961 RSExportPrimitiveType::DataType DT,
962 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -0800963 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800964
965 if (!InitExpr) {
966 return;
967 }
968
Stephen Hinesa0611e62011-02-11 16:35:47 -0800969 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
970 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
971 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
972 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
973
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800974 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
975 // TODO(srhines): Skip struct initialization right now
Stephen Hinesa0611e62011-02-11 16:35:47 -0800976 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
977 clang::DeclRefExpr *RefRSVar =
978 clang::DeclRefExpr::Create(C,
979 NULL,
980 VD->getQualifierRange(),
981 VD,
982 Loc,
983 T->getCanonicalTypeInternal());
984
985 clang::Stmt *RSSetObjectOps =
986 CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc);
987
988 AppendAfterStmt(C, mCS, DS, RSSetObjectOps);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800989 return;
990 }
991
992 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800993 slangAssert((SetObjectFD != NULL) &&
994 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800995
996 clang::QualType SetObjectFDType = SetObjectFD->getType();
997 clang::QualType SetObjectFDArgType[2];
998 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
999 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1000
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001001 clang::Expr *RefRSSetObjectFD =
1002 clang::DeclRefExpr::Create(C,
1003 NULL,
1004 SetObjectFD->getQualifierRange(),
1005 SetObjectFD,
1006 Loc,
1007 SetObjectFDType);
1008
1009 clang::Expr *RSSetObjectFP =
1010 clang::ImplicitCastExpr::Create(C,
1011 C.getPointerType(SetObjectFDType),
1012 clang::CK_FunctionToPointerDecay,
1013 RefRSSetObjectFD,
1014 NULL,
1015 clang::VK_RValue);
1016
1017 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1018 clang::DeclRefExpr *RefRSVar =
1019 clang::DeclRefExpr::Create(C,
1020 NULL,
1021 VD->getQualifierRange(),
1022 VD,
1023 Loc,
1024 T->getCanonicalTypeInternal());
1025
1026 clang::Expr *ArgList[2];
1027 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1028 clang::UO_AddrOf,
1029 SetObjectFDArgType[0],
1030 Loc);
1031 ArgList[1] = InitExpr;
1032
1033 clang::CallExpr *RSSetObjectCall =
1034 new(C) clang::CallExpr(C,
1035 RSSetObjectFP,
1036 ArgList,
1037 2,
1038 SetObjectFD->getCallResultType(),
1039 Loc);
1040
1041 AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001042
1043 return;
1044}
1045
Stephen Hines1bdd4972010-11-08 17:35:08 -08001046void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001047 std::list<clang::Stmt*> RSClearObjectCalls;
Stephen Hines1bdd4972010-11-08 17:35:08 -08001048 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1049 E = mRSO.end();
1050 I != E;
1051 I++) {
Stephen Hinesa858cb62011-01-17 12:17:51 -08001052 clang::Stmt *S = ClearRSObject(*I);
1053 if (S) {
1054 RSClearObjectCalls.push_back(S);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001055 }
1056 }
1057 if (RSClearObjectCalls.size() > 0) {
Stephen Hines4464d822010-11-11 16:45:08 -08001058 DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
1059 DV.Visit(mCS);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001060 }
1061 return;
1062}
1063
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001064clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001065 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001066 clang::ASTContext &C = VD->getASTContext();
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001067 clang::DeclContext *DC = VD->getDeclContext();
1068 clang::SourceRange Range = VD->getQualifierRange();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001069 clang::SourceLocation Loc = VD->getLocation();
1070 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001071
Stephen Hines1bdd4972010-11-08 17:35:08 -08001072 // Reference expr to target RS object variable
1073 clang::DeclRefExpr *RefRSVar =
1074 clang::DeclRefExpr::Create(C,
1075 NULL,
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001076 Range,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001077 VD,
1078 Loc,
Stephen Hines03981a32010-12-14 19:45:49 -08001079 T->getCanonicalTypeInternal());
Stephen Hines1bdd4972010-11-08 17:35:08 -08001080
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001081 if (T->isArrayType()) {
1082 return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc);
1083 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001084
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001085 RSExportPrimitiveType::DataType DT =
1086 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001087
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001088 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1089 DT == RSExportPrimitiveType::DataTypeIsStruct) {
1090 return ClearStructRSObject(C, DC, RefRSVar, Range, Loc);
1091 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001092
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001093 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1094 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001095
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001096 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001097}
1098
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001099bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1100 RSExportPrimitiveType::DataType *DT,
1101 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001102 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001103 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001104
1105 // Loop through array types to get to base type
1106 while (T && T->isArrayType()) {
1107 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001108 }
1109
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001110 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001111 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001112
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001113 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001114 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1115 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001116 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001117 } else {
1118 return false;
1119 }
Stephen Hines2d095042010-11-12 18:13:56 -08001120 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001121
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001122 bool DataTypeIsRSObject = false;
1123 if (DataTypeIsStructWithRSObject) {
1124 DataTypeIsRSObject = true;
1125 } else {
1126 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1127 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001128 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001129
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001130 if (!DataTypeIsRSObject && *InitExpr) {
1131 // If we already have an initializer for a matrix type, we are done.
1132 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001133 }
1134
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001135 clang::Expr *ZeroInitializer =
1136 CreateZeroInitializerForRSSpecificType(*DT,
1137 VD->getASTContext(),
1138 VD->getLocation());
1139
1140 if (ZeroInitializer) {
1141 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1142 VD->setInit(ZeroInitializer);
1143 }
1144
1145 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001146}
1147
1148clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1149 RSExportPrimitiveType::DataType DT,
1150 clang::ASTContext &C,
1151 const clang::SourceLocation &Loc) {
1152 clang::Expr *Res = NULL;
1153 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001154 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001155 case RSExportPrimitiveType::DataTypeRSElement:
1156 case RSExportPrimitiveType::DataTypeRSType:
1157 case RSExportPrimitiveType::DataTypeRSAllocation:
1158 case RSExportPrimitiveType::DataTypeRSSampler:
1159 case RSExportPrimitiveType::DataTypeRSScript:
1160 case RSExportPrimitiveType::DataTypeRSMesh:
1161 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1162 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1163 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1164 case RSExportPrimitiveType::DataTypeRSProgramStore:
1165 case RSExportPrimitiveType::DataTypeRSFont: {
1166 // (ImplicitCastExpr 'nullptr_t'
1167 // (IntegerLiteral 0)))
1168 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1169 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1170 clang::Expr *CastToNull =
1171 clang::ImplicitCastExpr::Create(C,
1172 C.NullPtrTy,
1173 clang::CK_IntegralToPointer,
1174 Int0,
1175 NULL,
1176 clang::VK_RValue);
1177
Stephen Hinese639eb52010-11-08 19:27:20 -08001178 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001179 break;
1180 }
1181 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1182 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1183 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1184 // RS matrix is not completely an RS object. They hold data by themselves.
1185 // (InitListExpr rs_matrix2x2
1186 // (InitListExpr float[4]
1187 // (FloatingLiteral 0)
1188 // (FloatingLiteral 0)
1189 // (FloatingLiteral 0)
1190 // (FloatingLiteral 0)))
1191 clang::QualType FloatTy = C.FloatTy;
1192 // Constructor sets value to 0.0f by default
1193 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1194 clang::FloatingLiteral *Float0Val =
1195 clang::FloatingLiteral::Create(C,
1196 Val,
1197 /* isExact = */true,
1198 FloatTy,
1199 Loc);
1200
1201 unsigned N = 0;
1202 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1203 N = 2;
1204 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1205 N = 3;
1206 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1207 N = 4;
1208
1209 // Directly allocate 16 elements instead of dynamically allocate N*N
1210 clang::Expr *InitVals[16];
1211 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1212 InitVals[i] = Float0Val;
1213 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -08001214 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001215 InitExpr->setType(C.getConstantArrayType(FloatTy,
1216 llvm::APInt(32, 4),
1217 clang::ArrayType::Normal,
1218 /* EltTypeQuals = */0));
1219
Stephen Hinese639eb52010-11-08 19:27:20 -08001220 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001221 break;
1222 }
1223 case RSExportPrimitiveType::DataTypeUnknown:
1224 case RSExportPrimitiveType::DataTypeFloat16:
1225 case RSExportPrimitiveType::DataTypeFloat32:
1226 case RSExportPrimitiveType::DataTypeFloat64:
1227 case RSExportPrimitiveType::DataTypeSigned8:
1228 case RSExportPrimitiveType::DataTypeSigned16:
1229 case RSExportPrimitiveType::DataTypeSigned32:
1230 case RSExportPrimitiveType::DataTypeSigned64:
1231 case RSExportPrimitiveType::DataTypeUnsigned8:
1232 case RSExportPrimitiveType::DataTypeUnsigned16:
1233 case RSExportPrimitiveType::DataTypeUnsigned32:
1234 case RSExportPrimitiveType::DataTypeUnsigned64:
1235 case RSExportPrimitiveType::DataTypeBoolean:
1236 case RSExportPrimitiveType::DataTypeUnsigned565:
1237 case RSExportPrimitiveType::DataTypeUnsigned5551:
1238 case RSExportPrimitiveType::DataTypeUnsigned4444:
1239 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001240 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001241 }
1242 // No default case will enable compiler detecting the missing cases
1243 }
1244
1245 return Res;
1246}
1247
1248void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1249 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1250 I != E;
1251 I++) {
1252 clang::Decl *D = *I;
1253 if (D->getKind() == clang::Decl::Var) {
1254 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001255 RSExportPrimitiveType::DataType DT =
1256 RSExportPrimitiveType::DataTypeUnknown;
1257 clang::Expr *InitExpr = NULL;
1258 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001259 getCurrentScope()->addRSObject(VD);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001260 getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001261 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001262 }
1263 }
1264 return;
1265}
1266
1267void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1268 if (!CS->body_empty()) {
1269 // Push a new scope
1270 Scope *S = new Scope(CS);
1271 mScopeStack.push(S);
1272
1273 VisitStmt(CS);
1274
1275 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001276 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001277 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001278 mScopeStack.pop();
1279 delete S;
1280 }
1281 return;
1282}
1283
1284void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001285 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001286
Stephen Hines2bb67db2011-02-11 01:36:40 -08001287 if (CountRSObjectTypes(QT.getTypePtr())) {
1288 getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001289 }
1290
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001291 return;
1292}
1293
1294void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1295 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1296 I != E;
1297 I++) {
1298 if (clang::Stmt *Child = *I) {
1299 Visit(Child);
1300 }
1301 }
1302 return;
1303}
1304
Stephen Hinese639eb52010-11-08 19:27:20 -08001305} // namespace slang