Skip to content

[4.0] IRGen: Make sure to use the C function type's alignment for indirect byval arguments #10932

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions lib/IRGen/GenCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -976,8 +976,9 @@ llvm::Type *SignatureExpansion::expandExternalSignatureTypes() {
auto paramTy = getSILFuncConventions().getSILType(param);
auto &paramTI = cast<FixedTypeInfo>(IGM.getTypeInfo(paramTy));
if (AI.getIndirectByVal())
addByvalArgumentAttributes(IGM, Attrs, getCurParamIndex(),
paramTI.getFixedAlignment());
addByvalArgumentAttributes(
IGM, Attrs, getCurParamIndex(),
Alignment(AI.getIndirectAlign().getQuantity()));
addPointerParameter(paramTI.getStorageType());
break;
}
Expand Down Expand Up @@ -1851,6 +1852,16 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee,
auto &ti = cast<LoadableTypeInfo>(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<llvm::AllocaInst>(addr.getAddress());
AS->setAlignment(ABIAlign.getQuantity());
addr = Address(addr.getAddress(), Alignment(ABIAlign.getQuantity()));
}
}

ti.initialize(IGF, in, addr);

out.add(addr.getAddress());
Expand Down
11 changes: 11 additions & 0 deletions test/IRGen/Inputs/c_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
}
6 changes: 3 additions & 3 deletions test/IRGen/abitypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down
11 changes: 11 additions & 0 deletions test/IRGen/c_functions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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]]