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 {
diff --git a/slang_rs_export_type.h b/slang_rs_export_type.h
index 60685cb..6dcaa44 100644
--- a/slang_rs_export_type.h
+++ b/slang_rs_export_type.h
@@ -110,6 +110,11 @@
// (all of these information are target dependent) without dealing with these
// by ourselves.
virtual const llvm::Type *convertToLLVMType() const = 0;
+ // Record type may recursively referece its type definition. We need a
+ // temporary type setup before the type construction gets done.
+ inline void setAbstractLLVMType(const llvm::Type *LLVMType) const {
+ mLLVMType = LLVMType;
+ }
virtual ~RSExportType() {}
public:
@@ -138,7 +143,7 @@
inline const std::string &getName() const { return mName; }
- virtual void keep();
+ virtual bool keep();
virtual bool equals(const RSExportable *E) const;
}; // RSExportType
@@ -154,7 +159,6 @@
#define ENUM_RS_DATA_TYPE(type, cname, bits) \
DataType ## type,
#include "RSDataTypeEnums.inc"
-#undef ENUM_RS_DATA_TYPE
DataTypeMax
} DataType;
@@ -165,7 +169,6 @@
#define ENUM_RS_DATA_KIND(kind) \
, DataKind ## kind
#include "RSDataKindEnums.inc"
-#undef ENUM_RS_DATA_KIND
} DataKind;
private:
@@ -261,7 +264,7 @@
public:
static const clang::Type *IntegerType;
- virtual void keep();
+ virtual bool keep();
inline const RSExportType *getPointeeType() const { return mPointeeType; }
@@ -367,7 +370,7 @@
inline unsigned getSize() const { return mSize; }
inline const RSExportType *getElementType() const { return mElementType; }
- virtual void keep();
+ virtual bool keep();
virtual bool equals(const RSExportable *E) const;
};
@@ -447,7 +450,7 @@
inline bool isArtificial() const { return mIsArtificial; }
inline size_t getAllocSize() const { return mAllocSize; }
- virtual void keep();
+ virtual bool keep();
virtual bool equals(const RSExportable *E) const;
~RSExportRecordType() {
diff --git a/slang_rs_exportable.cpp b/slang_rs_exportable.cpp
index 53ab33d..6e60582 100644
--- a/slang_rs_exportable.cpp
+++ b/slang_rs_exportable.cpp
@@ -18,10 +18,12 @@
using namespace slang;
-void RSExportable::keep() {
+bool RSExportable::keep() {
+ if (isKeep())
+ return false;
// Invalidate associated Context.
mContext = NULL;
- return;
+ return true;
}
bool RSExportable::equals(const RSExportable *E) const {
diff --git a/slang_rs_exportable.h b/slang_rs_exportable.h
index c3d0215..f336745 100644
--- a/slang_rs_exportable.h
+++ b/slang_rs_exportable.h
@@ -48,7 +48,8 @@
// When keep() is invoked, mKeep will set to true and the associated RSContext
// won't free this RSExportable object in its destructor. The deallcation
// responsibility is then transferred to the object who invoked this function.
- virtual void keep();
+ // Return false if the exportable is kept or failed to keep.
+ virtual bool keep();
inline bool isKeep() const { return (mContext == NULL); }
virtual bool equals(const RSExportable *E) const;
diff --git a/slang_rs_spec_table.cpp b/slang_rs_spec_table.cpp
index 6ef4e64..f08b28d 100644
--- a/slang_rs_spec_table.cpp
+++ b/slang_rs_spec_table.cpp
@@ -188,6 +188,7 @@
DataTypes[i]->getTypeName(),
DataTypes[i]->getTypePragmaName(),
DataTypes[i]->getSizeInBit());
+ printf("#undef ENUM_RS_DATA_TYPE");
return 0;
}
@@ -203,6 +204,7 @@
ClangBuilitinsMap[i]->getBuiltinTypeKind(),
ClangBuilitinsMap[i]->getDataType()->getTypeName(),
ClangBuilitinsMap[i]->getDataType()->getTypePragmaName());
+ printf("#undef ENUM_SUPPORT_BUILTIN_TYPE");
return 0;
}
@@ -217,6 +219,7 @@
printf("ENUM_RS_OBJECT_TYPE(%s, \"%s\")\n",
DataTypes[i]->getTypeName(),
DataTypes[i]->getTypePragmaName());
+ printf("#undef ENUM_RS_OBJECT_TYPE");
return 0;
}
@@ -228,6 +231,7 @@
unsigned NumDataKinds) {
for (unsigned i = 0; i < NumDataKinds; i++)
printf("ENUM_RS_DATA_KIND(%s)\n", DataKinds[i]->getKindName());
+ printf("#undef ENUM_RS_DATA_KIND");
return 0;
}
@@ -244,6 +248,7 @@
DataElements[i]->getDataType()->getTypeName(),
((DataElements[i]->isNormal()) ? "true" : "false"),
DataElements[i]->getVectorSize());
+ printf("#undef ENUM_RS_DATA_ELEMENT");
return 0;
}