slang_rs_export_element.cpp revision 2e1dba6c779a0ae55c76d36a3c03553e16725ab7
1#include "slang_rs_export_element.h" 2 3#include "clang/Basic/SourceLocation.h" 4#include "clang/Basic/IdentifierTable.h" 5 6#include "clang/AST/Decl.h" 7#include "clang/AST/Type.h" 8 9#include "slang_rs_context.h" 10#include "slang_rs_export_type.h" 11 12using namespace slang; 13 14bool RSExportElement::Initialized = false; 15RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap; 16 17void RSExportElement::Init() { 18 if (!Initialized) { 19 // Initialize ElementInfoMap 20#define USE_ELEMENT_DATA_TYPE 21#define USE_ELEMENT_DATA_KIND 22#define DEF_ELEMENT(_name, _dk, _dt, _norm, _vsize) \ 23 { \ 24 ElementInfo *EI = new ElementInfo; \ 25 EI->kind = GET_ELEMENT_DATA_KIND(_dk); \ 26 EI->type = GET_ELEMENT_DATA_TYPE(_dt); \ 27 EI->normalized = _norm; \ 28 EI->vsize = _vsize; \ 29 \ 30 llvm::StringRef Name(_name); \ 31 ElementInfoMap.insert( \ 32 ElementInfoMapTy::value_type::Create( \ 33 Name.begin(), \ 34 Name.end(), \ 35 ElementInfoMap.getAllocator(), \ 36 EI)); \ 37 } 38#include "slang_rs_export_element_support.inc" 39 40 Initialized = true; 41 } 42 return; 43} 44 45RSExportType *RSExportElement::Create(RSContext *Context, 46 const clang::Type *T, 47 const ElementInfo *EI) { 48 // Create RSExportType corresponded to the @T first and then verify 49 50 llvm::StringRef TypeName; 51 RSExportType *ET = NULL; 52 53 if (!Initialized) 54 Init(); 55 56 assert(EI != NULL && "Element info not found"); 57 58 if (!RSExportType::NormalizeType(T, TypeName)) 59 return NULL; 60 61 switch (T->getTypeClass()) { 62 case clang::Type::Builtin: 63 case clang::Type::Pointer: { 64 assert(EI->vsize == 1 && "Element not a primitive class (please check " 65 "your macro)"); 66 RSExportPrimitiveType *EPT = 67 RSExportPrimitiveType::Create(Context, 68 T, 69 TypeName, 70 EI->kind, 71 EI->normalized); 72 // Verify 73 assert(EI->type == EPT->getType() && "Element has unexpected type"); 74 ET = EPT; 75 break; 76 } 77 case clang::Type::ExtVector: { 78 assert(EI->vsize > 1 && "Element not a vector class (please check your " 79 "macro)"); 80 RSExportVectorType *EVT = 81 RSExportVectorType::Create(Context, 82 static_cast<clang::ExtVectorType*>( 83 T->getCanonicalTypeInternal() 84 .getTypePtr()), 85 TypeName, 86 EI->kind, 87 EI->normalized); 88 // Verify 89 assert(EI->type == EVT->getType() && "Element has unexpected type"); 90 assert(EI->vsize == EVT->getNumElement() && "Element has unexpected size " 91 "of vector"); 92 ET = EVT; 93 break; 94 } 95 default: { 96 // TODO(zonr): warn that type is not exportable 97 fprintf(stderr, "RSExportElement::Create : type '%s' is not exportable\n", 98 T->getTypeClassName()); 99 break; 100 } 101 } 102 103 return ET; 104} 105 106RSExportType *RSExportElement::CreateFromDecl(RSContext *Context, 107 const clang::DeclaratorDecl *DD) { 108 const clang::Type* T = RSExportType::GetTypeOfDecl(DD); 109 const clang::Type* CT = GET_CANONICAL_TYPE(T); 110 const ElementInfo* EI = NULL; 111 112 // Note: RS element like rs_pixel_rgb elements are either in the type of 113 // primitive or vector. 114 if ((CT->getTypeClass() != clang::Type::Builtin) && 115 (CT->getTypeClass() != clang::Type::ExtVector)) { 116 return RSExportType::Create(Context, T); 117 } 118 119 // Following the typedef chain to see whether it's an element name like 120 // rs_pixel_rgb or its alias (via typedef). 121 while (T != CT) { 122 if (T->getTypeClass() != clang::Type::Typedef) { 123 break; 124 } else { 125 const clang::TypedefType *TT = static_cast<const clang::TypedefType*>(T); 126 const clang::TypedefDecl *TD = TT->getDecl(); 127 EI = GetElementInfo(TD->getName()); 128 if (EI != NULL) 129 break; 130 131 T = TD->getUnderlyingType().getTypePtr(); 132 } 133 } 134 135 if (EI == NULL) { 136 return RSExportType::Create(Context, T); 137 } else { 138 return RSExportElement::Create(Context, T, EI); 139 } 140} 141 142const RSExportElement::ElementInfo * 143RSExportElement::GetElementInfo(const llvm::StringRef &Name) { 144 if (!Initialized) 145 Init(); 146 147 ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name); 148 if (I == ElementInfoMap.end()) 149 return NULL; 150 else 151 return I->getValue(); 152} 153