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