Files
swift-mirror/lib/SILGen/SILGenTopLevel.cpp

347 lines
12 KiB
C++

//===--- SILGenTopLevel.cpp - Top-level Code Emission ---------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
#include "SILGenTopLevel.h"
#include "SILGenFunction.h"
#include "Scope.h"
#include "swift/AST/DiagnosticsSIL.h"
#define DEBUG_TYPE "silgen"
using namespace swift;
using namespace Lowering;
void SILGenModule::emitEntryPoint(SourceFile *SF, SILFunction *TopLevel) {
auto EntryRef = SILDeclRef::getMainFileEntryPoint(SF);
bool isAsyncTopLevel = false;
if (SF->isAsyncContext()) {
isAsyncTopLevel = true;
auto asyncEntryRef = SILDeclRef::getAsyncMainFileEntryPoint(SF);
auto *asyncTopLevel = getFunction(asyncEntryRef, ForDefinition);
SILGenFunction(*this, *TopLevel, SF)
.emitAsyncMainThreadStart(asyncEntryRef);
TopLevel = asyncTopLevel;
EntryRef = asyncEntryRef;
}
TopLevel->createProfiler(EntryRef);
SILGenFunction TopLevelSGF(*this, *TopLevel, SF,
/* IsEmittingTopLevelCode */ true);
TopLevelSGF.MagicFunctionName = SwiftModule->getName();
auto moduleCleanupLoc = CleanupLocation::getModuleCleanupLocation();
TopLevelSGF.prepareEpilog(llvm::None, true, moduleCleanupLoc);
auto prologueLoc = RegularLocation::getModuleLocation();
prologueLoc.markAsPrologue();
if (SF->isAsyncContext()) {
// emitAsyncMainThreadStart will create argc and argv.
// Just set the main actor as the expected executor; we should
// already be running on it.
SILValue executor = TopLevelSGF.emitMainExecutor(prologueLoc);
TopLevelSGF.ExpectedExecutor = TopLevelSGF.B.createOptionalSome(
prologueLoc, executor, SILType::getOptionalType(executor->getType()));
} else {
// Create the argc and argv arguments.
auto entry = TopLevelSGF.B.getInsertionBB();
auto context = TopLevelSGF.getTypeExpansionContext();
auto paramTypeIter =
TopLevelSGF.F.getConventions().getParameterSILTypes(context).begin();
entry->createFunctionArgument(*paramTypeIter);
entry->createFunctionArgument(*std::next(paramTypeIter));
}
{
Scope S(TopLevelSGF.Cleanups, moduleCleanupLoc);
SILGenTopLevel(TopLevelSGF).visitSourceFile(SF);
}
// Unregister the top-level function emitter.
TopLevelSGF.stopEmittingTopLevelCode();
// Write out the epilog.
auto moduleLoc = RegularLocation::getModuleLocation();
moduleLoc.markAutoGenerated();
auto returnInfo = TopLevelSGF.emitEpilogBB(moduleLoc);
auto returnLoc = returnInfo.second;
returnLoc.markAutoGenerated();
SILFunction *exitFunc = nullptr;
SILType returnType;
if (isAsyncTopLevel) {
FuncDecl *exitFuncDecl = getExit();
assert(exitFuncDecl && "Failed to find exit function declaration");
exitFunc = getFunction(
SILDeclRef(exitFuncDecl, SILDeclRef::Kind::Func, /*isForeign*/ true),
NotForDefinition);
SILFunctionType &funcType =
*exitFunc->getLoweredType().getAs<SILFunctionType>();
returnType = SILType::getPrimitiveObjectType(
funcType.getParameters().front().getInterfaceType());
} else {
returnType = TopLevelSGF.F.getConventions().getSingleSILResultType(
TopLevelSGF.getTypeExpansionContext());
}
auto emitTopLevelReturnValue = [&](unsigned value) -> SILValue {
// Create an integer literal for the value.
auto litType = SILType::getBuiltinIntegerType(32, getASTContext());
SILValue retValue =
TopLevelSGF.B.createIntegerLiteral(moduleLoc, litType, value);
// Wrap that in a struct if necessary.
if (litType != returnType) {
retValue = TopLevelSGF.B.createStruct(moduleLoc, returnType, retValue);
}
return retValue;
};
// Fallthrough should signal a normal exit by returning 0.
SILValue returnValue;
if (TopLevelSGF.B.hasValidInsertionPoint())
returnValue = emitTopLevelReturnValue(0);
// Handle the implicit rethrow block.
auto rethrowBB = TopLevelSGF.ThrowDest.getBlock();
TopLevelSGF.ThrowDest = JumpDest::invalid();
// If the rethrow block wasn't actually used, just remove it.
if (rethrowBB->pred_empty()) {
TopLevelSGF.eraseBasicBlock(rethrowBB);
// Otherwise, we need to produce a unified return block.
} else {
auto returnBB = TopLevelSGF.createBasicBlock();
if (TopLevelSGF.B.hasValidInsertionPoint())
TopLevelSGF.B.createBranch(returnLoc, returnBB, returnValue);
returnValue = returnBB->createPhiArgument(returnType, OwnershipKind::Owned);
TopLevelSGF.B.emitBlock(returnBB);
// Emit the rethrow block.
SILGenSavedInsertionPoint savedIP(TopLevelSGF, rethrowBB,
FunctionSection::Postmatter);
// Log the error.
SILValue error = rethrowBB->getArgument(0);
TopLevelSGF.B.createBuiltin(moduleLoc,
getASTContext().getIdentifier("errorInMain"),
Types.getEmptyTupleType(), {}, {error});
// Then end the lifetime of the error.
//
// We do this to appease the ownership verifier. We do not care about
// actually destroying the value since we are going to immediately exit,
// so this saves us a slight bit of code-size since end_lifetime is
// stripped out after ownership is removed.
TopLevelSGF.B.createEndLifetime(moduleLoc, error);
// Signal an abnormal exit by returning 1.
TopLevelSGF.Cleanups.emitCleanupsForReturn(CleanupLocation(moduleLoc),
IsForUnwind);
TopLevelSGF.B.createBranch(returnLoc, returnBB, emitTopLevelReturnValue(1));
}
// Return.
if (TopLevelSGF.B.hasValidInsertionPoint()) {
if (isAsyncTopLevel) {
SILValue exitCall = TopLevelSGF.B.createFunctionRef(moduleLoc, exitFunc);
TopLevelSGF.B.createApply(moduleLoc, exitCall, {}, {returnValue});
TopLevelSGF.B.createUnreachable(moduleLoc);
} else {
TopLevelSGF.B.createReturn(returnLoc, returnValue);
}
}
// Okay, we're done emitting the top-level function; destroy the
// emitter and verify the result.
SILFunction &toplevel = TopLevelSGF.getFunction();
LLVM_DEBUG(llvm::dbgs() << "lowered toplevel sil:\n";
toplevel.print(llvm::dbgs()));
toplevel.verifyIncompleteOSSA();
emitLazyConformancesForFunction(&toplevel);
}
void SILGenModule::emitEntryPoint(SourceFile *SF) {
assert(!M.lookUpFunction(getASTContext().getEntryPointFunctionName()) &&
"already emitted toplevel?!");
auto mainEntryRef = SILDeclRef::getMainFileEntryPoint(SF);
SILFunction *TopLevel = getFunction(mainEntryRef, ForDefinition);
TopLevel->setBare(IsBare);
emitEntryPoint(SF, TopLevel);
}
void SILGenFunction::emitMarkFunctionEscapeForTopLevelCodeGlobals(
SILLocation Loc, CaptureInfo CaptureInfo) {
llvm::SmallVector<SILValue, 4> Captures;
for (auto Capture : CaptureInfo.getCaptures()) {
// Decls captured by value don't escape.
auto It = VarLocs.find(Capture.getDecl());
if (It == VarLocs.end() || !It->getSecond().value->getType().isAddress())
continue;
Captures.push_back(It->second.value);
}
if (!Captures.empty())
B.createMarkFunctionEscape(Loc, Captures);
}
/// Emit a `mark_function_escape_instruction` into `SGF` if `AFD` captures an
/// uninitialized global variable
static void emitMarkFunctionEscape(SILGenFunction &SGF,
AbstractFunctionDecl *AFD) {
if (AFD->getDeclContext()->isLocalContext())
return;
auto CaptureInfo = AFD->getCaptureInfo();
SGF.emitMarkFunctionEscapeForTopLevelCodeGlobals(AFD, std::move(CaptureInfo));
}
SILGenTopLevel::SILGenTopLevel(SILGenFunction &SGF) : SGF(SGF) {}
void SILGenTopLevel::visitSourceFile(SourceFile *SF) {
for (auto *D : SF->getTopLevelDecls()) {
D->visitAuxiliaryDecls([&](Decl *AuxiliaryDecl) { visit(AuxiliaryDecl); });
visit(D);
}
if (auto *SynthesizedFile = SF->getSynthesizedFile()) {
for (auto *D : SynthesizedFile->getTopLevelDecls()) {
if (isa<ExtensionDecl>(D)) {
visit(D);
}
}
}
for (Decl *D : SF->getHoistedDecls()) {
visit(D);
}
for (TypeDecl *TD : SF->LocalTypeDecls) {
if (TD->getDeclContext()->getInnermostSkippedFunctionContext())
continue;
visit(TD);
}
}
void SILGenTopLevel::visitNominalTypeDecl(NominalTypeDecl *NTD) {
TypeVisitor(SGF).emit(NTD);
}
void SILGenTopLevel::visitExtensionDecl(ExtensionDecl *ED) {
ExtensionVisitor(SGF).emit(ED);
}
void SILGenTopLevel::visitAbstractFunctionDecl(AbstractFunctionDecl *AFD) {
emitMarkFunctionEscape(SGF, AFD);
}
void SILGenTopLevel::visitAbstractStorageDecl(AbstractStorageDecl *ASD) {
ASD->visitEmittedAccessors(
[this](AccessorDecl *Accessor) { visitAbstractFunctionDecl(Accessor); });
}
void SILGenTopLevel::visitTopLevelCodeDecl(TopLevelCodeDecl *TD) {
SGF.emitProfilerIncrement(TD->getBody());
DebugScope DS(SGF, CleanupLocation(TD));
for (auto &ESD : TD->getBody()->getElements()) {
if (!SGF.B.hasValidInsertionPoint()) {
if (auto *S = ESD.dyn_cast<Stmt *>()) {
if (S->isImplicit())
continue;
} else if (auto *E = ESD.dyn_cast<Expr *>()) {
if (E->isImplicit())
continue;
}
SGF.SGM.diagnose(ESD.getStartLoc(), diag::unreachable_code);
// There's no point in trying to emit anything else.
return;
}
if (auto *S = ESD.dyn_cast<Stmt *>()) {
SGF.emitStmt(S);
} else if (auto *E = ESD.dyn_cast<Expr *>()) {
SGF.emitIgnoredExpr(E);
} else {
SGF.visit(ESD.get<Decl *>());
}
}
}
SILGenTopLevel::TypeVisitor::TypeVisitor(SILGenFunction &SGF) : SGF(SGF) {}
void SILGenTopLevel::TypeVisitor::emit(IterableDeclContext *Ctx) {
for (auto *Member : Ctx->getMembersForLowering()) {
visit(Member);
}
}
void SILGenTopLevel::TypeVisitor::visitPatternBindingDecl(
PatternBindingDecl *PD) {
for (auto i : range(PD->getNumPatternEntries())) {
if (!PD->getExecutableInit(i) || PD->isStatic())
continue;
auto *Var = PD->getAnchoringVarDecl(i);
if (Var->getDeclContext()->isLocalContext())
continue;
auto CaptureInfo = PD->getCaptureInfo(i);
// If this is a stored property initializer inside a type at global scope,
// it may close over a global variable. If we're emitting top-level code,
// then emit a "mark_function_escape" that lists the captured global
// variables so that definite initialization can reason about this
// escape point.
SGF.emitMarkFunctionEscapeForTopLevelCodeGlobals(Var,
std::move(CaptureInfo));
}
}
void SILGenTopLevel::TypeVisitor::visitNominalTypeDecl(NominalTypeDecl *NTD) {
TypeVisitor(SGF).emit(NTD);
}
void SILGenTopLevel::TypeVisitor::visitAbstractFunctionDecl(
AbstractFunctionDecl *AFD) {
emitMarkFunctionEscape(SGF, AFD);
}
void SILGenTopLevel::TypeVisitor::visitAbstractStorageDecl(
AbstractStorageDecl *ASD) {
ASD->visitEmittedAccessors(
[this](AccessorDecl *Accessor) { visitAbstractFunctionDecl(Accessor); });
}
SILGenTopLevel::ExtensionVisitor::ExtensionVisitor(SILGenFunction &SGF)
: TypeVisitor(SGF) {}
void SILGenTopLevel::ExtensionVisitor::visitPatternBindingDecl(
PatternBindingDecl *PD) {
auto *Ctx = PD->getDeclContext();
if (isa<ExtensionDecl>(Ctx) &&
cast<ExtensionDecl>(Ctx)->isObjCImplementation()) {
TypeVisitor::visitPatternBindingDecl(PD);
}
}