mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Introduce Name Binding as a Frontend Action
Introduces the -name-bind frontend action that is intended as an intermediary between the parse-only actions and a full typechecking pass. In this phase, module imports will be validated and resolved, making it possible to emit full make-style dependencies files among other things. Note that all information available to a parse-only pass is available to name binding, but because it does not continue-on to typecheck input files, full semantic information is not.
This commit is contained in:
@@ -425,7 +425,21 @@ shouldImplicityImportSwiftOnoneSupportModule(CompilerInvocation &Invocation) {
|
||||
return Invocation.getFrontendOptions().isCreatingSIL();
|
||||
}
|
||||
|
||||
void CompilerInstance::performParseAndNameBindingOnly() {
|
||||
performSemaUpTo(SourceFile::NameBound);
|
||||
}
|
||||
|
||||
void CompilerInstance::performSema() {
|
||||
performSemaUpTo(SourceFile::TypeChecked);
|
||||
}
|
||||
|
||||
void CompilerInstance::performSemaUpTo(SourceFile::ASTStage_t LimitStage) {
|
||||
// FIXME: A lot of the logic in `performParseOnly` is a stripped-down version
|
||||
// of the logic in `performSemaUpTo`. We should try to unify them over time.
|
||||
if (LimitStage <= SourceFile::Parsed) {
|
||||
return performParseOnly();
|
||||
}
|
||||
|
||||
FrontendStatsTracer tracer(Context->Stats, "perform-sema");
|
||||
Context->LoadedModules[MainModule->getName()] = getMainModule();
|
||||
|
||||
@@ -457,9 +471,10 @@ void CompilerInstance::performSema() {
|
||||
if (MainBufferID != NO_SUCH_BUFFER)
|
||||
addMainFileToModule(implicitImports);
|
||||
|
||||
parseAndCheckTypes(implicitImports);
|
||||
parseAndCheckTypesUpTo(implicitImports, LimitStage);
|
||||
}
|
||||
|
||||
|
||||
CompilerInstance::ImplicitImports::ImplicitImports(CompilerInstance &compiler) {
|
||||
kind = compiler.Invocation.getImplicitModuleImportKind();
|
||||
|
||||
@@ -575,8 +590,8 @@ void CompilerInstance::addMainFileToModule(
|
||||
addAdditionalInitialImportsTo(MainFile, implicitImports);
|
||||
}
|
||||
|
||||
void CompilerInstance::parseAndCheckTypes(
|
||||
const ImplicitImports &implicitImports) {
|
||||
void CompilerInstance::parseAndCheckTypesUpTo(
|
||||
const ImplicitImports &implicitImports, SourceFile::ASTStage_t limitStage) {
|
||||
FrontendStatsTracer tracer(Context->Stats, "parse-and-check-types");
|
||||
// Delayed parsing callback for the primary file, or all files
|
||||
// in non-WMO mode.
|
||||
@@ -611,8 +626,8 @@ void CompilerInstance::parseAndCheckTypes(
|
||||
// In addition, the main file has parsing and type-checking
|
||||
// interwined.
|
||||
if (MainBufferID != NO_SUCH_BUFFER) {
|
||||
parseAndTypeCheckMainFile(PersistentState, PrimaryDelayedCB.get(),
|
||||
TypeCheckOptions);
|
||||
parseAndTypeCheckMainFileUpTo(limitStage, PersistentState,
|
||||
PrimaryDelayedCB.get(), TypeCheckOptions);
|
||||
}
|
||||
|
||||
assert(llvm::all_of(MainModule->getFiles(), [](const FileUnit *File) -> bool {
|
||||
@@ -623,6 +638,11 @@ void CompilerInstance::parseAndCheckTypes(
|
||||
}) && "some files have not yet had their imports resolved");
|
||||
MainModule->setHasResolvedImports();
|
||||
|
||||
// If the limiting AST stage is name binding, we're done.
|
||||
if (limitStage <= SourceFile::NameBound) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &options = Invocation.getFrontendOptions();
|
||||
forEachFileToTypeCheck([&](SourceFile &SF) {
|
||||
performTypeChecking(SF, PersistentState.getTopLevelContext(),
|
||||
@@ -720,7 +740,8 @@ bool CompilerInstance::parsePartialModulesAndLibraryFiles(
|
||||
return hadLoadError;
|
||||
}
|
||||
|
||||
void CompilerInstance::parseAndTypeCheckMainFile(
|
||||
void CompilerInstance::parseAndTypeCheckMainFileUpTo(
|
||||
SourceFile::ASTStage_t LimitStage,
|
||||
PersistentParserState &PersistentState,
|
||||
DelayedParsingCallbacks *DelayedParseCB,
|
||||
OptionSet<TypeCheckingFlags> TypeCheckOptions) {
|
||||
@@ -747,15 +768,27 @@ void CompilerInstance::parseAndTypeCheckMainFile(
|
||||
parseIntoSourceFile(MainFile, MainFile.getBufferID().getValue(), &Done,
|
||||
TheSILModule ? &SILContext : nullptr, &PersistentState,
|
||||
DelayedParseCB);
|
||||
|
||||
if (mainIsPrimary) {
|
||||
const auto &options = Invocation.getFrontendOptions();
|
||||
performTypeChecking(MainFile, PersistentState.getTopLevelContext(),
|
||||
TypeCheckOptions, CurTUElem,
|
||||
options.WarnLongFunctionBodies,
|
||||
options.WarnLongExpressionTypeChecking,
|
||||
options.SolverExpressionTimeThreshold,
|
||||
options.SwitchCheckingInvocationThreshold);
|
||||
switch (LimitStage) {
|
||||
case SourceFile::Parsing:
|
||||
case SourceFile::Parsed:
|
||||
llvm_unreachable("invalid limit stage");
|
||||
case SourceFile::NameBound:
|
||||
performNameBinding(MainFile, CurTUElem);
|
||||
break;
|
||||
case SourceFile::TypeChecked:
|
||||
const auto &options = Invocation.getFrontendOptions();
|
||||
performTypeChecking(MainFile, PersistentState.getTopLevelContext(),
|
||||
TypeCheckOptions, CurTUElem,
|
||||
options.WarnLongFunctionBodies,
|
||||
options.WarnLongExpressionTypeChecking,
|
||||
options.SolverExpressionTimeThreshold,
|
||||
options.SwitchCheckingInvocationThreshold);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CurTUElem = MainFile.Decls.size();
|
||||
} while (!Done);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user