Skip to content

Commit b9ae66d

Browse files
committed
[Frontend] Add a new -emit-interface-path option
...but don't hook it up to anything yet. This is the very very start of the module stability / textual interfaces feature described at https://forums.swift.org/t/plan-for-module-stability/14551/ For now I've just made it a frontend option (not a driver option), which is good enough for testing.
1 parent d176bfa commit b9ae66d

15 files changed

+119
-34
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ ERROR(error_mode_cannot_emit_module,none,
119119
"this mode does not support emitting modules", ())
120120
ERROR(error_mode_cannot_emit_module_doc,none,
121121
"this mode does not support emitting module documentation files", ())
122+
ERROR(error_mode_cannot_emit_interface,none,
123+
"this mode does not support emitting textual interface files", ())
122124

123125
WARNING(emit_reference_dependencies_without_primary_file,none,
124126
"ignoring -emit-reference-dependencies (requires -primary-file)", ())

include/swift/Basic/SupplementaryOutputPaths.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ struct SupplementaryOutputPaths {
6060
/// It is currently only used with WMO, but could be generalized.
6161
std::string TBDPath;
6262

63+
/// The path to which we should emit a textual module interface, which can be
64+
/// used by a client source file to import this module.
65+
///
66+
/// Currently only makes sense when the compiler has whole-module knowledge.
67+
std::string ModuleInterfaceOutputPath;
68+
6369
SupplementaryOutputPaths() = default;
6470
SupplementaryOutputPaths(const SupplementaryOutputPaths &) = default;
6571

@@ -68,7 +74,7 @@ struct SupplementaryOutputPaths {
6874
ModuleDocOutputPath.empty() && DependenciesFilePath.empty() &&
6975
ReferenceDependenciesFilePath.empty() &&
7076
SerializedDiagnosticsPath.empty() && LoadedModuleTracePath.empty() &&
71-
TBDPath.empty();
77+
TBDPath.empty() && ModuleInterfaceOutputPath.empty();
7278
}
7379
};
7480
} // namespace swift

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ class FrontendInputsAndOutputs {
234234
bool hasLoadedModuleTracePath() const;
235235
bool hasModuleOutputPath() const;
236236
bool hasModuleDocOutputPath() const;
237+
bool hasModuleInterfaceOutputPath() const;
237238
bool hasTBDPath() const;
238239

239240
bool hasDependencyTrackerPath() const;

include/swift/Frontend/FrontendOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ class FrontendOptions {
302302
static bool canActionEmitLoadedModuleTrace(ActionType);
303303
static bool canActionEmitModule(ActionType);
304304
static bool canActionEmitModuleDoc(ActionType);
305+
static bool canActionEmitInterface(ActionType);
305306

306307
public:
307308
static bool doesActionProduceOutput(ActionType);

include/swift/Frontend/Types.def

Lines changed: 31 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -27,45 +27,46 @@
2727
// The second value is the type id, which will result in a
2828
// swift::driver::file_types::TY_XX enum constant.
2929

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

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

3838
// Input types
39-
TYPE("swift", Swift, "swift", "")
40-
TYPE("sil", SIL, "sil", "")
41-
TYPE("sib", SIB, "sib", "")
39+
TYPE("swift", Swift, "swift", "")
40+
TYPE("sil", SIL, "sil", "")
41+
TYPE("sib", SIB, "sib", "")
4242

4343
// Output types
44-
TYPE("image", Image, "out", "")
45-
TYPE("object", Object, "o", "")
46-
TYPE("dSYM", dSYM, "dSYM", "")
47-
TYPE("dependencies", Dependencies, "d", "")
48-
TYPE("autolink", AutolinkFile, "autolink", "")
49-
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
50-
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
51-
TYPE("assembly", Assembly, "s", "")
52-
TYPE("raw-sil", RawSIL, "sil", "")
53-
TYPE("raw-sib", RawSIB, "sib", "")
54-
TYPE("llvm-ir", LLVM_IR, "ir", "")
55-
TYPE("llvm-bc", LLVM_BC, "bc", "")
56-
TYPE("diagnostics", SerializedDiagnostics, "dia", "")
57-
TYPE("objc-header", ObjCHeader, "h", "")
58-
TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
59-
TYPE("remap", Remapping, "remap", "")
60-
TYPE("imported-modules", ImportedModules, "importedmodules", "")
61-
TYPE("tbd", TBD, "tbd", "")
62-
TYPE("module-trace", ModuleTrace, "trace.json", "")
63-
TYPE("index-data", IndexData, "", "")
64-
TYPE("opt-record", OptRecord, "opt.yaml", "")
44+
TYPE("image", Image, "out", "")
45+
TYPE("object", Object, "o", "")
46+
TYPE("dSYM", dSYM, "dSYM", "")
47+
TYPE("dependencies", Dependencies, "d", "")
48+
TYPE("autolink", AutolinkFile, "autolink", "")
49+
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
50+
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
51+
TYPE("swiftinterface", SwiftModuleInterfaceFile, "swiftinterface", "")
52+
TYPE("assembly", Assembly, "s", "")
53+
TYPE("raw-sil", RawSIL, "sil", "")
54+
TYPE("raw-sib", RawSIB, "sib", "")
55+
TYPE("llvm-ir", LLVM_IR, "ir", "")
56+
TYPE("llvm-bc", LLVM_BC, "bc", "")
57+
TYPE("diagnostics", SerializedDiagnostics, "dia", "")
58+
TYPE("objc-header", ObjCHeader, "h", "")
59+
TYPE("swift-dependencies", SwiftDeps, "swiftdeps", "")
60+
TYPE("remap", Remapping, "remap", "")
61+
TYPE("imported-modules", ImportedModules, "importedmodules", "")
62+
TYPE("tbd", TBD, "tbd", "")
63+
TYPE("module-trace", ModuleTrace, "trace.json", "")
64+
TYPE("index-data", IndexData, "", "")
65+
TYPE("opt-record", OptRecord, "opt.yaml", "")
6566

6667
// Misc types
67-
TYPE("pcm", ClangModuleFile, "pcm", "")
68-
TYPE("pch", PCH, "pch", "")
69-
TYPE("none", Nothing, "", "")
68+
TYPE("pcm", ClangModuleFile, "pcm", "")
69+
TYPE("pch", PCH, "pch", "")
70+
TYPE("none", Nothing, "", "")
7071

7172
#undef TYPE

include/swift/Option/FrontendOptions.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ def emit_fixits_path
6363
: Separate<["-"], "emit-fixits-path">, MetaVarName<"<path>">,
6464
HelpText<"Output compiler fixits as source edits to <path>">;
6565

66+
def emit_interface_path
67+
: Separate<["-"], "emit-interface-path">, MetaVarName<"<path>">,
68+
HelpText<"Output textual interface file to <path>">;
69+
6670
def tbd_install_name
6771
: Separate<["-"], "tbd-install_name">, MetaVarName<"<path>">,
6872
HelpText<"The install_name to use in an emitted TBD file">;

lib/Driver/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1731,6 +1731,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
17311731
case file_types::TY_TBD:
17321732
case file_types::TY_ModuleTrace:
17331733
case file_types::TY_OptRecord:
1734+
case file_types::TY_SwiftModuleInterfaceFile:
17341735
// We could in theory handle assembly or LLVM input, but let's not.
17351736
// FIXME: What about LTO?
17361737
Diags.diagnose(SourceLoc(), diag::error_unexpected_input_file,

lib/Driver/ToolChains.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
432432
case file_types::TY_ModuleTrace:
433433
case file_types::TY_TBD:
434434
case file_types::TY_OptRecord:
435+
case file_types::TY_SwiftModuleInterfaceFile:
435436
llvm_unreachable("Output type can never be primary output.");
436437
case file_types::TY_INVALID:
437438
llvm_unreachable("Invalid type ID");
@@ -655,6 +656,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
655656
case file_types::TY_Remapping:
656657
case file_types::TY_ModuleTrace:
657658
case file_types::TY_OptRecord:
659+
case file_types::TY_SwiftModuleInterfaceFile:
658660
llvm_unreachable("Output type can never be primary output.");
659661
case file_types::TY_INVALID:
660662
llvm_unreachable("Invalid type ID");

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
496496
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_module_doc);
497497
return true;
498498
}
499+
if (!FrontendOptions::canActionEmitInterface(Opts.RequestedAction) &&
500+
Opts.InputsAndOutputs.hasModuleInterfaceOutputPath()) {
501+
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_interface);
502+
return true;
503+
}
499504
return false;
500505
}
501506

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -291,10 +291,13 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
291291
auto loadedModuleTrace = getSupplementaryFilenamesFromArguments(
292292
options::OPT_emit_loaded_module_trace_path);
293293
auto TBD = getSupplementaryFilenamesFromArguments(options::OPT_emit_tbd_path);
294+
auto moduleInterfaceOutput = getSupplementaryFilenamesFromArguments(
295+
options::OPT_emit_interface_path);
294296

