//===----------------------------------------------------------------------===//
#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"
&& TypeBitWidth == rhs.TypeBitWidth);
}
-std::ostream &
-TargetAlignElem::dump(std::ostream &os) const {
- return os << AlignType
- << TypeBitWidth
- << ":" << (int) (ABIAlign * 8)
- << ":" << (int) (PrefAlign * 8);
-}
-
const TargetAlignElem TargetData::InvalidAlignmentElem =
TargetAlignElem::get((AlignTypeEnum) -1, 0, 0, 0);
: Alignments[BestMatchIdx].PrefAlign;
}
-typedef DenseMap<const StructType*, StructLayout*>LayoutInfoTy;
+namespace {
+
+class StructLayoutMap : public AbstractTypeUser {
+ typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy;
+ 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 = cast<const StructType>(OldTy);
+ LayoutInfoTy::iterator Iter = LayoutInfo.find(STy);
+ Iter->second->~StructLayout();
+ free(Iter->second);
+ LayoutInfo.erase(Iter);
+ 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 = cast<const StructType>(AbsTy);
+ LayoutInfoTy::iterator Iter = LayoutInfo.find(STy);
+ Iter->second->~StructLayout();
+ free(Iter->second);
+ LayoutInfo.erase(Iter);
+ AbsTy->removeAbstractTypeUser(this);
+ }
+
+public:
+ virtual ~StructLayoutMap() {
+ // Remove any layouts.
+ for (LayoutInfoTy::iterator
+ I = LayoutInfo.begin(), E = LayoutInfo.end(); I != E; ++I) {
+ const Type *Key = I->first;
+ StructLayout *Value = I->second;
+
+ if (Key->isAbstract())
+ Key->removeAbstractTypeUser(this);
+
+ Value->~StructLayout();
+ free(Value);
+ }
+ }
+
+ void InvalidateEntry(const StructType *Ty) {
+ LayoutInfoTy::iterator I = LayoutInfo.find(Ty);
+ if (I == LayoutInfo.end()) return;
-TargetData::~TargetData() {
- if (!LayoutMap)
- return;
-
- // Remove any layouts for this TD.
- LayoutInfoTy &TheMap = *static_cast<LayoutInfoTy*>(LayoutMap);
- for (LayoutInfoTy::iterator I = TheMap.begin(), E = TheMap.end(); I != E; ) {
I->second->~StructLayout();
free(I->second);
- TheMap.erase(I++);
+ LayoutInfo.erase(I);
+
+ if (Ty->isAbstract())
+ Ty->removeAbstractTypeUser(this);
}
-
- delete static_cast<LayoutInfoTy*>(LayoutMap);
+
+ StructLayout *&operator[](const StructType *STy) {
+ return LayoutInfo[STy];
+ }
+
+ // for debugging...
+ virtual void dump() const {}
+};
+
+} // end anonymous namespace
+
+TargetData::~TargetData() {
+ delete static_cast<StructLayoutMap*>(LayoutMap);
}
const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
if (!LayoutMap)
- LayoutMap = static_cast<void*>(new LayoutInfoTy());
+ LayoutMap = new StructLayoutMap();
- LayoutInfoTy &TheMap = *static_cast<LayoutInfoTy*>(LayoutMap);
-
- StructLayout *&SL = TheMap[Ty];
+ StructLayoutMap *STM = static_cast<StructLayoutMap*>(LayoutMap);
+ StructLayout *&SL = (*STM)[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.
SL = L;
new (L) StructLayout(Ty, *this);
+
+ if (Ty->isAbstract())
+ Ty->addAbstractTypeUser(STM);
+
return L;
}
void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
if (!LayoutMap) return; // No cache.
- LayoutInfoTy* LayoutInfo = static_cast<LayoutInfoTy*>(LayoutMap);
- LayoutInfoTy::iterator I = LayoutInfo->find(Ty);
- if (I == LayoutInfo->end()) return;
-
- I->second->~StructLayout();
- free(I->second);
- LayoutInfo->erase(I);
+ StructLayoutMap *STM = static_cast<StructLayoutMap*>(LayoutMap);
+ STM->InvalidateEntry(Ty);
}
-
std::string TargetData::getStringRepresentation() const {
std::string Result;
raw_string_ostream OS(Result);