]> granicus.if.org Git - clang/commitdiff
When doing int<->ptr coercion for big-endian, calculate the shift amount correctly.
authorJames Molloy <james.molloy@arm.com>
Wed, 7 May 2014 17:41:15 +0000 (17:41 +0000)
committerJames Molloy <james.molloy@arm.com>
Wed, 7 May 2014 17:41:15 +0000 (17:41 +0000)
Previously we calculated the shift amount based upon DataLayout::getTypeAllocSizeInBits.
This will only work for legal types - types such as i24 that are created as part of
structs for bitfields will return "32" from that function. Change to using
getTypeSizeInBits.

It turns out that AArch64 didn't run across this problem because it always returned
[1 x i64] as the type for a bitfield, whereas ARM64 returns i64 so goes down this
(better, but wrong) codepath.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@208231 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCall.cpp
test/CodeGen/arm64-be-bitfield.c [new file with mode: 0644]

index da504739836a994345257f5ded66c1e5ae6c698e..972a7c8dbb7778df8ae96d1bd34b2ad11477635c 100644 (file)
@@ -700,8 +700,9 @@ static llvm::Value *CoerceIntOrPtrToIntOrPtr(llvm::Value *Val,
     if (DL.isBigEndian()) {
       // Preserve the high bits on big-endian targets.
       // That is what memory coercion does.
-      uint64_t SrcSize = DL.getTypeAllocSizeInBits(Val->getType());
-      uint64_t DstSize = DL.getTypeAllocSizeInBits(DestIntTy);
+      uint64_t SrcSize = DL.getTypeSizeInBits(Val->getType());
+      uint64_t DstSize = DL.getTypeSizeInBits(DestIntTy);
+
       if (SrcSize > DstSize) {
         Val = CGF.Builder.CreateLShr(Val, SrcSize - DstSize, "coerce.highbits");
         Val = CGF.Builder.CreateTrunc(Val, DestIntTy, "coerce.val.ii");
diff --git a/test/CodeGen/arm64-be-bitfield.c b/test/CodeGen/arm64-be-bitfield.c
new file mode 100644 (file)
index 0000000..f563596
--- /dev/null
@@ -0,0 +1,9 @@
+// RUN:  %clang_cc1 -triple arm64_be-linux-gnu -ffreestanding -emit-llvm -O0 -o - %s | FileCheck %s
+
+struct bt3 { signed b2:10; signed b3:10; } b16;
+
+// The correct right-shift amount is 40 bits for big endian.
+signed callee_b0f(struct bt3 bp11) {
+// CHECK: = lshr i64 %{{.*}}, 40
+  return bp11.b2;
+}