Fix the asmprinter so that a globalvalue can specify an explicit alignment
[oota-llvm.git] / lib / Target / TargetData.cpp
index 696bdc2d76304f6b199c0c8480dd2d7697f3be69..301e8c12ab452d46b83a1d4509b923144d71466c 100644 (file)
@@ -35,6 +35,7 @@ namespace {
   // Register the default SparcV9 implementation...
   RegisterPass<TargetData> X("targetdata", "Target Data Layout");
 }
+char TargetData::ID = 0;
 
 //===----------------------------------------------------------------------===//
 // Support for StructLayout
@@ -94,7 +95,7 @@ unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
 
 TargetAlignElem
 TargetAlignElem::get(AlignTypeEnum align_type, unsigned char abi_align,
-                     unsigned char pref_align, short bit_width) {
+                     unsigned char pref_align, uint32_t bit_width) {
   TargetAlignElem retval;
   retval.AlignType = align_type;
   retval.ABIAlign = abi_align;
@@ -184,14 +185,8 @@ void TargetData::init(const std::string &TargetDescription) {
   
   while (!temp.empty()) {
     std::string token = getToken(temp, "-");
-    
     std::string arg0 = getToken(token, ":");
     const char *p = arg0.c_str();
-    AlignTypeEnum align_type;
-    short size;
-    unsigned char abi_align;
-    unsigned char pref_align;
-
     switch(*p) {
     case 'E':
       LittleEndian = false;
@@ -210,12 +205,12 @@ void TargetData::init(const std::string &TargetDescription) {
     case 'v':
     case 'f':
     case 'a': {
-      align_type = (*p == 'i' ? INTEGER_ALIGN :
-                    (*p == 'f' ? FLOAT_ALIGN :
-                     (*p == 'v' ? VECTOR_ALIGN : AGGREGATE_ALIGN)));
-      size = (short) atoi(++p);
-      abi_align = atoi(getToken(token, ":").c_str()) / 8;
-      pref_align = atoi(getToken(token, ":").c_str()) / 8;
+      AlignTypeEnum align_type = 
+        (*p == 'i' ? INTEGER_ALIGN : (*p == 'f' ? FLOAT_ALIGN :
+           (*p == 'v' ? VECTOR_ALIGN : AGGREGATE_ALIGN)));
+      uint32_t size = (uint32_t) atoi(++p);
+      unsigned char abi_align = atoi(getToken(token, ":").c_str()) / 8;
+      unsigned char pref_align = atoi(getToken(token, ":").c_str()) / 8;
       if (pref_align == 0)
         pref_align = abi_align;
       setAlignment(align_type, abi_align, pref_align, size);
@@ -227,13 +222,14 @@ void TargetData::init(const std::string &TargetDescription) {
   }
 }
 
-TargetData::TargetData(const Module *M) {
+TargetData::TargetData(const Module *M) 
+  : ImmutablePass((intptr_t)&ID) {
   init(M->getDataLayout());
 }
 
 void
 TargetData::setAlignment(AlignTypeEnum align_type, unsigned char abi_align,
-                         unsigned char pref_align, short bit_width) {
+                         unsigned char pref_align, uint32_t bit_width) {
   for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
     if (Alignments[i].AlignType == align_type &&
         Alignments[i].TypeBitWidth == bit_width) {
@@ -250,10 +246,11 @@ TargetData::setAlignment(AlignTypeEnum align_type, unsigned char abi_align,
 
 /// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or 
 /// preferred if ABIInfo = false) the target wants for the specified datatype.
-unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, short BitWidth,
-                                      bool ABIInfo) const {
+unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, 
+                                      uint32_t BitWidth, bool ABIInfo) const {
   // Check to see if we have an exact match and remember the best match we see.
   int BestMatchIdx = -1;
+  int LargestInt = -1;
   for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
     if (Alignments[i].AlignType == AlignType &&
         Alignments[i].TypeBitWidth == BitWidth)
@@ -271,14 +268,30 @@ unsigned TargetData::getAlignmentInfo(AlignTypeEnum AlignType, short BitWidth,
             Alignments[BestMatchIdx].TypeBitWidth < BitWidth)
           BestMatchIdx = i;
       }
+    } else if (AlignType == INTEGER_ALIGN && 
+               Alignments[i].AlignType == INTEGER_ALIGN) {
+      // The "best match" for integers is the smallest size that is larger than
+      // the BitWidth requested.
+      if (Alignments[i].TypeBitWidth > BitWidth && (BestMatchIdx == -1 || 
+           Alignments[i].TypeBitWidth < Alignments[BestMatchIdx].TypeBitWidth))
+        BestMatchIdx = i;
+      // However, if there isn't one that's larger, then we must use the
+      // largest one we have (see below)
+      if (LargestInt == -1 || 
+          Alignments[i].TypeBitWidth > Alignments[LargestInt].TypeBitWidth)
+        LargestInt = i;
     }
-    
-    // FIXME: handle things like i37.
   }
 
+  // For integers, if we didn't find a best match, use the largest one found.
+  if (BestMatchIdx == -1)
+    BestMatchIdx = LargestInt;
+
   // Okay, we didn't find an exact solution.  Fall back here depending on what
   // is being looked for.
   assert(BestMatchIdx != -1 && "Didn't find alignment info for this datatype!");
+
+  // Since we got a "best match" index, just return it.
   return ABIInfo ? Alignments[BestMatchIdx].ABIAlign
                  : Alignments[BestMatchIdx].PrefAlign;
 }
@@ -331,7 +344,7 @@ const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
 
   // Otherwise, create the struct layout.  Because it is variable length, we 
   // malloc it, then use placement new.
-  unsigned NumElts = Ty->getNumElements();
+  int NumElts = Ty->getNumElements();
   StructLayout *L =
     (StructLayout *)malloc(sizeof(StructLayout)+(NumElts-1)*sizeof(uint64_t));
   
@@ -389,7 +402,7 @@ uint64_t TargetData::getTypeSize(const Type *Ty) const {
     unsigned char Alignment;
     Size = getTypeSize(ATy->getElementType());
     Alignment = getABITypeAlignment(ATy->getElementType());
-    unsigned AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
+    uint64_t AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
     return AlignedSize*ATy->getNumElements();
   }
   case Type::StructTyID: {
@@ -407,8 +420,14 @@ uint64_t TargetData::getTypeSize(const Type *Ty) const {
       return 4;
     } else if (BitWidth <= 64) {
       return 8;
-    } else
-      assert(0 && "Integer types > 64 bits not supported.");
+    } else {
+      // The size of this > 64 bit type is chosen as a multiple of the
+      // preferred alignment of the largest "native" size the target supports. 
+      // We first obtain the the alignment info for this type and then compute
+      // the next largest multiple of that size.
+      uint64_t size = getAlignmentInfo(INTEGER_ALIGN, BitWidth, false) * 8;
+      return (((BitWidth / (size)) + (BitWidth % size != 0)) * size) / 8;
+    }
     break;
   }
   case Type::VoidTyID:
@@ -476,9 +495,15 @@ unsigned char TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {
   case Type::DoubleTyID:
     AlignType = FLOAT_ALIGN;
     break;
-  case Type::VectorTyID:
-    AlignType = VECTOR_ALIGN;
+  case Type::VectorTyID: {
+    const VectorType *VTy = cast<VectorType>(Ty);
+    // Degenerate vectors are assumed to be scalar-ized
+    if (VTy->getNumElements() == 1)
+      return getAlignment(VTy->getElementType(), abi_or_pref);
+    else
+      AlignType = VECTOR_ALIGN;
     break;
+  }
   default:
     assert(0 && "Bad type for getAlignment!!!");
     break;
@@ -524,7 +549,8 @@ uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
     TI = gep_type_begin(ptrTy, Indices, Indices+NumIndices);
   for (unsigned CurIDX = 0; CurIDX != NumIndices; ++CurIDX, ++TI) {
     if (const StructType *STy = dyn_cast<StructType>(*TI)) {
-      assert(Indices[CurIDX]->getType() == Type::Int32Ty &&"Illegal struct idx");
+      assert(Indices[CurIDX]->getType() == Type::Int32Ty &&
+             "Illegal struct idx");
       unsigned FieldNo = cast<ConstantInt>(Indices[CurIDX])->getZExtValue();
 
       // Get structure layout information...