blob: e945fcbf31bd8e39cbb66d5c9381006e4a65fcba [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"
Loganbe274822011-02-16 22:02:54 +080023#include "clang/AST/NestedNameSpecifier.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070024#include "clang/AST/OperationKinds.h"
25#include "clang/AST/Stmt.h"
26#include "clang/AST/StmtVisitor.h"
27
Stephen Hines6e6578a2011-02-07 18:05:48 -080028#include "slang_assert.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070029#include "slang_rs.h"
Stephen Hines292e00a2011-03-18 19:11:30 -070030#include "slang_rs_ast_replace.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070031#include "slang_rs_export_type.h"
32
Stephen Hinese639eb52010-11-08 19:27:20 -080033namespace slang {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070034
Stephen Hinesf2174cf2011-02-09 23:21:37 -080035clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080036 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
37 RSExportPrimitiveType::FirstRSObjectType + 1];
Stephen Hinesf2174cf2011-02-09 23:21:37 -080038clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080039 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
40 RSExportPrimitiveType::FirstRSObjectType + 1];
41
Stephen Hinesf2174cf2011-02-09 23:21:37 -080042void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080043 for (unsigned i = 0;
44 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
45 i++) {
46 RSSetObjectFD[i] = NULL;
47 RSClearObjectFD[i] = NULL;
48 }
49
50 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
51
52 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
53 E = TUDecl->decls_end(); I != E; I++) {
54 if ((I->getKind() >= clang::Decl::firstFunction) &&
55 (I->getKind() <= clang::Decl::lastFunction)) {
56 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
57
58 // points to RSSetObjectFD or RSClearObjectFD
59 clang::FunctionDecl **RSObjectFD;
60
61 if (FD->getName() == "rsSetObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080062 slangAssert((FD->getNumParams() == 2) &&
63 "Invalid rsSetObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080064 RSObjectFD = RSSetObjectFD;
65 } else if (FD->getName() == "rsClearObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080066 slangAssert((FD->getNumParams() == 1) &&
67 "Invalid rsClearObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080068 RSObjectFD = RSClearObjectFD;
Stephen Hinese639eb52010-11-08 19:27:20 -080069 } else {
Stephen Hines1bdd4972010-11-08 17:35:08 -080070 continue;
71 }
72
73 const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
74 clang::QualType PVT = PVD->getOriginalType();
75 // The first parameter must be a pointer like rs_allocation*
Stephen Hines6e6578a2011-02-07 18:05:48 -080076 slangAssert(PVT->isPointerType() &&
77 "Invalid rs{Set,Clear}Object function prototype (pointer param)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080078
79 // The rs object type passed to the FD
80 clang::QualType RST = PVT->getPointeeType();
81 RSExportPrimitiveType::DataType DT =
82 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
Stephen Hines6e6578a2011-02-07 18:05:48 -080083 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
Stephen Hines1bdd4972010-11-08 17:35:08 -080084 && "must be RS object type");
85
86 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
87 }
88 }
89}
90
Stephen Hines4464d822010-11-11 16:45:08 -080091namespace {
92
Stephen Hines292e00a2011-03-18 19:11:30 -070093// This function constructs a new CompoundStmt from the input StmtList.
94static clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
95 std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -080096 unsigned NewStmtCount = StmtList.size();
Stephen Hines292e00a2011-03-18 19:11:30 -070097 unsigned CompoundStmtCount = 0;
Stephen Hines1bdd4972010-11-08 17:35:08 -080098
Stephen Hines292e00a2011-03-18 19:11:30 -070099 clang::Stmt **CompoundStmtList;
100 CompoundStmtList = new clang::Stmt*[NewStmtCount];
101
102 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
103 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
104 for ( ; I != E; I++) {
105 CompoundStmtList[CompoundStmtCount++] = *I;
106 }
107 slangAssert(CompoundStmtCount == NewStmtCount);
108
109 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(C,
110 CompoundStmtList,
111 CompoundStmtCount,
112 Loc,
113 Loc);
114
115 delete [] CompoundStmtList;
116
117 return CS;
118}
119
120static void AppendAfterStmt(clang::ASTContext &C,
121 clang::CompoundStmt *CS,
122 clang::Stmt *S,
123 std::list<clang::Stmt*> &StmtList) {
124 slangAssert(CS);
125 clang::CompoundStmt::body_iterator bI = CS->body_begin();
126 clang::CompoundStmt::body_iterator bE = CS->body_end();
127 clang::Stmt **UpdatedStmtList =
128 new clang::Stmt*[CS->size() + StmtList.size()];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800129
130 unsigned UpdatedStmtCount = 0;
Stephen Hines292e00a2011-03-18 19:11:30 -0700131 unsigned Once = 0;
132 for ( ; bI != bE; bI++) {
133 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
134 // If we come across a return here, we don't have anything we can
135 // reasonably replace. We should have already inserted our destructor
136 // code in the proper spot, so we just clean up and return.
137 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800138
Stephen Hines292e00a2011-03-18 19:11:30 -0700139 return;
140 }
141
142 UpdatedStmtList[UpdatedStmtCount++] = *bI;
143
144 if ((*bI == S) && !Once) {
145 Once++;
146 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
147 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
148 for ( ; I != E; I++) {
149 UpdatedStmtList[UpdatedStmtCount++] = *I;
150 }
151 }
152 }
153 slangAssert(Once <= 1);
154
155 // When S is NULL, we are appending to the end of the CompoundStmt.
156 if (!S) {
157 slangAssert(Once == 0);
Stephen Hines03981a32010-12-14 19:45:49 -0800158 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
Stephen Hines292e00a2011-03-18 19:11:30 -0700159 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
160 for ( ; I != E; I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800161 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800162 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800163 }
164
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800165 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800166
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800167 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800168
169 return;
170}
171
Stephen Hinesa883ce32011-08-11 18:52:48 -0700172// This class visits a compound statement and inserts DtorStmt
173// in proper locations. This includes inserting it before any
Stephen Hines4464d822010-11-11 16:45:08 -0800174// return statement in any sub-block, at the end of the logical enclosing
175// scope (compound statement), and/or before any break/continue statement that
176// would resume outside the declared scope. We will not handle the case for
177// goto statements that leave a local scope.
Stephen Hines292e00a2011-03-18 19:11:30 -0700178//
179// To accomplish these goals, it collects a list of sub-Stmt's that
180// correspond to scope exit points. It then uses an RSASTReplace visitor to
181// transform the AST, inserting appropriate destructors before each of those
182// sub-Stmt's (and also before the exit of the outermost containing Stmt for
183// the scope).
Stephen Hines4464d822010-11-11 16:45:08 -0800184class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
185 private:
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700186 clang::ASTContext &mCtx;
Stephen Hines292e00a2011-03-18 19:11:30 -0700187
188 // The loop depth of the currently visited node.
189 int mLoopDepth;
190
191 // The switch statement depth of the currently visited node.
192 // Note that this is tracked separately from the loop depth because
193 // SwitchStmt-contained ContinueStmt's should have destructors for the
194 // corresponding loop scope.
195 int mSwitchDepth;
196
197 // The outermost statement block that we are currently visiting.
198 // This should always be a CompoundStmt.
199 clang::Stmt *mOuterStmt;
200
Stephen Hinesa883ce32011-08-11 18:52:48 -0700201 // The destructor to execute for this scope/variable.
202 clang::Stmt* mDtorStmt;
Stephen Hines292e00a2011-03-18 19:11:30 -0700203
204 // The stack of statements which should be replaced by a compound statement
Stephen Hinesa883ce32011-08-11 18:52:48 -0700205 // containing the new destructor call followed by the original Stmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700206 std::stack<clang::Stmt*> mReplaceStmtStack;
207
Stephen Hinesa883ce32011-08-11 18:52:48 -0700208 // The source location for the variable declaration that we are trying to
209 // insert destructors for. Note that InsertDestructors() will not generate
210 // destructor calls for source locations that occur lexically before this
211 // location.
212 clang::SourceLocation mVarLoc;
213
Stephen Hines4464d822010-11-11 16:45:08 -0800214 public:
Stephen Hines292e00a2011-03-18 19:11:30 -0700215 DestructorVisitor(clang::ASTContext &C,
216 clang::Stmt* OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700217 clang::Stmt* DtorStmt,
218 clang::SourceLocation VarLoc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700219
220 // This code walks the collected list of Stmts to replace and actually does
Stephen Hinesa883ce32011-08-11 18:52:48 -0700221 // the replacement. It also finishes up by appending the destructor to the
222 // current outermost CompoundStmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700223 void InsertDestructors() {
224 clang::Stmt *S = NULL;
Stephen Hinesa883ce32011-08-11 18:52:48 -0700225 clang::SourceManager &SM = mCtx.getSourceManager();
226 std::list<clang::Stmt *> StmtList;
227 StmtList.push_back(mDtorStmt);
228
Stephen Hines292e00a2011-03-18 19:11:30 -0700229 while (!mReplaceStmtStack.empty()) {
230 S = mReplaceStmtStack.top();
231 mReplaceStmtStack.pop();
232
Stephen Hinesa883ce32011-08-11 18:52:48 -0700233 // Skip all source locations that occur before the variable's
234 // declaration, since it won't have been initialized yet.
235 if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) {
236 continue;
237 }
238
239 StmtList.push_back(S);
Stephen Hines292e00a2011-03-18 19:11:30 -0700240 clang::CompoundStmt *CS =
Stephen Hinesa883ce32011-08-11 18:52:48 -0700241 BuildCompoundStmt(mCtx, StmtList, S->getLocEnd());
242 StmtList.pop_back();
Stephen Hines292e00a2011-03-18 19:11:30 -0700243
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700244 RSASTReplace R(mCtx);
Stephen Hines292e00a2011-03-18 19:11:30 -0700245 R.ReplaceStmt(mOuterStmt, S, CS);
246 }
Logan Chienab992e52011-07-20 22:06:52 +0800247 clang::CompoundStmt *CS =
248 llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt);
Stephen Hines292e00a2011-03-18 19:11:30 -0700249 slangAssert(CS);
Stephen Hinesa883ce32011-08-11 18:52:48 -0700250 AppendAfterStmt(mCtx, CS, NULL, StmtList);
Stephen Hines292e00a2011-03-18 19:11:30 -0700251 }
252
Stephen Hines4464d822010-11-11 16:45:08 -0800253 void VisitStmt(clang::Stmt *S);
254 void VisitCompoundStmt(clang::CompoundStmt *CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700255
256 void VisitBreakStmt(clang::BreakStmt *BS);
257 void VisitCaseStmt(clang::CaseStmt *CS);
258 void VisitContinueStmt(clang::ContinueStmt *CS);
259 void VisitDefaultStmt(clang::DefaultStmt *DS);
260 void VisitDoStmt(clang::DoStmt *DS);
261 void VisitForStmt(clang::ForStmt *FS);
262 void VisitIfStmt(clang::IfStmt *IS);
263 void VisitReturnStmt(clang::ReturnStmt *RS);
264 void VisitSwitchCase(clang::SwitchCase *SC);
265 void VisitSwitchStmt(clang::SwitchStmt *SS);
266 void VisitWhileStmt(clang::WhileStmt *WS);
Stephen Hines4464d822010-11-11 16:45:08 -0800267};
268
269DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hines292e00a2011-03-18 19:11:30 -0700270 clang::Stmt *OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700271 clang::Stmt *DtorStmt,
272 clang::SourceLocation VarLoc)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700273 : mCtx(C),
Stephen Hines292e00a2011-03-18 19:11:30 -0700274 mLoopDepth(0),
275 mSwitchDepth(0),
276 mOuterStmt(OuterStmt),
Stephen Hinesa883ce32011-08-11 18:52:48 -0700277 mDtorStmt(DtorStmt),
278 mVarLoc(VarLoc) {
Stephen Hines4464d822010-11-11 16:45:08 -0800279 return;
280}
281
282void DestructorVisitor::VisitStmt(clang::Stmt *S) {
283 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
284 I != E;
285 I++) {
286 if (clang::Stmt *Child = *I) {
287 Visit(Child);
288 }
289 }
290 return;
291}
292
Stephen Hines292e00a2011-03-18 19:11:30 -0700293void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
294 VisitStmt(CS);
295 return;
296}
297
298void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
299 VisitStmt(BS);
300 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
301 mReplaceStmtStack.push(BS);
302 }
303 return;
304}
305
306void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
307 VisitStmt(CS);
308 return;
309}
310
311void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
312 VisitStmt(CS);
313 if (mLoopDepth == 0) {
314 // Switch statements can have nested continues.
315 mReplaceStmtStack.push(CS);
316 }
317 return;
318}
319
320void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
321 VisitStmt(DS);
322 return;
323}
324
325void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
326 mLoopDepth++;
327 VisitStmt(DS);
328 mLoopDepth--;
329 return;
330}
331
332void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
333 mLoopDepth++;
334 VisitStmt(FS);
335 mLoopDepth--;
336 return;
337}
338
339void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
340 VisitStmt(IS);
341 return;
342}
343
344void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
345 mReplaceStmtStack.push(RS);
346 return;
347}
348
349void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
350 slangAssert(false && "Both case and default have specialized handlers");
351 VisitStmt(SC);
352 return;
353}
354
355void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
356 mSwitchDepth++;
357 VisitStmt(SS);
358 mSwitchDepth--;
359 return;
360}
361
362void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
363 mLoopDepth++;
364 VisitStmt(WS);
365 mLoopDepth--;
366 return;
367}
368
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800369clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
370 clang::Expr *RefRSVar,
371 clang::SourceLocation Loc) {
372 slangAssert(RefRSVar);
373 const clang::Type *T = RefRSVar->getType().getTypePtr();
374 slangAssert(!T->isArrayType() &&
375 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800376
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800377 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
378 slangAssert((ClearObjectFD != NULL) &&
379 "rsClearObject doesn't cover all RS object types");
380
381 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
382 clang::QualType ClearObjectFDArgType =
383 ClearObjectFD->getParamDecl(0)->getOriginalType();
384
385 // Example destructor for "rs_font localFont;"
386 //
387 // (CallExpr 'void'
388 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
389 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
390 // (UnaryOperator 'rs_font *' prefix '&'
391 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
392
393 // Get address of targeted RS object
394 clang::Expr *AddrRefRSVar =
395 new(C) clang::UnaryOperator(RefRSVar,
396 clang::UO_AddrOf,
397 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800398 clang::VK_RValue,
399 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800400 Loc);
401
402 clang::Expr *RefRSClearObjectFD =
403 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800404 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800405 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800406 ClearObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700407 false,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800408 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800409 ClearObjectFDType,
410 clang::VK_RValue,
411 NULL);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800412
413 clang::Expr *RSClearObjectFP =
414 clang::ImplicitCastExpr::Create(C,
415 C.getPointerType(ClearObjectFDType),
416 clang::CK_FunctionToPointerDecay,
417 RefRSClearObjectFD,
418 NULL,
419 clang::VK_RValue);
420
421 clang::CallExpr *RSClearObjectCall =
422 new(C) clang::CallExpr(C,
423 RSClearObjectFP,
424 &AddrRefRSVar,
425 1,
426 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800427 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800428 Loc);
429
430 return RSClearObjectCall;
431}
432
433static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800434 if (!T || !T->isArrayType()) {
435 return 0;
436 }
437
438 const clang::ConstantArrayType *CAT =
439 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800440 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800441}
442
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800443static clang::Stmt *ClearStructRSObject(
444 clang::ASTContext &C,
445 clang::DeclContext *DC,
446 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700447 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800448 clang::SourceLocation Loc);
449
450static clang::Stmt *ClearArrayRSObject(
451 clang::ASTContext &C,
452 clang::DeclContext *DC,
453 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700454 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800455 clang::SourceLocation Loc) {
456 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
457 slangAssert(BaseType->isArrayType());
458
459 int NumArrayElements = ArrayDim(BaseType);
460 // Actually extract out the base RS object type for use later
461 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800462
463 clang::Stmt *StmtArray[2] = {NULL};
464 int StmtCtr = 0;
465
Stephen Hines03981a32010-12-14 19:45:49 -0800466 if (NumArrayElements <= 0) {
467 return NULL;
468 }
469
470 // Example destructor loop for "rs_font fontArr[10];"
471 //
472 // (CompoundStmt
473 // (DeclStmt "int rsIntIter")
474 // (ForStmt
475 // (BinaryOperator 'int' '='
476 // (DeclRefExpr 'int' Var='rsIntIter')
477 // (IntegerLiteral 'int' 0))
478 // (BinaryOperator 'int' '<'
479 // (DeclRefExpr 'int' Var='rsIntIter')
480 // (IntegerLiteral 'int' 10)
481 // NULL << CondVar >>
482 // (UnaryOperator 'int' postfix '++'
483 // (DeclRefExpr 'int' Var='rsIntIter'))
484 // (CallExpr 'void'
485 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
486 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
487 // (UnaryOperator 'rs_font *' prefix '&'
488 // (ArraySubscriptExpr 'rs_font':'rs_font'
489 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
490 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
491 // (DeclRefExpr 'int' Var='rsIntIter')))))))
492
493 // Create helper variable for iterating through elements
494 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
495 clang::VarDecl *IIVD =
496 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800497 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700498 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800499 Loc,
500 &II,
501 C.IntTy,
502 C.getTrivialTypeSourceInfo(C.IntTy),
503 clang::SC_None,
504 clang::SC_None);
505 clang::Decl *IID = (clang::Decl *)IIVD;
506
507 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
508 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
509
510 // Form the actual destructor loop
511 // for (Init; Cond; Inc)
512 // RSClearObjectCall;
513
514 // Init -> "rsIntIter = 0"
515 clang::DeclRefExpr *RefrsIntIter =
516 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800517 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800518 clang::SourceLocation(),
Stephen Hines03981a32010-12-14 19:45:49 -0800519 IIVD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700520 false,
Stephen Hines03981a32010-12-14 19:45:49 -0800521 Loc,
Loganbe274822011-02-16 22:02:54 +0800522 C.IntTy,
523 clang::VK_RValue,
524 NULL);
Stephen Hines03981a32010-12-14 19:45:49 -0800525
526 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
527 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
528
529 clang::BinaryOperator *Init =
530 new(C) clang::BinaryOperator(RefrsIntIter,
531 Int0,
532 clang::BO_Assign,
533 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800534 clang::VK_RValue,
535 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800536 Loc);
537
538 // Cond -> "rsIntIter < NumArrayElements"
539 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
540 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
541
542 clang::BinaryOperator *Cond =
543 new(C) clang::BinaryOperator(RefrsIntIter,
544 NumArrayElementsExpr,
545 clang::BO_LT,
546 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800547 clang::VK_RValue,
548 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800549 Loc);
550
551 // Inc -> "rsIntIter++"
552 clang::UnaryOperator *Inc =
553 new(C) clang::UnaryOperator(RefrsIntIter,
554 clang::UO_PostInc,
555 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800556 clang::VK_RValue,
557 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800558 Loc);
559
560 // Body -> "rsClearObject(&VD[rsIntIter]);"
561 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800562
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800563 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800564 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800565 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800566 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800567 RefRSArr,
Stephen Hines03981a32010-12-14 19:45:49 -0800568 NULL,
569 clang::VK_RValue);
570
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800571 clang::Expr *RefRSArrPtrSubscript =
572 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hines03981a32010-12-14 19:45:49 -0800573 RefrsIntIter,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800574 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800575 clang::VK_RValue,
576 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800577 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800578
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800579 RSExportPrimitiveType::DataType DT =
580 RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800581
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800582 clang::Stmt *RSClearObjectCall = NULL;
583 if (BaseType->isArrayType()) {
584 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700585 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800586 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
587 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700588 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800589 } else {
590 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
591 }
Stephen Hines03981a32010-12-14 19:45:49 -0800592
593 clang::ForStmt *DestructorLoop =
594 new(C) clang::ForStmt(C,
595 Init,
596 Cond,
597 NULL, // no condVar
598 Inc,
599 RSClearObjectCall,
600 Loc,
601 Loc,
602 Loc);
603
604 StmtArray[StmtCtr++] = DestructorLoop;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800605 slangAssert(StmtCtr == 2);
Stephen Hines03981a32010-12-14 19:45:49 -0800606
607 clang::CompoundStmt *CS =
608 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
609
610 return CS;
611}
612
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700613static unsigned CountRSObjectTypes(clang::ASTContext &C,
614 const clang::Type *T,
615 clang::SourceLocation Loc) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800616 slangAssert(T);
617 unsigned RSObjectCount = 0;
618
619 if (T->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700620 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800621 }
622
623 RSExportPrimitiveType::DataType DT =
624 RSExportPrimitiveType::GetRSSpecificType(T);
625 if (DT != RSExportPrimitiveType::DataTypeUnknown) {
626 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
627 }
628
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700629 if (T->isUnionType()) {
630 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
631 RD = RD->getDefinition();
632 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
633 FE = RD->field_end();
634 FI != FE;
635 FI++) {
636 const clang::FieldDecl *FD = *FI;
637 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
638 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700639 slangAssert(false && "can't have unions with RS object types!");
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700640 return 0;
641 }
642 }
643 }
644
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800645 if (!T->isStructureType()) {
646 return 0;
647 }
648
649 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
650 RD = RD->getDefinition();
651 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
652 FE = RD->field_end();
653 FI != FE;
654 FI++) {
655 const clang::FieldDecl *FD = *FI;
656 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700657 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800658 // Sub-structs should only count once (as should arrays, etc.)
659 RSObjectCount++;
660 }
661 }
662
663 return RSObjectCount;
664}
665
666static clang::Stmt *ClearStructRSObject(
667 clang::ASTContext &C,
668 clang::DeclContext *DC,
669 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700670 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800671 clang::SourceLocation Loc) {
672 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
673
674 slangAssert(!BaseType->isArrayType());
675
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800676 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700677 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
678 RSExportPrimitiveType::DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800679
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700680 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800681
682 unsigned StmtCount = 0;
683 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800684 for (unsigned i = 0; i < FieldsToDestroy; i++) {
685 StmtArray[i] = NULL;
686 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800687
688 // Populate StmtArray by creating a destructor for each RS object field
689 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
690 RD = RD->getDefinition();
691 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
692 FE = RD->field_end();
693 FI != FE;
694 FI++) {
695 // We just look through all field declarations to see if we find a
696 // declaration for an RS object type (or an array of one).
697 bool IsArrayType = false;
698 clang::FieldDecl *FD = *FI;
699 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
700 const clang::Type *OrigType = FT;
701 while (FT && FT->isArrayType()) {
702 FT = FT->getArrayElementTypeNoTypeQual();
703 IsArrayType = true;
704 }
705
706 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
707 clang::DeclAccessPair FoundDecl =
708 clang::DeclAccessPair::make(FD, clang::AS_none);
709 clang::MemberExpr *RSObjectMember =
710 clang::MemberExpr::Create(C,
711 RefRSStruct,
712 false,
Loganbe274822011-02-16 22:02:54 +0800713 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800714 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800715 FD,
716 FoundDecl,
717 clang::DeclarationNameInfo(),
718 NULL,
Loganbe274822011-02-16 22:02:54 +0800719 OrigType->getCanonicalTypeInternal(),
720 clang::VK_RValue,
721 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800722
723 slangAssert(StmtCount < FieldsToDestroy);
724
725 if (IsArrayType) {
726 StmtArray[StmtCount++] = ClearArrayRSObject(C,
727 DC,
728 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700729 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800730 Loc);
731 } else {
732 StmtArray[StmtCount++] = ClearSingleRSObject(C,
733 RSObjectMember,
734 Loc);
735 }
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700736 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800737 // In this case, we have a nested struct. We may not end up filling all
738 // of the spaces in StmtArray (sub-structs should handle themselves
739 // with separate compound statements).
740 clang::DeclAccessPair FoundDecl =
741 clang::DeclAccessPair::make(FD, clang::AS_none);
742 clang::MemberExpr *RSObjectMember =
743 clang::MemberExpr::Create(C,
744 RefRSStruct,
745 false,
Loganbe274822011-02-16 22:02:54 +0800746 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800747 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800748 FD,
749 FoundDecl,
750 clang::DeclarationNameInfo(),
751 NULL,
Loganbe274822011-02-16 22:02:54 +0800752 OrigType->getCanonicalTypeInternal(),
753 clang::VK_RValue,
754 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800755
756 if (IsArrayType) {
757 StmtArray[StmtCount++] = ClearArrayRSObject(C,
758 DC,
759 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700760 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800761 Loc);
762 } else {
763 StmtArray[StmtCount++] = ClearStructRSObject(C,
764 DC,
765 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700766 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800767 Loc);
768 }
769 }
770 }
771
772 slangAssert(StmtCount > 0);
773 clang::CompoundStmt *CS =
774 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
775
776 delete [] StmtArray;
777
778 return CS;
779}
780
Stephen Hines2bb67db2011-02-11 01:36:40 -0800781static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800782 clang::Expr *DstExpr,
783 clang::Expr *SrcExpr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700784 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800785 clang::SourceLocation Loc) {
786 const clang::Type *T = DstExpr->getType().getTypePtr();
787 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800788 slangAssert((SetObjectFD != NULL) &&
789 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800790
791 clang::QualType SetObjectFDType = SetObjectFD->getType();
792 clang::QualType SetObjectFDArgType[2];
793 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
794 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
795
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800796 clang::Expr *RefRSSetObjectFD =
797 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800798 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800799 clang::SourceLocation(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800800 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700801 false,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800802 Loc,
Loganbe274822011-02-16 22:02:54 +0800803 SetObjectFDType,
804 clang::VK_RValue,
805 NULL);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800806
807 clang::Expr *RSSetObjectFP =
808 clang::ImplicitCastExpr::Create(C,
809 C.getPointerType(SetObjectFDType),
810 clang::CK_FunctionToPointerDecay,
811 RefRSSetObjectFD,
812 NULL,
813 clang::VK_RValue);
814
815 clang::Expr *ArgList[2];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800816 ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800817 clang::UO_AddrOf,
818 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +0800819 clang::VK_RValue,
820 clang::OK_Ordinary,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800821 Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800822 ArgList[1] = SrcExpr;
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800823
824 clang::CallExpr *RSSetObjectCall =
825 new(C) clang::CallExpr(C,
826 RSSetObjectFP,
827 ArgList,
828 2,
829 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800830 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800831 Loc);
832
Stephen Hines2bb67db2011-02-11 01:36:40 -0800833 return RSSetObjectCall;
834}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800835
Stephen Hines2bb67db2011-02-11 01:36:40 -0800836static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800837 clang::Expr *LHS,
838 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700839 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800840 clang::SourceLocation Loc);
841
Al Sutton246fa172012-02-23 13:09:08 +0000842/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800843 clang::Expr *DstArr,
844 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700845 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800846 clang::SourceLocation Loc) {
847 clang::DeclContext *DC = NULL;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800848 const clang::Type *BaseType = DstArr->getType().getTypePtr();
849 slangAssert(BaseType->isArrayType());
850
851 int NumArrayElements = ArrayDim(BaseType);
852 // Actually extract out the base RS object type for use later
853 BaseType = BaseType->getArrayElementTypeNoTypeQual();
854
855 clang::Stmt *StmtArray[2] = {NULL};
856 int StmtCtr = 0;
857
858 if (NumArrayElements <= 0) {
859 return NULL;
860 }
861
862 // Create helper variable for iterating through elements
863 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
864 clang::VarDecl *IIVD =
865 clang::VarDecl::Create(C,
866 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700867 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800868 Loc,
869 &II,
870 C.IntTy,
871 C.getTrivialTypeSourceInfo(C.IntTy),
872 clang::SC_None,
873 clang::SC_None);
874 clang::Decl *IID = (clang::Decl *)IIVD;
875
876 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
877 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
878
879 // Form the actual loop
880 // for (Init; Cond; Inc)
881 // RSSetObjectCall;
882
883 // Init -> "rsIntIter = 0"
884 clang::DeclRefExpr *RefrsIntIter =
885 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800886 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800887 IIVD,
888 Loc,
Loganbe274822011-02-16 22:02:54 +0800889 C.IntTy,
890 clang::VK_RValue,
891 NULL);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800892
893 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
894 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
895
896 clang::BinaryOperator *Init =
897 new(C) clang::BinaryOperator(RefrsIntIter,
898 Int0,
899 clang::BO_Assign,
900 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800901 clang::VK_RValue,
902 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800903 Loc);
904
905 // Cond -> "rsIntIter < NumArrayElements"
906 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
907 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
908
909 clang::BinaryOperator *Cond =
910 new(C) clang::BinaryOperator(RefrsIntIter,
911 NumArrayElementsExpr,
912 clang::BO_LT,
913 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800914 clang::VK_RValue,
915 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800916 Loc);
917
918 // Inc -> "rsIntIter++"
919 clang::UnaryOperator *Inc =
920 new(C) clang::UnaryOperator(RefrsIntIter,
921 clang::UO_PostInc,
922 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800923 clang::VK_RValue,
924 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800925 Loc);
926
927 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
928 // Loop operates on individual array elements
929
930 clang::Expr *DstArrPtr =
931 clang::ImplicitCastExpr::Create(C,
932 C.getPointerType(BaseType->getCanonicalTypeInternal()),
933 clang::CK_ArrayToPointerDecay,
934 DstArr,
935 NULL,
936 clang::VK_RValue);
937
938 clang::Expr *DstArrPtrSubscript =
939 new(C) clang::ArraySubscriptExpr(DstArrPtr,
940 RefrsIntIter,
941 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800942 clang::VK_RValue,
943 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800944 Loc);
945
946 clang::Expr *SrcArrPtr =
947 clang::ImplicitCastExpr::Create(C,
948 C.getPointerType(BaseType->getCanonicalTypeInternal()),
949 clang::CK_ArrayToPointerDecay,
950 SrcArr,
951 NULL,
952 clang::VK_RValue);
953
954 clang::Expr *SrcArrPtrSubscript =
955 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
956 RefrsIntIter,
957 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800958 clang::VK_RValue,
959 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800960 Loc);
961
962 RSExportPrimitiveType::DataType DT =
963 RSExportPrimitiveType::GetRSSpecificType(BaseType);
964
965 clang::Stmt *RSSetObjectCall = NULL;
966 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700967 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700968 SrcArrPtrSubscript,
969 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800970 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700971 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700972 SrcArrPtrSubscript,
973 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800974 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700975 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700976 SrcArrPtrSubscript,
977 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800978 }
979
980 clang::ForStmt *DestructorLoop =
981 new(C) clang::ForStmt(C,
982 Init,
983 Cond,
984 NULL, // no condVar
985 Inc,
986 RSSetObjectCall,
987 Loc,
988 Loc,
989 Loc);
990
991 StmtArray[StmtCtr++] = DestructorLoop;
992 slangAssert(StmtCtr == 2);
993
994 clang::CompoundStmt *CS =
995 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
996
997 return CS;
Al Sutton246fa172012-02-23 13:09:08 +0000998} */
Stephen Hines2bb67db2011-02-11 01:36:40 -0800999
1000static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -08001001 clang::Expr *LHS,
1002 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001003 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -08001004 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001005 clang::QualType QT = LHS->getType();
1006 const clang::Type *T = QT.getTypePtr();
1007 slangAssert(T->isStructureType());
1008 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
1009
1010 // Keep an extra slot for the original copy (memcpy)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001011 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001012
1013 unsigned StmtCount = 0;
1014 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
1015 for (unsigned i = 0; i < FieldsToSet; i++) {
1016 StmtArray[i] = NULL;
1017 }
1018
1019 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
1020 RD = RD->getDefinition();
1021 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1022 FE = RD->field_end();
1023 FI != FE;
1024 FI++) {
1025 bool IsArrayType = false;
1026 clang::FieldDecl *FD = *FI;
1027 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1028 const clang::Type *OrigType = FT;
1029
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001030 if (!CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001031 // Skip to next if we don't have any viable RS object types
1032 continue;
1033 }
1034
1035 clang::DeclAccessPair FoundDecl =
1036 clang::DeclAccessPair::make(FD, clang::AS_none);
1037 clang::MemberExpr *DstMember =
1038 clang::MemberExpr::Create(C,
1039 LHS,
1040 false,
Loganbe274822011-02-16 22:02:54 +08001041 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001042 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001043 FD,
1044 FoundDecl,
1045 clang::DeclarationNameInfo(),
1046 NULL,
Loganbe274822011-02-16 22:02:54 +08001047 OrigType->getCanonicalTypeInternal(),
1048 clang::VK_RValue,
1049 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001050
1051 clang::MemberExpr *SrcMember =
1052 clang::MemberExpr::Create(C,
1053 RHS,
1054 false,
Loganbe274822011-02-16 22:02:54 +08001055 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001056 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001057 FD,
1058 FoundDecl,
1059 clang::DeclarationNameInfo(),
1060 NULL,
Loganbe274822011-02-16 22:02:54 +08001061 OrigType->getCanonicalTypeInternal(),
1062 clang::VK_RValue,
1063 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001064
1065 if (FT->isArrayType()) {
1066 FT = FT->getArrayElementTypeNoTypeQual();
1067 IsArrayType = true;
1068 }
1069
1070 RSExportPrimitiveType::DataType DT =
1071 RSExportPrimitiveType::GetRSSpecificType(FT);
1072
1073 if (IsArrayType) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001074 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
1075 DiagEngine.Report(
1076 clang::FullSourceLoc(Loc, C.getSourceManager()),
1077 DiagEngine.getCustomDiagID(
1078 clang::DiagnosticsEngine::Error,
1079 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -08001080 // TODO(srhines): Support setting arrays of RS objects
1081 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001082 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001083 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
1084 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001085 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001086 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
1087 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001088 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001089 } else {
1090 slangAssert(false);
1091 }
1092 }
1093
1094 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
1095
1096 // We still need to actually do the overall struct copy. For simplicity,
1097 // we just do a straight-up assignment (which will still preserve all
1098 // the proper RS object reference counts).
1099 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001100 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
1101 clang::VK_RValue, clang::OK_Ordinary, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001102 StmtArray[StmtCount++] = CopyStruct;
1103
1104 clang::CompoundStmt *CS =
1105 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
1106
1107 delete [] StmtArray;
1108
1109 return CS;
1110}
1111
1112} // namespace
1113
1114void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001115 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001116
1117 clang::QualType QT = AS->getType();
1118
1119 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1120 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1121
Stephen Hines832429f2011-02-25 16:05:37 -08001122 clang::SourceLocation Loc = AS->getExprLoc();
Stephen Hines9f1d0aa2011-12-18 15:41:00 -08001123 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001124 clang::Stmt *UpdatedStmt = NULL;
1125
1126 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1127 // By definition, this is a struct assignment if we get here
1128 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001129 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001130 } else {
1131 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001132 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001133 }
1134
Stephen Hines292e00a2011-03-18 19:11:30 -07001135 RSASTReplace R(C);
1136 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001137 return;
1138}
1139
1140void RSObjectRefCount::Scope::AppendRSObjectInit(
1141 clang::VarDecl *VD,
1142 clang::DeclStmt *DS,
1143 RSExportPrimitiveType::DataType DT,
1144 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001145 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001146
1147 if (!InitExpr) {
1148 return;
1149 }
1150
Stephen Hinesa0611e62011-02-11 16:35:47 -08001151 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1152 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1153 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
1154 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001155 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
1156 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001157
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001158 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001159 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1160 clang::DeclRefExpr *RefRSVar =
1161 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001162 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001163 clang::SourceLocation(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001164 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001165 false,
Stephen Hinesa0611e62011-02-11 16:35:47 -08001166 Loc,
Loganbe274822011-02-16 22:02:54 +08001167 T->getCanonicalTypeInternal(),
1168 clang::VK_RValue,
1169 NULL);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001170
1171 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001172 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001173
Stephen Hines292e00a2011-03-18 19:11:30 -07001174 std::list<clang::Stmt*> StmtList;
1175 StmtList.push_back(RSSetObjectOps);
1176 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001177 return;
1178 }
1179
1180 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -08001181 slangAssert((SetObjectFD != NULL) &&
1182 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001183
1184 clang::QualType SetObjectFDType = SetObjectFD->getType();
1185 clang::QualType SetObjectFDArgType[2];
1186 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1187 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1188
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001189 clang::Expr *RefRSSetObjectFD =
1190 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001191 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001192 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001193 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001194 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001195 Loc,
Loganbe274822011-02-16 22:02:54 +08001196 SetObjectFDType,
1197 clang::VK_RValue,
1198 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001199
1200 clang::Expr *RSSetObjectFP =
1201 clang::ImplicitCastExpr::Create(C,
1202 C.getPointerType(SetObjectFDType),
1203 clang::CK_FunctionToPointerDecay,
1204 RefRSSetObjectFD,
1205 NULL,
1206 clang::VK_RValue);
1207
1208 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1209 clang::DeclRefExpr *RefRSVar =
1210 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001211 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001212 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001213 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001214 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001215 Loc,
Loganbe274822011-02-16 22:02:54 +08001216 T->getCanonicalTypeInternal(),
1217 clang::VK_RValue,
1218 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001219
1220 clang::Expr *ArgList[2];
1221 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1222 clang::UO_AddrOf,
1223 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +08001224 clang::VK_RValue,
1225 clang::OK_Ordinary,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001226 Loc);
1227 ArgList[1] = InitExpr;
1228
1229 clang::CallExpr *RSSetObjectCall =
1230 new(C) clang::CallExpr(C,
1231 RSSetObjectFP,
1232 ArgList,
1233 2,
1234 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001235 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001236 Loc);
1237
Stephen Hines292e00a2011-03-18 19:11:30 -07001238 std::list<clang::Stmt*> StmtList;
1239 StmtList.push_back(RSSetObjectCall);
1240 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001241
1242 return;
1243}
1244
Stephen Hines1bdd4972010-11-08 17:35:08 -08001245void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hines1bdd4972010-11-08 17:35:08 -08001246 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1247 E = mRSO.end();
1248 I != E;
1249 I++) {
Stephen Hinesa883ce32011-08-11 18:52:48 -07001250 clang::VarDecl *VD = *I;
Stephen Hines3f175af2011-09-16 16:26:29 -07001251 clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext());
Stephen Hinesa883ce32011-08-11 18:52:48 -07001252 if (RSClearObjectCall) {
1253 DestructorVisitor DV((*mRSO.begin())->getASTContext(),
1254 mCS,
1255 RSClearObjectCall,
1256 VD->getSourceRange().getBegin());
1257 DV.Visit(mCS);
1258 DV.InsertDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001259 }
1260 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001261 return;
1262}
1263
Stephen Hines3f175af2011-09-16 16:26:29 -07001264clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
1265 clang::VarDecl *VD,
1266 clang::DeclContext *DC) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001267 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001268 clang::ASTContext &C = VD->getASTContext();
1269 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001270 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001271 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001272
Stephen Hines1bdd4972010-11-08 17:35:08 -08001273 // Reference expr to target RS object variable
1274 clang::DeclRefExpr *RefRSVar =
1275 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001276 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001277 clang::SourceLocation(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001278 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001279 false,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001280 Loc,
Loganbe274822011-02-16 22:02:54 +08001281 T->getCanonicalTypeInternal(),
1282 clang::VK_RValue,
1283 NULL);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001284
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001285 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001286 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001287 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001288
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001289 RSExportPrimitiveType::DataType DT =
1290 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001291
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001292 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1293 DT == RSExportPrimitiveType::DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001294 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001295 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001296
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001297 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1298 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001299
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001300 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001301}
1302
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001303bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1304 RSExportPrimitiveType::DataType *DT,
1305 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001306 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001307 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001308
1309 // Loop through array types to get to base type
1310 while (T && T->isArrayType()) {
1311 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001312 }
1313
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001314 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001315 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001316
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001317 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001318 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1319 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001320 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001321 } else {
1322 return false;
1323 }
Stephen Hines2d095042010-11-12 18:13:56 -08001324 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001325
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001326 bool DataTypeIsRSObject = false;
1327 if (DataTypeIsStructWithRSObject) {
1328 DataTypeIsRSObject = true;
1329 } else {
1330 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1331 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001332 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001333
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001334 if (!DataTypeIsRSObject && *InitExpr) {
1335 // If we already have an initializer for a matrix type, we are done.
1336 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001337 }
1338
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001339 clang::Expr *ZeroInitializer =
1340 CreateZeroInitializerForRSSpecificType(*DT,
1341 VD->getASTContext(),
1342 VD->getLocation());
1343
1344 if (ZeroInitializer) {
1345 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1346 VD->setInit(ZeroInitializer);
1347 }
1348
1349 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001350}
1351
1352clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1353 RSExportPrimitiveType::DataType DT,
1354 clang::ASTContext &C,
1355 const clang::SourceLocation &Loc) {
1356 clang::Expr *Res = NULL;
1357 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001358 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001359 case RSExportPrimitiveType::DataTypeRSElement:
1360 case RSExportPrimitiveType::DataTypeRSType:
1361 case RSExportPrimitiveType::DataTypeRSAllocation:
1362 case RSExportPrimitiveType::DataTypeRSSampler:
1363 case RSExportPrimitiveType::DataTypeRSScript:
1364 case RSExportPrimitiveType::DataTypeRSMesh:
Jason Samsdb6dfdf2011-11-07 18:11:10 -08001365 case RSExportPrimitiveType::DataTypeRSPath:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001366 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1367 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1368 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1369 case RSExportPrimitiveType::DataTypeRSProgramStore:
1370 case RSExportPrimitiveType::DataTypeRSFont: {
1371 // (ImplicitCastExpr 'nullptr_t'
1372 // (IntegerLiteral 0)))
1373 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1374 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1375 clang::Expr *CastToNull =
1376 clang::ImplicitCastExpr::Create(C,
1377 C.NullPtrTy,
1378 clang::CK_IntegralToPointer,
1379 Int0,
1380 NULL,
1381 clang::VK_RValue);
1382
Stephen Hinese639eb52010-11-08 19:27:20 -08001383 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001384 break;
1385 }
1386 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1387 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1388 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1389 // RS matrix is not completely an RS object. They hold data by themselves.
1390 // (InitListExpr rs_matrix2x2
1391 // (InitListExpr float[4]
1392 // (FloatingLiteral 0)
1393 // (FloatingLiteral 0)
1394 // (FloatingLiteral 0)
1395 // (FloatingLiteral 0)))
1396 clang::QualType FloatTy = C.FloatTy;
1397 // Constructor sets value to 0.0f by default
1398 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1399 clang::FloatingLiteral *Float0Val =
1400 clang::FloatingLiteral::Create(C,
1401 Val,
1402 /* isExact = */true,
1403 FloatTy,
1404 Loc);
1405
1406 unsigned N = 0;
1407 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1408 N = 2;
1409 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1410 N = 3;
1411 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1412 N = 4;
1413
1414 // Directly allocate 16 elements instead of dynamically allocate N*N
1415 clang::Expr *InitVals[16];
1416 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1417 InitVals[i] = Float0Val;
1418 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -08001419 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001420 InitExpr->setType(C.getConstantArrayType(FloatTy,
Stephen Hines4c622e02011-11-10 18:57:34 -08001421 llvm::APInt(32, N * N),
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001422 clang::ArrayType::Normal,
1423 /* EltTypeQuals = */0));
1424
Stephen Hinese639eb52010-11-08 19:27:20 -08001425 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001426 break;
1427 }
1428 case RSExportPrimitiveType::DataTypeUnknown:
1429 case RSExportPrimitiveType::DataTypeFloat16:
1430 case RSExportPrimitiveType::DataTypeFloat32:
1431 case RSExportPrimitiveType::DataTypeFloat64:
1432 case RSExportPrimitiveType::DataTypeSigned8:
1433 case RSExportPrimitiveType::DataTypeSigned16:
1434 case RSExportPrimitiveType::DataTypeSigned32:
1435 case RSExportPrimitiveType::DataTypeSigned64:
1436 case RSExportPrimitiveType::DataTypeUnsigned8:
1437 case RSExportPrimitiveType::DataTypeUnsigned16:
1438 case RSExportPrimitiveType::DataTypeUnsigned32:
1439 case RSExportPrimitiveType::DataTypeUnsigned64:
1440 case RSExportPrimitiveType::DataTypeBoolean:
1441 case RSExportPrimitiveType::DataTypeUnsigned565:
1442 case RSExportPrimitiveType::DataTypeUnsigned5551:
1443 case RSExportPrimitiveType::DataTypeUnsigned4444:
1444 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001445 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001446 }
1447 // No default case will enable compiler detecting the missing cases
1448 }
1449
1450 return Res;
1451}
1452
1453void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1454 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1455 I != E;
1456 I++) {
1457 clang::Decl *D = *I;
1458 if (D->getKind() == clang::Decl::Var) {
1459 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001460 RSExportPrimitiveType::DataType DT =
1461 RSExportPrimitiveType::DataTypeUnknown;
1462 clang::Expr *InitExpr = NULL;
1463 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001464 getCurrentScope()->addRSObject(VD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001465 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001466 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001467 }
1468 }
1469 return;
1470}
1471
1472void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1473 if (!CS->body_empty()) {
1474 // Push a new scope
1475 Scope *S = new Scope(CS);
1476 mScopeStack.push(S);
1477
1478 VisitStmt(CS);
1479
1480 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001481 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001482 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001483 mScopeStack.pop();
1484 delete S;
1485 }
1486 return;
1487}
1488
1489void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001490 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001491
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001492 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1493 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001494 }
1495
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001496 return;
1497}
1498
1499void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1500 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1501 I != E;
1502 I++) {
1503 if (clang::Stmt *Child = *I) {
1504 Visit(Child);
1505 }
1506 }
1507 return;
1508}
1509
Stephen Hines688e64b2011-08-23 16:01:25 -07001510// This function walks the list of global variables and (potentially) creates
1511// a single global static destructor function that properly decrements
1512// reference counts on the contained RS object types.
1513clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1514 Init();
1515
1516 clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1517 clang::SourceLocation loc;
1518
Stephen Hines3f175af2011-09-16 16:26:29 -07001519 llvm::StringRef SR(".rs.dtor");
1520 clang::IdentifierInfo &II = mCtx.Idents.get(SR);
1521 clang::DeclarationName N(&II);
1522 clang::FunctionProtoType::ExtProtoInfo EPI;
1523 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy, NULL, 0, EPI);
1524 clang::FunctionDecl *FD = NULL;
1525
Stephen Hines688e64b2011-08-23 16:01:25 -07001526 // Generate rsClearObject() call chains for every global variable
1527 // (whether static or extern).
1528 std::list<clang::Stmt *> StmtList;
1529 for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1530 E = DC->decls_end(); I != E; I++) {
1531 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1532 if (VD) {
1533 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) {
Stephen Hines3f175af2011-09-16 16:26:29 -07001534 if (!FD) {
1535 // Only create FD if we are going to use it.
1536 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, NULL);
1537 }
1538 // Make sure to create any helpers within the function's DeclContext,
1539 // not the one associated with the global translation unit.
1540 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
Stephen Hines688e64b2011-08-23 16:01:25 -07001541 StmtList.push_back(RSClearObjectCall);
1542 }
1543 }
1544 }
1545
1546 // Nothing needs to be destroyed, so don't emit a dtor.
1547 if (StmtList.empty()) {
1548 return NULL;
1549 }
1550
Stephen Hines688e64b2011-08-23 16:01:25 -07001551 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1552
1553 FD->setBody(CS);
1554
1555 return FD;
1556}
1557
Stephen Hinese639eb52010-11-08 19:27:20 -08001558} // namespace slang