mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-14 00:32:55 +00:00
Add in the first step of the multiple pointer support. This adds in support to the data layout for specifying a per address space pointer size.
The next step is to update the optimizers to allow them to optimize the different address spaces with this information. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165505 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
942895d371
commit
7d66146868
@ -22,6 +22,7 @@
|
||||
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
|
||||
namespace llvm {
|
||||
@ -47,8 +48,8 @@ enum AlignTypeEnum {
|
||||
|
||||
/// Layout alignment element.
|
||||
///
|
||||
/// Stores the alignment data associated with a given alignment type (pointer,
|
||||
/// integer, vector, float) and type bit width.
|
||||
/// Stores the alignment data associated with a given alignment type (integer,
|
||||
/// vector, float) and type bit width.
|
||||
///
|
||||
/// @note The unusual order of elements in the structure attempts to reduce
|
||||
/// padding and make the structure slightly more cache friendly.
|
||||
@ -65,6 +66,26 @@ struct LayoutAlignElem {
|
||||
bool operator==(const LayoutAlignElem &rhs) const;
|
||||
};
|
||||
|
||||
/// Layout pointer alignment element.
|
||||
///
|
||||
/// Stores the alignment data associated with a given pointer and address space.
|
||||
///
|
||||
/// @note The unusual order of elements in the structure attempts to reduce
|
||||
/// padding and make the structure slightly more cache friendly.
|
||||
struct PointerAlignElem {
|
||||
unsigned ABIAlign; ///< ABI alignment for this type/bitw
|
||||
unsigned PrefAlign; ///< Pref. alignment for this type/bitw
|
||||
uint32_t TypeBitWidth; ///< Type bit width
|
||||
uint32_t AddressSpace; ///< Address space for the pointer type
|
||||
|
||||
/// Initializer
|
||||
static PointerAlignElem get(uint32_t addr_space, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width);
|
||||
/// Equality predicate
|
||||
bool operator==(const PointerAlignElem &rhs) const;
|
||||
};
|
||||
|
||||
|
||||
/// DataLayout - This class holds a parsed version of the target data layout
|
||||
/// string in a module and provides methods for querying it. The target data
|
||||
/// layout string is specified *by the target* - a frontend generating LLVM IR
|
||||
@ -74,9 +95,6 @@ struct LayoutAlignElem {
|
||||
class DataLayout : public ImmutablePass {
|
||||
private:
|
||||
bool LittleEndian; ///< Defaults to false
|
||||
unsigned PointerMemSize; ///< Pointer size in bytes
|
||||
unsigned PointerABIAlign; ///< Pointer ABI alignment
|
||||
unsigned PointerPrefAlign; ///< Pointer preferred alignment
|
||||
unsigned StackNaturalAlign; ///< Stack natural alignment
|
||||
|
||||
SmallVector<unsigned char, 8> LegalIntWidths; ///< Legal Integers.
|
||||
@ -88,11 +106,16 @@ private:
|
||||
/// pointers vs. 64-bit pointers by extending LayoutAlignment, but for now,
|
||||
/// we don't.
|
||||
SmallVector<LayoutAlignElem, 16> Alignments;
|
||||
DenseMap<unsigned, PointerAlignElem> Pointers;
|
||||
|
||||
/// InvalidAlignmentElem - This member is a signal that a requested alignment
|
||||
/// type and bit width were not found in the SmallVector.
|
||||
static const LayoutAlignElem InvalidAlignmentElem;
|
||||
|
||||
/// InvalidPointerElem - This member is a signal that a requested pointer
|
||||
/// type and bit width were not found in the DenseSet.
|
||||
static const PointerAlignElem InvalidPointerElem;
|
||||
|
||||
// The StructType -> StructLayout map.
|
||||
mutable void *LayoutMap;
|
||||
|
||||
@ -101,6 +124,11 @@ private:
|
||||
unsigned pref_align, uint32_t bit_width);
|
||||
unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width,
|
||||
bool ABIAlign, Type *Ty) const;
|
||||
|
||||
//! Set/initialize pointer alignments
|
||||
void setPointerAlignment(uint32_t addr_space, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width);
|
||||
|
||||
//! Internal helper method that returns requested alignment for type.
|
||||
unsigned getAlignment(Type *Ty, bool abi_or_pref) const;
|
||||
|
||||
@ -112,6 +140,14 @@ private:
|
||||
return &align != &InvalidAlignmentElem;
|
||||
}
|
||||
|
||||
/// Valid pointer predicate.
|
||||
///
|
||||
/// Predicate that tests a PointerAlignElem reference returned by get() against
|
||||
/// InvalidPointerElem.
|
||||
bool validPointer(const PointerAlignElem &align) const {
|
||||
return &align != &InvalidPointerElem;
|
||||
}
|
||||
|
||||
/// Initialise a DataLayout object with default values, ensure that the
|
||||
/// target data pass is registered.
|
||||
void init();
|
||||
@ -143,11 +179,9 @@ public:
|
||||
DataLayout(const DataLayout &TD) :
|
||||
ImmutablePass(ID),
|
||||
LittleEndian(TD.isLittleEndian()),
|
||||
PointerMemSize(TD.PointerMemSize),
|
||||
PointerABIAlign(TD.PointerABIAlign),
|
||||
PointerPrefAlign(TD.PointerPrefAlign),
|
||||
LegalIntWidths(TD.LegalIntWidths),
|
||||
Alignments(TD.Alignments),
|
||||
Pointers(TD.Pointers),
|
||||
LayoutMap(0)
|
||||
{ }
|
||||
|
||||
@ -197,14 +231,45 @@ public:
|
||||
}
|
||||
|
||||
/// Layout pointer alignment
|
||||
unsigned getPointerABIAlignment() const { return PointerABIAlign; }
|
||||
/// Return layout's alignment for stack-based pointers
|
||||
unsigned getPointerPrefAlignment() const { return PointerPrefAlign; }
|
||||
/// FIXME: The defaults need to be removed once all of
|
||||
/// the backends/clients are updated.
|
||||
unsigned getPointerABIAlignment(unsigned AS = 0) const {
|
||||
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
|
||||
if (val == Pointers.end()) {
|
||||
val = Pointers.find(0);
|
||||
}
|
||||
return val->second.ABIAlign;
|
||||
}
|
||||
/// Return target's alignment for stack-based pointers
|
||||
/// FIXME: The defaults need to be removed once all of
|
||||
/// the backends/clients are updated.
|
||||
unsigned getPointerPrefAlignment(unsigned AS = 0) const {
|
||||
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
|
||||
if (val == Pointers.end()) {
|
||||
val = Pointers.find(0);
|
||||
}
|
||||
return val->second.PrefAlign;
|
||||
}
|
||||
/// Layout pointer size
|
||||
unsigned getPointerSize() const { return PointerMemSize; }
|
||||
/// FIXME: The defaults need to be removed once all of
|
||||
/// the backends/clients are updated.
|
||||
unsigned getPointerSize(unsigned AS = 0) const {
|
||||
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
|
||||
if (val == Pointers.end()) {
|
||||
val = Pointers.find(0);
|
||||
}
|
||||
return val->second.TypeBitWidth;
|
||||
}
|
||||
/// Layout pointer size, in bits
|
||||
unsigned getPointerSizeInBits() const { return 8*PointerMemSize; }
|
||||
|
||||
/// FIXME: The defaults need to be removed once all of
|
||||
/// the backends/clients are updated.
|
||||
unsigned getPointerSizeInBits(unsigned AS = 0) const {
|
||||
DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS);
|
||||
if (val == Pointers.end()) {
|
||||
val = Pointers.find(0);
|
||||
}
|
||||
return 8*val->second.TypeBitWidth;
|
||||
}
|
||||
/// Size examples:
|
||||
///
|
||||
/// Type SizeInBits StoreSizeInBits AllocSizeInBits[*]
|
||||
@ -282,8 +347,9 @@ public:
|
||||
|
||||
/// getIntPtrType - Return an unsigned integer type that is the same size or
|
||||
/// greater to the host pointer size.
|
||||
///
|
||||
IntegerType *getIntPtrType(LLVMContext &C) const;
|
||||
/// FIXME: Need to remove the default argument when the rest of the LLVM code
|
||||
/// base has been updated.
|
||||
IntegerType *getIntPtrType(LLVMContext &C, unsigned AddressSpace = 0) const;
|
||||
|
||||
/// getIndexedOffset - return the offset from the beginning of the type for
|
||||
/// the specified indices. This is used to implement getelementptr.
|
||||
|
@ -143,7 +143,10 @@ public:
|
||||
|
||||
bool isBigEndian() const { return !IsLittleEndian; }
|
||||
bool isLittleEndian() const { return IsLittleEndian; }
|
||||
MVT getPointerTy() const { return PointerTy; }
|
||||
// Return the pointer type for the given address space, defaults to
|
||||
// the pointer type from the data layout.
|
||||
// FIXME: The default needs to be removed once all the code is updated.
|
||||
virtual MVT getPointerTy(uint32_t addrspace = 0) const { return PointerTy; }
|
||||
virtual MVT getShiftAmountTy(EVT LHSTy) const;
|
||||
|
||||
/// isSelectExpensive - Return true if the select operation is expensive for
|
||||
@ -1777,7 +1780,8 @@ private:
|
||||
const DataLayout *TD;
|
||||
const TargetLoweringObjectFile &TLOF;
|
||||
|
||||
/// PointerTy - The type to use for pointers, usually i32 or i64.
|
||||
/// PointerTy - The type to use for pointers for the default address space,
|
||||
/// usually i32 or i64.
|
||||
///
|
||||
MVT PointerTy;
|
||||
|
||||
|
@ -584,7 +584,7 @@ TargetLowering::TargetLowering(const TargetMachine &tm,
|
||||
setOperationAction(ISD::TRAP, MVT::Other, Expand);
|
||||
|
||||
IsLittleEndian = TD->isLittleEndian();
|
||||
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
PointerTy = MVT::getIntegerVT(8*TD->getPointerSize(0));
|
||||
memset(RegClassForVT, 0,MVT::LAST_VALUETYPE*sizeof(TargetRegisterClass*));
|
||||
memset(TargetDAGCombineArray, 0, array_lengthof(TargetDAGCombineArray));
|
||||
maxStoresPerMemset = maxStoresPerMemcpy = maxStoresPerMemmove = 8;
|
||||
@ -625,7 +625,7 @@ TargetLowering::~TargetLowering() {
|
||||
}
|
||||
|
||||
MVT TargetLowering::getShiftAmountTy(EVT LHSTy) const {
|
||||
return MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
return MVT::getIntegerVT(8*TD->getPointerSize(0));
|
||||
}
|
||||
|
||||
/// canOpTrap - Returns true if the operation can trap for the value type.
|
||||
@ -901,7 +901,7 @@ const char *TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
|
||||
EVT TargetLowering::getSetCCResultType(EVT VT) const {
|
||||
assert(!VT.isVector() && "No default SetCC type for vectors!");
|
||||
return PointerTy.SimpleTy;
|
||||
return getPointerTy(0).SimpleTy;
|
||||
}
|
||||
|
||||
MVT::SimpleValueType TargetLowering::getCmpLibcallReturnType() const {
|
||||
@ -1061,7 +1061,7 @@ SDValue TargetLowering::getPICJumpTableRelocBase(SDValue Table,
|
||||
|
||||
if ((JTEncoding == MachineJumpTableInfo::EK_GPRel64BlockAddress) ||
|
||||
(JTEncoding == MachineJumpTableInfo::EK_GPRel32BlockAddress))
|
||||
return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy());
|
||||
return DAG.getGLOBAL_OFFSET_TABLE(getPointerTy(0));
|
||||
|
||||
return Table;
|
||||
}
|
||||
@ -2953,8 +2953,9 @@ TargetLowering::AsmOperandInfoVector TargetLowering::ParseConstraints(
|
||||
EVT::getEVT(IntegerType::get(OpTy->getContext(), BitSize), true);
|
||||
break;
|
||||
}
|
||||
} else if (dyn_cast<PointerType>(OpTy)) {
|
||||
OpInfo.ConstraintVT = MVT::getIntegerVT(8*TD->getPointerSize());
|
||||
} else if (PointerType *PT = dyn_cast<PointerType>(OpTy)) {
|
||||
OpInfo.ConstraintVT = MVT::getIntegerVT(
|
||||
8*TD->getPointerSize(PT->getAddressSpace()));
|
||||
} else {
|
||||
OpInfo.ConstraintVT = EVT::getEVT(OpTy, true);
|
||||
}
|
||||
|
@ -118,7 +118,35 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
|
||||
}
|
||||
|
||||
const LayoutAlignElem
|
||||
DataLayout::InvalidAlignmentElem = { (AlignTypeEnum)0xFF, 0, 0, 0 };
|
||||
DataLayout::InvalidAlignmentElem =
|
||||
LayoutAlignElem::get((AlignTypeEnum) -1, 0, 0, 0);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// PointerAlignElem, PointerAlign support
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
PointerAlignElem
|
||||
PointerAlignElem::get(uint32_t addr_space, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width) {
|
||||
assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
|
||||
PointerAlignElem retval;
|
||||
retval.AddressSpace = addr_space;
|
||||
retval.ABIAlign = abi_align;
|
||||
retval.PrefAlign = pref_align;
|
||||
retval.TypeBitWidth = bit_width;
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool
|
||||
PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
|
||||
return (ABIAlign == rhs.ABIAlign
|
||||
&& AddressSpace == rhs.AddressSpace
|
||||
&& PrefAlign == rhs.PrefAlign
|
||||
&& TypeBitWidth == rhs.TypeBitWidth);
|
||||
}
|
||||
|
||||
const PointerAlignElem
|
||||
DataLayout::InvalidPointerElem = PointerAlignElem::get(~0U, 0U, 0U, 0U);
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// DataLayout Class Implementation
|
||||
@ -136,9 +164,6 @@ void DataLayout::init() {
|
||||
|
||||
LayoutMap = 0;
|
||||
LittleEndian = false;
|
||||
PointerMemSize = 8;
|
||||
PointerABIAlign = 8;
|
||||
PointerPrefAlign = PointerABIAlign;
|
||||
StackNaturalAlign = 0;
|
||||
|
||||
// Default alignments
|
||||
@ -154,6 +179,7 @@ void DataLayout::init() {
|
||||
setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ...
|
||||
setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
|
||||
setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct
|
||||
setPointerAlignment(0, 8, 8, 8);
|
||||
}
|
||||
|
||||
std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
|
||||
@ -185,13 +211,16 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
|
||||
td->LittleEndian = true;
|
||||
break;
|
||||
case 'p': {
|
||||
// Pointer size.
|
||||
int AddrSpace = 0;
|
||||
if (Specifier.size() > 1) {
|
||||
AddrSpace = getInt(Specifier.substr(1));
|
||||
if (AddrSpace < 0 || AddrSpace > (1 << 24))
|
||||
return "Invalid address space, must be a positive 24bit integer";
|
||||
}
|
||||
Split = Token.split(':');
|
||||
int PointerMemSizeBits = getInt(Split.first);
|
||||
if (PointerMemSizeBits < 0 || PointerMemSizeBits % 8 != 0)
|
||||
return "invalid pointer size, must be a positive 8-bit multiple";
|
||||
if (td)
|
||||
td->PointerMemSize = PointerMemSizeBits / 8;
|
||||
|
||||
// Pointer ABI alignment.
|
||||
Split = Split.second.split(':');
|
||||
@ -200,8 +229,6 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
|
||||
return "invalid pointer ABI alignment, "
|
||||
"must be a positive 8-bit multiple";
|
||||
}
|
||||
if (td)
|
||||
td->PointerABIAlign = PointerABIAlignBits / 8;
|
||||
|
||||
// Pointer preferred alignment.
|
||||
Split = Split.second.split(':');
|
||||
@ -210,11 +237,12 @@ std::string DataLayout::parseSpecifier(StringRef Desc, DataLayout *td) {
|
||||
return "invalid pointer preferred alignment, "
|
||||
"must be a positive 8-bit multiple";
|
||||
}
|
||||
if (td) {
|
||||
td->PointerPrefAlign = PointerPrefAlignBits / 8;
|
||||
if (td->PointerPrefAlign == 0)
|
||||
td->PointerPrefAlign = td->PointerABIAlign;
|
||||
}
|
||||
|
||||
if (PointerPrefAlignBits == 0)
|
||||
PointerPrefAlignBits = PointerABIAlignBits;
|
||||
if (td)
|
||||
td->setPointerAlignment(AddrSpace, PointerABIAlignBits/8,
|
||||
PointerPrefAlignBits/8, PointerMemSizeBits/8);
|
||||
break;
|
||||
}
|
||||
case 'i':
|
||||
@ -330,6 +358,21 @@ DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
|
||||
pref_align, bit_width));
|
||||
}
|
||||
|
||||
void
|
||||
DataLayout::setPointerAlignment(uint32_t addr_space, unsigned abi_align,
|
||||
unsigned pref_align, uint32_t bit_width) {
|
||||
assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
|
||||
DenseMap<unsigned,PointerAlignElem>::iterator val = Pointers.find(addr_space);
|
||||
if (val == Pointers.end()) {
|
||||
Pointers[addr_space] = PointerAlignElem::get(addr_space,
|
||||
abi_align, pref_align, bit_width);
|
||||
} else {
|
||||
val->second.ABIAlign = abi_align;
|
||||
val->second.PrefAlign = pref_align;
|
||||
val->second.TypeBitWidth = bit_width;
|
||||
}
|
||||
}
|
||||
|
||||
/// getAlignmentInfo - Return the alignment (either ABI if ABIInfo = true or
|
||||
/// preferred if ABIInfo = false) the layout wants for the specified datatype.
|
||||
unsigned DataLayout::getAlignmentInfo(AlignTypeEnum AlignType,
|
||||
@ -443,10 +486,28 @@ std::string DataLayout::getStringRepresentation() const {
|
||||
std::string Result;
|
||||
raw_string_ostream OS(Result);
|
||||
|
||||
OS << (LittleEndian ? "e" : "E")
|
||||
<< "-p:" << PointerMemSize*8 << ':' << PointerABIAlign*8
|
||||
<< ':' << PointerPrefAlign*8
|
||||
<< "-S" << StackNaturalAlign*8;
|
||||
OS << (LittleEndian ? "e" : "E");
|
||||
SmallVector<unsigned, 8> addrSpaces;
|
||||
// Lets get all of the known address spaces and sort them
|
||||
// into increasing order so that we can emit the string
|
||||
// in a cleaner format.
|
||||
for (DenseMap<unsigned, PointerAlignElem>::const_iterator
|
||||
pib = Pointers.begin(), pie = Pointers.end();
|
||||
pib != pie; ++pib) {
|
||||
addrSpaces.push_back(pib->first);
|
||||
}
|
||||
std::sort(addrSpaces.begin(), addrSpaces.end());
|
||||
for (SmallVector<unsigned, 8>::iterator asb = addrSpaces.begin(),
|
||||
ase = addrSpaces.end(); asb != ase; ++asb) {
|
||||
const PointerAlignElem &PI = Pointers.find(*asb)->second;
|
||||
OS << "-p";
|
||||
if (PI.AddressSpace) {
|
||||
OS << PI.AddressSpace;
|
||||
}
|
||||
OS << ":" << PI.TypeBitWidth*8 << ':' << PI.ABIAlign*8
|
||||
<< ':' << PI.PrefAlign*8;
|
||||
}
|
||||
OS << "-S" << StackNaturalAlign*8;
|
||||
|
||||
for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
|
||||
const LayoutAlignElem &AI = Alignments[i];
|
||||
@ -468,8 +529,11 @@ uint64_t DataLayout::getTypeSizeInBits(Type *Ty) const {
|
||||
assert(Ty->isSized() && "Cannot getTypeInfo() on a type that is unsized!");
|
||||
switch (Ty->getTypeID()) {
|
||||
case Type::LabelTyID:
|
||||
case Type::PointerTyID:
|
||||
return getPointerSizeInBits();
|
||||
return getPointerSizeInBits(0);
|
||||
case Type::PointerTyID: {
|
||||
unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace();
|
||||
return getPointerSizeInBits(AS);
|
||||
}
|
||||
case Type::ArrayTyID: {
|
||||
ArrayType *ATy = cast<ArrayType>(Ty);
|
||||
return getTypeAllocSizeInBits(ATy->getElementType())*ATy->getNumElements();
|
||||
@ -517,10 +581,15 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
|
||||
switch (Ty->getTypeID()) {
|
||||
// Early escape for the non-numeric types.
|
||||
case Type::LabelTyID:
|
||||
case Type::PointerTyID:
|
||||
return (abi_or_pref
|
||||
? getPointerABIAlignment()
|
||||
: getPointerPrefAlignment());
|
||||
? getPointerABIAlignment(0)
|
||||
: getPointerPrefAlignment(0));
|
||||
case Type::PointerTyID: {
|
||||
unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace();
|
||||
return (abi_or_pref
|
||||
? getPointerABIAlignment(AS)
|
||||
: getPointerPrefAlignment(AS));
|
||||
}
|
||||
case Type::ArrayTyID:
|
||||
return getAlignment(cast<ArrayType>(Ty)->getElementType(), abi_or_pref);
|
||||
|
||||
@ -591,8 +660,9 @@ unsigned DataLayout::getPreferredTypeAlignmentShift(Type *Ty) const {
|
||||
|
||||
/// getIntPtrType - Return an unsigned integer type that is the same size or
|
||||
/// greater to the host pointer size.
|
||||
IntegerType *DataLayout::getIntPtrType(LLVMContext &C) const {
|
||||
return IntegerType::get(C, getPointerSizeInBits());
|
||||
IntegerType *DataLayout::getIntPtrType(LLVMContext &C,
|
||||
unsigned AddressSpace) const {
|
||||
return IntegerType::get(C, getPointerSizeInBits(AddressSpace));
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user