slang_rs_export_type.cpp revision 6315f76e3cc6ff2d012d1183a0b030d4ff0dc808
1#include "slang_rs_export_type.h"
2
3#include <vector>
4
5#include "llvm/Type.h"
6#include "llvm/DerivedTypes.h"
7
8#include "llvm/ADT/StringExtras.h"
9#include "llvm/Target/TargetData.h"
10
11#include "clang/AST/RecordLayout.h"
12
13#include "slang_rs_context.h"
14#include "slang_rs_export_element.h"
15
16using namespace slang;
17
18/****************************** RSExportType ******************************/
19bool RSExportType::NormalizeType(const clang::Type *&T,
20                                 llvm::StringRef &TypeName) {
21  llvm::SmallPtrSet<const clang::Type*, 8> SPS =
22      llvm::SmallPtrSet<const clang::Type*, 8>();
23
24  if ((T = RSExportType::TypeExportable(T, SPS)) == NULL)
25    // TODO(zonr): warn that type not exportable.
26    return false;
27
28  // Get type name
29  TypeName = RSExportType::GetTypeName(T);
30  if (TypeName.empty())
31    // TODO(zonr): warning that the type is unnamed.
32    return false;
33
34  return true;
35}
36
37const clang::Type
38*RSExportType::GetTypeOfDecl(const clang::DeclaratorDecl *DD) {
39  if (DD && DD->getTypeSourceInfo()) {
40    clang::QualType T = DD->getTypeSourceInfo()->getType();
41    if (T.isNull())
42      return NULL;
43    else
44      return T.getTypePtr();
45  }
46  return NULL;
47}
48
49llvm::StringRef RSExportType::GetTypeName(const clang::Type* T) {
50  T = GET_CANONICAL_TYPE(T);
51  if (T == NULL)
52    return llvm::StringRef();
53
54  switch (T->getTypeClass()) {
55    case clang::Type::Builtin: {
56      const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
57
58      switch (BT->getKind()) {
59        // Compiler is smart enough to optimize following *big if branches*
60        // since they all become "constant comparison" after macro expansion
61#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type)       \
62        case builtin_type: {                                    \
63          if (type == RSExportPrimitiveType::DataTypeFloat32)           \
64            return "float";                                             \
65          else if (type == RSExportPrimitiveType::DataTypeFloat64)      \
66            return "double";                                            \
67          else if (type == RSExportPrimitiveType::DataTypeUnsigned8)    \
68            return "uchar";                                             \
69          else if (type == RSExportPrimitiveType::DataTypeUnsigned16)   \
70            return "ushort";                                            \
71          else if (type == RSExportPrimitiveType::DataTypeUnsigned32)   \
72            return "uint";                                              \
73          else if (type == RSExportPrimitiveType::DataTypeSigned8)      \
74            return "char";                                              \
75          else if (type == RSExportPrimitiveType::DataTypeSigned16)     \
76            return "short";                                             \
77          else if (type == RSExportPrimitiveType::DataTypeSigned32)     \
78            return "int";                                               \
79          else if (type == RSExportPrimitiveType::DataTypeSigned64)     \
80            return "long";                                              \
81          else if (type == RSExportPrimitiveType::DataTypeBoolean)      \
82            return "bool";                                              \
83          else                                                          \
84            assert(false && "Unknow data type of supported builtin");   \
85          break;                                                        \
86        }
87#include "slang_rs_export_type_support.inc"
88
89          default: {
90            assert(false && "Unknown data type of the builtin");
91            break;
92          }
93        }
94      break;
95    }
96    case clang::Type::Record: {
97      const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
98      llvm::StringRef Name = RD->getName();
99      if (Name.empty()) {
100          if (RD->getTypedefForAnonDecl() != NULL)
101            Name = RD->getTypedefForAnonDecl()->getName();
102
103          if (Name.empty())
104            // Try to find a name from redeclaration (i.e. typedef)
105            for (clang::TagDecl::redecl_iterator RI = RD->redecls_begin(),
106                     RE = RD->redecls_end();
107                 RI != RE;
108                 RI++) {
109              assert(*RI != NULL && "cannot be NULL object");
110
111              Name = (*RI)->getName();
112              if (!Name.empty())
113                break;
114            }
115      }
116      return Name;
117    }
118    case clang::Type::Pointer: {
119      // "*" plus pointee name
120      const clang::Type *PT = GET_POINTEE_TYPE(T);
121      llvm::StringRef PointeeName;
122      if (NormalizeType(PT, PointeeName)) {
123        char *Name = new char[ 1 /* * */ + PointeeName.size() + 1 ];
124        Name[0] = '*';
125        memcpy(Name + 1, PointeeName.data(), PointeeName.size());
126        Name[PointeeName.size() + 1] = '\0';
127        return Name;
128      }
129      break;
130    }
131    case clang::Type::ConstantArray: {
132      const clang::ConstantArrayType *ECT =
133          UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
134      return RSExportConstantArrayType::GetTypeName(ECT);
135      break;
136    }
137    case clang::Type::ExtVector: {
138      const clang::ExtVectorType *EVT =
139          UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
140      return RSExportVectorType::GetTypeName(EVT);
141      break;
142    }
143    default: {
144      break;
145    }
146  }
147
148  return llvm::StringRef();
149}
150
151const clang::Type *RSExportType::TypeExportable(
152    const clang::Type *T,
153    llvm::SmallPtrSet<const clang::Type*, 8>& SPS) {
154  // Normalize first
155  if ((T = GET_CANONICAL_TYPE(T)) == NULL)
156    return NULL;
157
158  if (SPS.count(T))
159    return T;
160
161  switch (T->getTypeClass()) {
162    case clang::Type::Builtin: {
163      const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
164
165      switch (BT->getKind()) {
166#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type)       \
167        case builtin_type:
168#include "slang_rs_export_type_support.inc"
169        {
170          return T;
171        }
172        default: {
173          return NULL;
174        }
175      }
176      // Never be here
177    }
178    case clang::Type::Record: {
179      if (RSExportPrimitiveType::GetRSObjectType(T) !=
180          RSExportPrimitiveType::DataTypeUnknown)
181        return T;  // RS object type, no further checks are needed
182
183      // Check internal struct
184      const clang::RecordDecl *RD = T->getAsStructureType()->getDecl();
185      if (RD != NULL)
186        RD = RD->getDefinition();
187
188      // Fast check
189      if (RD->hasFlexibleArrayMember() || RD->hasObjectMember())
190        return NULL;
191
192      // Insert myself into checking set
193      SPS.insert(T);
194
195      // Check all element
196      for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
197               FE = RD->field_end();
198           FI != FE;
199           FI++) {
200        const clang::Type *FT = GetTypeOfDecl(*FI);
201        FT = GET_CANONICAL_TYPE(FT);
202
203        if (!TypeExportable(FT, SPS))
204          // TODO(zonr): warn that is's an unsupported field type
205          return NULL;
206      }
207
208      return T;
209    }
210    case clang::Type::Pointer: {
211      const clang::PointerType *PT = UNSAFE_CAST_TYPE(clang::PointerType, T);
212      const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
213
214      if ((PointeeType->getTypeClass() != clang::Type::Pointer) &&
215         (TypeExportable(PointeeType, SPS) == NULL) )
216        return NULL;
217      else
218        return T;
219    }
220
221    case clang::Type::ConstantArray: {
222      const clang::ConstantArrayType *ECT =
223          UNSAFE_CAST_TYPE(clang::ConstantArrayType, T);
224      // No longer only support 2x2, 3x3 and 4x4 arrays
225      // if (ECT->getNumElements() != 4 &&
226      //     ECT->getNumElements() != 9 &&
227      //     ECT->getNumElements() != 16)
228      //  return NULL;
229
230      // Check base element type
231      const clang::Type *ElementType = GET_CONSTANT_ARRAY_ELEMENT_TYPE(ECT);
232
233      if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
234          (TypeExportable(ElementType, SPS) == NULL))
235        return NULL;
236      else
237        return T;
238    }
239    case clang::Type::ExtVector: {
240      const clang::ExtVectorType *EVT =
241          UNSAFE_CAST_TYPE(clang::ExtVectorType, T);
242      // Only vector with size 2, 3 and 4 are supported.
243      if (EVT->getNumElements() < 2 || EVT->getNumElements() > 4)
244        return NULL;
245
246      // Check base element type
247      const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
248
249      if ((ElementType->getTypeClass() != clang::Type::Builtin) ||
250          (TypeExportable(ElementType, SPS) == NULL))
251        return NULL;
252      else
253        return T;
254    }
255    default: {
256      return NULL;
257    }
258  }
259}
260
261RSExportType *RSExportType::Create(RSContext *Context,
262                                   const clang::Type *T,
263                                   const llvm::StringRef &TypeName) {
264  // Lookup the context to see whether the type was processed before.
265  // Newly created RSExportType will insert into context
266  // in RSExportType::RSExportType()
267  RSContext::export_type_iterator ETI = Context->findExportType(TypeName);
268
269  if (ETI != Context->export_types_end())
270    return ETI->second;
271
272  RSExportType *ET = NULL;
273  switch (T->getTypeClass()) {
274    case clang::Type::Record: {
275      RSExportPrimitiveType::DataType dt =
276          RSExportPrimitiveType::GetRSObjectType(TypeName);
277      switch (dt) {
278        case RSExportPrimitiveType::DataTypeUnknown: {  // User-defined types
279          ET = RSExportRecordType::Create(Context,
280                                          T->getAsStructureType(),
281                                          TypeName);
282          break;
283        }
284        case RSExportPrimitiveType::DataTypeRSMatrix2x2:
285        case RSExportPrimitiveType::DataTypeRSMatrix3x3:
286        case RSExportPrimitiveType::DataTypeRSMatrix4x4: {
287          const clang::RecordType *RT =
288              static_cast<const clang::RecordType*> (T);
289          const clang::RecordDecl *RD = RT->getDecl();
290          RD = RD->getDefinition();
291          clang::RecordDecl::field_iterator FI = RD->field_begin();
292          clang::FieldDecl *FD = *FI;
293          const clang::Type *FT = RSExportType::GetTypeOfDecl(FD);
294          ET = RSExportConstantArrayType::Create(
295              Context,
296              static_cast<const clang::ConstantArrayType*> (FT),
297              TypeName);
298          break;
299        }
300        default: {
301          ET = RSExportPrimitiveType::Create(Context, T, TypeName);
302          break;
303        }
304      }
305      break;
306    }
307    case clang::Type::Builtin: {
308      ET = RSExportPrimitiveType::Create(Context, T, TypeName);
309      break;
310    }
311    case clang::Type::Pointer: {
312      ET = RSExportPointerType::Create(Context,
313                                       UNSAFE_CAST_TYPE(clang::PointerType, T),
314                                       TypeName);
315      // Free the name (allocated in RSExportType::GetTypeName)
316      delete [] TypeName.data();
317      break;
318    }
319    case clang::Type::ConstantArray: {
320      ET = RSExportConstantArrayType::Create(
321          Context,
322          UNSAFE_CAST_TYPE(clang::ConstantArrayType, T),
323          TypeName);
324      break;
325    }
326    case clang::Type::ExtVector: {
327      ET = RSExportVectorType::Create(Context,
328                                      UNSAFE_CAST_TYPE(clang::ExtVectorType, T),
329                                      TypeName);
330      break;
331    }
332    default: {
333      // TODO(zonr): warn that type is not exportable.
334      fprintf(stderr,
335              "RSExportType::Create : type '%s' is not exportable\n",
336              T->getTypeClassName());
337      break;
338    }
339  }
340
341  return ET;
342}
343
344RSExportType *RSExportType::Create(RSContext *Context, const clang::Type *T) {
345  llvm::StringRef TypeName;
346  if (NormalizeType(T, TypeName))
347    return Create(Context, T, TypeName);
348  else
349    return NULL;
350}
351
352RSExportType *RSExportType::CreateFromDecl(RSContext *Context,
353                                           const clang::VarDecl *VD) {
354  return RSExportType::Create(Context, GetTypeOfDecl(VD));
355}
356
357size_t RSExportType::GetTypeStoreSize(const RSExportType *ET) {
358  return ET->getRSContext()->getTargetData()->getTypeStoreSize(
359      ET->getLLVMType());
360}
361
362size_t RSExportType::GetTypeAllocSize(const RSExportType *ET) {
363  if (ET->getClass() == RSExportType::ExportClassRecord)
364    return static_cast<const RSExportRecordType*>(ET)->getAllocSize();
365  else
366    return ET->getRSContext()->getTargetData()->getTypeAllocSize(
367        ET->getLLVMType());
368}
369
370RSExportType::RSExportType(RSContext *Context, const llvm::StringRef &Name)
371    : mContext(Context),
372      // Make a copy on Name since data of @Name which is stored in ASTContext
373      // will be destroyed later
374      mName(Name.data(), Name.size()),
375      mLLVMType(NULL) {
376  // TODO(zonr): Need to check whether the insertion is successful or not.
377  Context->insertExportType(Name, this);
378  return;
379}
380
381/************************** RSExportPrimitiveType **************************/
382RSExportPrimitiveType::RSObjectTypeMapTy
383*RSExportPrimitiveType::RSObjectTypeMap = NULL;
384
385llvm::Type *RSExportPrimitiveType::RSObjectLLVMType = NULL;
386
387bool RSExportPrimitiveType::IsPrimitiveType(const clang::Type *T) {
388  if ((T != NULL) && (T->getTypeClass() == clang::Type::Builtin))
389    return true;
390  else
391    return false;
392}
393
394RSExportPrimitiveType::DataType
395RSExportPrimitiveType::GetRSObjectType(const llvm::StringRef &TypeName) {
396  if (TypeName.empty())
397    return DataTypeUnknown;
398
399  if (RSObjectTypeMap == NULL) {
400    RSObjectTypeMap = new RSObjectTypeMapTy(16);
401
402#define USE_ELEMENT_DATA_TYPE
403#define DEF_RS_OBJECT_TYPE(type, name)                                  \
404    RSObjectTypeMap->GetOrCreateValue(name, GET_ELEMENT_DATA_TYPE(type));
405#include "slang_rs_export_element_support.inc"
406  }
407
408  RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
409  if (I == RSObjectTypeMap->end())
410    return DataTypeUnknown;
411  else
412    return I->getValue();
413}
414
415RSExportPrimitiveType::DataType
416RSExportPrimitiveType::GetRSObjectType(const clang::Type *T) {
417  T = GET_CANONICAL_TYPE(T);
418  if ((T == NULL) || (T->getTypeClass() != clang::Type::Record))
419    return DataTypeUnknown;
420
421  return GetRSObjectType( RSExportType::GetTypeName(T) );
422}
423
424const size_t
425RSExportPrimitiveType::SizeOfDataTypeInBits[
426    RSExportPrimitiveType::DataTypeMax + 1] = {
427  16,  // DataTypeFloat16
428  32,  // DataTypeFloat32
429  64,  // DataTypeFloat64
430  8,   // DataTypeSigned8
431  16,  // DataTypeSigned16
432  32,  // DataTypeSigned32
433  64,  // DataTypeSigned64
434  8,   // DataTypeUnsigned8
435  16,  // DataTypeUnsigned16
436  32,  // DataTypeUnsigned32
437  64,  // DataTypeUnSigned64
438  1,   // DataTypeBoolean
439
440  16,  // DataTypeUnsigned565
441  16,  // DataTypeUnsigned5551
442  16,  // DataTypeUnsigned4444
443
444  128,  // DataTypeRSMatrix2x2
445  288,  // DataTypeRSMatrix3x3
446  512,  // DataTypeRSMatrix4x4
447
448  32,  // DataTypeRSElement
449  32,  // DataTypeRSType
450  32,  // DataTypeRSAllocation
451  32,  // DataTypeRSSampler
452  32,  // DataTypeRSScript
453  32,  // DataTypeRSMesh
454  32,  // DataTypeRSProgramFragment
455  32,  // DataTypeRSProgramVertex
456  32,  // DataTypeRSProgramRaster
457  32,  // DataTypeRSProgramStore
458  32,  // DataTypeRSFont
459  0
460};
461
462size_t RSExportPrimitiveType::GetSizeInBits(const RSExportPrimitiveType *EPT) {
463  assert(((EPT->getType() >= DataTypeFloat32) &&
464          (EPT->getType() < DataTypeMax)) &&
465         "RSExportPrimitiveType::GetSizeInBits : unknown data type");
466  return SizeOfDataTypeInBits[ static_cast<int>(EPT->getType()) ];
467}
468
469RSExportPrimitiveType::DataType
470RSExportPrimitiveType::GetDataType(const clang::Type *T) {
471  if (T == NULL)
472    return DataTypeUnknown;
473
474  switch (T->getTypeClass()) {
475    case clang::Type::Builtin: {
476      const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType, T);
477      switch (BT->getKind()) {
478#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type)       \
479        case builtin_type: {                                    \
480          return type;                                          \
481          break;                                                \
482        }
483#include "slang_rs_export_type_support.inc"
484
485        // The size of types Long, ULong and WChar depend on platform so we
486        // abandon the support to them. Type of its size exceeds 32 bits (e.g.
487        // int64_t, double, etc.): no support
488
489        default: {
490          // TODO(zonr): warn that the type is unsupported
491          fprintf(stderr, "RSExportPrimitiveType::GetDataType : built-in type "
492                          "has no corresponding data type for built-in type");
493          break;
494        }
495      }
496      break;
497    }
498
499    case clang::Type::Record: {
500      // must be RS object type
501      return RSExportPrimitiveType::GetRSObjectType(T);
502      break;
503    }
504
505    default: {
506      fprintf(stderr, "RSExportPrimitiveType::GetDataType : type '%s' is not "
507                      "supported primitive type", T->getTypeClassName());
508      break;
509    }
510  }
511
512  return DataTypeUnknown;
513}
514
515RSExportPrimitiveType
516*RSExportPrimitiveType::Create(RSContext *Context,
517                               const clang::Type *T,
518                               const llvm::StringRef &TypeName,
519                               DataKind DK,
520                               bool Normalized) {
521  DataType DT = GetDataType(T);
522
523  if ((DT == DataTypeUnknown) || TypeName.empty())
524    return NULL;
525  else
526    return new RSExportPrimitiveType(Context, TypeName, DT, DK, Normalized);
527}
528
529RSExportPrimitiveType *RSExportPrimitiveType::Create(RSContext *Context,
530                                                     const clang::Type *T,
531                                                     DataKind DK) {
532  llvm::StringRef TypeName;
533  if (RSExportType::NormalizeType(T, TypeName) && IsPrimitiveType(T))
534    return Create(Context, T, TypeName, DK);
535  else
536    return NULL;
537}
538
539RSExportType::ExportClass RSExportPrimitiveType::getClass() const {
540  return RSExportType::ExportClassPrimitive;
541}
542
543const llvm::Type *RSExportPrimitiveType::convertToLLVMType() const {
544  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
545
546  if (isRSObjectType()) {
547    // struct {
548    //   int *p;
549    // } __attribute__((packed, aligned(pointer_size)))
550    //
551    // which is
552    //
553    // <{ [1 x i32] }> in LLVM
554    //
555    if (RSObjectLLVMType == NULL) {
556      std::vector<const llvm::Type *> Elements;
557      Elements.push_back(llvm::ArrayType::get(llvm::Type::getInt32Ty(C), 1));
558      RSObjectLLVMType = llvm::StructType::get(C, Elements, true);
559    }
560    return RSObjectLLVMType;
561  }
562
563  switch (mType) {
564    case DataTypeFloat32: {
565      return llvm::Type::getFloatTy(C);
566      break;
567    }
568    case DataTypeFloat64: {
569      return llvm::Type::getDoubleTy(C);
570      break;
571    }
572    case DataTypeBoolean: {
573      return llvm::Type::getInt1Ty(C);
574      break;
575    }
576    case DataTypeSigned8:
577    case DataTypeUnsigned8: {
578      return llvm::Type::getInt8Ty(C);
579      break;
580    }
581    case DataTypeSigned16:
582    case DataTypeUnsigned16:
583    case DataTypeUnsigned565:
584    case DataTypeUnsigned5551:
585    case DataTypeUnsigned4444: {
586      return llvm::Type::getInt16Ty(C);
587      break;
588    }
589    case DataTypeSigned32:
590    case DataTypeUnsigned32: {
591      return llvm::Type::getInt32Ty(C);
592      break;
593    }
594    case DataTypeSigned64: {
595    // case DataTypeUnsigned64:
596      return llvm::Type::getInt64Ty(C);
597      break;
598    }
599    default: {
600      assert(false && "Unknown data type");
601    }
602  }
603
604  return NULL;
605}
606
607/**************************** RSExportPointerType ****************************/
608
609const clang::Type *RSExportPointerType::IntegerType = NULL;
610
611RSExportPointerType
612*RSExportPointerType::Create(RSContext *Context,
613                             const clang::PointerType *PT,
614                             const llvm::StringRef &TypeName) {
615  const clang::Type *PointeeType = GET_POINTEE_TYPE(PT);
616  const RSExportType *PointeeET;
617
618  if (PointeeType->getTypeClass() != clang::Type::Pointer) {
619    PointeeET = RSExportType::Create(Context, PointeeType);
620  } else {
621    // Double or higher dimension of pointer, export as int*
622    assert(IntegerType != NULL && "Built-in integer type is not set");
623    PointeeET = RSExportPrimitiveType::Create(Context, IntegerType);
624  }
625
626  if (PointeeET == NULL) {
627    fprintf(stderr, "Failed to create type for pointee");
628    return NULL;
629  }
630
631  return new RSExportPointerType(Context, TypeName, PointeeET);
632}
633
634RSExportType::ExportClass RSExportPointerType::getClass() const {
635  return RSExportType::ExportClassPointer;
636}
637
638const llvm::Type *RSExportPointerType::convertToLLVMType() const {
639  const llvm::Type *PointeeType = mPointeeType->getLLVMType();
640  return llvm::PointerType::getUnqual(PointeeType);
641}
642
643/************************* RSExportConstantArrayType *************************/
644llvm::StringRef
645RSExportConstantArrayType::GetTypeName(const clang::ConstantArrayType *CT) {
646  llvm::APInt i = CT->getSize();
647  if (i == 4) {
648    return llvm::StringRef("rs_matrix2x2");
649  } else if (i == 9) {
650    return llvm::StringRef("rs_matrix3x3");
651  } else if (i == 16) {
652    return llvm::StringRef("rs_matrix4x4");
653  }
654  return llvm::StringRef();
655}
656
657RSExportConstantArrayType
658*RSExportConstantArrayType::Create(RSContext *Context,
659                                   const clang::ConstantArrayType *CT,
660                                   const llvm::StringRef &TypeName,
661                                   DataKind DK,
662                                   bool Normalized) {
663  assert(CT != NULL && CT->getTypeClass() == clang::Type::ConstantArray);
664
665  int64_t Size = CT->getSize().getSExtValue();
666  RSExportPrimitiveType::DataType DT;
667  if (Size == 4) {
668    DT = RSExportPrimitiveType::DataTypeRSMatrix2x2;
669  } else if (Size == 9) {
670    DT = RSExportPrimitiveType::DataTypeRSMatrix3x3;
671  } else if (Size == 16) {
672    DT = RSExportPrimitiveType::DataTypeRSMatrix4x4;
673  } else {
674    fprintf(stderr, "RSExportConstantArrayType::Create : unsupported base "
675                    "element type\n");
676    return NULL;
677  }
678
679  return new RSExportConstantArrayType(Context,
680                                       TypeName,
681                                       DT,
682                                       DK,
683                                       Normalized,
684                                       Size);
685}
686
687RSExportType::ExportClass RSExportConstantArrayType::getClass() const {
688  return RSExportType::ExportClassConstantArray;
689}
690
691const llvm::Type *RSExportConstantArrayType::convertToLLVMType() const {
692  llvm::LLVMContext &C = getRSContext()->getLLVMContext();
693  const llvm::Type *typ;
694  switch (getType()) {
695    case DataTypeFloat32:
696    case DataTypeRSMatrix2x2:
697    case DataTypeRSMatrix3x3:
698    case DataTypeRSMatrix4x4: {
699      typ = llvm::Type::getFloatTy(C);
700      break;
701    }
702    case DataTypeFloat64: {
703      typ = llvm::Type::getDoubleTy(C);
704      break;
705    }
706    case DataTypeBoolean: {
707      typ = llvm::Type::getInt1Ty(C);
708      break;
709    }
710    case DataTypeSigned8:
711    case DataTypeUnsigned8: {
712      typ = llvm::Type::getInt8Ty(C);
713      break;
714    }
715    case DataTypeSigned16:
716    case DataTypeUnsigned16:
717    case DataTypeUnsigned565:
718    case DataTypeUnsigned5551:
719    case DataTypeUnsigned4444: {
720      typ = llvm::Type::getInt16Ty(C);
721      break;
722    }
723    case DataTypeSigned32:
724    case DataTypeUnsigned32: {
725      typ = llvm::Type::getInt32Ty(C);
726      break;
727    }
728    case DataTypeSigned64: {
729    //case DataTypeUnsigned64:
730      typ = llvm::Type::getInt64Ty(C);
731      break;
732    }
733    default: {
734      assert(false && "Unknown data type");
735      break;
736    }
737  }
738  return llvm::ArrayType::get(typ, mNumElement);
739}
740
741/***************************** RSExportVectorType *****************************/
742const char* RSExportVectorType::VectorTypeNameStore[][3] = {
743  /* 0 */ { "char2",      "char3",    "char4" },
744  /* 1 */ { "uchar2",     "uchar3",   "uchar4" },
745  /* 2 */ { "short2",     "short3",   "short4" },
746  /* 3 */ { "ushort2",    "ushort3",  "ushort4" },
747  /* 4 */ { "int2",       "int3",     "int4" },
748  /* 5 */ { "uint2",      "uint3",    "uint4" },
749  /* 6 */ { "float2",     "float3",   "float4" },
750  /* 7 */ { "double2",    "double3",  "double4" },
751  /* 8 */ { "long2",      "long3",    "long4" },
752};
753
754llvm::StringRef
755RSExportVectorType::GetTypeName(const clang::ExtVectorType *EVT) {
756  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
757
758  if ((ElementType->getTypeClass() != clang::Type::Builtin))
759    return llvm::StringRef();
760
761  const clang::BuiltinType *BT = UNSAFE_CAST_TYPE(clang::BuiltinType,
762                                                  ElementType);
763  const char **BaseElement = NULL;
764
765  switch (BT->getKind()) {
766    // Compiler is smart enough to optimize following *big if branches* since
767    // they all become "constant comparison" after macro expansion
768#define SLANG_RS_SUPPORT_BUILTIN_TYPE(builtin_type, type)       \
769    case builtin_type: {                                                \
770      if (type == RSExportPrimitiveType::DataTypeSigned8) \
771        BaseElement = VectorTypeNameStore[0];                           \
772      else if (type == RSExportPrimitiveType::DataTypeUnsigned8) \
773        BaseElement = VectorTypeNameStore[1];                           \
774      else if (type == RSExportPrimitiveType::DataTypeSigned16) \
775        BaseElement = VectorTypeNameStore[2];                           \
776      else if (type == RSExportPrimitiveType::DataTypeUnsigned16) \
777        BaseElement = VectorTypeNameStore[3];                           \
778      else if (type == RSExportPrimitiveType::DataTypeSigned32) \
779        BaseElement = VectorTypeNameStore[4];                           \
780      else if (type == RSExportPrimitiveType::DataTypeUnsigned32) \
781        BaseElement = VectorTypeNameStore[5];                           \
782      else if (type == RSExportPrimitiveType::DataTypeFloat32) \
783        BaseElement = VectorTypeNameStore[6];                           \
784      else if (type == RSExportPrimitiveType::DataTypeFloat64) \
785        BaseElement = VectorTypeNameStore[7];                           \
786      else if (type == RSExportPrimitiveType::DataTypeSigned64) \
787        BaseElement = VectorTypeNameStore[8];                           \
788      else if (type == RSExportPrimitiveType::DataTypeBoolean) \
789        BaseElement = VectorTypeNameStore[0];                          \
790      break;  \
791    }
792#include "slang_rs_export_type_support.inc"
793    default: {
794      return llvm::StringRef();
795    }
796  }
797
798  if ((BaseElement != NULL) &&
799      (EVT->getNumElements() > 1) &&
800      (EVT->getNumElements() <= 4))
801    return BaseElement[EVT->getNumElements() - 2];
802  else
803    return llvm::StringRef();
804}
805
806RSExportVectorType *RSExportVectorType::Create(RSContext *Context,
807                                               const clang::ExtVectorType *EVT,
808                                               const llvm::StringRef &TypeName,
809                                               DataKind DK,
810                                               bool Normalized) {
811  assert(EVT != NULL && EVT->getTypeClass() == Type::ExtVector);
812
813  const clang::Type *ElementType = GET_EXT_VECTOR_ELEMENT_TYPE(EVT);
814  RSExportPrimitiveType::DataType DT =
815      RSExportPrimitiveType::GetDataType(ElementType);
816
817  if (DT != RSExportPrimitiveType::DataTypeUnknown)
818    return new RSExportVectorType(Context,
819                                  TypeName,
820                                  DT,
821                                  DK,
822                                  Normalized,
823                                  EVT->getNumElements());
824  else
825    fprintf(stderr, "RSExportVectorType::Create : unsupported base element "
826                    "type\n");
827  return NULL;
828}
829
830RSExportType::ExportClass RSExportVectorType::getClass() const {
831  return RSExportType::ExportClassVector;
832}
833
834const llvm::Type *RSExportVectorType::convertToLLVMType() const {
835  const llvm::Type *ElementType = RSExportPrimitiveType::convertToLLVMType();
836  return llvm::VectorType::get(ElementType, getNumElement());
837}
838
839/**************************** RSExportRecordType ****************************/
840RSExportRecordType *RSExportRecordType::Create(RSContext *Context,
841                                               const clang::RecordType *RT,
842                                               const llvm::StringRef &TypeName,
843                                               bool mIsArtificial) {
844  assert(RT != NULL && RT->getTypeClass() == Type::Record);
845
846  const clang::RecordDecl *RD = RT->getDecl();
847  assert(RD->isStruct());
848
849  RD = RD->getDefinition();
850  if (RD == NULL) {
851    // TODO(zonr): warn that actual struct definition isn't declared in this
852    //             moudle.
853    fprintf(stderr, "RSExportRecordType::Create : this struct is not defined "
854                    "in this module.");
855    return NULL;
856  }
857
858  RSExportRecordType *ERT = new RSExportRecordType(Context,
859                                                   TypeName,
860                                                   RD->
861                                                   hasAttr<clang::PackedAttr>(),
862                                                   mIsArtificial);
863  unsigned int Index = 0;
864
865  for (clang::RecordDecl::field_iterator FI = RD->field_begin(),
866           FE = RD->field_end();
867       FI != FE;
868       FI++, Index++) {
869#define FAILED_CREATE_FIELD(err)    do {         \
870      if (*err)                                                          \
871        fprintf(stderr, \
872                "RSExportRecordType::Create : failed to create field (%s)\n", \
873                err);                                                   \
874      delete ERT;                                                       \
875      return NULL;                                                      \
876    } while (false)
877
878    // FIXME: All fields should be primitive type
879    assert((*FI)->getKind() == clang::Decl::Field);
880    clang::FieldDecl *FD = *FI;
881
882    // We don't support bit field
883    //
884    // TODO(zonr): allow bitfield with size 8, 16, 32
885    if (FD->isBitField())
886      FAILED_CREATE_FIELD("bit field is not supported");
887
888    // Type
889    RSExportType *ET = RSExportElement::CreateFromDecl(Context, FD);
890
891    if (ET != NULL)
892      ERT->mFields.push_back(new Field(ET, FD->getName(), ERT, Index));
893    else
894      FAILED_CREATE_FIELD(FD->getName().str().c_str());
895#undef FAILED_CREATE_FIELD
896  }
897
898  const clang::ASTRecordLayout &ASTRL =
899      Context->getASTContext()->getASTRecordLayout(RD);
900  ERT->AllocSize =
901      (ASTRL.getSize() > ASTRL.getDataSize()) ?
902      (ASTRL.getSize() >> 3) :
903      (ASTRL.getDataSize() >> 3);
904
905  return ERT;
906}
907
908RSExportType::ExportClass RSExportRecordType::getClass() const {
909  return RSExportType::ExportClassRecord;
910}
911
912const llvm::Type *RSExportRecordType::convertToLLVMType() const {
913  std::vector<const llvm::Type*> FieldTypes;
914
915  for (const_field_iterator FI = fields_begin(),
916           FE = fields_end();
917       FI != FE;
918       FI++) {
919    const Field *F = *FI;
920    const RSExportType *FET = F->getType();
921
922    FieldTypes.push_back(FET->getLLVMType());
923  }
924
925  return llvm::StructType::get(getRSContext()->getLLVMContext(),
926                               FieldTypes,
927                               mIsPacked);
928}
929
930/************************* RSExportRecordType::Field *************************/
931size_t RSExportRecordType::Field::getOffsetInParent() const {
932  // Struct layout obtains below will be cached by LLVM
933  const llvm::StructLayout *SL =
934      mParent->getRSContext()->getTargetData()->getStructLayout(
935          static_cast<const llvm::StructType*>(mParent->getLLVMType()));
936  return SL->getElementOffset(mIndex);
937}
938