Skip to content

[Frontend] Add a new -emit-interface-path option #18090

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 24, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions include/swift/AST/DiagnosticsFrontend.def
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ ERROR(error_mode_cannot_emit_module,none,
"this mode does not support emitting modules", ())
ERROR(error_mode_cannot_emit_module_doc,none,
"this mode does not support emitting module documentation files", ())
ERROR(error_mode_cannot_emit_interface,none,
"this mode does not support emitting textual interface files", ())

WARNING(emit_reference_dependencies_without_primary_file,none,
"ignoring -emit-reference-dependencies (requires -primary-file)", ())
Expand Down
8 changes: 7 additions & 1 deletion include/swift/Basic/SupplementaryOutputPaths.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ struct SupplementaryOutputPaths {
/// It is currently only used with WMO, but could be generalized.
std::string TBDPath;

/// The path to which we should emit a textual module interface, which can be
/// used by a client source file to import this module.
///
/// Currently only makes sense when the compiler has whole-module knowledge.
std::string ModuleInterfaceOutputPath;

SupplementaryOutputPaths() = default;
SupplementaryOutputPaths(const SupplementaryOutputPaths &) = default;

Expand All @@ -68,7 +74,7 @@ struct SupplementaryOutputPaths {
ModuleDocOutputPath.empty() && DependenciesFilePath.empty() &&
ReferenceDependenciesFilePath.empty() &&
SerializedDiagnosticsPath.empty() && LoadedModuleTracePath.empty() &&
TBDPath.empty();
TBDPath.empty() && ModuleInterfaceOutputPath.empty();
}
};
} // namespace swift
Expand Down
1 change: 1 addition & 0 deletions include/swift/Frontend/FrontendInputsAndOutputs.h
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,7 @@ class FrontendInputsAndOutputs {
bool hasLoadedModuleTracePath() const;
bool hasModuleOutputPath() const;
bool hasModuleDocOutputPath() const;
bool hasModuleInterfaceOutputPath() const;
bool hasTBDPath() const;

bool hasDependencyTrackerPath() const;
Expand Down
1 change: 1 addition & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ class FrontendOptions {
static bool canActionEmitLoadedModuleTrace(ActionType);
static bool canActionEmitModule(ActionType);
static bool canActionEmitModuleDoc(ActionType);
static bool canActionEmitInterface(ActionType);

public:
static bool doesActionProduceOutput(ActionType);
Expand Down
61 changes: 31 additions & 30 deletions include/swift/Frontend/Types.def
Original file line number Diff line number Diff line change
Expand Up @@ -27,45 +27,46 @@
// The second value is the type id, which will result in a
// swift::driver::file_types::TY_XX enum constant.

// The third value is the suffix to use when creating temporary files
// The third value is the extension to use when creating temporary files
// of this type. It is also used when inferring a type from an extension.
// If multiple types specify the same extension, the first one is chosen when
// performing type inference.

// The fifth value is a string containing option flags. For now, this is unused,
// and should always be the empty string.
// The fourth value is a string containing option flags. For now, this is
// unused, and should always be the empty string.

// Input types
TYPE("swift", Swift, "swift", "")
TYPE("sil", SIL, "sil", "")
TYPE("sib", SIB, "sib", "")
TYPE("swift", Swift, "swift", "")
TYPE("sil", SIL, "sil", "")
TYPE("sib", SIB, "sib", "")

// Output types
TYPE("image", Image, "out", "")
TYPE("object", Object, "o", "")
TYPE("dSYM", dSYM, "dSYM", "")
TYPE("dependencies", Dependencies, "d", "")
TYPE("autolink", AutolinkFile, "autolink", "")
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
TYPE("assembly", Assembly, "s", "")
TYPE("raw-sil", RawSIL, "sil", "")
TYPE("raw-sib", RawSIB, "sib", "")
TYPE("llvm-ir", LLVM_IR, "ir", "")
TYPE("llvm-bc", LLVM_BC, "bc", "")
TYPE("diagnostics", SerializedDiagnostics, "dia", "")
TYPE("objc-header", ObjCHeader, "h", "")
TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
TYPE("remap", Remapping, "remap", "")
TYPE("imported-modules", ImportedModules, "importedmodules", "")
TYPE("tbd", TBD, "tbd", "")
TYPE("module-trace", ModuleTrace, "trace.json", "")
TYPE("index-data", IndexData, "", "")
TYPE("opt-record", OptRecord, "opt.yaml", "")
TYPE("image", Image, "out", "")
TYPE("object", Object, "o", "")
TYPE("dSYM", dSYM, "dSYM", "")
TYPE("dependencies", Dependencies, "d", "")
TYPE("autolink", AutolinkFile, "autolink", "")
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
TYPE("swiftinterface", SwiftModuleInterfaceFile, "swiftinterface", "")
TYPE("assembly", Assembly, "s", "")
TYPE("raw-sil", RawSIL, "sil", "")
TYPE("raw-sib", RawSIB, "sib", "")
TYPE("llvm-ir", LLVM_IR, "ir", "")
TYPE("llvm-bc", LLVM_BC, "bc", "")
TYPE("diagnostics", SerializedDiagnostics, "dia", "")
TYPE("objc-header", ObjCHeader, "h", "")
TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
TYPE("remap", Remapping, "remap", "")
TYPE("imported-modules", ImportedModules, "importedmodules", "")
TYPE("tbd", TBD, "tbd", "")
TYPE("module-trace", ModuleTrace, "trace.json", "")
TYPE("index-data", IndexData, "", "")
TYPE("opt-record", OptRecord, "opt.yaml", "")

// Misc types
TYPE("pcm", ClangModuleFile, "pcm", "")
TYPE("pch", PCH, "pch", "")
TYPE("none", Nothing, "", "")
TYPE("pcm", ClangModuleFile, "pcm", "")
TYPE("pch", PCH, "pch", "")
TYPE("none", Nothing, "", "")

#undef TYPE
4 changes: 4 additions & 0 deletions include/swift/Option/FrontendOptions.td
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def emit_fixits_path
: Separate<["-"], "emit-fixits-path">, MetaVarName<"<path>">,
HelpText<"Output compiler fixits as source edits to <path>">;

def emit_interface_path
: Separate<["-"], "emit-interface-path">, MetaVarName<"<path>">,
HelpText<"Output textual interface file to <path>">;

def tbd_install_name
: Separate<["-"], "tbd-install_name">, MetaVarName<"<path>">,
HelpText<"The install_name to use in an emitted TBD file">;
Expand Down
1 change: 1 addition & 0 deletions lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1731,6 +1731,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
case file_types::TY_TBD:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
// We could in theory handle assembly or LLVM input, but let's not.
// FIXME: What about LTO?
Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,
Expand Down
2 changes: 2 additions & 0 deletions lib/Driver/ToolChains.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
case file_types::TY_ModuleTrace:
case file_types::TY_TBD:
case file_types::TY_OptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
llvm_unreachable("Output type can never be primary output.");
case file_types::TY_INVALID:
llvm_unreachable("Invalid type ID");
Expand Down Expand Up @@ -655,6 +656,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
case file_types::TY_Remapping:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
llvm_unreachable("Output type can never be primary output.");
case file_types::TY_INVALID:
llvm_unreachable("Invalid type ID");
Expand Down
5 changes: 5 additions & 0 deletions lib/Frontend/ArgsToFrontendOptionsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
return true;
}
if (!FrontendOptions::canActionEmitInterface(Opts.RequestedAction) &&
Opts.InputsAndOutputs.hasModuleInterfaceOutputPath()) {
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_interface);
return true;
}
return false;
}

