Shih-wei Liao | 462aefd | 2010-06-04 15:32:04 -0700 | [diff] [blame] | 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 | |
| 11 | namespace slang { |
| 12 | |
| 13 | bool RSExportElement::Initialized = false; |
| 14 | RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap; |
| 15 | |
| 16 | void 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 | |
| 42 | RSExportType* 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 | |
| 102 | RSExportType* 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 | |
| 132 | const 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 */ |