Skip to content

Commit 01bf682

Browse files
authored
Merge pull request #4794 from DougGregor/objc-super-partial-forwarder-3-0
[IRGen] Handle 'super' method sends in ObjC partial application forwarders
2 parents 8db7b08 + e6ba4c4 commit 01bf682

File tree

4 files changed

+65
-37
lines changed

4 files changed

+65
-37
lines changed

lib/IRGen/GenObjC.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ llvm::Value *irgen::emitObjCAllocObjectCall(IRGenFunction &IGF,
785785
}
786786

787787
static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
788-
SILDeclRef method,
788+
ObjCMethod method,
789789
CanSILFunctionType origMethodType,
790790
CanSILFunctionType resultType,
791791
const HeapLayout &layout,
@@ -883,18 +883,21 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
883883
}
884884

885885
// Prepare the call to the underlying method.
886+
886887
CallEmission emission
887-
= prepareObjCMethodRootCall(subIGF, method, origMethodType, origMethodType,
888+
= prepareObjCMethodRootCall(subIGF, method.getMethod(),
889+
origMethodType, origMethodType,
888890
ArrayRef<Substitution>{},
889-
ObjCMessageKind::Normal);
891+
method.getMessageKind());
890892

891893
Explosion args;
892894

893895
// Take care of formal indirect returns ourselves.
894896
if (formalIndirectResult)
895897
args.add(formalIndirectResult);
896898

897-
addObjCMethodCallImplicitArguments(subIGF, args, method, self, SILType());
899+
addObjCMethodCallImplicitArguments(subIGF, args, method.getMethod(), self,
900+
method.getSearchType());
898901
args.add(params.claimAll());
899902
emission.setArgs(args);
900903

@@ -929,7 +932,7 @@ static llvm::Function *emitObjCPartialApplicationForwarder(IRGenModule &IGM,
929932
}
930933

