blob: cdf043f1011176d0b0a918256ce8dab20f6b1047 [file] [log] [blame]
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_object_ref_count.h"
18
Stephen Hinese639eb52010-11-08 19:27:20 -080019#include <list>
20
Stephen Hines4b32ffd2010-11-05 18:47:11 -070021#include "clang/AST/DeclGroup.h"
22#include "clang/AST/Expr.h"
Loganbe274822011-02-16 22:02:54 +080023#include "clang/AST/NestedNameSpecifier.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070024#include "clang/AST/OperationKinds.h"
25#include "clang/AST/Stmt.h"
26#include "clang/AST/StmtVisitor.h"
27
Stephen Hines6e6578a2011-02-07 18:05:48 -080028#include "slang_assert.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070029#include "slang_rs.h"
Stephen Hines292e00a2011-03-18 19:11:30 -070030#include "slang_rs_ast_replace.h"
Stephen Hines4b32ffd2010-11-05 18:47:11 -070031#include "slang_rs_export_type.h"
32
Stephen Hinese639eb52010-11-08 19:27:20 -080033namespace slang {
Stephen Hines4b32ffd2010-11-05 18:47:11 -070034
Stephen Hinesf2174cf2011-02-09 23:21:37 -080035clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080036 RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
37 RSExportPrimitiveType::FirstRSObjectType + 1];
Stephen Hinesf2174cf2011-02-09 23:21:37 -080038clang::FunctionDecl *RSObjectRefCount::
Stephen Hines1bdd4972010-11-08 17:35:08 -080039 RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
40 RSExportPrimitiveType::FirstRSObjectType + 1];
41
Stephen Hinesf2174cf2011-02-09 23:21:37 -080042void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
Stephen Hines1bdd4972010-11-08 17:35:08 -080043 for (unsigned i = 0;
44 i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
45 i++) {
46 RSSetObjectFD[i] = NULL;
47 RSClearObjectFD[i] = NULL;
48 }
49
50 clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
51
52 for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
53 E = TUDecl->decls_end(); I != E; I++) {
54 if ((I->getKind() >= clang::Decl::firstFunction) &&
55 (I->getKind() <= clang::Decl::lastFunction)) {
56 clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
57
58 // points to RSSetObjectFD or RSClearObjectFD
59 clang::FunctionDecl **RSObjectFD;
60
61 if (FD->getName() == "rsSetObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080062 slangAssert((FD->getNumParams() == 2) &&
63 "Invalid rsSetObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080064 RSObjectFD = RSSetObjectFD;
65 } else if (FD->getName() == "rsClearObject") {
Stephen Hines6e6578a2011-02-07 18:05:48 -080066 slangAssert((FD->getNumParams() == 1) &&
67 "Invalid rsClearObject function prototype (# params)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080068 RSObjectFD = RSClearObjectFD;
Stephen Hinese639eb52010-11-08 19:27:20 -080069 } else {
Stephen Hines1bdd4972010-11-08 17:35:08 -080070 continue;
71 }
72
73 const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
74 clang::QualType PVT = PVD->getOriginalType();
75 // The first parameter must be a pointer like rs_allocation*
Stephen Hines6e6578a2011-02-07 18:05:48 -080076 slangAssert(PVT->isPointerType() &&
77 "Invalid rs{Set,Clear}Object function prototype (pointer param)");
Stephen Hines1bdd4972010-11-08 17:35:08 -080078
79 // The rs object type passed to the FD
80 clang::QualType RST = PVT->getPointeeType();
81 RSExportPrimitiveType::DataType DT =
82 RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
Stephen Hines6e6578a2011-02-07 18:05:48 -080083 slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
Stephen Hines1bdd4972010-11-08 17:35:08 -080084 && "must be RS object type");
85
86 RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
87 }
88 }
89}
90
Stephen Hines4464d822010-11-11 16:45:08 -080091namespace {
92
Stephen Hines292e00a2011-03-18 19:11:30 -070093// This function constructs a new CompoundStmt from the input StmtList.
94static clang::CompoundStmt* BuildCompoundStmt(clang::ASTContext &C,
95 std::list<clang::Stmt*> &StmtList, clang::SourceLocation Loc) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -080096 unsigned NewStmtCount = StmtList.size();
Stephen Hines292e00a2011-03-18 19:11:30 -070097 unsigned CompoundStmtCount = 0;
Stephen Hines1bdd4972010-11-08 17:35:08 -080098
Stephen Hines292e00a2011-03-18 19:11:30 -070099 clang::Stmt **CompoundStmtList;
100 CompoundStmtList = new clang::Stmt*[NewStmtCount];
101
102 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
103 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
104 for ( ; I != E; I++) {
105 CompoundStmtList[CompoundStmtCount++] = *I;
106 }
107 slangAssert(CompoundStmtCount == NewStmtCount);
108
109 clang::CompoundStmt *CS = new(C) clang::CompoundStmt(C,
110 CompoundStmtList,
111 CompoundStmtCount,
112 Loc,
113 Loc);
114
115 delete [] CompoundStmtList;
116
117 return CS;
118}
119
120static void AppendAfterStmt(clang::ASTContext &C,
121 clang::CompoundStmt *CS,
122 clang::Stmt *S,
123 std::list<clang::Stmt*> &StmtList) {
124 slangAssert(CS);
125 clang::CompoundStmt::body_iterator bI = CS->body_begin();
126 clang::CompoundStmt::body_iterator bE = CS->body_end();
127 clang::Stmt **UpdatedStmtList =
128 new clang::Stmt*[CS->size() + StmtList.size()];
Stephen Hines1bdd4972010-11-08 17:35:08 -0800129
130 unsigned UpdatedStmtCount = 0;
Stephen Hines292e00a2011-03-18 19:11:30 -0700131 unsigned Once = 0;
132 for ( ; bI != bE; bI++) {
133 if (!S && ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass)) {
134 // If we come across a return here, we don't have anything we can
135 // reasonably replace. We should have already inserted our destructor
136 // code in the proper spot, so we just clean up and return.
137 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800138
Stephen Hines292e00a2011-03-18 19:11:30 -0700139 return;
140 }
141
142 UpdatedStmtList[UpdatedStmtCount++] = *bI;
143
144 if ((*bI == S) && !Once) {
145 Once++;
146 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
147 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
148 for ( ; I != E; I++) {
149 UpdatedStmtList[UpdatedStmtCount++] = *I;
150 }
151 }
152 }
153 slangAssert(Once <= 1);
154
155 // When S is NULL, we are appending to the end of the CompoundStmt.
156 if (!S) {
157 slangAssert(Once == 0);
Stephen Hines03981a32010-12-14 19:45:49 -0800158 std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
Stephen Hines292e00a2011-03-18 19:11:30 -0700159 std::list<clang::Stmt*>::const_iterator E = StmtList.end();
160 for ( ; I != E; I++) {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800161 UpdatedStmtList[UpdatedStmtCount++] = *I;
Stephen Hines4464d822010-11-11 16:45:08 -0800162 }
Stephen Hines1bdd4972010-11-08 17:35:08 -0800163 }
164
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800165 CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
Stephen Hines1bdd4972010-11-08 17:35:08 -0800166
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800167 delete [] UpdatedStmtList;
Stephen Hines1bdd4972010-11-08 17:35:08 -0800168
169 return;
170}
171
Stephen Hinesa883ce32011-08-11 18:52:48 -0700172// This class visits a compound statement and inserts DtorStmt
173// in proper locations. This includes inserting it before any
Stephen Hines4464d822010-11-11 16:45:08 -0800174// return statement in any sub-block, at the end of the logical enclosing
175// scope (compound statement), and/or before any break/continue statement that
176// would resume outside the declared scope. We will not handle the case for
177// goto statements that leave a local scope.
Stephen Hines292e00a2011-03-18 19:11:30 -0700178//
179// To accomplish these goals, it collects a list of sub-Stmt's that
180// correspond to scope exit points. It then uses an RSASTReplace visitor to
181// transform the AST, inserting appropriate destructors before each of those
182// sub-Stmt's (and also before the exit of the outermost containing Stmt for
183// the scope).
Stephen Hines4464d822010-11-11 16:45:08 -0800184class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
185 private:
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700186 clang::ASTContext &mCtx;
Stephen Hines292e00a2011-03-18 19:11:30 -0700187
188 // The loop depth of the currently visited node.
189 int mLoopDepth;
190
191 // The switch statement depth of the currently visited node.
192 // Note that this is tracked separately from the loop depth because
193 // SwitchStmt-contained ContinueStmt's should have destructors for the
194 // corresponding loop scope.
195 int mSwitchDepth;
196
197 // The outermost statement block that we are currently visiting.
198 // This should always be a CompoundStmt.
199 clang::Stmt *mOuterStmt;
200
Stephen Hinesa883ce32011-08-11 18:52:48 -0700201 // The destructor to execute for this scope/variable.
202 clang::Stmt* mDtorStmt;
Stephen Hines292e00a2011-03-18 19:11:30 -0700203
204 // The stack of statements which should be replaced by a compound statement
Stephen Hinesa883ce32011-08-11 18:52:48 -0700205 // containing the new destructor call followed by the original Stmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700206 std::stack<clang::Stmt*> mReplaceStmtStack;
207
Stephen Hinesa883ce32011-08-11 18:52:48 -0700208 // The source location for the variable declaration that we are trying to
209 // insert destructors for. Note that InsertDestructors() will not generate
210 // destructor calls for source locations that occur lexically before this
211 // location.
212 clang::SourceLocation mVarLoc;
213
Stephen Hines4464d822010-11-11 16:45:08 -0800214 public:
Stephen Hines292e00a2011-03-18 19:11:30 -0700215 DestructorVisitor(clang::ASTContext &C,
216 clang::Stmt* OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700217 clang::Stmt* DtorStmt,
218 clang::SourceLocation VarLoc);
Stephen Hines292e00a2011-03-18 19:11:30 -0700219
220 // This code walks the collected list of Stmts to replace and actually does
Stephen Hinesa883ce32011-08-11 18:52:48 -0700221 // the replacement. It also finishes up by appending the destructor to the
222 // current outermost CompoundStmt.
Stephen Hines292e00a2011-03-18 19:11:30 -0700223 void InsertDestructors() {
224 clang::Stmt *S = NULL;
Stephen Hinesa883ce32011-08-11 18:52:48 -0700225 clang::SourceManager &SM = mCtx.getSourceManager();
226 std::list<clang::Stmt *> StmtList;
227 StmtList.push_back(mDtorStmt);
228
Stephen Hines292e00a2011-03-18 19:11:30 -0700229 while (!mReplaceStmtStack.empty()) {
230 S = mReplaceStmtStack.top();
231 mReplaceStmtStack.pop();
232
Stephen Hinesa883ce32011-08-11 18:52:48 -0700233 // Skip all source locations that occur before the variable's
234 // declaration, since it won't have been initialized yet.
235 if (SM.isBeforeInTranslationUnit(S->getLocStart(), mVarLoc)) {
236 continue;
237 }
238
239 StmtList.push_back(S);
Stephen Hines292e00a2011-03-18 19:11:30 -0700240 clang::CompoundStmt *CS =
Stephen Hinesa883ce32011-08-11 18:52:48 -0700241 BuildCompoundStmt(mCtx, StmtList, S->getLocEnd());
242 StmtList.pop_back();
Stephen Hines292e00a2011-03-18 19:11:30 -0700243
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700244 RSASTReplace R(mCtx);
Stephen Hines292e00a2011-03-18 19:11:30 -0700245 R.ReplaceStmt(mOuterStmt, S, CS);
246 }
Logan Chienab992e52011-07-20 22:06:52 +0800247 clang::CompoundStmt *CS =
248 llvm::dyn_cast<clang::CompoundStmt>(mOuterStmt);
Stephen Hines292e00a2011-03-18 19:11:30 -0700249 slangAssert(CS);
Stephen Hinesa883ce32011-08-11 18:52:48 -0700250 AppendAfterStmt(mCtx, CS, NULL, StmtList);
Stephen Hines292e00a2011-03-18 19:11:30 -0700251 }
252
Stephen Hines4464d822010-11-11 16:45:08 -0800253 void VisitStmt(clang::Stmt *S);
254 void VisitCompoundStmt(clang::CompoundStmt *CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700255
256 void VisitBreakStmt(clang::BreakStmt *BS);
257 void VisitCaseStmt(clang::CaseStmt *CS);
258 void VisitContinueStmt(clang::ContinueStmt *CS);
259 void VisitDefaultStmt(clang::DefaultStmt *DS);
260 void VisitDoStmt(clang::DoStmt *DS);
261 void VisitForStmt(clang::ForStmt *FS);
262 void VisitIfStmt(clang::IfStmt *IS);
263 void VisitReturnStmt(clang::ReturnStmt *RS);
264 void VisitSwitchCase(clang::SwitchCase *SC);
265 void VisitSwitchStmt(clang::SwitchStmt *SS);
266 void VisitWhileStmt(clang::WhileStmt *WS);
Stephen Hines4464d822010-11-11 16:45:08 -0800267};
268
269DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hines292e00a2011-03-18 19:11:30 -0700270 clang::Stmt *OuterStmt,
Stephen Hinesa883ce32011-08-11 18:52:48 -0700271 clang::Stmt *DtorStmt,
272 clang::SourceLocation VarLoc)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700273 : mCtx(C),
Stephen Hines292e00a2011-03-18 19:11:30 -0700274 mLoopDepth(0),
275 mSwitchDepth(0),
276 mOuterStmt(OuterStmt),
Stephen Hinesa883ce32011-08-11 18:52:48 -0700277 mDtorStmt(DtorStmt),
278 mVarLoc(VarLoc) {
Stephen Hines4464d822010-11-11 16:45:08 -0800279 return;
280}
281
282void DestructorVisitor::VisitStmt(clang::Stmt *S) {
283 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
284 I != E;
285 I++) {
286 if (clang::Stmt *Child = *I) {
287 Visit(Child);
288 }
289 }
290 return;
291}
292
Stephen Hines292e00a2011-03-18 19:11:30 -0700293void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
294 VisitStmt(CS);
295 return;
296}
297
298void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
299 VisitStmt(BS);
300 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
301 mReplaceStmtStack.push(BS);
302 }
303 return;
304}
305
306void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
307 VisitStmt(CS);
308 return;
309}
310
311void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
312 VisitStmt(CS);
313 if (mLoopDepth == 0) {
314 // Switch statements can have nested continues.
315 mReplaceStmtStack.push(CS);
316 }
317 return;
318}
319
320void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
321 VisitStmt(DS);
322 return;
323}
324
325void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
326 mLoopDepth++;
327 VisitStmt(DS);
328 mLoopDepth--;
329 return;
330}
331
332void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
333 mLoopDepth++;
334 VisitStmt(FS);
335 mLoopDepth--;
336 return;
337}
338
339void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
340 VisitStmt(IS);
341 return;
342}
343
344void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
345 mReplaceStmtStack.push(RS);
346 return;
347}
348
349void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
350 slangAssert(false && "Both case and default have specialized handlers");
351 VisitStmt(SC);
352 return;
353}
354
355void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
356 mSwitchDepth++;
357 VisitStmt(SS);
358 mSwitchDepth--;
359 return;
360}
361
362void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
363 mLoopDepth++;
364 VisitStmt(WS);
365 mLoopDepth--;
366 return;
367}
368
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800369clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
370 clang::Expr *RefRSVar,
371 clang::SourceLocation Loc) {
372 slangAssert(RefRSVar);
373 const clang::Type *T = RefRSVar->getType().getTypePtr();
374 slangAssert(!T->isArrayType() &&
375 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800376
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800377 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
378 slangAssert((ClearObjectFD != NULL) &&
379 "rsClearObject doesn't cover all RS object types");
380
381 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
382 clang::QualType ClearObjectFDArgType =
383 ClearObjectFD->getParamDecl(0)->getOriginalType();
384
385 // Example destructor for "rs_font localFont;"
386 //
387 // (CallExpr 'void'
388 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
389 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
390 // (UnaryOperator 'rs_font *' prefix '&'
391 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
392
393 // Get address of targeted RS object
394 clang::Expr *AddrRefRSVar =
395 new(C) clang::UnaryOperator(RefRSVar,
396 clang::UO_AddrOf,
397 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800398 clang::VK_RValue,
399 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800400 Loc);
401
402 clang::Expr *RefRSClearObjectFD =
403 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800404 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800405 ClearObjectFD,
406 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800407 ClearObjectFDType,
408 clang::VK_RValue,
409 NULL);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800410
411 clang::Expr *RSClearObjectFP =
412 clang::ImplicitCastExpr::Create(C,
413 C.getPointerType(ClearObjectFDType),
414 clang::CK_FunctionToPointerDecay,
415 RefRSClearObjectFD,
416 NULL,
417 clang::VK_RValue);
418
419 clang::CallExpr *RSClearObjectCall =
420 new(C) clang::CallExpr(C,
421 RSClearObjectFP,
422 &AddrRefRSVar,
423 1,
424 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800425 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800426 Loc);
427
428 return RSClearObjectCall;
429}
430
431static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800432 if (!T || !T->isArrayType()) {
433 return 0;
434 }
435
436 const clang::ConstantArrayType *CAT =
437 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800438 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800439}
440
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800441static clang::Stmt *ClearStructRSObject(
442 clang::ASTContext &C,
443 clang::DeclContext *DC,
444 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700445 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800446 clang::SourceLocation Loc);
447
448static clang::Stmt *ClearArrayRSObject(
449 clang::ASTContext &C,
450 clang::DeclContext *DC,
451 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700452 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800453 clang::SourceLocation Loc) {
454 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
455 slangAssert(BaseType->isArrayType());
456
457 int NumArrayElements = ArrayDim(BaseType);
458 // Actually extract out the base RS object type for use later
459 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800460
461 clang::Stmt *StmtArray[2] = {NULL};
462 int StmtCtr = 0;
463
Stephen Hines03981a32010-12-14 19:45:49 -0800464 if (NumArrayElements <= 0) {
465 return NULL;
466 }
467
468 // Example destructor loop for "rs_font fontArr[10];"
469 //
470 // (CompoundStmt
471 // (DeclStmt "int rsIntIter")
472 // (ForStmt
473 // (BinaryOperator 'int' '='
474 // (DeclRefExpr 'int' Var='rsIntIter')
475 // (IntegerLiteral 'int' 0))
476 // (BinaryOperator 'int' '<'
477 // (DeclRefExpr 'int' Var='rsIntIter')
478 // (IntegerLiteral 'int' 10)
479 // NULL << CondVar >>
480 // (UnaryOperator 'int' postfix '++'
481 // (DeclRefExpr 'int' Var='rsIntIter'))
482 // (CallExpr 'void'
483 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
484 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
485 // (UnaryOperator 'rs_font *' prefix '&'
486 // (ArraySubscriptExpr 'rs_font':'rs_font'
487 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
488 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
489 // (DeclRefExpr 'int' Var='rsIntIter')))))))
490
491 // Create helper variable for iterating through elements
492 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
493 clang::VarDecl *IIVD =
494 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800495 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700496 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800497 Loc,
498 &II,
499 C.IntTy,
500 C.getTrivialTypeSourceInfo(C.IntTy),
501 clang::SC_None,
502 clang::SC_None);
503 clang::Decl *IID = (clang::Decl *)IIVD;
504
505 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
506 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
507
508 // Form the actual destructor loop
509 // for (Init; Cond; Inc)
510 // RSClearObjectCall;
511
512 // Init -> "rsIntIter = 0"
513 clang::DeclRefExpr *RefrsIntIter =
514 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800515 clang::NestedNameSpecifierLoc(),
Stephen Hines03981a32010-12-14 19:45:49 -0800516 IIVD,
517 Loc,
Loganbe274822011-02-16 22:02:54 +0800518 C.IntTy,
519 clang::VK_RValue,
520 NULL);
Stephen Hines03981a32010-12-14 19:45:49 -0800521
522 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
523 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
524
525 clang::BinaryOperator *Init =
526 new(C) clang::BinaryOperator(RefrsIntIter,
527 Int0,
528 clang::BO_Assign,
529 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800530 clang::VK_RValue,
531 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800532 Loc);
533
534 // Cond -> "rsIntIter < NumArrayElements"
535 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
536 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
537
538 clang::BinaryOperator *Cond =
539 new(C) clang::BinaryOperator(RefrsIntIter,
540 NumArrayElementsExpr,
541 clang::BO_LT,
542 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800543 clang::VK_RValue,
544 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800545 Loc);
546
547 // Inc -> "rsIntIter++"
548 clang::UnaryOperator *Inc =
549 new(C) clang::UnaryOperator(RefrsIntIter,
550 clang::UO_PostInc,
551 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800552 clang::VK_RValue,
553 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800554 Loc);
555
556 // Body -> "rsClearObject(&VD[rsIntIter]);"
557 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800558
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800559 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800560 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800561 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800562 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800563 RefRSArr,
Stephen Hines03981a32010-12-14 19:45:49 -0800564 NULL,
565 clang::VK_RValue);
566
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800567 clang::Expr *RefRSArrPtrSubscript =
568 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hines03981a32010-12-14 19:45:49 -0800569 RefrsIntIter,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800570 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800571 clang::VK_RValue,
572 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800573 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800574
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800575 RSExportPrimitiveType::DataType DT =
576 RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800577
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800578 clang::Stmt *RSClearObjectCall = NULL;
579 if (BaseType->isArrayType()) {
580 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700581 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800582 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
583 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700584 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800585 } else {
586 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
587 }
Stephen Hines03981a32010-12-14 19:45:49 -0800588
589 clang::ForStmt *DestructorLoop =
590 new(C) clang::ForStmt(C,
591 Init,
592 Cond,
593 NULL, // no condVar
594 Inc,
595 RSClearObjectCall,
596 Loc,
597 Loc,
598 Loc);
599
600 StmtArray[StmtCtr++] = DestructorLoop;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800601 slangAssert(StmtCtr == 2);
Stephen Hines03981a32010-12-14 19:45:49 -0800602
603 clang::CompoundStmt *CS =
604 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
605
606 return CS;
607}
608
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700609static unsigned CountRSObjectTypes(clang::ASTContext &C,
610 const clang::Type *T,
611 clang::SourceLocation Loc) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800612 slangAssert(T);
613 unsigned RSObjectCount = 0;
614
615 if (T->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700616 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800617 }
618
619 RSExportPrimitiveType::DataType DT =
620 RSExportPrimitiveType::GetRSSpecificType(T);
621 if (DT != RSExportPrimitiveType::DataTypeUnknown) {
622 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
623 }
624
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700625 if (T->isUnionType()) {
626 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
627 RD = RD->getDefinition();
628 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
629 FE = RD->field_end();
630 FI != FE;
631 FI++) {
632 const clang::FieldDecl *FD = *FI;
633 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
634 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines78e69cb2011-04-22 15:03:19 -0700635 slangAssert(false && "can't have unions with RS object types!");
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700636 return 0;
637 }
638 }
639 }
640
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800641 if (!T->isStructureType()) {
642 return 0;
643 }
644
645 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
646 RD = RD->getDefinition();
647 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
648 FE = RD->field_end();
649 FI != FE;
650 FI++) {
651 const clang::FieldDecl *FD = *FI;
652 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700653 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800654 // Sub-structs should only count once (as should arrays, etc.)
655 RSObjectCount++;
656 }
657 }
658
659 return RSObjectCount;
660}
661
662static clang::Stmt *ClearStructRSObject(
663 clang::ASTContext &C,
664 clang::DeclContext *DC,
665 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700666 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800667 clang::SourceLocation Loc) {
668 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
669
670 slangAssert(!BaseType->isArrayType());
671
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800672 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700673 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
674 RSExportPrimitiveType::DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800675
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700676 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800677
678 unsigned StmtCount = 0;
679 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800680 for (unsigned i = 0; i < FieldsToDestroy; i++) {
681 StmtArray[i] = NULL;
682 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800683
684 // Populate StmtArray by creating a destructor for each RS object field
685 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
686 RD = RD->getDefinition();
687 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
688 FE = RD->field_end();
689 FI != FE;
690 FI++) {
691 // We just look through all field declarations to see if we find a
692 // declaration for an RS object type (or an array of one).
693 bool IsArrayType = false;
694 clang::FieldDecl *FD = *FI;
695 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
696 const clang::Type *OrigType = FT;
697 while (FT && FT->isArrayType()) {
698 FT = FT->getArrayElementTypeNoTypeQual();
699 IsArrayType = true;
700 }
701
702 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
703 clang::DeclAccessPair FoundDecl =
704 clang::DeclAccessPair::make(FD, clang::AS_none);
705 clang::MemberExpr *RSObjectMember =
706 clang::MemberExpr::Create(C,
707 RefRSStruct,
708 false,
Loganbe274822011-02-16 22:02:54 +0800709 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800710 FD,
711 FoundDecl,
712 clang::DeclarationNameInfo(),
713 NULL,
Loganbe274822011-02-16 22:02:54 +0800714 OrigType->getCanonicalTypeInternal(),
715 clang::VK_RValue,
716 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800717
718 slangAssert(StmtCount < FieldsToDestroy);
719
720 if (IsArrayType) {
721 StmtArray[StmtCount++] = ClearArrayRSObject(C,
722 DC,
723 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700724 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800725 Loc);
726 } else {
727 StmtArray[StmtCount++] = ClearSingleRSObject(C,
728 RSObjectMember,
729 Loc);
730 }
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700731 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800732 // In this case, we have a nested struct. We may not end up filling all
733 // of the spaces in StmtArray (sub-structs should handle themselves
734 // with separate compound statements).
735 clang::DeclAccessPair FoundDecl =
736 clang::DeclAccessPair::make(FD, clang::AS_none);
737 clang::MemberExpr *RSObjectMember =
738 clang::MemberExpr::Create(C,
739 RefRSStruct,
740 false,
Loganbe274822011-02-16 22:02:54 +0800741 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800742 FD,
743 FoundDecl,
744 clang::DeclarationNameInfo(),
745 NULL,
Loganbe274822011-02-16 22:02:54 +0800746 OrigType->getCanonicalTypeInternal(),
747 clang::VK_RValue,
748 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800749
750 if (IsArrayType) {
751 StmtArray[StmtCount++] = ClearArrayRSObject(C,
752 DC,
753 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700754 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800755 Loc);
756 } else {
757 StmtArray[StmtCount++] = ClearStructRSObject(C,
758 DC,
759 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700760 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800761 Loc);
762 }
763 }
764 }
765
766 slangAssert(StmtCount > 0);
767 clang::CompoundStmt *CS =
768 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
769
770 delete [] StmtArray;
771
772 return CS;
773}
774
Stephen Hines2bb67db2011-02-11 01:36:40 -0800775static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800776 clang::Expr *DstExpr,
777 clang::Expr *SrcExpr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700778 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800779 clang::SourceLocation Loc) {
780 const clang::Type *T = DstExpr->getType().getTypePtr();
781 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800782 slangAssert((SetObjectFD != NULL) &&
783 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800784
785 clang::QualType SetObjectFDType = SetObjectFD->getType();
786 clang::QualType SetObjectFDArgType[2];
787 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
788 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
789
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800790 clang::Expr *RefRSSetObjectFD =
791 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800792 clang::NestedNameSpecifierLoc(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800793 SetObjectFD,
794 Loc,
Loganbe274822011-02-16 22:02:54 +0800795 SetObjectFDType,
796 clang::VK_RValue,
797 NULL);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800798
799 clang::Expr *RSSetObjectFP =
800 clang::ImplicitCastExpr::Create(C,
801 C.getPointerType(SetObjectFDType),
802 clang::CK_FunctionToPointerDecay,
803 RefRSSetObjectFD,
804 NULL,
805 clang::VK_RValue);
806
807 clang::Expr *ArgList[2];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800808 ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800809 clang::UO_AddrOf,
810 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +0800811 clang::VK_RValue,
812 clang::OK_Ordinary,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800813 Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800814 ArgList[1] = SrcExpr;
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800815
816 clang::CallExpr *RSSetObjectCall =
817 new(C) clang::CallExpr(C,
818 RSSetObjectFP,
819 ArgList,
820 2,
821 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800822 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800823 Loc);
824
Stephen Hines2bb67db2011-02-11 01:36:40 -0800825 return RSSetObjectCall;
826}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800827
Stephen Hines2bb67db2011-02-11 01:36:40 -0800828static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800829 clang::Expr *LHS,
830 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700831 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800832 clang::SourceLocation Loc);
833
834static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800835 clang::Expr *DstArr,
836 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700837 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800838 clang::SourceLocation Loc) {
839 clang::DeclContext *DC = NULL;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800840 const clang::Type *BaseType = DstArr->getType().getTypePtr();
841 slangAssert(BaseType->isArrayType());
842
843 int NumArrayElements = ArrayDim(BaseType);
844 // Actually extract out the base RS object type for use later
845 BaseType = BaseType->getArrayElementTypeNoTypeQual();
846
847 clang::Stmt *StmtArray[2] = {NULL};
848 int StmtCtr = 0;
849
850 if (NumArrayElements <= 0) {
851 return NULL;
852 }
853
854 // Create helper variable for iterating through elements
855 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
856 clang::VarDecl *IIVD =
857 clang::VarDecl::Create(C,
858 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700859 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800860 Loc,
861 &II,
862 C.IntTy,
863 C.getTrivialTypeSourceInfo(C.IntTy),
864 clang::SC_None,
865 clang::SC_None);
866 clang::Decl *IID = (clang::Decl *)IIVD;
867
868 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
869 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
870
871 // Form the actual loop
872 // for (Init; Cond; Inc)
873 // RSSetObjectCall;
874
875 // Init -> "rsIntIter = 0"
876 clang::DeclRefExpr *RefrsIntIter =
877 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800878 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800879 IIVD,
880 Loc,
Loganbe274822011-02-16 22:02:54 +0800881 C.IntTy,
882 clang::VK_RValue,
883 NULL);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800884
885 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
886 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
887
888 clang::BinaryOperator *Init =
889 new(C) clang::BinaryOperator(RefrsIntIter,
890 Int0,
891 clang::BO_Assign,
892 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800893 clang::VK_RValue,
894 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800895 Loc);
896
897 // Cond -> "rsIntIter < NumArrayElements"
898 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
899 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
900
901 clang::BinaryOperator *Cond =
902 new(C) clang::BinaryOperator(RefrsIntIter,
903 NumArrayElementsExpr,
904 clang::BO_LT,
905 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800906 clang::VK_RValue,
907 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800908 Loc);
909
910 // Inc -> "rsIntIter++"
911 clang::UnaryOperator *Inc =
912 new(C) clang::UnaryOperator(RefrsIntIter,
913 clang::UO_PostInc,
914 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800915 clang::VK_RValue,
916 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800917 Loc);
918
919 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
920 // Loop operates on individual array elements
921
922 clang::Expr *DstArrPtr =
923 clang::ImplicitCastExpr::Create(C,
924 C.getPointerType(BaseType->getCanonicalTypeInternal()),
925 clang::CK_ArrayToPointerDecay,
926 DstArr,
927 NULL,
928 clang::VK_RValue);
929
930 clang::Expr *DstArrPtrSubscript =
931 new(C) clang::ArraySubscriptExpr(DstArrPtr,
932 RefrsIntIter,
933 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800934 clang::VK_RValue,
935 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800936 Loc);
937
938 clang::Expr *SrcArrPtr =
939 clang::ImplicitCastExpr::Create(C,
940 C.getPointerType(BaseType->getCanonicalTypeInternal()),
941 clang::CK_ArrayToPointerDecay,
942 SrcArr,
943 NULL,
944 clang::VK_RValue);
945
946 clang::Expr *SrcArrPtrSubscript =
947 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
948 RefrsIntIter,
949 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800950 clang::VK_RValue,
951 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800952 Loc);
953
954 RSExportPrimitiveType::DataType DT =
955 RSExportPrimitiveType::GetRSSpecificType(BaseType);
956
957 clang::Stmt *RSSetObjectCall = NULL;
958 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700959 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700960 SrcArrPtrSubscript,
961 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800962 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700963 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700964 SrcArrPtrSubscript,
965 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800966 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700967 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700968 SrcArrPtrSubscript,
969 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800970 }
971
972 clang::ForStmt *DestructorLoop =
973 new(C) clang::ForStmt(C,
974 Init,
975 Cond,
976 NULL, // no condVar
977 Inc,
978 RSSetObjectCall,
979 Loc,
980 Loc,
981 Loc);
982
983 StmtArray[StmtCtr++] = DestructorLoop;
984 slangAssert(StmtCtr == 2);
985
986 clang::CompoundStmt *CS =
987 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
988
989 return CS;
990}
991
992static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800993 clang::Expr *LHS,
994 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700995 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800996 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800997 clang::QualType QT = LHS->getType();
998 const clang::Type *T = QT.getTypePtr();
999 slangAssert(T->isStructureType());
1000 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
1001
1002 // Keep an extra slot for the original copy (memcpy)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001003 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -08001004
1005 unsigned StmtCount = 0;
1006 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
1007 for (unsigned i = 0; i < FieldsToSet; i++) {
1008 StmtArray[i] = NULL;
1009 }
1010
1011 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
1012 RD = RD->getDefinition();
1013 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1014 FE = RD->field_end();
1015 FI != FE;
1016 FI++) {
1017 bool IsArrayType = false;
1018 clang::FieldDecl *FD = *FI;
1019 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1020 const clang::Type *OrigType = FT;
1021
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001022 if (!CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001023 // Skip to next if we don't have any viable RS object types
1024 continue;
1025 }
1026
1027 clang::DeclAccessPair FoundDecl =
1028 clang::DeclAccessPair::make(FD, clang::AS_none);
1029 clang::MemberExpr *DstMember =
1030 clang::MemberExpr::Create(C,
1031 LHS,
1032 false,
Loganbe274822011-02-16 22:02:54 +08001033 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001034 FD,
1035 FoundDecl,
1036 clang::DeclarationNameInfo(),
1037 NULL,
Loganbe274822011-02-16 22:02:54 +08001038 OrigType->getCanonicalTypeInternal(),
1039 clang::VK_RValue,
1040 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001041
1042 clang::MemberExpr *SrcMember =
1043 clang::MemberExpr::Create(C,
1044 RHS,
1045 false,
Loganbe274822011-02-16 22:02:54 +08001046 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001047 FD,
1048 FoundDecl,
1049 clang::DeclarationNameInfo(),
1050 NULL,
Loganbe274822011-02-16 22:02:54 +08001051 OrigType->getCanonicalTypeInternal(),
1052 clang::VK_RValue,
1053 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001054
1055 if (FT->isArrayType()) {
1056 FT = FT->getArrayElementTypeNoTypeQual();
1057 IsArrayType = true;
1058 }
1059
1060 RSExportPrimitiveType::DataType DT =
1061 RSExportPrimitiveType::GetRSSpecificType(FT);
1062
1063 if (IsArrayType) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001064 clang::Diagnostic &Diags = C.getDiagnostics();
1065 Diags.Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
1066 Diags.getCustomDiagID(clang::Diagnostic::Error,
Stephen Hines832429f2011-02-25 16:05:37 -08001067 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -08001068 // TODO(srhines): Support setting arrays of RS objects
1069 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001070 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001071 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
1072 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001073 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001074 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
1075 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001076 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001077 } else {
1078 slangAssert(false);
1079 }
1080 }
1081
1082 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
1083
1084 // We still need to actually do the overall struct copy. For simplicity,
1085 // we just do a straight-up assignment (which will still preserve all
1086 // the proper RS object reference counts).
1087 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001088 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
1089 clang::VK_RValue, clang::OK_Ordinary, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001090 StmtArray[StmtCount++] = CopyStruct;
1091
1092 clang::CompoundStmt *CS =
1093 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
1094
1095 delete [] StmtArray;
1096
1097 return CS;
1098}
1099
1100} // namespace
1101
1102void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001103 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001104
1105 clang::QualType QT = AS->getType();
1106
1107 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1108 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1109
Stephen Hines832429f2011-02-25 16:05:37 -08001110 clang::SourceLocation Loc = AS->getExprLoc();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001111 clang::SourceLocation StartLoc = AS->getExprLoc();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001112 clang::Stmt *UpdatedStmt = NULL;
1113
1114 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1115 // By definition, this is a struct assignment if we get here
1116 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001117 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001118 } else {
1119 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001120 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001121 }
1122
Stephen Hines292e00a2011-03-18 19:11:30 -07001123 RSASTReplace R(C);
1124 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001125 return;
1126}
1127
1128void RSObjectRefCount::Scope::AppendRSObjectInit(
1129 clang::VarDecl *VD,
1130 clang::DeclStmt *DS,
1131 RSExportPrimitiveType::DataType DT,
1132 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001133 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001134
1135 if (!InitExpr) {
1136 return;
1137 }
1138
Stephen Hinesa0611e62011-02-11 16:35:47 -08001139 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1140 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1141 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
1142 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001143 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
1144 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001145
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001146 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001147 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1148 clang::DeclRefExpr *RefRSVar =
1149 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001150 clang::NestedNameSpecifierLoc(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001151 VD,
1152 Loc,
Loganbe274822011-02-16 22:02:54 +08001153 T->getCanonicalTypeInternal(),
1154 clang::VK_RValue,
1155 NULL);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001156
1157 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001158 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001159
Stephen Hines292e00a2011-03-18 19:11:30 -07001160 std::list<clang::Stmt*> StmtList;
1161 StmtList.push_back(RSSetObjectOps);
1162 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001163 return;
1164 }
1165
1166 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -08001167 slangAssert((SetObjectFD != NULL) &&
1168 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001169
1170 clang::QualType SetObjectFDType = SetObjectFD->getType();
1171 clang::QualType SetObjectFDArgType[2];
1172 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1173 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1174
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001175 clang::Expr *RefRSSetObjectFD =
1176 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001177 clang::NestedNameSpecifierLoc(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001178 SetObjectFD,
1179 Loc,
Loganbe274822011-02-16 22:02:54 +08001180 SetObjectFDType,
1181 clang::VK_RValue,
1182 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001183
1184 clang::Expr *RSSetObjectFP =
1185 clang::ImplicitCastExpr::Create(C,
1186 C.getPointerType(SetObjectFDType),
1187 clang::CK_FunctionToPointerDecay,
1188 RefRSSetObjectFD,
1189 NULL,
1190 clang::VK_RValue);
1191
1192 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1193 clang::DeclRefExpr *RefRSVar =
1194 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001195 clang::NestedNameSpecifierLoc(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001196 VD,
1197 Loc,
Loganbe274822011-02-16 22:02:54 +08001198 T->getCanonicalTypeInternal(),
1199 clang::VK_RValue,
1200 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001201
1202 clang::Expr *ArgList[2];
1203 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1204 clang::UO_AddrOf,
1205 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +08001206 clang::VK_RValue,
1207 clang::OK_Ordinary,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001208 Loc);
1209 ArgList[1] = InitExpr;
1210
1211 clang::CallExpr *RSSetObjectCall =
1212 new(C) clang::CallExpr(C,
1213 RSSetObjectFP,
1214 ArgList,
1215 2,
1216 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001217 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001218 Loc);
1219
Stephen Hines292e00a2011-03-18 19:11:30 -07001220 std::list<clang::Stmt*> StmtList;
1221 StmtList.push_back(RSSetObjectCall);
1222 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001223
1224 return;
1225}
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;
1233 clang::Stmt *RSClearObjectCall = ClearRSObject(VD);
1234 if (RSClearObjectCall) {
1235 DestructorVisitor DV((*mRSO.begin())->getASTContext(),
1236 mCS,
1237 RSClearObjectCall,
1238 VD->getSourceRange().getBegin());
1239 DV.Visit(mCS);
1240 DV.InsertDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001241 }
1242 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001243 return;
1244}
1245
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001246clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001247 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001248 clang::ASTContext &C = VD->getASTContext();
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001249 clang::DeclContext *DC = VD->getDeclContext();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001250 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001251 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001252 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001253
Stephen Hines1bdd4972010-11-08 17:35:08 -08001254 // Reference expr to target RS object variable
1255 clang::DeclRefExpr *RefRSVar =
1256 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001257 clang::NestedNameSpecifierLoc(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001258 VD,
1259 Loc,
Loganbe274822011-02-16 22:02:54 +08001260 T->getCanonicalTypeInternal(),
1261 clang::VK_RValue,
1262 NULL);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001263
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001264 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001265 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001266 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001267
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001268 RSExportPrimitiveType::DataType DT =
1269 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001270
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001271 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1272 DT == RSExportPrimitiveType::DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001273 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001274 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001275
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001276 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1277 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001278
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001279 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001280}
1281
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001282bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1283 RSExportPrimitiveType::DataType *DT,
1284 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001285 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001286 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001287
1288 // Loop through array types to get to base type
1289 while (T && T->isArrayType()) {
1290 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001291 }
1292
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001293 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001294 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001295
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001296 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001297 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1298 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001299 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001300 } else {
1301 return false;
1302 }
Stephen Hines2d095042010-11-12 18:13:56 -08001303 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001304
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001305 bool DataTypeIsRSObject = false;
1306 if (DataTypeIsStructWithRSObject) {
1307 DataTypeIsRSObject = true;
1308 } else {
1309 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1310 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001311 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001312
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001313 if (!DataTypeIsRSObject && *InitExpr) {
1314 // If we already have an initializer for a matrix type, we are done.
1315 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001316 }
1317
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001318 clang::Expr *ZeroInitializer =
1319 CreateZeroInitializerForRSSpecificType(*DT,
1320 VD->getASTContext(),
1321 VD->getLocation());
1322
1323 if (ZeroInitializer) {
1324 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1325 VD->setInit(ZeroInitializer);
1326 }
1327
1328 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001329}
1330
1331clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1332 RSExportPrimitiveType::DataType DT,
1333 clang::ASTContext &C,
1334 const clang::SourceLocation &Loc) {
1335 clang::Expr *Res = NULL;
1336 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001337 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001338 case RSExportPrimitiveType::DataTypeRSElement:
1339 case RSExportPrimitiveType::DataTypeRSType:
1340 case RSExportPrimitiveType::DataTypeRSAllocation:
1341 case RSExportPrimitiveType::DataTypeRSSampler:
1342 case RSExportPrimitiveType::DataTypeRSScript:
1343 case RSExportPrimitiveType::DataTypeRSMesh:
1344 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1345 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1346 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1347 case RSExportPrimitiveType::DataTypeRSProgramStore:
1348 case RSExportPrimitiveType::DataTypeRSFont: {
1349 // (ImplicitCastExpr 'nullptr_t'
1350 // (IntegerLiteral 0)))
1351 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1352 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1353 clang::Expr *CastToNull =
1354 clang::ImplicitCastExpr::Create(C,
1355 C.NullPtrTy,
1356 clang::CK_IntegralToPointer,
1357 Int0,
1358 NULL,
1359 clang::VK_RValue);
1360
Stephen Hinese639eb52010-11-08 19:27:20 -08001361 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001362 break;
1363 }
1364 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1365 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1366 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1367 // RS matrix is not completely an RS object. They hold data by themselves.
1368 // (InitListExpr rs_matrix2x2
1369 // (InitListExpr float[4]
1370 // (FloatingLiteral 0)
1371 // (FloatingLiteral 0)
1372 // (FloatingLiteral 0)
1373 // (FloatingLiteral 0)))
1374 clang::QualType FloatTy = C.FloatTy;
1375 // Constructor sets value to 0.0f by default
1376 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1377 clang::FloatingLiteral *Float0Val =
1378 clang::FloatingLiteral::Create(C,
1379 Val,
1380 /* isExact = */true,
1381 FloatTy,
1382 Loc);
1383
1384 unsigned N = 0;
1385 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1386 N = 2;
1387 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1388 N = 3;
1389 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1390 N = 4;
1391
1392 // Directly allocate 16 elements instead of dynamically allocate N*N
1393 clang::Expr *InitVals[16];
1394 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1395 InitVals[i] = Float0Val;
1396 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -08001397 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001398 InitExpr->setType(C.getConstantArrayType(FloatTy,
1399 llvm::APInt(32, 4),
1400 clang::ArrayType::Normal,
1401 /* EltTypeQuals = */0));
1402
Stephen Hinese639eb52010-11-08 19:27:20 -08001403 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001404 break;
1405 }
1406 case RSExportPrimitiveType::DataTypeUnknown:
1407 case RSExportPrimitiveType::DataTypeFloat16:
1408 case RSExportPrimitiveType::DataTypeFloat32:
1409 case RSExportPrimitiveType::DataTypeFloat64:
1410 case RSExportPrimitiveType::DataTypeSigned8:
1411 case RSExportPrimitiveType::DataTypeSigned16:
1412 case RSExportPrimitiveType::DataTypeSigned32:
1413 case RSExportPrimitiveType::DataTypeSigned64:
1414 case RSExportPrimitiveType::DataTypeUnsigned8:
1415 case RSExportPrimitiveType::DataTypeUnsigned16:
1416 case RSExportPrimitiveType::DataTypeUnsigned32:
1417 case RSExportPrimitiveType::DataTypeUnsigned64:
1418 case RSExportPrimitiveType::DataTypeBoolean:
1419 case RSExportPrimitiveType::DataTypeUnsigned565:
1420 case RSExportPrimitiveType::DataTypeUnsigned5551:
1421 case RSExportPrimitiveType::DataTypeUnsigned4444:
1422 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001423 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001424 }
1425 // No default case will enable compiler detecting the missing cases
1426 }
1427
1428 return Res;
1429}
1430
1431void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1432 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1433 I != E;
1434 I++) {
1435 clang::Decl *D = *I;
1436 if (D->getKind() == clang::Decl::Var) {
1437 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001438 RSExportPrimitiveType::DataType DT =
1439 RSExportPrimitiveType::DataTypeUnknown;
1440 clang::Expr *InitExpr = NULL;
1441 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001442 getCurrentScope()->addRSObject(VD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001443 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001444 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001445 }
1446 }
1447 return;
1448}
1449
1450void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1451 if (!CS->body_empty()) {
1452 // Push a new scope
1453 Scope *S = new Scope(CS);
1454 mScopeStack.push(S);
1455
1456 VisitStmt(CS);
1457
1458 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001459 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001460 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001461 mScopeStack.pop();
1462 delete S;
1463 }
1464 return;
1465}
1466
1467void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001468 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001469
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001470 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1471 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001472 }
1473
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001474 return;
1475}
1476
1477void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1478 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1479 I != E;
1480 I++) {
1481 if (clang::Stmt *Child = *I) {
1482 Visit(Child);
1483 }
1484 }
1485 return;
1486}
1487
Stephen Hinese639eb52010-11-08 19:27:20 -08001488} // namespace slang