aboutsummaryrefslogtreecommitdiff
path: root/CodeGen/CodeGenTypes.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2008-02-05 08:06:13 +0000
committerChris Lattner <sabre@nondot.org>2008-02-05 08:06:13 +0000
commitd86e6bc7ab4388a578daf46e7c76be9122a25072 (patch)
tree00e1cb94e691418b35d2fe71f1ed5283671af17f /CodeGen/CodeGenTypes.cpp
parent9153f73d1035ddcaac5a253ac2a0570e04e22b1f (diff)
rewrite some of the type refinement code to eliminate dangling pointers
simplify the code and generally make it more robust. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46745 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'CodeGen/CodeGenTypes.cpp')
-rw-r--r--CodeGen/CodeGenTypes.cpp112
1 files changed, 57 insertions, 55 deletions
diff --git a/CodeGen/CodeGenTypes.cpp b/CodeGen/CodeGenTypes.cpp
index 97fc61d4ac..2e10cfc971 100644
--- a/CodeGen/CodeGenTypes.cpp
+++ b/CodeGen/CodeGenTypes.cpp
@@ -91,29 +91,6 @@ CodeGenTypes::~CodeGenTypes() {
CGRecordLayouts.clear();
}
-/// isOpaqueTypeDefinition - Return true if LT is a llvm::OpaqueType
-/// and T is tag definition. This helper routine does not check
-/// relationship between T and LT.
-static bool isOpaqueTypeDefinition(QualType T, const llvm::Type *LT) {
- if (const PointerType* PTy = T->getAsPointerType()) {
- return
- isOpaqueTypeDefinition(PTy->getPointeeType(),
- cast<llvm::PointerType>(LT)->getElementType());
- }
- if (!isa<llvm::OpaqueType>(LT))
- return false;
-
- const clang::Type &Ty = *T.getCanonicalType();
- if (Ty.getTypeClass() == Type::Tagged) {
- const TagType &TT = cast<TagType>(Ty);
- const TagDecl *TD = TT.getDecl();
- if (TD->isDefinition())
- return true;
- }
-
- return false;
-}
-
/// ConvertType - Convert the specified type to its LLVM form.
const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
// See if type is already cached.
@@ -121,7 +98,7 @@ const llvm::Type *CodeGenTypes::ConvertType(QualType T) {
I = TypeHolderMap.find(T.getTypePtr());
// If type is found in map and this is not a definition for a opaque
// place holder type then use it. Otherwise convert type T.
- if (I != TypeHolderMap.end() && !isOpaqueTypeDefinition(T, I->second.get()))
+ if (I != TypeHolderMap.end())
return I->second.get();
const llvm::Type *ResultType = ConvertNewType(T);
@@ -148,6 +125,31 @@ const llvm::Type *CodeGenTypes::ConvertTypeForMem(QualType T) {
}
+/// ForceTypeCompilation - When we find the definition for a type, we require
+/// it to be recompiled, to update the lazy understanding of what it is in our
+/// maps.
+void CodeGenTypes::ForceTypeCompilation(QualType T) {
+ const TagDecl *TD = cast<TagType>(T)->getDecl();
+
+ // Remember the opaque LLVM type for this tagdecl.
+ llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI =
+ TagDeclTypes.find(TD);
+ llvm::PATypeHolder OpaqueHolder = TDTI->second;
+ assert(isa<llvm::OpaqueType>(OpaqueHolder.get()) &&
+ "Forcing compilation of non-opaque type?");
+
+ // Remove it from TagDeclTypes so that it will be regenerated.
+ TagDeclTypes.erase(TDTI);
+
+ const llvm::Type *NT = ConvertNewType(T);
+
+ // If getting the type didn't itself refine it, refine it to its actual type
+ // now.
+ if (llvm::OpaqueType *OT = dyn_cast<llvm::OpaqueType>(OpaqueHolder.get()))
+ OT->refineAbstractTypeTo(NT);
+}
+
+
const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
const clang::Type &Ty = *T.getCanonicalType();
@@ -268,7 +270,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
case Type::ASQual:
return ConvertType(cast<ASQualType>(Ty).getBaseType());
- break;
case Type::ObjCInterface:
assert(0 && "FIXME: add missing functionality here");
@@ -285,40 +286,36 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
case Type::Tagged:
const TagType &TT = cast<TagType>(Ty);
const TagDecl *TD = TT.getDecl();
- llvm::Type *ResultType = TagDeclTypes[TD];
+ llvm::DenseMap<const TagDecl*, llvm::PATypeHolder>::iterator TDTI =
+ TagDeclTypes.find(TD);
// If corresponding llvm type is not a opaque struct type
// then use it.
- if (ResultType && !isOpaqueTypeDefinition(T, ResultType))
- return ResultType;
+ if (TDTI != TagDeclTypes.end() && // Don't have a type?
+ // Have a type, but it was opaque before and now we have a definition.
+ (!isa<llvm::OpaqueType>(TDTI->second.get()) || !TD->isDefinition()))
+ return TDTI->second;
+
+ llvm::Type *ResultType = 0;
if (!TD->isDefinition()) {
- ResultType = TagDeclTypes[TD] = llvm::OpaqueType::get();
+ ResultType = llvm::OpaqueType::get();
+ TagDeclTypes.insert(std::make_pair(TD, ResultType));
} else if (TD->getKind() == Decl::Enum) {
+ // Don't bother storing enums in TagDeclTypes.
return ConvertType(cast<EnumDecl>(TD)->getIntegerType());
} else if (TD->getKind() == Decl::Struct) {
const RecordDecl *RD = cast<const RecordDecl>(TD);
// If this is nested record and this RecordDecl is already under
// process then return associated OpaqueType for now.
- llvm::DenseMap<const RecordDecl *, llvm::Type *>::iterator
- OpaqueI = RecordTypesToResolve.find(RD);
- if (OpaqueI != RecordTypesToResolve.end())
- return OpaqueI->second;
-
- llvm::OpaqueType *OpaqueTy = NULL;
- if (ResultType)
- OpaqueTy = dyn_cast<llvm::OpaqueType>(ResultType);
- if (!OpaqueTy) {
- // Create new OpaqueType now for later use.
- // FIXME: This creates a lot of opaque types, most of them are not
- // needed. Reevaluate this when performance analyis finds tons of
- // opaque types.
- OpaqueTy = llvm::OpaqueType::get();
- TypeHolderMap.insert(std::make_pair(T.getTypePtr(),
- llvm::PATypeHolder(OpaqueTy)));
+ if (TDTI == TagDeclTypes.end()) {
+ // Create new OpaqueType now for later use in case this is a recursive
+ // type. This will later be refined to the actual type.
+ ResultType = llvm::OpaqueType::get();
+ TagDeclTypes.insert(std::make_pair(TD, ResultType));
+ TypeHolderMap.insert(std::make_pair(T.getTypePtr(), ResultType));
}
- RecordTypesToResolve[RD] = OpaqueTy;
// Layout fields.
RecordOrganizer RO(*this);
@@ -331,16 +328,19 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
// Get llvm::StructType.
CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
RO.getPaddingFields());
- ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
+ ResultType = RLI->getLLVMType();
+ TagDeclTypes.insert(std::make_pair(TD, ResultType));
CGRecordLayouts[TD] = RLI;
- // Refine any OpaqueType associated with this RecordDecl.
- OpaqueTy->refineAbstractTypeTo(ResultType);
- OpaqueI = RecordTypesToResolve.find(RD);
- assert (OpaqueI != RecordTypesToResolve.end()
- && "Expected RecordDecl in RecordTypesToResolve");
- RecordTypesToResolve.erase(OpaqueI);
+ // Refining away Opaque could cause ResultType to become invalidated.
+ // Keep it in a happy little type holder to handle this.
+ llvm::PATypeHolder Holder(ResultType);
+
+ // Refine the OpaqueType associated with this RecordDecl.
+ cast<llvm::OpaqueType>(TagDeclTypes.find(TD)->second.get())
+ ->refineAbstractTypeTo(ResultType);
+ ResultType = Holder.get();
} else if (TD->getKind() == Decl::Union) {
const RecordDecl *RD = cast<const RecordDecl>(TD);
// Just use the largest element of the union, breaking ties with the
@@ -355,11 +355,13 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
// Get llvm::StructType.
CGRecordLayout *RLI = new CGRecordLayout(RO.getLLVMType(),
RO.getPaddingFields());
- ResultType = TagDeclTypes[TD] = RLI->getLLVMType();
+ ResultType = RLI->getLLVMType();
+ TagDeclTypes.insert(std::make_pair(TD, ResultType));
CGRecordLayouts[TD] = RLI;
} else {
std::vector<const llvm::Type*> Fields;
- ResultType = TagDeclTypes[TD] = llvm::StructType::get(Fields);
+ ResultType = llvm::StructType::get(Fields);
+ TagDeclTypes.insert(std::make_pair(TD, ResultType));
}
} else {
assert(0 && "FIXME: Implement tag decl kind!");