Expand Down
14 changes: 12 additions & 2 deletions lib/Frontend/ArgsToFrontendOutputsConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,10 +291,13 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
auto loadedModuleTrace = getSupplementaryFilenamesFromArguments(
options::OPT_emit_loaded_module_trace_path);
auto TBD = getSupplementaryFilenamesFromArguments(options::OPT_emit_tbd_path);
auto moduleInterfaceOutput = getSupplementaryFilenamesFromArguments(
options::OPT_emit_interface_path);

if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
!dependenciesFile || !referenceDependenciesFile ||
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD) {
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD ||
!moduleInterfaceOutput) {
return None;
}
std::vector<SupplementaryOutputPaths> result;
Expand All @@ -312,6 +315,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
sop.FixItsOutputPath = (*fixItsOutput)[i];
sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
sop.TBDPath = (*TBD)[i];
sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[i];

result.push_back(sop);
}
Expand Down Expand Up @@ -382,6 +386,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
SERIALIZED_MODULE_DOC_EXTENSION, "",
defaultSupplementaryOutputPathExcludingExtension);

// There is no non-path form of -emit-interface-path
auto moduleInterfaceOutputPath = pathsFromArguments.ModuleInterfaceOutputPath;

ID emitModuleOption;
std::string moduleExtension;
std::string mainOutputIfUsableForModule;
Expand All @@ -403,6 +410,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
sop.FixItsOutputPath = fixItsOutputPath;
sop.LoadedModuleTracePath = loadedModuleTracePath;
sop.TBDPath = tbdPath;
sop.ModuleInterfaceOutputPath = moduleInterfaceOutputPath;
return sop;
}

