blob: c5c66ec3ffe51d5b7505c332e74e85d23e14cbdf [file] [log] [blame]
Shih-wei Liao462aefd2010-06-04 15:32:04 -07001#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 */