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