//===-- TargetData.cpp - Data size & alignment routines --------------------==//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines target properties related to datatype size/offset/alignment
// information.
//
// This structure should be created once, filled in if the defaults are not
// correct and then passed around by const&.  None of the members functions
// require modification to the object.
//
//===----------------------------------------------------------------------===//

#include "llvm/Target/TargetData.h"
#include "llvm/Module.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Constants.h"
#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringExtras.h"
#include <algorithm>
#include <cstdlib>
#include <sstream>
using namespace llvm;

// Handle the Pass registration stuff necessary to use TargetData's.
namespace {
  // Register the default SparcV9 implementation...
  RegisterPass<TargetData> X("targetdata", "Target Data Layout");
}
char TargetData::ID = 0;

//===----------------------------------------------------------------------===//
// Support for StructLayout
//===----------------------------------------------------------------------===//

StructLayout::StructLayout(const StructType *ST, const TargetData &TD) {
  StructAlignment = 0;
  StructSize = 0;
  NumElements = ST->getNumElements();

  // Loop over each of the elements, placing them in memory...
  for (unsigned i = 0, e = NumElements; i != e; ++i) {
    const Type *Ty = ST->getElementType(i);
    unsigned TyAlign;
    uint64_t TySize;
    TyAlign = (ST->isPacked() ? 1 : TD.getABITypeAlignment(Ty));
    TySize = TD.getTypeSize(Ty);

    // Add padding if necessary to make the data element aligned properly...
    if (StructSize % TyAlign != 0)
      StructSize = (StructSize/TyAlign + 1) * TyAlign;   // Add padding...

    // Keep track of maximum alignment constraint
    StructAlignment = std::max(TyAlign, StructAlignment);

    MemberOffsets[i] = StructSize;
    StructSize += TySize;                 // Consume space for this data item
  }

  // Empty structures have alignment of 1 byte.
  if (StructAlignment == 0) StructAlignment = 1;

  // Add padding to the end of the struct so that it could be put in an array
  // and all array elements would be aligned correctly.
  if (StructSize % StructAlignment != 0)
    StructSize = (StructSize/StructAlignment + 1) * StructAlignment;
}


/// getElementContainingOffset - Given a valid offset into the structure,
/// return the structure index that contains it.
unsigned StructLayout::getElementContainingOffset(uint64_t Offset) const {
  const uint64_t *SI =
    std::upper_bound(&MemberOffsets[0], &MemberOffsets[NumElements], Offset);
  assert(SI != &MemberOffsets[0] && "Offset not in structure type!");
  --SI;
  assert(*SI <= Offset && "upper_bound didn't work");
  assert((SI == &MemberOffsets[0] || *(SI-1) < Offset) &&
         (SI+1 == &MemberOffsets[NumElements] || *(SI+1) > Offset) &&
         "Upper bound didn't work!");
  return SI-&MemberOffsets[0];
}

//===----------------------------------------------------------------------===//
// TargetAlignElem, TargetAlign support
//===----------------------------------------------------------------------===//

TargetAlignElem
TargetAlignElem::get(AlignTypeEnum align_type, unsigned char abi_align,
                     unsigned char pref_align, uint32_t bit_width) {
  TargetAlignElem retval;
  retval.AlignType = align_type;
  retval.ABIAlign = abi_align;
  retval.PrefAlign = pref_align;
  retval.TypeBitWidth = bit_width;
  return retval;
}

