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