• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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