bool
TargetAlignElem::operator==(const TargetAlignElem &rhs) const {
  return (AlignType == rhs.AlignType
          && ABIAlign == rhs.ABIAlign
          && PrefAlign == rhs.PrefAlign
          && 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);

//===----------------------------------------------------------------------===//
//                       TargetData Class Implementation
//===----------------------------------------------------------------------===//

/*!
 A TargetDescription string consists of a sequence of hyphen-delimited
 specifiers for target endianness, pointer size and alignments, and various
 primitive type sizes and alignments. A typical string looks something like:
 <br><br>
 "E-p:32:32:32-i1:8:8-i8:8:8-i32:32:32-i64:32:64-f32:32:32-f64:32:64"
 <br><br>
 (note: this string is not fully specified and is only an example.)
 \p
 Alignments come in two flavors: ABI and preferred. ABI alignment (abi_align,
 below) dictates how a type will be aligned within an aggregate and when used
 as an argument.  Preferred alignment (pref_align, below) determines a type's
 alignment when emitted as a global.
 \p
 Specifier string details:
 <br><br>
 <i>[E|e]</i>: Endianness. "E" specifies a big-endian target data model, "e"
 specifies a little-endian target data model.
 <br><br>
 <i>p:<size>:<abi_align>:<pref_align></i>: Pointer size, ABI and preferred
 alignment.
 <br><br>
 <i><type><size>:<abi_align>:<pref_align></i>: Numeric type alignment. Type is
 one of <i>i|f|v|a</i>, corresponding to integer, floating point, vector (aka
 packed) or aggregate.  Size indicates the size, e.g., 32 or 64 bits.
 \p
 The default string, fully specified is:
 <br><br>
 "E-p:64:64:64-a0:0:0-f32:32:32-f64:0:64"
 "-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:0:64"
 "-v64:64:64-v128:128:128"
 <br><br>
 Note that in the case of aggregates, 0 is the default ABI and preferred
 alignment. This is a special case, where the aggregate's computed worst-case
 alignment will be used.
 */ 
void TargetData::init(const std::string &TargetDescription) {
  std::string temp = TargetDescription;
  
  LittleEndian = false;
  PointerMemSize = 8;
  PointerABIAlign   = 8;
  PointerPrefAlign = PointerABIAlign;

  // Default alignments
  setAlignment(INTEGER_ALIGN,   1,  1, 1);   // Bool
  setAlignment(INTEGER_ALIGN,   1,  1, 8);   // Byte
  setAlignment(INTEGER_ALIGN,   2,  2, 16);  // short
  setAlignment(INTEGER_ALIGN,   4,  4, 32);  // int
  setAlignment(INTEGER_ALIGN,   4,  8, 64);  // long
  setAlignment(FLOAT_ALIGN,     4,  4, 32);  // float
  setAlignment(FLOAT_ALIGN,     8,  8, 64);  // double
  setAlignment(VECTOR_ALIGN,    8,  8, 64);  // v2i32
  setAlignment(VECTOR_ALIGN,   16, 16, 128); // v16i8, v8i16, v4i32, ...
  setAlignment(AGGREGATE_ALIGN, 0,  8,  0);  // struct, union, class, ...
  
  while (!temp.empty()) {
    std::string token = getToken(temp, "-");
    std::string arg0 = getToken(token, ":");
    const char *p = arg0.c_str();
    switch(*p) {
    case 'E':
      LittleEndian = false;
      break;
    case 'e':
      LittleEndian = true;
      break;
    case 'p':
      PointerMemSize = atoi(getToken(token,":").c_str()) / 8;
      PointerABIAlign = atoi(getToken(token,":").c_str()) / 8;
      PointerPrefAlign = atoi(getToken(token,":").c_str()) / 8;
      if (PointerPrefAlign == 0)
        PointerPrefAlign = PointerABIAlign;
      break;
    case 'i':
    case 'v':
    case 'f':
    case 'a': {
      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);
      break;
    }
    default:
      break;
    }
  }
}

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, 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) {
      // Update the abi, preferred alignments.
      Alignments[i].ABIAlign = abi_align;
      Alignments[i].PrefAlign = pref_align;
      return;
    }
  }
  
  Alignments.push_back(TargetAlignElem::get(align_type, abi_align,
                                            pref_align, bit_width));
}

/// 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, 
                                      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)
      return ABIInfo ? Alignments[i].ABIAlign : Alignments[i].PrefAlign;
    
    // The best match so far depends on what we're looking for.
    if (AlignType == VECTOR_ALIGN) {
      // If this is a specification for a smaller vector type, we will fall back
      // to it.  This happens because <128 x double> can be implemented in terms
      // of 64 <2 x double>.
      if (Alignments[i].AlignType == VECTOR_ALIGN && 
          Alignments[i].TypeBitWidth < BitWidth) {
        // Verify that we pick the biggest of the fallbacks.
        if (BestMatchIdx == -1 ||
            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;
    }
  }

  // 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;
}

/// LayoutInfo - The lazy cache of structure layout information maintained by
/// TargetData.  Note that the struct types must have been free'd before
/// llvm_shutdown is called (and thus this is deallocated) because all the
/// targets with cached elements should have been destroyed.
///
typedef std::pair<const TargetData*,const StructType*> LayoutKey;

