Bug fix: support self-referential struct type.
diff --git a/slang_rs_export_type.cpp b/slang_rs_export_type.cpp
index 1028eb6..6542c5d 100644
--- a/slang_rs_export_type.cpp
+++ b/slang_rs_export_type.cpp
@@ -86,7 +86,6 @@
return cname; \
break;
#include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
default: {
assert(false && "Unknown data type of the builtin");
break;
@@ -165,7 +164,6 @@
#define ENUM_SUPPORT_BUILTIN_TYPE(builtin_type, type, cname) \
case builtin_type:
#include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
return T;
default: {
return NULL;
@@ -403,11 +401,12 @@
return;
}
-void RSExportType::keep() {
+bool RSExportType::keep() {
+ if (!RSExportable::keep())
+ return false;
// Invalidate converted LLVM type.
mLLVMType = NULL;
- RSExportable::keep();
- return;
+ return true;
}
bool RSExportType::equals(const RSExportable *E) const {
@@ -437,7 +436,6 @@
#define ENUM_RS_OBJECT_TYPE(type, cname) \
RSObjectTypeMap->GetOrCreateValue(cname, DataType ## type);
#include "RSObjectTypeEnums.inc"
-#undef ENUM_RS_OBJECT_TYPE
}
RSObjectTypeMapTy::const_iterator I = RSObjectTypeMap->find(TypeName);
@@ -460,7 +458,6 @@
#define ENUM_RS_DATA_TYPE(type, cname, bits) \
bits,
#include "RSDataTypeEnums.inc"
-#undef ENUM_RS_DATA_TYPE
0 // DataTypeMax
};
@@ -485,7 +482,6 @@
return DataType ## type; \
}
#include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
// The size of type WChar depend on platform so we abandon the support
// to them.
default: {
@@ -637,9 +633,11 @@
return llvm::PointerType::getUnqual(PointeeType);
}
-void RSExportPointerType::keep() {
+bool RSExportPointerType::keep() {
+ if (!RSExportType::keep())
+ return false;
const_cast<RSExportType*>(mPointeeType)->keep();
- RSExportType::keep();
+ return true;
}
bool RSExportPointerType::equals(const RSExportable *E) const {
@@ -672,7 +670,6 @@
break; \
}
#include "RSClangBuiltinEnums.inc"
-#undef ENUM_SUPPORT_BUILTIN_TYPE
default: {
return llvm::StringRef();
}
@@ -819,10 +816,11 @@
return llvm::ArrayType::get(mElementType->getLLVMType(), getSize());
}
-void RSExportConstantArrayType::keep() {
+bool RSExportConstantArrayType::keep() {
+ if (!RSExportType::keep())
+ return false;
const_cast<RSExportType*>(mElementType)->keep();
- RSExportType::keep();
- return;
+ return true;
}
bool RSExportConstantArrayType::equals(const RSExportable *E) const {
@@ -903,10 +901,14 @@
}
const llvm::Type *RSExportRecordType::convertToLLVMType() const {
+ // Create an opaque type since struct may reference itself recursively.
+ llvm::PATypeHolder ResultHolder =
+ llvm::OpaqueType::get(getRSContext()->getLLVMContext());
+ setAbstractLLVMType(ResultHolder.get());
+
std::vector<const llvm::Type*> FieldTypes;
- for (const_field_iterator FI = fields_begin(),
- FE = fields_end();
+ for (const_field_iterator FI = fields_begin(), FE = fields_end();
FI != FE;
FI++) {
const Field *F = *FI;
@@ -915,20 +917,27 @@
FieldTypes.push_back(FET->getLLVMType());
}
- return llvm::StructType::get(getRSContext()->getLLVMContext(),
- FieldTypes,
- mIsPacked);
+ llvm::StructType *ST = llvm::StructType::get(getRSContext()->getLLVMContext(),
+ FieldTypes,
+ mIsPacked);
+ if (ST != NULL)
+ static_cast<llvm::OpaqueType*>(ResultHolder.get())
+ ->refineAbstractTypeTo(ST);
+ else
+ return NULL;
+ return ResultHolder.get();
}
-void RSExportRecordType::keep() {
+bool RSExportRecordType::keep() {
+ if (!RSExportType::keep())
+ return false;
for (std::list<const Field*>::iterator I = mFields.begin(),
E = mFields.end();
I != E;
I++) {
const_cast<RSExportType*>((*I)->getType())->keep();
}
- RSExportType::keep();
- return;
+ return true;
}
bool RSExportRecordType::equals(const RSExportable *E) const {