Expand Down Expand Up @@ -475,7 +483,9 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
{file_types::TY_SwiftDeps, paths.ReferenceDependenciesFilePath},
{file_types::TY_SerializedDiagnostics, paths.SerializedDiagnosticsPath},
{file_types::TY_ModuleTrace, paths.LoadedModuleTracePath},
{file_types::TY_TBD, paths.TBDPath}};
{file_types::TY_TBD, paths.TBDPath},
{file_types::TY_SwiftModuleInterfaceFile,paths.ModuleInterfaceOutputPath}
};
for (const std::pair<file_types::ID, std::string &> &typeAndString :
typesAndStrings) {
auto const out = map->find(typeAndString.first);
Expand Down
6 changes: 6 additions & 0 deletions lib/Frontend/FrontendInputsAndOutputs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,12 @@ bool FrontendInputsAndOutputs::hasModuleDocOutputPath() const {
return outs.ModuleDocOutputPath;
});
}
bool FrontendInputsAndOutputs::hasModuleInterfaceOutputPath() const {
return hasSupplementaryOutputPath(
[](const SupplementaryOutputPaths &outs) -> const std::string & {
return outs.ModuleInterfaceOutputPath;
});
}
bool FrontendInputsAndOutputs::hasTBDPath() const {
return hasSupplementaryOutputPath(
[](const SupplementaryOutputPaths &outs) -> const std::string & {
Expand Down
33 changes: 33 additions & 0 deletions lib/Frontend/FrontendOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ void FrontendOptions::forAllOutputPaths(
input.getPrimarySpecificPaths().SupplementaryOutputs;
const std::string *outputs[] = {&outs.ModuleOutputPath,
&outs.ModuleDocOutputPath,
&outs.ModuleInterfaceOutputPath,
&outs.ObjCHeaderOutputPath};
for (const std::string *next : outputs) {
if (!next->empty())
Expand Down Expand Up @@ -348,6 +349,38 @@ bool FrontendOptions::canActionEmitModuleDoc(ActionType action) {
return canActionEmitModule(action);
}

bool FrontendOptions::canActionEmitInterface(ActionType action) {
switch (action) {
case ActionType::NoneAction:
case ActionType::Parse:
case ActionType::ResolveImports:
case ActionType::Typecheck:
case ActionType::DumpParse:
case ActionType::DumpInterfaceHash:
case ActionType::DumpAST:
case ActionType::EmitSyntax:
case ActionType::PrintAST:
case ActionType::EmitPCH:
case ActionType::DumpScopeMaps:
case ActionType::DumpTypeRefinementContexts:
case ActionType::EmitSILGen:
case ActionType::EmitSIBGen:
case ActionType::Immediate:
case ActionType::REPL:
case ActionType::EmitImportedModules:
return false;
case ActionType::MergeModules:
case ActionType::EmitModuleOnly:
case ActionType::EmitSIL:
case ActionType::EmitSIB:
case ActionType::EmitIR:
case ActionType::EmitBC:
case ActionType::EmitAssembly:
case ActionType::EmitObject:
return true;
}
}

bool FrontendOptions::doesActionProduceOutput(ActionType action) {
switch (action) {
case ActionType::Parse:
Expand Down
3 changes: 3 additions & 0 deletions lib/Frontend/Types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ bool file_types::isTextual(ID Id) {
case file_types::TY_TBD:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
return true;
case file_types::TY_Image:
case file_types::TY_Object:
Expand Down Expand Up @@ -130,6 +131,7 @@ bool file_types::isAfterLLVM(ID Id) {
case file_types::TY_IndexData:
case file_types::TY_ModuleTrace:
case file_types::TY_OptRecord:
case file_types::TY_SwiftModuleInterfaceFile:
return false;
case file_types::TY_INVALID:
llvm_unreachable("Invalid type ID.");
Expand Down Expand Up @@ -161,6 +163,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
case file_types::TY_dSYM:
case file_types::TY_SwiftModuleFile:
case file_types::TY_SwiftModuleDocFile:
case file_types::TY_SwiftModuleInterfaceFile:
case file_types::TY_SerializedDiagnostics:
case file_types::TY_ClangModuleFile:
case file_types::TY_SwiftDeps:
Expand Down
18 changes: 16 additions & 2 deletions test/Driver/Inputs/invalid-module-name.swift
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
func meow() {
}
// Tests what happens when an explicitly-specified or inferred module name isn't
// a valid Swift identifier.

// RUN: not %target-swift-frontend -emit-silgen -parse-as-library %S/Inputs/invalid-module-name.swift 2>&1 | %FileCheck -check-prefix=INVALID_MODULE_NAME %s
// INVALID_MODULE_NAME: error: module name "invalid-module-name" is not a valid identifier; use -module-name flag to specify an alternate name

// RUN: not %target-swift-frontend -emit-silgen -parse-as-library %S/Inputs/invalid.module.name.swift 2>&1 | %FileCheck -check-prefix=INVALID_MODULE_NAME2 %s
// INVALID_MODULE_NAME2: error: module name "invalid.module.name" is not a valid identifier; use -module-name flag to specify an alternate name

// RUN: not %target-swift-frontend -emit-silgen -parse-as-library %S/Inputs/invalid-module-name.swift -module-name still-invalid 2>&1 | %FileCheck -check-prefix=STILL_INVALID %s
// STILL_INVALID: error: module name "still-invalid" is not a valid identifier{{$}}

// These should succeed.
// RUN: %target-swift-frontend -emit-silgen %S/Inputs/invalid-module-name.swift > /dev/null
// RUN: %target-swift-frontend -emit-silgen -parse-as-library %S/Inputs/invalid-module-name.swift -module-name foo > /dev/null
// RUN: %target-swift-frontend -typecheck -parse-as-library %S/Inputs/invalid-module-name.swift -module-name foo
2 changes: 1 addition & 1 deletion test/Driver/Inputs/lib.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
// Used by multiple_input.swift and emit-objc-header.swift tests.
// Used by emit-objc-header.swift and others.

func libraryFunction() {}
4 changes: 2 additions & 2 deletions test/Driver/Inputs/main.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Used by multiple_input.swift and emit-objc-header.swift tests. This file
// should be inferred as the main source file from its name.
// Used by emit-objc-header.swift and others.
// This file should be inferred as the main source file from its name.

var x = 4 + 5
print(x)
Expand Down
6 changes: 0 additions & 6 deletions test/Driver/multiple_input.swift

This file was deleted.

Loading