295297
if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
296298
!dependenciesFile || !referenceDependenciesFile ||
297-
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD) {
299+
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD ||
300+
!moduleInterfaceOutput) {
298301
return None;
299302
}
300303
std::vector<SupplementaryOutputPaths> result;
@@ -312,6 +315,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
312315
sop.FixItsOutputPath = (*fixItsOutput)[i];
313316
sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
314317
sop.TBDPath = (*TBD)[i];
318+
sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[i];
315319

316320
result.push_back(sop);
317321
}
@@ -382,6 +386,9 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
382386
SERIALIZED_MODULE_DOC_EXTENSION, "",
383387
defaultSupplementaryOutputPathExcludingExtension);
384388

389+
// There is no non-path form of -emit-interface-path
390+
auto moduleInterfaceOutputPath = pathsFromArguments.ModuleInterfaceOutputPath;
391+
385392
ID emitModuleOption;
386393
std::string moduleExtension;
387394
std::string mainOutputIfUsableForModule;
@@ -403,6 +410,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
403410
sop.FixItsOutputPath = fixItsOutputPath;
404411
sop.LoadedModuleTracePath = loadedModuleTracePath;
405412
sop.TBDPath = tbdPath;
413+
sop.ModuleInterfaceOutputPath = moduleInterfaceOutputPath;
406414
return sop;
407415
}
408416

