SILGen: Extract some code into a new SILGenThunk.cpp file

Also replace the crazy templated preEmitFunction() with
something simpler.
This commit is contained in:
Slava Pestov
2017-03-28 18:30:37 -07:00
parent 3ad7df273f
commit 97a8ce4776
6 changed files with 353 additions and 311 deletions

View File

@@ -18,13 +18,10 @@
#include "SILGenFunction.h"
#include "RValue.h"
#include "Scope.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/SIL/SILArgument.h"
#include "swift/SIL/SILUndef.h"
#include "swift/AST/DiagnosticsSIL.h"
using namespace swift;
using namespace Lowering;
@@ -129,56 +126,6 @@ DeclName SILGenModule::getMagicFunctionName(SILDeclRef ref) {
llvm_unreachable("Unhandled SILDeclRefKind in switch.");
}
SILValue SILGenFunction::emitGlobalFunctionRef(SILLocation loc,
SILDeclRef constant,
SILConstantInfo constantInfo) {
assert(constantInfo == getConstantInfo(constant));
// Builtins must be fully applied at the point of reference.
if (constant.hasDecl() &&
isa<BuiltinUnit>(constant.getDecl()->getDeclContext())) {
SGM.diagnose(loc.getSourceLoc(), diag::not_implemented,
"delayed application of builtin");
return SILUndef::get(constantInfo.getSILType(), SGM.M);
}
// If the constant is a thunk we haven't emitted yet, emit it.
if (!SGM.hasFunction(constant)) {
if (constant.isCurried) {
auto vd = constant.getDecl();
// Reference the next uncurrying level of the function.
SILDeclRef next = SILDeclRef(vd, constant.kind,
SILDeclRef::ConstructAtBestResilienceExpansion,
constant.uncurryLevel + 1);
// If the function is fully uncurried and natively foreign, reference its
// foreign entry point.
if (!next.isCurried) {
if (requiresForeignToNativeThunk(vd))
next = next.asForeign();
}
// Preserve whether the curry thunks lead to a direct reference to the
// method implementation.
next = next.asDirectReference(constant.isDirectReference);
SGM.emitCurryThunk(vd, constant, next);
}
// Otherwise, if this is a calling convention thunk we haven't emitted yet,
// emit it.
else if (constant.isForeignToNativeThunk()) {
SGM.emitForeignToNativeThunk(constant);
} else if (constant.isNativeToForeignThunk()) {
SGM.emitNativeToForeignThunk(constant);
} else if (constant.kind == SILDeclRef::Kind::EnumElement) {
SGM.emitEnumConstructor(cast<EnumElementDecl>(constant.getDecl()));
}
}
auto f = SGM.getFunction(constant, NotForDefinition);
assert(f->getLoweredFunctionType() == constantInfo.SILFnType);
return B.createFunctionRef(loc, f);
}
std::tuple<ManagedValue, SILType>
SILGenFunction::emitSiblingMethodRef(SILLocation loc,
SILValue selfValue,
@@ -678,170 +625,6 @@ void SILGenFunction::emitArtificialTopLevel(ClassDecl *mainClass) {
}
}
static void forwardCaptureArgs(SILGenFunction &gen,
SmallVectorImpl<SILValue> &args,
CapturedValue capture) {
auto addSILArgument = [&](SILType t, ValueDecl *d) {
args.push_back(gen.F.begin()->createFunctionArgument(t, d));
};
auto *vd = capture.getDecl();
switch (gen.SGM.Types.getDeclCaptureKind(capture)) {
case CaptureKind::None:
break;
case CaptureKind::Constant: {
auto *var = dyn_cast<VarDecl>(vd);
addSILArgument(gen.getLoweredType(var->getType()), vd);
break;
}
case CaptureKind::Box: {
// Forward the captured owning box.
auto *var = cast<VarDecl>(vd);
auto boxTy = gen.SGM.Types
.getInterfaceBoxTypeForCapture(vd,
gen.getLoweredType(var->getType())
.getSwiftRValueType(),
/*mutable*/ true);
addSILArgument(SILType::getPrimitiveObjectType(boxTy), vd);
break;
}
case CaptureKind::StorageAddress: {
auto *var = dyn_cast<VarDecl>(vd);
SILType ty = gen.getLoweredType(var->getType()->getRValueType())
.getAddressType();
// Forward the captured value address.
addSILArgument(ty, vd);
break;
}
}
}
static SILValue getNextUncurryLevelRef(SILGenFunction &gen,
SILLocation loc,
SILDeclRef next,
bool direct,
ArrayRef<SILValue> curriedArgs,
SubstitutionList curriedSubs) {
if (next.isForeign || next.isCurried || !next.hasDecl() || direct)
return gen.emitGlobalFunctionRef(loc, next.asForeign(false));
auto constantInfo = gen.SGM.Types.getConstantInfo(next);
SILValue thisArg;
if (!curriedArgs.empty())
thisArg = curriedArgs.back();
if (isa<AbstractFunctionDecl>(next.getDecl()) &&
getMethodDispatch(cast<AbstractFunctionDecl>(next.getDecl()))
== MethodDispatch::Class) {
SILValue thisArg = curriedArgs.back();
// Use the dynamic thunk if dynamic.
if (next.getDecl()->isDynamic()) {
auto dynamicThunk = gen.SGM.getDynamicThunk(next, constantInfo);
return gen.B.createFunctionRef(loc, dynamicThunk);
}
return gen.B.createClassMethod(loc, thisArg, next);
}
// If the fully-uncurried reference is to a generic method, look up the
// witness.
if (constantInfo.SILFnType->getRepresentation()
== SILFunctionTypeRepresentation::WitnessMethod) {
auto thisType = curriedSubs[0].getReplacement()->getCanonicalType();
assert(isa<ArchetypeType>(thisType) && "no archetype for witness?!");
SILValue OpenedExistential;
if (!cast<ArchetypeType>(thisType)->getOpenedExistentialType().isNull())
OpenedExistential = thisArg;
auto protocol =
next.getDecl()->getDeclContext()->getAsProtocolOrProtocolExtensionContext();
auto conformance = ProtocolConformanceRef(protocol);
return gen.B.createWitnessMethod(loc, thisType, conformance, next,
constantInfo.getSILType(),
OpenedExistential);
}
// Otherwise, emit a direct call.
return gen.emitGlobalFunctionRef(loc, next);
}
void SILGenFunction::emitCurryThunk(ValueDecl *vd,
SILDeclRef from, SILDeclRef to) {
SmallVector<SILValue, 8> curriedArgs;
unsigned paramCount = from.uncurryLevel + 1;
if (isa<ConstructorDecl>(vd) || isa<EnumElementDecl>(vd)) {
// The first body parameter pattern for a constructor specifies the
// "self" instance, but the constructor is invoked from outside on a
// metatype.
assert(from.uncurryLevel == 0 && to.uncurryLevel == 1
&& "currying constructor at level other than one?!");
F.setBare(IsBare);
auto selfMetaTy = vd->getInterfaceType()->getAs<AnyFunctionType>()
->getInput();
selfMetaTy = vd->getInnermostDeclContext()->mapTypeIntoContext(selfMetaTy);
auto metatypeVal =
F.begin()->createFunctionArgument(getLoweredLoadableType(selfMetaTy));
curriedArgs.push_back(metatypeVal);
} else if (auto fd = dyn_cast<AbstractFunctionDecl>(vd)) {
// Forward implicit closure context arguments.
bool hasCaptures = SGM.M.Types.hasLoweredLocalCaptures(fd);
if (hasCaptures)
--paramCount;
// Forward the curried formal arguments.
auto forwardedPatterns = fd->getParameterLists().slice(0, paramCount);
for (auto *paramPattern : reversed(forwardedPatterns))
bindParametersForForwarding(paramPattern, curriedArgs);
// Forward captures.
if (hasCaptures) {
auto captureInfo = SGM.Types.getLoweredLocalCaptures(fd);
for (auto capture : captureInfo.getCaptures())
forwardCaptureArgs(*this, curriedArgs, capture);
}
} else {
llvm_unreachable("don't know how to curry this decl");
}
// Forward substitutions.
SubstitutionList subs;
auto constantInfo = getConstantInfo(to);
if (auto *env = constantInfo.GenericEnv)
subs = env->getForwardingSubstitutions();
SILValue toFn = getNextUncurryLevelRef(*this, vd, to, from.isDirectReference,
curriedArgs, subs);
SILFunctionConventions fromConv(
SGM.getConstantType(from).castTo<SILFunctionType>(), SGM.M);
SILType resultTy = fromConv.getSingleSILResultType();
resultTy = F.mapTypeIntoContext(resultTy);
auto toTy = toFn->getType();
// Forward archetypes and specialize if the function is generic.
if (!subs.empty()) {
auto toFnTy = toFn->getType().castTo<SILFunctionType>();
toTy = getLoweredLoadableType(toFnTy->substGenericArgs(SGM.M, subs));
}
// Partially apply the next uncurry level and return the result closure.
auto closureTy =
SILGenBuilder::getPartialApplyResultType(toFn->getType(), curriedArgs.size(),
SGM.M, subs,
ParameterConvention::Direct_Owned);
SILInstruction *toClosure =
B.createPartialApply(vd, toFn, toTy, subs, curriedArgs, closureTy);
if (resultTy != closureTy)
toClosure = B.createConvertFunction(vd, toClosure, resultTy);
B.createReturn(ImplicitReturnLocation::getImplicitReturnLoc(vd), toClosure);
}
void SILGenFunction::emitGeneratorFunction(SILDeclRef function, Expr *value) {
MagicFunctionName = SILGenModule::getMagicFunctionName(function);