slang_rs_export_element.cpp revision dd6206bb61bf8df2ed6b643abe8a29c48a315685
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_rs_context.h" 26#include "slang_rs_export_type.h" 27 28namespace slang { 29 30bool RSExportElement::Initialized = false; 31RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap; 32 33void RSExportElement::Init() { 34 if (!Initialized) { 35 // Initialize ElementInfoMap 36#define ENUM_RS_DATA_ELEMENT(_name, _dk, _dt, _norm, _vsize) \ 37 { \ 38 ElementInfo *EI = new ElementInfo; \ 39 EI->kind = RSExportPrimitiveType::DataKind ## _dk; \ 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 59RSExportType *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 assert(EI != NULL && "Element info not found"); 71 72 if (!RSExportType::NormalizeType(T, TypeName, NULL, NULL, NULL)) 73 return NULL; 74 75 switch (T->getTypeClass()) { 76 case clang::Type::Builtin: 77 case clang::Type::Pointer: { 78 assert(EI->vsize == 1 && "Element not a primitive class (please check " 79 "your macro)"); 80 RSExportPrimitiveType *EPT = 81 RSExportPrimitiveType::Create(Context, 82 T, 83 TypeName, 84 EI->kind, 85 EI->normalized); 86 // Verify 87 assert(EI->type == EPT->getType() && "Element has unexpected type"); 88 ET = EPT; 89 break; 90 } 91 case clang::Type::ExtVector: { 92 assert(EI->vsize > 1 && "Element not a vector class (please check your " 93 "macro)"); 94 RSExportVectorType *EVT = 95 RSExportVectorType::Create(Context, 96 static_cast<clang::ExtVectorType*>( 97 T->getCanonicalTypeInternal() 98 .getTypePtr()), 99 TypeName, 100 EI->kind, 101 EI->normalized); 102 // Verify 103 assert(EI->type == EVT->getType() && "Element has unexpected type"); 104 assert(EI->vsize == EVT->getNumElement() && "Element has unexpected size " 105 "of vector"); 106 ET = EVT; 107 break; 108 } 109 default: { 110 // TODO(zonr): warn that type is not exportable 111 fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n", 112 T->getTypeClassName()); 113 break; 114 } 115 } 116 117 return ET; 118} 119 120RSExportType *RSExportElement::CreateFromDecl(RSContext *Context, 121 const clang::DeclaratorDecl *DD) { 122 const clang::Type* T = RSExportType::GetTypeOfDecl(DD); 123 const clang::Type* CT = GET_CANONICAL_TYPE(T); 124 const ElementInfo* EI = NULL; 125 126 // Note: RS element like rs_pixel_rgb elements are either in the type of 127 // primitive or vector. 128 if ((CT->getTypeClass() != clang::Type::Builtin) && 129 (CT->getTypeClass() != clang::Type::ExtVector)) { 130 return RSExportType::Create(Context, T); 131 } 132 133 // Following the typedef chain to see whether it's an element name like 134 // rs_pixel_rgb or its alias (via typedef). 135 while (T != CT) { 136 if (T->getTypeClass() != clang::Type::Typedef) { 137 break; 138 } else { 139 const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T); 140 const clang::TypedefDecl *TD = TT->getDecl(); 141 EI = GetElementInfo(TD->getName()); 142 if (EI != NULL) 143 break; 144 145 T = TD->getUnderlyingType().getTypePtr(); 146 } 147 } 148 149 if (EI == NULL) { 150 return RSExportType::Create(Context, T); 151 } else { 152 return RSExportElement::Create(Context, T, EI); 153 } 154} 155 156const RSExportElement::ElementInfo * 157RSExportElement::GetElementInfo(const llvm::StringRef &Name) { 158 if (!Initialized) 159 Init(); 160 161 ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name); 162 if (I == ElementInfoMap.end()) 163 return NULL; 164 else 165 return I->getValue(); 166} 167 168} // namespace slang 169