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 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 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 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 * 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