blob: 718f84e87083383f9340d5360565b0fb2ad88548 [file] [log] [blame]
#include "slang_rs_context.hpp"
#include "slang_rs_export_type.hpp"
#include "slang_rs_export_element.hpp"
#include "clang/AST/Decl.h" /* for class clang::*Decl */
#include "clang/AST/Type.h" /* for class clang::*Type */
#include "clang/Basic/SourceLocation.h" /* for class clang::SourceLocation */
#include "clang/Basic/IdentifierTable.h" /* for class clang::IdentifierInfo */
namespace slang {
bool RSExportElement::Initialized = false;
RSExportElement::ElementInfoMapTy RSExportElement::ElementInfoMap;
void RSExportElement::Init() {
if(!Initialized) {
/* Initialize ElementInfoMap */
#define USE_ELEMENT_DATA_TYPE
#define USE_ELEMENT_DATA_KIND
#define DEF_ELEMENT(_name, _dk, _dt, _norm, _vsize) \
{ \
ElementInfo* EI = new ElementInfo; \
EI->kind = GET_ELEMENT_DATA_KIND(_dk); \
EI->type = GET_ELEMENT_DATA_TYPE(_dt); \
EI->normalized = _norm; \
EI->vsize = _vsize; \
\
llvm::StringRef Name(_name); \
ElementInfoMap.insert( ElementInfoMapTy::value_type::Create(Name.begin(), \
Name.end(), \
ElementInfoMap.getAllocator(), \
EI)); \
}
#include "slang_rs_export_element_support.inc"
Initialized = true;
}
return;
}
RSExportType* RSExportElement::Create(RSContext* Context, const Type* T, const ElementInfo* EI) {
/* Create RSExportType corresponded to the @T first and then verify */
llvm::StringRef TypeName;
RSExportType* ET = NULL;
if(!Initialized)
Init();
assert(EI != NULL && "Element info not found");
if(!RSExportType::NormalizeType(T, TypeName))
return NULL;
switch(T->getTypeClass()) {
case Type::Builtin:
case Type::Pointer:
{
assert(EI->vsize == 1 && "Element not a primitive class (please check your macro)");
RSExportPrimitiveType* EPT = RSExportPrimitiveType::Create(Context, T, TypeName, EI->kind, EI->normalized);
/* verify */
assert(EI->type == EPT->getType() && "Element has unexpected type");
ET = EPT;
}
break;
case Type::ConstantArray:
{
//XXX
break;
}
case Type::ExtVector:
{
assert(EI->vsize > 1 && "Element not a vector class (please check your macro)");
RSExportVectorType* EVT = RSExportVectorType::Create(Context,
static_cast<ExtVectorType*>(T->getCanonicalTypeInternal().getTypePtr()),
TypeName,
EI->kind,
EI->normalized);
/* verify */
assert(EI->type == EVT->getType() && "Element has unexpected type");
assert(EI->vsize == EVT->getNumElement() && "Element has unexpected size of vector");
ET = EVT;
}
break;
case Type::Record:
{
/* Must be RS object type */
if ( TypeName.equals(llvm::StringRef("rs_matrix2x2")) ||
TypeName.equals(llvm::StringRef("rs_matrix3x3")) ||
TypeName.equals(llvm::StringRef("rs_matrix4x4")) ) {
const clang::RecordType* RT = static_cast<const RecordType*> (T);
const RecordDecl* RD = RT->getDecl();
RD = RD->getDefinition();
//RSExportRecordType* ERT = new RSExportRecordType(Context, TypeName, RD->hasAttr<PackedAttr>());
RecordDecl::field_iterator fit = RD->field_begin();
FieldDecl* FD = *fit;
const Type* FT = RSExportType::GetTypeOfDecl(FD);
RSExportConstantArrayType* ECT = RSExportConstantArrayType::Create(Context, static_cast<const ConstantArrayType*> (FT), TypeName);
ET = ECT;
//RSExportType* FieldET = RSExportElement::CreateFromDecl(Context, FD);
//ERT->mFields.push_back( new Field(FieldET, FD->getName(), ERT, 0) );
//const ASTRecordLayout &ASTRL = Context->getASTContext()->getASTRecordLayout(RD);
//ERT->AllocSize = (ASTRL.getSize() > ASTRL.getDataSize()) ? (ASTRL.getSize() >> 3) : (ASTRL.getDataSize() >> 3);
//ET = ERT;
} else {
RSExportPrimitiveType* EPT = RSExportPrimitiveType::Create(Context, T, TypeName, EI->kind, EI->normalized);
/* verify */
assert(EI->type == EPT->getType() && "Element has unexpected type");
ET = EPT;
}
}
break;
default:
/* TODO: warning: type is not exportable */
printf("RSExportElement::Create : type '%s' is not exportable\n", T->getTypeClassName());
break;
}
return ET;
}
RSExportType* RSExportElement::CreateFromDecl(RSContext* Context, const DeclaratorDecl* DD) {
const Type* T = RSExportType::GetTypeOfDecl(DD);
const Type* CT = GET_CANONICAL_TYPE(T);
const ElementInfo* EI = NULL;
/* For rs element that's NOT like those rs_color4f..., just call Create(Context, T) without finding EI */
/* Note: Those rs_color4f kind of elements are either typed primitive or vector */
if ((CT->getTypeClass() != Type::Builtin) && (CT->getTypeClass() != Type::ExtVector) && (CT->getTypeClass() != Type::Record)) {
return RSExportType::Create(Context, T);
}
/* Iterative query the name of type to see whether it's an element name like rs_color4f or its alias (via typedef) */
while (T != CT) {
if (T->getTypeClass() != Type::Typedef) {
break;
} else {
const TypedefType* TT = static_cast<const TypedefType*>(T);
const TypedefDecl* TD = TT->getDecl();
EI = GetElementInfo(TD->getName());
if (EI != NULL)
break;
T = TD->getUnderlyingType().getTypePtr();
}
}
if(EI == NULL) {
return RSExportType::Create(Context, T);
} else {
return RSExportElement::Create(Context, T, EI);
}
}
const RSExportElement::ElementInfo* RSExportElement::GetElementInfo(const llvm::StringRef& Name) {
if(!Initialized)
Init();
ElementInfoMapTy::const_iterator I = ElementInfoMap.find(Name);
if(I == ElementInfoMap.end())
return NULL;
else
return I->getValue();
}
} /* namespace slang */