Skip to content

Commit 9013928

Browse files
committed
[Frontend] Output the private module interface with the SPI info
1 parent 2e73cb4 commit 9013928

19 files changed

+139
-24
lines changed

include/swift/AST/PrintOptions.h

+9-2
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ struct PrintOptions {
270270
/// Whether to skip keywords with a prefix of underscore such as __consuming.
271271
bool SkipUnderscoredKeywords = false;
272272

273+
// Print SPI attributes and decls that are visible only as SPI.
274+
bool PrintSPIs = true;
275+
273276
/// Prints type variables and unresolved types in an expanded notation suitable
274277
/// for debugging.
275278
bool PrintTypesForDebugging = false;
@@ -515,14 +518,18 @@ struct PrintOptions {
515518
return result;
516519
}
517520

518-
/// Retrieve the set of options suitable for module interfaces.
521+
/// Retrieve the set of options suitable for textual module interfaces.
519522
///
520523
/// This is a format that will be parsed again later, so the output must be
521524
/// consistent and well-formed.
522525
///
526+
/// Set \p printSPIs to produce a module interface with the SPI decls and
527+
/// attributes.
528+
///
523529
/// \see swift::emitSwiftInterface
524530
static PrintOptions printSwiftInterfaceFile(bool preferTypeRepr,
525-
bool printFullConvention);
531+
bool printFullConvention,
532+
bool printSPIs);
526533

527534
/// Retrieve the set of options suitable for "Generated Interfaces", which
528535
/// are a prettified representation of the public API of a module, to be

include/swift/Basic/FileTypes.def

+1
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ TYPE("autolink", AutolinkFile, "autolink", "")
5050
TYPE("swiftmodule", SwiftModuleFile, "swiftmodule", "")
5151
TYPE("swiftdoc", SwiftModuleDocFile, "swiftdoc", "")
5252
TYPE("swiftinterface", SwiftModuleInterfaceFile, "swiftinterface", "")
53+
TYPE("private-swiftinterface", PrivateSwiftModuleInterfaceFile, "private.swiftinterface", "")
5354
TYPE("swiftsourceinfo", SwiftSourceInfoFile, "swiftsourceinfo", "")
5455
TYPE("assembly", Assembly, "s", "")
5556
TYPE("raw-sil", RawSIL, "sil", "")

include/swift/Basic/SupplementaryOutputPaths.h

