slang_rs_export_element.cpp revision f8149d9e5a3795e9952717ee6346789a134c55c7
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::ConstantArray:
69          {
70            //XXX
71            break;
72          }
73
74        case Type::ExtVector:
75        {
76            assert(EI->vsize > 1 && "Element not a vector class (please check your macro)");
77            RSExportVectorType* EVT = RSExportVectorType::Create(Context,
78                                                                 static_cast<ExtVectorType*>(T->getCanonicalTypeInternal().getTypePtr()),
79                                                                 TypeName,
80                                                                 EI->kind,
81                                                                 EI->normalized);
82            /* verify */
83            assert(EI->type == EVT->getType() && "Element has unexpected type");
84            assert(EI->vsize == EVT->getNumElement() && "Element has unexpected size of vector");
85            ET = EVT;
86        }
87        break;
88
89        case Type::Record:
90        {
91          /* Must be RS object type */
92
93          if ( TypeName.equals(llvm::StringRef("rs_matrix2x2")) ||
94               TypeName.equals(llvm::StringRef("rs_matrix3x3")) ||
95               TypeName.equals(llvm::StringRef("rs_matrix4x4")) ) {
96
97            const clang::RecordType* RT = static_cast<const RecordType*> (T);
98            const RecordDecl* RD = RT->getDecl();
99            RD = RD->getDefinition();
100            //RSExportRecordType* ERT = new RSExportRecordType(Context, TypeName, RD->hasAttr<PackedAttr>());
101            RecordDecl::field_iterator fit = RD->field_begin();
102            FieldDecl* FD = *fit;
103            const Type* FT = RSExportType::GetTypeOfDecl(FD);
104            RSExportConstantArrayType* ECT = RSExportConstantArrayType::Create(Context, static_cast<const ConstantArrayType*> (FT), TypeName);
105            ET = ECT;
106
107            //RSExportType* FieldET = RSExportElement::CreateFromDecl(Context, FD);
108            //ERT->mFields.push_back( new Field(FieldET, FD->getName(), ERT, 0) );
109            //const ASTRecordLayout &ASTRL = Context->getASTContext()->getASTRecordLayout(RD);
110            //ERT->AllocSize = (ASTRL.getSize() > ASTRL.getDataSize()) ? (ASTRL.getSize() >> 3) : (ASTRL.getDataSize() >> 3);
111            //ET = ERT;
112
113          } else {
114            RSExportPrimitiveType* EPT = RSExportPrimitiveType::Create(Context, T, TypeName, EI->kind, EI->normalized);
115            /* verify */
116            assert(EI->type == EPT->getType() && "Element has unexpected type");
117            ET = EPT;
118          }
119        }
120        break;
121
122        default:
123            /* TODO: warning: type is not exportable */
124            printf("RSExportElement::Create : type '%s' is not exportable\n", T->getTypeClassName());
125        break;
126    }
127
128    return ET;
129}
130
131RSExportType* RSExportElement::CreateFromDecl(RSContext* Context, const DeclaratorDecl* DD) {
132    const Type* T = RSExportType::GetTypeOfDecl(DD);
133    const Type* CT = GET_CANONICAL_TYPE(T);
134    const ElementInfo* EI = NULL;
135
136    /* For rs element that's NOT like those rs_color4f..., just call Create(Context, T) without finding EI */
137    /* Note: Those rs_color4f kind of elements are either typed primitive or vector */
138    if ((CT->getTypeClass() != Type::Builtin) && (CT->getTypeClass() != Type::ExtVector) && (CT->getTypeClass() != Type::Record)) {
139        return RSExportType::Create(Context, T);
140    }
141
142    /* Iterative query the name of type to see whether it's an element name like rs_color4f or its alias (via typedef) */
143    while (T != CT) {
144        if (T->getTypeClass() != Type::Typedef) {
145            break;
146        } else {
147            const TypedefType* TT = static_cast<const TypedefType*>(T);
148            const TypedefDecl* TD = TT->getDecl();
149            EI = GetElementInfo(TD->getName());
150            if (EI != NULL)
151                break;
152
153            T = TD->getUnderlyingType().getTypePtr();
154        }
155    }
156
157    if(EI == NULL) {
158        return RSExportType::Create(Context, T);
159    } else {
160        return RSExportElement::Create(Context, T, EI);
161    }
162}
163
164const RSExportElement::ElementInfo* RSExportElement::GetElementInfo(const llvm::StringRef& Name) {
165    if(!Initialized)
166        Init();
167
168    ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
169    if(I == ElementInfoMap.end())
170        return NULL;
171    else
172        return I->getValue();
173}
174
175}   /* namespace slang */
176