slang_rs_object_ref_count.cpp revision a0611e66bec148b176404cf6afe4c9ec9b960414
1/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_object_ref_count.h"
18
19#include <list>
20
21#include "clang/AST/DeclGroup.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/OperationKinds.h"
24#include "clang/AST/Stmt.h"
25#include "clang/AST/StmtVisitor.h"
26
27#include "slang_assert.h"
28#include "slang_rs.h"
29#include "slang_rs_export_type.h"
30
31namespace slang {
32
33clang::FunctionDecl *RSObjectRefCount::
34    RSSetObjectFD[RSExportPrimitiveType::LastRSObjectType -
35                  RSExportPrimitiveType::FirstRSObjectType + 1];
36clang::FunctionDecl *RSObjectRefCount::
37    RSClearObjectFD[RSExportPrimitiveType::LastRSObjectType -
38                    RSExportPrimitiveType::FirstRSObjectType + 1];
39
40void RSObjectRefCount::GetRSRefCountingFunctions(clang::ASTContext &C) {
41  for (unsigned i = 0;
42       i < (sizeof(RSClearObjectFD) / sizeof(clang::FunctionDecl*));
43       i++) {
44    RSSetObjectFD[i] = NULL;
45    RSClearObjectFD[i] = NULL;
46  }
47
48  clang::TranslationUnitDecl *TUDecl = C.getTranslationUnitDecl();
49
50  for (clang::DeclContext::decl_iterator I = TUDecl->decls_begin(),
51          E = TUDecl->decls_end(); I != E; I++) {
52    if ((I->getKind() >= clang::Decl::firstFunction) &&
53        (I->getKind() <= clang::Decl::lastFunction)) {
54      clang::FunctionDecl *FD = static_cast<clang::FunctionDecl*>(*I);
55
56      // points to RSSetObjectFD or RSClearObjectFD
57      clang::FunctionDecl **RSObjectFD;
58
59      if (FD->getName() == "rsSetObject") {
60        slangAssert((FD->getNumParams() == 2) &&
61                    "Invalid rsSetObject function prototype (# params)");
62        RSObjectFD = RSSetObjectFD;
63      } else if (FD->getName() == "rsClearObject") {
64        slangAssert((FD->getNumParams() == 1) &&
65                    "Invalid rsClearObject function prototype (# params)");
66        RSObjectFD = RSClearObjectFD;
67      } else {
68        continue;
69      }
70
71      const clang::ParmVarDecl *PVD = FD->getParamDecl(0);
72      clang::QualType PVT = PVD->getOriginalType();
73      // The first parameter must be a pointer like rs_allocation*
74      slangAssert(PVT->isPointerType() &&
75          "Invalid rs{Set,Clear}Object function prototype (pointer param)");
76
77      // The rs object type passed to the FD
78      clang::QualType RST = PVT->getPointeeType();
79      RSExportPrimitiveType::DataType DT =
80          RSExportPrimitiveType::GetRSSpecificType(RST.getTypePtr());
81      slangAssert(RSExportPrimitiveType::IsRSObjectType(DT)
82             && "must be RS object type");
83
84      RSObjectFD[(DT - RSExportPrimitiveType::FirstRSObjectType)] = FD;
85    }
86  }
87}
88
89namespace {
90
91static void AppendToCompoundStatement(clang::ASTContext& C,
92                                      clang::CompoundStmt *CS,
93                                      std::list<clang::Stmt*> &StmtList,
94                                      bool InsertAtEndOfBlock) {
95  // Destructor code will be inserted before any return statement.
96  // Any subsequent statements in the compound statement are then placed
97  // after our new code.
98  // TODO(srhines): This should also handle the case of goto/break/continue.
99
100  clang::CompoundStmt::body_iterator bI = CS->body_begin();
101
102  unsigned OldStmtCount = 0;
103  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
104    OldStmtCount++;
105  }
106
107  unsigned NewStmtCount = StmtList.size();
108
109  clang::Stmt **UpdatedStmtList;
110  UpdatedStmtList = new clang::Stmt*[OldStmtCount+NewStmtCount];
111
112  unsigned UpdatedStmtCount = 0;
113  bool FoundReturn = false;
114  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
115    if ((*bI)->getStmtClass() == clang::Stmt::ReturnStmtClass) {
116      FoundReturn = true;
117      break;
118    }
119    UpdatedStmtList[UpdatedStmtCount++] = *bI;
120  }
121
122  // Always insert before a return that we found, or if we are told
123  // to insert at the end of the block
124  if (FoundReturn || InsertAtEndOfBlock) {
125    std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
126    for (std::list<clang::Stmt*>::const_iterator I = StmtList.begin();
127         I != StmtList.end();
128         I++) {
129      UpdatedStmtList[UpdatedStmtCount++] = *I;
130    }
131  }
132
133  // Pick up anything left over after a return statement
134  for ( ; bI != CS->body_end(); bI++) {
135    UpdatedStmtList[UpdatedStmtCount++] = *bI;
136  }
137
138  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
139
140  delete [] UpdatedStmtList;
141
142  return;
143}
144
145static void AppendAfterStmt(clang::ASTContext& C,
146                            clang::CompoundStmt *CS,
147                            clang::Stmt *OldStmt,
148                            clang::Stmt *NewStmt) {
149  slangAssert(CS && OldStmt && NewStmt);
150  clang::CompoundStmt::body_iterator bI = CS->body_begin();
151  unsigned StmtCount = 1;  // Take into account new statement
152  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
153    StmtCount++;
154  }
155
156  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
157
158  unsigned UpdatedStmtCount = 0;
159  unsigned Once = 0;
160  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
161    UpdatedStmtList[UpdatedStmtCount++] = *bI;
162    if (*bI == OldStmt) {
163      Once++;
164      slangAssert(Once == 1);
165      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
166    }
167  }
168
169  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
170
171  delete [] UpdatedStmtList;
172
173  return;
174}
175
176static void ReplaceInCompoundStmt(clang::ASTContext& C,
177                                  clang::CompoundStmt *CS,
178                                  clang::Stmt* OldStmt,
179                                  clang::Stmt* NewStmt) {
180  clang::CompoundStmt::body_iterator bI = CS->body_begin();
181
182  unsigned StmtCount = 0;
183  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
184    StmtCount++;
185  }
186
187  clang::Stmt **UpdatedStmtList = new clang::Stmt*[StmtCount];
188
189  unsigned UpdatedStmtCount = 0;
190  for (bI = CS->body_begin(); bI != CS->body_end(); bI++) {
191    if (*bI == OldStmt) {
192      UpdatedStmtList[UpdatedStmtCount++] = NewStmt;
193    } else {
194      UpdatedStmtList[UpdatedStmtCount++] = *bI;
195    }
196  }
197
198  CS->setStmts(C, UpdatedStmtList, UpdatedStmtCount);
199
200  delete [] UpdatedStmtList;
201
202  return;
203}
204
205
206// This class visits a compound statement and inserts the StmtList containing
207// destructors in proper locations. This includes inserting them before any
208// return statement in any sub-block, at the end of the logical enclosing
209// scope (compound statement), and/or before any break/continue statement that
210// would resume outside the declared scope. We will not handle the case for
211// goto statements that leave a local scope.
212// TODO(srhines): Make this work properly for break/continue.
213class DestructorVisitor : public clang::StmtVisitor<DestructorVisitor> {
214 private:
215  clang::ASTContext &mC;
216  std::list<clang::Stmt*> &mStmtList;
217  bool mTopLevel;
218 public:
219  DestructorVisitor(clang::ASTContext &C, std::list<clang::Stmt*> &StmtList);
220  void VisitStmt(clang::Stmt *S);
221  void VisitCompoundStmt(clang::CompoundStmt *CS);
222};
223
224DestructorVisitor::DestructorVisitor(clang::ASTContext &C,
225                                     std::list<clang::Stmt*> &StmtList)
226  : mC(C),
227    mStmtList(StmtList),
228    mTopLevel(true) {
229  return;
230}
231
232void DestructorVisitor::VisitCompoundStmt(clang::CompoundStmt *CS) {
233  if (!CS->body_empty()) {
234    AppendToCompoundStatement(mC, CS, mStmtList, mTopLevel);
235    mTopLevel = false;
236    VisitStmt(CS);
237  }
238  return;
239}
240
241void DestructorVisitor::VisitStmt(clang::Stmt *S) {
242  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
243       I != E;
244       I++) {
245    if (clang::Stmt *Child = *I) {
246      Visit(Child);
247    }
248  }
249  return;
250}
251
252clang::Expr *ClearSingleRSObject(clang::ASTContext &C,
253                                 clang::Expr *RefRSVar,
254                                 clang::SourceLocation Loc) {
255  slangAssert(RefRSVar);
256  const clang::Type *T = RefRSVar->getType().getTypePtr();
257  slangAssert(!T->isArrayType() &&
258              "Should not be destroying arrays with this function");
259
260  clang::FunctionDecl *ClearObjectFD = RSObjectRefCount::GetRSClearObjectFD(T);
261  slangAssert((ClearObjectFD != NULL) &&
262              "rsClearObject doesn't cover all RS object types");
263
264  clang::QualType ClearObjectFDType = ClearObjectFD->getType();
265  clang::QualType ClearObjectFDArgType =
266      ClearObjectFD->getParamDecl(0)->getOriginalType();
267
268  // Example destructor for "rs_font localFont;"
269  //
270  // (CallExpr 'void'
271  //   (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
272  //     (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
273  //   (UnaryOperator 'rs_font *' prefix '&'
274  //     (DeclRefExpr 'rs_font':'rs_font' Var='localFont')))
275
276  // Get address of targeted RS object
277  clang::Expr *AddrRefRSVar =
278      new(C) clang::UnaryOperator(RefRSVar,
279                                  clang::UO_AddrOf,
280                                  ClearObjectFDArgType,
281                                  Loc);
282
283  clang::Expr *RefRSClearObjectFD =
284      clang::DeclRefExpr::Create(C,
285                                 NULL,
286                                 ClearObjectFD->getQualifierRange(),
287                                 ClearObjectFD,
288                                 ClearObjectFD->getLocation(),
289                                 ClearObjectFDType);
290
291  clang::Expr *RSClearObjectFP =
292      clang::ImplicitCastExpr::Create(C,
293                                      C.getPointerType(ClearObjectFDType),
294                                      clang::CK_FunctionToPointerDecay,
295                                      RefRSClearObjectFD,
296                                      NULL,
297                                      clang::VK_RValue);
298
299  clang::CallExpr *RSClearObjectCall =
300      new(C) clang::CallExpr(C,
301                             RSClearObjectFP,
302                             &AddrRefRSVar,
303                             1,
304                             ClearObjectFD->getCallResultType(),
305                             Loc);
306
307  return RSClearObjectCall;
308}
309
310static int ArrayDim(const clang::Type *T) {
311  if (!T || !T->isArrayType()) {
312    return 0;
313  }
314
315  const clang::ConstantArrayType *CAT =
316    static_cast<const clang::ConstantArrayType *>(T);
317  return static_cast<int>(CAT->getSize().getSExtValue());
318}
319
320static clang::Stmt *ClearStructRSObject(
321    clang::ASTContext &C,
322    clang::DeclContext *DC,
323    clang::Expr *RefRSStruct,
324    clang::SourceRange Range,
325    clang::SourceLocation Loc);
326
327static clang::Stmt *ClearArrayRSObject(
328    clang::ASTContext &C,
329    clang::DeclContext *DC,
330    clang::Expr *RefRSArr,
331    clang::SourceRange Range,
332    clang::SourceLocation Loc) {
333  const clang::Type *BaseType = RefRSArr->getType().getTypePtr();
334  slangAssert(BaseType->isArrayType());
335
336  int NumArrayElements = ArrayDim(BaseType);
337  // Actually extract out the base RS object type for use later
338  BaseType = BaseType->getArrayElementTypeNoTypeQual();
339
340  clang::Stmt *StmtArray[2] = {NULL};
341  int StmtCtr = 0;
342
343  if (NumArrayElements <= 0) {
344    return NULL;
345  }
346
347  // Example destructor loop for "rs_font fontArr[10];"
348  //
349  // (CompoundStmt
350  //   (DeclStmt "int rsIntIter")
351  //   (ForStmt
352  //     (BinaryOperator 'int' '='
353  //       (DeclRefExpr 'int' Var='rsIntIter')
354  //       (IntegerLiteral 'int' 0))
355  //     (BinaryOperator 'int' '<'
356  //       (DeclRefExpr 'int' Var='rsIntIter')
357  //       (IntegerLiteral 'int' 10)
358  //     NULL << CondVar >>
359  //     (UnaryOperator 'int' postfix '++'
360  //       (DeclRefExpr 'int' Var='rsIntIter'))
361  //     (CallExpr 'void'
362  //       (ImplicitCastExpr 'void (*)(rs_font *)' <FunctionToPointerDecay>
363  //         (DeclRefExpr 'void (rs_font *)' FunctionDecl='rsClearObject'))
364  //       (UnaryOperator 'rs_font *' prefix '&'
365  //         (ArraySubscriptExpr 'rs_font':'rs_font'
366  //           (ImplicitCastExpr 'rs_font *' <ArrayToPointerDecay>
367  //             (DeclRefExpr 'rs_font [10]' Var='fontArr'))
368  //           (DeclRefExpr 'int' Var='rsIntIter')))))))
369
370  // Create helper variable for iterating through elements
371  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
372  clang::VarDecl *IIVD =
373      clang::VarDecl::Create(C,
374                             DC,
375                             Loc,
376                             &II,
377                             C.IntTy,
378                             C.getTrivialTypeSourceInfo(C.IntTy),
379                             clang::SC_None,
380                             clang::SC_None);
381  clang::Decl *IID = (clang::Decl *)IIVD;
382
383  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
384  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
385
386  // Form the actual destructor loop
387  // for (Init; Cond; Inc)
388  //   RSClearObjectCall;
389
390  // Init -> "rsIntIter = 0"
391  clang::DeclRefExpr *RefrsIntIter =
392      clang::DeclRefExpr::Create(C,
393                                 NULL,
394                                 Range,
395                                 IIVD,
396                                 Loc,
397                                 C.IntTy);
398
399  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
400      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
401
402  clang::BinaryOperator *Init =
403      new(C) clang::BinaryOperator(RefrsIntIter,
404                                   Int0,
405                                   clang::BO_Assign,
406                                   C.IntTy,
407                                   Loc);
408
409  // Cond -> "rsIntIter < NumArrayElements"
410  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
411      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
412
413  clang::BinaryOperator *Cond =
414      new(C) clang::BinaryOperator(RefrsIntIter,
415                                   NumArrayElementsExpr,
416                                   clang::BO_LT,
417                                   C.IntTy,
418                                   Loc);
419
420  // Inc -> "rsIntIter++"
421  clang::UnaryOperator *Inc =
422      new(C) clang::UnaryOperator(RefrsIntIter,
423                                  clang::UO_PostInc,
424                                  C.IntTy,
425                                  Loc);
426
427  // Body -> "rsClearObject(&VD[rsIntIter]);"
428  // Destructor loop operates on individual array elements
429
430  clang::Expr *RefRSArrPtr =
431      clang::ImplicitCastExpr::Create(C,
432          C.getPointerType(BaseType->getCanonicalTypeInternal()),
433          clang::CK_ArrayToPointerDecay,
434          RefRSArr,
435          NULL,
436          clang::VK_RValue);
437
438  clang::Expr *RefRSArrPtrSubscript =
439      new(C) clang::ArraySubscriptExpr(RefRSArrPtr,
440                                       RefrsIntIter,
441                                       BaseType->getCanonicalTypeInternal(),
442                                       Loc);
443
444  RSExportPrimitiveType::DataType DT =
445      RSExportPrimitiveType::GetRSSpecificType(BaseType);
446
447  clang::Stmt *RSClearObjectCall = NULL;
448  if (BaseType->isArrayType()) {
449    RSClearObjectCall =
450        ClearArrayRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
451  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
452    RSClearObjectCall =
453        ClearStructRSObject(C, DC, RefRSArrPtrSubscript, Range, Loc);
454  } else {
455    RSClearObjectCall = ClearSingleRSObject(C, RefRSArrPtrSubscript, Loc);
456  }
457
458  clang::ForStmt *DestructorLoop =
459      new(C) clang::ForStmt(C,
460                            Init,
461                            Cond,
462                            NULL,  // no condVar
463                            Inc,
464                            RSClearObjectCall,
465                            Loc,
466                            Loc,
467                            Loc);
468
469  StmtArray[StmtCtr++] = DestructorLoop;
470  slangAssert(StmtCtr == 2);
471
472  clang::CompoundStmt *CS =
473      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
474
475  return CS;
476}
477
478static unsigned CountRSObjectTypes(const clang::Type *T) {
479  slangAssert(T);
480  unsigned RSObjectCount = 0;
481
482  if (T->isArrayType()) {
483    return CountRSObjectTypes(T->getArrayElementTypeNoTypeQual());
484  }
485
486  RSExportPrimitiveType::DataType DT =
487      RSExportPrimitiveType::GetRSSpecificType(T);
488  if (DT != RSExportPrimitiveType::DataTypeUnknown) {
489    return (RSExportPrimitiveType::IsRSObjectType(DT) ? 1 : 0);
490  }
491
492  if (!T->isStructureType()) {
493    return 0;
494  }
495
496  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
497  RD = RD->getDefinition();
498  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
499         FE = RD->field_end();
500       FI != FE;
501       FI++) {
502    const clang::FieldDecl *FD = *FI;
503    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
504    if (CountRSObjectTypes(FT)) {
505      // Sub-structs should only count once (as should arrays, etc.)
506      RSObjectCount++;
507    }
508  }
509
510  return RSObjectCount;
511}
512
513static clang::Stmt *ClearStructRSObject(
514    clang::ASTContext &C,
515    clang::DeclContext *DC,
516    clang::Expr *RefRSStruct,
517    clang::SourceRange Range,
518    clang::SourceLocation Loc) {
519  const clang::Type *BaseType = RefRSStruct->getType().getTypePtr();
520
521  slangAssert(!BaseType->isArrayType());
522
523  RSExportPrimitiveType::DataType DT =
524      RSExportPrimitiveType::GetRSSpecificType(BaseType);
525
526  // Structs should show up as unknown primitive types
527  slangAssert(DT == RSExportPrimitiveType::DataTypeUnknown);
528
529  unsigned FieldsToDestroy = CountRSObjectTypes(BaseType);
530
531  unsigned StmtCount = 0;
532  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToDestroy];
533  for (unsigned i = 0; i < FieldsToDestroy; i++) {
534    StmtArray[i] = NULL;
535  }
536
537  // Populate StmtArray by creating a destructor for each RS object field
538  clang::RecordDecl *RD = BaseType->getAsStructureType()->getDecl();
539  RD = RD->getDefinition();
540  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
541         FE = RD->field_end();
542       FI != FE;
543       FI++) {
544    // We just look through all field declarations to see if we find a
545    // declaration for an RS object type (or an array of one).
546    bool IsArrayType = false;
547    clang::FieldDecl *FD = *FI;
548    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
549    const clang::Type *OrigType = FT;
550    while (FT && FT->isArrayType()) {
551      FT = FT->getArrayElementTypeNoTypeQual();
552      IsArrayType = true;
553    }
554
555    if (RSExportPrimitiveType::IsRSObjectType(FT)) {
556      clang::DeclAccessPair FoundDecl =
557          clang::DeclAccessPair::make(FD, clang::AS_none);
558      clang::MemberExpr *RSObjectMember =
559          clang::MemberExpr::Create(C,
560                                    RefRSStruct,
561                                    false,
562                                    NULL,
563                                    Range,
564                                    FD,
565                                    FoundDecl,
566                                    clang::DeclarationNameInfo(),
567                                    NULL,
568                                    OrigType->getCanonicalTypeInternal());
569
570      slangAssert(StmtCount < FieldsToDestroy);
571
572      if (IsArrayType) {
573        StmtArray[StmtCount++] = ClearArrayRSObject(C,
574                                                    DC,
575                                                    RSObjectMember,
576                                                    Range,
577                                                    Loc);
578      } else {
579        StmtArray[StmtCount++] = ClearSingleRSObject(C,
580                                                     RSObjectMember,
581                                                     Loc);
582      }
583    } else if (FT->isStructureType() && CountRSObjectTypes(FT)) {
584      // In this case, we have a nested struct. We may not end up filling all
585      // of the spaces in StmtArray (sub-structs should handle themselves
586      // with separate compound statements).
587      clang::DeclAccessPair FoundDecl =
588          clang::DeclAccessPair::make(FD, clang::AS_none);
589      clang::MemberExpr *RSObjectMember =
590          clang::MemberExpr::Create(C,
591                                    RefRSStruct,
592                                    false,
593                                    NULL,
594                                    Range,
595                                    FD,
596                                    FoundDecl,
597                                    clang::DeclarationNameInfo(),
598                                    NULL,
599                                    OrigType->getCanonicalTypeInternal());
600
601      if (IsArrayType) {
602        StmtArray[StmtCount++] = ClearArrayRSObject(C,
603                                                    DC,
604                                                    RSObjectMember,
605                                                    Range,
606                                                    Loc);
607      } else {
608        StmtArray[StmtCount++] = ClearStructRSObject(C,
609                                                     DC,
610                                                     RSObjectMember,
611                                                     Range,
612                                                     Loc);
613      }
614    }
615  }
616
617  slangAssert(StmtCount > 0);
618  clang::CompoundStmt *CS =
619      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
620
621  delete [] StmtArray;
622
623  return CS;
624}
625
626static clang::Stmt *CreateSingleRSSetObject(clang::ASTContext &C,
627                                            clang::Diagnostic *Diags,
628                                            clang::Expr *DstExpr,
629                                            clang::Expr *SrcExpr,
630                                            clang::SourceLocation Loc) {
631  const clang::Type *T = DstExpr->getType().getTypePtr();
632  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(T);
633  slangAssert((SetObjectFD != NULL) &&
634              "rsSetObject doesn't cover all RS object types");
635
636  clang::QualType SetObjectFDType = SetObjectFD->getType();
637  clang::QualType SetObjectFDArgType[2];
638  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
639  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
640
641  clang::Expr *RefRSSetObjectFD =
642      clang::DeclRefExpr::Create(C,
643                                 NULL,
644                                 SetObjectFD->getQualifierRange(),
645                                 SetObjectFD,
646                                 Loc,
647                                 SetObjectFDType);
648
649  clang::Expr *RSSetObjectFP =
650      clang::ImplicitCastExpr::Create(C,
651                                      C.getPointerType(SetObjectFDType),
652                                      clang::CK_FunctionToPointerDecay,
653                                      RefRSSetObjectFD,
654                                      NULL,
655                                      clang::VK_RValue);
656
657  clang::Expr *ArgList[2];
658  ArgList[0] = new(C) clang::UnaryOperator(DstExpr,
659                                           clang::UO_AddrOf,
660                                           SetObjectFDArgType[0],
661                                           Loc);
662  ArgList[1] = SrcExpr;
663
664  clang::CallExpr *RSSetObjectCall =
665      new(C) clang::CallExpr(C,
666                             RSSetObjectFP,
667                             ArgList,
668                             2,
669                             SetObjectFD->getCallResultType(),
670                             Loc);
671
672  return RSSetObjectCall;
673}
674
675static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
676                                            clang::Diagnostic *Diags,
677                                            clang::Expr *LHS,
678                                            clang::Expr *RHS,
679                                            clang::SourceLocation Loc);
680
681static clang::Stmt *CreateArrayRSSetObject(clang::ASTContext &C,
682                                           clang::Diagnostic *Diags,
683                                           clang::Expr *DstArr,
684                                           clang::Expr *SrcArr,
685                                           clang::SourceLocation Loc) {
686  clang::DeclContext *DC = NULL;
687  clang::SourceRange Range;
688  const clang::Type *BaseType = DstArr->getType().getTypePtr();
689  slangAssert(BaseType->isArrayType());
690
691  int NumArrayElements = ArrayDim(BaseType);
692  // Actually extract out the base RS object type for use later
693  BaseType = BaseType->getArrayElementTypeNoTypeQual();
694
695  clang::Stmt *StmtArray[2] = {NULL};
696  int StmtCtr = 0;
697
698  if (NumArrayElements <= 0) {
699    return NULL;
700  }
701
702  // Create helper variable for iterating through elements
703  clang::IdentifierInfo& II = C.Idents.get("rsIntIter");
704  clang::VarDecl *IIVD =
705      clang::VarDecl::Create(C,
706                             DC,
707                             Loc,
708                             &II,
709                             C.IntTy,
710                             C.getTrivialTypeSourceInfo(C.IntTy),
711                             clang::SC_None,
712                             clang::SC_None);
713  clang::Decl *IID = (clang::Decl *)IIVD;
714
715  clang::DeclGroupRef DGR = clang::DeclGroupRef::Create(C, &IID, 1);
716  StmtArray[StmtCtr++] = new(C) clang::DeclStmt(DGR, Loc, Loc);
717
718  // Form the actual loop
719  // for (Init; Cond; Inc)
720  //   RSSetObjectCall;
721
722  // Init -> "rsIntIter = 0"
723  clang::DeclRefExpr *RefrsIntIter =
724      clang::DeclRefExpr::Create(C,
725                                 NULL,
726                                 Range,
727                                 IIVD,
728                                 Loc,
729                                 C.IntTy);
730
731  clang::Expr *Int0 = clang::IntegerLiteral::Create(C,
732      llvm::APInt(C.getTypeSize(C.IntTy), 0), C.IntTy, Loc);
733
734  clang::BinaryOperator *Init =
735      new(C) clang::BinaryOperator(RefrsIntIter,
736                                   Int0,
737                                   clang::BO_Assign,
738                                   C.IntTy,
739                                   Loc);
740
741  // Cond -> "rsIntIter < NumArrayElements"
742  clang::Expr *NumArrayElementsExpr = clang::IntegerLiteral::Create(C,
743      llvm::APInt(C.getTypeSize(C.IntTy), NumArrayElements), C.IntTy, Loc);
744
745  clang::BinaryOperator *Cond =
746      new(C) clang::BinaryOperator(RefrsIntIter,
747                                   NumArrayElementsExpr,
748                                   clang::BO_LT,
749                                   C.IntTy,
750                                   Loc);
751
752  // Inc -> "rsIntIter++"
753  clang::UnaryOperator *Inc =
754      new(C) clang::UnaryOperator(RefrsIntIter,
755                                  clang::UO_PostInc,
756                                  C.IntTy,
757                                  Loc);
758
759  // Body -> "rsSetObject(&Dst[rsIntIter], Src[rsIntIter]);"
760  // Loop operates on individual array elements
761
762  clang::Expr *DstArrPtr =
763      clang::ImplicitCastExpr::Create(C,
764          C.getPointerType(BaseType->getCanonicalTypeInternal()),
765          clang::CK_ArrayToPointerDecay,
766          DstArr,
767          NULL,
768          clang::VK_RValue);
769
770  clang::Expr *DstArrPtrSubscript =
771      new(C) clang::ArraySubscriptExpr(DstArrPtr,
772                                       RefrsIntIter,
773                                       BaseType->getCanonicalTypeInternal(),
774                                       Loc);
775
776  clang::Expr *SrcArrPtr =
777      clang::ImplicitCastExpr::Create(C,
778          C.getPointerType(BaseType->getCanonicalTypeInternal()),
779          clang::CK_ArrayToPointerDecay,
780          SrcArr,
781          NULL,
782          clang::VK_RValue);
783
784  clang::Expr *SrcArrPtrSubscript =
785      new(C) clang::ArraySubscriptExpr(SrcArrPtr,
786                                       RefrsIntIter,
787                                       BaseType->getCanonicalTypeInternal(),
788                                       Loc);
789
790  RSExportPrimitiveType::DataType DT =
791      RSExportPrimitiveType::GetRSSpecificType(BaseType);
792
793  clang::Stmt *RSSetObjectCall = NULL;
794  if (BaseType->isArrayType()) {
795    RSSetObjectCall = CreateArrayRSSetObject(C, Diags, DstArrPtrSubscript,
796                                             SrcArrPtrSubscript, Loc);
797  } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
798    RSSetObjectCall = CreateStructRSSetObject(C, Diags, DstArrPtrSubscript,
799                                              SrcArrPtrSubscript, Loc);
800  } else {
801    RSSetObjectCall = CreateSingleRSSetObject(C, Diags, DstArrPtrSubscript,
802                                              SrcArrPtrSubscript, Loc);
803  }
804
805  clang::ForStmt *DestructorLoop =
806      new(C) clang::ForStmt(C,
807                            Init,
808                            Cond,
809                            NULL,  // no condVar
810                            Inc,
811                            RSSetObjectCall,
812                            Loc,
813                            Loc,
814                            Loc);
815
816  StmtArray[StmtCtr++] = DestructorLoop;
817  slangAssert(StmtCtr == 2);
818
819  clang::CompoundStmt *CS =
820      new(C) clang::CompoundStmt(C, StmtArray, StmtCtr, Loc, Loc);
821
822  return CS;
823}
824
825static clang::Stmt *CreateStructRSSetObject(clang::ASTContext &C,
826                                            clang::Diagnostic *Diags,
827                                            clang::Expr *LHS,
828                                            clang::Expr *RHS,
829                                            clang::SourceLocation Loc) {
830  clang::SourceRange Range;
831  clang::QualType QT = LHS->getType();
832  const clang::Type *T = QT.getTypePtr();
833  slangAssert(T->isStructureType());
834  slangAssert(!RSExportPrimitiveType::IsRSObjectType(T));
835
836  // Keep an extra slot for the original copy (memcpy)
837  unsigned FieldsToSet = CountRSObjectTypes(T) + 1;
838
839  unsigned StmtCount = 0;
840  clang::Stmt **StmtArray = new clang::Stmt*[FieldsToSet];
841  for (unsigned i = 0; i < FieldsToSet; i++) {
842    StmtArray[i] = NULL;
843  }
844
845  clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
846  RD = RD->getDefinition();
847  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
848         FE = RD->field_end();
849       FI != FE;
850       FI++) {
851    bool IsArrayType = false;
852    clang::FieldDecl *FD = *FI;
853    const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
854    const clang::Type *OrigType = FT;
855
856    if (!CountRSObjectTypes(FT)) {
857      // Skip to next if we don't have any viable RS object types
858      continue;
859    }
860
861    clang::DeclAccessPair FoundDecl =
862        clang::DeclAccessPair::make(FD, clang::AS_none);
863    clang::MemberExpr *DstMember =
864        clang::MemberExpr::Create(C,
865                                  LHS,
866                                  false,
867                                  NULL,
868                                  Range,
869                                  FD,
870                                  FoundDecl,
871                                  clang::DeclarationNameInfo(),
872                                  NULL,
873                                  OrigType->getCanonicalTypeInternal());
874
875    clang::MemberExpr *SrcMember =
876        clang::MemberExpr::Create(C,
877                                  RHS,
878                                  false,
879                                  NULL,
880                                  Range,
881                                  FD,
882                                  FoundDecl,
883                                  clang::DeclarationNameInfo(),
884                                  NULL,
885                                  OrigType->getCanonicalTypeInternal());
886
887    if (FT->isArrayType()) {
888      FT = FT->getArrayElementTypeNoTypeQual();
889      IsArrayType = true;
890    }
891
892    RSExportPrimitiveType::DataType DT =
893        RSExportPrimitiveType::GetRSSpecificType(FT);
894
895    if (IsArrayType) {
896      Diags->Report(Diags->getCustomDiagID(clang::Diagnostic::Error,
897           "Arrays of RS object types within structures cannot be copied"));
898      // TODO(srhines): Support setting arrays of RS objects
899      // StmtArray[StmtCount++] =
900      //    CreateArrayRSSetObject(C, Diags, DstMember, SrcMember, Loc);
901    } else if (DT == RSExportPrimitiveType::DataTypeUnknown) {
902      StmtArray[StmtCount++] =
903          CreateStructRSSetObject(C, Diags, DstMember, SrcMember, Loc);
904    } else if (RSExportPrimitiveType::IsRSObjectType(DT)) {
905      StmtArray[StmtCount++] =
906          CreateSingleRSSetObject(C, Diags, DstMember, SrcMember, Loc);
907    } else {
908      slangAssert(false);
909    }
910  }
911
912  slangAssert(StmtCount > 0 && StmtCount < FieldsToSet);
913
914  // We still need to actually do the overall struct copy. For simplicity,
915  // we just do a straight-up assignment (which will still preserve all
916  // the proper RS object reference counts).
917  clang::BinaryOperator *CopyStruct =
918      new(C) clang::BinaryOperator(LHS, RHS, clang::BO_Assign, QT, Loc);
919  StmtArray[StmtCount++] = CopyStruct;
920
921  clang::CompoundStmt *CS =
922      new(C) clang::CompoundStmt(C, StmtArray, StmtCount, Loc, Loc);
923
924  delete [] StmtArray;
925
926  return CS;
927}
928
929}  // namespace
930
931void RSObjectRefCount::Scope::ReplaceRSObjectAssignment(
932    clang::BinaryOperator *AS,
933    clang::Diagnostic *Diags) {
934
935  clang::QualType QT = AS->getType();
936
937  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
938      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
939
940  clang::SourceLocation Loc = AS->getLocEnd();
941  clang::Stmt *UpdatedStmt = NULL;
942
943  if (!RSExportPrimitiveType::IsRSObjectType(QT.getTypePtr())) {
944    // By definition, this is a struct assignment if we get here
945    UpdatedStmt =
946        CreateStructRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
947  } else {
948    UpdatedStmt =
949        CreateSingleRSSetObject(C, Diags, AS->getLHS(), AS->getRHS(), Loc);
950  }
951
952  ReplaceInCompoundStmt(C, mCS, AS, UpdatedStmt);
953  return;
954}
955
956void RSObjectRefCount::Scope::AppendRSObjectInit(
957    clang::Diagnostic *Diags,
958    clang::VarDecl *VD,
959    clang::DeclStmt *DS,
960    RSExportPrimitiveType::DataType DT,
961    clang::Expr *InitExpr) {
962  slangAssert(VD);
963
964  if (!InitExpr) {
965    return;
966  }
967
968  clang::ASTContext &C = RSObjectRefCount::GetRSSetObjectFD(
969      RSExportPrimitiveType::DataTypeRSFont)->getASTContext();
970  clang::SourceLocation Loc = RSObjectRefCount::GetRSSetObjectFD(
971      RSExportPrimitiveType::DataTypeRSFont)->getLocation();
972
973  if (DT == RSExportPrimitiveType::DataTypeIsStruct) {
974    // TODO(srhines): Skip struct initialization right now
975    const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
976    clang::DeclRefExpr *RefRSVar =
977        clang::DeclRefExpr::Create(C,
978                                   NULL,
979                                   VD->getQualifierRange(),
980                                   VD,
981                                   Loc,
982                                   T->getCanonicalTypeInternal());
983
984    clang::Stmt *RSSetObjectOps =
985        CreateStructRSSetObject(C, Diags, RefRSVar, InitExpr, Loc);
986
987    AppendAfterStmt(C, mCS, DS, RSSetObjectOps);
988    return;
989  }
990
991  clang::FunctionDecl *SetObjectFD = RSObjectRefCount::GetRSSetObjectFD(DT);
992  slangAssert((SetObjectFD != NULL) &&
993              "rsSetObject doesn't cover all RS object types");
994
995  clang::QualType SetObjectFDType = SetObjectFD->getType();
996  clang::QualType SetObjectFDArgType[2];
997  SetObjectFDArgType[0] = SetObjectFD->getParamDecl(0)->getOriginalType();
998  SetObjectFDArgType[1] = SetObjectFD->getParamDecl(1)->getOriginalType();
999
1000  clang::Expr *RefRSSetObjectFD =
1001      clang::DeclRefExpr::Create(C,
1002                                 NULL,
1003                                 SetObjectFD->getQualifierRange(),
1004                                 SetObjectFD,
1005                                 Loc,
1006                                 SetObjectFDType);
1007
1008  clang::Expr *RSSetObjectFP =
1009      clang::ImplicitCastExpr::Create(C,
1010                                      C.getPointerType(SetObjectFDType),
1011                                      clang::CK_FunctionToPointerDecay,
1012                                      RefRSSetObjectFD,
1013                                      NULL,
1014                                      clang::VK_RValue);
1015
1016  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1017  clang::DeclRefExpr *RefRSVar =
1018      clang::DeclRefExpr::Create(C,
1019                                 NULL,
1020                                 VD->getQualifierRange(),
1021                                 VD,
1022                                 Loc,
1023                                 T->getCanonicalTypeInternal());
1024
1025  clang::Expr *ArgList[2];
1026  ArgList[0] = new(C) clang::UnaryOperator(RefRSVar,
1027                                           clang::UO_AddrOf,
1028                                           SetObjectFDArgType[0],
1029                                           Loc);
1030  ArgList[1] = InitExpr;
1031
1032  clang::CallExpr *RSSetObjectCall =
1033      new(C) clang::CallExpr(C,
1034                             RSSetObjectFP,
1035                             ArgList,
1036                             2,
1037                             SetObjectFD->getCallResultType(),
1038                             Loc);
1039
1040  AppendAfterStmt(C, mCS, DS, RSSetObjectCall);
1041
1042  return;
1043}
1044
1045void RSObjectRefCount::Scope::InsertLocalVarDestructors() {
1046  std::list<clang::Stmt*> RSClearObjectCalls;
1047  for (std::list<clang::VarDecl*>::const_iterator I = mRSO.begin(),
1048          E = mRSO.end();
1049        I != E;
1050        I++) {
1051    clang::Stmt *S = ClearRSObject(*I);
1052    if (S) {
1053      RSClearObjectCalls.push_back(S);
1054    }
1055  }
1056  if (RSClearObjectCalls.size() > 0) {
1057    DestructorVisitor DV((*mRSO.begin())->getASTContext(), RSClearObjectCalls);
1058    DV.Visit(mCS);
1059  }
1060  return;
1061}
1062
1063clang::Stmt *RSObjectRefCount::Scope::ClearRSObject(clang::VarDecl *VD) {
1064  slangAssert(VD);
1065  clang::ASTContext &C = VD->getASTContext();
1066  clang::DeclContext *DC = VD->getDeclContext();
1067  clang::SourceRange Range = VD->getQualifierRange();
1068  clang::SourceLocation Loc = VD->getLocation();
1069  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1070
1071  // Reference expr to target RS object variable
1072  clang::DeclRefExpr *RefRSVar =
1073      clang::DeclRefExpr::Create(C,
1074                                 NULL,
1075                                 Range,
1076                                 VD,
1077                                 Loc,
1078                                 T->getCanonicalTypeInternal());
1079
1080  if (T->isArrayType()) {
1081    return ClearArrayRSObject(C, DC, RefRSVar, Range, Loc);
1082  }
1083
1084  RSExportPrimitiveType::DataType DT =
1085      RSExportPrimitiveType::GetRSSpecificType(T);
1086
1087  if (DT == RSExportPrimitiveType::DataTypeUnknown ||
1088      DT == RSExportPrimitiveType::DataTypeIsStruct) {
1089    return ClearStructRSObject(C, DC, RefRSVar, Range, Loc);
1090  }
1091
1092  slangAssert((RSExportPrimitiveType::IsRSObjectType(DT)) &&
1093              "Should be RS object");
1094
1095  return ClearSingleRSObject(C, RefRSVar, Loc);
1096}
1097
1098bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD,
1099                                          RSExportPrimitiveType::DataType *DT,
1100                                          clang::Expr **InitExpr) {
1101  slangAssert(VD && DT && InitExpr);
1102  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
1103
1104  // Loop through array types to get to base type
1105  while (T && T->isArrayType()) {
1106    T = T->getArrayElementTypeNoTypeQual();
1107  }
1108
1109  bool DataTypeIsStructWithRSObject = false;
1110  *DT = RSExportPrimitiveType::GetRSSpecificType(T);
1111
1112  if (*DT == RSExportPrimitiveType::DataTypeUnknown) {
1113    if (RSExportPrimitiveType::IsStructureTypeWithRSObject(T)) {
1114      *DT = RSExportPrimitiveType::DataTypeIsStruct;
1115      DataTypeIsStructWithRSObject = true;
1116    } else {
1117      return false;
1118    }
1119  }
1120
1121  bool DataTypeIsRSObject = false;
1122  if (DataTypeIsStructWithRSObject) {
1123    DataTypeIsRSObject = true;
1124  } else {
1125    DataTypeIsRSObject = RSExportPrimitiveType::IsRSObjectType(*DT);
1126  }
1127  *InitExpr = VD->getInit();
1128
1129  if (!DataTypeIsRSObject && *InitExpr) {
1130    // If we already have an initializer for a matrix type, we are done.
1131    return DataTypeIsRSObject;
1132  }
1133
1134  clang::Expr *ZeroInitializer =
1135      CreateZeroInitializerForRSSpecificType(*DT,
1136                                             VD->getASTContext(),
1137                                             VD->getLocation());
1138
1139  if (ZeroInitializer) {
1140    ZeroInitializer->setType(T->getCanonicalTypeInternal());
1141    VD->setInit(ZeroInitializer);
1142  }
1143
1144  return DataTypeIsRSObject;
1145}
1146
1147clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
1148    RSExportPrimitiveType::DataType DT,
1149    clang::ASTContext &C,
1150    const clang::SourceLocation &Loc) {
1151  clang::Expr *Res = NULL;
1152  switch (DT) {
1153    case RSExportPrimitiveType::DataTypeIsStruct:
1154    case RSExportPrimitiveType::DataTypeRSElement:
1155    case RSExportPrimitiveType::DataTypeRSType:
1156    case RSExportPrimitiveType::DataTypeRSAllocation:
1157    case RSExportPrimitiveType::DataTypeRSSampler:
1158    case RSExportPrimitiveType::DataTypeRSScript:
1159    case RSExportPrimitiveType::DataTypeRSMesh:
1160    case RSExportPrimitiveType::DataTypeRSProgramFragment:
1161    case RSExportPrimitiveType::DataTypeRSProgramVertex:
1162    case RSExportPrimitiveType::DataTypeRSProgramRaster:
1163    case RSExportPrimitiveType::DataTypeRSProgramStore:
1164    case RSExportPrimitiveType::DataTypeRSFont: {
1165      //    (ImplicitCastExpr 'nullptr_t'
1166      //      (IntegerLiteral 0)))
1167      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
1168      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
1169      clang::Expr *CastToNull =
1170          clang::ImplicitCastExpr::Create(C,
1171                                          C.NullPtrTy,
1172                                          clang::CK_IntegralToPointer,
1173                                          Int0,
1174                                          NULL,
1175                                          clang::VK_RValue);
1176
1177      Res = new(C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
1178      break;
1179    }
1180    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
1181    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
1182    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
1183      // RS matrix is not completely an RS object. They hold data by themselves.
1184      // (InitListExpr rs_matrix2x2
1185      //   (InitListExpr float[4]
1186      //     (FloatingLiteral 0)
1187      //     (FloatingLiteral 0)
1188      //     (FloatingLiteral 0)
1189      //     (FloatingLiteral 0)))
1190      clang::QualType FloatTy = C.FloatTy;
1191      // Constructor sets value to 0.0f by default
1192      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
1193      clang::FloatingLiteral *Float0Val =
1194          clang::FloatingLiteral::Create(C,
1195                                         Val,
1196                                         /* isExact = */true,
1197                                         FloatTy,
1198                                         Loc);
1199
1200      unsigned N = 0;
1201      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
1202        N = 2;
1203      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
1204        N = 3;
1205      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
1206        N = 4;
1207
1208      // Directly allocate 16 elements instead of dynamically allocate N*N
1209      clang::Expr *InitVals[16];
1210      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
1211        InitVals[i] = Float0Val;
1212      clang::Expr *InitExpr =
1213          new(C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
1214      InitExpr->setType(C.getConstantArrayType(FloatTy,
1215                                               llvm::APInt(32, 4),
1216                                               clang::ArrayType::Normal,
1217                                               /* EltTypeQuals = */0));
1218
1219      Res = new(C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
1220      break;
1221    }
1222    case RSExportPrimitiveType::DataTypeUnknown:
1223    case RSExportPrimitiveType::DataTypeFloat16:
1224    case RSExportPrimitiveType::DataTypeFloat32:
1225    case RSExportPrimitiveType::DataTypeFloat64:
1226    case RSExportPrimitiveType::DataTypeSigned8:
1227    case RSExportPrimitiveType::DataTypeSigned16:
1228    case RSExportPrimitiveType::DataTypeSigned32:
1229    case RSExportPrimitiveType::DataTypeSigned64:
1230    case RSExportPrimitiveType::DataTypeUnsigned8:
1231    case RSExportPrimitiveType::DataTypeUnsigned16:
1232    case RSExportPrimitiveType::DataTypeUnsigned32:
1233    case RSExportPrimitiveType::DataTypeUnsigned64:
1234    case RSExportPrimitiveType::DataTypeBoolean:
1235    case RSExportPrimitiveType::DataTypeUnsigned565:
1236    case RSExportPrimitiveType::DataTypeUnsigned5551:
1237    case RSExportPrimitiveType::DataTypeUnsigned4444:
1238    case RSExportPrimitiveType::DataTypeMax: {
1239      slangAssert(false && "Not RS object type!");
1240    }
1241    // No default case will enable compiler detecting the missing cases
1242  }
1243
1244  return Res;
1245}
1246
1247void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
1248  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
1249       I != E;
1250       I++) {
1251    clang::Decl *D = *I;
1252    if (D->getKind() == clang::Decl::Var) {
1253      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
1254      RSExportPrimitiveType::DataType DT =
1255          RSExportPrimitiveType::DataTypeUnknown;
1256      clang::Expr *InitExpr = NULL;
1257      if (InitializeRSObject(VD, &DT, &InitExpr)) {
1258        getCurrentScope()->addRSObject(VD);
1259        getCurrentScope()->AppendRSObjectInit(mDiags, VD, DS, DT, InitExpr);
1260      }
1261    }
1262  }
1263  return;
1264}
1265
1266void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
1267  if (!CS->body_empty()) {
1268    // Push a new scope
1269    Scope *S = new Scope(CS);
1270    mScopeStack.push(S);
1271
1272    VisitStmt(CS);
1273
1274    // Destroy the scope
1275    slangAssert((getCurrentScope() == S) && "Corrupted scope stack!");
1276    S->InsertLocalVarDestructors();
1277    mScopeStack.pop();
1278    delete S;
1279  }
1280  return;
1281}
1282
1283void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
1284  clang::QualType QT = AS->getType();
1285
1286  if (CountRSObjectTypes(QT.getTypePtr())) {
1287    getCurrentScope()->ReplaceRSObjectAssignment(AS, mDiags);
1288  }
1289
1290  return;
1291}
1292
1293void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
1294  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
1295       I != E;
1296       I++) {
1297    if (clang::Stmt *Child = *I) {
1298      Visit(Child);
1299    }
1300  }
1301  return;
1302}
1303
1304}  // namespace slang
1305