Skip to content

Commit b99b6d8

Browse files
committed
IRGen: Properly adjust the closure type of a partial_apply of an objc_method
It needs to match with the (large loadable) lowered closure type in the rest of the program: Large types in the signature need to be passed indirectly. rdar://127367321
1 parent 55a2a41 commit b99b6d8

File tree

4 files changed

+72
-10
lines changed

4 files changed

+72
-10
lines changed

lib/IRGen/IRGenSIL.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6674,6 +6674,20 @@ void IRGenSILFunction::visitEndUnpairedAccessInst(EndUnpairedAccessInst *i) {
66746674
}
66756675

66766676
void IRGenSILFunction::visitConvertFunctionInst(swift::ConvertFunctionInst *i) {
6677+
auto &lv = getLoweredValue(i->getOperand());
6678+
if (lv.kind == LoweredValue::Kind::ObjCMethod) {
6679+
// LoadableByAddress lowering will insert convert_function instructions to
6680+
// change the type of a partial_apply instruction involving a objc_method
6681+
// convention, to change the partial_apply's SIL type (rewriting large types
6682+
// to @in_guaranteed/@out). This is important for pointer authentication.
6683+
6684+
// The convert_function instruction will carry the desired SIL type.
6685+
// Here we just forward the objective-c method.
6686+
auto &objcMethod = lv.getObjCMethod();
6687+
setLoweredObjCMethod(i, objcMethod.getMethod());
6688+
return;
6689+
}
6690+
66776691
// This instruction is specified to be a no-op.
66786692
Explosion temp = getLoweredExplosion(i->getOperand());
66796693

lib/IRGen/LoadableByAddress.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,12 @@ class LargeSILTypeMapper {
8181
irgen::IRGenModule &IGM);
8282
SmallVector<SILResultInfo, 2> getNewResults(GenericEnvironment *GenericEnv,
8383
CanSILFunctionType fnType,
84-
irgen::IRGenModule &Mod);
84+
irgen::IRGenModule &Mod,
85+
bool mustTransform = false);
8586
CanSILFunctionType getNewSILFunctionType(GenericEnvironment *env,
8687
CanSILFunctionType fnType,
87-
irgen::IRGenModule &IGM);
88+
irgen::IRGenModule &IGM,
89+
bool mustTransform = false);
8890
SILType getNewOptionalFunctionType(GenericEnvironment *GenericEnv,
8991
SILType storageType,
9092
irgen::IRGenModule &Mod);
@@ -241,8 +243,9 @@ bool LargeSILTypeMapper::newResultsDiffer(GenericEnvironment *GenericEnv,
241243

242244
static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
243245
CanSILFunctionType loweredTy,
244-
irgen::IRGenModule &Mod) {
245-
if (!modifiableFunction(loweredTy)) {
246+
irgen::IRGenModule &Mod,
247+
bool mustTransform = false) {
248+
if (!modifiableFunction(loweredTy) && !mustTransform) {
246249
return false;
247250
}
248251
if (loweredTy->getNumResults() != 1) {
@@ -259,7 +262,8 @@ static bool modNonFuncTypeResultType(GenericEnvironment *genEnv,
259262
SmallVector<SILResultInfo, 2>
260263
LargeSILTypeMapper::getNewResults(GenericEnvironment *GenericEnv,
261264
CanSILFunctionType fnType,
262-
irgen::IRGenModule &Mod) {
265+
irgen::IRGenModule &Mod,
266+
bool mustTransform) {
263267
// Get new SIL Function results - same as old results UNLESS:
264268
// 1) Function type results might have a different signature
265269
// 2) Large loadables are replaced by @out version
@@ -268,7 +272,7 @@ LargeSILTypeMapper::getNewResults(GenericEnvironment *GenericEnv,
268272
for (auto result : origResults) {
269273
SILType currResultTy = result.getSILStorageInterfaceType();
270274
SILType newSILType = getNewSILType(GenericEnv, currResultTy, Mod);
271-
if (modNonFuncTypeResultType(GenericEnv, fnType, Mod)) {
275+
if (modNonFuncTypeResultType(GenericEnv, fnType, Mod, mustTransform)) {
272276
// Case (2) Above
273277
SILResultInfo newSILResultInfo(newSILType.getASTType(),
274278
ResultConvention::Indirect);
@@ -288,8 +292,9 @@ LargeSILTypeMapper::getNewResults(GenericEnvironment *GenericEnv,
288292
CanSILFunctionType
289293
LargeSILTypeMapper::getNewSILFunctionType(GenericEnvironment *env,
290294
CanSILFunctionType fnType,
291-
irgen::IRGenModule &IGM) {
292-
if (!modifiableFunction(fnType)) {
295+
irgen::IRGenModule &IGM,
296+
bool mustTransform) {
297+
if (!modifiableFunction(fnType) && !mustTransform) {
293298
return fnType;
294299
}
295300

@@ -301,7 +306,7 @@ LargeSILTypeMapper::getNewSILFunctionType(GenericEnvironment *env,
301306

302307
auto newParams = getNewParameters(env, fnType, IGM);
303308
auto newYields = getNewYields(env, fnType, IGM);
304-
auto newResults = getNewResults(env, fnType, IGM);
309+
auto newResults = getNewResults(env, fnType, IGM, mustTransform);
305310
auto newFnType = SILFunctionType::get(
306311
fnType->getInvocationGenericSignature(),
307312
fnType->getExtInfo(),
@@ -2623,7 +2628,20 @@ void LoadableByAddress::recreateSingleApply(
26232628
// Change the type of the Closure
26242629
auto partialApplyConvention = castedApply->getCalleeConvention();
26252630
auto resultIsolation = castedApply->getResultIsolation();
2626-
2631+
// We do need to update the closure's funtion type to match with the other
2632+
// uses inside of the binary. Pointer auth cares about the SIL function
2633+
// type.
2634+
if (callee->getType().castTo<SILFunctionType>()->getExtInfo().getRepresentation() ==
2635+
SILFunctionTypeRepresentation::ObjCMethod) {
2636+
CanSILFunctionType newFnType =
2637+
MapperCache.getNewSILFunctionType(
2638+
genEnv,
2639+
callee->getType().castTo<SILFunctionType>(), *currIRMod,
2640+
/*mustTransform*/ true);
2641+
SILType newType = SILType::getPrimitiveObjectType(newFnType);
2642+
callee = applyBuilder.createConvertFunction(castedApply->getLoc(),
2643+
callee, newType, false);
2644+
}
26272645
auto newApply = applyBuilder.createPartialApply(
26282646
castedApply->getLoc(), callee, applySite.getSubstitutionMap(), callArgs,
26292647
partialApplyConvention, resultIsolation, castedApply->isOnStack());

test/IRGen/Inputs/large_c.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct SamplesType {
3030
void* AA;
3131
};
3232

33+
struct SamplesType samples();
3334

3435
typedef struct _ContainedType {
3536
unsigned int f1;
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %target-swift-frontend -I %t -emit-ir %s -import-objc-header %S/Inputs/large_c.h | %FileCheck %s
2+
// RUN: %target-swift-frontend -I %t -emit-ir %s -import-objc-header %S/Inputs/large_c.h -Xllvm -sil-print-after=loadable-address 2>&1 | %FileCheck %s --check-prefix=SIL
3+
4+
// REQUIRES: OS=ios && CPU=arm64e
5+
6+
import Foundation
7+
8+
@objc protocol P { @objc optional func testFunction(_ i: SamplesType) -> SamplesType }
9+
10+
class C: P { func testFunction(_ i: SamplesType) -> SamplesType { samples() } }
11+
12+
func test() {
13+
_ = (C() as P).testFunction?(samples())
14+
}
15+
16+
// Make sure the ptrauth discriminator at closure build and invocation time match.
17+
18+
// CHECK: @"$sTa.ptrauth" = private constant {{.*}} ptr @"$sTa"{{.*}} i64 55683 }, section "llvm.ptrauth"
19+
// CHECK: define hidden swiftcc void @"$s31loadable_by_address_objc_method4testyyF"()
20+
// CHECK: store {{.*}} @"$sTa.ptrauth"
21+
// CHECK: call swiftcc void {{.*}}(ptr {{.*}}sret(%TSo11SamplesTypeV) {{.*}} [ "ptrauth"(i32 0, i64 55683) ]
22+
// CHECK: }
23+
24+
test()
25+
26+
27+
// SIL: sil hidden @$s31loadable_by_address_objc_method4testyyF : $@convention(thin) () -> () {
28+
// SIL: [[C:%.*]] = convert_function {{.*}} : $@convention(objc_method) (SamplesType, @opened({{.*}}, any P) Self) -> SamplesType to $@convention(objc_method) (@in_guaranteed SamplesType, @opened({{.*}}, any P) Self) -> @out SamplesType
29+
// SIL: partial_apply [callee_guaranteed] [[C]]({{.*}}) : $@convention(objc_method) (@in_guaranteed SamplesType, @opened({{.*}}, any P) Self) -> @out SamplesType

0 commit comments

Comments
 (0)