struct DenseMapLayoutKeyInfo {
  static inline LayoutKey getEmptyKey() { return LayoutKey(0, 0); }
  static inline LayoutKey getTombstoneKey() {
    return LayoutKey((TargetData*)(intptr_t)-1, 0);
  }
  static unsigned getHashValue(const LayoutKey &Val) {
    return DenseMapKeyInfo<void*>::getHashValue(Val.first) ^
           DenseMapKeyInfo<void*>::getHashValue(Val.second);
  }
  static bool isPod() { return true; }
};

typedef DenseMap<LayoutKey, StructLayout*, DenseMapLayoutKeyInfo> LayoutInfoTy;
static ManagedStatic<LayoutInfoTy> LayoutInfo;


TargetData::~TargetData() {
  if (LayoutInfo.isConstructed()) {
    // Remove any layouts for this TD.
    LayoutInfoTy &TheMap = *LayoutInfo;
    for (LayoutInfoTy::iterator I = TheMap.begin(), E = TheMap.end();
         I != E; ) {
      if (I->first.first == this) {
        I->second->~StructLayout();
        free(I->second);
        TheMap.erase(I++);
      } else {
        ++I;
      }
    }
  }
}

const StructLayout *TargetData::getStructLayout(const StructType *Ty) const {
  LayoutInfoTy &TheMap = *LayoutInfo;
  
  StructLayout *&SL = TheMap[LayoutKey(this, 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));
  
  // 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);
  return L;
}

/// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout
/// objects.  If a TargetData object is alive when types are being refined and
/// removed, this method must be called whenever a StructType is removed to
/// avoid a dangling pointer in this cache.
void TargetData::InvalidateStructLayoutInfo(const StructType *Ty) const {
  if (!LayoutInfo.isConstructed()) return;  // No cache.
  
  LayoutInfoTy::iterator I = LayoutInfo->find(LayoutKey(this, Ty));
  if (I != LayoutInfo->end()) {
    I->second->~StructLayout();
    free(I->second);
    LayoutInfo->erase(I);
  }
}


std::string TargetData::getStringRepresentation() const {
  std::string repr;
  repr.append(LittleEndian ? "e" : "E");
  repr.append("-p:").append(itostr((int64_t) (PointerMemSize * 8))).
      append(":").append(itostr((int64_t) (PointerABIAlign * 8))).
      append(":").append(itostr((int64_t) (PointerPrefAlign * 8)));
  for (align_const_iterator I = Alignments.begin();
       I != Alignments.end();
       ++I) {
    repr.append("-").append(1, (char) I->AlignType).
      append(utostr((int64_t) I->TypeBitWidth)).
      append(":").append(utostr((uint64_t) (I->ABIAlign * 8))).
      append(":").append(utostr((uint64_t) (I->PrefAlign * 8)));
  }
  return repr;
}


uint64_t TargetData::getTypeSize(const Type *Ty) const {
  assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
  switch (Ty->getTypeID()) {
  case Type::LabelTyID:
  case Type::PointerTyID:
    return getPointerSize();
  case Type::ArrayTyID: {
    const ArrayType *ATy = cast<ArrayType>(Ty);
    uint64_t Size;
    unsigned char Alignment;
    Size = getTypeSize(ATy->getElementType());
    Alignment = getABITypeAlignment(ATy->getElementType());
    uint64_t AlignedSize = (Size + Alignment - 1)/Alignment*Alignment;
    return AlignedSize*ATy->getNumElements();
  }
  case Type::StructTyID: {
    // Get the layout annotation... which is lazily created on demand.
    const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
    return Layout->getSizeInBytes();
  }
  case Type::IntegerTyID: {
    unsigned BitWidth = cast<IntegerType>(Ty)->getBitWidth();
    if (BitWidth <= 8) {
      return 1;
    } else if (BitWidth <= 16) {
      return 2;
    } else if (BitWidth <= 32) {
      return 4;
    } else if (BitWidth <= 64) {
      return 8;
    } 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:
    return 1;
  case Type::FloatTyID:
    return 4;
  case Type::DoubleTyID:
    return 8;
  case Type::VectorTyID: {
    const VectorType *PTy = cast<VectorType>(Ty);
    return PTy->getBitWidth() / 8;
  }
  default:
    assert(0 && "TargetData::getTypeSize(): Unsupported type");
    break;
  }
  return 0;
}

uint64_t TargetData::getTypeSizeInBits(const Type *Ty) const {
  if (Ty->isInteger())
    return cast<IntegerType>(Ty)->getBitWidth();
  else
    return getTypeSize(Ty) * 8;
}


/*!
  \param abi_or_pref Flag that determines which alignment is returned. true
  returns the ABI alignment, false returns the preferred alignment.
  \param Ty The underlying type for which alignment is determined.

  Get the ABI (\a abi_or_pref == true) or preferred alignment (\a abi_or_pref
  == false) for the requested type \a Ty.
 */
unsigned char TargetData::getAlignment(const Type *Ty, bool abi_or_pref) const {
  int AlignType = -1;

  assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
  switch (Ty->getTypeID()) {
  /* Early escape for the non-numeric types */
  case Type::LabelTyID:
  case Type::PointerTyID:
    return (abi_or_pref
            ? getPointerABIAlignment()
            : getPointerPrefAlignment());
  case Type::ArrayTyID:
    return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref);
    
  case Type::StructTyID: {
    // Packed structure types always have an ABI alignment of one.
    if (cast<StructType>(Ty)->isPacked() && abi_or_pref)
      return 1;
    
    // Get the layout annotation... which is lazily created on demand.
    const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
    unsigned Align = getAlignmentInfo(AGGREGATE_ALIGN, 0, abi_or_pref);
    return std::max(Align, (unsigned)Layout->getAlignment());
  }
  case Type::IntegerTyID:
  case Type::VoidTyID:
    AlignType = INTEGER_ALIGN;
    break;
  case Type::FloatTyID:
  case Type::DoubleTyID:
    AlignType = FLOAT_ALIGN;
    break;
  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;
  }

  return getAlignmentInfo((AlignTypeEnum)AlignType, getTypeSize(Ty) * 8,
                          abi_or_pref);
}

