blob: 96daaf719f83d05e14ceb013034d83014d0aeca9 [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 Hinesd5f9d6c2010-12-15 16:11:29 -0800172// This class visits a compound statement and inserts the StmtList containing
Stephen Hines4464d822010-11-11 16:45:08 -0800173// destructors in proper locations. This includes inserting them before any
174// 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
201 // The list of destructors to execute for this scope.
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -0800202 std::list<clang::Stmt*> &mStmtList;
Stephen Hines292e00a2011-03-18 19:11:30 -0700203
204 // The stack of statements which should be replaced by a compound statement
205 // containing the new destructor calls followed by the original Stmt.
206 std::stack<clang::Stmt*> mReplaceStmtStack;
207
Stephen Hines4464d822010-11-11 16:45:08 -0800208 public:
Stephen Hines292e00a2011-03-18 19:11:30 -0700209 DestructorVisitor(clang::ASTContext &C,
210 clang::Stmt* OuterStmt,
211 std::list<clang::Stmt*> &StmtList);
212
213 // This code walks the collected list of Stmts to replace and actually does
214 // the replacement. It also finishes up by appending appropriate destructors
215 // to the current outermost CompoundStmt.
216 void InsertDestructors() {
217 clang::Stmt *S = NULL;
218 while (!mReplaceStmtStack.empty()) {
219 S = mReplaceStmtStack.top();
220 mReplaceStmtStack.pop();
221
222 mStmtList.push_back(S);
223 clang::CompoundStmt *CS =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700224 BuildCompoundStmt(mCtx, mStmtList, S->getLocEnd());
Stephen Hines292e00a2011-03-18 19:11:30 -0700225 mStmtList.pop_back();
226
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700227 RSASTReplace R(mCtx);
Stephen Hines292e00a2011-03-18 19:11:30 -0700228 R.ReplaceStmt(mOuterStmt, S, CS);
229 }
230 clang::CompoundStmt *CS = dyn_cast<clang::CompoundStmt>(mOuterStmt);
231 slangAssert(CS);
232 if (CS) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700233 AppendAfterStmt(mCtx, CS, NULL, mStmtList);
Stephen Hines292e00a2011-03-18 19:11:30 -0700234 }
235 }
236
Stephen Hines4464d822010-11-11 16:45:08 -0800237 void VisitStmt(clang::Stmt *S);
238 void VisitCompoundStmt(clang::CompoundStmt *CS);
Stephen Hines292e00a2011-03-18 19:11:30 -0700239
240 void VisitBreakStmt(clang::BreakStmt *BS);
241 void VisitCaseStmt(clang::CaseStmt *CS);
242 void VisitContinueStmt(clang::ContinueStmt *CS);
243 void VisitDefaultStmt(clang::DefaultStmt *DS);
244 void VisitDoStmt(clang::DoStmt *DS);
245 void VisitForStmt(clang::ForStmt *FS);
246 void VisitIfStmt(clang::IfStmt *IS);
247 void VisitReturnStmt(clang::ReturnStmt *RS);
248 void VisitSwitchCase(clang::SwitchCase *SC);
249 void VisitSwitchStmt(clang::SwitchStmt *SS);
250 void VisitWhileStmt(clang::WhileStmt *WS);
Stephen Hines4464d822010-11-11 16:45:08 -0800251};
252
253DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
Stephen Hines292e00a2011-03-18 19:11:30 -0700254 clang::Stmt *OuterStmt,
255 std::list<clang::Stmt*> &StmtList)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700256 : mCtx(C),
Stephen Hines292e00a2011-03-18 19:11:30 -0700257 mLoopDepth(0),
258 mSwitchDepth(0),
259 mOuterStmt(OuterStmt),
260 mStmtList(StmtList) {
Stephen Hines4464d822010-11-11 16:45:08 -0800261 return;
262}
263
264void DestructorVisitor::VisitStmt(clang::Stmt *S) {
265 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
266 I != E;
267 I++) {
268 if (clang::Stmt *Child = *I) {
269 Visit(Child);
270 }
271 }
272 return;
273}
274
Stephen Hines292e00a2011-03-18 19:11:30 -0700275void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
276 VisitStmt(CS);
277 return;
278}
279
280void DestructorVisitor::VisitBreakStmt(clang::BreakStmt *BS) {
281 VisitStmt(BS);
282 if ((mLoopDepth == 0) && (mSwitchDepth == 0)) {
283 mReplaceStmtStack.push(BS);
284 }
285 return;
286}
287
288void DestructorVisitor::VisitCaseStmt(clang::CaseStmt *CS) {
289 VisitStmt(CS);
290 return;
291}
292
293void DestructorVisitor::VisitContinueStmt(clang::ContinueStmt *CS) {
294 VisitStmt(CS);
295 if (mLoopDepth == 0) {
296 // Switch statements can have nested continues.
297 mReplaceStmtStack.push(CS);
298 }
299 return;
300}
301
302void DestructorVisitor::VisitDefaultStmt(clang::DefaultStmt *DS) {
303 VisitStmt(DS);
304 return;
305}
306
307void DestructorVisitor::VisitDoStmt(clang::DoStmt *DS) {
308 mLoopDepth++;
309 VisitStmt(DS);
310 mLoopDepth--;
311 return;
312}
313
314void DestructorVisitor::VisitForStmt(clang::ForStmt *FS) {
315 mLoopDepth++;
316 VisitStmt(FS);
317 mLoopDepth--;
318 return;
319}
320
321void DestructorVisitor::VisitIfStmt(clang::IfStmt *IS) {
322 VisitStmt(IS);
323 return;
324}
325
326void DestructorVisitor::VisitReturnStmt(clang::ReturnStmt *RS) {
327 mReplaceStmtStack.push(RS);
328 return;
329}
330
331void DestructorVisitor::VisitSwitchCase(clang::SwitchCase *SC) {
332 slangAssert(false && "Both case and default have specialized handlers");
333 VisitStmt(SC);
334 return;
335}
336
337void DestructorVisitor::VisitSwitchStmt(clang::SwitchStmt *SS) {
338 mSwitchDepth++;
339 VisitStmt(SS);
340 mSwitchDepth--;
341 return;
342}
343
344void DestructorVisitor::VisitWhileStmt(clang::WhileStmt *WS) {
345 mLoopDepth++;
346 VisitStmt(WS);
347 mLoopDepth--;
348 return;
349}
350
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800351clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
352 clang::Expr *RefRSVar,
353 clang::SourceLocation Loc) {
354 slangAssert(RefRSVar);
355 const clang::Type *T = RefRSVar->getType().getTypePtr();
356 slangAssert(!T->isArrayType() &&
357 "Should not be destroying arrays with this function");
Stephen Hines03981a32010-12-14 19:45:49 -0800358
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800359 clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
360 slangAssert((ClearObjectFD != NULL) &&
361 "rsClearObject doesn't cover all RS object types");
362
363 clang::QualType ClearObjectFDType = ClearObjectFD->getType();
364 clang::QualType ClearObjectFDArgType =
365 ClearObjectFD->getParamDecl(0)->getOriginalType();
366
367 // Example destructor for "rs_font localFont;"
368 //
369 // (CallExpr 'void'
370 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
371 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
372 // (UnaryOperator 'rs_font *' prefix '&'
373 // (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
374
375 // Get address of targeted RS object
376 clang::Expr *AddrRefRSVar =
377 new(C) clang::UnaryOperator(RefRSVar,
378 clang::UO_AddrOf,
379 ClearObjectFDArgType,
Loganbe274822011-02-16 22:02:54 +0800380 clang::VK_RValue,
381 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800382 Loc);
383
384 clang::Expr *RefRSClearObjectFD =
385 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800386 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800387 ClearObjectFD,
388 ClearObjectFD->getLocation(),
Loganbe274822011-02-16 22:02:54 +0800389 ClearObjectFDType,
390 clang::VK_RValue,
391 NULL);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800392
393 clang::Expr *RSClearObjectFP =
394 clang::ImplicitCastExpr::Create(C,
395 C.getPointerType(ClearObjectFDType),
396 clang::CK_FunctionToPointerDecay,
397 RefRSClearObjectFD,
398 NULL,
399 clang::VK_RValue);
400
401 clang::CallExpr *RSClearObjectCall =
402 new(C) clang::CallExpr(C,
403 RSClearObjectFP,
404 &AddrRefRSVar,
405 1,
406 ClearObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800407 clang::VK_RValue,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800408 Loc);
409
410 return RSClearObjectCall;
411}
412
413static int ArrayDim(const clang::Type *T) {
Stephen Hines03981a32010-12-14 19:45:49 -0800414 if (!T || !T->isArrayType()) {
415 return 0;
416 }
417
418 const clang::ConstantArrayType *CAT =
419 static_cast<const clang::ConstantArrayType *>(T);
Stephen Hines9d2c0fa2011-01-05 14:55:18 -0800420 return static_cast<int>(CAT->getSize().getSExtValue());
Stephen Hines03981a32010-12-14 19:45:49 -0800421}
422
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800423static clang::Stmt *ClearStructRSObject(
424 clang::ASTContext &C,
425 clang::DeclContext *DC,
426 clang::Expr *RefRSStruct,
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700427 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800428 clang::SourceLocation Loc);
429
430static clang::Stmt *ClearArrayRSObject(
431 clang::ASTContext &C,
432 clang::DeclContext *DC,
433 clang::Expr *RefRSArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700434 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800435 clang::SourceLocation Loc) {
436 const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
437 slangAssert(BaseType->isArrayType());
438
439 int NumArrayElements = ArrayDim(BaseType);
440 // Actually extract out the base RS object type for use later
441 BaseType = BaseType->getArrayElementTypeNoTypeQual();
Stephen Hines03981a32010-12-14 19:45:49 -0800442
443 clang::Stmt *StmtArray[2] = {NULL};
444 int StmtCtr = 0;
445
Stephen Hines03981a32010-12-14 19:45:49 -0800446 if (NumArrayElements <= 0) {
447 return NULL;
448 }
449
450 // Example destructor loop for "rs_font fontArr[10];"
451 //
452 // (CompoundStmt
453 // (DeclStmt "int rsIntIter")
454 // (ForStmt
455 // (BinaryOperator 'int' '='
456 // (DeclRefExpr 'int' Var='rsIntIter')
457 // (IntegerLiteral 'int' 0))
458 // (BinaryOperator 'int' '<'
459 // (DeclRefExpr 'int' Var='rsIntIter')
460 // (IntegerLiteral 'int' 10)
461 // NULL << CondVar >>
462 // (UnaryOperator 'int' postfix '++'
463 // (DeclRefExpr 'int' Var='rsIntIter'))
464 // (CallExpr 'void'
465 // (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
466 // (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
467 // (UnaryOperator 'rs_font *' prefix '&'
468 // (ArraySubscriptExpr 'rs_font':'rs_font'
469 // (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
470 // (DeclRefExpr 'rs_font [10]' Var='fontArr'))
471 // (DeclRefExpr 'int' Var='rsIntIter')))))))
472
473 // Create helper variable for iterating through elements
474 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
475 clang::VarDecl *IIVD =
476 clang::VarDecl::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800477 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700478 StartLoc,
Stephen Hines03981a32010-12-14 19:45:49 -0800479 Loc,
480 &II,
481 C.IntTy,
482 C.getTrivialTypeSourceInfo(C.IntTy),
483 clang::SC_None,
484 clang::SC_None);
485 clang::Decl *IID = (clang::Decl *)IIVD;
486
487 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
488 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
489
490 // Form the actual destructor loop
491 // for (Init; Cond; Inc)
492 // RSClearObjectCall;
493
494 // Init -> "rsIntIter = 0"
495 clang::DeclRefExpr *RefrsIntIter =
496 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800497 clang::NestedNameSpecifierLoc(),
Stephen Hines03981a32010-12-14 19:45:49 -0800498 IIVD,
499 Loc,
Loganbe274822011-02-16 22:02:54 +0800500 C.IntTy,
501 clang::VK_RValue,
502 NULL);
Stephen Hines03981a32010-12-14 19:45:49 -0800503
504 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
505 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
506
507 clang::BinaryOperator *Init =
508 new(C) clang::BinaryOperator(RefrsIntIter,
509 Int0,
510 clang::BO_Assign,
511 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800512 clang::VK_RValue,
513 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800514 Loc);
515
516 // Cond -> "rsIntIter < NumArrayElements"
517 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
518 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
519
520 clang::BinaryOperator *Cond =
521 new(C) clang::BinaryOperator(RefrsIntIter,
522 NumArrayElementsExpr,
523 clang::BO_LT,
524 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800525 clang::VK_RValue,
526 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800527 Loc);
528
529 // Inc -> "rsIntIter++"
530 clang::UnaryOperator *Inc =
531 new(C) clang::UnaryOperator(RefrsIntIter,
532 clang::UO_PostInc,
533 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800534 clang::VK_RValue,
535 clang::OK_Ordinary,
Stephen Hines03981a32010-12-14 19:45:49 -0800536 Loc);
537
538 // Body -> "rsClearObject(&VD[rsIntIter]);"
539 // Destructor loop operates on individual array elements
Stephen Hines03981a32010-12-14 19:45:49 -0800540
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800541 clang::Expr *RefRSArrPtr =
Stephen Hines03981a32010-12-14 19:45:49 -0800542 clang::ImplicitCastExpr::Create(C,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800543 C.getPointerType(BaseType->getCanonicalTypeInternal()),
Stephen Hines03981a32010-12-14 19:45:49 -0800544 clang::CK_ArrayToPointerDecay,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800545 RefRSArr,
Stephen Hines03981a32010-12-14 19:45:49 -0800546 NULL,
547 clang::VK_RValue);
548
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800549 clang::Expr *RefRSArrPtrSubscript =
550 new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
Stephen Hines03981a32010-12-14 19:45:49 -0800551 RefrsIntIter,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800552 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800553 clang::VK_RValue,
554 clang::OK_Ordinary,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800555 Loc);
Stephen Hines03981a32010-12-14 19:45:49 -0800556
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800557 RSExportPrimitiveType::DataType DT =
558 RSExportPrimitiveType::GetRSSpecificType(BaseType);
Stephen Hines03981a32010-12-14 19:45:49 -0800559
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800560 clang::Stmt *RSClearObjectCall = NULL;
561 if (BaseType->isArrayType()) {
562 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700563 ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800564 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
565 RSClearObjectCall =
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700566 ClearStructRSObject(C, DC, RefRSArrPtrSubscript, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800567 } else {
568 RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
569 }
Stephen Hines03981a32010-12-14 19:45:49 -0800570
571 clang::ForStmt *DestructorLoop =
572 new(C) clang::ForStmt(C,
573 Init,
574 Cond,
575 NULL, // no condVar
576 Inc,
577 RSClearObjectCall,
578 Loc,
579 Loc,
580 Loc);
581
582 StmtArray[StmtCtr++] = DestructorLoop;
Stephen Hines6e6578a2011-02-07 18:05:48 -0800583 slangAssert(StmtCtr == 2);
Stephen Hines03981a32010-12-14 19:45:49 -0800584
585 clang::CompoundStmt *CS =
586 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
587
588 return CS;
589}
590
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700591static unsigned CountRSObjectTypes(clang::ASTContext &C,
592 const clang::Type *T,
593 clang::SourceLocation Loc) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800594 slangAssert(T);
595 unsigned RSObjectCount = 0;
596
597 if (T->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700598 return CountRSObjectTypes(C, T->getArrayElementTypeNoTypeQual(), Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800599 }
600
601 RSExportPrimitiveType::DataType DT =
602 RSExportPrimitiveType::GetRSSpecificType(T);
603 if (DT != RSExportPrimitiveType::DataTypeUnknown) {
604 return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
605 }
606
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700607 if (T->isUnionType()) {
608 clang::RecordDecl *RD = T->getAsUnionType()->getDecl();
609 RD = RD->getDefinition();
610 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
611 FE = RD->field_end();
612 FI != FE;
613 FI++) {
614 const clang::FieldDecl *FD = *FI;
615 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
616 if (CountRSObjectTypes(C, FT, Loc)) {
617 clang::Diagnostic &Diags = C.getDiagnostics();
618 // RS objects within unions are forbidden.
619 Diags.Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
620 Diags.getCustomDiagID(clang::Diagnostic::Error,
621 "unions containing RS object types cannot be copied"));
622 return 0;
623 }
624 }
625 }
626
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800627 if (!T->isStructureType()) {
628 return 0;
629 }
630
631 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
632 RD = RD->getDefinition();
633 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
634 FE = RD->field_end();
635 FI != FE;
636 FI++) {
637 const clang::FieldDecl *FD = *FI;
638 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700639 if (CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800640 // Sub-structs should only count once (as should arrays, etc.)
641 RSObjectCount++;
642 }
643 }
644
645 return RSObjectCount;
646}
647
648static clang::Stmt *ClearStructRSObject(
649 clang::ASTContext &C,
650 clang::DeclContext *DC,
651 clang::Expr *RefRSStruct,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700652 clang::SourceLocation StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800653 clang::SourceLocation Loc) {
654 const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
655
656 slangAssert(!BaseType->isArrayType());
657
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800658 // Structs should show up as unknown primitive types
Alex Sakhartchouk9be93602011-03-17 17:03:36 -0700659 slangAssert(RSExportPrimitiveType::GetRSSpecificType(BaseType) ==
660 RSExportPrimitiveType::DataTypeUnknown);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800661
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700662 unsigned FieldsToDestroy = CountRSObjectTypes(C, BaseType, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800663
664 unsigned StmtCount = 0;
665 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800666 for (unsigned i = 0; i < FieldsToDestroy; i++) {
667 StmtArray[i] = NULL;
668 }
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800669
670 // Populate StmtArray by creating a destructor for each RS object field
671 clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
672 RD = RD->getDefinition();
673 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
674 FE = RD->field_end();
675 FI != FE;
676 FI++) {
677 // We just look through all field declarations to see if we find a
678 // declaration for an RS object type (or an array of one).
679 bool IsArrayType = false;
680 clang::FieldDecl *FD = *FI;
681 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
682 const clang::Type *OrigType = FT;
683 while (FT && FT->isArrayType()) {
684 FT = FT->getArrayElementTypeNoTypeQual();
685 IsArrayType = true;
686 }
687
688 if (RSExportPrimitiveType::IsRSObjectType(FT)) {
689 clang::DeclAccessPair FoundDecl =
690 clang::DeclAccessPair::make(FD, clang::AS_none);
691 clang::MemberExpr *RSObjectMember =
692 clang::MemberExpr::Create(C,
693 RefRSStruct,
694 false,
Loganbe274822011-02-16 22:02:54 +0800695 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800696 FD,
697 FoundDecl,
698 clang::DeclarationNameInfo(),
699 NULL,
Loganbe274822011-02-16 22:02:54 +0800700 OrigType->getCanonicalTypeInternal(),
701 clang::VK_RValue,
702 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800703
704 slangAssert(StmtCount < FieldsToDestroy);
705
706 if (IsArrayType) {
707 StmtArray[StmtCount++] = ClearArrayRSObject(C,
708 DC,
709 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700710 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800711 Loc);
712 } else {
713 StmtArray[StmtCount++] = ClearSingleRSObject(C,
714 RSObjectMember,
715 Loc);
716 }
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700717 } else if (FT->isStructureType() && CountRSObjectTypes(C, FT, Loc)) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800718 // In this case, we have a nested struct. We may not end up filling all
719 // of the spaces in StmtArray (sub-structs should handle themselves
720 // with separate compound statements).
721 clang::DeclAccessPair FoundDecl =
722 clang::DeclAccessPair::make(FD, clang::AS_none);
723 clang::MemberExpr *RSObjectMember =
724 clang::MemberExpr::Create(C,
725 RefRSStruct,
726 false,
Loganbe274822011-02-16 22:02:54 +0800727 clang::NestedNameSpecifierLoc(),
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800728 FD,
729 FoundDecl,
730 clang::DeclarationNameInfo(),
731 NULL,
Loganbe274822011-02-16 22:02:54 +0800732 OrigType->getCanonicalTypeInternal(),
733 clang::VK_RValue,
734 clang::OK_Ordinary);
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800735
736 if (IsArrayType) {
737 StmtArray[StmtCount++] = ClearArrayRSObject(C,
738 DC,
739 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700740 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800741 Loc);
742 } else {
743 StmtArray[StmtCount++] = ClearStructRSObject(C,
744 DC,
745 RSObjectMember,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700746 StartLoc,
Stephen Hinesf2174cf2011-02-09 23:21:37 -0800747 Loc);
748 }
749 }
750 }
751
752 slangAssert(StmtCount > 0);
753 clang::CompoundStmt *CS =
754 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
755
756 delete [] StmtArray;
757
758 return CS;
759}
760
Stephen Hines2bb67db2011-02-11 01:36:40 -0800761static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800762 clang::Expr *DstExpr,
763 clang::Expr *SrcExpr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700764 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800765 clang::SourceLocation Loc) {
766 const clang::Type *T = DstExpr->getType().getTypePtr();
767 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
Stephen Hines6e6578a2011-02-07 18:05:48 -0800768 slangAssert((SetObjectFD != NULL) &&
769 "rsSetObject doesn't cover all RS object types");
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800770
771 clang::QualType SetObjectFDType = SetObjectFD->getType();
772 clang::QualType SetObjectFDArgType[2];
773 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
774 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
775
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800776 clang::Expr *RefRSSetObjectFD =
777 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800778 clang::NestedNameSpecifierLoc(),
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800779 SetObjectFD,
780 Loc,
Loganbe274822011-02-16 22:02:54 +0800781 SetObjectFDType,
782 clang::VK_RValue,
783 NULL);
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800784
785 clang::Expr *RSSetObjectFP =
786 clang::ImplicitCastExpr::Create(C,
787 C.getPointerType(SetObjectFDType),
788 clang::CK_FunctionToPointerDecay,
789 RefRSSetObjectFD,
790 NULL,
791 clang::VK_RValue);
792
793 clang::Expr *ArgList[2];
Stephen Hines2bb67db2011-02-11 01:36:40 -0800794 ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800795 clang::UO_AddrOf,
796 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +0800797 clang::VK_RValue,
798 clang::OK_Ordinary,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800799 Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800800 ArgList[1] = SrcExpr;
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800801
802 clang::CallExpr *RSSetObjectCall =
803 new(C) clang::CallExpr(C,
804 RSSetObjectFP,
805 ArgList,
806 2,
807 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +0800808 clang::VK_RValue,
Stephen Hinesc202d2d2011-01-26 11:57:57 -0800809 Loc);
810
Stephen Hines2bb67db2011-02-11 01:36:40 -0800811 return RSSetObjectCall;
812}
Stephen Hinese79fb5e2011-02-01 19:12:43 -0800813
Stephen Hines2bb67db2011-02-11 01:36:40 -0800814static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800815 clang::Expr *LHS,
816 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700817 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800818 clang::SourceLocation Loc);
819
820static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800821 clang::Expr *DstArr,
822 clang::Expr *SrcArr,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700823 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800824 clang::SourceLocation Loc) {
825 clang::DeclContext *DC = NULL;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800826 const clang::Type *BaseType = DstArr->getType().getTypePtr();
827 slangAssert(BaseType->isArrayType());
828
829 int NumArrayElements = ArrayDim(BaseType);
830 // Actually extract out the base RS object type for use later
831 BaseType = BaseType->getArrayElementTypeNoTypeQual();
832
833 clang::Stmt *StmtArray[2] = {NULL};
834 int StmtCtr = 0;
835
836 if (NumArrayElements <= 0) {
837 return NULL;
838 }
839
840 // Create helper variable for iterating through elements
841 clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
842 clang::VarDecl *IIVD =
843 clang::VarDecl::Create(C,
844 DC,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700845 StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800846 Loc,
847 &II,
848 C.IntTy,
849 C.getTrivialTypeSourceInfo(C.IntTy),
850 clang::SC_None,
851 clang::SC_None);
852 clang::Decl *IID = (clang::Decl *)IIVD;
853
854 clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
855 StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
856
857 // Form the actual loop
858 // for (Init; Cond; Inc)
859 // RSSetObjectCall;
860
861 // Init -> "rsIntIter = 0"
862 clang::DeclRefExpr *RefrsIntIter =
863 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +0800864 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -0800865 IIVD,
866 Loc,
Loganbe274822011-02-16 22:02:54 +0800867 C.IntTy,
868 clang::VK_RValue,
869 NULL);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800870
871 clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
872 llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
873
874 clang::BinaryOperator *Init =
875 new(C) clang::BinaryOperator(RefrsIntIter,
876 Int0,
877 clang::BO_Assign,
878 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800879 clang::VK_RValue,
880 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800881 Loc);
882
883 // Cond -> "rsIntIter < NumArrayElements"
884 clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
885 llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
886
887 clang::BinaryOperator *Cond =
888 new(C) clang::BinaryOperator(RefrsIntIter,
889 NumArrayElementsExpr,
890 clang::BO_LT,
891 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800892 clang::VK_RValue,
893 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800894 Loc);
895
896 // Inc -> "rsIntIter++"
897 clang::UnaryOperator *Inc =
898 new(C) clang::UnaryOperator(RefrsIntIter,
899 clang::UO_PostInc,
900 C.IntTy,
Loganbe274822011-02-16 22:02:54 +0800901 clang::VK_RValue,
902 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800903 Loc);
904
905 // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
906 // Loop operates on individual array elements
907
908 clang::Expr *DstArrPtr =
909 clang::ImplicitCastExpr::Create(C,
910 C.getPointerType(BaseType->getCanonicalTypeInternal()),
911 clang::CK_ArrayToPointerDecay,
912 DstArr,
913 NULL,
914 clang::VK_RValue);
915
916 clang::Expr *DstArrPtrSubscript =
917 new(C) clang::ArraySubscriptExpr(DstArrPtr,
918 RefrsIntIter,
919 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800920 clang::VK_RValue,
921 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800922 Loc);
923
924 clang::Expr *SrcArrPtr =
925 clang::ImplicitCastExpr::Create(C,
926 C.getPointerType(BaseType->getCanonicalTypeInternal()),
927 clang::CK_ArrayToPointerDecay,
928 SrcArr,
929 NULL,
930 clang::VK_RValue);
931
932 clang::Expr *SrcArrPtrSubscript =
933 new(C) clang::ArraySubscriptExpr(SrcArrPtr,
934 RefrsIntIter,
935 BaseType->getCanonicalTypeInternal(),
Loganbe274822011-02-16 22:02:54 +0800936 clang::VK_RValue,
937 clang::OK_Ordinary,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800938 Loc);
939
940 RSExportPrimitiveType::DataType DT =
941 RSExportPrimitiveType::GetRSSpecificType(BaseType);
942
943 clang::Stmt *RSSetObjectCall = NULL;
944 if (BaseType->isArrayType()) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700945 RSSetObjectCall = CreateArrayRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700946 SrcArrPtrSubscript,
947 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800948 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700949 RSSetObjectCall = CreateStructRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700950 SrcArrPtrSubscript,
951 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800952 } else {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700953 RSSetObjectCall = CreateSingleRSSetObject(C, DstArrPtrSubscript,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700954 SrcArrPtrSubscript,
955 StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -0800956 }
957
958 clang::ForStmt *DestructorLoop =
959 new(C) clang::ForStmt(C,
960 Init,
961 Cond,
962 NULL, // no condVar
963 Inc,
964 RSSetObjectCall,
965 Loc,
966 Loc,
967 Loc);
968
969 StmtArray[StmtCtr++] = DestructorLoop;
970 slangAssert(StmtCtr == 2);
971
972 clang::CompoundStmt *CS =
973 new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
974
975 return CS;
976}
977
978static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800979 clang::Expr *LHS,
980 clang::Expr *RHS,
Shih-wei Liaocc887ba2011-04-19 18:36:20 -0700981 clang::SourceLocation StartLoc,
Stephen Hines2bb67db2011-02-11 01:36:40 -0800982 clang::SourceLocation Loc) {
Stephen Hines2bb67db2011-02-11 01:36:40 -0800983 clang::QualType QT = LHS->getType();
984 const clang::Type *T = QT.getTypePtr();
985 slangAssert(T->isStructureType());
986 slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
987
988 // Keep an extra slot for the original copy (memcpy)
Stephen Hinesd0b5edd2011-04-18 16:38:03 -0700989 unsigned FieldsToSet = CountRSObjectTypes(C, T, Loc) + 1;
Stephen Hines2bb67db2011-02-11 01:36:40 -0800990
991 unsigned StmtCount = 0;
992 clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
993 for (unsigned i = 0; i < FieldsToSet; i++) {
994 StmtArray[i] = NULL;
995 }
996
997 clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
998 RD = RD->getDefinition();
999 for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
1000 FE = RD->field_end();
1001 FI != FE;
1002 FI++) {
1003 bool IsArrayType = false;
1004 clang::FieldDecl *FD = *FI;
1005 const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
1006 const clang::Type *OrigType = FT;
1007
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001008 if (!CountRSObjectTypes(C, FT, Loc)) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001009 // Skip to next if we don't have any viable RS object types
1010 continue;
1011 }
1012
1013 clang::DeclAccessPair FoundDecl =
1014 clang::DeclAccessPair::make(FD, clang::AS_none);
1015 clang::MemberExpr *DstMember =
1016 clang::MemberExpr::Create(C,
1017 LHS,
1018 false,
Loganbe274822011-02-16 22:02:54 +08001019 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001020 FD,
1021 FoundDecl,
1022 clang::DeclarationNameInfo(),
1023 NULL,
Loganbe274822011-02-16 22:02:54 +08001024 OrigType->getCanonicalTypeInternal(),
1025 clang::VK_RValue,
1026 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001027
1028 clang::MemberExpr *SrcMember =
1029 clang::MemberExpr::Create(C,
1030 RHS,
1031 false,
Loganbe274822011-02-16 22:02:54 +08001032 clang::NestedNameSpecifierLoc(),
Stephen Hines2bb67db2011-02-11 01:36:40 -08001033 FD,
1034 FoundDecl,
1035 clang::DeclarationNameInfo(),
1036 NULL,
Loganbe274822011-02-16 22:02:54 +08001037 OrigType->getCanonicalTypeInternal(),
1038 clang::VK_RValue,
1039 clang::OK_Ordinary);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001040
1041 if (FT->isArrayType()) {
1042 FT = FT->getArrayElementTypeNoTypeQual();
1043 IsArrayType = true;
1044 }
1045
1046 RSExportPrimitiveType::DataType DT =
1047 RSExportPrimitiveType::GetRSSpecificType(FT);
1048
1049 if (IsArrayType) {
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001050 clang::Diagnostic &Diags = C.getDiagnostics();
1051 Diags.Report(clang::FullSourceLoc(Loc, C.getSourceManager()),
1052 Diags.getCustomDiagID(clang::Diagnostic::Error,
Stephen Hines832429f2011-02-25 16:05:37 -08001053 "Arrays of RS object types within structures cannot be copied"));
Stephen Hines2bb67db2011-02-11 01:36:40 -08001054 // TODO(srhines): Support setting arrays of RS objects
1055 // StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001056 // CreateArrayRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001057 } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
1058 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001059 CreateStructRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001060 } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
1061 StmtArray[StmtCount++] =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001062 CreateSingleRSSetObject(C, DstMember, SrcMember, StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001063 } else {
1064 slangAssert(false);
1065 }
1066 }
1067
1068 slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
1069
1070 // We still need to actually do the overall struct copy. For simplicity,
1071 // we just do a straight-up assignment (which will still preserve all
1072 // the proper RS object reference counts).
1073 clang::BinaryOperator *CopyStruct =
Loganbe274822011-02-16 22:02:54 +08001074 new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT,
1075 clang::VK_RValue, clang::OK_Ordinary, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001076 StmtArray[StmtCount++] = CopyStruct;
1077
1078 clang::CompoundStmt *CS =
1079 new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
1080
1081 delete [] StmtArray;
1082
1083 return CS;
1084}
1085
1086} // namespace
1087
1088void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001089 clang::BinaryOperator *AS) {
Stephen Hines2bb67db2011-02-11 01:36:40 -08001090
1091 clang::QualType QT = AS->getType();
1092
1093 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1094 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1095
Stephen Hines832429f2011-02-25 16:05:37 -08001096 clang::SourceLocation Loc = AS->getExprLoc();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001097 clang::SourceLocation StartLoc = AS->getExprLoc();
Stephen Hines2bb67db2011-02-11 01:36:40 -08001098 clang::Stmt *UpdatedStmt = NULL;
1099
1100 if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
1101 // By definition, this is a struct assignment if we get here
1102 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001103 CreateStructRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001104 } else {
1105 UpdatedStmt =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001106 CreateSingleRSSetObject(C, AS->getLHS(), AS->getRHS(), StartLoc, Loc);
Stephen Hines2bb67db2011-02-11 01:36:40 -08001107 }
1108
Stephen Hines292e00a2011-03-18 19:11:30 -07001109 RSASTReplace R(C);
1110 R.ReplaceStmt(mCS, AS, UpdatedStmt);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001111 return;
1112}
1113
1114void RSObjectRefCount::Scope::AppendRSObjectInit(
1115 clang::VarDecl *VD,
1116 clang::DeclStmt *DS,
1117 RSExportPrimitiveType::DataType DT,
1118 clang::Expr *InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001119 slangAssert(VD);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001120
1121 if (!InitExpr) {
1122 return;
1123 }
1124
Stephen Hinesa0611e62011-02-11 16:35:47 -08001125 clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
1126 RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
1127 clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
1128 RSExportPrimitiveType::DataTypeRSFont)->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001129 clang::SourceLocation StartLoc = RSObjectRefCount::GetRSSetObjectFD(
1130 RSExportPrimitiveType::DataTypeRSFont)->getInnerLocStart();
Stephen Hinesa0611e62011-02-11 16:35:47 -08001131
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001132 if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
Stephen Hinesa0611e62011-02-11 16:35:47 -08001133 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1134 clang::DeclRefExpr *RefRSVar =
1135 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001136 clang::NestedNameSpecifierLoc(),
Stephen Hinesa0611e62011-02-11 16:35:47 -08001137 VD,
1138 Loc,
Loganbe274822011-02-16 22:02:54 +08001139 T->getCanonicalTypeInternal(),
1140 clang::VK_RValue,
1141 NULL);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001142
1143 clang::Stmt *RSSetObjectOps =
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001144 CreateStructRSSetObject(C, RefRSVar, InitExpr, StartLoc, Loc);
Stephen Hinesa0611e62011-02-11 16:35:47 -08001145
Stephen Hines292e00a2011-03-18 19:11:30 -07001146 std::list<clang::Stmt*> StmtList;
1147 StmtList.push_back(RSSetObjectOps);
1148 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001149 return;
1150 }
1151
1152 clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
Stephen Hines6e6578a2011-02-07 18:05:48 -08001153 slangAssert((SetObjectFD != NULL) &&
1154 "rsSetObject doesn't cover all RS object types");
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001155
1156 clang::QualType SetObjectFDType = SetObjectFD->getType();
1157 clang::QualType SetObjectFDArgType[2];
1158 SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
1159 SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
1160
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001161 clang::Expr *RefRSSetObjectFD =
1162 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001163 clang::NestedNameSpecifierLoc(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001164 SetObjectFD,
1165 Loc,
Loganbe274822011-02-16 22:02:54 +08001166 SetObjectFDType,
1167 clang::VK_RValue,
1168 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001169
1170 clang::Expr *RSSetObjectFP =
1171 clang::ImplicitCastExpr::Create(C,
1172 C.getPointerType(SetObjectFDType),
1173 clang::CK_FunctionToPointerDecay,
1174 RefRSSetObjectFD,
1175 NULL,
1176 clang::VK_RValue);
1177
1178 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1179 clang::DeclRefExpr *RefRSVar =
1180 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001181 clang::NestedNameSpecifierLoc(),
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001182 VD,
1183 Loc,
Loganbe274822011-02-16 22:02:54 +08001184 T->getCanonicalTypeInternal(),
1185 clang::VK_RValue,
1186 NULL);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001187
1188 clang::Expr *ArgList[2];
1189 ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1190 clang::UO_AddrOf,
1191 SetObjectFDArgType[0],
Loganbe274822011-02-16 22:02:54 +08001192 clang::VK_RValue,
1193 clang::OK_Ordinary,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001194 Loc);
1195 ArgList[1] = InitExpr;
1196
1197 clang::CallExpr *RSSetObjectCall =
1198 new(C) clang::CallExpr(C,
1199 RSSetObjectFP,
1200 ArgList,
1201 2,
1202 SetObjectFD->getCallResultType(),
Loganbe274822011-02-16 22:02:54 +08001203 clang::VK_RValue,
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001204 Loc);
1205
Stephen Hines292e00a2011-03-18 19:11:30 -07001206 std::list<clang::Stmt*> StmtList;
1207 StmtList.push_back(RSSetObjectCall);
1208 AppendAfterStmt(C, mCS, DS, StmtList);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001209
1210 return;
1211}
1212
Stephen Hines1bdd4972010-11-08 17:35:08 -08001213void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001214 std::list<clang::Stmt*> RSClearObjectCalls;
Stephen Hines1bdd4972010-11-08 17:35:08 -08001215 for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1216 E = mRSO.end();
1217 I != E;
1218 I++) {
Stephen Hinesa858cb62011-01-17 12:17:51 -08001219 clang::Stmt *S = ClearRSObject(*I);
1220 if (S) {
1221 RSClearObjectCalls.push_back(S);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001222 }
1223 }
1224 if (RSClearObjectCalls.size() > 0) {
Stephen Hines292e00a2011-03-18 19:11:30 -07001225 DestructorVisitor DV((*mRSO.begin())->getASTContext(),
1226 mCS,
1227 RSClearObjectCalls);
Stephen Hines4464d822010-11-11 16:45:08 -08001228 DV.Visit(mCS);
Stephen Hines292e00a2011-03-18 19:11:30 -07001229 DV.InsertDestructors();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001230 }
1231 return;
1232}
1233
Stephen Hinesd5f9d6c2010-12-15 16:11:29 -08001234clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001235 slangAssert(VD);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001236 clang::ASTContext &C = VD->getASTContext();
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001237 clang::DeclContext *DC = VD->getDeclContext();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001238 clang::SourceLocation Loc = VD->getLocation();
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001239 clang::SourceLocation StartLoc = VD->getInnerLocStart();
Stephen Hines1bdd4972010-11-08 17:35:08 -08001240 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines03981a32010-12-14 19:45:49 -08001241
Stephen Hines1bdd4972010-11-08 17:35:08 -08001242 // Reference expr to target RS object variable
1243 clang::DeclRefExpr *RefRSVar =
1244 clang::DeclRefExpr::Create(C,
Loganbe274822011-02-16 22:02:54 +08001245 clang::NestedNameSpecifierLoc(),
Stephen Hines1bdd4972010-11-08 17:35:08 -08001246 VD,
1247 Loc,
Loganbe274822011-02-16 22:02:54 +08001248 T->getCanonicalTypeInternal(),
1249 clang::VK_RValue,
1250 NULL);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001251
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001252 if (T->isArrayType()) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001253 return ClearArrayRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001254 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001255
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001256 RSExportPrimitiveType::DataType DT =
1257 RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001258
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001259 if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1260 DT == RSExportPrimitiveType::DataTypeIsStruct) {
Shih-wei Liaocc887ba2011-04-19 18:36:20 -07001261 return ClearStructRSObject(C, DC, RefRSVar, StartLoc, Loc);
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001262 }
Stephen Hines1bdd4972010-11-08 17:35:08 -08001263
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001264 slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1265 "Should be RS object");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001266
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001267 return ClearSingleRSObject(C, RefRSVar, Loc);
Stephen Hines1bdd4972010-11-08 17:35:08 -08001268}
1269
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001270bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1271 RSExportPrimitiveType::DataType *DT,
1272 clang::Expr **InitExpr) {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001273 slangAssert(VD && DT && InitExpr);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001274 const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
Stephen Hines2d095042010-11-12 18:13:56 -08001275
1276 // Loop through array types to get to base type
1277 while (T && T->isArrayType()) {
1278 T = T->getArrayElementTypeNoTypeQual();
Stephen Hines2d095042010-11-12 18:13:56 -08001279 }
1280
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001281 bool DataTypeIsStructWithRSObject = false;
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001282 *DT = RSExportPrimitiveType::GetRSSpecificType(T);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001283
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001284 if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001285 if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1286 *DT = RSExportPrimitiveType::DataTypeIsStruct;
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001287 DataTypeIsStructWithRSObject = true;
Stephen Hinesfeaca062011-02-04 14:08:13 -08001288 } else {
1289 return false;
1290 }
Stephen Hines2d095042010-11-12 18:13:56 -08001291 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001292
Stephen Hinesf2174cf2011-02-09 23:21:37 -08001293 bool DataTypeIsRSObject = false;
1294 if (DataTypeIsStructWithRSObject) {
1295 DataTypeIsRSObject = true;
1296 } else {
1297 DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1298 }
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001299 *InitExpr = VD->getInit();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001300
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001301 if (!DataTypeIsRSObject && *InitExpr) {
1302 // If we already have an initializer for a matrix type, we are done.
1303 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001304 }
1305
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001306 clang::Expr *ZeroInitializer =
1307 CreateZeroInitializerForRSSpecificType(*DT,
1308 VD->getASTContext(),
1309 VD->getLocation());
1310
1311 if (ZeroInitializer) {
1312 ZeroInitializer->setType(T->getCanonicalTypeInternal());
1313 VD->setInit(ZeroInitializer);
1314 }
1315
1316 return DataTypeIsRSObject;
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001317}
1318
1319clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1320 RSExportPrimitiveType::DataType DT,
1321 clang::ASTContext &C,
1322 const clang::SourceLocation &Loc) {
1323 clang::Expr *Res = NULL;
1324 switch (DT) {
Stephen Hinesfeaca062011-02-04 14:08:13 -08001325 case RSExportPrimitiveType::DataTypeIsStruct:
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001326 case RSExportPrimitiveType::DataTypeRSElement:
1327 case RSExportPrimitiveType::DataTypeRSType:
1328 case RSExportPrimitiveType::DataTypeRSAllocation:
1329 case RSExportPrimitiveType::DataTypeRSSampler:
1330 case RSExportPrimitiveType::DataTypeRSScript:
1331 case RSExportPrimitiveType::DataTypeRSMesh:
1332 case RSExportPrimitiveType::DataTypeRSProgramFragment:
1333 case RSExportPrimitiveType::DataTypeRSProgramVertex:
1334 case RSExportPrimitiveType::DataTypeRSProgramRaster:
1335 case RSExportPrimitiveType::DataTypeRSProgramStore:
1336 case RSExportPrimitiveType::DataTypeRSFont: {
1337 // (ImplicitCastExpr 'nullptr_t'
1338 // (IntegerLiteral 0)))
1339 llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1340 clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1341 clang::Expr *CastToNull =
1342 clang::ImplicitCastExpr::Create(C,
1343 C.NullPtrTy,
1344 clang::CK_IntegralToPointer,
1345 Int0,
1346 NULL,
1347 clang::VK_RValue);
1348
Stephen Hinese639eb52010-11-08 19:27:20 -08001349 Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001350 break;
1351 }
1352 case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1353 case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1354 case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1355 // RS matrix is not completely an RS object. They hold data by themselves.
1356 // (InitListExpr rs_matrix2x2
1357 // (InitListExpr float[4]
1358 // (FloatingLiteral 0)
1359 // (FloatingLiteral 0)
1360 // (FloatingLiteral 0)
1361 // (FloatingLiteral 0)))
1362 clang::QualType FloatTy = C.FloatTy;
1363 // Constructor sets value to 0.0f by default
1364 llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1365 clang::FloatingLiteral *Float0Val =
1366 clang::FloatingLiteral::Create(C,
1367 Val,
1368 /* isExact = */true,
1369 FloatTy,
1370 Loc);
1371
1372 unsigned N = 0;
1373 if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1374 N = 2;
1375 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1376 N = 3;
1377 else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1378 N = 4;
1379
1380 // Directly allocate 16 elements instead of dynamically allocate N*N
1381 clang::Expr *InitVals[16];
1382 for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1383 InitVals[i] = Float0Val;
1384 clang::Expr *InitExpr =
Stephen Hinese639eb52010-11-08 19:27:20 -08001385 new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001386 InitExpr->setType(C.getConstantArrayType(FloatTy,
1387 llvm::APInt(32, 4),
1388 clang::ArrayType::Normal,
1389 /* EltTypeQuals = */0));
1390
Stephen Hinese639eb52010-11-08 19:27:20 -08001391 Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001392 break;
1393 }
1394 case RSExportPrimitiveType::DataTypeUnknown:
1395 case RSExportPrimitiveType::DataTypeFloat16:
1396 case RSExportPrimitiveType::DataTypeFloat32:
1397 case RSExportPrimitiveType::DataTypeFloat64:
1398 case RSExportPrimitiveType::DataTypeSigned8:
1399 case RSExportPrimitiveType::DataTypeSigned16:
1400 case RSExportPrimitiveType::DataTypeSigned32:
1401 case RSExportPrimitiveType::DataTypeSigned64:
1402 case RSExportPrimitiveType::DataTypeUnsigned8:
1403 case RSExportPrimitiveType::DataTypeUnsigned16:
1404 case RSExportPrimitiveType::DataTypeUnsigned32:
1405 case RSExportPrimitiveType::DataTypeUnsigned64:
1406 case RSExportPrimitiveType::DataTypeBoolean:
1407 case RSExportPrimitiveType::DataTypeUnsigned565:
1408 case RSExportPrimitiveType::DataTypeUnsigned5551:
1409 case RSExportPrimitiveType::DataTypeUnsigned4444:
1410 case RSExportPrimitiveType::DataTypeMax: {
Stephen Hines6e6578a2011-02-07 18:05:48 -08001411 slangAssert(false && "Not RS object type!");
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001412 }
1413 // No default case will enable compiler detecting the missing cases
1414 }
1415
1416 return Res;
1417}
1418
1419void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1420 for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1421 I != E;
1422 I++) {
1423 clang::Decl *D = *I;
1424 if (D->getKind() == clang::Decl::Var) {
1425 clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001426 RSExportPrimitiveType::DataType DT =
1427 RSExportPrimitiveType::DataTypeUnknown;
1428 clang::Expr *InitExpr = NULL;
1429 if (InitializeRSObject(VD, &DT, &InitExpr)) {
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001430 getCurrentScope()->addRSObject(VD);
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001431 getCurrentScope()->AppendRSObjectInit(VD, DS, DT, InitExpr);
Stephen Hinese79fb5e2011-02-01 19:12:43 -08001432 }
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001433 }
1434 }
1435 return;
1436}
1437
1438void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1439 if (!CS->body_empty()) {
1440 // Push a new scope
1441 Scope *S = new Scope(CS);
1442 mScopeStack.push(S);
1443
1444 VisitStmt(CS);
1445
1446 // Destroy the scope
Stephen Hines6e6578a2011-02-07 18:05:48 -08001447 slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
Stephen Hines1bdd4972010-11-08 17:35:08 -08001448 S->InsertLocalVarDestructors();
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001449 mScopeStack.pop();
1450 delete S;
1451 }
1452 return;
1453}
1454
1455void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001456 clang::QualType QT = AS->getType();
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001457
Stephen Hinesd0b5edd2011-04-18 16:38:03 -07001458 if (CountRSObjectTypes(mCtx, QT.getTypePtr(), AS->getExprLoc())) {
1459 getCurrentScope()->ReplaceRSObjectAssignment(AS);
Stephen Hinesc202d2d2011-01-26 11:57:57 -08001460 }
1461
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001462 return;
1463}
1464
1465void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1466 for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1467 I != E;
1468 I++) {
1469 if (clang::Stmt *Child = *I) {
1470 Visit(Child);
1471 }
1472 }
1473 return;
1474}
1475
Stephen Hinese639eb52010-11-08 19:27:20 -08001476} // namespace slang