931934
void irgen::emitObjCPartialApplication(IRGenFunction &IGF,
932-
SILDeclRef method,
935+
ObjCMethod method,
933936
CanSILFunctionType origMethodType,
934937
CanSILFunctionType resultType,
935938
llvm::Value *self,

lib/IRGen/GenObjC.h

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,42 @@ namespace irgen {
4646
Peer
4747
};
4848

49+
/// Represents an ObjC method reference that will be invoked by a form of
50+
/// objc_msgSend.
51+
class ObjCMethod {
52+
/// The SILDeclRef declaring the method.
53+
SILDeclRef method;
54+
/// For a bounded call, the static type that provides the lower bound for
55+
/// the search. Null for unbounded calls that will look for the method in
56+
/// the dynamic type of the object.
57+
llvm::PointerIntPair<SILType, 1, bool> searchTypeAndSuper;
58+
59+
public:
60+
ObjCMethod(SILDeclRef method, SILType searchType, bool startAtSuper)
61+
: method(method), searchTypeAndSuper(searchType, startAtSuper)
62+
{}
63+
64+
SILDeclRef getMethod() const { return method; }
65+
SILType getSearchType() const { return searchTypeAndSuper.getPointer(); }
66+
bool shouldStartAtSuper() const { return searchTypeAndSuper.getInt(); }
67+
68+
/// FIXME: Thunk down to a Swift function value?
69+
llvm::Value *getExplosionValue(IRGenFunction &IGF) const {
70+
llvm_unreachable("thunking unapplied objc method to swift function "
71+
"not yet implemented");
72+
}
73+
74+
/// Determine the kind of message that should be sent to this
75+
/// method.
76+
ObjCMessageKind getMessageKind() const {
77+
// Determine the kind of message send to perform.
78+
if (!getSearchType()) return ObjCMessageKind::Normal;
79+
80+
return shouldStartAtSuper()? ObjCMessageKind::Super
81+
: ObjCMessageKind::Peer;
82+
}
83+
};
84+
4985
CallEmission prepareObjCMethodRootCall(IRGenFunction &IGF,
5086
SILDeclRef method,
5187
CanSILFunctionType origFnType,
@@ -62,7 +98,7 @@ namespace irgen {
6298
/// Emit a partial application of an Objective-C method to its 'self'
6399
/// argument.
64100
void emitObjCPartialApplication(IRGenFunction &IGF,
65-
SILDeclRef method,
101+
ObjCMethod method,
66102
CanSILFunctionType origType,
67103
CanSILFunctionType partialAppliedType,
68104
llvm::Value *self,

lib/IRGen/IRGenSIL.cpp

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -100,32 +100,6 @@ class StaticFunction {
100100
llvm::Value *getExplosionValue(IRGenFunction &IGF) const;
101101
};
102102

103-
/// Represents an ObjC method reference that will be invoked by a form of
104-
/// objc_msgSend.
105-
class ObjCMethod {
106-
/// The SILDeclRef declaring the method.
107-
SILDeclRef method;
108-
/// For a bounded call, the static type that provides the lower bound for
109-
/// the search. Null for unbounded calls that will look for the method in
110-
/// the dynamic type of the object.
111-
llvm::PointerIntPair<SILType, 1, bool> searchTypeAndSuper;
112-
113-
public:
114-
ObjCMethod(SILDeclRef method, SILType searchType, bool startAtSuper)
115-
: method(method), searchTypeAndSuper(searchType, startAtSuper)
116-
{}
117-
118-
SILDeclRef getMethod() const { return method; }
119-
SILType getSearchType() const { return searchTypeAndSuper.getPointer(); }
120-
bool shouldStartAtSuper() const { return searchTypeAndSuper.getInt(); }
121-
122-
/// FIXME: Thunk down to a Swift function value?
123-
llvm::Value *getExplosionValue(IRGenFunction &IGF) const {
124-
llvm_unreachable("thunking unapplied objc method to swift function "
125-
"not yet implemented");
126-
}
127-
};
128-
129103
/// Represents a SIL value lowered to IR, in one of these forms:
130104
/// - an Address, corresponding to a SIL address value;
131105
/// - an Explosion of (unmanaged) Values, corresponding to a SIL "register"; or
@@ -1919,10 +1893,7 @@ static CallEmission getCallEmissionForLoweredValue(IRGenSILFunction &IGF,
19191893
case LoweredValue::Kind::ObjCMethod: {
19201894
assert(selfValue);
19211895
auto &objcMethod = lv.getObjCMethod();
1922-
ObjCMessageKind kind = ObjCMessageKind::Normal;
1923-
if (objcMethod.getSearchType())
1924-
kind = objcMethod.shouldStartAtSuper()? ObjCMessageKind::Super
1925-
: ObjCMessageKind::Peer;
1896+
ObjCMessageKind kind = objcMethod.getMessageKind();
19261897

19271898
CallEmission emission =
19281899
prepareObjCMethodRootCall(IGF, objcMethod.getMethod(),
@@ -2245,7 +2216,7 @@ void IRGenSILFunction::visitPartialApplyInst(swift::PartialApplyInst *i) {
22452216

22462217
Explosion function;
22472218
emitObjCPartialApplication(*this,
2248-
objcMethod.getMethod(),
2219+
objcMethod,
22492220
i->getOrigCalleeType(),
22502221
i->getType().castTo<SILFunctionType>(),
22512222
selfVal,

test/IRGen/objc_super.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import gizmo
1111
// CHECK: [[TYPE:%swift.type]] = type
1212
// CHECK: [[HOOZIT:%C10objc_super6Hoozit]] = type
1313
// CHECK: [[NSRECT:%VSC6NSRect]] = type
14+
// CHECK: [[PARTIAL_APPLY_CLASS:%C10objc_super12PartialApply]] = type
1415
// CHECK: [[SUPER:%objc_super]] = type
1516
// CHECK: [[OBJC:%objc_object]] = type
1617
// CHECK: [[GIZMO:%CSo5Gizmo]] = type
@@ -67,3 +68,20 @@ class Hoozit : Gizmo {
6768
}
6869
// CHECK: }
6970
}
71+
72+
func acceptFn(_ fn: () -> Void) { }
73+
74+
class PartialApply : Gizmo {
75+
// CHECK: define hidden void @_TFC10objc_super12PartialApply4frobfT_T_([[PARTIAL_APPLY_CLASS]]*) {{.*}} {
76+
override func frob() {
77+
// CHECK: call void @_TF10objc_super8acceptFnFFT_T_T_(i8* bitcast (void (%swift.refcounted*)* [[PARTIAL_FORWARDING_THUNK:@[A-Za-z0-9_]+]] to i8*), %swift.refcounted* %3)
78+
acceptFn( super.frob )
79+
}
80+
// CHECK: }
81+
82+
// CHECK: define internal void [[PARTIAL_FORWARDING_THUNK]](%swift.refcounted*) #0 {
83+
// CHECK: call %swift.type* @_TMaC10objc_super12PartialApply()
84+
// CHECK: @"\01L_selector(frob)"
85+
// CHECK: call void bitcast (void ()* @objc_msgSendSuper2
86+
// CHECK: }
87+
}

0 commit comments

Comments
 (0)