unsigned char TargetData::getABITypeAlignment(const Type *Ty) const {
  return getAlignment(Ty, true);
}

unsigned char TargetData::getPrefTypeAlignment(const Type *Ty) const {
  return getAlignment(Ty, false);
}

unsigned char TargetData::getPreferredTypeAlignmentShift(const Type *Ty) const {
  unsigned Align = (unsigned) getPrefTypeAlignment(Ty);
  assert(!(Align & (Align-1)) && "Alignment is not a power of two!");
  return Log2_32(Align);
}

/// getIntPtrType - Return an unsigned integer type that is the same size or
/// greater to the host pointer size.
const Type *TargetData::getIntPtrType() const {
  switch (getPointerSize()) {
  default: assert(0 && "Unknown pointer size!");
  case 2: return Type::Int16Ty;
  case 4: return Type::Int32Ty;
  case 8: return Type::Int64Ty;
  }
}


uint64_t TargetData::getIndexedOffset(const Type *ptrTy, Value* const* Indices,
                                      unsigned NumIndices) const {
  const Type *Ty = ptrTy;
  assert(isa<PointerType>(Ty) && "Illegal argument for getIndexedOffset()");
  uint64_t Result = 0;

  generic_gep_type_iterator<Value* const*>
    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");
      unsigned FieldNo = cast<ConstantInt>(Indices[CurIDX])->getZExtValue();

      // Get structure layout information...
      const StructLayout *Layout = getStructLayout(STy);

      // Add in the offset, as calculated by the structure layout info...
      Result += Layout->getElementOffset(FieldNo);

      // Update Ty to refer to current element
      Ty = STy->getElementType(FieldNo);
    } else {
      // Update Ty to refer to current element
      Ty = cast<SequentialType>(Ty)->getElementType();

      // Get the array index and the size of each array element.
      int64_t arrayIdx = cast<ConstantInt>(Indices[CurIDX])->getSExtValue();
      Result += arrayIdx * (int64_t)getTypeSize(Ty);
    }
  }

  return Result;
}

/// getPreferredAlignmentLog - Return the preferred alignment of the
/// specified global, returned in log form.  This includes an explicitly
/// requested alignment (if the global has one).
unsigned TargetData::getPreferredAlignmentLog(const GlobalVariable *GV) const {
  const Type *ElemType = GV->getType()->getElementType();
  unsigned Alignment = getPreferredTypeAlignmentShift(ElemType);
  if (GV->getAlignment() > (1U << Alignment))
    Alignment = Log2_32(GV->getAlignment());
  
  if (GV->hasInitializer()) {
    if (Alignment < 4) {
      // If the global is not external, see if it is large.  If so, give it a
      // larger alignment.
      if (getTypeSize(ElemType) > 128)
        Alignment = 4;    // 16-byte alignment.
    }
  }
  return Alignment;
}
