blob: 9a4057b60257055f558335a36088264727da6200 [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
Stephen Hines23c43582013-01-09 20:02:04 -0800109 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
110 C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700111
112 delete [] CompoundStmtList;
113
114 return CS;
115}
116
117static void AppendAfterStmt(clang::ASTContext &C,
118 clang::CompoundStmt *CS,
119 clang::Stmt *S,
120 std::list<clang::Stmt*> &StmtList) {
121 slangAssert(CS);
122 clang::CompoundStmt::body_iterator bI = CS->body_begin();
123 clang::CompoundStmt::body_iterator bE = CS->body_end();
124 clang::Stmt **UpdatedStmtList =
125 new clang::Stmt*[CS->size() + StmtList.size()];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800126
127 unsigned UpdatedStmtCount = 0;
Stephen Hines292e00a2011-03-18 19:11:30 -0700128 unsigned Once = 0;
129 for ( ; bI != bE; bI++) {
130 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
131 // If we come across a return here, we don't have anything we can
132 // reasonably replace. We should have already inserted our destructor
133 // code in the proper spot, so we just clean up and return.
134 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800135
Stephen Hines292e00a2011-03-18 19:11:30 -0700136 return;
137 }
138
139 UpdatedStmtList[UpdatedStmtCount++] = *bI;
140
141 if ((*bI == S) && !Once) {
142 Once++;
143 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
144 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
145 for ( ; I != E; I++) {
146 UpdatedStmtList[UpdatedStmtCount++] = *I;
147 }
148 }
149 }
150 slangAssert(Once <= 1);
151
152 // When S is NULL, we are appending to the end of the CompoundStmt.
153 if (!S) {
154 slangAssert(Once == 0);
Stephen Hines03981a32010-12-14 19:45:49 -0800155 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
Stephen Hines292e00a2011-03-18 19:11:30 -0700156 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
157 for ( ; I != E; I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800158 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800159 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800160 }
161
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800162 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800163
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800164 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800165
166 return;
167}
168
Stephen Hinesa883ce32011-08-11 18:52:48 -0700169// This class visits a compound statement and inserts DtorStmt
170// in proper locations. This includes inserting it before any
Stephen Hines4464d822010-11-11 16:45:08 -0800171// return statement in any sub-block, at the end of the logical enclosing
172// scope (compound statement), and/or before any break/continue statement that
173// would resume outside the declared scope. We will not handle the case for
174// goto statements that leave a local scope.
Stephen Hines292e00a2011-03-18 19:11:30 -0700175//
176// To accomplish these goals, it collects a list of sub-Stmt's that
177// correspond to scope exit points. It then uses an RSASTReplace visitor to
178// transform the AST, inserting appropriate destructors before each of those
179// sub-Stmt's (and also before the exit of the outermost containing Stmt for
180// the scope).
Stephen Hines4464d822010-11-11 16:45:08 -0800181class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
182 private:
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700183 clang::ASTContext &mCtx;
Stephen Hines292e00a2011-03-18 19:11:30 -0700184
185 // The loop depth of the currently visited node.
186 int mLoopDepth;
187
188 // The switch statement depth of the currently visited node.
189 // Note that this is tracked separately from the loop depth because
190 // SwitchStmt-contained ContinueStmt's should have destructors for the
191 // corresponding loop scope.
192 int mSwitchDepth;
193
194 // The outermost statement block that we are currently visiting.
195 // This should always be a CompoundStmt.
196 clang::Stmt *mOuterStmt;
197
Stephen Hinesa883ce32011-08-11 18:52:48 -0700198 // The destructor to execute for this scope/variable.
199 clang::Stmt* mDtorStmt;
Stephen Hines292e00a2011-03-18 19:11:30 -0700200
201 // The stack of statements which should be replaced by a compound statement
Stephen Hinesa883ce32011-08-11 18:52:48 -0700202 // containing the new destructor call followed by the original Stmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700203 std::stack<clang::Stmt*> mReplaceStmtStack;
204
Stephen Hinesa883ce32011-08-11 18:52:48 -0700205 // The source location for the variable declaration that we are trying to
206 // insert destructors for. Note that InsertDestructors() will not generate
207 // destructor calls for source locations that occur lexically before this
208 // location.
209 clang::SourceLocation mVarLoc;
210
Stephen Hines4464d822010-11-11 16:45:08 -0800211 public:
Stephen Hines292e00a2011-03-18 19:11:30 -0700212 DestructorVisitor(clang::ASTContext &C,
213 clang::Stmt* OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700214 clang::Stmt* DtorStmt,
215 clang::SourceLocation VarLoc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700216
217 // This code walks the collected list of Stmts to replace and actually does
Stephen Hinesa883ce32011-08-11 18:52:48 -0700218 // the replacement. It also finishes up by appending the destructor to the
219 // current outermost CompoundStmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700220 void InsertDestructors() {
221 clang::Stmt *S = NULL;
Stephen Hinesa883ce32011-08-11 18:52:48 -0700222 clang::SourceManager &SM = mCtx.getSourceManager();
223 std::list<clang::Stmt *> StmtList;
224 StmtList.push_back(mDtorStmt);
225
Stephen Hines292e00a2011-03-18 19:11:30 -0700226 while (!mReplaceStmtStack.empty()) {
227 S = mReplaceStmtStack.top();
228 mReplaceStmtStack.pop();
229
Stephen Hinesa883ce32011-08-11 18:52:48 -0700230 // Skip all source locations that occur before the variable's
231 // declaration, since it won't have been initialized yet.
232 if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) {
233 continue;
234 }
235
236 StmtList.push_back(S);
Stephen Hines292e00a2011-03-18 19:11:30 -0700237 clang::CompoundStmt *CS =
Stephen Hinesa883ce32011-08-11 18:52:48 -0700238 BuildCompoundStmt(mCtx, StmtList, S->getLocEnd());
239 StmtList.pop_back();
Stephen Hines292e00a2011-03-18 19:11:30 -0700240
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700241 RSASTReplace R(mCtx);
Stephen Hines292e00a2011-03-18 19:11:30 -0700242 R.ReplaceStmt(mOuterStmt, S, CS);
243 }
Logan Chienab992e52011-07-20 22:06:52 +0800244 clang::CompoundStmt *CS =
245 llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt);
Stephen Hines292e00a2011-03-18 19:11:30 -0700246 slangAssert(CS);
Stephen Hinesa883ce32011-08-11 18:52:48 -0700247 AppendAfterStmt(mCtx, CS, NULL, StmtList);
Stephen Hines292e00a2011-03-18 19:11:30 -0700248 }
249
Stephen Hines4464d822010-11-11 16:45:08 -0800250 void VisitStmt(clang::Stmt *S);
251 void VisitCompoundStmt(clang::CompoundStmt *CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700252
253 void VisitBreakStmt(clang::BreakStmt *BS);
254 void VisitCaseStmt(clang::CaseStmt *CS);
255 void VisitContinueStmt(clang::ContinueStmt *CS);
256 void VisitDefaultStmt(clang::DefaultStmt *DS);
257 void VisitDoStmt(clang::DoStmt *DS);
258 void VisitForStmt(clang::ForStmt *FS);
259 void VisitIfStmt(clang::IfStmt *IS);
260 void VisitReturnStmt(clang::ReturnStmt *RS);
261 void VisitSwitchCase(clang::SwitchCase *SC);
262 void VisitSwitchStmt(clang::SwitchStmt *SS);
263 void VisitWhileStmt(clang::WhileStmt *WS);
Stephen Hines4464d822010-11-11 16:45:08 -0800264};
265
266DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hines292e00a2011-03-18 19:11:30 -0700267 clang::Stmt *OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700268 clang::Stmt *DtorStmt,
269 clang::SourceLocation VarLoc)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700270 : mCtx(C),
Stephen Hines292e00a2011-03-18 19:11:30 -0700271 mLoopDepth(0),
272 mSwitchDepth(0),
273 mOuterStmt(OuterStmt),
Stephen Hinesa883ce32011-08-11 18:52:48 -0700274 mDtorStmt(DtorStmt),
275 mVarLoc(VarLoc) {
Stephen Hines4464d822010-11-11 16:45:08 -0800276 return;
277}
278
279void DestructorVisitor::VisitStmt(clang::Stmt *S) {
280 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
281 I != E;
282 I++) {
283 if (clang::Stmt *Child = *I) {
284 Visit(Child);
285 }
286 }
287 return;
288}
289
Stephen Hines292e00a2011-03-18 19:11:30 -0700290void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
291 VisitStmt(CS);
292 return;
293}
294
295void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
296 VisitStmt(BS);
297 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
298 mReplaceStmtStack.push(BS);
299 }
300 return;
301}
302
303void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
304 VisitStmt(CS);
305 return;
306}
307
308void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
309 VisitStmt(CS);
310 if (mLoopDepth == 0) {
311 // Switch statements can have nested continues.
312 mReplaceStmtStack.push(CS);
313 }
314 return;
315}
316
317void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
318 VisitStmt(DS);
319 return;
320}
321
322void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
323 mLoopDepth++;
324 VisitStmt(DS);
325 mLoopDepth--;
326 return;
327}
328
329void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
330 mLoopDepth++;
331 VisitStmt(FS);
332 mLoopDepth--;
333 return;
334}
335
336void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
337 VisitStmt(IS);
338 return;
339}
340
341void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
342 mReplaceStmtStack.push(RS);
343 return;
344}
345
346void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
347 slangAssert(false && "Both case and default have specialized handlers");
348 VisitStmt(SC);
349 return;
350}
351
352void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
353 mSwitchDepth++;
354 VisitStmt(SS);
355 mSwitchDepth--;
356 return;
357}
358
359void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
360 mLoopDepth++;
361 VisitStmt(WS);
362 mLoopDepth--;
363 return;
364}
365
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800366clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
367 clang::Expr *RefRSVar,
368 clang::SourceLocation Loc) {
369 slangAssert(RefRSVar);
370 const clang::Type *T = RefRSVar->getType().getTypePtr();
371 slangAssert(!T->isArrayType() &&
372 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800373
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800374 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
375 slangAssert((ClearObjectFD != NULL) &&
376 "rsClearObject doesn't cover all RS object types");
377
378 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
379 clang::QualType ClearObjectFDArgType =
380 ClearObjectFD->getParamDecl(0)->getOriginalType();
381
382 // Example destructor for "rs_font localFont;"
383 //
384 // (CallExpr 'void'
385 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
386 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
387 // (UnaryOperator 'rs_font *' prefix '&'
388 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
389
390 // Get address of targeted RS object
391 clang::Expr *AddrRefRSVar =
392 new(C) clang::UnaryOperator(RefRSVar,
393 clang::UO_AddrOf,
394 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800395 clang::VK_RValue,
396 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800397 Loc);
398
399 clang::Expr *RefRSClearObjectFD =
400 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800401 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800402 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800403 ClearObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700404 false,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800405 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800406 ClearObjectFDType,
407 clang::VK_RValue,
408 NULL);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800409
410 clang::Expr *RSClearObjectFP =
411 clang::ImplicitCastExpr::Create(C,
412 C.getPointerType(ClearObjectFDType),
413 clang::CK_FunctionToPointerDecay,
414 RefRSClearObjectFD,
415 NULL,
416 clang::VK_RValue);
417
Stephen Hines1dfc4152012-09-10 20:16:04 -0700418 llvm::SmallVector<clang::Expr*, 1> ArgList;
419 ArgList.push_back(AddrRefRSVar);
420
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800421 clang::CallExpr *RSClearObjectCall =
422 new(C) clang::CallExpr(C,
423 RSClearObjectFP,
Stephen Hines1dfc4152012-09-10 20:16:04 -0700424 ArgList,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800425 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800426 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800427 Loc);
428
429 return RSClearObjectCall;
430}
431
432static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800433 if (!T || !T->isArrayType()) {
434 return 0;
435 }
436
437 const clang::ConstantArrayType *CAT =
438 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800439 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800440}
441
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800442static clang::Stmt *ClearStructRSObject(
443 clang::ASTContext &C,
444 clang::DeclContext *DC,
445 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700446 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800447 clang::SourceLocation Loc);
448
449static clang::Stmt *ClearArrayRSObject(
450 clang::ASTContext &C,
451 clang::DeclContext *DC,
452 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700453 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800454 clang::SourceLocation Loc) {
455 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
456 slangAssert(BaseType->isArrayType());
457
458 int NumArrayElements = ArrayDim(BaseType);
459 // Actually extract out the base RS object type for use later
460 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800461
462 clang::Stmt *StmtArray[2] = {NULL};
463 int StmtCtr = 0;
464
Stephen Hines03981a32010-12-14 19:45:49 -0800465 if (NumArrayElements <= 0) {
466 return NULL;
467 }
468
469 // Example destructor loop for "rs_font fontArr[10];"
470 //
471 // (CompoundStmt
472 // (DeclStmt "int rsIntIter")
473 // (ForStmt
474 // (BinaryOperator 'int' '='
475 // (DeclRefExpr 'int' Var='rsIntIter')
476 // (IntegerLiteral 'int' 0))
477 // (BinaryOperator 'int' '<'
478 // (DeclRefExpr 'int' Var='rsIntIter')
479 // (IntegerLiteral 'int' 10)
480 // NULL << CondVar >>
481 // (UnaryOperator 'int' postfix '++'
482 // (DeclRefExpr 'int' Var='rsIntIter'))
483 // (CallExpr 'void'
484 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
485 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
486 // (UnaryOperator 'rs_font *' prefix '&'
487 // (ArraySubscriptExpr 'rs_font':'rs_font'
488 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
489 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
490 // (DeclRefExpr 'int' Var='rsIntIter')))))))
491
492 // Create helper variable for iterating through elements
493 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
494 clang::VarDecl *IIVD =
495 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800496 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700497 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800498 Loc,
499 &II,
500 C.IntTy,
501 C.getTrivialTypeSourceInfo(C.IntTy),
502 clang::SC_None,
503 clang::SC_None);
504 clang::Decl *IID = (clang::Decl *)IIVD;
505
506 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
507 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
508
509 // Form the actual destructor loop
510 // for (Init; Cond; Inc)
511 // RSClearObjectCall;
512
513 // Init -> "rsIntIter = 0"
514 clang::DeclRefExpr *RefrsIntIter =
515 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800516 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800517 clang::SourceLocation(),
Stephen Hines03981a32010-12-14 19:45:49 -0800518 IIVD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700519 false,
Stephen Hines03981a32010-12-14 19:45:49 -0800520 Loc,
Loganbe274822011-02-16 22:02:54 +0800521 C.IntTy,
522 clang::VK_RValue,
523 NULL);
Stephen Hines03981a32010-12-14 19:45:49 -0800524
525 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
526 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
527
528 clang::BinaryOperator *Init =
529 new(C) clang::BinaryOperator(RefrsIntIter,
530 Int0,
531 clang::BO_Assign,
532 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800533 clang::VK_RValue,
534 clang::OK_Ordinary,
Stephen Hines23c43582013-01-09 20:02:04 -0800535 Loc,
536 false);
Stephen Hines03981a32010-12-14 19:45:49 -0800537
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 Hines23c43582013-01-09 20:02:04 -0800549 Loc,
550 false);
Stephen Hines03981a32010-12-14 19:45:49 -0800551
552 // Inc -> "rsIntIter++"
553 clang::UnaryOperator *Inc =
554 new(C) clang::UnaryOperator(RefrsIntIter,
555 clang::UO_PostInc,
556 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800557 clang::VK_RValue,
558 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800559 Loc);
560
561 // Body -> "rsClearObject(&VD[rsIntIter]);"
562 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800563
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800564 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800565 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800566 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800567 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800568 RefRSArr,
Stephen Hines03981a32010-12-14 19:45:49 -0800569 NULL,
570 clang::VK_RValue);
571
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800572 clang::Expr *RefRSArrPtrSubscript =
573 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hines03981a32010-12-14 19:45:49 -0800574 RefrsIntIter,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800575 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800576 clang::VK_RValue,
577 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800578 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800579
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800580 RSExportPrimitiveType::DataType DT =
581 RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800582
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800583 clang::Stmt *RSClearObjectCall = NULL;
584 if (BaseType->isArrayType()) {
585 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700586 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800587 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
588 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700589 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800590 } else {
591 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
592 }
Stephen Hines03981a32010-12-14 19:45:49 -0800593
594 clang::ForStmt *DestructorLoop =
595 new(C) clang::ForStmt(C,
596 Init,
597 Cond,
598 NULL, // no condVar
599 Inc,
600 RSClearObjectCall,
601 Loc,
602 Loc,
603 Loc);
604
605 StmtArray[StmtCtr++] = DestructorLoop;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800606 slangAssert(StmtCtr == 2);
Stephen Hines03981a32010-12-14 19:45:49 -0800607
Stephen Hines23c43582013-01-09 20:02:04 -0800608 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
609 C, llvm::makeArrayRef(StmtArray, StmtCtr), Loc, Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800610
611 return CS;
612}
613
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700614static unsigned CountRSObjectTypes(clang::ASTContext &C,
615 const clang::Type *T,
616 clang::SourceLocation Loc) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800617 slangAssert(T);
618 unsigned RSObjectCount = 0;
619
620 if (T->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700621 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800622 }
623
624 RSExportPrimitiveType::DataType DT =
625 RSExportPrimitiveType::GetRSSpecificType(T);
626 if (DT != RSExportPrimitiveType::DataTypeUnknown) {
627 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
628 }
629
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700630 if (T->isUnionType()) {
631 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
632 RD = RD->getDefinition();
633 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
634 FE = RD->field_end();
635 FI != FE;
636 FI++) {
637 const clang::FieldDecl *FD = *FI;
638 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
639 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700640 slangAssert(false && "can't have unions with RS object types!");
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700641 return 0;
642 }
643 }
644 }
645
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800646 if (!T->isStructureType()) {
647 return 0;
648 }
649
650 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
651 RD = RD->getDefinition();
652 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
653 FE = RD->field_end();
654 FI != FE;
655 FI++) {
656 const clang::FieldDecl *FD = *FI;
657 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700658 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800659 // Sub-structs should only count once (as should arrays, etc.)
660 RSObjectCount++;
661 }
662 }
663
664 return RSObjectCount;
665}
666
667static clang::Stmt *ClearStructRSObject(
668 clang::ASTContext &C,
669 clang::DeclContext *DC,
670 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700671 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800672 clang::SourceLocation Loc) {
673 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
674
675 slangAssert(!BaseType->isArrayType());
676
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800677 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700678 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
679 RSExportPrimitiveType::DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800680
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700681 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800682 slangAssert(FieldsToDestroy != 0);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800683
684 unsigned StmtCount = 0;
685 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800686 for (unsigned i = 0; i < FieldsToDestroy; i++) {
687 StmtArray[i] = NULL;
688 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800689
690 // Populate StmtArray by creating a destructor for each RS object field
691 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
692 RD = RD->getDefinition();
693 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
694 FE = RD->field_end();
695 FI != FE;
696 FI++) {
697 // We just look through all field declarations to see if we find a
698 // declaration for an RS object type (or an array of one).
699 bool IsArrayType = false;
700 clang::FieldDecl *FD = *FI;
701 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
702 const clang::Type *OrigType = FT;
703 while (FT && FT->isArrayType()) {
704 FT = FT->getArrayElementTypeNoTypeQual();
705 IsArrayType = true;
706 }
707
708 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
709 clang::DeclAccessPair FoundDecl =
710 clang::DeclAccessPair::make(FD, clang::AS_none);
711 clang::MemberExpr *RSObjectMember =
712 clang::MemberExpr::Create(C,
713 RefRSStruct,
714 false,
Loganbe274822011-02-16 22:02:54 +0800715 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800716 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800717 FD,
718 FoundDecl,
719 clang::DeclarationNameInfo(),
720 NULL,
Loganbe274822011-02-16 22:02:54 +0800721 OrigType->getCanonicalTypeInternal(),
722 clang::VK_RValue,
723 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800724
725 slangAssert(StmtCount < FieldsToDestroy);
726
727 if (IsArrayType) {
728 StmtArray[StmtCount++] = ClearArrayRSObject(C,
729 DC,
730 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700731 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800732 Loc);
733 } else {
734 StmtArray[StmtCount++] = ClearSingleRSObject(C,
735 RSObjectMember,
736 Loc);
737 }
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700738 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800739 // In this case, we have a nested struct. We may not end up filling all
740 // of the spaces in StmtArray (sub-structs should handle themselves
741 // with separate compound statements).
742 clang::DeclAccessPair FoundDecl =
743 clang::DeclAccessPair::make(FD, clang::AS_none);
744 clang::MemberExpr *RSObjectMember =
745 clang::MemberExpr::Create(C,
746 RefRSStruct,
747 false,
Loganbe274822011-02-16 22:02:54 +0800748 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800749 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800750 FD,
751 FoundDecl,
752 clang::DeclarationNameInfo(),
753 NULL,
Loganbe274822011-02-16 22:02:54 +0800754 OrigType->getCanonicalTypeInternal(),
755 clang::VK_RValue,
756 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800757
758 if (IsArrayType) {
759 StmtArray[StmtCount++] = ClearArrayRSObject(C,
760 DC,
761 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700762 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800763 Loc);
764 } else {
765 StmtArray[StmtCount++] = ClearStructRSObject(C,
766 DC,
767 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700768 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800769 Loc);
770 }
771 }
772 }
773
774 slangAssert(StmtCount > 0);
Stephen Hines23c43582013-01-09 20:02:04 -0800775 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
776 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800777
778 delete [] StmtArray;
779
780 return CS;
781}
782
Stephen Hines2bb67db2011-02-11 01:36:40 -0800783static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800784 clang::Expr *DstExpr,
785 clang::Expr *SrcExpr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700786 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800787 clang::SourceLocation Loc) {
788 const clang::Type *T = DstExpr->getType().getTypePtr();
789 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800790 slangAssert((SetObjectFD != NULL) &&
791 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800792
793 clang::QualType SetObjectFDType = SetObjectFD->getType();
794 clang::QualType SetObjectFDArgType[2];
795 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
796 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
797
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800798 clang::Expr *RefRSSetObjectFD =
799 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800800 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800801 clang::SourceLocation(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800802 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700803 false,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800804 Loc,
Loganbe274822011-02-16 22:02:54 +0800805 SetObjectFDType,
806 clang::VK_RValue,
807 NULL);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800808
809 clang::Expr *RSSetObjectFP =
810 clang::ImplicitCastExpr::Create(C,
811 C.getPointerType(SetObjectFDType),
812 clang::CK_FunctionToPointerDecay,
813 RefRSSetObjectFD,
814 NULL,
815 clang::VK_RValue);
816
Stephen Hines1dfc4152012-09-10 20:16:04 -0700817 llvm::SmallVector<clang::Expr*, 2> ArgList;
818 ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
819 clang::UO_AddrOf,
820 SetObjectFDArgType[0],
821 clang::VK_RValue,
822 clang::OK_Ordinary,
823 Loc));
824 ArgList.push_back(SrcExpr);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800825
826 clang::CallExpr *RSSetObjectCall =
827 new(C) clang::CallExpr(C,
828 RSSetObjectFP,
829 ArgList,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800830 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800831 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800832 Loc);
833
Stephen Hines2bb67db2011-02-11 01:36:40 -0800834 return RSSetObjectCall;
835}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800836
Stephen Hines2bb67db2011-02-11 01:36:40 -0800837static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800838 clang::Expr *LHS,
839 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700840 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800841 clang::SourceLocation Loc);
842
Al Sutton246fa172012-02-23 13:09:08 +0000843/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800844 clang::Expr *DstArr,
845 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700846 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800847 clang::SourceLocation Loc) {
848 clang::DeclContext *DC = NULL;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800849 const clang::Type *BaseType = DstArr->getType().getTypePtr();
850 slangAssert(BaseType->isArrayType());
851
852 int NumArrayElements = ArrayDim(BaseType);
853 // Actually extract out the base RS object type for use later
854 BaseType = BaseType->getArrayElementTypeNoTypeQual();
855
856 clang::Stmt *StmtArray[2] = {NULL};
857 int StmtCtr = 0;
858
859 if (NumArrayElements <= 0) {
860 return NULL;
861 }
862
863 // Create helper variable for iterating through elements
864 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
865 clang::VarDecl *IIVD =
866 clang::VarDecl::Create(C,
867 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700868 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800869 Loc,
870 &II,
871 C.IntTy,
872 C.getTrivialTypeSourceInfo(C.IntTy),
873 clang::SC_None,
874 clang::SC_None);
875 clang::Decl *IID = (clang::Decl *)IIVD;
876
877 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
878 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
879
880 // Form the actual loop
881 // for (Init; Cond; Inc)
882 // RSSetObjectCall;
883
884 // Init -> "rsIntIter = 0"
885 clang::DeclRefExpr *RefrsIntIter =
886 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800887 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800888 IIVD,
889 Loc,
Loganbe274822011-02-16 22:02:54 +0800890 C.IntTy,
891 clang::VK_RValue,
892 NULL);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800893
894 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
895 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
896
897 clang::BinaryOperator *Init =
898 new(C) clang::BinaryOperator(RefrsIntIter,
899 Int0,
900 clang::BO_Assign,
901 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800902 clang::VK_RValue,
903 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800904 Loc);
905
906 // Cond -> "rsIntIter < NumArrayElements"
907 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
908 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
909
910 clang::BinaryOperator *Cond =
911 new(C) clang::BinaryOperator(RefrsIntIter,
912 NumArrayElementsExpr,
913 clang::BO_LT,
914 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800915 clang::VK_RValue,
916 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800917 Loc);
918
919 // Inc -> "rsIntIter++"
920 clang::UnaryOperator *Inc =
921 new(C) clang::UnaryOperator(RefrsIntIter,
922 clang::UO_PostInc,
923 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800924 clang::VK_RValue,
925 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800926 Loc);
927
928 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
929 // Loop operates on individual array elements
930
931 clang::Expr *DstArrPtr =
932 clang::ImplicitCastExpr::Create(C,
933 C.getPointerType(BaseType->getCanonicalTypeInternal()),
934 clang::CK_ArrayToPointerDecay,
935 DstArr,
936 NULL,
937 clang::VK_RValue);
938
939 clang::Expr *DstArrPtrSubscript =
940 new(C) clang::ArraySubscriptExpr(DstArrPtr,
941 RefrsIntIter,
942 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800943 clang::VK_RValue,
944 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800945 Loc);
946
947 clang::Expr *SrcArrPtr =
948 clang::ImplicitCastExpr::Create(C,
949 C.getPointerType(BaseType->getCanonicalTypeInternal()),
950 clang::CK_ArrayToPointerDecay,
951 SrcArr,
952 NULL,
953 clang::VK_RValue);
954
955 clang::Expr *SrcArrPtrSubscript =
956 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
957 RefrsIntIter,
958 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800959 clang::VK_RValue,
960 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800961 Loc);
962
963 RSExportPrimitiveType::DataType DT =
964 RSExportPrimitiveType::GetRSSpecificType(BaseType);
965
966 clang::Stmt *RSSetObjectCall = NULL;
967 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700968 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700969 SrcArrPtrSubscript,
970 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800971 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700972 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700973 SrcArrPtrSubscript,
974 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800975 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700976 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700977 SrcArrPtrSubscript,
978 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800979 }
980
981 clang::ForStmt *DestructorLoop =
982 new(C) clang::ForStmt(C,
983 Init,
984 Cond,
985 NULL, // no condVar
986 Inc,
987 RSSetObjectCall,
988 Loc,
989 Loc,
990 Loc);
991
992 StmtArray[StmtCtr++] = DestructorLoop;
993 slangAssert(StmtCtr == 2);
994
995 clang::CompoundStmt *CS =
996 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
997
998 return CS;
Al Sutton246fa172012-02-23 13:09:08 +0000999} */
Stephen Hines2bb67db2011-02-11 01:36:40 -08001000
1001static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -08001002 clang::Expr *LHS,
1003 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001004 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -08001005 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001006 clang::QualType QT = LHS->getType();
1007 const clang::Type *T = QT.getTypePtr();
1008 slangAssert(T->isStructureType());
1009 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
1010
1011 // Keep an extra slot for the original copy (memcpy)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001012 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001013
1014 unsigned StmtCount = 0;
1015 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
1016 for (unsigned i = 0; i < FieldsToSet; i++) {
1017 StmtArray[i] = NULL;
1018 }
1019
1020 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
1021 RD = RD->getDefinition();
1022 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1023 FE = RD->field_end();
1024 FI != FE;
1025 FI++) {
1026 bool IsArrayType = false;
1027 clang::FieldDecl *FD = *FI;
1028 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1029 const clang::Type *OrigType = FT;
1030
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001031 if (!CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001032 // Skip to next if we don't have any viable RS object types
1033 continue;
1034 }
1035
1036 clang::DeclAccessPair FoundDecl =
1037 clang::DeclAccessPair::make(FD, clang::AS_none);
1038 clang::MemberExpr *DstMember =
1039 clang::MemberExpr::Create(C,
1040 LHS,
1041 false,
Loganbe274822011-02-16 22:02:54 +08001042 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001043 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001044 FD,
1045 FoundDecl,
1046 clang::DeclarationNameInfo(),
1047 NULL,
Loganbe274822011-02-16 22:02:54 +08001048 OrigType->getCanonicalTypeInternal(),
1049 clang::VK_RValue,
1050 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001051
1052 clang::MemberExpr *SrcMember =
1053 clang::MemberExpr::Create(C,
1054 RHS,
1055 false,
Loganbe274822011-02-16 22:02:54 +08001056 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001057 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001058 FD,
1059 FoundDecl,
1060 clang::DeclarationNameInfo(),
1061 NULL,
Loganbe274822011-02-16 22:02:54 +08001062 OrigType->getCanonicalTypeInternal(),
1063 clang::VK_RValue,
1064 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001065
1066 if (FT->isArrayType()) {
1067 FT = FT->getArrayElementTypeNoTypeQual();
1068 IsArrayType = true;
1069 }
1070
1071 RSExportPrimitiveType::DataType DT =
1072 RSExportPrimitiveType::GetRSSpecificType(FT);
1073
1074 if (IsArrayType) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001075 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
1076 DiagEngine.Report(
1077 clang::FullSourceLoc(Loc, C.getSourceManager()),
1078 DiagEngine.getCustomDiagID(
1079 clang::DiagnosticsEngine::Error,
1080 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -08001081 // TODO(srhines): Support setting arrays of RS objects
1082 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001083 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001084 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
1085 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001086 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001087 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
1088 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001089 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001090 } else {
1091 slangAssert(false);
1092 }
1093 }
1094
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001095 slangAssert(StmtCount < FieldsToSet);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001096
1097 // We still need to actually do the overall struct copy. For simplicity,
1098 // we just do a straight-up assignment (which will still preserve all
1099 // the proper RS object reference counts).
1100 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001101 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
Stephen Hines23c43582013-01-09 20:02:04 -08001102 clang::VK_RValue, clang::OK_Ordinary, Loc,
1103 false);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001104 StmtArray[StmtCount++] = CopyStruct;
1105
Stephen Hines23c43582013-01-09 20:02:04 -08001106 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
1107 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001108
1109 delete [] StmtArray;
1110
1111 return CS;
1112}
1113
1114} // namespace
1115
1116void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001117 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001118
1119 clang::QualType QT = AS->getType();
1120
1121 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1122 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1123
Stephen Hines832429f2011-02-25 16:05:37 -08001124 clang::SourceLocation Loc = AS->getExprLoc();
Stephen Hines9f1d0aa2011-12-18 15:41:00 -08001125 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001126 clang::Stmt *UpdatedStmt = NULL;
1127
1128 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1129 // By definition, this is a struct assignment if we get here
1130 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001131 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001132 } else {
1133 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001134 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001135 }
1136
Stephen Hines292e00a2011-03-18 19:11:30 -07001137 RSASTReplace R(C);
1138 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001139 return;
1140}
1141
1142void RSObjectRefCount::Scope::AppendRSObjectInit(
1143 clang::VarDecl *VD,
1144 clang::DeclStmt *DS,
1145 RSExportPrimitiveType::DataType DT,
1146 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001147 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001148
1149 if (!InitExpr) {
1150 return;
1151 }
1152
Stephen Hinesa0611e62011-02-11 16:35:47 -08001153 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1154 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1155 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
1156 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001157 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
1158 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001159
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001160 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001161 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1162 clang::DeclRefExpr *RefRSVar =
1163 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001164 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001165 clang::SourceLocation(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001166 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001167 false,
Stephen Hinesa0611e62011-02-11 16:35:47 -08001168 Loc,
Loganbe274822011-02-16 22:02:54 +08001169 T->getCanonicalTypeInternal(),
1170 clang::VK_RValue,
1171 NULL);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001172
1173 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001174 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001175
Stephen Hines292e00a2011-03-18 19:11:30 -07001176 std::list<clang::Stmt*> StmtList;
1177 StmtList.push_back(RSSetObjectOps);
1178 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001179 return;
1180 }
1181
1182 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -08001183 slangAssert((SetObjectFD != NULL) &&
1184 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001185
1186 clang::QualType SetObjectFDType = SetObjectFD->getType();
1187 clang::QualType SetObjectFDArgType[2];
1188 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1189 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1190
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001191 clang::Expr *RefRSSetObjectFD =
1192 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001193 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001194 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001195 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001196 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001197 Loc,
Loganbe274822011-02-16 22:02:54 +08001198 SetObjectFDType,
1199 clang::VK_RValue,
1200 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001201
1202 clang::Expr *RSSetObjectFP =
1203 clang::ImplicitCastExpr::Create(C,
1204 C.getPointerType(SetObjectFDType),
1205 clang::CK_FunctionToPointerDecay,
1206 RefRSSetObjectFD,
1207 NULL,
1208 clang::VK_RValue);
1209
1210 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1211 clang::DeclRefExpr *RefRSVar =
1212 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001213 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001214 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001215 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001216 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001217 Loc,
Loganbe274822011-02-16 22:02:54 +08001218 T->getCanonicalTypeInternal(),
1219 clang::VK_RValue,
1220 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001221
Stephen Hines1dfc4152012-09-10 20:16:04 -07001222 llvm::SmallVector<clang::Expr*, 2> ArgList;
1223 ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
1224 clang::UO_AddrOf,
1225 SetObjectFDArgType[0],
1226 clang::VK_RValue,
1227 clang::OK_Ordinary,
1228 Loc));
1229 ArgList.push_back(InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001230
1231 clang::CallExpr *RSSetObjectCall =
1232 new(C) clang::CallExpr(C,
1233 RSSetObjectFP,
1234 ArgList,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001235 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001236 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001237 Loc);
1238
Stephen Hines292e00a2011-03-18 19:11:30 -07001239 std::list<clang::Stmt*> StmtList;
1240 StmtList.push_back(RSSetObjectCall);
1241 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001242
1243 return;
1244}
1245
Stephen Hines1bdd4972010-11-08 17:35:08 -08001246void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hines1bdd4972010-11-08 17:35:08 -08001247 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1248 E = mRSO.end();
1249 I != E;
1250 I++) {
Stephen Hinesa883ce32011-08-11 18:52:48 -07001251 clang::VarDecl *VD = *I;
Stephen Hines3f175af2011-09-16 16:26:29 -07001252 clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext());
Stephen Hinesa883ce32011-08-11 18:52:48 -07001253 if (RSClearObjectCall) {
1254 DestructorVisitor DV((*mRSO.begin())->getASTContext(),
1255 mCS,
1256 RSClearObjectCall,
1257 VD->getSourceRange().getBegin());
1258 DV.Visit(mCS);
1259 DV.InsertDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001260 }
1261 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001262 return;
1263}
1264
Stephen Hines3f175af2011-09-16 16:26:29 -07001265clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
1266 clang::VarDecl *VD,
1267 clang::DeclContext *DC) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001268 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001269 clang::ASTContext &C = VD->getASTContext();
1270 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001271 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001272 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001273
Stephen Hines1bdd4972010-11-08 17:35:08 -08001274 // Reference expr to target RS object variable
1275 clang::DeclRefExpr *RefRSVar =
1276 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001277 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001278 clang::SourceLocation(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001279 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001280 false,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001281 Loc,
Loganbe274822011-02-16 22:02:54 +08001282 T->getCanonicalTypeInternal(),
1283 clang::VK_RValue,
1284 NULL);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001285
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001286 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001287 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001288 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001289
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001290 RSExportPrimitiveType::DataType DT =
1291 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001292
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001293 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1294 DT == RSExportPrimitiveType::DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001295 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001296 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001297
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001298 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1299 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001300
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001301 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001302}
1303
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001304bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1305 RSExportPrimitiveType::DataType *DT,
1306 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001307 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001308 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001309
1310 // Loop through array types to get to base type
1311 while (T && T->isArrayType()) {
1312 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001313 }
1314
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001315 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001316 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001317
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001318 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001319 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1320 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001321 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001322 } else {
1323 return false;
1324 }
Stephen Hines2d095042010-11-12 18:13:56 -08001325 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001326
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001327 bool DataTypeIsRSObject = false;
1328 if (DataTypeIsStructWithRSObject) {
1329 DataTypeIsRSObject = true;
1330 } else {
1331 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1332 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001333 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001334
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001335 if (!DataTypeIsRSObject && *InitExpr) {
1336 // If we already have an initializer for a matrix type, we are done.
1337 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001338 }
1339
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001340 clang::Expr *ZeroInitializer =
1341 CreateZeroInitializerForRSSpecificType(*DT,
1342 VD->getASTContext(),
1343 VD->getLocation());
1344
1345 if (ZeroInitializer) {
1346 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1347 VD->setInit(ZeroInitializer);
1348 }
1349
1350 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001351}
1352
1353clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1354 RSExportPrimitiveType::DataType DT,
1355 clang::ASTContext &C,
1356 const clang::SourceLocation &Loc) {
1357 clang::Expr *Res = NULL;
1358 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001359 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001360 case RSExportPrimitiveType::DataTypeRSElement:
1361 case RSExportPrimitiveType::DataTypeRSType:
1362 case RSExportPrimitiveType::DataTypeRSAllocation:
1363 case RSExportPrimitiveType::DataTypeRSSampler:
1364 case RSExportPrimitiveType::DataTypeRSScript:
1365 case RSExportPrimitiveType::DataTypeRSMesh:
Jason Samsdb6dfdf2011-11-07 18:11:10 -08001366 case RSExportPrimitiveType::DataTypeRSPath:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001367 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1368 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1369 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1370 case RSExportPrimitiveType::DataTypeRSProgramStore:
1371 case RSExportPrimitiveType::DataTypeRSFont: {
1372 // (ImplicitCastExpr 'nullptr_t'
1373 // (IntegerLiteral 0)))
1374 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1375 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1376 clang::Expr *CastToNull =
1377 clang::ImplicitCastExpr::Create(C,
1378 C.NullPtrTy,
1379 clang::CK_IntegralToPointer,
1380 Int0,
1381 NULL,
1382 clang::VK_RValue);
1383
Stephen Hines1dfc4152012-09-10 20:16:04 -07001384 llvm::SmallVector<clang::Expr*, 1>InitList;
1385 InitList.push_back(CastToNull);
1386
1387 Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001388 break;
1389 }
1390 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1391 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1392 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1393 // RS matrix is not completely an RS object. They hold data by themselves.
1394 // (InitListExpr rs_matrix2x2
1395 // (InitListExpr float[4]
1396 // (FloatingLiteral 0)
1397 // (FloatingLiteral 0)
1398 // (FloatingLiteral 0)
1399 // (FloatingLiteral 0)))
1400 clang::QualType FloatTy = C.FloatTy;
1401 // Constructor sets value to 0.0f by default
1402 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1403 clang::FloatingLiteral *Float0Val =
1404 clang::FloatingLiteral::Create(C,
1405 Val,
1406 /* isExact = */true,
1407 FloatTy,
1408 Loc);
1409
1410 unsigned N = 0;
1411 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1412 N = 2;
1413 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1414 N = 3;
1415 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1416 N = 4;
Stephen Hines1dfc4152012-09-10 20:16:04 -07001417 unsigned N_2 = N * N;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001418
Stephen Hines1dfc4152012-09-10 20:16:04 -07001419 // Assume we are going to be allocating 16 elements, since 4x4 is max.
1420 llvm::SmallVector<clang::Expr*, 16> InitVals;
1421 for (unsigned i = 0; i < N_2; i++)
1422 InitVals.push_back(Float0Val);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001423 clang::Expr *InitExpr =
Stephen Hines1dfc4152012-09-10 20:16:04 -07001424 new(C) clang::InitListExpr(C, Loc, InitVals, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001425 InitExpr->setType(C.getConstantArrayType(FloatTy,
Stephen Hines1dfc4152012-09-10 20:16:04 -07001426 llvm::APInt(32, N_2),
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001427 clang::ArrayType::Normal,
1428 /* EltTypeQuals = */0));
Stephen Hines1dfc4152012-09-10 20:16:04 -07001429 llvm::SmallVector<clang::Expr*, 1> InitExprVec;
1430 InitExprVec.push_back(InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001431
Stephen Hines1dfc4152012-09-10 20:16:04 -07001432 Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001433 break;
1434 }
1435 case RSExportPrimitiveType::DataTypeUnknown:
1436 case RSExportPrimitiveType::DataTypeFloat16:
1437 case RSExportPrimitiveType::DataTypeFloat32:
1438 case RSExportPrimitiveType::DataTypeFloat64:
1439 case RSExportPrimitiveType::DataTypeSigned8:
1440 case RSExportPrimitiveType::DataTypeSigned16:
1441 case RSExportPrimitiveType::DataTypeSigned32:
1442 case RSExportPrimitiveType::DataTypeSigned64:
1443 case RSExportPrimitiveType::DataTypeUnsigned8:
1444 case RSExportPrimitiveType::DataTypeUnsigned16:
1445 case RSExportPrimitiveType::DataTypeUnsigned32:
1446 case RSExportPrimitiveType::DataTypeUnsigned64:
1447 case RSExportPrimitiveType::DataTypeBoolean:
1448 case RSExportPrimitiveType::DataTypeUnsigned565:
1449 case RSExportPrimitiveType::DataTypeUnsigned5551:
1450 case RSExportPrimitiveType::DataTypeUnsigned4444:
1451 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001452 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001453 }
1454 // No default case will enable compiler detecting the missing cases
1455 }
1456
1457 return Res;
1458}
1459
1460void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1461 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1462 I != E;
1463 I++) {
1464 clang::Decl *D = *I;
1465 if (D->getKind() == clang::Decl::Var) {
1466 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001467 RSExportPrimitiveType::DataType DT =
1468 RSExportPrimitiveType::DataTypeUnknown;
1469 clang::Expr *InitExpr = NULL;
1470 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001471 // We need to zero-init all RS object types (including matrices), ...
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001472 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001473 // ... but, only add to the list of RS objects if we have some
1474 // non-matrix RS object fields.
1475 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(),
1476 VD->getLocation())) {
1477 getCurrentScope()->addRSObject(VD);
1478 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001479 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001480 }
1481 }
1482 return;
1483}
1484
1485void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1486 if (!CS->body_empty()) {
1487 // Push a new scope
1488 Scope *S = new Scope(CS);
1489 mScopeStack.push(S);
1490
1491 VisitStmt(CS);
1492
1493 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001494 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001495 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001496 mScopeStack.pop();
1497 delete S;
1498 }
1499 return;
1500}
1501
1502void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001503 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001504
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001505 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1506 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001507 }
1508
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001509 return;
1510}
1511
1512void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1513 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1514 I != E;
1515 I++) {
1516 if (clang::Stmt *Child = *I) {
1517 Visit(Child);
1518 }
1519 }
1520 return;
1521}
1522
Stephen Hines688e64b2011-08-23 16:01:25 -07001523// This function walks the list of global variables and (potentially) creates
1524// a single global static destructor function that properly decrements
1525// reference counts on the contained RS object types.
1526clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1527 Init();
1528
1529 clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1530 clang::SourceLocation loc;
1531
Stephen Hines3f175af2011-09-16 16:26:29 -07001532 llvm::StringRef SR(".rs.dtor");
1533 clang::IdentifierInfo &II = mCtx.Idents.get(SR);
1534 clang::DeclarationName N(&II);
1535 clang::FunctionProtoType::ExtProtoInfo EPI;
Stephen Hines82d72882013-03-18 18:17:57 -07001536 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
1537 llvm::ArrayRef<clang::QualType>(), EPI);
Stephen Hines3f175af2011-09-16 16:26:29 -07001538 clang::FunctionDecl *FD = NULL;
1539
Stephen Hines688e64b2011-08-23 16:01:25 -07001540 // Generate rsClearObject() call chains for every global variable
1541 // (whether static or extern).
1542 std::list<clang::Stmt *> StmtList;
1543 for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1544 E = DC->decls_end(); I != E; I++) {
1545 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1546 if (VD) {
1547 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) {
Stephen Hines3f175af2011-09-16 16:26:29 -07001548 if (!FD) {
1549 // Only create FD if we are going to use it.
1550 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, NULL);
1551 }
1552 // Make sure to create any helpers within the function's DeclContext,
1553 // not the one associated with the global translation unit.
1554 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
Stephen Hines688e64b2011-08-23 16:01:25 -07001555 StmtList.push_back(RSClearObjectCall);
1556 }
1557 }
1558 }
1559
1560 // Nothing needs to be destroyed, so don't emit a dtor.
1561 if (StmtList.empty()) {
1562 return NULL;
1563 }
1564
Stephen Hines688e64b2011-08-23 16:01:25 -07001565 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1566
1567 FD->setBody(CS);
1568
1569 return FD;
1570}
1571
Stephen Hinese639eb52010-11-08 19:27:20 -08001572} // namespace slang