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
34 struct DataElementInfo {
35 const char *name;
36 DataType dataType;
37 bool normalized;
38 int vsize;
39 };
40
41 static DataElementInfo DataElementInfoTable[] = {
42 {"rs_pixel_l", DataTypeUnsigned8, true, 1},
43 {"rs_pixel_a", DataTypeUnsigned8, true, 1},
44 {"rs_pixel_la", DataTypeUnsigned8, true, 2},
45 {"rs_pixel_rgb", DataTypeUnsigned8, true, 3},
46 {"rs_pixel_rgba", DataTypeUnsigned8, true, 4},
47 {"rs_pixel_rgb565", DataTypeUnsigned8, true, 3},
48 {"rs_pixel_rgb5551", DataTypeUnsigned8, true, 4},
49 {"rs_pixel_rgb4444", DataTypeUnsigned8, true, 4},
50 };
51
52 const int DataElementInfoTableCount = sizeof(DataElementInfoTable) / sizeof(DataElementInfoTable[0]);
53
54 // TODO Rename RSExportElement to RSExportDataElement
Init()55 void RSExportElement::Init() {
56 if (!Initialized) {
57 // Initialize ElementInfoMap
58 for (int i = 0; i < DataElementInfoTableCount; i++) {
59 ElementInfo *EI = new ElementInfo;
60 EI->type = DataElementInfoTable[i].dataType;
61 EI->normalized = DataElementInfoTable[i].normalized;
62 EI->vsize = DataElementInfoTable[i].vsize;
63 llvm::StringRef Name(DataElementInfoTable[i].name);
64 ElementInfoMap.insert(ElementInfoMapTy::value_type::Create(
65 Name, ElementInfoMap.getAllocator(), EI));
66 }
67 Initialized = true;
68 }
69 }
70
Create(RSContext * Context,const clang::Type * T,const ElementInfo * EI)71 RSExportType *RSExportElement::Create(RSContext *Context,
72 const clang::Type *T,
73 const ElementInfo *EI) {
74 // Create RSExportType corresponded to the @T first and then verify
75
76 llvm::StringRef TypeName;
77 RSExportType *ET = nullptr;
78
79 if (!Initialized)
80 Init();
81
82 slangAssert(EI != nullptr && "Element info not found");
83
84 if (!RSExportType::NormalizeType(T, TypeName, Context, nullptr,
85 NotLegacyKernelArgument))
86 return nullptr;
87
88 switch (T->getTypeClass()) {
89 case clang::Type::Builtin:
90 case clang::Type::Pointer: {
91 slangAssert(EI->vsize == 1 && "Element not a primitive class (please "
92 "check your macro)");
93 RSExportPrimitiveType *EPT =
94 RSExportPrimitiveType::Create(Context,
95 T,
96 TypeName,
97 EI->normalized);
98 // Verify
99 slangAssert(EI->type == EPT->getType() && "Element has unexpected type");
100 ET = EPT;
101 break;
102 }
103 case clang::Type::ExtVector: {
104 slangAssert(EI->vsize > 1 && "Element not a vector class (please check "
105 "your macro)");
106 RSExportVectorType *EVT =
107 RSExportVectorType::Create(Context,
108 static_cast<const clang::ExtVectorType*>(
109 T->getCanonicalTypeInternal()
110 .getTypePtr()),
111 TypeName,
112 EI->normalized);
113 // Verify
114 slangAssert(EI->type == EVT->getType() && "Element has unexpected type");
115 slangAssert(EI->vsize == EVT->getNumElement() && "Element has unexpected "
116 "size of vector");
117 ET = EVT;
118 break;
119 }
120 default: {
121 // TODO(zonr): warn that type is not exportable
122 fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n",
123 T->getTypeClassName());
124 break;
125 }
126 }
127
128 return ET;
129 }
130
CreateFromDecl(RSContext * Context,const clang::DeclaratorDecl * DD)131 RSExportType *RSExportElement::CreateFromDecl(RSContext *Context,
132 const clang::DeclaratorDecl *DD) {
133 const clang::Type* T = RSExportType::GetTypeOfDecl(DD);
134 const clang::Type* CT = GetCanonicalType(T);
135 const ElementInfo* EI = nullptr;
136
137 // Note: RS element like rs_pixel_rgb elements are either in the type of
138 // primitive or vector.
139 if ((CT->getTypeClass() != clang::Type::Builtin) &&
140 (CT->getTypeClass() != clang::Type::ExtVector)) {
141 return RSExportType::Create(Context, T, NotLegacyKernelArgument);
142 }
143
144 // Following the typedef chain to see whether it's an element name like
145 // rs_pixel_rgb or its alias (via typedef).
146 while (T != CT) {
147 if (T->getTypeClass() != clang::Type::Typedef) {
148 break;
149 } else {
150 const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T);
151 const clang::TypedefNameDecl *TD = TT->getDecl();
152 EI = GetElementInfo(TD->getName());
153 if (EI != nullptr)
154 break;
155
156 T = TD->getUnderlyingType().getTypePtr();
157 }
158 }
159
160 if (EI == nullptr) {
161 return RSExportType::Create(Context, T, NotLegacyKernelArgument);
162 } else {
163 return RSExportElement::Create(Context, T, EI);
164 }
165 }
166
167 const RSExportElement::ElementInfo *
GetElementInfo(const llvm::StringRef & Name)168 RSExportElement::GetElementInfo(const llvm::StringRef &Name) {
169 if (!Initialized)
170 Init();
171
172 ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
173 if (I == ElementInfoMap.end())
174 return nullptr;
175 else
176 return I->getValue();
177 }
178
179 } // namespace slang
180