Skip to content

Commit 9025cf8

Browse files
committed
SILGen: Add comments describing call decomposition in more detail, NFC
1 parent ca48f14 commit 9025cf8

File tree

3 files changed

+60
-14
lines changed

3 files changed

+60
-14
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,9 @@ static ManagedValue emitPartialSuperMethod(SILGenFunction &SGF,
222222

223223
namespace {
224224

225-
/// Abstractly represents a callee, and knows how to emit the entry point
226-
/// reference for a callee at any valid uncurry level.
225+
/// Abstractly represents a callee, which may be a constant or function value,
226+
/// and knows how to perform dynamic dispatch and reference the appropriate
227+
/// entry point at any valid uncurry level.
227228
class Callee {
228229
public:
229230
enum class Kind {
@@ -834,12 +835,28 @@ static Callee prepareArchetypeCallee(SILGenFunction &gen, SILLocation loc,
834835
constant, substFnType, loc);
835836
}
836837

837-
/// An ASTVisitor for building SIL function calls.
838+
/// An ASTVisitor for decomposing a a nesting of ApplyExprs into an initial
839+
/// Callee and a list of CallSites. The CallEmission class below uses these
840+
/// to generate the actual SIL call.
838841
///
839-
/// Nested ApplyExprs applied to an underlying curried function or method
840-
/// reference are flattened into a single SIL apply to the most uncurried entry
841-
/// point fitting the call site, avoiding pointless intermediate closure
842-
/// construction.
842+
/// Formally, an ApplyExpr in the AST always has a single argument, which may
843+
/// be of tuple type, possibly empty. Also, some callees have a formal type
844+
/// which is curried -- for example, methods have type Self -> Arg -> Result.
845+
///
846+
/// However, SIL functions take zero or more parameters and the natural entry
847+
/// point of a method takes Self as an additional argument, rather than
848+
/// returning a partial application.
849+
///
850+
/// Therefore, nested ApplyExprs applied to a constant are flattened into a
851+
/// single call of the most uncurried entry point fitting the call site.
852+
/// This avoids intermediate closure construction.
853+
///
854+
/// For example, a method reference 'self.method' decomposes into curry thunk
855+
/// as the callee, with a single call site '(self)'.
856+
///
857+
/// On the other hand, a call of a method 'self.method(x)(y)' with a function
858+
/// return type decomposes into the method's natural entry point as the callee,
859+
/// and two call sites, first '(x, self)' then '(y)'.
843860
class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
844861
public:
845862
/// The SILGenFunction that we are emitting SIL into.
@@ -1200,7 +1217,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
12001217
SILDeclRef::ConstructAtNaturalUncurryLevel,
12011218
SGF.SGM.requiresObjCDispatch(e->getDecl()));
12021219

1203-
// Otherwise, we have a direct call.
1220+
// Otherwise, we have a statically-dispatched call.
12041221
CanFunctionType substFnType = getSubstFnType();
12051222
ArrayRef<Substitution> subs;
12061223

@@ -2988,6 +3005,8 @@ namespace {
29883005
}
29893006
};
29903007

3008+
/// An application of possibly unevaluated arguments in the form of an
3009+
/// ArgumentSource to a Callee.
29913010
class CallSite {
29923011
public:
29933012
SILLocation Loc;
@@ -3027,6 +3046,7 @@ namespace {
30273046

30283047
bool throws() const { return Throws; }
30293048

3049+
/// Evaluate arguments and begin any inout formal accesses.
30303050
void emit(SILGenFunction &gen, AbstractionPattern origParamType,
30313051
ParamLowering &lowering, SmallVectorImpl<ManagedValue> &args,
30323052
SmallVectorImpl<InOutArgument> &inoutArgs,
@@ -3039,6 +3059,7 @@ namespace {
30393059
emitter.emitTopLevel(std::move(ArgValue), origParamType);
30403060
}
30413061

3062+
/// Take the arguments for special processing, in place of the above.
30423063
ArgumentSource &&forward() && {
30433064
return std::move(ArgValue);
30443065
}
@@ -3079,6 +3100,18 @@ namespace {
30793100
}
30803101
};
30813102

3103+
/// Once the Callee and CallSites have been prepared by SILGenApply,
3104+
/// generate SIL for a fully-formed call.
3105+
///
3106+
/// The lowered function type of the callee defines an abstraction pattern
3107+
/// for evaluating argument values of tuple type directly into explosions of
3108+
/// scalars where possible.
3109+
///
3110+
/// If there are more call sites than the natural uncurry level, they are
3111+
/// have to be applied recursively to each intermediate callee.
3112+
///
3113+
/// Also inout formal access and parameter and result conventions are
3114+
/// handled here, with some special logic required for calls with +0 self.
30823115
class CallEmission {
30833116
SILGenFunction &gen;
30843117

@@ -3091,6 +3124,7 @@ namespace {
30913124
bool AssumedPlusZeroSelf;
30923125

30933126
public:
3127+
/// Create an emission for a call of the given callee.
30943128
CallEmission(SILGenFunction &gen, Callee &&callee,
30953129
WritebackScope &&writebackScope,
30963130
bool assumedPlusZeroSelf = false)
@@ -3102,6 +3136,8 @@ namespace {
31023136
AssumedPlusZeroSelf(assumedPlusZeroSelf)
31033137
{}
31043138

3139+
/// Add a level of function application by passing in its possibly
3140+
/// unevaluated arguments and their formal type.
31053141
void addCallSite(CallSite &&site) {
31063142
assert(!applied && "already applied!");
31073143

@@ -3115,7 +3151,9 @@ namespace {
31153151
// Otherwise, apply these arguments to the result of the previous call.
31163152
extraSites.push_back(std::move(site));
31173153
}
3118-
3154+
3155+
/// Add a level of function application by passing in its possibly
3156+
/// unevaluated arguments and their formal type
31193157
template<typename...T>
31203158
void addCallSite(T &&...args) {
31213159
addCallSite(CallSite{std::forward<T>(args)...});
@@ -3134,12 +3172,15 @@ namespace {
31343172
uncurriedSites[0].convertToPlusOneFromPlusZero(gen);
31353173
}
31363174

3175+
/// Emit the fully-formed call.
31373176
ManagedValue apply(SGFContext C = SGFContext()) {
31383177
assert(!applied && "already applied!");
31393178

31403179
applied = true;
31413180

3142-
// Get the callee value at the needed uncurry level.
3181+
// Get the callee value at the needed uncurry level, uncurrying as
3182+
// much as possible. If the number of calls is less than the natural
3183+
// uncurry level, the callee emission might create a curry thunk.
31433184
unsigned uncurryLevel = callee.getNaturalUncurryLevel() - uncurries;
31443185

31453186
// Get either the specialized emitter for a known function, or the
@@ -3263,6 +3304,8 @@ namespace {
32633304
args = {};
32643305

32653306
// Emit the uncurried call.
3307+
3308+
// Handle a regular call.
32663309
if (!specializedEmitter) {
32673310
result = gen.emitApply(uncurriedLoc.getValue(), mv,
32683311
callee.getSubstitutions(),
@@ -3273,6 +3316,7 @@ namespace {
32733316
initialOptions, None,
32743317
foreignError,
32753318
uncurriedContext);
3319+
// Handle a specialized emitter operating on evaluated arguments.
32763320
} else if (specializedEmitter->isLateEmitter()) {
32773321
auto emitter = specializedEmitter->getLateEmitter();
32783322
result = emitter(gen,
@@ -3281,6 +3325,7 @@ namespace {
32813325
uncurriedArgs,
32823326
formalApplyType,
32833327
uncurriedContext);
3328+
// Special case for superclass method calls.
32843329
} else if (specializedEmitter->isLatePartialSuperEmitter()) {
32853330
auto emitter = specializedEmitter->getLatePartialSuperEmitter();
32863331
result = emitter(gen,
@@ -3290,6 +3335,8 @@ namespace {
32903335
uncurriedArgs,
32913336
formalApplyType,
32923337
uncurriedContext);
3338+
3339+
// Builtins.
32933340
} else {
32943341
assert(specializedEmitter->isNamedBuiltin());
32953342
auto builtinName = specializedEmitter->getBuiltinName();

lib/SILGen/SILGenConvert.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,8 @@
3030
using namespace swift;
3131
using namespace Lowering;
3232

33-
// FIXME: need to sit down and abstract away differences between
34-
// SGF::emitInjectOptionalInto(), SGF::emitInjectOptionalValueInto(),
35-
// SGF::getOptionalSomeValue(), and this function...
33+
// FIXME: With some changes to their callers, all of the below functions
34+
// could be re-worked to use emitInjectEnum().
3635
ManagedValue
3736
SILGenFunction::emitInjectOptional(SILLocation loc,
3837
ManagedValue v,

lib/SILGen/SpecializedEmitter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ class SILGenModule;
3737
/// Some kind of specialized emitter for a builtin function.
3838
class SpecializedEmitter {
3939
public:
40-
/// A special function for emitting a call after the arguments
40+
/// A special function for emitting a call before the arguments
4141
/// have already been emitted.
4242
using EarlyEmitter = ManagedValue (SILGenFunction &,
4343
SILLocation,

0 commit comments

Comments
 (0)