Skip to content

Commit 0e31acb

Browse files
committed
[IRGen] Emit missing sret for function arguments
If the IR representation of a C++ function takes an `SRet` parameter instead of a return value, Swift needs to wrap the corresponding argument with `sret(...)` on call site. This fixes SILOptimizer crashes on arm64. rdar://92963081
1 parent db08503 commit 0e31acb

File tree

9 files changed

+84
-11
lines changed

9 files changed

+84
-11
lines changed

lib/IRGen/GenCall.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2917,8 +2917,19 @@ llvm::CallInst *IRBuilder::CreateCall(const FunctionPointer &fn,
29172917
llvm::CallInst *call =
29182918
IRBuilderBase::CreateCall(fnTy, fn.getRawPointer(), args, bundles);
29192919

2920-
call->setAttributes(
2921-
fixUpTypesInByValAndStructRetAttributes(fnTy, fn.getAttributes()));
2920+
llvm::AttributeList attrs = fn.getAttributes();
2921+
// If a parameter of a function is SRet, the corresponding argument should be
2922+
// wrapped in SRet(...).
2923+
if (auto func = dyn_cast<llvm::Function>(fn.getRawPointer())) {
2924+
for (unsigned argIndex = 0; argIndex < func->arg_size(); ++argIndex) {
2925+
if (func->hasParamAttribute(argIndex, llvm::Attribute::StructRet)) {
2926+
llvm::AttrBuilder builder;
2927+
builder.addStructRetAttr(nullptr);
2928+
attrs = attrs.addParamAttributes(func->getContext(), argIndex, builder);
2929+
}
2930+
}
2931+
}
2932+
call->setAttributes(fixUpTypesInByValAndStructRetAttributes(fnTy, attrs));
29222933
call->setCallingConv(fn.getCallingConv());
29232934
return call;
29242935
}

test/Interop/Cxx/class/Inputs/module.modulemap

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,8 @@ module ForwardDeclaredCxxRecord {
102102
header "forward-declared-cxx-record.h"
103103
requires cplusplus
104104
}
105+
106+
module ReturnsLargeClass {
107+
header "returns-large-class.h"
108+
requires cplusplus
109+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#ifndef TEST_INTEROP_CXX_CLASS_INPUTS_RETURNS_LARGE_CLASS_H
2+
#define TEST_INTEROP_CXX_CLASS_INPUTS_RETURNS_LARGE_CLASS_H
3+
4+
struct LargeClass {
5+
long long a1 = 0;
6+
long long a2 = 0;
7+
long long a3 = 0;
8+
long long a4 = 0;
9+
long long a5 = 0;
10+
long long a6 = 0;
11+
long long a7 = 0;
12+
long long a8 = 0;
13+
};
14+
15+
LargeClass funcReturnsLargeClass() {
16+
LargeClass l;
17+
l.a2 = 2;
18+
l.a6 = 6;
19+
return l;
20+
}
21+
22+
#endif // TEST_INTEROP_CXX_CLASS_INPUTS_RETURNS_LARGE_CLASS_H
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-emit-ir -I %S/Inputs -enable-experimental-cxx-interop %s -validate-tbd-against-ir=none | %FileCheck %s
2+
3+
// This test verifies that Swift correctly emits IR calls to C++ functions that
4+
// had Named Return Value Optimization applied to them. The first argument of
5+
// such functions has `sret` attribute. When calling them, the first
6+
// parameter should be wrapped in `sret(...)`.
7+
8+
import ReturnsLargeClass
9+
10+
func foo() -> LargeClass {
11+
let x = funcReturnsLargeClass()
12+
return x
13+
}
14+
15+
foo()
16+
17+
// CHECK: call swiftcc void @"$s4main3fooSo10LargeClassVyF"(%TSo10LargeClassV* noalias nocapture sret(%TSo10LargeClassV) %{{.*}})
18+
19+
// The C++ function:
20+
// CHECK: define{{( dso_local)?}} void @{{_Z21funcReturnsLargeClassv|"\?funcReturnsLargeClass@@YA\?AULargeClass@@XZ"}}({{%struct.LargeClass\*|ptr}} noalias sret(%struct.LargeClass){{( align .*)?}} %{{.*}})
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-experimental-cxx-interop -Xfrontend -validate-tbd-against-ir=none)
2+
3+
// REQUIRES: executable_test
4+
5+
// This test verifies that Swift correctly handles calls to C++ functions that
6+
// had Named Return Value Optimization applied to them.
7+
8+
import StdlibUnittest
9+
import ReturnsLargeClass
10+
11+
var LargeTypes = TestSuite("Large C++ Return Types")
12+
13+
LargeTypes.test("NRVO") {
14+
let x = funcReturnsLargeClass()
15+
16+
expectEqual(0, x.a1)
17+
expectEqual(2, x.a2)
18+
expectEqual(6, x.a6)
19+
expectEqual(0, x.a7)
20+
}
21+
22+
runAllTests()

test/Interop/Cxx/operators/member-inline.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ OperatorsTestSuite.test("LoadableIntWrapper.successor() (inline)") {
5252
expectEqual(42, wrapper.value)
5353
}
5454

55+
#if !os(Windows) // SR-13129
5556
OperatorsTestSuite.test("LoadableBoolWrapper.exclaim (inline)") {
5657
var wrapper = LoadableBoolWrapper(value: true)
5758

5859
let resultExclaim = !wrapper
5960
expectEqual(false, resultExclaim.value)
6061
}
62+
#endif
6163

6264
OperatorsTestSuite.test("AddressOnlyIntWrapper.call (inline)") {
6365
var wrapper = AddressOnlyIntWrapper(42)

test/SILOptimizer/addr_escape_info.sil

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
// REQUIRES: swift_in_compiler
44

5-
// Currently failing on arm: rdar://92963081
6-
// REQUIRES: CPU=x86_64
7-
85
sil_stage canonical
96

107
import Builtin

test/SILOptimizer/escape_info.sil

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
// REQUIRES: swift_in_compiler
44

5-
// Currently failing on arm: rdar://92963081
6-
// REQUIRES: CPU=x86_64
7-
85
sil_stage canonical
96

107
import Builtin

test/SILOptimizer/ranges.sil

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22

33
// REQUIRES: swift_in_compiler
44

5-
// Currently failing on arm: rdar://92963081
6-
// REQUIRES: CPU=x86_64
7-
85
sil_stage canonical
96

107
// CHECK-LABEL: Instruction range in basic_test:

0 commit comments

Comments
 (0)