[llvm-commits] CVS: llvm-gcc/gcc/llvm-expand.c
Chris Lattner
lattner at cs.uiuc.edu
Fri Feb 18 23:27:00 PST 2005
Changes in directory llvm-gcc/gcc:
llvm-expand.c updated: 1.82 -> 1.83
---
Log message:
Fix PR517: http://llvm.cs.uiuc.edu/PR517 and Regression/C++Frontend/2005-02-19-BitfieldStructCrash.cpp
Apparently the GCC IR allows 'X = Y' where X can be an aggregate, and Y is
a bitfield reference. It also allows X to be a bitfield and Y to be an
aggregate. No, there is no such thing in C as a aggregate bitfield.
---
Diffs of the changes: (+81 -18)
llvm-expand.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++-----------
1 files changed, 81 insertions(+), 18 deletions(-)
Index: llvm-gcc/gcc/llvm-expand.c
diff -u llvm-gcc/gcc/llvm-expand.c:1.82 llvm-gcc/gcc/llvm-expand.c:1.83
--- llvm-gcc/gcc/llvm-expand.c:1.82 Tue Feb 15 00:59:52 2005
+++ llvm-gcc/gcc/llvm-expand.c Sat Feb 19 01:26:44 2005
@@ -2906,29 +2906,62 @@
static void llvm_store_expr(llvm_function *Fn, tree From, llvm_value *Dest,
llvm_value **CompVal, unsigned BitStart,
unsigned BitSize, int isVolatile) {
+ llvm_type *SrcType = llvm_type_get_from_tree(TREE_TYPE(From));
llvm_type *ResultType = GET_POINTER_TYPE_ELEMENT(Dest->Ty);
- if (!llvm_type_is_composite(ResultType)) {
- llvm_value *Val = llvm_expand_expr(Fn, From, 0);
-
- /* If expand was not able to provide the correct type, cast now */
- Val = cast_if_type_not_equal(Fn, Val, ResultType);
- if (CompVal) *CompVal = Val;
-
- /* Copy the value computed into the destination. If this is not a bitfield,
- * this is just a store, otherwise we need to emit a load, some masking,
- * then a store.
+ llvm_value *Val = 0;
+
+ if (llvm_type_is_composite(SrcType)) {
+ llvm_value *TmpLoc;
+
+ /* If this isn't a bitfield reference, expand the value directly into the
+ * destination.
*/
- Val = WriteBitField(Fn, Val, Dest, BitStart, BitSize, isVolatile);
+ if (BitSize == 0) {
+ /* Expand the RHS into the appropriate location directly. */
+ llvm_value *Val = llvm_expand_expr(Fn, From, Dest);
+ if (CompVal) *CompVal = 0;
+ assert(Val == 0 && "Structure value returned a value??");
+ return;
+ }
+
+ /* Otherwise, expand into a temporary location. This must be an aggregate
+ * with one element.
+ */
+ TmpLoc = D2V(make_temporary_alloca(Fn, SrcType));
+ Val = llvm_expand_expr(Fn, From, TmpLoc);
+ assert(Val == 0 && "Structure value returned a value??");
- append_inst(Fn, create_store_inst(Val, Dest, isVolatile));
+ /* This may be something like {{{{int}}}}, unwrap it. */
+ while (llvm_type_is_composite(SrcType)) {
+ assert(SrcType->ID == StructTyID && SrcType->NumElements == 1 &&
+ "Not a single element!?");
+ TmpLoc = append_inst(Fn, create_gep3(TmpLoc, llvm_constant_uint_0,
+ llvm_constant_uint_0));
+ SrcType = SrcType->Elements[0];
+ }
+ Val = append_inst(Fn, create_load_inst("aggel", TmpLoc, 0));
+ /* If the element is not exactly the right type, convert it now. */
+ Val = cast_if_type_not_equal(Fn, Val, ResultType);
} else {
- /* Expand the RHS into the appropriate location directly. */
- llvm_value *Val = llvm_expand_expr(Fn, From, Dest);
- if (CompVal) *CompVal = 0;
- assert(Val == 0 && "Structure value returned a value??");
- assert(!BitSize && "Store of aggregate into a bitfield??");
+ /* Simple scalar value, common case. */
+ Val = llvm_expand_expr(Fn, From, 0);
+
+ /* If expand was not able to provide the correct type, cast now */
+ Val = cast_if_type_not_equal(Fn, Val, ResultType);
+ if (CompVal) *CompVal = Val;
}
+
+ assert(!llvm_type_is_composite(ResultType) &&
+ "Storing a scalar or bitfield value into a composite value?");
+
+ /* Copy the value computed into the destination. If this is not a bitfield,
+ * this is just a store, otherwise we need to emit a load, some masking,
+ * then a store.
+ */
+ Val = WriteBitField(Fn, Val, Dest, BitStart, BitSize, isVolatile);
+
+ append_inst(Fn, create_store_inst(Val, Dest, isVolatile));
}
@@ -5933,7 +5966,8 @@
unsigned BitStart = 0, BitSize = 0;
op0 = llvm_expand_lvalue_expr(Fn, exp, &BitStart, &BitSize);
- if (!isDestTyComposite) { /* Return a normal scalar by loading it */
+ /* Return a normal scalar by loading it. */
+ if (!llvm_type_is_composite(GET_POINTER_TYPE_ELEMENT(op0->Ty))) {
unsigned ResultBitSize;
Result = append_inst(Fn, create_load_inst("tmp", op0, expVolatile));
@@ -5953,6 +5987,35 @@
*/
Result = ReadBitField(Fn, Result, BitStart, BitSize);
+ /* WIERDNESS: G++ allows loading from a bitfield and storing into an
+ * aggregate. For example, the aggregate may have type "{ushort}", and
+ * the lvalue might be of type "int*" with some bit offset/size. The
+ * bitfieldness has already been taken care of, we just check to see if
+ * we need to store to the aggregate location now.
+ */
+ if (isDestTyComposite) {
+ /* The destination can only be a single element structure. We handle
+ * {{{uint}}} for generality.
+ */
+ while (llvm_type_is_composite(GET_POINTER_TYPE_ELEMENT(DestLoc->Ty))){
+ llvm_type *ElTy = GET_POINTER_TYPE_ELEMENT(DestLoc->Ty);
+ assert(ElTy->ID == StructTyID && ElTy->NumElements == 1 &&
+ "Bitfield store to non-single-element aggregate!");
+ DestLoc = append_inst(Fn, create_gep3(DestLoc,
+ llvm_constant_intptr_0,
+ llvm_constant_uint_0));
+ }
+
+ /* If the source isn't the exact type needed for the store, make it so
+ * now.
+ */
+ Result =cast_if_type_not_equal(Fn, Result,
+ GET_POINTER_TYPE_ELEMENT(DestLoc->Ty));
+ /* Finally, do the store into the aggregate. */
+ append_inst(Fn, create_store_inst(Result, DestLoc, 0));
+ Result = 0;
+ }
+
} else if (DestLoc) { /* Generating structure, using value */
unsigned Align = TYPE_ALIGN(TREE_TYPE(exp))/8;
assert(BitSize == 0 && "Invalid bitfield read of composite value!");
More information about the llvm-commits
mailing list