Skip to content

Commit e8937fb

Browse files
committed
IRGen: partial_applies of ObjC methods must emit loads from loadable arguments that are passed indirectly
rdar://28464766
1 parent 2adff51 commit e8937fb

File tree

2 files changed

+58
-1
lines changed

2 files changed

+58
-1
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,36 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
883883
}
884884
}
885885

886+
// Translate direct parameters passed indirectly.
887+
Explosion translatedParams;
888+
889+
// We already handled self.
890+
assert(origMethodType->hasSelfParam());
891+
auto origParamInfos = origMethodType->getParameters();
892+
origParamInfos = origParamInfos.drop_back();
893+
894+
for (auto info : origParamInfos) {
895+
// Addresses consist of a single pointer argument.
896+
if (isIndirectParameter(info.getConvention())) {
897+
translatedParams.add(params.claimNext());
898+
continue;
899+
}
900+
// Otherwise, we have a loadable type that can either be passed directly or
901+
// indirectly.
902+
assert(info.getSILType().isObject());
903+
auto &ti = cast<LoadableTypeInfo>(IGM.getTypeInfo(info.getSILType()));
904+
auto schema = ti.getSchema();
905+
906+
// Load the indirectly passed parameter.
907+
if (schema.requiresIndirectParameter(IGM)) {
908+
Address paramAddr = ti.getAddressForPointer(params.claimNext());
909+
ti.loadAsTake(subIGF, paramAddr, translatedParams);
910+
continue;
911+
}
912+
// Pass along the value.
913+
ti.reexplode(subIGF, params, translatedParams);
914+
}
915+
886916
// Prepare the call to the underlying method.
887917

888918
CallEmission emission
@@ -899,7 +929,7 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
899929

900930
addObjCMethodCallImplicitArguments(subIGF, args, method.getMethod(), self,
901931
method.getSearchType());
902-
args.add(params.claimAll());
932+
args.add(translatedParams.claimAll());
903933
emission.setArgs(args);
904934

905935
// Cleanup that always has to occur after the function call.

test/IRGen/partial_apply.sil

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import gizmo
1212

1313
@objc class ObjCClass : BaseClassForMethodFamilies {
1414
func method(x: Int) {}
15+
func method2(r: NSRect) {}
1516

1617
override func fakeInitFamily() -> ObjCClass { return self }
1718
}
@@ -36,6 +37,11 @@ bb0(%0 : $Int, %1 : $ObjCClass):
3637
%v = tuple()
3738
return %v : $()
3839
}
40+
sil @_TToFC13partial_apply9ObjCClass7method2fT1rVSC6NSRect_T_ : $@convention(objc_method) (NSRect, ObjCClass) -> () {
41+
bb0(%0 : $NSRect, %1 : $ObjCClass):
42+
%v = tuple()
43+
return %v : $()
44+
}
3945

4046
sil @_TToFC13partial_apply9ObjCClass14fakeInitFamilyfT_S0_ : $@convention(objc_method) (@owned ObjCClass) -> @owned ObjCClass {
4147
bb0(%0 : $ObjCClass):
@@ -107,6 +113,27 @@ entry(%c : $ObjCClass):
107113
return %p : $@callee_owned Int -> ()
108114
}
109115

116+
// CHECK-LABEL: define{{.*}} { i8*, %swift.refcounted* } @objc_partial_apply_indirect_sil_argument(%C13partial_apply9ObjCClass*) {{.*}}
117+
// CHECK: [[CTX:%.*]] = call noalias %swift.refcounted* @rt_swift_allocObject
118+
// CHECK: [[CTX_ADDR:%.*]] = bitcast %swift.refcounted* [[CTX]] to [[CTXTYPE:<{ %swift.refcounted, %C13partial_apply9ObjCClass\* }>]]*
119+
// CHECK: [[SELF_ADDR:%.*]] = getelementptr inbounds [[CTXTYPE]], [[CTXTYPE]]* [[CTX_ADDR]], i32 0, i32 1
120+
// CHECK: store %C13partial_apply9ObjCClass* %0, %C13partial_apply9ObjCClass** [[SELF_ADDR]]
121+
// CHECK: [[CLOSURE:%.*]] = insertvalue { i8*, %swift.refcounted* } { i8* bitcast (void (%VSC6NSRect*, %swift.refcounted*)* [[OBJC_PARTIAL_APPLY_STUB2:@_TPA[A-Za-z0-9_.]*]] to i8*), %swift.refcounted* undef }, %swift.refcounted* [[CTX]], 1
122+
// CHECK: ret { i8*, %swift.refcounted* } [[CLOSURE]]
123+
// CHECK:}
124+
// CHECK: define internal void [[OBJC_PARTIAL_APPLY_STUB2]](%VSC6NSRect* noalias nocapture dereferenceable(32), %swift.refcounted*
125+
// CHECK: [[TMP:%.*]] = alloca %VSC6NSRect
126+
// CHECK: [[ORIGIN:%.*]] = getelementptr inbounds %VSC6NSRect, %VSC6NSRect* %0
127+
// CHECK: [[ORIGINX:%.*]] = getelementptr inbounds %VSC7NSPoint, %VSC7NSPoint* [[ORIGIN]]
128+
// CHECK: [[ORIGINXVAL:%*]] = getelementptr inbounds %Sd, %Sd* [[ORIGINX]]
129+
// CHECK: [[VAL:%.*]] = load double, double* [[ORIGINXVAL]]
130+
sil @objc_partial_apply_indirect_sil_argument : $@convention(thin) ObjCClass -> @callee_owned NSRect -> () {
131+
entry(%c : $ObjCClass):
132+
%m = class_method [volatile] %c : $ObjCClass, #ObjCClass.method2!1.foreign : (ObjCClass) -> (NSRect) -> () , $@convention(objc_method) (NSRect, ObjCClass) -> ()
133+
%p = partial_apply %m(%c) : $@convention(objc_method) (NSRect, ObjCClass) -> ()
134+
return %p : $@callee_owned NSRect -> ()
135+
}
136+
110137
// CHECK-LABEL: define{{( protected)?}} { i8*, %swift.refcounted* } @objc_partial_apply_consumes_self(%C13partial_apply9ObjCClass*) {{.*}} {
111138
// CHECK: bitcast %swift.refcounted* {{%.*}} to [[DATA_TYPE:<{ %swift.refcounted, %C13partial_apply9ObjCClass\* }>]]*
112139
// CHECK: insertvalue {{.*}} [[OBJC_CONSUMES_SELF_PARTIAL_APPLY_STUB:@_TPA[A-Za-z0-9_.]*]]

0 commit comments

Comments
 (0)