@@ -475,7 +483,9 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
475483
{file_types::TY_SwiftDeps, paths.ReferenceDependenciesFilePath},
476484
{file_types::TY_SerializedDiagnostics, paths.SerializedDiagnosticsPath},
477485
{file_types::TY_ModuleTrace, paths.LoadedModuleTracePath},
478-
{file_types::TY_TBD, paths.TBDPath}};
486+
{file_types::TY_TBD, paths.TBDPath},
487+
{file_types::TY_SwiftModuleInterfaceFile,paths.ModuleInterfaceOutputPath}
488+
};
479489
for (const std::pair<file_types::ID, std::string &> &typeAndString :
480490
typesAndStrings) {
481491
auto const out = map->find(typeAndString.first);

lib/Frontend/FrontendInputsAndOutputs.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,12 @@ bool FrontendInputsAndOutputs::hasModuleDocOutputPath() const {
418418
return outs.ModuleDocOutputPath;
419419
});
420420
}
421+
bool FrontendInputsAndOutputs::hasModuleInterfaceOutputPath() const {
422+
return hasSupplementaryOutputPath(
423+
[](const SupplementaryOutputPaths &outs) -> const std::string & {
424+
return outs.ModuleInterfaceOutputPath;
425+
});
426+
}
421427
bool FrontendInputsAndOutputs::hasTBDPath() const {
422428
return hasSupplementaryOutputPath(
423429
[](const SupplementaryOutputPaths &outs) -> const std::string & {

lib/Frontend/FrontendOptions.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ void FrontendOptions::forAllOutputPaths(
122122
input.getPrimarySpecificPaths().SupplementaryOutputs;
123123
const std::string *outputs[] = {&outs.ModuleOutputPath,
124124
&outs.ModuleDocOutputPath,
125+
&outs.ModuleInterfaceOutputPath,
125126
&outs.ObjCHeaderOutputPath};
126127
for (const std::string *next : outputs) {
127128
if (!next->empty())
@@ -348,6 +349,38 @@ bool FrontendOptions::canActionEmitModuleDoc(ActionType action) {
348349
return canActionEmitModule(action);
349350
}
350351

352+
bool FrontendOptions::canActionEmitInterface(ActionType action) {
353+
switch (action) {
354+
case ActionType::NoneAction:
355+
case ActionType::Parse:
356+
case ActionType::ResolveImports:
357+
case ActionType::Typecheck:
358+
case ActionType::DumpParse:
359+
case ActionType::DumpInterfaceHash:
360+
case ActionType::DumpAST:
361+
case ActionType::EmitSyntax:
362+
case ActionType::PrintAST:
363+
case ActionType::EmitPCH:
364+
case ActionType::DumpScopeMaps:
365+
case ActionType::DumpTypeRefinementContexts:
366+
case ActionType::EmitSILGen:
367+
case ActionType::EmitSIBGen:
368+
case ActionType::Immediate:
369+
case ActionType::REPL:
370+
case ActionType::EmitImportedModules:
371+
return false;
372+
case ActionType::MergeModules:
373+
case ActionType::EmitModuleOnly:
374+
case ActionType::EmitSIL:
375+
case ActionType::EmitSIB:
376+
case ActionType::EmitIR:
377+
case ActionType::EmitBC:
378+
case ActionType::EmitAssembly:
379+
case ActionType::EmitObject:
380+
return true;
381+
}
382+
}
383+
351384
bool FrontendOptions::doesActionProduceOutput(ActionType action) {
352385
switch (action) {
353386
case ActionType::Parse:

lib/Frontend/Types.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ bool file_types::isTextual(ID Id) {
7575
case file_types::TY_TBD:
7676
case file_types::TY_ModuleTrace:
7777
case file_types::TY_OptRecord:
78+
case file_types::TY_SwiftModuleInterfaceFile:
7879
return true;
7980
case file_types::TY_Image:
8081
case file_types::TY_Object:
@@ -130,6 +131,7 @@ bool file_types::isAfterLLVM(ID Id) {
130131
case file_types::TY_IndexData:
131132
case file_types::TY_ModuleTrace:
132133
case file_types::TY_OptRecord:
134+
case file_types::TY_SwiftModuleInterfaceFile:
133135
return false;
134136
case file_types::TY_INVALID:
135137
llvm_unreachable("Invalid type ID.");
@@ -161,6 +163,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
161163
case file_types::TY_dSYM:
162164
case file_types::TY_SwiftModuleFile:
163165
case file_types::TY_SwiftModuleDocFile:
166+
case file_types::TY_SwiftModuleInterfaceFile:
164167
case file_types::TY_SerializedDiagnostics:
165168
case file_types::TY_ClangModuleFile:
166169
case file_types::TY_SwiftDeps:

test/Frontend/dependencies.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@
2525
// NO-PRIMARY-FILE: warning: ignoring -emit-reference-dependencies (requires -primary-file)
2626

2727

28-
// RUN: %target-swift-frontend -emit-dependencies-path - -emit-module %S/../Inputs/empty\ file.swift -o %t/empty\ file.swiftmodule -emit-module-doc-path %t/empty\ file.swiftdoc -emit-objc-header-path %t/empty\ file.h | %FileCheck -check-prefix=CHECK-MULTIPLE-OUTPUTS %s
28+
// RUN: %target-swift-frontend -emit-dependencies-path - -emit-module %S/../Inputs/empty\ file.swift -o %t/empty\ file.swiftmodule -emit-module-doc-path %t/empty\ file.swiftdoc -emit-objc-header-path %t/empty\ file.h -emit-interface-path %t/empty\ file.swiftinterface | %FileCheck -check-prefix=CHECK-MULTIPLE-OUTPUTS %s
2929

3030
// CHECK-MULTIPLE-OUTPUTS-LABEL: empty\ file.swiftmodule :
3131
// CHECK-MULTIPLE-OUTPUTS: Inputs/empty\ file.swift
3232
// CHECK-MULTIPLE-OUTPUTS: Swift.swiftmodule
3333
// CHECK-MULTIPLE-OUTPUTS-LABEL: empty\ file.swiftdoc :
3434
// CHECK-MULTIPLE-OUTPUTS: Inputs/empty\ file.swift
3535
// CHECK-MULTIPLE-OUTPUTS: Swift.swiftmodule
36+
// CHECK-MULTIPLE-OUTPUTS-LABEL: empty\ file.swiftinterface :
37+
// CHECK-MULTIPLE-OUTPUTS: Inputs/empty\ file.swift
38+
// CHECK-MULTIPLE-OUTPUTS: Swift.swiftmodule
3639
// CHECK-MULTIPLE-OUTPUTS-LABEL: empty\ file.h :
3740
// CHECK-MULTIPLE-OUTPUTS: Inputs/empty\ file.swift
3841
// CHECK-MULTIPLE-OUTPUTS: Swift.swiftmodule

test/Frontend/supplementary-output-support.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,10 @@
2323
// DUMP_NO_OBJC_HEADER: error: this mode does not support emitting Objective-C headers{{$}}
2424
// RUN: not %target-swift-frontend -resolve-imports -emit-objc-header %s 2>&1 | %FileCheck -check-prefix=RESOLVE_IMPORTS_NO_OBJC_HEADER %s
2525
// RESOLVE_IMPORTS_NO_OBJC_HEADER: error: this mode does not support emitting Objective-C headers{{$}}
26+
27+
// RUN: not %target-swift-frontend -parse -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=PARSE_NO_INTERFACE %s
28+
// PARSE_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}
29+
// RUN: not %target-swift-frontend -typecheck -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=TYPECHECK_NO_INTERFACE %s
30+
// TYPECHECK_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}
31+
// RUN: not %target-swift-frontend -emit-silgen -emit-interface-path %t %s 2>&1 | %FileCheck -check-prefix=SILGEN_NO_INTERFACE %s
32+
// SILGEN_NO_INTERFACE: error: this mode does not support emitting textual interface files{{$}}

0 commit comments

Comments
 (0)