+7
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,13 @@ struct SupplementaryOutputPaths {
149149
/// \sa swift::emitSwiftInterface
150150
std::string ModuleInterfaceOutputPath;
151151

152+
/// The path to which we should emit a private module interface.
153+
///
154+
/// The private module interface contains all SPI decls and attributes.
155+
///
156+
/// \sa ModuleInterfaceOutputPath
157+
std::string PrivateModuleInterfaceOutputPath;
158+
152159
/// The path to a .c file where we should declare $ld$add symbols for those
153160
/// symbols moved to the current module.
154161
/// When symbols are moved to this module, this module declares them as HIDE

include/swift/Driver/Driver.h

+1
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ class Driver {
364364
void chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
365365
StringRef workingDirectory,
366366
llvm::SmallString<128> &buffer,
367+
file_types::ID fileType,
367368
CommandOutput *output) const;
368369

369370
void chooseRemappingOutputPath(Compilation &C, const TypeToPathMap *OutputMap,

include/swift/Frontend/Frontend.h

+1
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ class CompilerInvocation {
375375
/// mode, so return the ModuleInterfaceOutputPath when in that mode and
376376
/// fail an assert if not in that mode.
377377
std::string getModuleInterfaceOutputPathForWholeModule() const;
378+
std::string getPrivateModuleInterfaceOutputPathForWholeModule() const;
378379

379380
std::string getLdAddCFileOutputPathForWholeModule() const;
380381

include/swift/Frontend/FrontendInputsAndOutputs.h

+1
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,7 @@ class FrontendInputsAndOutputs {
239239
bool hasModuleDocOutputPath() const;
240240
bool hasModuleSourceInfoOutputPath() const;
241241
bool hasModuleInterfaceOutputPath() const;
242+
bool hasPrivateModuleInterfaceOutputPath() const;
242243
bool hasTBDPath() const;
243244

244245
bool hasDependencyTrackerPath() const;

include/swift/Frontend/ModuleInterfaceSupport.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ struct ModuleInterfaceOptions {
3939
/// generation time, re-applied to CompilerInvocation when reading
4040
/// back .swiftinterface and reconstructing .swiftmodule.
4141
std::string Flags;
42+
43+
// Print SPI decls and attributes.
44+
bool PrintSPIs = false;
4245
};
4346

4447
extern version::Version InterfaceFormatVersion;
@@ -50,7 +53,7 @@ llvm::Regex getSwiftInterfaceModuleFlagsRegex();
5053
/// source file to import this module, subject to options given by \p Opts.
5154
///
5255
/// Unlike a serialized module, the textual format generated by
53-
/// emitModuleInterface is intended to be stable across compiler versions while
56+
/// emitSwiftInterface is intended to be stable across compiler versions while
5457
/// still describing the full ABI of the module in question.
5558
///
5659
/// The initial plan for this format can be found at

include/swift/Option/Options.td

+6
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,12 @@ def emit_module_interface_path :
422422
ArgumentIsPath]>,
423423
MetaVarName<"<path>">, HelpText<"Output module interface file to <path>">;
424424

425+
def emit_private_module_interface_path :
426+
Separate<["-"], "emit-private-module-interface-path">,
427+
Flags<[FrontendOption, NoInteractiveOption, HelpHidden,
428+
DoesNotAffectIncrementalBuild, ArgumentIsPath]>,
429+
MetaVarName<"<path>">, HelpText<"Output private module interface file to <path>">;
430+
425431
def avoid_emit_module_source_info :
426432
Flag<["-"], "avoid-emit-module-source-info">,
427433
Flags<[NoInteractiveOption, DoesNotAffectIncrementalBuild]>,

lib/AST/ASTPrinter.cpp

+11-2
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,8 @@ static bool contributesToParentTypeStorage(const AbstractStorageDecl *ASD) {
100100
}
101101

102102
PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
103-
bool printFullConvention) {
103+
bool printFullConvention,
104+
bool printSPIs) {
104105
PrintOptions result;
105106
result.PrintLongAttrsOnSeparateLines = true;
106107
result.TypeDefinitions = true;
@@ -120,6 +121,7 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
120121
if (printFullConvention)
121122
result.PrintFunctionRepresentationAttrs =
122123
PrintOptions::FunctionRepresentationMode::Full;
124+
result.PrintSPIs = printSPIs;
123125

124126
// We should print __consuming, __owned, etc for the module interface file.
125127
result.SkipUnderscoredKeywords = false;
@@ -143,14 +145,21 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(bool preferTypeRepr,
143145
if (D->getAttrs().hasAttribute<ImplementationOnlyAttr>())
144146
return false;
145147

146-
// Skip anything that isn't 'public' or '@usableFromInline'.
148+
// Skip anything that isn't 'public' or '@usableFromInline',
149+
// or SPI if desired.
147150
if (auto *VD = dyn_cast<ValueDecl>(D)) {
148151
if (!isPublicOrUsableFromInline(VD)) {
149152
// We do want to print private stored properties, without their
150153
// original names present.
151154
if (auto *ASD = dyn_cast<AbstractStorageDecl>(VD))
152155
if (contributesToParentTypeStorage(ASD))
153156
return true;
157+
158+
// Always print SPI decls if `PrintSPIs`.
159+
if (options.PrintSPIs &&
160+
VD->getAttrs().hasAttribute<SPIAccessControlAttr>())
161+
return true;
162+
154163
return false;
155164
}
156165
}

lib/AST/Attr.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -778,8 +778,18 @@ bool DeclAttribute::printImpl(ASTPrinter &Printer, const PrintOptions &Options,
778778
Printer.printKeyword(getAttrName(), Options, "(set)");
779779
return true;
780780

781-
case DAK_SPIAccessControl:
781+
case DAK_SPIAccessControl: {
782+
if (!Options.PrintSPIs) return false;
783+
784+
auto spiAttr = static_cast<const SPIAccessControlAttr*>(this);
785+
interleave(spiAttr->getSPINames(),
786+
[&](Identifier spiName) {
787+
Printer.printAttrName(getAttrName(), true);
788+
Printer << "(" << spiName << ")";
789+
},
790+
[&] { Printer << " "; });
782791
return true;
792+
}
783793

784794
default:
785795
break;

lib/Basic/FileTypes.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ bool file_types::isTextual(ID Id) {
8080
case file_types::TY_ModuleTrace:
8181
case file_types::TY_OptRecord:
8282
case file_types::TY_SwiftModuleInterfaceFile:
83+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
8384
case file_types::TY_SwiftOverlayFile:
8485
return true;
8586
case file_types::TY_Image:
@@ -147,6 +148,7 @@ bool file_types::isAfterLLVM(ID Id) {
147148
case file_types::TY_ModuleTrace:
148149
case file_types::TY_OptRecord:
149150
case file_types::TY_SwiftModuleInterfaceFile:
151+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
150152
return false;
151153
case file_types::TY_INVALID:
152154
llvm_unreachable("Invalid type ID.");
@@ -179,6 +181,7 @@ bool file_types::isPartOfSwiftCompilation(ID Id) {
179181
case file_types::TY_SwiftModuleFile:
180182
case file_types::TY_SwiftModuleDocFile:
181183
case file_types::TY_SwiftModuleInterfaceFile:
184+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
182185
case file_types::TY_SwiftSourceInfoFile:
183186
case file_types::TY_SwiftCrossImportDir:
184187
case file_types::TY_SwiftOverlayFile:

lib/Driver/Driver.cpp

+19-10
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,8 @@ void Driver::buildOutputInfo(const ToolChain &TC, const DerivedArgList &Args,
16001600
} else if (Args.hasArg(options::OPT_emit_objc_header,
16011601
options::OPT_emit_objc_header_path,
16021602
options::OPT_emit_module_interface,
1603-
options::OPT_emit_module_interface_path) &&
1603+
options::OPT_emit_module_interface_path,
1604+
options::OPT_emit_private_module_interface_path) &&
16041605
OI.CompilerMode != OutputInfo::Mode::SingleCompile) {
16051606
// An option has been passed which requires whole-module knowledge, but we
16061607
// don't have that. Generate a module, but treat it as an intermediate
@@ -1942,6 +1943,7 @@ void Driver::buildActions(SmallVectorImpl<const Action *> &TopLevelActions,
19421943
case file_types::TY_ModuleTrace:
19431944
case file_types::TY_OptRecord:
19441945
case file_types::TY_SwiftModuleInterfaceFile:
1946+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
19451947
case file_types::TY_SwiftCrossImportDir:
19461948
case file_types::TY_SwiftOverlayFile:
19471949
// We could in theory handle assembly or LLVM input, but let's not.
@@ -2734,7 +2736,12 @@ Job *Driver::buildJobsForAction(Compilation &C, const JobAction *JA,
27342736

27352737
if (C.getArgs().hasArg(options::OPT_emit_module_interface,
27362738
options::OPT_emit_module_interface_path))
2737-
chooseModuleInterfacePath(C, JA, workingDirectory, Buf, Output.get());
2739+
chooseModuleInterfacePath(C, JA, workingDirectory, Buf,
2740+
file_types::TY_SwiftModuleInterfaceFile, Output.get());
2741+
2742+
if (C.getArgs().hasArg(options::OPT_emit_private_module_interface_path))
2743+
chooseModuleInterfacePath(C, JA, workingDirectory, Buf,
2744+
file_types::TY_PrivateSwiftModuleInterfaceFile, Output.get());
27382745

27392746
if (C.getArgs().hasArg(options::OPT_update_code) && isa<CompileJobAction>(JA))
27402747
chooseRemappingOutputPath(C, OutputMap, Output.get());
@@ -3065,9 +3072,10 @@ void Driver::chooseRemappingOutputPath(Compilation &C,
30653072
}
30663073

30673074
void Driver::chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
3068-
StringRef workingDirectory,
3069-
llvm::SmallString<128> &buffer,
3070-
CommandOutput *output) const {
3075+
StringRef workingDirectory,
3076+
llvm::SmallString<128> &buffer,
3077+
file_types::ID fileType,
3078+
CommandOutput *output) const {
30713079
switch (C.getOutputInfo().CompilerMode) {
30723080
case OutputInfo::Mode::StandardCompile:
30733081
case OutputInfo::Mode::BatchModeCompile:
@@ -3083,13 +3091,14 @@ void Driver::chooseModuleInterfacePath(Compilation &C, const JobAction *JA,
30833091
llvm_unreachable("these modes aren't usable with 'swiftc'");
30843092
}
30853093

3094+
auto pathOpt = fileType == file_types::TY_SwiftModuleInterfaceFile?
3095+
options::OPT_emit_module_interface_path:
3096+
options::OPT_emit_private_module_interface_path;
3097+
30863098
StringRef outputPath = *getOutputFilenameFromPathArgOrAsTopLevel(
3087-
C.getOutputInfo(), C.getArgs(),
3088-
options::OPT_emit_module_interface_path,
3089-
file_types::TY_SwiftModuleInterfaceFile,
3099+
C.getOutputInfo(), C.getArgs(), pathOpt, fileType,
30903100
/*TreatAsTopLevelOutput*/true, workingDirectory, buffer);
3091-
output->setAdditionalOutputForType(file_types::TY_SwiftModuleInterfaceFile,
3092-
outputPath);
3101+
output->setAdditionalOutputForType(fileType, outputPath);
30933102
}
30943103

30953104
void Driver::chooseSerializedDiagnosticsPath(Compilation &C,

lib/Driver/ToolChains.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ const char *ToolChain::JobContext::computeFrontendModeForCompile() const {
561561
case file_types::TY_TBD:
562562
case file_types::TY_OptRecord:
563563
case file_types::TY_SwiftModuleInterfaceFile:
564+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
564565
case file_types::TY_SwiftSourceInfoFile:
565566
case file_types::TY_SwiftCrossImportDir:
566567
case file_types::TY_SwiftOverlayFile:
@@ -679,6 +680,10 @@ void ToolChain::JobContext::addFrontendSupplementaryOutputArguments(
679680
file_types::ID::TY_SwiftModuleInterfaceFile,
680681
"-emit-module-interface-path");
681682

683+
addOutputsOfType(arguments, Output, Args,
684+
file_types::ID::TY_PrivateSwiftModuleInterfaceFile,
685+
"-emit-private-module-interface-path");
686+
682687
addOutputsOfType(arguments, Output, Args,
683688
file_types::TY_SerializedDiagnostics,
684689
"-serialize-diagnostics-path");
@@ -812,6 +817,7 @@ ToolChain::constructInvocation(const BackendJobAction &job,
812817
case file_types::TY_ModuleTrace:
813818
case file_types::TY_OptRecord:
814819
case file_types::TY_SwiftModuleInterfaceFile:
820+
case file_types::TY_PrivateSwiftModuleInterfaceFile:
815821
case file_types::TY_SwiftSourceInfoFile:
816822
case file_types::TY_SwiftCrossImportDir:
817823
case file_types::TY_SwiftOverlayFile:

lib/Frontend/ArgsToFrontendOutputsConverter.cpp

+12-2
Original file line numberDiff line numberDiff line change
@@ -300,14 +300,17 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
300300
auto TBD = getSupplementaryFilenamesFromArguments(options::OPT_emit_tbd_path);
301301
auto moduleInterfaceOutput = getSupplementaryFilenamesFromArguments(
302302
options::OPT_emit_module_interface_path);
303+
auto privateModuleInterfaceOutput = getSupplementaryFilenamesFromArguments(
304+
options::OPT_emit_private_module_interface_path);
303305
auto moduleSourceInfoOutput = getSupplementaryFilenamesFromArguments(
304306
options::OPT_emit_module_source_info_path);
305307
auto ldAddCFileOutput = getSupplementaryFilenamesFromArguments(
306308
options::OPT_emit_ldadd_cfile_path);
307309
if (!objCHeaderOutput || !moduleOutput || !moduleDocOutput ||
308310
!dependenciesFile || !referenceDependenciesFile ||
309311
!serializedDiagnostics || !fixItsOutput || !loadedModuleTrace || !TBD ||
310-
!moduleInterfaceOutput || !moduleSourceInfoOutput || !ldAddCFileOutput) {
312+
!moduleInterfaceOutput || !privateModuleInterfaceOutput ||
313+
!moduleSourceInfoOutput || !ldAddCFileOutput) {
311314
return None;
312315
}
313316
std::vector<SupplementaryOutputPaths> result;
@@ -328,6 +331,7 @@ SupplementaryOutputPathsComputer::getSupplementaryOutputPathsFromArguments()
328331
sop.LoadedModuleTracePath = (*loadedModuleTrace)[i];
329332
sop.TBDPath = (*TBD)[i];
330333
sop.ModuleInterfaceOutputPath = (*moduleInterfaceOutput)[i];
334+
sop.PrivateModuleInterfaceOutputPath = (*privateModuleInterfaceOutput)[i];
331335
sop.ModuleSourceInfoOutputPath = (*moduleSourceInfoOutput)[i];
332336
sop.LdAddCFilePath = (*ldAddCFileOutput)[i];
333337
result.push_back(sop);
@@ -422,6 +426,8 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
422426
// There is no non-path form of -emit-interface-path
423427
auto ModuleInterfaceOutputPath =
424428
pathsFromArguments.ModuleInterfaceOutputPath;
429+
auto PrivateModuleInterfaceOutputPath =
430+
pathsFromArguments.PrivateModuleInterfaceOutputPath;
425431

426432
ID emitModuleOption;
427433
std::string moduleExtension;
@@ -447,6 +453,7 @@ SupplementaryOutputPathsComputer::computeOutputPathsForOneInput(
447453
sop.LoadedModuleTracePath = loadedModuleTracePath;
448454
sop.TBDPath = tbdPath;
449455
sop.ModuleInterfaceOutputPath = ModuleInterfaceOutputPath;
456+
sop.PrivateModuleInterfaceOutputPath = PrivateModuleInterfaceOutputPath;
450457
sop.ModuleSourceInfoOutputPath = moduleSourceInfoOutputPath;
451458
sop.LdAddCFilePath = pathsFromArguments.LdAddCFilePath;
452459
return sop;
@@ -527,7 +534,9 @@ createFromTypeToPathMap(const TypeToPathMap *map) {
527534
{file_types::TY_ModuleTrace, paths.LoadedModuleTracePath},
528535
{file_types::TY_TBD, paths.TBDPath},
529536
{file_types::TY_SwiftModuleInterfaceFile,
530-
paths.ModuleInterfaceOutputPath}};
537+
paths.ModuleInterfaceOutputPath},
538+
{file_types::TY_PrivateSwiftModuleInterfaceFile,
539+
paths.PrivateModuleInterfaceOutputPath}};
531540
for (const std::pair<file_types::ID, std::string &> &typeAndString :
532541
typesAndStrings) {
533542
auto const out = map->find(typeAndString.first);
@@ -548,6 +557,7 @@ SupplementaryOutputPathsComputer::readSupplementaryOutputFileMap() const {
548557
options::OPT_serialize_diagnostics_path,
549558
options::OPT_emit_loaded_module_trace_path,
550559
options::OPT_emit_module_interface_path,
560+
options::OPT_emit_private_module_interface_path,
551561
options::OPT_emit_module_source_info_path,
552562
options::OPT_emit_tbd_path,
553563
options::OPT_emit_ldadd_cfile_path)) {

lib/Frontend/Frontend.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ CompilerInvocation::getModuleInterfaceOutputPathForWholeModule() const {
141141
.SupplementaryOutputs.ModuleInterfaceOutputPath;
142142
}
143143

144+
std::string
145+
CompilerInvocation::getPrivateModuleInterfaceOutputPathForWholeModule() const {
146+
assert(getFrontendOptions().InputsAndOutputs.isWholeModule() &&
147+
"PrivateModuleInterfaceOutputPath only makes sense when the whole "
148+
"module can be seen");
149+
return getPrimarySpecificPathsForAtMostOnePrimary()
150+
.SupplementaryOutputs.PrivateModuleInterfaceOutputPath;
151+
}
152+
144153
SerializationOptions CompilerInvocation::computeSerializationOptions(
145154
const SupplementaryOutputPaths &outs, bool moduleIsPublic) const {
146155
const FrontendOptions &opts = getFrontendOptions();

lib/Frontend/FrontendInputsAndOutputs.cpp

+6
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,12 @@ bool FrontendInputsAndOutputs::hasModuleInterfaceOutputPath() const {
460460
return outs.ModuleInterfaceOutputPath;
461461
});
462462
}
463+
bool FrontendInputsAndOutputs::hasPrivateModuleInterfaceOutputPath() const {
464+
return hasSupplementaryOutputPath(
465+
[](const SupplementaryOutputPaths &outs) -> const std::string & {
466+
return outs.PrivateModuleInterfaceOutputPath;
467+
});
468+
}
463469
bool FrontendInputsAndOutputs::hasTBDPath() const {
464470
return hasSupplementaryOutputPath(
465471
[](const SupplementaryOutputPaths &outs) -> const std::string & {

lib/Frontend/FrontendOptions.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ void FrontendOptions::forAllOutputPaths(
131131
const std::string *outputs[] = {&outs.ModuleOutputPath,
132132
&outs.ModuleDocOutputPath,
133133
&outs.ModuleInterfaceOutputPath,
134+
&outs.PrivateModuleInterfaceOutputPath,
134135
&outs.ObjCHeaderOutputPath,
135136
&outs.ModuleSourceInfoOutputPath};
136137
for (const std::string *next : outputs) {

0 commit comments

Comments
 (0)