From 5eea34267376e76aceb53b6c3dfead816021258f Mon Sep 17 00:00:00 2001 From: Bill Wendling Date: Wed, 18 Nov 2009 01:03:56 +0000 Subject: [PATCH] The llvm-gcc front-end and the pass manager use two separate TargetData objects. This is probably not confined to *just* these two things. Anyway, the llvm-gcc front-end may look up the structure layout information for an abstract type. That information will be stored into a table with the FE's TD. Instruction combine can come along and also ask for information on that abstract type, but for a separate TD (the one associated with the pass manager). After the type is refined, the old structure layout information in the pass manager's TD file is out of date. If a new type is allocated in the same space as the old-unrefined type, then the structure type information in the pass manager's TD file will be wrong, but won't know it. Fix this by making the TD's structure type information an abstract type user. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@89176 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Target/TargetData.h | 5 +- lib/Target/TargetData.cpp | 140 +++++++++++++++++++++++++------ 2 files changed, 119 insertions(+), 26 deletions(-) diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h index b663d4792ba..e1d052edbe1 100644 --- a/include/llvm/Target/TargetData.h +++ b/include/llvm/Target/TargetData.h @@ -30,6 +30,7 @@ class Type; class IntegerType; class StructType; class StructLayout; +class StructLayoutMap; class GlobalVariable; class LLVMContext; @@ -84,8 +85,8 @@ private: /// type and bit width were not found in the SmallVector. static const TargetAlignElem InvalidAlignmentElem; - // Opaque pointer for the StructType -> StructLayout map. - mutable void *LayoutMap; + // The StructType -> StructLayout map. + mutable StructLayoutMap *LayoutMap; //! Set/initialize target alignments void setAlignment(AlignTypeEnum align_type, unsigned char abi_align, diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp index c2fbd3f0e61..fc71bc3ab1f 100644 --- a/lib/Target/TargetData.cpp +++ b/lib/Target/TargetData.cpp @@ -17,9 +17,9 @@ //===----------------------------------------------------------------------===// #include "llvm/Target/TargetData.h" -#include "llvm/Module.h" -#include "llvm/DerivedTypes.h" #include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" #include "llvm/Support/GetElementPtrTypeIterator.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/ManagedStatic.h" @@ -323,37 +323,130 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, : Alignments[BestMatchIdx].PrefAlign; } -typedef DenseMapLayoutInfoTy; +typedef DenseMap LayoutInfoTy; + +namespace llvm { + +class StructLayoutMap : public AbstractTypeUser { + LayoutInfoTy LayoutInfo; + + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *) { + const StructType *STy = dyn_cast(OldTy); + if (!STy) { + OldTy->removeAbstractTypeUser(this); + return; + } + + StructLayout *SL = LayoutInfo[STy]; + if (SL) { + SL->~StructLayout(); + free(SL); + LayoutInfo[STy] = NULL; + } + + OldTy->removeAbstractTypeUser(this); + } + + /// typeBecameConcrete - The other case which AbstractTypeUsers must be aware + /// of is when a type makes the transition from being abstract (where it has + /// clients on its AbstractTypeUsers list) to concrete (where it does not). + /// This method notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) { + const StructType *STy = dyn_cast(AbsTy); + if (!STy) { + AbsTy->removeAbstractTypeUser(this); + return; + } + + StructLayout *SL = LayoutInfo[STy]; + if (SL) { + SL->~StructLayout(); + free(SL); + LayoutInfo[STy] = NULL; + } + + AbsTy->removeAbstractTypeUser(this); + } + + bool insert(const Type *Ty) { + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(this); + return true; + } + +public: + virtual ~StructLayoutMap() { + // Remove any layouts. + for (LayoutInfoTy::iterator + I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) + if (StructLayout *SL = I->second) { + SL->~StructLayout(); + free(SL); + } + } + + inline LayoutInfoTy::iterator begin() { + return LayoutInfo.begin(); + } + inline LayoutInfoTy::iterator end() { + return LayoutInfo.end(); + } + inline LayoutInfoTy::const_iterator begin() const { + return LayoutInfo.begin(); + } + inline LayoutInfoTy::const_iterator end() const { + return LayoutInfo.end(); + } + + LayoutInfoTy::iterator find(const StructType *&Val) { + return LayoutInfo.find(Val); + } + LayoutInfoTy::const_iterator find(const StructType *&Val) const { + return LayoutInfo.find(Val); + } + + bool erase(const StructType *&Val) { + return LayoutInfo.erase(Val); + } + bool erase(LayoutInfoTy::iterator I) { + return LayoutInfo.erase(I); + } + + StructLayout *&operator[](const Type *Key) { + const StructType *STy = dyn_cast(Key); + assert(STy && "Trying to access the struct layout map with a non-struct!"); + insert(STy); + return LayoutInfo[STy]; + } + + // for debugging... + virtual void dump() const {} +}; + +} // end namespace llvm TargetData::~TargetData() { - if (!LayoutMap) - return; - - // Remove any layouts for this TD. - LayoutInfoTy &TheMap = *static_cast(LayoutMap); - for (LayoutInfoTy::iterator I = TheMap.begin(), E = TheMap.end(); I != E; ) { - I->second->~StructLayout(); - free(I->second); - TheMap.erase(I++); - } - - delete static_cast(LayoutMap); + delete LayoutMap; } const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { if (!LayoutMap) - LayoutMap = static_cast(new LayoutInfoTy()); + LayoutMap = new StructLayoutMap(); - LayoutInfoTy &TheMap = *static_cast(LayoutMap); - - StructLayout *&SL = TheMap[Ty]; + StructLayout *&SL = (*LayoutMap)[Ty]; if (SL) return SL; // Otherwise, create the struct layout. Because it is variable length, we // malloc it, then use placement new. int NumElts = Ty->getNumElements(); StructLayout *L = - (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1)*sizeof(uint64_t)); + (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1) * sizeof(uint64_t)); // Set SL before calling StructLayout's ctor. The ctor could cause other // entries to be added to TheMap, invalidating our reference. @@ -370,13 +463,12 @@ const StructLayout *TargetData::getStructLayout(const StructType *Ty) const { void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const { if (!LayoutMap) return; // No cache. - LayoutInfoTy* LayoutInfo = static_cast(LayoutMap); - LayoutInfoTy::iterator I = LayoutInfo->find(Ty); - if (I == LayoutInfo->end()) return; + DenseMap::iterator I = LayoutMap->find(Ty); + if (I == LayoutMap->end()) return; I->second->~StructLayout(); free(I->second); - LayoutInfo->erase(I); + LayoutMap->erase(I); }