slang_rs_object_ref_count.cpp revision 4b32ffdfc1ac766f8932e7effbcdf7484e804a8e
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 "clang/AST/DeclGroup.h"
20#include "clang/AST/Expr.h"
21#include "clang/AST/OperationKinds.h"
22#include "clang/AST/Stmt.h"
23#include "clang/AST/StmtVisitor.h"
24
25#include "slang_rs.h"
26#include "slang_rs_export_type.h"
27
28using namespace slang;
29
30bool RSObjectRefCount::InitializeRSObject(clang::VarDecl *VD) {
31  const clang::Type *T = RSExportType::GetTypeOfDecl(VD);
32  RSExportPrimitiveType::DataType DT =
33      RSExportPrimitiveType::GetRSSpecificType(T);
34
35  if (DT == RSExportPrimitiveType::DataTypeUnknown)
36    return false;
37
38  if (VD->hasInit()) {
39    // TODO: Update the reference count of RS object in initializer.
40    // This can potentially be done as part of the assignment pass.
41  } else {
42    clang::Expr *ZeroInitializer =
43        CreateZeroInitializerForRSSpecificType(DT,
44                                               VD->getASTContext(),
45                                               VD->getLocation());
46
47    if (ZeroInitializer) {
48      ZeroInitializer->setType(T->getCanonicalTypeInternal());
49      VD->setInit(ZeroInitializer);
50    }
51  }
52
53  return RSExportPrimitiveType::IsRSObjectType(DT);
54}
55
56clang::Expr *RSObjectRefCount::CreateZeroInitializerForRSSpecificType(
57    RSExportPrimitiveType::DataType DT,
58    clang::ASTContext &C,
59    const clang::SourceLocation &Loc) {
60  clang::Expr *Res = NULL;
61  switch (DT) {
62    case RSExportPrimitiveType::DataTypeRSElement:
63    case RSExportPrimitiveType::DataTypeRSType:
64    case RSExportPrimitiveType::DataTypeRSAllocation:
65    case RSExportPrimitiveType::DataTypeRSSampler:
66    case RSExportPrimitiveType::DataTypeRSScript:
67    case RSExportPrimitiveType::DataTypeRSMesh:
68    case RSExportPrimitiveType::DataTypeRSProgramFragment:
69    case RSExportPrimitiveType::DataTypeRSProgramVertex:
70    case RSExportPrimitiveType::DataTypeRSProgramRaster:
71    case RSExportPrimitiveType::DataTypeRSProgramStore:
72    case RSExportPrimitiveType::DataTypeRSFont: {
73      //    (ImplicitCastExpr 'nullptr_t'
74      //      (IntegerLiteral 0)))
75      llvm::APInt Zero(C.getTypeSize(C.IntTy), 0);
76      clang::Expr *Int0 = clang::IntegerLiteral::Create(C, Zero, C.IntTy, Loc);
77      clang::Expr *CastToNull =
78          clang::ImplicitCastExpr::Create(C,
79                                          C.NullPtrTy,
80                                          clang::CK_IntegralToPointer,
81                                          Int0,
82                                          NULL,
83                                          clang::VK_RValue);
84
85      Res = new (C) clang::InitListExpr(C, Loc, &CastToNull, 1, Loc);
86      break;
87    }
88    case RSExportPrimitiveType::DataTypeRSMatrix2x2:
89    case RSExportPrimitiveType::DataTypeRSMatrix3x3:
90    case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
91      // RS matrix is not completely an RS object. They hold data by themselves.
92      // (InitListExpr rs_matrix2x2
93      //   (InitListExpr float[4]
94      //     (FloatingLiteral 0)
95      //     (FloatingLiteral 0)
96      //     (FloatingLiteral 0)
97      //     (FloatingLiteral 0)))
98      clang::QualType FloatTy = C.FloatTy;
99      // Constructor sets value to 0.0f by default
100      llvm::APFloat Val(C.getFloatTypeSemantics(FloatTy));
101      clang::FloatingLiteral *Float0Val =
102          clang::FloatingLiteral::Create(C,
103                                         Val,
104                                         /* isExact = */true,
105                                         FloatTy,
106                                         Loc);
107
108      unsigned N = 0;
109      if (DT == RSExportPrimitiveType::DataTypeRSMatrix2x2)
110        N = 2;
111      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix3x3)
112        N = 3;
113      else if (DT == RSExportPrimitiveType::DataTypeRSMatrix4x4)
114        N = 4;
115
116      // Directly allocate 16 elements instead of dynamically allocate N*N
117      clang::Expr *InitVals[16];
118      for (unsigned i = 0; i < sizeof(InitVals) / sizeof(InitVals[0]); i++)
119        InitVals[i] = Float0Val;
120      clang::Expr *InitExpr =
121          new (C) clang::InitListExpr(C, Loc, InitVals, N * N, Loc);
122      InitExpr->setType(C.getConstantArrayType(FloatTy,
123                                               llvm::APInt(32, 4),
124                                               clang::ArrayType::Normal,
125                                               /* EltTypeQuals = */0));
126
127      Res = new (C) clang::InitListExpr(C, Loc, &InitExpr, 1, Loc);
128      break;
129    }
130    case RSExportPrimitiveType::DataTypeUnknown:
131    case RSExportPrimitiveType::DataTypeFloat16:
132    case RSExportPrimitiveType::DataTypeFloat32:
133    case RSExportPrimitiveType::DataTypeFloat64:
134    case RSExportPrimitiveType::DataTypeSigned8:
135    case RSExportPrimitiveType::DataTypeSigned16:
136    case RSExportPrimitiveType::DataTypeSigned32:
137    case RSExportPrimitiveType::DataTypeSigned64:
138    case RSExportPrimitiveType::DataTypeUnsigned8:
139    case RSExportPrimitiveType::DataTypeUnsigned16:
140    case RSExportPrimitiveType::DataTypeUnsigned32:
141    case RSExportPrimitiveType::DataTypeUnsigned64:
142    case RSExportPrimitiveType::DataTypeBoolean:
143    case RSExportPrimitiveType::DataTypeUnsigned565:
144    case RSExportPrimitiveType::DataTypeUnsigned5551:
145    case RSExportPrimitiveType::DataTypeUnsigned4444:
146    case RSExportPrimitiveType::DataTypeMax: {
147      assert(false && "Not RS object type!");
148    }
149    // No default case will enable compiler detecting the missing cases
150  }
151
152  return Res;
153}
154
155void RSObjectRefCount::VisitDeclStmt(clang::DeclStmt *DS) {
156  for (clang::DeclStmt::decl_iterator I = DS->decl_begin(), E = DS->decl_end();
157       I != E;
158       I++) {
159    clang::Decl *D = *I;
160    if (D->getKind() == clang::Decl::Var) {
161      clang::VarDecl *VD = static_cast<clang::VarDecl*>(D);
162      if (InitializeRSObject(VD))
163        getCurrentScope()->addRSObject(VD);
164    }
165  }
166  return;
167}
168
169void RSObjectRefCount::VisitCompoundStmt(clang::CompoundStmt *CS) {
170  if (!CS->body_empty()) {
171    // Push a new scope
172    Scope *S = new Scope(CS);
173    mScopeStack.push(S);
174
175    VisitStmt(CS);
176
177    // Destroy the scope
178    // TODO: Update reference count of the RS object refenced by
179    //       getCurrentScope().
180    assert((getCurrentScope() == S) && "Corrupted scope stack!");
181    mScopeStack.pop();
182    delete S;
183  }
184  return;
185}
186
187void RSObjectRefCount::VisitBinAssign(clang::BinaryOperator *AS) {
188  // TODO: Update reference count
189  return;
190}
191
192void RSObjectRefCount::VisitStmt(clang::Stmt *S) {
193  for (clang::Stmt::child_iterator I = S->child_begin(), E = S->child_end();
194       I != E;
195       I++) {
196    if (clang::Stmt *Child = *I) {
197      Visit(Child);
198    }
199  }
200  return;
201}
202
203