Skip to content

Commit e01f234

Browse files
authored
Merge pull request #68994 from tshortli/api-extract-supplementary-output
TBDGen: Introduce option to emit API descriptor as supplementary output
2 parents 37f5b43 + 778532d commit e01f234

24 files changed

+428
-142
lines changed

include/swift/AST/DiagnosticsFrontend.def

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,9 @@ ERROR(error_mode_cannot_emit_module_summary,none,
152152
ERROR(error_mode_cannot_emit_symbol_graph,none,
153153
"this mode does not support emitting symbol graph files", ())
154154
ERROR(error_mode_cannot_emit_abi_descriptor,none,
155-
"this mode does not support emitting ABI descriptor", ())
155+
"this mode does not support emitting ABI descriptor files", ())
156+
ERROR(error_mode_cannot_emit_api_descriptor,none,
157+
"this mode does not support emitting API descriptor files", ())
156158
ERROR(error_mode_cannot_emit_const_values,none,
157159
"this mode does not support emitting extracted const values", ())
158160
ERROR(error_mode_cannot_emit_module_semantic_info,none,
@@ -313,6 +315,10 @@ ERROR(tbd_not_supported_with_cmo,none,
313315
"Test-Based InstallAPI (TBD) is not support with cross-module-optimization",
314316
())
315317

318+
WARNING(api_descriptor_only_supported_in_whole_module,none,
319+
"API descriptor generation is only supported when the whole module can be seen",
320+
())
321+
316322
ERROR(previous_installname_map_missing,none,
317323
"cannot open previous install name map from %0",
318324
(StringRef))

include/swift/Basic/FileTypes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ TYPE("pch", PCH, "pch", "")
9898
TYPE("none", Nothing, "", "")
9999

100100
TYPE("abi-baseline-json", SwiftABIDescriptor, "abi.json", "")
101+
TYPE("api-json", SwiftAPIDescriptor, "", "")
101102
TYPE("fixit", SwiftFixIt, "", "")
102103
TYPE("module-semantic-info", ModuleSemanticInfo, "", "")
103104
TYPE("cached-diagnostics", CachedDiagnostics, "", "")

include/swift/Basic/SupplementaryOutputPaths.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ OUTPUT(ModuleSummaryOutputPath, TY_SwiftModuleSummaryFile)
143143
/// The output path to generate ABI baseline.
144144
OUTPUT(ABIDescriptorOutputPath, TY_SwiftABIDescriptor)
145145

146+
/// The output path to the module's API description.
147+
OUTPUT(APIDescriptorOutputPath, TY_SwiftAPIDescriptor)
148+
146149
/// The output path for extracted compile-time-known value information
147150
OUTPUT(ConstValuesOutputPath, TY_ConstValues)
148151

include/swift/Frontend/Frontend.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,11 @@ class CompilerInvocation {
428428
std::string getModuleInterfaceOutputPathForWholeModule() const;
429429
std::string getPrivateModuleInterfaceOutputPathForWholeModule() const;
430430

431+
/// APIDescriptorPath only makes sense in whole module compilation mode,
432+
/// so return the APIDescriptorPath when in that mode and fail an assert
433+
/// if not in that mode.
434+
std::string getAPIDescriptorPathForWholeModule() const;
435+
431436
public:
432437
/// Given the current configuration of this frontend invocation, a set of
433438
/// supplementary output paths, and a module, compute the appropriate set of

include/swift/Frontend/FrontendInputsAndOutputs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class FrontendInputsAndOutputs {
265265
bool hasModuleInterfaceOutputPath() const;
266266
bool hasPrivateModuleInterfaceOutputPath() const;
267267
bool hasABIDescriptorOutputPath() const;
268+
bool hasAPIDescriptorOutputPath() const;
268269
bool hasConstValuesOutputPath() const;
269270
bool hasModuleSemanticInfoOutputPath() const;
270271
bool hasModuleSummaryOutputPath() const;

include/swift/Frontend/FrontendOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ class FrontendOptions {
569569
static bool canActionEmitModuleSummary(ActionType);
570570
static bool canActionEmitInterface(ActionType);
571571
static bool canActionEmitABIDescriptor(ActionType);
572+
static bool canActionEmitAPIDescriptor(ActionType);
572573
static bool canActionEmitConstValues(ActionType);
573574
static bool canActionEmitModuleSemanticInfo(ActionType);
574575

include/swift/Option/Options.td

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,19 @@ def emit_const_values :
626626
def emit_const_values_path : Separate<["-"], "emit-const-values-path">,
627627
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
628628
SupplementaryOutput, CacheInvariant]>,
629-
MetaVarName<"<path>">, HelpText<"Emit the extracted compile-time known values to <path>">;
629+
MetaVarName<"<path>">,
630+
HelpText<"Emit the extracted compile-time known values to <path>">;
631+
632+
def emit_api_descriptor :
633+
Flag<["-"], "emit-api-descriptor">,
634+
Flags<[NoInteractiveOption, SupplementaryOutput, CacheInvariant]>,
635+
HelpText<"Output a JSON file describing the module's API">;
636+
def emit_api_descriptor_path :
637+
Separate<["-"], "emit-api-descriptor-path">,
638+
Flags<[FrontendOption, NoInteractiveOption, ArgumentIsPath,
639+
SupplementaryOutput, CacheInvariant]>,
640+
MetaVarName<"<path>">,
641+
HelpText<"Output a JSON file describing the module's API to <path>">;
630642

631643
def emit_objc_header : Flag<["-"], "emit-objc-header">,
632644
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput, CacheInvariant]>,

lib/Basic/FileTypes.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ bool file_types::isTextual(ID Id) {
8686
case file_types::TY_JSONDependencies:
8787
case file_types::TY_JSONFeatures:
8888
case file_types::TY_SwiftABIDescriptor:
89+
case file_types::TY_SwiftAPIDescriptor:
8990
case file_types::TY_ConstValues:
9091
return true;
9192
case file_types::TY_Image:
@@ -164,6 +165,7 @@ bool file_types::isAfterLLVM(ID Id) {
164165
case file_types::TY_JSONFeatures:
165166
case file_types::TY_IndexUnitOutputPath:
166167
case file_types::TY_SwiftABIDescriptor:
168+
case file_types::TY_SwiftAPIDescriptor:
167169
case file_types::TY_ConstValues:
168170
case file_types::TY_SwiftFixIt:
169171
case file_types::TY_ModuleSemanticInfo:
@@ -220,6 +222,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
220222
case file_types::TY_JSONFeatures:
221223
case file_types::TY_IndexUnitOutputPath:
222224
case file_types::TY_SwiftABIDescriptor:
225+
case file_types::TY_SwiftAPIDescriptor:
223226
case file_types::TY_ConstValues:
224227
case file_types::TY_SwiftFixIt:
225228
case file_types::TY_ModuleSemanticInfo:

lib/Driver/Driver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2090,6 +2090,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
20902090
case file_types::TY_JSONDependencies:
20912091
case file_types::TY_JSONFeatures:
20922092
case file_types::TY_SwiftABIDescriptor:
2093+
case file_types::TY_SwiftAPIDescriptor:
20932094
case file_types::TY_ConstValues:
20942095
case file_types::TY_SwiftFixIt:
20952096
case file_types::TY_ModuleSemanticInfo:

lib/Driver/ToolChains.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
733733
case file_types::TY_SwiftOverlayFile:
734734
case file_types::TY_IndexUnitOutputPath:
735735
case file_types::TY_SwiftABIDescriptor:
736+
case file_types::TY_SwiftAPIDescriptor:
736737
case file_types::TY_ConstValues:
737738
case file_types::TY_SwiftFixIt:
738739
case file_types::TY_ModuleSemanticInfo:
@@ -997,6 +998,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
997998
case file_types::TY_SwiftOverlayFile:
998999
case file_types::TY_IndexUnitOutputPath:
9991000
case file_types::TY_SwiftABIDescriptor:
1001+
case file_types::TY_SwiftAPIDescriptor:
10001002
case file_types::TY_ConstValues:
10011003
case file_types::TY_SwiftFixIt:
10021004
case file_types::TY_ModuleSemanticInfo:

lib/Frontend/ArgsToFrontendOptionsConverter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,11 @@ bool ArgsToFrontendOptionsConverter::checkUnusedSupplementaryOutputPaths()
765765
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_abi_descriptor);
766766
return true;
767767
}
768+
if (!FrontendOptions::canActionEmitAPIDescriptor(Opts.RequestedAction) &&
769+
Opts.InputsAndOutputs.hasAPIDescriptorOutputPath()) {
770+
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_api_descriptor);
771+
return true;
772+
}
768773
if (!FrontendOptions::canActionEmitConstValues(Opts.RequestedAction) &&
769774
Opts.InputsAndOutputs.hasConstValuesOutputPath()) {
770775
Diags.diagnose(SourceLoc(), diag::error_mode_cannot_emit_const_values);

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,8 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
331331
options::OPT_emit_module_summary_path);
332332
auto abiDescriptorOutput = getSupplementaryFilenamesFromArguments(
333333
options::OPT_emit_abi_descriptor_path);
334+
auto apiDescriptorOutput = getSupplementaryFilenamesFromArguments(
335+
options::OPT_emit_api_descriptor_path);
334336
auto constValuesOutput = getSupplementaryFilenamesFromArguments(
335337
options::OPT_emit_const_values_path);
336338
auto moduleSemanticInfoOutput = getSupplementaryFilenamesFromArguments(
@@ -365,6 +367,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
365367
sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i];
366368
sop.ModuleSummaryOutputPath = (*moduleSummaryOutput)[i];
367369
sop.ABIDescriptorOutputPath = (*abiDescriptorOutput)[i];
370+
sop.APIDescriptorOutputPath = (*apiDescriptorOutput)[i];
368371
sop.ConstValuesOutputPath = (*constValuesOutput)[i];
369372
sop.ModuleSemanticInfoOutputPath = (*moduleSemanticInfoOutput)[i];
370373
sop.YAMLOptRecordPath = (*optRecordOutput)[i];
@@ -475,8 +478,13 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
475478

476479
// There is no non-path form of -emit-abi-descriptor-path
477480
auto ABIDescriptorOutputPath = pathsFromArguments.ABIDescriptorOutputPath;
481+
482+
// There is no non-path form of -emit-api-descriptor-path
483+
auto APIDescriptorOutputPath = pathsFromArguments.APIDescriptorOutputPath;
484+
478485
// There is no non-path form of -emit-module-semantic-info-path
479-
auto ModuleSemanticInfoOutputPath = pathsFromArguments.ModuleSemanticInfoOutputPath;
486+
auto ModuleSemanticInfoOutputPath =
487+
pathsFromArguments.ModuleSemanticInfoOutputPath;
480488

481489
ID emitModuleOption;
482490
std::string moduleExtension;
@@ -513,6 +521,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
513521
sop.ModuleSourceInfoOutputPath = moduleSourceInfoOutputPath;
514522
sop.ModuleSummaryOutputPath = moduleSummaryOutputPath;
515523
sop.ABIDescriptorOutputPath = ABIDescriptorOutputPath;
524+
sop.APIDescriptorOutputPath = APIDescriptorOutputPath;
516525
sop.ConstValuesOutputPath = constValuesOutputPath;
517526
sop.ModuleSemanticInfoOutputPath = ModuleSemanticInfoOutputPath;
518527
sop.YAMLOptRecordPath = YAMLOptRecordPath;

lib/Frontend/Frontend.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,14 @@ CompilerInvocation::getPrivateModuleInterfaceOutputPathForWholeModule() const {
165165
.SupplementaryOutputs.PrivateModuleInterfaceOutputPath;
166166
}
167167

168+
std::string CompilerInvocation::getAPIDescriptorPathForWholeModule() const {
169+
assert(
170+
getFrontendOptions().InputsAndOutputs.isWholeModule() &&
171+
"APIDescriptorPath only makes sense when the whole module can be seen");
172+
return getPrimarySpecificPathsForAtMostOnePrimary()
173+
.SupplementaryOutputs.APIDescriptorOutputPath;
174+
}
175+
168176
SerializationOptions CompilerInvocation::computeSerializationOptions(
169177
const SupplementaryOutputPaths &outs, const ModuleDecl *module) const {
170178
const FrontendOptions &opts = getFrontendOptions();

lib/Frontend/FrontendInputsAndOutputs.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,12 @@ bool FrontendInputsAndOutputs::hasABIDescriptorOutputPath() const {
511511
return outs.ABIDescriptorOutputPath;
512512
});
513513
}
514+
bool FrontendInputsAndOutputs::hasAPIDescriptorOutputPath() const {
515+
return hasSupplementaryOutputPath(
516+
[](const SupplementaryOutputPaths &outs) -> const std::string & {
517+
return outs.APIDescriptorOutputPath;
518+
});
519+
}
514520
bool FrontendInputsAndOutputs::hasConstValuesOutputPath() const {
515521
return hasSupplementaryOutputPath(
516522
[](const SupplementaryOutputPaths &outs) -> const std::string & {

lib/Frontend/FrontendOptions.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,48 @@ bool FrontendOptions::canActionEmitInterface(ActionType action) {
743743
llvm_unreachable("unhandled action");
744744
}
745745

746+
bool FrontendOptions::canActionEmitAPIDescriptor(ActionType action) {
747+
switch (action) {
748+
case ActionType::NoneAction:
749+
case ActionType::Parse:
750+
case ActionType::DumpParse:
751+
case ActionType::DumpInterfaceHash:
752+
case ActionType::DumpAST:
753+
case ActionType::PrintAST:
754+
case ActionType::PrintASTDecl:
755+
case ActionType::EmitImportedModules:
756+
case ActionType::EmitPCH:
757+
case ActionType::DumpScopeMaps:
758+
case ActionType::DumpTypeRefinementContexts:
759+
case ActionType::DumpTypeInfo:
760+
case ActionType::EmitSILGen:
761+
case ActionType::EmitSIBGen:
762+
case ActionType::CompileModuleFromInterface:
763+
case ActionType::TypecheckModuleFromInterface:
764+
case ActionType::Immediate:
765+
case ActionType::REPL:
766+
case ActionType::EmitPCM:
767+
case ActionType::DumpPCM:
768+
case ActionType::ScanDependencies:
769+
case ActionType::PrintFeature:
770+
return false;
771+
case ActionType::ResolveImports:
772+
case ActionType::Typecheck:
773+
case ActionType::MergeModules:
774+
case ActionType::EmitModuleOnly:
775+
case ActionType::EmitSIL:
776+
case ActionType::EmitSIB:
777+
case ActionType::EmitIRGen:
778+
case ActionType::EmitIR:
779+
case ActionType::EmitBC:
780+
case ActionType::EmitAssembly:
781+
case ActionType::EmitObject:
782+
case ActionType::PrintVersion:
783+
return true;
784+
}
785+
llvm_unreachable("unhandled action");
786+
}
787+
746788
bool FrontendOptions::doesActionProduceOutput(ActionType action) {
747789
switch (action) {
748790
case ActionType::Parse:

lib/FrontendTool/FrontendTool.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,34 @@ static bool writeTBDIfNeeded(CompilerInstance &Instance) {
809809
Instance.getOutputBackend(), tbdOpts);
810810
}
811811

812+
static bool writeAPIDescriptor(ModuleDecl *M, StringRef OutputPath,
813+
llvm::vfs::OutputBackend &Backend) {
814+
return withOutputPath(M->getDiags(), Backend, OutputPath,
815+
[&](raw_ostream &OS) -> bool {
816+
writeAPIJSONFile(M, OS, /*PrettyPrinted=*/false);
817+
return false;
818+
});
819+
}
820+
821+
static bool writeAPIDescriptorIfNeeded(CompilerInstance &Instance) {
822+
const auto &Invocation = Instance.getInvocation();
823+
const auto &frontendOpts = Invocation.getFrontendOptions();
824+
if (!frontendOpts.InputsAndOutputs.hasAPIDescriptorOutputPath())
825+
return false;
826+
827+
if (!frontendOpts.InputsAndOutputs.isWholeModule()) {
828+
Instance.getDiags().diagnose(
829+
SourceLoc(), diag::api_descriptor_only_supported_in_whole_module);
830+
return false;
831+
}
832+
833+
const std::string &APIDescriptorPath =
834+
Invocation.getAPIDescriptorPathForWholeModule();
835+
836+
return writeAPIDescriptor(Instance.getMainModule(), APIDescriptorPath,
837+
Instance.getOutputBackend());
838+
}
839+
812840
static bool performCompileStepsPostSILGen(CompilerInstance &Instance,
813841
std::unique_ptr<SILModule> SM,
814842
ModuleOrSourceFile MSF,
@@ -975,6 +1003,10 @@ static bool emitAnyWholeModulePostTypeCheckSupplementaryOutputs(
9751003
hadAnyError |= writeTBDIfNeeded(Instance);
9761004
}
9771005

1006+
{
1007+
hadAnyError |= writeAPIDescriptorIfNeeded(Instance);
1008+
}
1009+
9781010
{
9791011
hadAnyError |= writeModuleSemanticInfoIfNeeded(Instance);
9801012
}

0 commit comments

Comments
 (0)