aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGCall.cpp15
-rw-r--r--test/CodeGen/x86_64-arguments.c6
2 files changed, 14 insertions, 7 deletions
diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp
index 954ac53068..248619fc2d 100644
--- a/lib/CodeGen/CGCall.cpp
+++ b/lib/CodeGen/CGCall.cpp
@@ -1638,13 +1638,7 @@ static void CreateCoercedStore(llvm::Value *Src,
uint64_t DstSize = CGF.CGM.getTargetData().getTypeAllocSize(DstTy);
// If store is legal, just bitcast the src pointer.
- if (SrcSize >= DstSize) {
- // Generally SrcSize is never greater than DstSize, since this means we are
- // losing bits. However, this can happen in cases where the structure has
- // additional padding, for example due to a user specified alignment.
- //
- // FIXME: Assert that we aren't truncating non-padding bits when have access
- // to that information.
+ if (SrcSize <= DstSize) {
llvm::Value *Casted =
CGF.Builder.CreateBitCast(DstPtr, llvm::PointerType::getUnqual(SrcTy));
// FIXME: Use better alignment / avoid requiring aligned store.
@@ -1652,6 +1646,13 @@ static void CreateCoercedStore(llvm::Value *Src,
} else {
// Otherwise do coercion through memory. This is stupid, but
// simple.
+
+ // Generally SrcSize is never greater than DstSize, since this means we are
+ // losing bits. However, this can happen in cases where the structure has
+ // additional padding, for example due to a user specified alignment.
+ //
+ // FIXME: Assert that we aren't truncating non-padding bits when have access
+ // to that information.
llvm::Value *Tmp = CGF.CreateTempAlloca(SrcTy);
CGF.Builder.CreateStore(Src, Tmp);
llvm::Value *Casted =
diff --git a/test/CodeGen/x86_64-arguments.c b/test/CodeGen/x86_64-arguments.c
index 6f7ec82872..0b68afdb4e 100644
--- a/test/CodeGen/x86_64-arguments.c
+++ b/test/CodeGen/x86_64-arguments.c
@@ -82,4 +82,10 @@ void f16(float a, float b, float c, float d, float e, float f, float g, float h,
void f17(float a, float b, float c, float d, float e, float f, float g, float h,
long double X) {}
+// Check for valid coercion.
+// RUN: grep '.1 = bitcast i64. .tmp to .struct.f18_s0.' %t &&
+// RUN: grep '.2 = load .struct.f18_s0. .1, align 1' %t &&
+// RUN: grep 'store .struct.f18_s0 .2, .struct.f18_s0. .f18_arg1' %t &&
+void f18(int a, struct f18_s0 { int f0; } f18_arg1) {}
+
// RUN: true