[dragonegg] r182391 - Port bitfield fixes from mainline.

Duncan Sands baldrick at free.fr
Tue May 21 09:08:58 PDT 2013


Author: baldrick
Date: Tue May 21 11:08:58 2013
New Revision: 182391

URL: http://llvm.org/viewvc/llvm-project?rev=182391&view=rev
Log:
Port bitfield fixes from mainline.

Added:
    dragonegg/branches/release_33/test/compilator/local/ada/bitfield.adb
      - copied unchanged from r182103, dragonegg/trunk/test/compilator/local/ada/bitfield.adb
    dragonegg/branches/release_33/test/compilator/local/ada/bitfield.ads
      - copied unchanged from r182103, dragonegg/trunk/test/compilator/local/ada/bitfield.ads
    dragonegg/branches/release_33/test/compilator/local/ada/pr15984.adb
      - copied unchanged from r182103, dragonegg/trunk/test/compilator/local/ada/pr15984.adb
    dragonegg/branches/release_33/test/compilator/local/ada/pr15984.ads
      - copied unchanged from r182103, dragonegg/trunk/test/compilator/local/ada/pr15984.ads
Modified:
    dragonegg/branches/release_33/   (props changed)
    dragonegg/branches/release_33/src/Convert.cpp

Propchange: dragonegg/branches/release_33/
------------------------------------------------------------------------------
    svn:mergeinfo = /dragonegg/trunk:181689-182103

