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