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