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_export_element.h"
18
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/Type.h"
21
22 #include "clang/Basic/SourceLocation.h"
23 #include "clang/Basic/IdentifierTable.h"
24
25 #include "slang_assert.h"
26 #include "slang_rs_context.h"
27 #include "slang_rs_export_type.h"
28
29 namespace slang {
30
31 bool RSExportElement::Initialized = false;
32 RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
33
Init()34 void RSExportElement::Init() {
35 if (!Initialized) {
36 // Initialize ElementInfoMap
37 #define ENUM_RS_DATA_ELEMENT(_name, _dk, _dt, _norm, _vsize) \
38 { \
39 ElementInfo *EI = new ElementInfo; \
40 EI->kind = RSExportPrimitiveType::DataKind ## _dk; \
41 EI->type = RSExportPrimitiveType::DataType ## _dt; \
42 EI->normalized = _norm; \
43 EI->vsize = _vsize; \
44 \
45 llvm::StringRef Name(_name); \
46 ElementInfoMap.insert( \
47 ElementInfoMapTy::value_type::Create( \
48 Name.begin(), \
49 Name.end(), \
50 ElementInfoMap.getAllocator(), \
51 EI)); \
52 }
53 #include "RSDataElementEnums.inc"
54
55 Initialized = true;
56 }
57 return;
58 }
59
Create(RSContext * Context,const clang::Type * T,const ElementInfo * EI)60 RSExportType *RSExportElement::Create(RSContext *Context,
61 const clang::Type *T,
62 const ElementInfo *EI) {
63 // Create RSExportType corresponded to the @T first and then verify
64
65 llvm::StringRef TypeName;
66 RSExportType *ET = NULL;
67
68 if (!Initialized)
69 Init();
70
71 slangAssert(EI != NULL && "Element info not found");
72
73 if (!RSExportType::NormalizeType(T, TypeName, Context->getDiagnostics(),
74 NULL))
75 return NULL;
76
77 switch (T->getTypeClass()) {
78 case clang::Type::Builtin:
79 case clang::Type::Pointer: {
80 slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
81 "check your macro)");
82 RSExportPrimitiveType *EPT =
83 RSExportPrimitiveType::Create(Context,
84 T,
85 TypeName,
86 EI->kind,
87 EI->normalized);
88 // Verify
89 slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
90 ET = EPT;
91 break;
92 }
93 case clang::Type::ExtVector: {
94 slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
95 "your macro)");
96 RSExportVectorType *EVT =
97 RSExportVectorType::Create(Context,
98 static_cast<const clang::ExtVectorType*>(
99 T->getCanonicalTypeInternal()
100 .getTypePtr()),
101 TypeName,
102 EI->kind,
103 EI->normalized);
104 // Verify
105 slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
106 slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
107 "size of vector");
108 ET = EVT;
109 break;
110 }
111 default: {
112 // TODO(zonr): warn that type is not exportable
113 fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
114 T->getTypeClassName());
115 break;
116 }
117 }
118
119 return ET;
120 }
121
CreateFromDecl(RSContext * Context,const clang::DeclaratorDecl * DD)122 RSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
123 const clang::DeclaratorDecl *DD) {
124 const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
125 const clang::Type* CT = GET_CANONICAL_TYPE(T);
126 const ElementInfo* EI = NULL;
127
128 // Note: RS element like rs_pixel_rgb elements are either in the type of
129 // primitive or vector.
130 if ((CT->getTypeClass() != clang::Type::Builtin) &&
131 (CT->getTypeClass() != clang::Type::ExtVector)) {
132 return RSExportType::Create(Context, T);
133 }
134
135 // Following the typedef chain to see whether it's an element name like
136 // rs_pixel_rgb or its alias (via typedef).
137 while (T != CT) {
138 if (T->getTypeClass() != clang::Type::Typedef) {
139 break;
140 } else {
141 const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
142 const clang::TypedefNameDecl *TD = TT->getDecl();
143 EI = GetElementInfo(TD->getName());
144 if (EI != NULL)
145 break;
146
147 T = TD->getUnderlyingType().getTypePtr();
148 }
149 }
150
151 if (EI == NULL) {
152 return RSExportType::Create(Context, T);
153 } else {
154 return RSExportElement::Create(Context, T, EI);
155 }
156 }
157
158 const RSExportElement::ElementInfo *
GetElementInfo(const llvm::StringRef & Name)159 RSExportElement::GetElementInfo(const llvm::StringRef &Name) {
160 if (!Initialized)
161 Init();
162
163 ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
164 if (I == ElementInfoMap.end())
165 return NULL;
166 else
167 return I->getValue();
168 }
169
170 } // namespace slang
171