blob: e2e911738fd17908d53f09c38cf2ee6b75782711 [file] [log] [blame]
Stephen Hines4b32ffd2010-11-05 18:47:11 -07001/*
2 * Copyright 2010, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "slang_rs_object_ref_count.h"
18
19#include "clang/AST/DeclGroup.h"
20#include "clang/AST/Expr.h"
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