diff --git a/llvm/include/llvm/DerivedTypes.h b/llvm/include/llvm/DerivedTypes.h index b9ade512cfb4..da5ad27b1f1c 100644 --- a/llvm/include/llvm/DerivedTypes.h +++ b/llvm/include/llvm/DerivedTypes.h @@ -195,9 +195,10 @@ class StructType : public CompositeType { // This is the contents of the SubClassData field. SCDB_HasBody = 1, SCDB_Packed = 2, - SCDB_IsLiteral = 4 + SCDB_IsLiteral = 4, + SCDB_IsSized = 8 }; - + /// SymbolTableEntry - For a named struct that actually has a name, this is a /// pointer to the symbol table entry (maintained by LLVMContext) for the /// struct. This is null if the type is an literal struct or if it is @@ -248,6 +249,9 @@ public: /// isOpaque - Return true if this is a type with an identity that has no body /// specified yet. These prints as 'opaque' in .ll files. bool isOpaque() const { return (getSubclassData() & SCDB_HasBody) == 0; } + + /// isSized - Return true if this is a sized type. + bool isSized() const; /// hasName - Return true if this is a named struct that has a non-empty name. bool hasName() const { return SymbolTableEntry != 0; } diff --git a/llvm/lib/VMCore/Type.cpp b/llvm/lib/VMCore/Type.cpp index 0bc4f74af216..c6f35580e158 100644 --- a/llvm/lib/VMCore/Type.cpp +++ b/llvm/lib/VMCore/Type.cpp @@ -185,16 +185,7 @@ bool Type::isSizedDerivedType() const { if (!this->isStructTy()) return false; - // Opaque structs have no size. - if (cast(this)->isOpaque()) - return false; - - // Okay, our struct is sized if all of the elements are. - for (subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I) - if (!(*I)->isSized()) - return false; - - return true; + return cast(this)->isSized(); } //===----------------------------------------------------------------------===// @@ -579,6 +570,26 @@ StructType *StructType::create(StringRef Name, Type *type, ...) { return llvm::StructType::create(Ctx, StructFields, Name); } +bool StructType::isSized() const { + if ((getSubclassData() & SCDB_IsSized) != 0) + return true; + if (isOpaque()) + return false; + + // Okay, our struct is sized if all of the elements are, but if one of the + // elements is opaque, the struct isn't sized *yet*, but may become sized in + // the future, so just bail out without caching. + for (element_iterator I = element_begin(), E = element_end(); I != E; ++I) + if (!(*I)->isSized()) + return false; + + // Here we cheat a bit and cast away const-ness. The goal is to memoize when + // we find a sized type, as types can only move from opaque to sized, not the + // other way. + const_cast(this)->setSubclassData( + getSubclassData() | SCDB_IsSized); + return true; +} StringRef StructType::getName() const { assert(!isLiteral() && "Literal structs never have names");