[llvm-commits] [dragonegg] r128710 - /dragonegg/trunk/Constants.cpp
Duncan Sands
baldrick at free.fr
Fri Apr 1 03:44:34 PDT 2011
Author: baldrick
Date: Fri Apr 1 05:44:33 2011
New Revision: 128710
URL: http://llvm.org/viewvc/llvm-project?rev=128710&view=rev
Log:
GCC allows implicit (scalar) type casts when an initial value
is "assigned" to a field. Handle the case of record fields as
well as array elements, and factor out the casting code.
Modified:
dragonegg/trunk/Constants.cpp
Modified: dragonegg/trunk/Constants.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/trunk/Constants.cpp?rev=128710&r1=128709&r2=128710&view=diff
==============================================================================
--- dragonegg/trunk/Constants.cpp (original)
+++ dragonegg/trunk/Constants.cpp Fri Apr 1 05:44:33 2011
@@ -482,6 +482,40 @@
// ... ConvertInitializer ...
//===----------------------------------------------------------------------===//
+/// ConvertInitializerWithCast - Convert the initial value for a global variable
+/// to an equivalent LLVM constant then cast to the given type if both the type
+/// and the initializer are scalar. This is convenient for making explicit the
+/// implicit scalar casts that GCC allows in "assignments" such as initializing
+/// a record field.
+static Constant *ConvertInitializerWithCast(tree exp, tree type) {
+ // Convert the initializer.
+ Constant *C = ConvertInitializer(exp);
+
+ // If no cast is needed, or it would not be a scalar cast, then just return
+ // the initializer as is.
+ 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.
+ 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.
+ 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);
+}
+
/// ConvertCST - Return the given simple constant as an array of bytes. For the
/// moment only INTEGER_CST, REAL_CST, COMPLEX_CST and VECTOR_CST are supported.
static Constant *ConvertCST(tree exp) {
@@ -579,8 +613,6 @@
// If we have a lower bound for the range of the type, get it.
tree init_type = TREE_TYPE(exp);
tree elt_type = TREE_TYPE(init_type);
- const Type *EltTy = ConvertType(elt_type);
- bool EltIsSigned = !TYPE_UNSIGNED(elt_type);
tree min_element = size_zero_node;
std::vector<Constant*> ResultElts;
@@ -609,19 +641,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 = ConvertInitializer(elt_value);
-
- // If needed, cast the value to the type of the array element.
- if (TREE_TYPE(elt_value) != elt_type && !AGGREGATE_TYPE_P(elt_type) &&
- !AGGREGATE_TYPE_P(TREE_TYPE(elt_value))) {
- const Type *ValTy = ConvertType(TREE_TYPE(elt_value));
- Val = InterpretAsType(Val, ValTy, 0);
- bool ValIsSigned = !TYPE_UNSIGNED(TREE_TYPE(elt_value));
- Instruction::CastOps opcode = CastInst::getCastOpcode(Val, ValIsSigned,
- EltTy, EltIsSigned);
- Val = TheFolder->CreateCast(opcode, Val, EltTy);
- }
-
+ Constant *Val = ConvertInitializerWithCast(elt_value, elt_type);
SomeVal = Val;
// Get the index position of the element within the array. Note that this
@@ -904,7 +924,7 @@
assert(TREE_CODE(field) == FIELD_DECL && "Initial value not for a field!");
assert(OffsetIsLLVMCompatible(field) && "Field position not known!");
// Turn the initial value for this field into an LLVM constant.
- Constant *Init = ConvertInitializer(value);
+ Constant *Init = ConvertInitializerWithCast(value, TREE_TYPE(field));
// Work out the range of bits occupied by the field.
uint64_t FirstBit = getFieldOffsetInBits(field);
assert(FirstBit <= TypeSize && "Field off end of type!");
@@ -1011,22 +1031,6 @@
}
}
-static Constant *ConvertCONVERT_EXPR(tree exp) {
- if (AGGREGATE_TYPE_P(TREE_TYPE(exp)) ||
- AGGREGATE_TYPE_P(TREE_TYPE(TREE_OPERAND(exp, 0)))) {
- // A no-op record view conversion. These do not change any of the bits in
- // the constant so just ignore them.
- return ConvertInitializer(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));
- Instruction::CastOps opcode = CastInst::getCastOpcode(Elt, EltIsSigned, Ty,
- TyIsSigned);
- return TheFolder->CreateCast(opcode, Elt, Ty);
-}
-
static Constant *ConvertBinOp_CST(tree exp) {
Constant *LHS = ConvertInitializer(TREE_OPERAND(exp, 0));
bool LHSIsSigned = !TYPE_UNSIGNED(TREE_TYPE(TREE_OPERAND(exp,0)));
@@ -1104,7 +1108,7 @@
break;
case CONVERT_EXPR:
case NOP_EXPR:
- Init = ConvertCONVERT_EXPR(exp);
+ Init = ConvertInitializerWithCast(TREE_OPERAND(exp, 0), TREE_TYPE(exp));
break;
case MINUS_EXPR:
case PLUS_EXPR:
More information about the llvm-commits
mailing list