Modified: dragonegg/branches/release_33/src/Convert.cpp
URL: http://llvm.org/viewvc/llvm-project/dragonegg/branches/release_33/src/Convert.cpp?rev=182391&r1=182390&r2=182391&view=diff
==============================================================================
--- dragonegg/branches/release_33/src/Convert.cpp (original)
+++ dragonegg/branches/release_33/src/Convert.cpp Tue May 21 11:08:58 2013
@@ -2809,50 +2809,65 @@ Value *TreeToLLVM::EmitLoadOfLValue(tree
   // TODO: Arrange for Volatile to already be set in the LValue.
   unsigned Alignment = LV.getAlignment();
 
-  if (!LV.isBitfield()) {
+  tree type = TREE_TYPE(exp);
+  if (!LV.isBitfield())
     // Scalar value: emit a load.
-    return LoadRegisterFromMemory(LV, TREE_TYPE(exp), describeAliasSet(exp),
-                                  Builder);
-  } else {
-    // This is a bitfield reference.
-    Type *Ty = getRegType(TREE_TYPE(exp));
-    if (!LV.BitSize)
-      return Constant::getNullValue(Ty);
-
-    // Load the minimum number of bytes that covers the field.
-    unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
-    LoadSizeInBits = RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
-    Type *LoadType = IntegerType::get(Context, LoadSizeInBits);
-
-    // Load the bits.
-    Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
-    Value *Val = Builder.CreateAlignedLoad(Ptr, Alignment, LV.Volatile);
-
-    // Mask the bits out by shifting left first, then shifting right.  The
-    // optimizers will turn this into an "and" in the unsigned case.
-
-    // Shift the sign bit of the bitfield to the sign bit position in the loaded
-    // type.  This zaps any extra bits occurring after the end of the bitfield.
-    unsigned FirstBitInVal =
-        BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
-                         : LV.BitStart;
-    if (FirstBitInVal + LV.BitSize != LoadSizeInBits) {
-      Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits -
-                                                (FirstBitInVal + LV.BitSize));
-      Val = Builder.CreateShl(Val, ShAmt);
-    }
-    // Shift the first bit of the bitfield to be bit zero.  This zaps any extra
-    // bits that occurred before the start of the bitfield.  In the signed case
-    // this also duplicates the sign bit, giving a sign extended value.
-    bool isSigned = !TYPE_UNSIGNED(TREE_TYPE(exp));
-    Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits - LV.BitSize);
-    Val = isSigned ? Builder.CreateAShr(Val, ShAmt)
-                   : Builder.CreateLShr(Val, ShAmt);
-
-    // Get the bits as a value of the correct type.
-    // FIXME: This assumes the result is an integer.
-    return Builder.CreateIntCast(Val, Ty, isSigned);
-  }
+    return LoadRegisterFromMemory(LV, type, describeAliasSet(exp), Builder);
+
+  // This is a bitfield reference.
+  Type *Ty = getRegType(type);
+  if (!LV.BitSize)
+    return Constant::getNullValue(Ty);
+
+  // Load the minimum number of bytes that covers the field.
+  unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
+  LoadSizeInBits = RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
+  Type *LoadType = IntegerType::get(Context, LoadSizeInBits);
+
+  // Load the bits.
+  Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
+  Value *Val = Builder.CreateAlignedLoad(Ptr, Alignment, LV.Volatile);
+
+  // Mask the bits out by shifting left first, then shifting right.  The
+  // optimizers will turn this into an "and" in the unsigned case.
+
+  // Shift the sign bit of the bitfield to the sign bit position in the loaded
+  // type.  This zaps any extra bits occurring after the end of the bitfield.
+  unsigned FirstBitInVal =
+      BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
+                       : LV.BitStart;
+  if (FirstBitInVal + LV.BitSize != LoadSizeInBits) {
+    Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits -
+                                              (FirstBitInVal + LV.BitSize));
+    Val = Builder.CreateShl(Val, ShAmt);
+  }
+  // Shift the first bit of the bitfield to be bit zero.  This zaps any extra
+  // bits that occurred before the start of the bitfield.  In the signed case
+  // this also duplicates the sign bit, giving a sign extended value.
+  bool isSigned = !TYPE_UNSIGNED(type);
+  Value *ShAmt = ConstantInt::get(LoadType, LoadSizeInBits - LV.BitSize);
+  Val = isSigned ? Builder.CreateAShr(Val, ShAmt)
+                 : Builder.CreateLShr(Val, ShAmt);
+
+  // Get the bits as an integer with the same in-memory size as the result.
+  // Extending the integer with defined bits (rather than storing it as is to
+  // the temporary, which in effect extends with undefined bits) is required
+  // in order to get the right result for C-like languages.
+  unsigned MemSize = GET_MODE_BITSIZE(TYPE_MODE(type));
+  Type *ResIntTy = IntegerType::get(Context, MemSize);
+  Value *ResInt = Builder.CreateIntCast(Val, ResIntTy, isSigned);
+
+  // Create the temporary, an integer.  Ensure it is sufficiently aligned for
+  // both the integer and the real type.  Store the bits to it.
+  Alignment = std::max(TYPE_ALIGN(type) / 8,
+                       DL.getPrefTypeAlignment(ResIntTy));
+  MemRef Tmp(CreateTemporary(ResIntTy, Alignment), Alignment, false);
+  Builder.CreateStore(ResInt, Tmp.Ptr);
+
+  // At this point we have in essence just displaced the original set of bits to
+  // a new memory location that is byte aligned, from which we now trivially load
+  // the desired value.
+  return LoadRegisterFromMemory(Tmp, type, 0, Builder);
 }
 
 Value *TreeToLLVM::EmitADDR_EXPR(tree exp) {
@@ -9180,78 +9195,108 @@ bool TreeToLLVM::EmitBuiltinCall(gimple
                     : 0;
     }
 
-    /// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
-    void TreeToLLVM::WriteScalarToLHS(tree lhs, Value * RHS) {
-      // May need a useless type conversion (useless_type_conversion_p).
-      RHS = TriviallyTypeConvert(RHS, getRegType(TREE_TYPE(lhs)));
-
-      // If this is the definition of an ssa name, record it in the SSANames map.
-      if (isa<SSA_NAME>(lhs)) {
-        if (flag_verbose_asm)
-          NameValue(RHS, lhs);
-        DefineSSAName(lhs, RHS);
-        return;
-      }
+/// WriteScalarToLHS - Store RHS, a non-aggregate value, into the given LHS.
+void TreeToLLVM::WriteScalarToLHS(tree lhs, Value * RHS) {
+  tree type = TREE_TYPE(lhs);
+
+  // May need a useless type conversion (useless_type_conversion_p).
+  RHS = TriviallyTypeConvert(RHS, getRegType(type));
+
+  // If this is the definition of an ssa name, record it in the SSANames map.
+  if (isa<SSA_NAME>(lhs)) {
+    if (flag_verbose_asm)
+      NameValue(RHS, lhs);
+    DefineSSAName(lhs, RHS);
+    return;
+  }
 
-      if (canEmitRegisterVariable(lhs)) {
-        // If this is a store to a register variable, EmitLV can't handle the dest
-        // (there is no l-value of a register variable).  Emit an inline asm node
-        // that copies the value into the specified register.
-        EmitModifyOfRegisterVariable(lhs, RHS);
-        return;
-      }
+  if (canEmitRegisterVariable(lhs)) {
+    // If this is a store to a register variable, EmitLV can't handle the dest
+    // (there is no l-value of a register variable).  Emit an inline asm node
+    // that copies the value into the specified register.
+    EmitModifyOfRegisterVariable(lhs, RHS);
+    return;
+  }
 
-      LValue LV = EmitLV(lhs);
-      LV.Volatile = TREE_THIS_VOLATILE(lhs);
-      // TODO: Arrange for Volatile to already be set in the LValue.
-      if (!LV.isBitfield()) {
-        // Non-bitfield, scalar value.  Just emit a store.
-        StoreRegisterToMemory(RHS, LV, TREE_TYPE(lhs), describeAliasSet(lhs),
-                              Builder);
-        return;
-      }
+  LValue LV = EmitLV(lhs);
+  LV.Volatile = TREE_THIS_VOLATILE(lhs);
+  // TODO: Arrange for Volatile to already be set in the LValue.
+  if (!LV.isBitfield()) {
+    // Non-bitfield, scalar value.  Just emit a store.
+    StoreRegisterToMemory(RHS, LV, type, describeAliasSet(lhs), Builder);
+    return;
+  }
 
-      // Last case, this is a store to a bitfield, so we have to emit a
-      // read/modify/write sequence.
-      if (!LV.BitSize)
-        return;
+  // Last case, this is a store to a bitfield, so we have to emit a
+  // read/modify/write sequence.
+  if (!LV.BitSize)
+    return;
 
-      // Load and store the minimum number of bytes that covers the field.
-      unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
-      LoadSizeInBits =
-          (unsigned) RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
-      Type *LoadType = IntegerType::get(Context, LoadSizeInBits);
-
-      // Load the bits.
-      Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
-      Value *Val =
-          Builder.CreateAlignedLoad(Ptr, LV.getAlignment(), LV.Volatile);
-
-      // Get the right-hand side as a value of the same type.
-      // FIXME: This assumes the right-hand side is an integer.
-      bool isSigned = !TYPE_UNSIGNED(TREE_TYPE(lhs));
-      RHS = CastToAnyType(RHS, isSigned, LoadType, isSigned);
-
-      // Shift the right-hand side so that its bits are in the right position.
-      unsigned FirstBitInVal =
-          BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
-                           : LV.BitStart;
-      if (FirstBitInVal) {
-        Value *ShAmt = ConstantInt::get(LoadType, FirstBitInVal);
-        RHS = Builder.CreateShl(RHS, ShAmt);
-      }
-      // Mask out any bits in the right-hand side that shouldn't be in the result.
-      // The lower bits are zero already, so this only changes bits off the end.
-      APInt Mask = APInt::getBitsSet(LoadSizeInBits, FirstBitInVal,
-                                     FirstBitInVal + LV.BitSize);
-      if (FirstBitInVal + LV.BitSize != LoadSizeInBits)
-        RHS = Builder.CreateAnd(RHS, ConstantInt::get(Context, Mask));
-
-      // Mask out those bits in the original value that are being replaced by the
-      // right-hand side.
-      Val = Builder.CreateAnd(Val, ConstantInt::get(Context, ~Mask));
-
-      // Finally, merge the two together and store it.
-      Val = Builder.CreateOr(Val, RHS);
-      Builder.CreateAlignedStore(Val, Ptr, LV.getAlignment(), LV.Volatile);
-    }
+  // Load and store the minimum number of bytes that covers the field.
+  unsigned LoadSizeInBits = LV.BitStart + LV.BitSize;
+  LoadSizeInBits =
+      (unsigned) RoundUpToAlignment(LoadSizeInBits, BITS_PER_UNIT);
+  Type *LoadType = IntegerType::get(Context, LoadSizeInBits);
+
+  // Load the existing bits.
+  Value *Ptr = Builder.CreateBitCast(LV.Ptr, LoadType->getPointerTo());
+  Value *Val =
+      Builder.CreateAlignedLoad(Ptr, LV.getAlignment(), LV.Volatile);
+
+  // Turn RHS into a bunch of bits by storing it to a temporary then loading it
+  // out again as an integer.  The temporary needs to be big enough to hold the
+  // in-memory representation of RHS.  If the bitfield is wider than this (which
+  // only happens for non C-like languages) then any extra bits are undefined.
+  // We tell the optimizers that they are undefined by widening the temporary to
+  // at least the bitfield size but not storing anything to the extra bits.
+  unsigned MemSize = GET_MODE_BITSIZE(TYPE_MODE(type));
+  unsigned TmpSize = std::max(LoadSizeInBits, MemSize);
+  Type *TmpType = IntegerType::get(Context, TmpSize);
+
+  // Create the temporary, an integer.  Ensure it is aligned enough for both RHS
+  // and the integer version of RHS.
+  unsigned Alignment = std::max(TYPE_ALIGN(type) / 8,
+                                DL.getPrefTypeAlignment(TmpType));
+  Value *Tmp = CreateTemporary(TmpType, Alignment);
+
+  // Store the right-hand side to it.  Ensure that any extra bits turn up in the
+  // high bits of the integer loaded out below.
+  MemRef TmpLoc(Tmp, Alignment, false);
+  if (BYTES_BIG_ENDIAN && MemSize < LoadSizeInBits) {
+    unsigned BitOffset = LoadSizeInBits - MemSize;
+    assert(BitOffset % BITS_PER_UNIT == 0 && "Mode size not round?");
+    TmpLoc = DisplaceLocationByUnits(TmpLoc, BitOffset/BITS_PER_UNIT, Builder);
+  }
+  StoreRegisterToMemory(RHS, TmpLoc, type, 0, Builder);
+
+  // Load it out again as an integer.  Only the first LV.BitSize bits of this
+  // integer will be used (see the masking below).  For C-like languages, the
+  // original RHS is always an integer that is at least as wide as LV.BitSize,
+  // so the used bits are just the original integer truncated to be LV.BitSize
+  // bits wide.
+  RHS = Builder.CreateIntCast(Builder.CreateLoad(Tmp), LoadType,
+                              !TYPE_UNSIGNED(type));
+
+  // Shift the right-hand side so that its bits are in the right position.
+  unsigned FirstBitInVal =
+      BYTES_BIG_ENDIAN ? LoadSizeInBits - LV.BitStart - LV.BitSize
+                       : LV.BitStart;
+  if (FirstBitInVal) {
+    Value *ShAmt = ConstantInt::get(LoadType, FirstBitInVal);
+    RHS = Builder.CreateShl(RHS, ShAmt);
+  }
+  // Mask out any bits in the right-hand side that shouldn't be in the result.
+  // The lower bits are zero already, so this only changes bits off the end.
+  APInt Mask = APInt::getBitsSet(LoadSizeInBits, FirstBitInVal,
+                                 FirstBitInVal + LV.BitSize);
+  if (FirstBitInVal + LV.BitSize != LoadSizeInBits)
+    RHS = Builder.CreateAnd(RHS, ConstantInt::get(Context, Mask));
+
+  // Mask out those bits in the original value that are being replaced by the
+  // right-hand side.
+  Val = Builder.CreateAnd(Val, ConstantInt::get(Context, ~Mask));
+
+  // Finally, merge the two together and store it.
+  Val = Builder.CreateOr(Val, RHS);
+  Builder.CreateAlignedStore(Val, Ptr, LV.getAlignment(), LV.Volatile);
+}





More information about the llvm-commits mailing list