blob: a948a455f85a25027dc62c4767408933d93cc414 [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
19#include "clang/AST/DeclGroup.h"
20#include "clang/AST/Expr.h"
Loganbe274822011-02-16 22:02:54 +080021#include "clang/AST/NestedNameSpecifier.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070022#include "clang/AST/OperationKinds.h"
Yang Nif05ee4b2017-06-13 15:51:50 -070023#include "clang/AST/RecursiveASTVisitor.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070024#include "clang/AST/Stmt.h"
25#include "clang/AST/StmtVisitor.h"
26
Stephen Hines6e6578a2011-02-07 18:05:48 -080027#include "slang_assert.h"
Jean-Luc Brouillet8024ed52015-05-04 23:02:25 -070028#include "slang.h"
Stephen Hines292e00a2011-03-18 19:11:30 -070029#include "slang_rs_ast_replace.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070030#include "slang_rs_export_type.h"
31
Stephen Hinese639eb52010-11-08 19:27:20 -080032namespace slang {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070033
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070034/* Even though those two arrays are of size DataTypeMax, only entries that
35 * correspond to object types will be set.
36 */
37clang::FunctionDecl *
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070038RSObjectRefCount::RSSetObjectFD[DataTypeMax];
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070039clang::FunctionDecl *
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070040RSObjectRefCount::RSClearObjectFD[DataTypeMax];
Stephen Hines1bdd4972010-11-08 17:35:08 -080041
Stephen Hinesf2174cf2011-02-09 23:21:37 -080042void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070043 for (unsigned i = 0; i < DataTypeMax; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -070044 RSSetObjectFD[i] = nullptr;
45 RSClearObjectFD[i] = nullptr;
Stephen Hines1bdd4972010-11-08 17:35:08 -080046 }
47
48 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
49
50 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
51 E = TUDecl->decls_end(); I != E; I++) {
52 if ((I->getKind() >= clang::Decl::firstFunction) &&
53 (I->getKind() <= clang::Decl::lastFunction)) {
54 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
55
56 // points to RSSetObjectFD or RSClearObjectFD
57 clang::FunctionDecl **RSObjectFD;
58
59 if (FD->getName() == "rsSetObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080060 slangAssert((FD->getNumParams() == 2) &&
61 "Invalid rsSetObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080062 RSObjectFD = RSSetObjectFD;
63 } else if (FD->getName() == "rsClearObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080064 slangAssert((FD->getNumParams() == 1) &&
65 "Invalid rsClearObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080066 RSObjectFD = RSClearObjectFD;
Stephen Hinese639eb52010-11-08 19:27:20 -080067 } else {
Stephen Hines1bdd4972010-11-08 17:35:08 -080068 continue;
69 }
70
71 const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
72 clang::QualType PVT = PVD->getOriginalType();
73 // The first parameter must be a pointer like rs_allocation*
Stephen Hines6e6578a2011-02-07 18:05:48 -080074 slangAssert(PVT->isPointerType() &&
75 "Invalid rs{Set,Clear}Object function prototype (pointer param)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080076
77 // The rs object type passed to the FD
78 clang::QualType RST = PVT->getPointeeType();
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070079 DataType DT = RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
Stephen Hines6e6578a2011-02-07 18:05:48 -080080 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
Stephen Hines1bdd4972010-11-08 17:35:08 -080081 && "must be RS object type");
82
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -070083 if (DT >= 0 && DT < DataTypeMax) {
Jean-Luc Brouillet474655a2014-04-28 15:25:51 -070084 RSObjectFD[DT] = FD;
85 } else {
86 slangAssert(false && "incorrect type");
87 }
Stephen Hines1bdd4972010-11-08 17:35:08 -080088 }
89 }
90}
91
Stephen Hines4464d822010-11-11 16:45:08 -080092namespace {
93
Yang Nib478c3d2016-01-15 16:37:04 -080094unsigned CountRSObjectTypes(const clang::Type *T);
95
96clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
97 clang::Expr *DstExpr,
98 clang::Expr *SrcExpr,
99 clang::SourceLocation StartLoc,
100 clang::SourceLocation Loc);
101
Stephen Hines292e00a2011-03-18 19:11:30 -0700102// This function constructs a new CompoundStmt from the input StmtList.
Yang Nib478c3d2016-01-15 16:37:04 -0800103clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
Yang Ni31d2ea32017-04-14 15:44:23 -0700104 std::vector<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800105 unsigned NewStmtCount = StmtList.size();
Stephen Hines292e00a2011-03-18 19:11:30 -0700106 unsigned CompoundStmtCount = 0;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800107
Stephen Hines292e00a2011-03-18 19:11:30 -0700108 clang::Stmt **CompoundStmtList;
109 CompoundStmtList = new clang::Stmt*[NewStmtCount];
110
Yang Ni31d2ea32017-04-14 15:44:23 -0700111 std::vector<clang::Stmt*>::const_iterator I = StmtList.begin();
112 std::vector<clang::Stmt*>::const_iterator E = StmtList.end();
Stephen Hines292e00a2011-03-18 19:11:30 -0700113 for ( ; I != E; I++) {
114 CompoundStmtList[CompoundStmtCount++] = *I;
115 }
116 slangAssert(CompoundStmtCount == NewStmtCount);
117
Stephen Hines23c43582013-01-09 20:02:04 -0800118 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
119 C, llvm::makeArrayRef(CompoundStmtList, CompoundStmtCount), Loc, Loc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700120
121 delete [] CompoundStmtList;
122
123 return CS;
124}
125
Yang Nib478c3d2016-01-15 16:37:04 -0800126void AppendAfterStmt(clang::ASTContext &C,
127 clang::CompoundStmt *CS,
128 clang::Stmt *S,
129 std::list<clang::Stmt*> &StmtList) {
Stephen Hines292e00a2011-03-18 19:11:30 -0700130 slangAssert(CS);
131 clang::CompoundStmt::body_iterator bI = CS->body_begin();
132 clang::CompoundStmt::body_iterator bE = CS->body_end();
133 clang::Stmt **UpdatedStmtList =
134 new clang::Stmt*[CS->size() + StmtList.size()];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800135
136 unsigned UpdatedStmtCount = 0;
Stephen Hines292e00a2011-03-18 19:11:30 -0700137 unsigned Once = 0;
138 for ( ; bI != bE; bI++) {
139 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
140 // If we come across a return here, we don't have anything we can
141 // reasonably replace. We should have already inserted our destructor
142 // code in the proper spot, so we just clean up and return.
143 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800144
Stephen Hines292e00a2011-03-18 19:11:30 -0700145 return;
146 }
147
148 UpdatedStmtList[UpdatedStmtCount++] = *bI;
149
150 if ((*bI == S) && !Once) {
151 Once++;
152 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
153 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
154 for ( ; I != E; I++) {
155 UpdatedStmtList[UpdatedStmtCount++] = *I;
156 }
157 }
158 }
159 slangAssert(Once <= 1);
160
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700161 // When S is nullptr, we are appending to the end of the CompoundStmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700162 if (!S) {
163 slangAssert(Once == 0);
Stephen Hines03981a32010-12-14 19:45:49 -0800164 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
Stephen Hines292e00a2011-03-18 19:11:30 -0700165 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
166 for ( ; I != E; I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800167 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800168 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800169 }
170
Pirama Arumuga Nainar98cfae42016-03-03 23:56:27 -0800171 CS->setStmts(C, llvm::makeArrayRef(UpdatedStmtList, UpdatedStmtCount));
Stephen Hines1bdd4972010-11-08 17:35:08 -0800172
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800173 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800174}
175
Yang Nib478c3d2016-01-15 16:37:04 -0800176// This class visits a compound statement and collects a list of all the exiting
177// statements, such as any return statement in any sub-block, and any
178// break/continue statement that would resume outside the current scope.
179// We do not handle the case for goto statements that leave a local scope.
Stephen Hines4464d822010-11-11 16:45:08 -0800180class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
181 private:
Stephen Hines292e00a2011-03-18 19:11:30 -0700182 // The loop depth of the currently visited node.
183 int mLoopDepth;
184
185 // The switch statement depth of the currently visited node.
186 // Note that this is tracked separately from the loop depth because
187 // SwitchStmt-contained ContinueStmt's should have destructors for the
188 // corresponding loop scope.
189 int mSwitchDepth;
190
Yang Nib478c3d2016-01-15 16:37:04 -0800191 // Output of the visitor: the statements that should be replaced by compound
192 // statements, each of which contains rsClearObject() calls followed by the
193 // original statement.
194 std::vector<clang::Stmt*> mExitingStmts;
Stephen Hinesa883ce32011-08-11 18:52:48 -0700195
Stephen Hines4464d822010-11-11 16:45:08 -0800196 public:
Yang Nib478c3d2016-01-15 16:37:04 -0800197 DestructorVisitor() : mLoopDepth(0), mSwitchDepth(0) {}
Stephen Hines292e00a2011-03-18 19:11:30 -0700198
Yang Nib478c3d2016-01-15 16:37:04 -0800199 const std::vector<clang::Stmt*>& getExitingStmts() const {
200 return mExitingStmts;
Stephen Hines292e00a2011-03-18 19:11:30 -0700201 }
202
Stephen Hines4464d822010-11-11 16:45:08 -0800203 void VisitStmt(clang::Stmt *S);
Stephen Hines292e00a2011-03-18 19:11:30 -0700204 void VisitBreakStmt(clang::BreakStmt *BS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700205 void VisitContinueStmt(clang::ContinueStmt *CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700206 void VisitDoStmt(clang::DoStmt *DS);
207 void VisitForStmt(clang::ForStmt *FS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700208 void VisitReturnStmt(clang::ReturnStmt *RS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700209 void VisitSwitchStmt(clang::SwitchStmt *SS);
210 void VisitWhileStmt(clang::WhileStmt *WS);
Stephen Hines4464d822010-11-11 16:45:08 -0800211};
212
Stephen Hines4464d822010-11-11 16:45:08 -0800213void DestructorVisitor::VisitStmt(clang::Stmt *S) {
Yang Ni56916be2015-11-30 11:34:15 -0800214 for (clang::Stmt* Child : S->children()) {
215 if (Child) {
Stephen Hines4464d822010-11-11 16:45:08 -0800216 Visit(Child);
217 }
218 }
Stephen Hines4464d822010-11-11 16:45:08 -0800219}
220
Stephen Hines292e00a2011-03-18 19:11:30 -0700221void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
222 VisitStmt(BS);
223 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
Yang Nib478c3d2016-01-15 16:37:04 -0800224 mExitingStmts.push_back(BS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700225 }
Stephen Hines292e00a2011-03-18 19:11:30 -0700226}
227
Stephen Hines292e00a2011-03-18 19:11:30 -0700228void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
229 VisitStmt(CS);
230 if (mLoopDepth == 0) {
231 // Switch statements can have nested continues.
Yang Nib478c3d2016-01-15 16:37:04 -0800232 mExitingStmts.push_back(CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700233 }
Stephen Hines292e00a2011-03-18 19:11:30 -0700234}
235
Stephen Hines292e00a2011-03-18 19:11:30 -0700236void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
237 mLoopDepth++;
238 VisitStmt(DS);
239 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700240}
241
242void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
243 mLoopDepth++;
244 VisitStmt(FS);
245 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700246}
247
Stephen Hines292e00a2011-03-18 19:11:30 -0700248void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
Yang Nib478c3d2016-01-15 16:37:04 -0800249 mExitingStmts.push_back(RS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700250}
251
Stephen Hines292e00a2011-03-18 19:11:30 -0700252void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
253 mSwitchDepth++;
254 VisitStmt(SS);
255 mSwitchDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700256}
257
258void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
259 mLoopDepth++;
260 VisitStmt(WS);
261 mLoopDepth--;
Stephen Hines292e00a2011-03-18 19:11:30 -0700262}
263
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800264clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
265 clang::Expr *RefRSVar,
266 clang::SourceLocation Loc) {
267 slangAssert(RefRSVar);
268 const clang::Type *T = RefRSVar->getType().getTypePtr();
269 slangAssert(!T->isArrayType() &&
270 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800271
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800272 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700273 slangAssert((ClearObjectFD != nullptr) &&
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800274 "rsClearObject doesn't cover all RS object types");
275
276 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
277 clang::QualType ClearObjectFDArgType =
278 ClearObjectFD->getParamDecl(0)->getOriginalType();
279
280 // Example destructor for "rs_font localFont;"
281 //
282 // (CallExpr 'void'
283 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
284 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
285 // (UnaryOperator 'rs_font *' prefix '&'
286 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
287
288 // Get address of targeted RS object
289 clang::Expr *AddrRefRSVar =
290 new(C) clang::UnaryOperator(RefRSVar,
291 clang::UO_AddrOf,
292 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800293 clang::VK_RValue,
294 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800295 Loc);
296
297 clang::Expr *RefRSClearObjectFD =
298 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800299 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800300 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800301 ClearObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700302 false,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800303 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800304 ClearObjectFDType,
305 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700306 nullptr);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800307
308 clang::Expr *RSClearObjectFP =
309 clang::ImplicitCastExpr::Create(C,
310 C.getPointerType(ClearObjectFDType),
311 clang::CK_FunctionToPointerDecay,
312 RefRSClearObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700313 nullptr,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800314 clang::VK_RValue);
315
Stephen Hines1dfc4152012-09-10 20:16:04 -0700316 llvm::SmallVector<clang::Expr*, 1> ArgList;
317 ArgList.push_back(AddrRefRSVar);
318
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800319 clang::CallExpr *RSClearObjectCall =
320 new(C) clang::CallExpr(C,
321 RSClearObjectFP,
Stephen Hines1dfc4152012-09-10 20:16:04 -0700322 ArgList,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800323 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800324 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800325 Loc);
326
327 return RSClearObjectCall;
328}
329
330static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800331 if (!T || !T->isArrayType()) {
332 return 0;
333 }
334
335 const clang::ConstantArrayType *CAT =
336 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800337 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800338}
339
Yang Nib478c3d2016-01-15 16:37:04 -0800340clang::Stmt *ClearStructRSObject(
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800341 clang::ASTContext &C,
342 clang::DeclContext *DC,
343 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700344 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800345 clang::SourceLocation Loc);
346
Yang Nib478c3d2016-01-15 16:37:04 -0800347clang::Stmt *ClearArrayRSObject(
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800348 clang::ASTContext &C,
349 clang::DeclContext *DC,
350 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700351 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800352 clang::SourceLocation Loc) {
353 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
354 slangAssert(BaseType->isArrayType());
355
356 int NumArrayElements = ArrayDim(BaseType);
357 // Actually extract out the base RS object type for use later
358 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800359
Stephen Hines03981a32010-12-14 19:45:49 -0800360 if (NumArrayElements <= 0) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700361 return nullptr;
Stephen Hines03981a32010-12-14 19:45:49 -0800362 }
363
364 // Example destructor loop for "rs_font fontArr[10];"
365 //
Stephen Hinescd57c542015-08-25 02:09:27 -0700366 // (ForStmt
367 // (DeclStmt
368 // (VarDecl used rsIntIter 'int' cinit
369 // (IntegerLiteral 'int' 0)))
370 // (BinaryOperator 'int' '<'
371 // (ImplicitCastExpr int LValueToRValue
Stephen Hines03981a32010-12-14 19:45:49 -0800372 // (DeclRefExpr 'int' Var='rsIntIter'))
Stephen Hinescd57c542015-08-25 02:09:27 -0700373 // (IntegerLiteral 'int' 10)
374 // nullptr << CondVar >>
375 // (UnaryOperator 'int' postfix '++'
376 // (DeclRefExpr 'int' Var='rsIntIter'))
377 // (CallExpr 'void'
378 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
379 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
380 // (UnaryOperator 'rs_font *' prefix '&'
381 // (ArraySubscriptExpr 'rs_font':'rs_font'
382 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
383 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
384 // (DeclRefExpr 'int' Var='rsIntIter'))))))
Stephen Hines03981a32010-12-14 19:45:49 -0800385
386 // Create helper variable for iterating through elements
Stephen Hinescd57c542015-08-25 02:09:27 -0700387 static unsigned sIterCounter = 0;
388 std::stringstream UniqueIterName;
389 UniqueIterName << "rsIntIter" << sIterCounter++;
390 clang::IdentifierInfo *II = &C.Idents.get(UniqueIterName.str());
Stephen Hines03981a32010-12-14 19:45:49 -0800391 clang::VarDecl *IIVD =
392 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800393 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700394 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800395 Loc,
Stephen Hinescd57c542015-08-25 02:09:27 -0700396 II,
Stephen Hines03981a32010-12-14 19:45:49 -0800397 C.IntTy,
398 C.getTrivialTypeSourceInfo(C.IntTy),
Stephen Hines03981a32010-12-14 19:45:49 -0800399 clang::SC_None);
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700400 // Mark "rsIntIter" as used
401 IIVD->markUsed(C);
Stephen Hines03981a32010-12-14 19:45:49 -0800402
403 // Form the actual destructor loop
404 // for (Init; Cond; Inc)
405 // RSClearObjectCall;
406
Stephen Hinescd57c542015-08-25 02:09:27 -0700407 // Init -> "int rsIntIter = 0"
408 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
409 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
410 IIVD->setInit(Int0);
411
412 clang::Decl *IID = (clang::Decl *)IIVD;
413 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
414 clang::Stmt *Init = new(C) clang::DeclStmt(DGR, Loc, Loc);
415
416 // Cond -> "rsIntIter < NumArrayElements"
417 clang::DeclRefExpr *RefrsIntIterLValue =
Stephen Hines03981a32010-12-14 19:45:49 -0800418 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800419 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800420 clang::SourceLocation(),
Stephen Hines03981a32010-12-14 19:45:49 -0800421 IIVD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700422 false,
Stephen Hines03981a32010-12-14 19:45:49 -0800423 Loc,
Loganbe274822011-02-16 22:02:54 +0800424 C.IntTy,
Stephen Hinescd57c542015-08-25 02:09:27 -0700425 clang::VK_LValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700426 nullptr);
Stephen Hines03981a32010-12-14 19:45:49 -0800427
Stephen Hinescd57c542015-08-25 02:09:27 -0700428 clang::Expr *RefrsIntIterRValue =
429 clang::ImplicitCastExpr::Create(C,
430 RefrsIntIterLValue->getType(),
431 clang::CK_LValueToRValue,
432 RefrsIntIterLValue,
433 nullptr,
434 clang::VK_RValue);
Stephen Hines03981a32010-12-14 19:45:49 -0800435
Stephen Hines03981a32010-12-14 19:45:49 -0800436 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
437 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
438
439 clang::BinaryOperator *Cond =
Stephen Hinescd57c542015-08-25 02:09:27 -0700440 new(C) clang::BinaryOperator(RefrsIntIterRValue,
Stephen Hines03981a32010-12-14 19:45:49 -0800441 NumArrayElementsExpr,
442 clang::BO_LT,
443 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800444 clang::VK_RValue,
445 clang::OK_Ordinary,
Stephen Hines23c43582013-01-09 20:02:04 -0800446 Loc,
447 false);
Stephen Hines03981a32010-12-14 19:45:49 -0800448
449 // Inc -> "rsIntIter++"
450 clang::UnaryOperator *Inc =
Stephen Hinescd57c542015-08-25 02:09:27 -0700451 new(C) clang::UnaryOperator(RefrsIntIterLValue,
Stephen Hines03981a32010-12-14 19:45:49 -0800452 clang::UO_PostInc,
453 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800454 clang::VK_RValue,
455 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800456 Loc);
457
458 // Body -> "rsClearObject(&VD[rsIntIter]);"
459 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800460
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800461 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800462 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800463 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800464 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800465 RefRSArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700466 nullptr,
Stephen Hines03981a32010-12-14 19:45:49 -0800467 clang::VK_RValue);
468
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800469 clang::Expr *RefRSArrPtrSubscript =
470 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hinescd57c542015-08-25 02:09:27 -0700471 RefrsIntIterRValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800472 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800473 clang::VK_RValue,
474 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800475 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800476
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700477 DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800478
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700479 clang::Stmt *RSClearObjectCall = nullptr;
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800480 if (BaseType->isArrayType()) {
481 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700482 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700483 } else if (DT == DataTypeUnknown) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800484 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700485 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800486 } else {
487 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
488 }
Stephen Hines03981a32010-12-14 19:45:49 -0800489
490 clang::ForStmt *DestructorLoop =
491 new(C) clang::ForStmt(C,
492 Init,
493 Cond,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700494 nullptr, // no condVar
Stephen Hines03981a32010-12-14 19:45:49 -0800495 Inc,
496 RSClearObjectCall,
497 Loc,
498 Loc,
499 Loc);
500
Stephen Hinescd57c542015-08-25 02:09:27 -0700501 return DestructorLoop;
Stephen Hines03981a32010-12-14 19:45:49 -0800502}
503
Yang Nib478c3d2016-01-15 16:37:04 -0800504unsigned CountRSObjectTypes(const clang::Type *T) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800505 slangAssert(T);
506 unsigned RSObjectCount = 0;
507
508 if (T->isArrayType()) {
David Gross65f23ed2016-01-08 12:04:59 -0800509 return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800510 }
511
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700512 DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
513 if (DT != DataTypeUnknown) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800514 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
515 }
516
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700517 if (T->isUnionType()) {
518 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
519 RD = RD->getDefinition();
520 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
521 FE = RD->field_end();
522 FI != FE;
523 FI++) {
524 const clang::FieldDecl *FD = *FI;
525 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
David Gross65f23ed2016-01-08 12:04:59 -0800526 if (CountRSObjectTypes(FT)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700527 slangAssert(false && "can't have unions with RS object types!");
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700528 return 0;
529 }
530 }
531 }
532
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800533 if (!T->isStructureType()) {
534 return 0;
535 }
536
537 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
538 RD = RD->getDefinition();
539 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
540 FE = RD->field_end();
541 FI != FE;
542 FI++) {
543 const clang::FieldDecl *FD = *FI;
544 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
David Gross65f23ed2016-01-08 12:04:59 -0800545 if (CountRSObjectTypes(FT)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800546 // Sub-structs should only count once (as should arrays, etc.)
547 RSObjectCount++;
548 }
549 }
550
551 return RSObjectCount;
552}
553
Yang Nib478c3d2016-01-15 16:37:04 -0800554clang::Stmt *ClearStructRSObject(
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800555 clang::ASTContext &C,
556 clang::DeclContext *DC,
557 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700558 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800559 clang::SourceLocation Loc) {
560 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
561
562 slangAssert(!BaseType->isArrayType());
563
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800564 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700565 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700566 DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800567
David Gross65f23ed2016-01-08 12:04:59 -0800568 unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800569 slangAssert(FieldsToDestroy != 0);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800570
571 unsigned StmtCount = 0;
572 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800573 for (unsigned i = 0; i < FieldsToDestroy; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700574 StmtArray[i] = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800575 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800576
577 // Populate StmtArray by creating a destructor for each RS object field
578 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
579 RD = RD->getDefinition();
580 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
581 FE = RD->field_end();
582 FI != FE;
583 FI++) {
584 // We just look through all field declarations to see if we find a
585 // declaration for an RS object type (or an array of one).
586 bool IsArrayType = false;
587 clang::FieldDecl *FD = *FI;
588 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -0700589 slangAssert(FT);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800590 const clang::Type *OrigType = FT;
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -0700591 while (FT->isArrayType()) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800592 FT = FT->getArrayElementTypeNoTypeQual();
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -0700593 slangAssert(FT);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800594 IsArrayType = true;
595 }
596
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700597 // Pass a DeclarationNameInfo with a valid DeclName, since name equality
598 // gets asserted during CodeGen.
599 clang::DeclarationNameInfo FDDeclNameInfo(FD->getDeclName(),
600 FD->getLocation());
601
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800602 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
603 clang::DeclAccessPair FoundDecl =
604 clang::DeclAccessPair::make(FD, clang::AS_none);
605 clang::MemberExpr *RSObjectMember =
606 clang::MemberExpr::Create(C,
607 RefRSStruct,
608 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700609 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800610 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800611 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800612 FD,
613 FoundDecl,
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -0700614 FDDeclNameInfo,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700615 nullptr,
Loganbe274822011-02-16 22:02:54 +0800616 OrigType->getCanonicalTypeInternal(),
617 clang::VK_RValue,
618 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800619
620 slangAssert(StmtCount < FieldsToDestroy);
621
622 if (IsArrayType) {
623 StmtArray[StmtCount++] = ClearArrayRSObject(C,
624 DC,
625 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700626 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800627 Loc);
628 } else {
629 StmtArray[StmtCount++] = ClearSingleRSObject(C,
630 RSObjectMember,
631 Loc);
632 }
David Gross65f23ed2016-01-08 12:04:59 -0800633 } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800634 // In this case, we have a nested struct. We may not end up filling all
635 // of the spaces in StmtArray (sub-structs should handle themselves
636 // with separate compound statements).
637 clang::DeclAccessPair FoundDecl =
638 clang::DeclAccessPair::make(FD, clang::AS_none);
639 clang::MemberExpr *RSObjectMember =
640 clang::MemberExpr::Create(C,
641 RefRSStruct,
642 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700643 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800644 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800645 clang::SourceLocation(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800646 FD,
647 FoundDecl,
648 clang::DeclarationNameInfo(),
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700649 nullptr,
Loganbe274822011-02-16 22:02:54 +0800650 OrigType->getCanonicalTypeInternal(),
651 clang::VK_RValue,
652 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800653
654 if (IsArrayType) {
655 StmtArray[StmtCount++] = ClearArrayRSObject(C,
656 DC,
657 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700658 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800659 Loc);
660 } else {
661 StmtArray[StmtCount++] = ClearStructRSObject(C,
662 DC,
663 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700664 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800665 Loc);
666 }
667 }
668 }
669
670 slangAssert(StmtCount > 0);
Stephen Hines23c43582013-01-09 20:02:04 -0800671 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
672 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800673
674 delete [] StmtArray;
675
676 return CS;
677}
678
Yang Nib478c3d2016-01-15 16:37:04 -0800679clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
680 clang::Expr *DstExpr,
681 clang::Expr *SrcExpr,
682 clang::SourceLocation StartLoc,
683 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800684 const clang::Type *T = DstExpr->getType().getTypePtr();
685 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700686 slangAssert((SetObjectFD != nullptr) &&
Stephen Hines6e6578a2011-02-07 18:05:48 -0800687 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800688
689 clang::QualType SetObjectFDType = SetObjectFD->getType();
690 clang::QualType SetObjectFDArgType[2];
691 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
692 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
693
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800694 clang::Expr *RefRSSetObjectFD =
695 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800696 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800697 clang::SourceLocation(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800698 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -0700699 false,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800700 Loc,
Loganbe274822011-02-16 22:02:54 +0800701 SetObjectFDType,
702 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700703 nullptr);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800704
705 clang::Expr *RSSetObjectFP =
706 clang::ImplicitCastExpr::Create(C,
707 C.getPointerType(SetObjectFDType),
708 clang::CK_FunctionToPointerDecay,
709 RefRSSetObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700710 nullptr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800711 clang::VK_RValue);
712
Stephen Hines1dfc4152012-09-10 20:16:04 -0700713 llvm::SmallVector<clang::Expr*, 2> ArgList;
714 ArgList.push_back(new(C) clang::UnaryOperator(DstExpr,
715 clang::UO_AddrOf,
716 SetObjectFDArgType[0],
717 clang::VK_RValue,
718 clang::OK_Ordinary,
719 Loc));
720 ArgList.push_back(SrcExpr);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800721
722 clang::CallExpr *RSSetObjectCall =
723 new(C) clang::CallExpr(C,
724 RSSetObjectFP,
725 ArgList,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800726 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800727 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800728 Loc);
729
Stephen Hines2bb67db2011-02-11 01:36:40 -0800730 return RSSetObjectCall;
731}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800732
Yang Nib478c3d2016-01-15 16:37:04 -0800733clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
734 clang::Expr *LHS,
735 clang::Expr *RHS,
736 clang::SourceLocation StartLoc,
737 clang::SourceLocation Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800738
Al Sutton246fa172012-02-23 13:09:08 +0000739/*static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800740 clang::Expr *DstArr,
741 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700742 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800743 clang::SourceLocation Loc) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700744 clang::DeclContext *DC = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800745 const clang::Type *BaseType = DstArr->getType().getTypePtr();
746 slangAssert(BaseType->isArrayType());
747
748 int NumArrayElements = ArrayDim(BaseType);
749 // Actually extract out the base RS object type for use later
750 BaseType = BaseType->getArrayElementTypeNoTypeQual();
751
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700752 clang::Stmt *StmtArray[2] = {nullptr};
Stephen Hines2bb67db2011-02-11 01:36:40 -0800753 int StmtCtr = 0;
754
755 if (NumArrayElements <= 0) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700756 return nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800757 }
758
759 // Create helper variable for iterating through elements
760 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
761 clang::VarDecl *IIVD =
762 clang::VarDecl::Create(C,
763 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700764 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800765 Loc,
766 &II,
767 C.IntTy,
768 C.getTrivialTypeSourceInfo(C.IntTy),
769 clang::SC_None,
770 clang::SC_None);
771 clang::Decl *IID = (clang::Decl *)IIVD;
772
773 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
774 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
775
776 // Form the actual loop
777 // for (Init; Cond; Inc)
778 // RSSetObjectCall;
779
780 // Init -> "rsIntIter = 0"
781 clang::DeclRefExpr *RefrsIntIter =
782 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800783 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800784 IIVD,
785 Loc,
Loganbe274822011-02-16 22:02:54 +0800786 C.IntTy,
787 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700788 nullptr);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800789
790 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
791 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
792
793 clang::BinaryOperator *Init =
794 new(C) clang::BinaryOperator(RefrsIntIter,
795 Int0,
796 clang::BO_Assign,
797 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800798 clang::VK_RValue,
799 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800800 Loc);
801
802 // Cond -> "rsIntIter < NumArrayElements"
803 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
804 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
805
806 clang::BinaryOperator *Cond =
807 new(C) clang::BinaryOperator(RefrsIntIter,
808 NumArrayElementsExpr,
809 clang::BO_LT,
810 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800811 clang::VK_RValue,
812 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800813 Loc);
814
815 // Inc -> "rsIntIter++"
816 clang::UnaryOperator *Inc =
817 new(C) clang::UnaryOperator(RefrsIntIter,
818 clang::UO_PostInc,
819 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800820 clang::VK_RValue,
821 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800822 Loc);
823
824 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
825 // Loop operates on individual array elements
826
827 clang::Expr *DstArrPtr =
828 clang::ImplicitCastExpr::Create(C,
829 C.getPointerType(BaseType->getCanonicalTypeInternal()),
830 clang::CK_ArrayToPointerDecay,
831 DstArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700832 nullptr,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800833 clang::VK_RValue);
834
835 clang::Expr *DstArrPtrSubscript =
836 new(C) clang::ArraySubscriptExpr(DstArrPtr,
837 RefrsIntIter,
838 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800839 clang::VK_RValue,
840 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800841 Loc);
842
843 clang::Expr *SrcArrPtr =
844 clang::ImplicitCastExpr::Create(C,
845 C.getPointerType(BaseType->getCanonicalTypeInternal()),
846 clang::CK_ArrayToPointerDecay,
847 SrcArr,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700848 nullptr,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800849 clang::VK_RValue);
850
851 clang::Expr *SrcArrPtrSubscript =
852 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
853 RefrsIntIter,
854 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800855 clang::VK_RValue,
856 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800857 Loc);
858
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700859 DataType DT = RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800860
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700861 clang::Stmt *RSSetObjectCall = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800862 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700863 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700864 SrcArrPtrSubscript,
865 StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700866 } else if (DT == DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700867 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700868 SrcArrPtrSubscript,
869 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800870 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700871 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700872 SrcArrPtrSubscript,
873 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800874 }
875
876 clang::ForStmt *DestructorLoop =
877 new(C) clang::ForStmt(C,
878 Init,
879 Cond,
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700880 nullptr, // no condVar
Stephen Hines2bb67db2011-02-11 01:36:40 -0800881 Inc,
882 RSSetObjectCall,
883 Loc,
884 Loc,
885 Loc);
886
887 StmtArray[StmtCtr++] = DestructorLoop;
888 slangAssert(StmtCtr == 2);
889
890 clang::CompoundStmt *CS =
891 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
892
893 return CS;
Al Sutton246fa172012-02-23 13:09:08 +0000894} */
Stephen Hines2bb67db2011-02-11 01:36:40 -0800895
Yang Nib478c3d2016-01-15 16:37:04 -0800896clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
897 clang::Expr *LHS,
898 clang::Expr *RHS,
899 clang::SourceLocation StartLoc,
900 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800901 clang::QualType QT = LHS->getType();
902 const clang::Type *T = QT.getTypePtr();
903 slangAssert(T->isStructureType());
904 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
905
906 // Keep an extra slot for the original copy (memcpy)
David Gross65f23ed2016-01-08 12:04:59 -0800907 unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800908
909 unsigned StmtCount = 0;
910 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
911 for (unsigned i = 0; i < FieldsToSet; i++) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700912 StmtArray[i] = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800913 }
914
915 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
916 RD = RD->getDefinition();
917 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
918 FE = RD->field_end();
919 FI != FE;
920 FI++) {
921 bool IsArrayType = false;
922 clang::FieldDecl *FD = *FI;
923 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
924 const clang::Type *OrigType = FT;
925
David Gross65f23ed2016-01-08 12:04:59 -0800926 if (!CountRSObjectTypes(FT)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800927 // Skip to next if we don't have any viable RS object types
928 continue;
929 }
930
931 clang::DeclAccessPair FoundDecl =
932 clang::DeclAccessPair::make(FD, clang::AS_none);
933 clang::MemberExpr *DstMember =
934 clang::MemberExpr::Create(C,
935 LHS,
936 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700937 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800938 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800939 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800940 FD,
941 FoundDecl,
I-Jui (Ray) Sungc9344ac2016-12-01 16:44:13 -0800942 clang::DeclarationNameInfo(
943 FD->getDeclName(),
944 clang::SourceLocation()),
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700945 nullptr,
Loganbe274822011-02-16 22:02:54 +0800946 OrigType->getCanonicalTypeInternal(),
947 clang::VK_RValue,
948 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800949
950 clang::MemberExpr *SrcMember =
951 clang::MemberExpr::Create(C,
952 RHS,
953 false,
Stephen Hines0b754582015-04-07 13:59:57 -0700954 clang::SourceLocation(),
Loganbe274822011-02-16 22:02:54 +0800955 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -0800956 clang::SourceLocation(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800957 FD,
958 FoundDecl,
I-Jui (Ray) Sungfe8b8852017-04-17 15:50:03 -0700959 clang::DeclarationNameInfo(
960 FD->getDeclName(),
961 clang::SourceLocation()),
Chris Wailes5abbe0e2014-08-12 15:58:29 -0700962 nullptr,
Loganbe274822011-02-16 22:02:54 +0800963 OrigType->getCanonicalTypeInternal(),
964 clang::VK_RValue,
965 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800966
967 if (FT->isArrayType()) {
968 FT = FT->getArrayElementTypeNoTypeQual();
969 IsArrayType = true;
970 }
971
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700972 DataType DT = RSExportPrimitiveType::GetRSSpecificType(FT);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800973
974 if (IsArrayType) {
Logan Chien9207a2e2011-10-21 15:39:28 +0800975 clang::DiagnosticsEngine &DiagEngine = C.getDiagnostics();
976 DiagEngine.Report(
977 clang::FullSourceLoc(Loc, C.getSourceManager()),
978 DiagEngine.getCustomDiagID(
979 clang::DiagnosticsEngine::Error,
980 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -0800981 // TODO(srhines): Support setting arrays of RS objects
982 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700983 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -0700984 } else if (DT == DataTypeUnknown) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800985 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700986 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800987 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
988 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700989 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800990 } else {
991 slangAssert(false);
992 }
993 }
994
Stephen Hinesb0fabe52013-01-07 19:06:09 -0800995 slangAssert(StmtCount < FieldsToSet);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800996
997 // We still need to actually do the overall struct copy. For simplicity,
998 // we just do a straight-up assignment (which will still preserve all
999 // the proper RS object reference counts).
1000 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001001 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
Stephen Hines23c43582013-01-09 20:02:04 -08001002 clang::VK_RValue, clang::OK_Ordinary, Loc,
1003 false);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001004 StmtArray[StmtCount++] = CopyStruct;
1005
Stephen Hines23c43582013-01-09 20:02:04 -08001006 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(
1007 C, llvm::makeArrayRef(StmtArray, StmtCount), Loc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001008
1009 delete [] StmtArray;
1010
1011 return CS;
1012}
1013
1014} // namespace
1015
Yang Nib478c3d2016-01-15 16:37:04 -08001016void RSObjectRefCount::Scope::InsertStmt(const clang::ASTContext &C,
1017 clang::Stmt *NewStmt) {
1018 std::vector<clang::Stmt*> newBody;
1019 for (clang::Stmt* S1 : mCS->body()) {
1020 if (S1 == mCurrent) {
1021 newBody.push_back(NewStmt);
1022 }
1023 newBody.push_back(S1);
1024 }
Pirama Arumuga Nainar98cfae42016-03-03 23:56:27 -08001025 mCS->setStmts(C, newBody);
Yang Nib478c3d2016-01-15 16:37:04 -08001026}
1027
1028void RSObjectRefCount::Scope::ReplaceStmt(const clang::ASTContext &C,
1029 clang::Stmt *NewStmt) {
1030 std::vector<clang::Stmt*> newBody;
1031 for (clang::Stmt* S1 : mCS->body()) {
1032 if (S1 == mCurrent) {
1033 newBody.push_back(NewStmt);
1034 } else {
1035 newBody.push_back(S1);
1036 }
1037 }
Pirama Arumuga Nainar98cfae42016-03-03 23:56:27 -08001038 mCS->setStmts(C, newBody);
Yang Nib478c3d2016-01-15 16:37:04 -08001039}
1040
1041void RSObjectRefCount::Scope::ReplaceExpr(const clang::ASTContext& C,
1042 clang::Expr* OldExpr,
1043 clang::Expr* NewExpr) {
1044 RSASTReplace R(C);
1045 R.ReplaceStmt(mCurrent, OldExpr, NewExpr);
1046}
1047
Stephen Hines2bb67db2011-02-11 01:36:40 -08001048void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001049 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001050
1051 clang::QualType QT = AS->getType();
1052
1053 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001054 DataTypeRSAllocation)->getASTContext();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001055
Stephen Hines832429f2011-02-25 16:05:37 -08001056 clang::SourceLocation Loc = AS->getExprLoc();
Stephen Hines9f1d0aa2011-12-18 15:41:00 -08001057 clang::SourceLocation StartLoc = AS->getLHS()->getExprLoc();
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001058 clang::Stmt *UpdatedStmt = nullptr;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001059
1060 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1061 // By definition, this is a struct assignment if we get here
1062 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001063 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001064 } else {
1065 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001066 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001067 }
1068
Stephen Hines292e00a2011-03-18 19:11:30 -07001069 RSASTReplace R(C);
1070 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001071}
1072
1073void RSObjectRefCount::Scope::AppendRSObjectInit(
1074 clang::VarDecl *VD,
1075 clang::DeclStmt *DS,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001076 DataType DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001077 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001078 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001079
1080 if (!InitExpr) {
1081 return;
1082 }
1083
Stephen Hinesa0611e62011-02-11 16:35:47 -08001084 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001085 DataTypeRSAllocation)->getASTContext();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001086 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001087 DataTypeRSAllocation)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001088 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
Stephen Hines9ae18b22014-06-10 23:53:00 -07001089 DataTypeRSAllocation)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001090
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001091 if (DT == DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001092 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1093 clang::DeclRefExpr *RefRSVar =
1094 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001095 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001096 clang::SourceLocation(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001097 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001098 false,
Stephen Hinesa0611e62011-02-11 16:35:47 -08001099 Loc,
Loganbe274822011-02-16 22:02:54 +08001100 T->getCanonicalTypeInternal(),
1101 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001102 nullptr);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001103
1104 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001105 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
I-Jui (Ray) Sunge498a142017-04-18 15:54:20 -07001106 // Fix for b/37363420; consider:
1107 //
1108 // struct foo { rs_matrix m; };
1109 // void bar() {
1110 // struct foo M = {...};
1111 // }
1112 //
1113 // slang modifies that declaration with initialization to a
1114 // declaration plus an assignment of the initialization values.
1115 //
1116 // void bar() {
1117 // struct foo M = {};
1118 // M = {...}; // by CreateStructRSSetObject() above
1119 // }
1120 //
1121 // the slang-generated statement (M = {...}) is a use of M, and we
1122 // need to mark M (clang::VarDecl *VD) as used.
1123 VD->markUsed(C);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001124
Stephen Hines292e00a2011-03-18 19:11:30 -07001125 std::list<clang::Stmt*> StmtList;
1126 StmtList.push_back(RSSetObjectOps);
1127 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001128 return;
1129 }
1130
1131 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001132 slangAssert((SetObjectFD != nullptr) &&
Stephen Hines6e6578a2011-02-07 18:05:48 -08001133 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001134
1135 clang::QualType SetObjectFDType = SetObjectFD->getType();
1136 clang::QualType SetObjectFDArgType[2];
1137 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1138 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1139
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001140 clang::Expr *RefRSSetObjectFD =
1141 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001142 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001143 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001144 SetObjectFD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001145 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001146 Loc,
Loganbe274822011-02-16 22:02:54 +08001147 SetObjectFDType,
1148 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001149 nullptr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001150
1151 clang::Expr *RSSetObjectFP =
1152 clang::ImplicitCastExpr::Create(C,
1153 C.getPointerType(SetObjectFDType),
1154 clang::CK_FunctionToPointerDecay,
1155 RefRSSetObjectFD,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001156 nullptr,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001157 clang::VK_RValue);
1158
1159 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1160 clang::DeclRefExpr *RefRSVar =
1161 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001162 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001163 clang::SourceLocation(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001164 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001165 false,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001166 Loc,
Loganbe274822011-02-16 22:02:54 +08001167 T->getCanonicalTypeInternal(),
1168 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001169 nullptr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001170
Stephen Hines1dfc4152012-09-10 20:16:04 -07001171 llvm::SmallVector<clang::Expr*, 2> ArgList;
1172 ArgList.push_back(new(C) clang::UnaryOperator(RefRSVar,
1173 clang::UO_AddrOf,
1174 SetObjectFDArgType[0],
1175 clang::VK_RValue,
1176 clang::OK_Ordinary,
1177 Loc));
1178 ArgList.push_back(InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001179
1180 clang::CallExpr *RSSetObjectCall =
1181 new(C) clang::CallExpr(C,
1182 RSSetObjectFP,
1183 ArgList,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001184 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001185 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001186 Loc);
1187
Stephen Hines292e00a2011-03-18 19:11:30 -07001188 std::list<clang::Stmt*> StmtList;
1189 StmtList.push_back(RSSetObjectCall);
1190 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001191}
1192
Stephen Hines1bdd4972010-11-08 17:35:08 -08001193void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Yang Nib478c3d2016-01-15 16:37:04 -08001194 if (mRSO.empty()) {
1195 return;
Stephen Hines1bdd4972010-11-08 17:35:08 -08001196 }
Yang Nib478c3d2016-01-15 16:37:04 -08001197
1198 clang::DeclContext* DC = mRSO.front()->getDeclContext();
1199 clang::ASTContext& C = DC->getParentASTContext();
1200 clang::SourceManager& SM = C.getSourceManager();
1201
1202 const auto& OccursBefore = [&SM] (clang::SourceLocation L1, clang::SourceLocation L2)->bool {
1203 return SM.isBeforeInTranslationUnit(L1, L2);
1204 };
1205 typedef std::map<clang::SourceLocation, clang::Stmt*, decltype(OccursBefore)> DMap;
1206
1207 DMap dtors(OccursBefore);
1208
1209 // Create rsClearObject calls. Note the DMap entries are sorted by the SourceLocation.
1210 for (clang::VarDecl* VD : mRSO) {
1211 clang::SourceLocation Loc = VD->getSourceRange().getBegin();
1212 clang::Stmt* RSClearObjectCall = ClearRSObject(VD, DC);
1213 dtors.insert(std::make_pair(Loc, RSClearObjectCall));
1214 }
1215
1216 DestructorVisitor Visitor;
1217 Visitor.Visit(mCS);
1218
1219 // Replace each exiting statement with a block that contains the original statement
1220 // and added rsClearObject() calls before it.
1221 for (clang::Stmt* S : Visitor.getExitingStmts()) {
1222
1223 const clang::SourceLocation currentLoc = S->getLocStart();
1224
1225 DMap::iterator firstDtorIter = dtors.begin();
1226 DMap::iterator currentDtorIter = firstDtorIter;
1227 DMap::iterator lastDtorIter = dtors.end();
1228
1229 while (currentDtorIter != lastDtorIter &&
1230 OccursBefore(currentDtorIter->first, currentLoc)) {
1231 currentDtorIter++;
1232 }
1233
1234 if (currentDtorIter == firstDtorIter) {
1235 continue;
1236 }
1237
Yang Ni31d2ea32017-04-14 15:44:23 -07001238 std::vector<clang::Stmt*> Stmts;
Yang Nib478c3d2016-01-15 16:37:04 -08001239
1240 // Insert rsClearObject() calls for all rsObjects declared before the current statement
1241 for(DMap::iterator it = firstDtorIter; it != currentDtorIter; it++) {
1242 Stmts.push_back(it->second);
1243 }
1244 Stmts.push_back(S);
1245
1246 RSASTReplace R(C);
1247 clang::CompoundStmt* CS = BuildCompoundStmt(C, Stmts, S->getLocEnd());
1248 R.ReplaceStmt(mCS, S, CS);
1249 }
1250
1251 std::list<clang::Stmt*> Stmts;
1252 for(auto LocCallPair : dtors) {
1253 Stmts.push_back(LocCallPair.second);
1254 }
1255 AppendAfterStmt(C, mCS, nullptr, Stmts);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001256}
1257
Stephen Hines3f175af2011-09-16 16:26:29 -07001258clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(
1259 clang::VarDecl *VD,
1260 clang::DeclContext *DC) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001261 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001262 clang::ASTContext &C = VD->getASTContext();
1263 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001264 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001265 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001266
Stephen Hines1bdd4972010-11-08 17:35:08 -08001267 // Reference expr to target RS object variable
1268 clang::DeclRefExpr *RefRSVar =
1269 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001270 clang::NestedNameSpecifierLoc(),
Stephen Hines0444de02012-03-02 23:19:06 -08001271 clang::SourceLocation(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001272 VD,
Shih-wei Liaoe2597ac2012-03-24 02:44:33 -07001273 false,
Stephen Hines1bdd4972010-11-08 17:35:08 -08001274 Loc,
Loganbe274822011-02-16 22:02:54 +08001275 T->getCanonicalTypeInternal(),
1276 clang::VK_RValue,
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001277 nullptr);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001278
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001279 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001280 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001281 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001282
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001283 DataType DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001284
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001285 if (DT == DataTypeUnknown ||
1286 DT == DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001287 return ClearStructRSObject(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 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1291 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001292
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001293 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001294}
1295
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001296bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001297 DataType *DT,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001298 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001299 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001300 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001301
1302 // Loop through array types to get to base type
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -07001303 slangAssert(T);
1304 while (T->isArrayType()) {
Stephen Hines2d095042010-11-12 18:13:56 -08001305 T = T->getArrayElementTypeNoTypeQual();
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -07001306 slangAssert(T);
Stephen Hines2d095042010-11-12 18:13:56 -08001307 }
1308
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001309 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001310 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001311
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001312 if (*DT == DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001313 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001314 *DT = DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001315 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001316 } else {
1317 return false;
1318 }
Stephen Hines2d095042010-11-12 18:13:56 -08001319 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001320
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001321 bool DataTypeIsRSObject = false;
1322 if (DataTypeIsStructWithRSObject) {
1323 DataTypeIsRSObject = true;
1324 } else {
1325 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1326 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001327 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001328
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001329 if (!DataTypeIsRSObject && *InitExpr) {
1330 // If we already have an initializer for a matrix type, we are done.
1331 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001332 }
1333
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001334 clang::Expr *ZeroInitializer =
Stephen Hinesd9ed6b52016-03-30 22:09:53 -07001335 CreateEmptyInitListExpr(VD->getASTContext(), VD->getLocation());
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001336
1337 if (ZeroInitializer) {
1338 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1339 VD->setInit(ZeroInitializer);
1340 }
1341
1342 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001343}
1344
Stephen Hinesd9ed6b52016-03-30 22:09:53 -07001345clang::Expr *RSObjectRefCount::CreateEmptyInitListExpr(
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001346 clang::ASTContext &C,
1347 const clang::SourceLocation &Loc) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001348
Stephen Hinesd9ed6b52016-03-30 22:09:53 -07001349 // We can cheaply construct a zero initializer by just creating an empty
1350 // initializer list. Clang supports this extension to C(99), and will create
1351 // any necessary constructs to zero out the entire variable.
1352 llvm::SmallVector<clang::Expr*, 1> EmptyInitList;
1353 return new(C) clang::InitListExpr(C, Loc, EmptyInitList, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001354}
1355
Yang Ni31d2ea32017-04-14 15:44:23 -07001356clang::DeclRefExpr *RSObjectRefCount::CreateGuard(clang::ASTContext &C,
1357 clang::DeclContext *DC,
1358 clang::Expr *E,
1359 const llvm::Twine &VarName,
1360 std::vector<clang::Stmt*> &NewStmts) {
1361 clang::SourceLocation Loc = E->getLocStart();
1362 const clang::QualType Ty = E->getType();
1363 clang::VarDecl* TmpDecl = clang::VarDecl::Create(
Yang Ni5767c352016-03-22 16:30:27 -07001364 C, // AST context
1365 DC, // Decl context
1366 Loc, // Start location
1367 Loc, // Id location
Yang Ni31d2ea32017-04-14 15:44:23 -07001368 &C.Idents.get(VarName.str()), // Id
1369 Ty, // Type
1370 C.getTrivialTypeSourceInfo(Ty), // Type info
Yang Ni5767c352016-03-22 16:30:27 -07001371 clang::SC_None // Storage class
1372 );
Yang Ni31d2ea32017-04-14 15:44:23 -07001373 const clang::Type *T = Ty.getTypePtr();
Yang Ni5767c352016-03-22 16:30:27 -07001374 clang::Expr *ZeroInitializer =
Stephen Hinesd9ed6b52016-03-30 22:09:53 -07001375 RSObjectRefCount::CreateEmptyInitListExpr(C, Loc);
Yang Ni5767c352016-03-22 16:30:27 -07001376 ZeroInitializer->setType(T->getCanonicalTypeInternal());
Yang Ni31d2ea32017-04-14 15:44:23 -07001377 TmpDecl->setInit(ZeroInitializer);
1378 TmpDecl->markUsed(C);
1379 clang::Decl* Decls[] = { TmpDecl };
Yang Ni5767c352016-03-22 16:30:27 -07001380 const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
1381 C, Decls, sizeof(Decls) / sizeof(*Decls));
1382 clang::DeclStmt* DS = new (C) clang::DeclStmt(DGR, Loc, Loc);
1383 NewStmts.push_back(DS);
1384
1385 clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
1386 C,
1387 clang::NestedNameSpecifierLoc(), // QualifierLoc
1388 Loc, // TemplateKWLoc
Yang Ni31d2ea32017-04-14 15:44:23 -07001389 TmpDecl,
Yang Ni5767c352016-03-22 16:30:27 -07001390 false, // RefersToEnclosingVariableOrCapture
1391 Loc, // NameLoc
Yang Ni31d2ea32017-04-14 15:44:23 -07001392 Ty,
Yang Ni5767c352016-03-22 16:30:27 -07001393 clang::VK_LValue
1394 );
Yang Ni31d2ea32017-04-14 15:44:23 -07001395
1396 clang::Stmt *UpdatedStmt = nullptr;
Yang Nif05ee4b2017-06-13 15:51:50 -07001397 if (CountRSObjectTypes(Ty.getTypePtr()) == 0) {
1398 // The expression E is not an RS object itself. Instead of calling
1399 // rsSetObject(), create an assignment statement to set the value of the
1400 // temporary "guard" variable to the expression.
1401 // This can happen if called from RSObjectRefCount::VisitReturnStmt(),
1402 // when the return expression is not an RS object but references one.
1403 UpdatedStmt =
1404 new(C) clang::BinaryOperator(DRE, E, clang::BO_Assign, Ty,
1405 clang::VK_RValue, clang::OK_Ordinary, Loc,
1406 false);
1407
1408 } else if (!RSExportPrimitiveType::IsRSObjectType(Ty.getTypePtr())) {
Yang Ni31d2ea32017-04-14 15:44:23 -07001409 // By definition, this is a struct assignment if we get here
1410 UpdatedStmt =
1411 CreateStructRSSetObject(C, DRE, E, Loc, Loc);
1412 } else {
1413 UpdatedStmt =
1414 CreateSingleRSSetObject(C, DRE, E, Loc, Loc);
1415 }
1416 NewStmts.push_back(UpdatedStmt);
1417
1418 return DRE;
1419}
1420
1421void RSObjectRefCount::CreateParameterGuard(clang::ASTContext &C,
1422 clang::DeclContext *DC,
1423 clang::ParmVarDecl *PD,
1424 std::vector<clang::Stmt*> &NewStmts) {
1425 clang::SourceLocation Loc = PD->getLocStart();
1426 clang::DeclRefExpr* ParamDRE = clang::DeclRefExpr::Create(
1427 C,
1428 clang::NestedNameSpecifierLoc(), // QualifierLoc
1429 Loc, // TemplateKWLoc
1430 PD,
1431 false, // RefersToEnclosingVariableOrCapture
1432 Loc, // NameLoc
1433 PD->getType(),
1434 clang::VK_RValue
1435 );
1436
1437 CreateGuard(C, DC, ParamDRE,
1438 llvm::Twine(".rs.param.") + llvm::Twine(PD->getName()), NewStmts);
1439}
1440
1441void RSObjectRefCount::HandleParamsAndLocals(clang::FunctionDecl *FD) {
1442 std::vector<clang::Stmt*> NewStmts;
1443 std::list<clang::ParmVarDecl*> ObjParams;
1444 for (clang::ParmVarDecl *Param : FD->parameters()) {
1445 clang::QualType QT = Param->getType();
1446 if (CountRSObjectTypes(QT.getTypePtr())) {
1447 // Ignore non-object types
1448 RSObjectRefCount::CreateParameterGuard(mCtx, FD, Param, NewStmts);
1449 ObjParams.push_back(Param);
1450 }
1451 }
1452
1453 clang::Stmt *OldBody = FD->getBody();
1454 if (ObjParams.empty()) {
1455 Visit(OldBody);
1456 return;
1457 }
1458
1459 NewStmts.push_back(OldBody);
1460
1461 clang::SourceLocation Loc = FD->getLocStart();
1462 clang::CompoundStmt *NewBody = BuildCompoundStmt(mCtx, NewStmts, Loc);
1463 Scope S(NewBody);
1464 for (clang::ParmVarDecl *Param : ObjParams) {
1465 S.addRSObject(Param);
1466 }
1467 mScopeStack.push_back(&S);
1468
1469 // To avoid adding unnecessary ref counting artifacts to newly added temporary
1470 // local variables for parameters, visits only the old function body here.
1471 Visit(OldBody);
1472
1473 FD->setBody(NewBody);
1474
1475 S.InsertLocalVarDestructors();
1476 mScopeStack.pop_back();
1477}
1478
1479clang::CompoundStmt* RSObjectRefCount::CreateRetStmtWithTempVar(
1480 clang::ASTContext& C,
1481 clang::DeclContext* DC,
1482 clang::ReturnStmt* RS,
1483 const unsigned id) {
1484 std::vector<clang::Stmt*> NewStmts;
1485 // Since we insert rsClearObj() calls before the return statement, we need
1486 // to make sure none of the cleared RS objects are referenced in the
1487 // return statement.
1488 // For that, we create a new local variable named .rs.retval, assign the
1489 // original return expression to it, make all necessary rsClearObj()
1490 // calls, then return .rs.retval. Note rsClearObj() is not called on
1491 // .rs.retval.
1492 clang::SourceLocation Loc = RS->getLocStart();
1493 clang::Expr* RetVal = RS->getRetValue();
1494 const clang::QualType RetTy = RetVal->getType();
1495 clang::DeclRefExpr *DRE = CreateGuard(C, DC, RetVal,
1496 llvm::Twine(".rs.retval") + llvm::Twine(id),
1497 NewStmts);
Yang Ni5767c352016-03-22 16:30:27 -07001498
1499 // Creates a new return statement
Yang Ni31d2ea32017-04-14 15:44:23 -07001500 clang::ReturnStmt* NewRet = new (C) clang::ReturnStmt(Loc);
Yang Ni5767c352016-03-22 16:30:27 -07001501 clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
1502 C,
1503 RetTy,
1504 clang::CK_LValueToRValue,
1505 DRE,
1506 nullptr,
1507 clang::VK_RValue
1508 );
1509 NewRet->setRetValue(CastExpr);
1510 NewStmts.push_back(NewRet);
1511
1512 return BuildCompoundStmt(C, NewStmts, Loc);
1513}
1514
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001515void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
Yang Nib478c3d2016-01-15 16:37:04 -08001516 VisitStmt(DS);
1517 getCurrentScope()->setCurrentStmt(DS);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001518 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1519 I != E;
1520 I++) {
1521 clang::Decl *D = *I;
1522 if (D->getKind() == clang::Decl::Var) {
1523 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Jean-Luc Brouilletcec9b652014-05-14 19:33:57 -07001524 DataType DT = DataTypeUnknown;
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001525 clang::Expr *InitExpr = nullptr;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001526 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001527 // We need to zero-init all RS object types (including matrices), ...
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001528 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001529 // ... but, only add to the list of RS objects if we have some
1530 // non-matrix RS object fields.
David Gross65f23ed2016-01-08 12:04:59 -08001531 if (CountRSObjectTypes(VD->getType().getTypePtr())) {
Stephen Hinesb0fabe52013-01-07 19:06:09 -08001532 getCurrentScope()->addRSObject(VD);
1533 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001534 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001535 }
1536 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001537}
1538
Yang Nib478c3d2016-01-15 16:37:04 -08001539void RSObjectRefCount::VisitCallExpr(clang::CallExpr* CE) {
1540 clang::QualType RetTy;
1541 const clang::FunctionDecl* FD = CE->getDirectCallee();
1542
1543 if (FD) {
1544 // Direct calls
1545
1546 RetTy = FD->getReturnType();
1547 } else {
1548 // Indirect calls through function pointers
1549
1550 const clang::Expr* Callee = CE->getCallee();
1551 const clang::Type* CalleeType = Callee->getType().getTypePtr();
1552 const clang::PointerType* PtrType = CalleeType->getAs<clang::PointerType>();
1553
1554 if (!PtrType) {
1555 return;
1556 }
1557
1558 const clang::Type* PointeeType = PtrType->getPointeeType().getTypePtr();
1559 const clang::FunctionType* FuncType = PointeeType->getAs<clang::FunctionType>();
1560
1561 if (!FuncType) {
1562 return;
1563 }
1564
1565 RetTy = FuncType->getReturnType();
1566 }
1567
Yang Ni9e580012016-08-25 13:54:36 -07001568 // The RenderScript runtime API maintains the invariant that the sysRef of a new RS object would
1569 // be 1, with the exception of rsGetAllocation() (deprecated in API 22), which leaves the sysRef
1570 // 0 for a new allocation. It is the responsibility of the callee of the API to decrement the
1571 // sysRef when a reference of the RS object goes out of scope. The compiler generates code to do
1572 // just that, by creating a temporary variable named ".rs.tmpN" with the result of
1573 // an RS-object-returning API directly assigned to it, and calling rsClearObject() on .rs.tmpN
1574 // right before it exits the current scope. Such code generation is skipped for rsGetAllocation()
1575 // to avoid decrementing its sysRef below zero.
1576
1577 if (CountRSObjectTypes(RetTy.getTypePtr())==0 ||
1578 (FD && FD->getName() == "rsGetAllocation")) {
Yang Nib478c3d2016-01-15 16:37:04 -08001579 return;
1580 }
1581
1582 clang::SourceLocation Loc = CE->getSourceRange().getBegin();
1583 std::stringstream ss;
1584 ss << ".rs.tmp" << getNextID();
Pirama Arumuga Nainarc429d8f2017-06-07 15:29:17 -07001585 clang::IdentifierInfo *II = &mCtx.Idents.get(ss.str());
Yang Nib478c3d2016-01-15 16:37:04 -08001586
1587 clang::VarDecl* TempVarDecl = clang::VarDecl::Create(
1588 mCtx, // AST context
1589 GetDeclContext(), // Decl context
1590 Loc, // Start location
1591 Loc, // Id location
Pirama Arumuga Nainarc429d8f2017-06-07 15:29:17 -07001592 II, // Id
Yang Nib478c3d2016-01-15 16:37:04 -08001593 RetTy, // Type
1594 mCtx.getTrivialTypeSourceInfo(RetTy), // Type info
1595 clang::SC_None // Storage class
1596 );
1597 TempVarDecl->setInit(CE);
Stephen Hines041656a2016-07-18 23:15:43 -07001598 TempVarDecl->markUsed(mCtx);
Yang Nib478c3d2016-01-15 16:37:04 -08001599 clang::Decl* Decls[] = { TempVarDecl };
1600 const clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(
1601 mCtx, Decls, sizeof(Decls) / sizeof(*Decls));
1602 clang::DeclStmt* DS = new (mCtx) clang::DeclStmt(DGR, Loc, Loc);
1603
1604 getCurrentScope()->InsertStmt(mCtx, DS);
1605
1606 clang::DeclRefExpr* DRE = clang::DeclRefExpr::Create(
1607 mCtx, // AST context
1608 clang::NestedNameSpecifierLoc(), // QualifierLoc
1609 Loc, // TemplateKWLoc
1610 TempVarDecl,
1611 false, // RefersToEnclosingVariableOrCapture
1612 Loc, // NameLoc
1613 RetTy,
1614 clang::VK_LValue
1615 );
1616 clang::Expr* CastExpr = clang::ImplicitCastExpr::Create(
1617 mCtx,
1618 RetTy,
1619 clang::CK_LValueToRValue,
1620 DRE,
1621 nullptr,
1622 clang::VK_RValue
1623 );
1624
1625 getCurrentScope()->ReplaceExpr(mCtx, CE, CastExpr);
1626
1627 // Register TempVarDecl for destruction call (rsClearObj).
1628 getCurrentScope()->addRSObject(TempVarDecl);
1629}
1630
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001631void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
Yang Nib478c3d2016-01-15 16:37:04 -08001632 if (!emptyScope()) {
1633 getCurrentScope()->setCurrentStmt(CS);
1634 }
1635
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001636 if (!CS->body_empty()) {
1637 // Push a new scope
1638 Scope *S = new Scope(CS);
Yang Nib478c3d2016-01-15 16:37:04 -08001639 mScopeStack.push_back(S);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001640
1641 VisitStmt(CS);
1642
1643 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001644 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001645 S->InsertLocalVarDestructors();
Yang Nib478c3d2016-01-15 16:37:04 -08001646 mScopeStack.pop_back();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001647 delete S;
1648 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001649}
1650
1651void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Yang Nib478c3d2016-01-15 16:37:04 -08001652 getCurrentScope()->setCurrentStmt(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001653 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001654
David Gross65f23ed2016-01-08 12:04:59 -08001655 if (CountRSObjectTypes(QT.getTypePtr())) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001656 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001657 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001658}
1659
Yang Nif05ee4b2017-06-13 15:51:50 -07001660namespace {
1661
1662class FindRSObjRefVisitor : public clang::RecursiveASTVisitor<FindRSObjRefVisitor> {
1663public:
1664 explicit FindRSObjRefVisitor() : mRefRSObj(false) {}
1665 bool VisitExpr(clang::Expr* Expression) {
1666 if (CountRSObjectTypes(Expression->getType().getTypePtr()) > 0) {
1667 mRefRSObj = true;
1668 // Found a reference to an RS object. Stop the AST traversal.
1669 return false;
1670 }
1671 return true;
1672 }
1673
1674 bool foundRSObjRef() const { return mRefRSObj; }
1675
1676private:
1677 bool mRefRSObj;
1678};
1679
1680} // anonymous namespace
1681
Yang Nib478c3d2016-01-15 16:37:04 -08001682void RSObjectRefCount::VisitReturnStmt(clang::ReturnStmt *RS) {
1683 getCurrentScope()->setCurrentStmt(RS);
1684
1685 // If there is no local rsObject declared so far, no need to transform the
1686 // return statement.
1687
1688 bool RSObjDeclared = false;
1689
1690 for (const Scope* S : mScopeStack) {
1691 if (S->hasRSObject()) {
1692 RSObjDeclared = true;
1693 break;
1694 }
1695 }
1696
1697 if (!RSObjDeclared) {
1698 return;
1699 }
1700
Yang Nif05ee4b2017-06-13 15:51:50 -07001701 FindRSObjRefVisitor visitor;
1702
1703 visitor.TraverseStmt(RS);
1704
1705 // If the return statement does not return anything, or if it does not reference
Yang Nib478c3d2016-01-15 16:37:04 -08001706 // a rsObject, no need to transform it.
1707
Yang Nif05ee4b2017-06-13 15:51:50 -07001708 if (!visitor.foundRSObjRef()) {
Yang Nib478c3d2016-01-15 16:37:04 -08001709 return;
1710 }
1711
1712 // Transform the return statement so that it does not potentially return or
1713 // reference a rsObject that has been cleared.
1714
1715 clang::CompoundStmt* NewRS;
1716 NewRS = CreateRetStmtWithTempVar(mCtx, GetDeclContext(), RS, getNextID());
1717
1718 getCurrentScope()->ReplaceStmt(mCtx, NewRS);
1719}
1720
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001721void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
Yang Nib478c3d2016-01-15 16:37:04 -08001722 getCurrentScope()->setCurrentStmt(S);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001723 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1724 I != E;
1725 I++) {
1726 if (clang::Stmt *Child = *I) {
1727 Visit(Child);
1728 }
1729 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001730}
1731
Stephen Hines688e64b2011-08-23 16:01:25 -07001732// This function walks the list of global variables and (potentially) creates
1733// a single global static destructor function that properly decrements
1734// reference counts on the contained RS object types.
1735clang::FunctionDecl *RSObjectRefCount::CreateStaticGlobalDtor() {
1736 Init();
1737
1738 clang::DeclContext *DC = mCtx.getTranslationUnitDecl();
1739 clang::SourceLocation loc;
1740
Stephen Hines3f175af2011-09-16 16:26:29 -07001741 llvm::StringRef SR(".rs.dtor");
1742 clang::IdentifierInfo &II = mCtx.Idents.get(SR);
1743 clang::DeclarationName N(&II);
1744 clang::FunctionProtoType::ExtProtoInfo EPI;
Stephen Hines82d72882013-03-18 18:17:57 -07001745 clang::QualType T = mCtx.getFunctionType(mCtx.VoidTy,
1746 llvm::ArrayRef<clang::QualType>(), EPI);
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001747 clang::FunctionDecl *FD = nullptr;
Stephen Hines3f175af2011-09-16 16:26:29 -07001748
Stephen Hines688e64b2011-08-23 16:01:25 -07001749 // Generate rsClearObject() call chains for every global variable
1750 // (whether static or extern).
Yang Ni31d2ea32017-04-14 15:44:23 -07001751 std::vector<clang::Stmt *> StmtList;
Stephen Hines688e64b2011-08-23 16:01:25 -07001752 for (clang::DeclContext::decl_iterator I = DC->decls_begin(),
1753 E = DC->decls_end(); I != E; I++) {
1754 clang::VarDecl *VD = llvm::dyn_cast<clang::VarDecl>(*I);
1755 if (VD) {
David Gross65f23ed2016-01-08 12:04:59 -08001756 if (CountRSObjectTypes(VD->getType().getTypePtr())) {
Stephen Hines3f175af2011-09-16 16:26:29 -07001757 if (!FD) {
1758 // Only create FD if we are going to use it.
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001759 FD = clang::FunctionDecl::Create(mCtx, DC, loc, loc, N, T, nullptr,
Stephen Hines4b3f3ba2013-05-06 16:18:56 -07001760 clang::SC_None);
Stephen Hines3f175af2011-09-16 16:26:29 -07001761 }
Pirama Arumuga Nainarcc4d9342015-06-09 11:34:18 -07001762 // Mark VD as used. It might be unused, except for the destructor.
1763 // 'markUsed' has side-effects that are caused only if VD is not already
1764 // used. Hence no need for an extra check here.
1765 VD->markUsed(mCtx);
Stephen Hines3f175af2011-09-16 16:26:29 -07001766 // Make sure to create any helpers within the function's DeclContext,
1767 // not the one associated with the global translation unit.
1768 clang::Stmt *RSClearObjectCall = Scope::ClearRSObject(VD, FD);
Stephen Hines688e64b2011-08-23 16:01:25 -07001769 StmtList.push_back(RSClearObjectCall);
1770 }
1771 }
1772 }
1773
1774 // Nothing needs to be destroyed, so don't emit a dtor.
1775 if (StmtList.empty()) {
Chris Wailes5abbe0e2014-08-12 15:58:29 -07001776 return nullptr;
Stephen Hines688e64b2011-08-23 16:01:25 -07001777 }
1778
Stephen Hines688e64b2011-08-23 16:01:25 -07001779 clang::CompoundStmt *CS = BuildCompoundStmt(mCtx, StmtList, loc);
1780
Luis A. Lozanofb5cb9d2017-05-09 16:23:57 -07001781 slangAssert(FD);
Stephen Hines688e64b2011-08-23 16:01:25 -07001782 FD->setBody(CS);
I-Jui (Ray) Sungc8f5b2d2016-12-01 13:40:06 -08001783 // We need some way to tell if this FD is generated by slang
1784 FD->setImplicit();
Stephen Hines688e64b2011-08-23 16:01:25 -07001785
1786 return FD;
1787}
1788
David Gross65f23ed2016-01-08 12:04:59 -08001789bool HasRSObjectType(const clang::Type *T) {
1790 return CountRSObjectTypes(T) != 0;
1791}
1792
Stephen Hinese639eb52010-11-08 19:27:20 -08001793} // namespace slang