blob: 200b6163e72f1abcb0d939ecca2b11d88ea47d82 [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"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070029#include "slang.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
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070035/* Even though those two arrays are of size DataTypeMax, only entries that
36 * correspond to object types will be set.
37 */
38clang::FunctionDecl *
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070039RSObjectRefCount::RSSetObjectFD[DataTypeMax];
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070040clang::FunctionDecl *
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070041RSObjectRefCount::RSClearObjectFD[DataTypeMax];
Stephen Hines1bdd4972010-11-08 17:35:08 -080042
Stephen Hinesf2174cf2011-02-09 23:21:37 -080043void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070044 for (unsigned i = 0; i < DataTypeMax; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -070045 RSSetObjectFD[i] = nullptr;
46 RSClearObjectFD[i] = nullptr;
Stephen Hines1bdd4972010-11-08 17:35:08 -080047 }
48
49 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
50
51 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
52 E = TUDecl->decls_end(); I != E; I++) {
53 if ((I->getKind() >= clang::Decl::firstFunction) &&
54 (I->getKind() <= clang::Decl::lastFunction)) {
55 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
56
57 // points to RSSetObjectFD or RSClearObjectFD
58 clang::FunctionDecl **RSObjectFD;
59
60 if (FD->getName() == "rsSetObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080061 slangAssert((FD->getNumParams() == 2) &&
62 "Invalid rsSetObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080063 RSObjectFD = RSSetObjectFD;
64 } else if (FD->getName() == "rsClearObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080065 slangAssert((FD->getNumParams() == 1) &&
66 "Invalid rsClearObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080067 RSObjectFD = RSClearObjectFD;
Stephen Hinese639eb52010-11-08 19:27:20 -080068 } else {
Stephen Hines1bdd4972010-11-08 17:35:08 -080069 continue;
70 }
71
72 const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
73 clang::QualType PVT = PVD->getOriginalType();
74 // The first parameter must be a pointer like rs_allocation*
Stephen Hines6e6578a2011-02-07 18:05:48 -080075 slangAssert(PVT->isPointerType() &&
76 "Invalid rs{Set,Clear}Object function prototype (pointer param)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080077
78 // The rs object type passed to the FD
79 clang::QualType RST = PVT->getPointeeType();
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070080 DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
Stephen Hines6e6578a2011-02-07 18:05:48 -080081 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
Stephen Hines1bdd4972010-11-08 17:35:08 -080082 && "must be RS object type");
83
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070084 if (DT >= 0 && DT < DataTypeMax) {
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070085 RSObjectFD[DT] = FD;
86 } else {
87 slangAssert(false && "incorrect type");
88 }
Stephen Hines1bdd4972010-11-08 17:35:08 -080089 }
90 }
91}
92
Stephen Hines4464d822010-11-11 16:45:08 -080093namespace {
94
Stephen Hines292e00a2011-03-18 19:11:30 -070095// This function constructs a new CompoundStmt from the input StmtList.
96static clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
97 std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -080098 unsigned NewStmtCount = StmtList.size();
Stephen Hines292e00a2011-03-18 19:11:30 -070099 unsigned CompoundStmtCount = 0;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800100
Stephen Hines292e00a2011-03-18 19:11:30 -0700101 clang::Stmt **CompoundStmtList;
102 CompoundStmtList = new clang::Stmt*[NewStmtCount];
103
104 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
105 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
106 for ( ; I != E; I++) {
107 CompoundStmtList[CompoundStmtCount++] = *I;
108 }
109 slangAssert(CompoundStmtCount == NewStmtCount);
110
Stephen Hines23c43582013-01-09 20:02:04 -0800111 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
112 C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700113
114 delete [] CompoundStmtList;
115
116 return CS;
117}
118
119static void AppendAfterStmt(clang::ASTContext &C,
120 clang::CompoundStmt *CS,
121 clang::Stmt *S,
122 std::list<clang::Stmt*> &StmtList) {
123 slangAssert(CS);
124 clang::CompoundStmt::body_iterator bI = CS->body_begin();
125 clang::CompoundStmt::body_iterator bE = CS->body_end();
126 clang::Stmt **UpdatedStmtList =
127 new clang::Stmt*[CS->size() + StmtList.size()];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800128
129 unsigned UpdatedStmtCount = 0;
Stephen Hines292e00a2011-03-18 19:11:30 -0700130 unsigned Once = 0;
131 for ( ; bI != bE; bI++) {
132 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
133 // If we come across a return here, we don't have anything we can
134 // reasonably replace. We should have already inserted our destructor
135 // code in the proper spot, so we just clean up and return.
136 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800137
Stephen Hines292e00a2011-03-18 19:11:30 -0700138 return;
139 }
140
141 UpdatedStmtList[UpdatedStmtCount++] = *bI;
142
143 if ((*bI == S) && !Once) {
144 Once++;
145 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
146 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
147 for ( ; I != E; I++) {
148 UpdatedStmtList[UpdatedStmtCount++] = *I;
149 }
150 }
151 }
152 slangAssert(Once <= 1);
153
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700154 // When S is nullptr, we are appending to the end of the CompoundStmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700155 if (!S) {
156 slangAssert(Once == 0);
Stephen Hines03981a32010-12-14 19:45:49 -0800157 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
Stephen Hines292e00a2011-03-18 19:11:30 -0700158 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
159 for ( ; I != E; I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800160 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800161 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800162 }
163
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800164 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800165
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800166 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800167}
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() {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700221 clang::Stmt *S = nullptr;
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);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700247 AppendAfterStmt(mCtx, CS, nullptr, 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}
277
278void DestructorVisitor::VisitStmt(clang::Stmt *S) {
279 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
280 I != E;
281 I++) {
282 if (clang::Stmt *Child = *I) {
283 Visit(Child);
284 }
285 }
Stephen Hines4464d822010-11-11 16:45:08 -0800286}
287
Stephen Hines292e00a2011-03-18 19:11:30 -0700288void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
289 VisitStmt(CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700290}
291
292void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
293 VisitStmt(BS);
294 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
295 mReplaceStmtStack.push(BS);
296 }
Stephen Hines292e00a2011-03-18 19:11:30 -0700297}
298
299void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
300 VisitStmt(CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700301}
302
303void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
304 VisitStmt(CS);
305 if (mLoopDepth == 0) {
306 // Switch statements can have nested continues.
307 mReplaceStmtStack.push(CS);
308 }
Stephen Hines292e00a2011-03-18 19:11:30 -0700309}
310
311void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
312 VisitStmt(DS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700313}
314
315void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
316 mLoopDepth++;
317 VisitStmt(DS);
318 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700319}
320
321void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
322 mLoopDepth++;
323 VisitStmt(FS);
324 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700325}
326
327void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
328 VisitStmt(IS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700329}
330
331void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
332 mReplaceStmtStack.push(RS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700333}
334
335void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
336 slangAssert(false && "Both case and default have specialized handlers");
337 VisitStmt(SC);
Stephen Hines292e00a2011-03-18 19:11:30 -0700338}
339
340void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
341 mSwitchDepth++;
342 VisitStmt(SS);
343 mSwitchDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700344}
345
346void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
347 mLoopDepth++;
348 VisitStmt(WS);
349 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700350}
351
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800352clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
353 clang::Expr *RefRSVar,
354 clang::SourceLocation Loc) {
355 slangAssert(RefRSVar);
356 const clang::Type *T = RefRSVar->getType().getTypePtr();
357 slangAssert(!T->isArrayType() &&
358 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800359
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800360 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700361 slangAssert((ClearObjectFD != nullptr) &&
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800362 "rsClearObject doesn't cover all RS object types");
363
364 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
365 clang::QualType ClearObjectFDArgType =
366 ClearObjectFD->getParamDecl(0)->getOriginalType();
367
368 // Example destructor for "rs_font localFont;"
369 //
370 // (CallExpr 'void'
371 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
372 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
373 // (UnaryOperator 'rs_font *' prefix '&'
374 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
375
376 // Get address of targeted RS object
377 clang::Expr *AddrRefRSVar =
378 new(C) clang::UnaryOperator(RefRSVar,
379 clang::UO_AddrOf,
380 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800381 clang::VK_RValue,
382 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800383 Loc);
384
385 clang::Expr *RefRSClearObjectFD =
386 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800387 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800388 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800389 ClearObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700390 false,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800391 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800392 ClearObjectFDType,
393 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700394 nullptr);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800395
396 clang::Expr *RSClearObjectFP =
397 clang::ImplicitCastExpr::Create(C,
398 C.getPointerType(ClearObjectFDType),
399 clang::CK_FunctionToPointerDecay,
400 RefRSClearObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700401 nullptr,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800402 clang::VK_RValue);
403
Stephen Hines1dfc4152012-09-10 20:16:04 -0700404 llvm::SmallVector<clang::Expr*, 1> ArgList;
405 ArgList.push_back(AddrRefRSVar);
406
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800407 clang::CallExpr *RSClearObjectCall =
408 new(C) clang::CallExpr(C,
409 RSClearObjectFP,
Stephen Hines1dfc4152012-09-10 20:16:04 -0700410 ArgList,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800411 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800412 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800413 Loc);
414
415 return RSClearObjectCall;
416}
417
418static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800419 if (!T || !T->isArrayType()) {
420 return 0;
421 }
422
423 const clang::ConstantArrayType *CAT =
424 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800425 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800426}
427
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800428static clang::Stmt *ClearStructRSObject(
429 clang::ASTContext &C,
430 clang::DeclContext *DC,
431 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700432 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800433 clang::SourceLocation Loc);
434
435static clang::Stmt *ClearArrayRSObject(
436 clang::ASTContext &C,
437 clang::DeclContext *DC,
438 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700439 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800440 clang::SourceLocation Loc) {
441 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
442 slangAssert(BaseType->isArrayType());
443
444 int NumArrayElements = ArrayDim(BaseType);
445 // Actually extract out the base RS object type for use later
446 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800447
Stephen Hines03981a32010-12-14 19:45:49 -0800448 if (NumArrayElements <= 0) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700449 return nullptr;
Stephen Hines03981a32010-12-14 19:45:49 -0800450 }
451
452 // Example destructor loop for "rs_font fontArr[10];"
453 //
Stephen Hinescd57c542015-08-25 02:09:27 -0700454 // (ForStmt
455 // (DeclStmt
456 // (VarDecl used rsIntIter 'int' cinit
457 // (IntegerLiteral 'int' 0)))
458 // (BinaryOperator 'int' '<'
459 // (ImplicitCastExpr int LValueToRValue
Stephen Hines03981a32010-12-14 19:45:49 -0800460 // (DeclRefExpr 'int' Var='rsIntIter'))
Stephen Hinescd57c542015-08-25 02:09:27 -0700461 // (IntegerLiteral 'int' 10)
462 // nullptr << CondVar >>
463 // (UnaryOperator 'int' postfix '++'
464 // (DeclRefExpr 'int' Var='rsIntIter'))
465 // (CallExpr 'void'
466 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
467 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
468 // (UnaryOperator 'rs_font *' prefix '&'
469 // (ArraySubscriptExpr 'rs_font':'rs_font'
470 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
471 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
472 // (DeclRefExpr 'int' Var='rsIntIter'))))))
Stephen Hines03981a32010-12-14 19:45:49 -0800473
474 // Create helper variable for iterating through elements
Stephen Hinescd57c542015-08-25 02:09:27 -0700475 static unsigned sIterCounter = 0;
476 std::stringstream UniqueIterName;
477 UniqueIterName << "rsIntIter" << sIterCounter++;
478 clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
Stephen Hines03981a32010-12-14 19:45:49 -0800479 clang::VarDecl *IIVD =
480 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800481 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700482 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800483 Loc,
Stephen Hinescd57c542015-08-25 02:09:27 -0700484 II,
Stephen Hines03981a32010-12-14 19:45:49 -0800485 C.IntTy,
486 C.getTrivialTypeSourceInfo(C.IntTy),
Stephen Hines03981a32010-12-14 19:45:49 -0800487 clang::SC_None);
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700488 // Mark "rsIntIter" as used
489 IIVD->markUsed(C);
Stephen Hines03981a32010-12-14 19:45:49 -0800490
491 // Form the actual destructor loop
492 // for (Init; Cond; Inc)
493 // RSClearObjectCall;
494
Stephen Hinescd57c542015-08-25 02:09:27 -0700495 // Init -> "int rsIntIter = 0"
496 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
497 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
498 IIVD->setInit(Int0);
499
500 clang::Decl *IID = (clang::Decl *)IIVD;
501 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
502 clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
503
504 // Cond -> "rsIntIter < NumArrayElements"
505 clang::DeclRefExpr *RefrsIntIterLValue =
Stephen Hines03981a32010-12-14 19:45:49 -0800506 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800507 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800508 clang::SourceLocation(),
Stephen Hines03981a32010-12-14 19:45:49 -0800509 IIVD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700510 false,
Stephen Hines03981a32010-12-14 19:45:49 -0800511 Loc,
Loganbe274822011-02-16 22:02:54 +0800512 C.IntTy,
Stephen Hinescd57c542015-08-25 02:09:27 -0700513 clang::VK_LValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700514 nullptr);
Stephen Hines03981a32010-12-14 19:45:49 -0800515
Stephen Hinescd57c542015-08-25 02:09:27 -0700516 clang::Expr *RefrsIntIterRValue =
517 clang::ImplicitCastExpr::Create(C,
518 RefrsIntIterLValue->getType(),
519 clang::CK_LValueToRValue,
520 RefrsIntIterLValue,
521 nullptr,
522 clang::VK_RValue);
Stephen Hines03981a32010-12-14 19:45:49 -0800523
Stephen Hines03981a32010-12-14 19:45:49 -0800524 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
525 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
526
527 clang::BinaryOperator *Cond =
Stephen Hinescd57c542015-08-25 02:09:27 -0700528 new(C) clang::BinaryOperator(RefrsIntIterRValue,
Stephen Hines03981a32010-12-14 19:45:49 -0800529 NumArrayElementsExpr,
530 clang::BO_LT,
531 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800532 clang::VK_RValue,
533 clang::OK_Ordinary,
Stephen Hines23c43582013-01-09 20:02:04 -0800534 Loc,
535 false);
Stephen Hines03981a32010-12-14 19:45:49 -0800536
537 // Inc -> "rsIntIter++"
538 clang::UnaryOperator *Inc =
Stephen Hinescd57c542015-08-25 02:09:27 -0700539 new(C) clang::UnaryOperator(RefrsIntIterLValue,
Stephen Hines03981a32010-12-14 19:45:49 -0800540 clang::UO_PostInc,
541 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800542 clang::VK_RValue,
543 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800544 Loc);
545
546 // Body -> "rsClearObject(&VD[rsIntIter]);"
547 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800548
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800549 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800550 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800551 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800552 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800553 RefRSArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700554 nullptr,
Stephen Hines03981a32010-12-14 19:45:49 -0800555 clang::VK_RValue);
556
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800557 clang::Expr *RefRSArrPtrSubscript =
558 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hinescd57c542015-08-25 02:09:27 -0700559 RefrsIntIterRValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800560 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800561 clang::VK_RValue,
562 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800563 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800564
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700565 DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800566
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700567 clang::Stmt *RSClearObjectCall = nullptr;
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800568 if (BaseType->isArrayType()) {
569 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700570 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700571 } else if (DT == DataTypeUnknown) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800572 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700573 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800574 } else {
575 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
576 }
Stephen Hines03981a32010-12-14 19:45:49 -0800577
578 clang::ForStmt *DestructorLoop =
579 new(C) clang::ForStmt(C,
580 Init,
581 Cond,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700582 nullptr, // no condVar
Stephen Hines03981a32010-12-14 19:45:49 -0800583 Inc,
584 RSClearObjectCall,
585 Loc,
586 Loc,
587 Loc);
588
Stephen Hinescd57c542015-08-25 02:09:27 -0700589 return DestructorLoop;
Stephen Hines03981a32010-12-14 19:45:49 -0800590}
591
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700592static unsigned CountRSObjectTypes(clang::ASTContext &C,
593 const clang::Type *T,
594 clang::SourceLocation Loc) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800595 slangAssert(T);
596 unsigned RSObjectCount = 0;
597
598 if (T->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700599 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800600 }
601
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700602 DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
603 if (DT != DataTypeUnknown) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800604 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
605 }
606
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700607 if (T->isUnionType()) {
608 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
609 RD = RD->getDefinition();
610 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
611 FE = RD->field_end();
612 FI != FE;
613 FI++) {
614 const clang::FieldDecl *FD = *FI;
615 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
616 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700617 slangAssert(false && "can't have unions with RS object types!");
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700618 return 0;
619 }
620 }
621 }
622
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800623 if (!T->isStructureType()) {
624 return 0;
625 }
626
627 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
628 RD = RD->getDefinition();
629 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
630 FE = RD->field_end();
631 FI != FE;
632 FI++) {
633 const clang::FieldDecl *FD = *FI;
634 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700635 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800636 // Sub-structs should only count once (as should arrays, etc.)
637 RSObjectCount++;
638 }
639 }
640
641 return RSObjectCount;
642}
643
644static clang::Stmt *ClearStructRSObject(
645 clang::ASTContext &C,
646 clang::DeclContext *DC,
647 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700648 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800649 clang::SourceLocation Loc) {
650 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
651
652 slangAssert(!BaseType->isArrayType());
653
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800654 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700655 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700656 DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800657
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700658 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800659 slangAssert(FieldsToDestroy != 0);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800660
661 unsigned StmtCount = 0;
662 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800663 for (unsigned i = 0; i < FieldsToDestroy; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700664 StmtArray[i] = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800665 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800666
667 // Populate StmtArray by creating a destructor for each RS object field
668 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
669 RD = RD->getDefinition();
670 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
671 FE = RD->field_end();
672 FI != FE;
673 FI++) {
674 // We just look through all field declarations to see if we find a
675 // declaration for an RS object type (or an array of one).
676 bool IsArrayType = false;
677 clang::FieldDecl *FD = *FI;
678 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
679 const clang::Type *OrigType = FT;
680 while (FT && FT->isArrayType()) {
681 FT = FT->getArrayElementTypeNoTypeQual();
682 IsArrayType = true;
683 }
684
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700685 // Pass a DeclarationNameInfo with a valid DeclName, since name equality
686 // gets asserted during CodeGen.
687 clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
688 FD->getLocation());
689
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800690 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
691 clang::DeclAccessPair FoundDecl =
692 clang::DeclAccessPair::make(FD, clang::AS_none);
693 clang::MemberExpr *RSObjectMember =
694 clang::MemberExpr::Create(C,
695 RefRSStruct,
696 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700697 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800698 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800699 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800700 FD,
701 FoundDecl,
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700702 FDDeclNameInfo,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700703 nullptr,
Loganbe274822011-02-16 22:02:54 +0800704 OrigType->getCanonicalTypeInternal(),
705 clang::VK_RValue,
706 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800707
708 slangAssert(StmtCount < FieldsToDestroy);
709
710 if (IsArrayType) {
711 StmtArray[StmtCount++] = ClearArrayRSObject(C,
712 DC,
713 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700714 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800715 Loc);
716 } else {
717 StmtArray[StmtCount++] = ClearSingleRSObject(C,
718 RSObjectMember,
719 Loc);
720 }
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700721 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800722 // In this case, we have a nested struct. We may not end up filling all
723 // of the spaces in StmtArray (sub-structs should handle themselves
724 // with separate compound statements).
725 clang::DeclAccessPair FoundDecl =
726 clang::DeclAccessPair::make(FD, clang::AS_none);
727 clang::MemberExpr *RSObjectMember =
728 clang::MemberExpr::Create(C,
729 RefRSStruct,
730 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700731 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800732 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800733 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800734 FD,
735 FoundDecl,
736 clang::DeclarationNameInfo(),
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700737 nullptr,
Loganbe274822011-02-16 22:02:54 +0800738 OrigType->getCanonicalTypeInternal(),
739 clang::VK_RValue,
740 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800741
742 if (IsArrayType) {
743 StmtArray[StmtCount++] = ClearArrayRSObject(C,
744 DC,
745 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700746 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800747 Loc);
748 } else {
749 StmtArray[StmtCount++] = ClearStructRSObject(C,
750 DC,
751 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700752 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800753 Loc);
754 }
755 }
756 }
757
758 slangAssert(StmtCount > 0);
Stephen Hines23c43582013-01-09 20:02:04 -0800759 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
760 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800761
762 delete [] StmtArray;
763
764 return CS;
765}
766
Stephen Hines2bb67db2011-02-11 01:36:40 -0800767static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800768 clang::Expr *DstExpr,
769 clang::Expr *SrcExpr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700770 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800771 clang::SourceLocation Loc) {
772 const clang::Type *T = DstExpr->getType().getTypePtr();
773 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700774 slangAssert((SetObjectFD != nullptr) &&
Stephen Hines6e6578a2011-02-07 18:05:48 -0800775 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800776
777 clang::QualType SetObjectFDType = SetObjectFD->getType();
778 clang::QualType SetObjectFDArgType[2];
779 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
780 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
781
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800782 clang::Expr *RefRSSetObjectFD =
783 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800784 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800785 clang::SourceLocation(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800786 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700787 false,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800788 Loc,
Loganbe274822011-02-16 22:02:54 +0800789 SetObjectFDType,
790 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700791 nullptr);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800792
793 clang::Expr *RSSetObjectFP =
794 clang::ImplicitCastExpr::Create(C,
795 C.getPointerType(SetObjectFDType),
796 clang::CK_FunctionToPointerDecay,
797 RefRSSetObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700798 nullptr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800799 clang::VK_RValue);
800
Stephen Hines1dfc4152012-09-10 20:16:04 -0700801 llvm::SmallVector<clang::Expr*, 2> ArgList;
802 ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
803 clang::UO_AddrOf,
804 SetObjectFDArgType[0],
805 clang::VK_RValue,
806 clang::OK_Ordinary,
807 Loc));
808 ArgList.push_back(SrcExpr);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800809
810 clang::CallExpr *RSSetObjectCall =
811 new(C) clang::CallExpr(C,
812 RSSetObjectFP,
813 ArgList,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800814 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800815 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800816 Loc);
817
Stephen Hines2bb67db2011-02-11 01:36:40 -0800818 return RSSetObjectCall;
819}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800820
Stephen Hines2bb67db2011-02-11 01:36:40 -0800821static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800822 clang::Expr *LHS,
823 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700824 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800825 clang::SourceLocation Loc);
826
Al Sutton246fa172012-02-23 13:09:08 +0000827/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800828 clang::Expr *DstArr,
829 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700830 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800831 clang::SourceLocation Loc) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700832 clang::DeclContext *DC = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800833 const clang::Type *BaseType = DstArr->getType().getTypePtr();
834 slangAssert(BaseType->isArrayType());
835
836 int NumArrayElements = ArrayDim(BaseType);
837 // Actually extract out the base RS object type for use later
838 BaseType = BaseType->getArrayElementTypeNoTypeQual();
839
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700840 clang::Stmt *StmtArray[2] = {nullptr};
Stephen Hines2bb67db2011-02-11 01:36:40 -0800841 int StmtCtr = 0;
842
843 if (NumArrayElements <= 0) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700844 return nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800845 }
846
847 // Create helper variable for iterating through elements
848 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
849 clang::VarDecl *IIVD =
850 clang::VarDecl::Create(C,
851 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700852 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800853 Loc,
854 &II,
855 C.IntTy,
856 C.getTrivialTypeSourceInfo(C.IntTy),
857 clang::SC_None,
858 clang::SC_None);
859 clang::Decl *IID = (clang::Decl *)IIVD;
860
861 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
862 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
863
864 // Form the actual loop
865 // for (Init; Cond; Inc)
866 // RSSetObjectCall;
867
868 // Init -> "rsIntIter = 0"
869 clang::DeclRefExpr *RefrsIntIter =
870 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800871 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800872 IIVD,
873 Loc,
Loganbe274822011-02-16 22:02:54 +0800874 C.IntTy,
875 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700876 nullptr);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800877
878 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
879 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
880
881 clang::BinaryOperator *Init =
882 new(C) clang::BinaryOperator(RefrsIntIter,
883 Int0,
884 clang::BO_Assign,
885 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800886 clang::VK_RValue,
887 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800888 Loc);
889
890 // Cond -> "rsIntIter < NumArrayElements"
891 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
892 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
893
894 clang::BinaryOperator *Cond =
895 new(C) clang::BinaryOperator(RefrsIntIter,
896 NumArrayElementsExpr,
897 clang::BO_LT,
898 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800899 clang::VK_RValue,
900 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800901 Loc);
902
903 // Inc -> "rsIntIter++"
904 clang::UnaryOperator *Inc =
905 new(C) clang::UnaryOperator(RefrsIntIter,
906 clang::UO_PostInc,
907 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800908 clang::VK_RValue,
909 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800910 Loc);
911
912 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
913 // Loop operates on individual array elements
914
915 clang::Expr *DstArrPtr =
916 clang::ImplicitCastExpr::Create(C,
917 C.getPointerType(BaseType->getCanonicalTypeInternal()),
918 clang::CK_ArrayToPointerDecay,
919 DstArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700920 nullptr,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800921 clang::VK_RValue);
922
923 clang::Expr *DstArrPtrSubscript =
924 new(C) clang::ArraySubscriptExpr(DstArrPtr,
925 RefrsIntIter,
926 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800927 clang::VK_RValue,
928 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800929 Loc);
930
931 clang::Expr *SrcArrPtr =
932 clang::ImplicitCastExpr::Create(C,
933 C.getPointerType(BaseType->getCanonicalTypeInternal()),
934 clang::CK_ArrayToPointerDecay,
935 SrcArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700936 nullptr,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800937 clang::VK_RValue);
938
939 clang::Expr *SrcArrPtrSubscript =
940 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
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
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700947 DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800948
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700949 clang::Stmt *RSSetObjectCall = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800950 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700951 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700952 SrcArrPtrSubscript,
953 StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700954 } else if (DT == DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700955 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700956 SrcArrPtrSubscript,
957 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800958 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700959 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700960 SrcArrPtrSubscript,
961 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800962 }
963
964 clang::ForStmt *DestructorLoop =
965 new(C) clang::ForStmt(C,
966 Init,
967 Cond,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700968 nullptr, // no condVar
Stephen Hines2bb67db2011-02-11 01:36:40 -0800969 Inc,
970 RSSetObjectCall,
971 Loc,
972 Loc,
973 Loc);
974
975 StmtArray[StmtCtr++] = DestructorLoop;
976 slangAssert(StmtCtr == 2);
977
978 clang::CompoundStmt *CS =
979 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
980
981 return CS;
Al Sutton246fa172012-02-23 13:09:08 +0000982} */
Stephen Hines2bb67db2011-02-11 01:36:40 -0800983
984static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800985 clang::Expr *LHS,
986 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700987 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800988 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800989 clang::QualType QT = LHS->getType();
990 const clang::Type *T = QT.getTypePtr();
991 slangAssert(T->isStructureType());
992 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
993
994 // Keep an extra slot for the original copy (memcpy)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700995 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800996
997 unsigned StmtCount = 0;
998 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
999 for (unsigned i = 0; i < FieldsToSet; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001000 StmtArray[i] = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001001 }
1002
1003 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
1004 RD = RD->getDefinition();
1005 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1006 FE = RD->field_end();
1007 FI != FE;
1008 FI++) {
1009 bool IsArrayType = false;
1010 clang::FieldDecl *FD = *FI;
1011 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1012 const clang::Type *OrigType = FT;
1013
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001014 if (!CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001015 // Skip to next if we don't have any viable RS object types
1016 continue;
1017 }
1018
1019 clang::DeclAccessPair FoundDecl =
1020 clang::DeclAccessPair::make(FD, clang::AS_none);
1021 clang::MemberExpr *DstMember =
1022 clang::MemberExpr::Create(C,
1023 LHS,
1024 false,
Stephen Hines0b754582015-04-07 13:59:57 -07001025 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +08001026 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001027 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001028 FD,
1029 FoundDecl,
1030 clang::DeclarationNameInfo(),
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001031 nullptr,
Loganbe274822011-02-16 22:02:54 +08001032 OrigType->getCanonicalTypeInternal(),
1033 clang::VK_RValue,
1034 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001035
1036 clang::MemberExpr *SrcMember =
1037 clang::MemberExpr::Create(C,
1038 RHS,
1039 false,
Stephen Hines0b754582015-04-07 13:59:57 -07001040 clang::SourceLocation(),
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(),
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001046 nullptr,
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 if (FT->isArrayType()) {
1052 FT = FT->getArrayElementTypeNoTypeQual();
1053 IsArrayType = true;
1054 }
1055
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001056 DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001057
1058 if (IsArrayType) {
Logan Chien9207a2e2011-10-21 15:39:28 +08001059 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
1060 DiagEngine.Report(
1061 clang::FullSourceLoc(Loc, C.getSourceManager()),
1062 DiagEngine.getCustomDiagID(
1063 clang::DiagnosticsEngine::Error,
1064 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -08001065 // TODO(srhines): Support setting arrays of RS objects
1066 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001067 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001068 } else if (DT == DataTypeUnknown) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001069 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001070 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001071 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
1072 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001073 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001074 } else {
1075 slangAssert(false);
1076 }
1077 }
1078
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001079 slangAssert(StmtCount < FieldsToSet);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001080
1081 // We still need to actually do the overall struct copy. For simplicity,
1082 // we just do a straight-up assignment (which will still preserve all
1083 // the proper RS object reference counts).
1084 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001085 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
Stephen Hines23c43582013-01-09 20:02:04 -08001086 clang::VK_RValue, clang::OK_Ordinary, Loc,
1087 false);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001088 StmtArray[StmtCount++] = CopyStruct;
1089
Stephen Hines23c43582013-01-09 20:02:04 -08001090 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
1091 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001092
1093 delete [] StmtArray;
1094
1095 return CS;
1096}
1097
1098} // namespace
1099
1100void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001101 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001102
1103 clang::QualType QT = AS->getType();
1104
1105 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001106 DataTypeRSAllocation)->getASTContext();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001107
Stephen Hines832429f2011-02-25 16:05:37 -08001108 clang::SourceLocation Loc = AS->getExprLoc();
Stephen Hines9f1d0aa2011-12-18 15:41:00 -08001109 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001110 clang::Stmt *UpdatedStmt = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001111
1112 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1113 // By definition, this is a struct assignment if we get here
1114 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001115 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001116 } else {
1117 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001118 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001119 }
1120
Stephen Hines292e00a2011-03-18 19:11:30 -07001121 RSASTReplace R(C);
1122 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001123}
1124
1125void RSObjectRefCount::Scope::AppendRSObjectInit(
1126 clang::VarDecl *VD,
1127 clang::DeclStmt *DS,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001128 DataType DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001129 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001130 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001131
1132 if (!InitExpr) {
1133 return;
1134 }
1135
Stephen Hinesa0611e62011-02-11 16:35:47 -08001136 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001137 DataTypeRSAllocation)->getASTContext();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001138 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001139 DataTypeRSAllocation)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001140 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001141 DataTypeRSAllocation)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001142
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001143 if (DT == DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001144 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1145 clang::DeclRefExpr *RefRSVar =
1146 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001147 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001148 clang::SourceLocation(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001149 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001150 false,
Stephen Hinesa0611e62011-02-11 16:35:47 -08001151 Loc,
Loganbe274822011-02-16 22:02:54 +08001152 T->getCanonicalTypeInternal(),
1153 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001154 nullptr);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001155
1156 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001157 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001158
Stephen Hines292e00a2011-03-18 19:11:30 -07001159 std::list<clang::Stmt*> StmtList;
1160 StmtList.push_back(RSSetObjectOps);
1161 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001162 return;
1163 }
1164
1165 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001166 slangAssert((SetObjectFD != nullptr) &&
Stephen Hines6e6578a2011-02-07 18:05:48 -08001167 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001168
1169 clang::QualType SetObjectFDType = SetObjectFD->getType();
1170 clang::QualType SetObjectFDArgType[2];
1171 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1172 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1173
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001174 clang::Expr *RefRSSetObjectFD =
1175 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001176 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001177 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001178 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001179 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001180 Loc,
Loganbe274822011-02-16 22:02:54 +08001181 SetObjectFDType,
1182 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001183 nullptr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001184
1185 clang::Expr *RSSetObjectFP =
1186 clang::ImplicitCastExpr::Create(C,
1187 C.getPointerType(SetObjectFDType),
1188 clang::CK_FunctionToPointerDecay,
1189 RefRSSetObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001190 nullptr,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001191 clang::VK_RValue);
1192
1193 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1194 clang::DeclRefExpr *RefRSVar =
1195 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001196 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001197 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001198 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001199 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001200 Loc,
Loganbe274822011-02-16 22:02:54 +08001201 T->getCanonicalTypeInternal(),
1202 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001203 nullptr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001204
Stephen Hines1dfc4152012-09-10 20:16:04 -07001205 llvm::SmallVector<clang::Expr*, 2> ArgList;
1206 ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
1207 clang::UO_AddrOf,
1208 SetObjectFDArgType[0],
1209 clang::VK_RValue,
1210 clang::OK_Ordinary,
1211 Loc));
1212 ArgList.push_back(InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001213
1214 clang::CallExpr *RSSetObjectCall =
1215 new(C) clang::CallExpr(C,
1216 RSSetObjectFP,
1217 ArgList,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001218 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001219 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001220 Loc);
1221
Stephen Hines292e00a2011-03-18 19:11:30 -07001222 std::list<clang::Stmt*> StmtList;
1223 StmtList.push_back(RSSetObjectCall);
1224 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001225}
1226
Stephen Hines1bdd4972010-11-08 17:35:08 -08001227void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hines1bdd4972010-11-08 17:35:08 -08001228 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1229 E = mRSO.end();
1230 I != E;
1231 I++) {
Stephen Hinesa883ce32011-08-11 18:52:48 -07001232 clang::VarDecl *VD = *I;
Stephen Hines3f175af2011-09-16 16:26:29 -07001233 clang::Stmt *RSClearObjectCall = ClearRSObject(VD, VD->getDeclContext());
Stephen Hinesa883ce32011-08-11 18:52:48 -07001234 if (RSClearObjectCall) {
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -07001235 clang::ASTContext &C = (*mRSO.begin())->getASTContext();
1236 // Mark VD as used. It might be unused, except for the destructor.
1237 // 'markUsed' has side-effects that are caused only if VD is not already
1238 // used. Hence no need for an extra check here.
1239 VD->markUsed(C);
1240 DestructorVisitor DV(C,
Stephen Hinesa883ce32011-08-11 18:52:48 -07001241 mCS,
1242 RSClearObjectCall,
1243 VD->getSourceRange().getBegin());
1244 DV.Visit(mCS);
1245 DV.InsertDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001246 }
1247 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001248}
1249
Stephen Hines3f175af2011-09-16 16:26:29 -07001250clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
1251 clang::VarDecl *VD,
1252 clang::DeclContext *DC) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001253 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001254 clang::ASTContext &C = VD->getASTContext();
1255 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001256 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001257 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001258
Stephen Hines1bdd4972010-11-08 17:35:08 -08001259 // Reference expr to target RS object variable
1260 clang::DeclRefExpr *RefRSVar =
1261 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001262 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001263 clang::SourceLocation(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001264 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001265 false,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001266 Loc,
Loganbe274822011-02-16 22:02:54 +08001267 T->getCanonicalTypeInternal(),
1268 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001269 nullptr);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001270
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001271 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001272 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001273 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001274
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001275 DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001276
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001277 if (DT == DataTypeUnknown ||
1278 DT == DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001279 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001280 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001281
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001282 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1283 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001284
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001285 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001286}
1287
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001288bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001289 DataType *DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001290 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001291 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001292 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001293
1294 // Loop through array types to get to base type
1295 while (T && T->isArrayType()) {
1296 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001297 }
1298
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001299 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001300 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001301
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001302 if (*DT == DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001303 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001304 *DT = DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001305 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001306 } else {
1307 return false;
1308 }
Stephen Hines2d095042010-11-12 18:13:56 -08001309 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001310
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001311 bool DataTypeIsRSObject = false;
1312 if (DataTypeIsStructWithRSObject) {
1313 DataTypeIsRSObject = true;
1314 } else {
1315 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1316 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001317 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001318
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001319 if (!DataTypeIsRSObject && *InitExpr) {
1320 // If we already have an initializer for a matrix type, we are done.
1321 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001322 }
1323
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001324 clang::Expr *ZeroInitializer =
1325 CreateZeroInitializerForRSSpecificType(*DT,
1326 VD->getASTContext(),
1327 VD->getLocation());
1328
1329 if (ZeroInitializer) {
1330 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1331 VD->setInit(ZeroInitializer);
1332 }
1333
1334 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001335}
1336
1337clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001338 DataType DT,
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001339 clang::ASTContext &C,
1340 const clang::SourceLocation &Loc) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001341 clang::Expr *Res = nullptr;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001342 switch (DT) {
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001343 case DataTypeIsStruct:
1344 case DataTypeRSElement:
1345 case DataTypeRSType:
1346 case DataTypeRSAllocation:
1347 case DataTypeRSSampler:
1348 case DataTypeRSScript:
1349 case DataTypeRSMesh:
1350 case DataTypeRSPath:
1351 case DataTypeRSProgramFragment:
1352 case DataTypeRSProgramVertex:
1353 case DataTypeRSProgramRaster:
1354 case DataTypeRSProgramStore:
1355 case DataTypeRSFont: {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001356 // (ImplicitCastExpr 'nullptr_t'
1357 // (IntegerLiteral 0)))
1358 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1359 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1360 clang::Expr *CastToNull =
1361 clang::ImplicitCastExpr::Create(C,
1362 C.NullPtrTy,
1363 clang::CK_IntegralToPointer,
1364 Int0,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001365 nullptr,
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001366 clang::VK_RValue);
1367
Stephen Hines1dfc4152012-09-10 20:16:04 -07001368 llvm::SmallVector<clang::Expr*, 1>InitList;
1369 InitList.push_back(CastToNull);
1370
1371 Res = new(C) clang::InitListExpr(C, Loc, InitList, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001372 break;
1373 }
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001374 case DataTypeRSMatrix2x2:
1375 case DataTypeRSMatrix3x3:
1376 case DataTypeRSMatrix4x4: {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001377 // RS matrix is not completely an RS object. They hold data by themselves.
1378 // (InitListExpr rs_matrix2x2
1379 // (InitListExpr float[4]
1380 // (FloatingLiteral 0)
1381 // (FloatingLiteral 0)
1382 // (FloatingLiteral 0)
1383 // (FloatingLiteral 0)))
1384 clang::QualType FloatTy = C.FloatTy;
1385 // Constructor sets value to 0.0f by default
1386 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1387 clang::FloatingLiteral *Float0Val =
1388 clang::FloatingLiteral::Create(C,
1389 Val,
1390 /* isExact = */true,
1391 FloatTy,
1392 Loc);
1393
1394 unsigned N = 0;
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001395 if (DT == DataTypeRSMatrix2x2)
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001396 N = 2;
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001397 else if (DT == DataTypeRSMatrix3x3)
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001398 N = 3;
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001399 else if (DT == DataTypeRSMatrix4x4)
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001400 N = 4;
Stephen Hines1dfc4152012-09-10 20:16:04 -07001401 unsigned N_2 = N * N;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001402
Stephen Hines1dfc4152012-09-10 20:16:04 -07001403 // Assume we are going to be allocating 16 elements, since 4x4 is max.
1404 llvm::SmallVector<clang::Expr*, 16> InitVals;
1405 for (unsigned i = 0; i < N_2; i++)
1406 InitVals.push_back(Float0Val);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001407 clang::Expr *InitExpr =
Stephen Hines1dfc4152012-09-10 20:16:04 -07001408 new(C) clang::InitListExpr(C, Loc, InitVals, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001409 InitExpr->setType(C.getConstantArrayType(FloatTy,
Stephen Hines1dfc4152012-09-10 20:16:04 -07001410 llvm::APInt(32, N_2),
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001411 clang::ArrayType::Normal,
1412 /* EltTypeQuals = */0));
Stephen Hines1dfc4152012-09-10 20:16:04 -07001413 llvm::SmallVector<clang::Expr*, 1> InitExprVec;
1414 InitExprVec.push_back(InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001415
Stephen Hines1dfc4152012-09-10 20:16:04 -07001416 Res = new(C) clang::InitListExpr(C, Loc, InitExprVec, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001417 break;
1418 }
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001419 case DataTypeUnknown:
1420 case DataTypeFloat16:
1421 case DataTypeFloat32:
1422 case DataTypeFloat64:
1423 case DataTypeSigned8:
1424 case DataTypeSigned16:
1425 case DataTypeSigned32:
1426 case DataTypeSigned64:
1427 case DataTypeUnsigned8:
1428 case DataTypeUnsigned16:
1429 case DataTypeUnsigned32:
1430 case DataTypeUnsigned64:
1431 case DataTypeBoolean:
1432 case DataTypeUnsigned565:
1433 case DataTypeUnsigned5551:
1434 case DataTypeUnsigned4444:
1435 case DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001436 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001437 }
1438 // No default case will enable compiler detecting the missing cases
1439 }
1440
1441 return Res;
1442}
1443
1444void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1445 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1446 I != E;
1447 I++) {
1448 clang::Decl *D = *I;
1449 if (D->getKind() == clang::Decl::Var) {
1450 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001451 DataType DT = DataTypeUnknown;
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001452 clang::Expr *InitExpr = nullptr;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001453 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001454 // We need to zero-init all RS object types (including matrices), ...
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001455 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001456 // ... but, only add to the list of RS objects if we have some
1457 // non-matrix RS object fields.
1458 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(),
1459 VD->getLocation())) {
1460 getCurrentScope()->addRSObject(VD);
1461 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001462 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001463 }
1464 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001465}
1466
1467void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1468 if (!CS->body_empty()) {
1469 // Push a new scope
1470 Scope *S = new Scope(CS);
1471 mScopeStack.push(S);
1472
1473 VisitStmt(CS);
1474
1475 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001476 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001477 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001478 mScopeStack.pop();
1479 delete S;
1480 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001481}
1482
1483void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001484 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001485
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001486 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1487 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001488 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001489}
1490
1491void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1492 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1493 I != E;
1494 I++) {
1495 if (clang::Stmt *Child = *I) {
1496 Visit(Child);
1497 }
1498 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001499}
1500
Stephen Hines688e64b2011-08-23 16:01:25 -07001501// This function walks the list of global variables and (potentially) creates
1502// a single global static destructor function that properly decrements
1503// reference counts on the contained RS object types.
1504clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1505 Init();
1506
1507 clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1508 clang::SourceLocation loc;
1509
Stephen Hines3f175af2011-09-16 16:26:29 -07001510 llvm::StringRef SR(".rs.dtor");
1511 clang::IdentifierInfo &II = mCtx.Idents.get(SR);
1512 clang::DeclarationName N(&II);
1513 clang::FunctionProtoType::ExtProtoInfo EPI;
Stephen Hines82d72882013-03-18 18:17:57 -07001514 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
1515 llvm::ArrayRef<clang::QualType>(), EPI);
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001516 clang::FunctionDecl *FD = nullptr;
Stephen Hines3f175af2011-09-16 16:26:29 -07001517
Stephen Hines688e64b2011-08-23 16:01:25 -07001518 // Generate rsClearObject() call chains for every global variable
1519 // (whether static or extern).
1520 std::list<clang::Stmt *> StmtList;
1521 for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1522 E = DC->decls_end(); I != E; I++) {
1523 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1524 if (VD) {
1525 if (CountRSObjectTypes(mCtx, VD->getType().getTypePtr(), loc)) {
Stephen Hines3f175af2011-09-16 16:26:29 -07001526 if (!FD) {
1527 // Only create FD if we are going to use it.
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001528 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
Stephen Hines4b3f3ba2013-05-06 16:18:56 -07001529 clang::SC_None);
Stephen Hines3f175af2011-09-16 16:26:29 -07001530 }
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -07001531 // Mark VD as used. It might be unused, except for the destructor.
1532 // 'markUsed' has side-effects that are caused only if VD is not already
1533 // used. Hence no need for an extra check here.
1534 VD->markUsed(mCtx);
Stephen Hines3f175af2011-09-16 16:26:29 -07001535 // Make sure to create any helpers within the function's DeclContext,
1536 // not the one associated with the global translation unit.
1537 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
Stephen Hines688e64b2011-08-23 16:01:25 -07001538 StmtList.push_back(RSClearObjectCall);
1539 }
1540 }
1541 }
1542
1543 // Nothing needs to be destroyed, so don't emit a dtor.
1544 if (StmtList.empty()) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001545 return nullptr;
Stephen Hines688e64b2011-08-23 16:01:25 -07001546 }
1547
Stephen Hines688e64b2011-08-23 16:01:25 -07001548 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1549
1550 FD->setBody(CS);
1551
1552 return FD;
1553}
1554
Stephen Hinese639eb52010-11-08 19:27:20 -08001555} // namespace slang