[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