aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/TargetData.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2009-11-18 01:03:56 +0000
committerBill Wendling <isanbard@gmail.com>2009-11-18 01:03:56 +0000
commit5eea34267376e76aceb53b6c3dfead816021258f (patch)
tree642ec53ac5486505dbc7587657803d280d8f488b /lib/Target/TargetData.cpp
parent3dbb9e64d6e9d1e8bf16f75ebe4fe59ffdf93dd3 (diff)
downloadexternal_llvm-5eea34267376e76aceb53b6c3dfead816021258f.zip
external_llvm-5eea34267376e76aceb53b6c3dfead816021258f.tar.gz
external_llvm-5eea34267376e76aceb53b6c3dfead816021258f.tar.bz2
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
Diffstat (limited to 'lib/Target/TargetData.cpp')
-rw-r--r--lib/Target/TargetData.cpp140
1 files changed, 116 insertions, 24 deletions
diff --git a/lib/Target/TargetData.cpp b/lib/Target/TargetData.cpp
index c2fbd3f..fc71bc3 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 DenseMap<const StructType*, StructLayout*>LayoutInfoTy;
+typedef DenseMap<const StructType*, StructLayout*> LayoutInfoTy;
-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++);
+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<const StructType>(OldTy);
+ if (!STy) {
+ OldTy->removeAbstractTypeUser(this);
+ return;
+ }
+
+ StructLayout *SL = LayoutInfo[STy];
+ if (SL) {
+ SL->~StructLayout();
+ free(SL);
+ LayoutInfo[STy] = NULL;
+ }
+
+ OldTy->removeAbstractTypeUser(this);
}
-
- delete static_cast<LayoutInfoTy*>(LayoutMap);
+
+ /// 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<const StructType>(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<const StructType>(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() {
+ delete LayoutMap;
}
const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
if (!LayoutMap)
- LayoutMap = static_cast<void*>(new LayoutInfoTy());
-
- LayoutInfoTy &TheMap = *static_cast<LayoutInfoTy*>(LayoutMap);
+ LayoutMap = new StructLayoutMap();
- 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<LayoutInfoTy*>(LayoutMap);
- LayoutInfoTy::iterator I = LayoutInfo->find(Ty);
- if (I == LayoutInfo->end()) return;
+ DenseMap<const StructType*, StructLayout*>::iterator I = LayoutMap->find(Ty);
+ if (I == LayoutMap->end()) return;
I->second->~StructLayout();
free(I->second);
- LayoutInfo->erase(I);
+ LayoutMap->erase(I);
}