[llvm-commits] [dragonegg] r130236 - /dragonegg/trunk/src/Constants.cpp
Duncan Sands
baldrick at free.fr
Tue Apr 26 13:00:59 PDT 2011
Author: baldrick
Date: Tue Apr 26 15:00:59 2011
New Revision: 130236
URL: http://llvm.org/viewvc/llvm-project?rev=130236&view=rev
Log:
Only do arithmetic on constants of "register type". The code for
handling constants now has no assumptions about what ConvertType
and ConvertInitializer return.
Modified:
dragonegg/trunk/src/Constants.cpp
Modified: dragonegg/trunk/src/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/src/Constants.cpp?rev=130236&r1=130235&r2=130236&view=diff
==============================================================================
--- dragonegg/trunk/src/Constants.cpp (original)
+++ dragonegg/trunk/src/Constants.cpp Tue Apr 26 15:00:59 2011
@@ -399,7 +399,7 @@
/// 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, int StartingBit) {
+Constant *InterpretAsType(Constant *C, const Type* Ty, int StartingBit = 0) {
if (C->getType() == Ty)
return C;
@@ -493,7 +493,7 @@
/// using LoadRegisterFromMemory to load a register value back out starting from
/// byte StartingByte.
Constant *ExtractRegisterFromConstant(Constant *C, tree type, int StartingByte) {
- // NOTE: Needs to be kept in sync with getRegType.
+ // NOTE: Needs to be kept in sync with getRegType and EncapsulateRegister.
int StartingBit = StartingByte * BITS_PER_UNIT;
switch (TREE_CODE(type)) {
@@ -515,8 +515,8 @@
}
case COMPLEX_TYPE: {
- tree elt_type = TREE_TYPE (type);
- unsigned Stride = GET_MODE_BITSIZE (TYPE_MODE (elt_type));
+ tree elt_type = TREE_TYPE(type);
+ unsigned Stride = GET_MODE_BITSIZE(TYPE_MODE(elt_type));
Constant *Vals[2] = {
ExtractRegisterFromConstant(C, elt_type, StartingBit),
ExtractRegisterFromConstant(C, elt_type, StartingBit + Stride)
@@ -535,9 +535,9 @@
return InterpretAsType(C, getRegType(type), StartingBit);
case VECTOR_TYPE: {
- tree elt_type = TREE_TYPE (type);
+ tree elt_type = TREE_TYPE(type);
unsigned NumElts = TYPE_VECTOR_SUBPARTS(type);
- unsigned Stride = GET_MODE_BITSIZE (TYPE_MODE (elt_type));
+ unsigned Stride = GET_MODE_BITSIZE(TYPE_MODE(elt_type));
SmallVector<Constant*, 16> Vals(NumElts);
for (unsigned i = 0; i != NumElts; ++i) {
Vals[i] = ExtractRegisterFromConstant(C, elt_type, StartingBit+i*Stride);
@@ -559,6 +559,89 @@
// ... ConvertInitializer ...
//===----------------------------------------------------------------------===//
+/// EncapsulateRegister - Turn a constant of in-register type (corresponding
+/// to the given GCC type) into an in-memory constant. The result has the
+/// property that applying ExtractRegisterFromConstant to it gives you the
+/// original in-register constant back again.
+static Constant *EncapsulateRegister(Constant *C, tree type) {
+ // NOTE: Needs to be kept in sync with ExtractRegisterFromConstant.
+ assert(C->getType() == getRegType(type) && "Constant has wrong type!");
+ Constant *Result;
+
+ switch (TREE_CODE(type)) {
+
+ default:
+ DieAbjectly("Unknown register type!", type);
+
+ case BOOLEAN_TYPE:
+ case ENUMERAL_TYPE:
+ case INTEGER_TYPE: {
+ // For integral types extend to an integer with size equal to the type size.
+ // For example, when inserting a bool this probably extends it to an i8 or
+ // to an i32. This approach means we get the right result on both little
+ // and big endian machines.
+ uint64_t Size = getInt64(TYPE_SIZE(type), true);
+ const Type *MemTy = IntegerType::get(Context, Size);
+ // We can extend in any way, but get nicer IR by respecting signedness.
+ bool isSigned = !TYPE_UNSIGNED(type);
+ Result = isSigned ? TheFolder->CreateSExtOrBitCast(C, MemTy) :
+ TheFolder->CreateZExtOrBitCast(C, MemTy);
+ break;
+ }
+
+ case COMPLEX_TYPE: {
+ tree elt_type = TREE_TYPE(type);
+ unsigned Idx[2] = {0, 1};
+ Constant *Real = TheFolder->CreateExtractValue(C, Idx, 1);
+ Constant *Imag = TheFolder->CreateExtractValue(C, Idx + 1, 1);
+ Real = EncapsulateRegister(Real, elt_type);
+ Imag = EncapsulateRegister(Imag, elt_type);
+ Constant *Vals[2] = { Real, Imag };
+ Result = ConstantStruct::get(Context, Vals, 2, false);
+ break;
+ }
+
+ case OFFSET_TYPE:
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ Result = C;
+ break;
+
+ case REAL_TYPE:
+ // NOTE: This might be wrong for floats with precision less than their alloc
+ // size on big-endian machines.
+ // If the float precision is less than the alloc size then it will be padded
+ // out below.
+ Result = C;
+ break;
+
+ case VECTOR_TYPE: {
+ tree elt_type = TREE_TYPE(type);
+ unsigned NumElts = TYPE_VECTOR_SUBPARTS(type);
+ std::vector<Constant*> Vals(NumElts);
+ for (unsigned i = 0; i != NumElts; ++i) {
+ ConstantInt *Idx = ConstantInt::get(Type::getInt32Ty(Context), i);
+ Vals[i] = TheFolder->CreateExtractElement(C, Idx);
+ Vals[i] = EncapsulateRegister(Vals[i], elt_type);
+ }
+ // The elements may have funky types, so forming a vector may not always be
+ // possible.
+ Result = ConstantStruct::get(Context, Vals, false);
+ break;
+ }
+
+ }
+
+ // Ensure that the result satisfies the guarantees given by ConvertInitializer
+ // by turning it into a type with the right size and an appropriate alignment.
+ Result = InterpretAsType(Result, ConvertType(type));
+
+ assert(C == ExtractRegisterFromConstant(Result, type) &&
+ "Register inserted wrong!");
+
+ return Result;
+}
+
/// getAsRegister - Turn the given GCC scalar constant into an LLVM constant of
/// register type.
static Constant *getAsRegister(tree exp) {
@@ -580,24 +663,29 @@
if (type == TREE_TYPE(exp) || AGGREGATE_TYPE_P(TREE_TYPE(exp)) ||
AGGREGATE_TYPE_P(type))
return C;
- const Type *SrcTy = ConvertType(TREE_TYPE(exp));
- const Type *DestTy = ConvertType(type);
- // LLVM types are often the same even when the GCC types differ.
+ // No cast is needed if the LLVM types are the same. This occurs often since
+ // many different GCC types usually map to the same LLVM type.
+ const Type *SrcTy = getRegType(TREE_TYPE(exp));
+ const Type *DestTy = getRegType(type);
if (SrcTy == DestTy)
return C;
- // First ensure that the initializer has a sensible type. Note that it would
- // be wrong to interpret the constant as being of type DestTy here since that
- // would not perform a value extension (adding extra zeros or sign bits when
- // casting to a larger integer type for example): any extra bits would get an
- // undefined value instead.
- C = InterpretAsType(C, SrcTy, 0);
- // Now cast to the desired type.
+ // Ensure that the initializer has a sensible type. Note that it would be
+ // wrong to just interpret the constant as being of type DestTy here since
+ // that would not perform a value extension (adding extra zeros or sign bits
+ // when casting to a larger integer type for example): any extra bits would
+ // wrongly get an undefined value instead.
+ C = ExtractRegisterFromConstant(C, TREE_TYPE(exp));
+
+ // Cast to the desired type.
bool SrcIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
bool DestIsSigned = !TYPE_UNSIGNED(type);
Instruction::CastOps opcode = CastInst::getCastOpcode(C, SrcIsSigned, DestTy,
DestIsSigned);
- return TheFolder->CreateCast(opcode, C, DestTy);
+ C = TheFolder->CreateCast(opcode, C, DestTy);
+
+ // Turn the register constant back into an in-memory constant.
+ return EncapsulateRegister(C, type);
}
/// ConvertCST - Return the given simple constant as an array of bytes. For the
@@ -927,7 +1015,7 @@
// The integer type used to hold the bits was too big (for example an i24
// typically occupies 32 bits so is too big for a range of 24 bits). Turn
// it into an array of bytes instead.
- C = InterpretAsType(C, GetUnitType(Context, Units), 0);
+ C = InterpretAsType(C, GetUnitType(Context, Units));
assert(isSafeToReturnContentsDirectly(TD) && "Unit over aligned?");
return C;
}
@@ -1126,9 +1214,9 @@
}
static Constant *ConvertBinOp_CST(tree exp) {
- Constant *LHS = ConvertInitializer(TREE_OPERAND(exp, 0));
+ Constant *LHS = getAsRegister(TREE_OPERAND(exp, 0));
bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 0)));
- Constant *RHS = ConvertInitializer(TREE_OPERAND(exp, 1));
+ Constant *RHS = getAsRegister(TREE_OPERAND(exp, 1));
bool RHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp, 1)));
Instruction::CastOps opcode;
if (LHS->getType()->isPointerTy()) {
@@ -1146,24 +1234,30 @@
case MINUS_EXPR: Result = TheFolder->CreateSub(LHS, RHS); break;
}
- const Type *Ty = ConvertType(TREE_TYPE(exp));
+ const Type *Ty = getRegType(TREE_TYPE(exp));
bool TyIsSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
opcode = CastInst::getCastOpcode(Result, LHSIsSigned, Ty, TyIsSigned);
- return TheFolder->CreateCast(opcode, Result, Ty);
+ Result = TheFolder->CreateCast(opcode, Result, Ty);
+
+ // Turn the register constant back into an in-memory constant.
+ return EncapsulateRegister(Result, TREE_TYPE(exp));
}
static Constant *ConvertPOINTER_PLUS_EXPR(tree exp) {
- Constant *Ptr = ConvertInitializer(TREE_OPERAND(exp, 0)); // The pointer.
- Constant *Idx = ConvertInitializer(TREE_OPERAND(exp, 1)); // Offset in units.
+ Constant *Ptr = getAsRegister(TREE_OPERAND(exp, 0)); // The pointer.
+ Constant *Idx = getAsRegister(TREE_OPERAND(exp, 1)); // Offset in units.
// Convert the pointer into an i8* and add the offset to it.
Ptr = TheFolder->CreateBitCast(Ptr, GetUnitPointerType(Context));
- Constant *GEP = POINTER_TYPE_OVERFLOW_UNDEFINED ?
+ Constant *Result = POINTER_TYPE_OVERFLOW_UNDEFINED ?
TheFolder->CreateInBoundsGetElementPtr(Ptr, &Idx, 1) :
TheFolder->CreateGetElementPtr(Ptr, &Idx, 1);
// The result may be of a different pointer type.
- return TheFolder->CreateBitCast(GEP, ConvertType(TREE_TYPE(exp)));
+ Result = TheFolder->CreateBitCast(Result, getRegType(TREE_TYPE(exp)));
+
+ // Turn the register constant back into an in-memory constant.
+ return EncapsulateRegister(Result, TREE_TYPE(exp));
}
static Constant *ConvertVIEW_CONVERT_EXPR(tree exp) {
@@ -1189,9 +1283,7 @@
case INTEGER_CST:
case REAL_CST:
case VECTOR_CST:
- // Make the IR easier to read by converting the bunch of bytes returned by
- // ConvertCST into a less surprising type.
- Init = InterpretAsType(ConvertCST(exp), ConvertType(TREE_TYPE(exp)), 0);
+ Init = ConvertCST(exp);
break;
case STRING_CST:
Init = ConvertSTRING_CST(exp);
@@ -1218,6 +1310,11 @@
break;
}
+ // Make the IR easier to read by converting the bunch of bytes returned by
+ // ConvertCST into a less surprising type when it is safe to do so.
+ if (!AGGREGATE_TYPE_P(TREE_TYPE(exp)))
+ Init = InterpretAsType(Init, ConvertType(TREE_TYPE(exp)));
+
#ifndef NDEBUG
// Check that the guarantees we make about the returned value actually hold.
// The initializer should always be at least as big as the constructor's type,
@@ -1259,9 +1356,9 @@
// Create a new global variable.
Slot = new GlobalVariable(*TheModule, Init->getType(), true,
GlobalVariable::PrivateLinkage, Init, ".cst");
- unsigned align = TYPE_ALIGN (TREE_TYPE (exp));
+ unsigned align = TYPE_ALIGN(TREE_TYPE(exp));
#ifdef CONSTANT_ALIGNMENT
- align = CONSTANT_ALIGNMENT (exp, align);
+ align = CONSTANT_ALIGNMENT(exp, align);
#endif
Slot->setAlignment(align);
@@ -1351,9 +1448,7 @@
/// AddressOfINDIRECT_REF - Return the address of a dereference.
static Constant *AddressOfINDIRECT_REF(tree exp) {
// The address is just the dereferenced operand. Get it as an LLVM constant.
- Constant *C = ConvertInitializer(TREE_OPERAND(exp, 0));
- // Make no assumptions about the type of the constant.
- return InterpretAsType(C, ConvertType(TREE_TYPE(TREE_OPERAND(exp, 0))), 0);
+ return getAsRegister(TREE_OPERAND(exp, 0));
}
/// AddressOfLABEL_DECL - Return the address of a label.
@@ -1401,7 +1496,7 @@
Addr = AddressOfCOMPONENT_REF(exp);
break;
case COMPOUND_LITERAL_EXPR: // FIXME: not gimple - defined by C front-end
- Addr = AddressOf(DECL_EXPR_DECL (TREE_OPERAND (exp, 0)));
+ Addr = AddressOf(DECL_EXPR_DECL(TREE_OPERAND(exp, 0)));
break;
case CONST_DECL:
case FUNCTION_DECL:
More information about the llvm-commits
mailing list