Compute and cache information about the storage size and layout
of structures.  This information is machine-dependent.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@222 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h
index 31a35b6..b5eba11 100644
--- a/include/llvm/DerivedTypes.h
+++ b/include/llvm/DerivedTypes.h
@@ -12,7 +12,11 @@
 #define LLVM_DERIVED_TYPES_H
 
 #include "llvm/Type.h"
-#include <vector>
+#include "llvm/Codegen/TargetMachine.h"
+#include "vector"
+
+class TargetMachine;
+
 
 // Future derived types: SIMD packed format
 
@@ -81,12 +85,20 @@
 class StructType : public Type {
 public:
   typedef vector<const Type*> ElementTypes;
+
 private:
   ElementTypes ETypes;
-
+  struct StructSizeAndOffsetInfo {
+    int storageSize;			// -1 until the value is computd
+    vector<int> memberOffsets;		// -1 until values are computed 
+    const TargetMachine* targetInfo;
+  }
+  *layoutCache;
+  
+private:
   StructType(const StructType &);                   // Do not implement
   const StructType &operator=(const StructType &);  // Do not implement
-
+  
 protected:
   // This should really be private, but it squelches a bogus warning
   // from GCC to make them protected:  warning: `class StructType' only 
@@ -94,6 +106,10 @@
 
   // Private ctor - Only can be created by a static member...
   StructType(const vector<const Type*> &Types, const string &Name);
+  
+  // Reset cached info so it will be computed when first requested
+  void ResetCachedInfo() const;
+  
 public:
 
   inline const ElementTypes &getElementTypes() const { return ETypes; }
@@ -101,9 +117,65 @@
   static const StructType *get(const ElementTypes &Params) {
     return getStructType(Params);
   }
+  unsigned int		   getStorageSize(const TargetMachine& tmi) const;
+  unsigned int		   getElementOffset(int i, const TargetMachine& tmi) const;
 };
 
 
+inline unsigned int
+StructType::getStorageSize(const TargetMachine& tmi) const
+{
+  if (layoutCache->targetInfo != NULL && ! (* layoutCache->targetInfo == tmi))
+    {// target machine has changed (hey it could happen). discard cached info.
+      ResetCachedInfo();
+      layoutCache->targetInfo = &tmi;
+    }
+  
+  if (layoutCache->storageSize < 0)
+    {
+      layoutCache->storageSize = tmi.findOptimalStorageSize(this);
+      assert(layoutCache->storageSize >= 0);
+    }
+  
+  return layoutCache->storageSize;
+}
+
+
+inline unsigned int
+StructType::getElementOffset(int i, const TargetMachine& tmi) const
+{
+  if (layoutCache->targetInfo != NULL && ! (* layoutCache->targetInfo == tmi))
+    {// target machine has changed (hey it could happen). discard cached info.
+      ResetCachedInfo();
+    }
+  
+  if (layoutCache->memberOffsets[i] < 0)
+    {
+      layoutCache->targetInfo = &tmi;	// remember which target was used
+      
+      unsigned int* offsetVec = tmi.findOptimalMemberOffsets(this);
+      for (unsigned i=0, N=layoutCache->memberOffsets.size(); i < N; i++)
+	{
+	  layoutCache->memberOffsets[i] = offsetVec[i];
+	  assert(layoutCache->memberOffsets[i] >= 0);
+	}
+      delete[] offsetVec; 
+    }
+  
+  return layoutCache->memberOffsets[i];
+}
+
+
+inline void
+StructType::ResetCachedInfo() const
+{
+  layoutCache->storageSize = -1;
+  layoutCache->memberOffsets.insert(layoutCache->memberOffsets.begin(),
+				    ETypes.size(), -1);
+  layoutCache->targetInfo = NULL;
+}
+
+
 class PointerType : public Type {
 private:
   const Type *ValueType;
diff --git a/lib/VMCore/Type.cpp b/lib/VMCore/Type.cpp
index 0b272f0..ef6a892 100644
--- a/lib/VMCore/Type.cpp
+++ b/lib/VMCore/Type.cpp
@@ -143,7 +143,11 @@
 }
 
 StructType::StructType(const vector<const Type*> &Types, const string &Name) 
-  : Type(Name, StructTyID), ETypes(Types) {
+  : Type(Name, StructTyID),
+    ETypes(Types),
+    layoutCache(new StructSizeAndOffsetInfo) 
+{
+  ResetCachedInfo();
 }
 
 PointerType::PointerType(const Type *E)