[llvm-commits] [dragonegg] r127804 - in /dragonegg/trunk: Backend.cpp Constants.cpp Constants.h Convert.cpp
Duncan Sands
baldrick at free.fr
Thu Mar 17 02:03:33 PDT 2011
Author: baldrick
Date: Thu Mar 17 04:03:33 2011
New Revision: 127804
URL: http://llvm.org/viewvc/llvm-project?rev=127804&view=rev
Log:
Rename ConvertConstant to ConvertInitializer and make sure that all
users of this method outside of Constants.cpp make no assumptions
about the type of the returned value. This gives a lot more freedom
in how initializers are converted, which is needed to handle a bunch
of nasty corner cases.
Modified:
dragonegg/trunk/Backend.cpp
dragonegg/trunk/Constants.cpp
dragonegg/trunk/Constants.h
dragonegg/trunk/Convert.cpp
Modified: dragonegg/trunk/Backend.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Backend.cpp?rev=127804&r1=127803&r2=127804&view=diff
==============================================================================
--- dragonegg/trunk/Backend.cpp (original)
+++ dragonegg/trunk/Backend.cpp Thu Mar 17 04:03:33 2011
@@ -1020,7 +1020,7 @@
// When constructing the initializer it might refer to itself.
// This can happen for things like void *G = &G;
GV->setInitializer(UndefValue::get(GV->getType()->getElementType()));
- Init = ConvertConstant(DECL_INITIAL(decl));
+ Init = ConvertInitializer(DECL_INITIAL(decl));
}
// If we had a forward definition that has a type that disagrees with our
Modified: dragonegg/trunk/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.cpp?rev=127804&r1=127803&r2=127804&view=diff
==============================================================================
--- dragonegg/trunk/Constants.cpp (original)
+++ dragonegg/trunk/Constants.cpp Thu Mar 17 04:03:33 2011
@@ -28,6 +28,7 @@
// LLVM headers
#include "llvm/GlobalVariable.h"
#include "llvm/LLVMContext.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Host.h"
#include "llvm/Target/TargetData.h"
@@ -51,6 +52,342 @@
static LLVMContext &Context = getGlobalContext();
+/// BitSlice - A contiguous range of bits held in memory.
+class BitSlice {
+ int First, Last; // Range [First, Last)
+ Constant *Contents; // May be null for an empty range.
+
+ /// ExtendRange - Extend the slice to a wider range. All added bits are zero.
+ BitSlice ExtendRange(int WideFirst, int WideLast) const {
+ // Quick exit if the range did not actually increase.
+ if (WideFirst == First && WideLast == Last)
+ return *this;
+ if (WideFirst > First || WideLast < Last || WideLast <= WideFirst) {
+ assert(empty() && WideLast <= WideFirst && "Not an extension!");
+ // The trivial case of extending an empty range to an empty range.
+ return BitSlice();
+ }
+ const Type *WideTy = IntegerType::get(Context, WideLast - WideFirst);
+ // If the slice contains no bits then every bit of the extension is zero.
+ if (empty())
+ return BitSlice(WideFirst, WideLast, Constant::getNullValue(WideTy));
+ // Zero extend the contents to the new type;
+ Constant *C = TheFolder->CreateZExtOrBitCast(Contents, WideTy);
+ // Position the old contents correctly inside the new contents.
+ if (BYTES_BIG_ENDIAN && WideLast > Last) {
+ Constant *ShiftAmt = ConstantInt::get(C->getType(), WideLast - Last);
+ C = TheFolder->CreateShl(C, ShiftAmt);
+ } else if (!BYTES_BIG_ENDIAN && WideFirst < First) {
+ Constant *ShiftAmt = ConstantInt::get(C->getType(), First - WideFirst);
+ C = TheFolder->CreateShl(C, ShiftAmt);
+ }
+ return BitSlice(WideFirst, WideLast, C);
+ }
+
+ /// ReduceRange - Reduce the slice to a smaller range.
+ BitSlice ReduceRange(int NarrowFirst, int NarrowLast) const {
+ // Quick exit if the range did not actually decrease.
+ if (NarrowFirst == First && NarrowLast == Last)
+ return *this;
+ // The trivial case of reducing to an empty range.
+ if (NarrowLast <= NarrowFirst)
+ return BitSlice();
+ assert(NarrowFirst >= First && NarrowLast <= Last && "Not a reduction!");
+ // Move the least-significant bit to the correct position.
+ Constant *C = Contents;
+ if (BYTES_BIG_ENDIAN && NarrowLast < Last) {
+ Constant *ShiftAmt = ConstantInt::get(C->getType(), Last - NarrowLast);
+ C = TheFolder->CreateLShr(C, ShiftAmt);
+ } else if (!BYTES_BIG_ENDIAN && NarrowFirst > First) {
+ Constant *ShiftAmt = ConstantInt::get(C->getType(), NarrowFirst - First);
+ C = TheFolder->CreateLShr(C, ShiftAmt);
+ }
+ // Truncate to the new type.
+ const Type *NarrowTy = IntegerType::get(Context, NarrowLast - NarrowFirst);
+ C = TheFolder->CreateTruncOrBitCast(C, NarrowTy);
+ return BitSlice(NarrowFirst, NarrowLast, C);
+ }
+
+public:
+ /// BitSlice - Default constructor: empty bit range.
+ BitSlice() : First(0), Last(0), Contents(0) {}
+
+ /// BitSlice - Constructor for the range of bits ['first', 'last'). The bits
+ /// themselves are supplied in 'contents' as a constant of integer type. On
+ /// little-endian machines the least significant bit of 'contents corresponds
+ /// to the first bit of the range (aka 'first'), while on big-endian machines
+ /// it corresponds to the last bit of the range (aka 'last'-1).
+ BitSlice(int first, int last, Constant *contents)
+ : First(first), Last(last), Contents(contents) {
+ assert((empty() || isa<IntegerType>(Contents->getType())) &&
+ "Not an integer type!");
+ assert((empty() || getBitWidth() ==
+ Contents->getType()->getPrimitiveSizeInBits()) &&
+ "Bitwidth mismatch!");
+ }
+
+ /// empty - Return whether the range is empty.
+ bool empty() const {
+ return Last <= First;
+ }
+
+ /// getBitWidth - Return the number of bits in the range.
+ unsigned getBitWidth() {
+ return empty() ? 0 : Last - First;
+ }
+
+ /// Displace - Return the result of sliding all bits by the given offset.
+ BitSlice Displace(int Offset) const {
+ return BitSlice(First + Offset, Last + Offset, Contents);
+ }
+
+ /// getBits - Return the bits in the range [first, last). This range need not
+ /// be contained in the range of the slice, but if not then the bits outside
+ /// the slice get an undefined value. The bits are returned as a constant of
+ /// integer type. On little-endian machine the least significant bit of the
+ /// returned value corresponds to the first bit of the range (aka 'first'),
+ /// while on big-endian machines it corresponds to the last bit of the range
+ /// (aka 'last'-1).
+ Constant *getBits(int first, int last) {
+ assert(first < last && "Bit range is empty!");
+ // Quick exit if the desired range matches that of the slice.
+ if (First == first && Last == last)
+ return Contents;
+ const Type *RetTy = IntegerType::get(Context, last - first);
+ // If the slice contains no bits then every returned bit is undefined.
+ if (empty())
+ return UndefValue::get(RetTy);
+ // Extend to the convex hull of the two ranges.
+ int WideFirst = first < First ? first : First;
+ int WideLast = last > Last ? last : Last;
+ BitSlice Slice = ExtendRange(WideFirst, WideLast);
+ // Chop the slice down to the requested range.
+ Slice = Slice.ReduceRange(first, last);
+ // Now we can just return the bits contained in the slice.
+ return Slice.Contents;
+ }
+
+ /// Merge - Join the slice with another (which must be disjoint), forming the
+ /// convex hull of the ranges. The bits in the range of one of the slices are
+ /// those of that slice. Any other bits have an undefined value.
+ void Merge(const BitSlice &that) {
+ // If the other slice is empty, the result is this slice.
+ if (that.empty())
+ return;
+ // If this slice is empty, the result is the other slice.
+ if (empty()) {
+ *this = that;
+ return;
+ }
+ assert((that.Last <= First || that.First >= Last) && "Slices overlap!");
+ // Zero extend each slice to the convex hull of the ranges.
+ int JoinFirst = that.First < First ? that.First : First;
+ int JoinLast = that.Last > Last ? that.Last : Last;
+ BitSlice ThisExtended = ExtendRange(JoinFirst, JoinLast);
+ BitSlice ThatExtended = that.ExtendRange(JoinFirst, JoinLast);
+ // Since the slices are disjoint and all added bits are zero they can be
+ // joined via a simple 'or'.
+ Constant *Join = TheFolder->CreateOr(ThisExtended.Contents,
+ ThatExtended.Contents);
+ *this = BitSlice(JoinFirst, JoinLast, Join);
+ }
+};
+
+/// ViewAsBits - View the given constant as a bunch of bits, i.e. as one big
+/// integer. Only the bits in the range [First, Last) are needed, so there
+/// is no need to supply bits outside this range though it is harmless to do
+/// so. There is also no need to supply undefined bits inside this range.
+static BitSlice ViewAsBits(Constant *C, int First, int Last) {
+ assert(First < Last && "Empty range!");
+
+ // Sanitize the range to make life easier in what follows.
+ const Type *Ty = C->getType();
+ int StoreSize = getTargetData().getTypeStoreSizeInBits(Ty);
+ First = First < 0 ? 0 : First;
+ Last = Last > StoreSize ? StoreSize : Last;
+
+ // Quick exit if it is clear that there are no bits in the range.
+ if (Last <= 0 || First >= StoreSize)
+ return BitSlice();
+ assert(StoreSize > 0 && "Empty range not eliminated?");
+
+ switch (Ty->getTypeID()) {
+ default:
+ llvm_unreachable("Unsupported type!");
+ case Type::DoubleTyID:
+ case Type::FloatTyID:
+ case Type::FP128TyID:
+ case Type::IntegerTyID:
+ case Type::PointerTyID:
+ case Type::PPC_FP128TyID:
+ case Type::X86_FP80TyID:
+ case Type::X86_MMXTyID: {
+ // Bitcast to an integer with the same number of bits and return that.
+ unsigned Size = Ty->getPrimitiveSizeInBits();
+ const IntegerType *IntTy = IntegerType::get(Context, Size);
+ C = isa<PointerType>(Ty) ?
+ TheFolder->CreatePtrToInt(C, IntTy) : TheFolder->CreateBitCast(C, IntTy);
+ // Be careful about where the bits are placed in case this is a funky type
+ // like i1. If the width is a multiple of the address unit then there is
+ // nothing to worry about: the bits occupy the range [0, StoreSize). But
+ // if not then endianness matters: on big-endian machines there are padding
+ // bits at the start, while on little-endian machines they are at the end.
+ return BYTES_BIG_ENDIAN ?
+ BitSlice(StoreSize - Size, StoreSize, C) : BitSlice(0, Size, C);
+ }
+
+ case Type::ArrayTyID: {
+ const ArrayType *ATy = cast<ArrayType>(Ty);
+ const Type *EltTy = ATy->getElementType();
+ const unsigned NumElts = ATy->getNumElements();
+ const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy);
+ assert(Stride > 0 && "Store size smaller than alloc size?");
+ // Elements with indices in [FirstElt, LastElt) overlap the range.
+ unsigned FirstElt = First / Stride;
+ unsigned LastElt = (Last + Stride - 1) / Stride;
+ assert(LastElt <= NumElts && "Store size bigger than array?");
+ // Visit all elements that overlap the requested range, accumulating their
+ // bits in Bits.
+ BitSlice Bits;
+ for (unsigned i = FirstElt; i < LastElt; ++i) {
+ // Extract the element.
+ Constant *Elt = TheFolder->CreateExtractValue(C, &i, 1);
+ // View it as a bunch of bits.
+ BitSlice EltBits = ViewAsBits(Elt, 0, Stride);
+ // Add to the already known bits.
+ Bits.Merge(EltBits.Displace(i * Stride));
+ }
+ return Bits;
+ }
+
+ case Type::StructTyID: {
+ const StructType *STy = cast<StructType>(Ty);
+ const StructLayout *SL = getTargetData().getStructLayout(STy);
+ // Fields with indices in [FirstIdx, LastIdx) overlap the range.
+ unsigned FirstIdx = SL->getElementContainingOffset((First+7)/8);
+ unsigned LastIdx = 1 + SL->getElementContainingOffset((Last+6)/8);
+ // Visit all fields that overlap the requested range, accumulating their
+ // bits in Bits.
+ BitSlice Bits;
+ for (unsigned i = FirstIdx; i < LastIdx; ++i) {
+ // Extract the field.
+ Constant *Field = TheFolder->CreateExtractValue(C, &i, 1);
+ // View it as a bunch of bits.
+ const Type *FieldTy = Field->getType();
+ unsigned FieldStoreSize = getTargetData().getTypeStoreSizeInBits(FieldTy);
+ BitSlice FieldBits = ViewAsBits(Field, 0, FieldStoreSize);
+ // Add to the already known bits.
+ Bits.Merge(FieldBits.Displace(SL->getElementOffset(i)*8));
+ }
+ return Bits;
+ }
+
+ case Type::VectorTyID: {
+ const VectorType *VTy = cast<VectorType>(Ty);
+ const Type *EltTy = VTy->getElementType();
+ const unsigned NumElts = VTy->getNumElements();
+ const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy);
+ assert(Stride > 0 && "Store size smaller than alloc size?");
+ // Elements with indices in [FirstElt, LastElt) overlap the range.
+ unsigned FirstElt = First / Stride;
+ unsigned LastElt = (Last + Stride - 1) / Stride;
+ assert(LastElt <= NumElts && "Store size bigger than vector?");
+ // Visit all elements that overlap the requested range, accumulating their
+ // bits in Bits.
+ BitSlice Bits;
+ for (unsigned i = FirstElt; i < LastElt; ++i) {
+ // Extract the element.
+ ConstantInt *Idx = ConstantInt::get(Type::getInt32Ty(Context), i);
+ Constant *Elt = TheFolder->CreateExtractElement(C, Idx);
+ // View it as a bunch of bits.
+ BitSlice EltBits = ViewAsBits(Elt, 0, Stride);
+ // Add to the already known bits.
+ Bits.Merge(EltBits.Displace(i * Stride));
+ }
+ return Bits;
+ }
+ }
+}
+
+/// InterpretAsType - Interpret the bits of the given constant (starting from
+/// StartingBit) as representing a constant of type 'Ty'. This results in the
+/// same constant as you would get by storing the bits of 'C' to memory (with
+/// the first bit stored being 'StartingBit') and then loading out a (constant)
+/// value of type 'Ty' from the stored to memory location.
+Constant *InterpretAsType(Constant *C, const Type* Ty, unsigned StartingBit) {
+ switch (Ty->getTypeID()) {
+ default:
+ llvm_unreachable("Unsupported type!");
+ case Type::IntegerTyID: {
+ unsigned BitWidth = Ty->getPrimitiveSizeInBits();
+ unsigned StoreSize = getTargetData().getTypeStoreSizeInBits(Ty);
+ // Convert the constant into a bunch of bits. Only the bits to be "loaded"
+ // out are needed, so rather than converting the entire constant this only
+ // converts enough to get all of the required bits.
+ BitSlice Bits = ViewAsBits(C, StartingBit, StartingBit + StoreSize);
+ // Extract the bits used by the integer. If the integer width is a multiple
+ // of the address unit then the endianness of the target doesn't matter. If
+ // not then the padding bits come at the start on big-endian machines and at
+ // the end on little-endian machines.
+ Bits = Bits.Displace(-StartingBit);
+ return BYTES_BIG_ENDIAN ?
+ Bits.getBits(StoreSize - BitWidth, StoreSize) : Bits.getBits(0, BitWidth);
+ }
+
+ case Type::DoubleTyID:
+ case Type::FloatTyID:
+ case Type::FP128TyID:
+ case Type::PointerTyID:
+ case Type::PPC_FP128TyID:
+ case Type::X86_FP80TyID:
+ case Type::X86_MMXTyID: {
+ // Interpret as an integer with the same number of bits then cast back to
+ // the original type.
+ unsigned BitWidth = Ty->getPrimitiveSizeInBits();
+ const IntegerType *IntTy = IntegerType::get(Context, BitWidth);
+ C = InterpretAsType(C, IntTy, StartingBit);
+ return isa<PointerType>(Ty) ?
+ TheFolder->CreateIntToPtr(C, Ty) : TheFolder->CreateBitCast(C, Ty);
+ }
+
+ case Type::ArrayTyID: {
+ // Interpret each array element in turn.
+ const ArrayType *ATy = cast<ArrayType>(Ty);
+ const Type *EltTy = ATy->getElementType();
+ const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy);
+ const unsigned NumElts = ATy->getNumElements();
+ std::vector<Constant*> Vals(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Vals[i] = InterpretAsType(C, EltTy, StartingBit + i*Stride);
+ return ConstantArray::get(ATy, Vals); // TODO: Use ArrayRef constructor.
+ }
+
+ case Type::StructTyID: {
+ // Interpret each struct field in turn.
+ const StructType *STy = cast<StructType>(Ty);
+ const StructLayout *SL = getTargetData().getStructLayout(STy);
+ unsigned NumElts = STy->getNumElements();
+ std::vector<Constant*> Vals(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Vals[i] = InterpretAsType(C, STy->getElementType(i),
+ StartingBit + SL->getElementOffsetInBits(i));
+ return ConstantStruct::get(STy, Vals); // TODO: Use ArrayRef constructor.
+ }
+
+ case Type::VectorTyID: {
+ // Interpret each vector element in turn.
+ const VectorType *VTy = cast<VectorType>(Ty);
+ const Type *EltTy = VTy->getElementType();
+ const unsigned Stride = getTargetData().getTypeAllocSizeInBits(EltTy);
+ const unsigned NumElts = VTy->getNumElements();
+ SmallVector<Constant*, 16> Vals(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Vals[i] = InterpretAsType(C, EltTy, StartingBit + i*Stride);
+ return ConstantVector::get(Vals);
+ }
+ }
+}
+
/// EncodeExpr - Write the given expression into Buffer as it would appear in
/// memory on the target (the buffer is resized to contain exactly the bytes
/// written). Return the number of bytes written; this can also be obtained
@@ -140,7 +477,7 @@
std::vector<Constant*> Elts;
for (tree elt = TREE_VECTOR_CST_ELTS(exp); elt; elt = TREE_CHAIN(elt))
- Elts.push_back(ConvertConstant(TREE_VALUE(elt)));
+ Elts.push_back(ConvertInitializer(TREE_VALUE(elt)));
// The vector should be zero filled if insufficient elements are provided.
if (Elts.size() < TYPE_VECTOR_SUBPARTS(TREE_TYPE(exp))) {
@@ -226,14 +563,14 @@
static Constant *ConvertCOMPLEX_CST(tree exp) {
Constant *Elts[2] = {
- ConvertConstant(TREE_REALPART(exp)),
- ConvertConstant(TREE_IMAGPART(exp))
+ ConvertInitializer(TREE_REALPART(exp)),
+ ConvertInitializer(TREE_IMAGPART(exp))
};
return ConstantStruct::get(Context, Elts, 2, false);
}
static Constant *ConvertNOP_EXPR(tree exp) {
- Constant *Elt = ConvertConstant(TREE_OPERAND(exp, 0));
+ Constant *Elt = ConvertInitializer(TREE_OPERAND(exp, 0));
const Type *Ty = ConvertType(TREE_TYPE(exp));
bool EltIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
@@ -249,7 +586,7 @@
}
static Constant *ConvertCONVERT_EXPR(tree exp) {
- Constant *Elt = ConvertConstant(TREE_OPERAND(exp, 0));
+ Constant *Elt = ConvertInitializer(TREE_OPERAND(exp, 0));
bool EltIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
const Type *Ty = ConvertType(TREE_TYPE(exp));
bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
@@ -259,8 +596,8 @@
}
static Constant *ConvertPOINTER_PLUS_EXPR(tree exp) {
- Constant *Ptr = ConvertConstant(TREE_OPERAND(exp, 0)); // The pointer.
- Constant *Idx = ConvertConstant(TREE_OPERAND(exp, 1)); // The offset in bytes.
+ Constant *Ptr = ConvertInitializer(TREE_OPERAND(exp, 0)); // The pointer.
+ Constant *Idx = ConvertInitializer(TREE_OPERAND(exp, 1)); // Offset in bytes.
// Convert the pointer into an i8* and add the offset to it.
Ptr = TheFolder->CreateBitCast(Ptr, Type::getInt8PtrTy(Context));
@@ -273,9 +610,9 @@
}
static Constant *ConvertBinOp_CST(tree exp) {
- Constant *LHS = ConvertConstant(TREE_OPERAND(exp, 0));
+ Constant *LHS = ConvertInitializer(TREE_OPERAND(exp, 0));
bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp,0)));
- Constant *RHS = ConvertConstant(TREE_OPERAND(exp, 1));
+ Constant *RHS = ConvertInitializer(TREE_OPERAND(exp, 1));
bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp,1)));
Instruction::CastOps opcode;
if (LHS->getType()->isPointerTy()) {
@@ -332,7 +669,7 @@
Constant *SomeVal = 0;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (exp), ix, elt_index, elt_value) {
// Find and decode the constructor's value.
- Constant *Val = ConvertConstant(elt_value);
+ Constant *Val = ConvertInitializer(elt_value);
SomeVal = Val;
// Get the index position of the element within the array. Note that this
@@ -798,7 +1135,7 @@
}
// Decode the field's value.
- Constant *Val = ConvertConstant(FieldValue);
+ Constant *Val = ConvertInitializer(FieldValue);
// GCCFieldOffsetInBits is where GCC is telling us to put the current field.
uint64_t GCCFieldOffsetInBits = getFieldOffsetInBits(Field);
@@ -870,7 +1207,7 @@
ConstantLayoutInfo LayoutInfo(getTargetData());
// Convert the constant itself.
- Constant *Val = ConvertConstant(VEC_index(constructor_elt, elt, 0)->value);
+ Constant *Val = ConvertInitializer(VEC_index(constructor_elt, elt, 0)->value);
// Unions are initialized using the first member field. Find it.
tree Field = TYPE_FIELDS(TREE_TYPE(exp));
@@ -934,7 +1271,7 @@
}
}
-Constant *ConvertConstant(tree exp) {
+Constant *ConvertInitializer(tree exp) {
assert(TREE_CONSTANT(exp) && "Isn't a constant!");
switch (TREE_CODE(exp)) {
case FDESC_EXPR: // Needed on itanium
@@ -952,7 +1289,7 @@
case PLUS_EXPR:
case MINUS_EXPR: return ConvertBinOp_CST(exp);
case CONSTRUCTOR: return ConvertCONSTRUCTOR(exp);
- case VIEW_CONVERT_EXPR: return ConvertConstant(TREE_OPERAND(exp, 0));
+ case VIEW_CONVERT_EXPR: return ConvertInitializer(TREE_OPERAND(exp, 0));
case POINTER_PLUS_EXPR: return ConvertPOINTER_PLUS_EXPR(exp);
case ADDR_EXPR:
return TheFolder->CreateBitCast(AddressOf(TREE_OPERAND(exp, 0)),
@@ -1070,10 +1407,10 @@
"Global with variable size?");
// First subtract the lower bound, if any, in the type of the index.
- Constant *IndexVal = ConvertConstant(Index);
+ Constant *IndexVal = ConvertInitializer(Index);
tree LowerBound = array_ref_low_bound(exp);
if (!integer_zerop(LowerBound))
- IndexVal = TheFolder->CreateSub(IndexVal, ConvertConstant(LowerBound),
+ IndexVal = TheFolder->CreateSub(IndexVal, ConvertInitializer(LowerBound),
hasNUW(TREE_TYPE(Index)),
hasNSW(TREE_TYPE(Index)));
@@ -1125,7 +1462,7 @@
assert(!(BITS_PER_UNIT & 7) && "Unit size not a multiple of 8 bits!");
if (TREE_OPERAND(exp, 2)) {
- Offset = ConvertConstant(TREE_OPERAND(exp, 2));
+ Offset = ConvertInitializer(TREE_OPERAND(exp, 2));
// At this point the offset is measured in units divided by (exactly)
// (DECL_OFFSET_ALIGN / BITS_PER_UNIT). Convert to octets.
unsigned factor = DECL_OFFSET_ALIGN(FieldDecl) / 8;
@@ -1135,7 +1472,7 @@
factor));
} else {
assert(DECL_FIELD_OFFSET(FieldDecl) && "Field offset not available!");
- Offset = ConvertConstant(DECL_FIELD_OFFSET(FieldDecl));
+ Offset = ConvertInitializer(DECL_FIELD_OFFSET(FieldDecl));
// At this point the offset is measured in units. Convert to octets.
unsigned factor = BITS_PER_UNIT / 8;
if (factor != 1)
@@ -1204,7 +1541,7 @@
break;
case INDIRECT_REF:
// The lvalue is just the address.
- LV = ConvertConstant(TREE_OPERAND(exp, 0));
+ LV = ConvertInitializer(TREE_OPERAND(exp, 0));
break;
case COMPOUND_LITERAL_EXPR: // FIXME: not gimple - defined by C front-end
/* This used to read
Modified: dragonegg/trunk/Constants.h
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.h?rev=127804&r1=127803&r2=127804&view=diff
==============================================================================
--- dragonegg/trunk/Constants.h (original)
+++ dragonegg/trunk/Constants.h Thu Mar 17 04:03:33 2011
@@ -24,14 +24,12 @@
#ifndef DRAGONEGG_CONSTANTS_H
#define DRAGONEGG_CONSTANTS_H
-union tree_node;
-
+// Forward declarations.
namespace llvm {
class Constant;
+ class Type;
}
-
-// Constant Expressions
-extern llvm::Constant *ConvertConstant(tree_node *exp);
+union tree_node;
/// AddressOf - Given an expression with a constant address such as a constant,
/// a global variable or a label, returns the address. The type of the returned
@@ -40,4 +38,19 @@
/// (see ConvertType).
extern llvm::Constant *AddressOf(tree_node *exp);
+/// ConvertInitializer - Convert the initial value for a global variable to an
+/// equivalent LLVM constant. Also handles constant constructors. The type of
+/// the returned value may be pretty much anything. All that is guaranteed is
+/// that it has the same alloc size as the original expression and has alignment
+/// equal to or less than that of the original expression.
+extern llvm::Constant *ConvertInitializer(tree_node *exp);
+
+/// InterpretAsType - Interpret the bits of the given constant (starting from
+/// StartingBit) as representing a constant of type 'Ty'. This results in the
+/// same constant as you would get by storing the bits of 'C' to memory (with
+/// the first bit stored being 'StartingBit') and then loading out a (constant)
+/// value of type 'Ty' from the stored to memory location.
+extern llvm::Constant *InterpretAsType(llvm::Constant *C, const llvm::Type* Ty,
+ unsigned StartingBit);
+
#endif /* DRAGONEGG_CONSTANTS_H */
Modified: dragonegg/trunk/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Convert.cpp?rev=127804&r1=127803&r2=127804&view=diff
==============================================================================
--- dragonegg/trunk/Convert.cpp (original)
+++ dragonegg/trunk/Convert.cpp Thu Mar 17 04:03:33 2011
@@ -6005,8 +6005,20 @@
/// EmitConstantVectorConstructor - Turn the given constant CONSTRUCTOR into
/// an LLVM constant of the corresponding vector register type.
Constant *TreeToLLVM::EmitConstantVectorConstructor(tree reg) {
- Constant *C = ConvertConstant(reg);
- return Mem2Reg(C, TREE_TYPE(reg), *TheFolder);
+ // Get the constructor as an LLVM constant.
+ Constant *C = ConvertInitializer(reg);
+ // The constant may have pretty much any type, for example it could be a bunch
+ // of bytes. Extract the vector elements from the constant.
+ tree elt_type = TREE_TYPE (TREE_TYPE (reg));
+ const Type *EltTy = GetRegType(elt_type);
+ unsigned NumElts = TYPE_VECTOR_SUBPARTS(TREE_TYPE(reg));
+ // Get the spacing between consecutive vector elements. Obtain this from the
+ // GCC type in case the LLVM type is something funky like i1.
+ unsigned Stride = GET_MODE_BITSIZE (TYPE_MODE (elt_type));
+ SmallVector<Constant*, 16> Vals(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i)
+ Vals[i] = InterpretAsType(C, EltTy, i*Stride);
+ return ConstantVector::get(Vals);
}
/// EmitVectorRegisterConstant - Turn the given VECTOR_CST into an LLVM constant
More information about the llvm-commits
mailing list