From 09cc9b22352ded8f49fa998311038891d5291092 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 12 Jul 2017 12:44:04 -0700 Subject: [PATCH] [4.0] IRGen: Make sure to use the C function type's alignment for indirect byval arguments rdar://33242303 * Fix abitypes.swift test case * Use the max of abi alignment and swift's type alignment --- lib/IRGen/GenCall.cpp | 15 +++++++++++++-- test/IRGen/Inputs/c_functions.h | 11 +++++++++++ test/IRGen/abitypes.swift | 6 +++--- test/IRGen/c_functions.swift | 11 +++++++++++ 4 files changed, 38 insertions(+), 5 deletions(-) diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index 79faf83f5c080..fac359ee389bb 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -976,8 +976,9 @@ llvm::Type *SignatureExpansion::expandExternalSignatureTypes() { auto paramTy = getSILFuncConventions().getSILType(param); auto ¶mTI = cast(IGM.getTypeInfo(paramTy)); if (AI.getIndirectByVal()) - addByvalArgumentAttributes(IGM, Attrs, getCurParamIndex(), - paramTI.getFixedAlignment()); + addByvalArgumentAttributes( + IGM, Attrs, getCurParamIndex(), + Alignment(AI.getIndirectAlign().getQuantity())); addPointerParameter(paramTI.getStorageType()); break; } @@ -1851,6 +1852,16 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, auto &ti = cast(IGF.getTypeInfo(paramType)); Address addr = ti.allocateStack(IGF, paramType, false, "indirect-temporary").getAddress(); + // Set at least the alignment the ABI expects. + if (AI.getIndirectByVal()) { + auto ABIAlign = AI.getIndirectAlign(); + if (ABIAlign > addr.getAlignment()) { + auto *AS = cast(addr.getAddress()); + AS->setAlignment(ABIAlign.getQuantity()); + addr = Address(addr.getAddress(), Alignment(ABIAlign.getQuantity())); + } + } + ti.initialize(IGF, in, addr); out.add(addr.getAddress()); diff --git a/test/IRGen/Inputs/c_functions.h b/test/IRGen/Inputs/c_functions.h index 700d67711dfd5..e0b423983de3b 100644 --- a/test/IRGen/Inputs/c_functions.h +++ b/test/IRGen/Inputs/c_functions.h @@ -9,3 +9,14 @@ static inline void test_my_log() { __attribute__((internal_linkage)) static const char fmt[] = "foobar"; use(fmt); } + +extern void useInt(unsigned int); + +typedef struct { + unsigned int val[8]; +} a_thing; + +static inline void log_a_thing(const a_thing thing) { + useInt(thing.val[0]); + useInt(thing.val[7]); +} diff --git a/test/IRGen/abitypes.swift b/test/IRGen/abitypes.swift index bda17a2f09610..934643e09d2db 100644 --- a/test/IRGen/abitypes.swift +++ b/test/IRGen/abitypes.swift @@ -107,7 +107,7 @@ class Foo { } // Ensure that MyRect is passed as an indirect-byval on x86_64 because we run out of registers for direct arguments - // x86_64-macosx: define hidden float @_T08abitypes3FooC25getXFromRectIndirectByVal{{[_0-9a-zA-Z]*}}FTo(i8*, i8*, float, float, float, float, float, float, float, %TSC6MyRectV* byval align 4) unnamed_addr {{.*}} { + // x86_64-macosx: define hidden float @_T08abitypes3FooC25getXFromRectIndirectByVal{{[_0-9a-zA-Z]*}}FTo(i8*, i8*, float, float, float, float, float, float, float, %TSC6MyRectV* byval align 8) unnamed_addr {{.*}} { dynamic func getXFromRectIndirectByVal(_: Float, second _: Float, third _: Float, fourth _: Float, fifth _: Float, sixth _: Float, @@ -120,8 +120,8 @@ class Foo { // x86_64-macosx: define hidden swiftcc float @_T08abitypes3FooC25getXFromRectIndirectSwift{{[_0-9a-zA-Z]*}}F(i64, i64, %T8abitypes3FooC* swiftself) {{.*}} { func getXFromRectIndirectSwift(_ r: MyRect) -> Float { let f : Float = 1.0 - // x86_64-macosx: [[TEMP:%.*]] = alloca [[TEMPTYPE:%.*]], align 4 - // x86_64-macosx: [[RESULT:%.*]] = call float bitcast (void ()* @objc_msgSend to float (i8*, i8*, float, float, float, float, float, float, float, [[TEMPTYPE]]*)*)(i8* %{{.*}}, i8* %{{.*}}, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, [[TEMPTYPE]]* byval align 4 [[TEMP]]) + // x86_64-macosx: [[TEMP:%.*]] = alloca [[TEMPTYPE:%.*]], align 8 + // x86_64-macosx: [[RESULT:%.*]] = call float bitcast (void ()* @objc_msgSend to float (i8*, i8*, float, float, float, float, float, float, float, [[TEMPTYPE]]*)*)(i8* %{{.*}}, i8* %{{.*}}, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, float 1.000000e+00, [[TEMPTYPE]]* byval align 8 [[TEMP]]) // x86_64-macosx: ret float [[RESULT]] return getXFromRectIndirectByVal(f, second: f, third: f, fourth: f, fifth: f, sixth: f, seventh: f, withRect: r); } diff --git a/test/IRGen/c_functions.swift b/test/IRGen/c_functions.swift index b755af5745967..10767f0eca11a 100644 --- a/test/IRGen/c_functions.swift +++ b/test/IRGen/c_functions.swift @@ -12,3 +12,14 @@ func testOverloaded() { // CHECK: call void @{{.*}}test_my_log test_my_log() } // CHECK: {{^}$}} + +func test_indirect_by_val_alignment() { + let x = a_thing() + log_a_thing(x) +} + +// CHECK-LABEL: define hidden swiftcc void @_T011c_functions30test_indirect_by_val_alignmentyyF() +// CHECK: %indirect-temporary = alloca %TSC7a_thingV, align [[ALIGN:[0-9]+]] +// CHECK: [[CAST:%.*]] = bitcast %TSC7a_thingV* %indirect-temporary to %struct.a_thing* +// CHECK: call void @log_a_thing(%struct.a_thing* byval align [[ALIGN]] [[CAST]]) +// CHECK: define internal void @log_a_thing(%struct.a_thing* byval align [[ALIGN]]