Skip to content

Commit

Permalink
[BrdigingHeader] Auto bridging header chaining
Browse files Browse the repository at this point in the history
Add ability to automatically chaining the bridging headers discovered
from all dependencies module when doing swift caching build. This will
elminiate all implicit bridging header imports from the build and make
the bridging header importing behavior much more reliable, while keep
the compatibility at maximum.

For example, if the current module `A` depends on module `B` and `C` and
both `B` and `C` are binary modules that uses bridging header, when
building module A, dependency scanner will construct a new header that
chains three bridging headers together with the option to build a PCH
from it. This will make all importing errors more obvious while
improving the performance.

This is currently only enabled for swift caching since the new chained
header is written into CAS directly without the need to serialization.
  • Loading branch information
cachemeifyoucan committed Jan 14, 2025
1 parent e89abf8 commit c58fd27
Show file tree
Hide file tree
Showing 28 changed files with 475 additions and 161 deletions.
8 changes: 4 additions & 4 deletions include/swift/AST/ModuleDependencies.h
Original file line number Diff line number Diff line change
Expand Up @@ -786,11 +786,11 @@ class ModuleDependencyInfo {
setLinkLibraries(const ArrayRef<LinkLibrary> linkLibraries) {
storage->linkLibraries.assign(linkLibraries.begin(), linkLibraries.end());
}

const ArrayRef<std::string> getAuxiliaryFiles() const {
return storage->auxiliaryFiles;
}

void
setAuxiliaryFiles(const ArrayRef<std::string> auxiliaryFiles) {
storage->auxiliaryFiles.assign(auxiliaryFiles.begin(), auxiliaryFiles.end());
Expand Down Expand Up @@ -1196,11 +1196,11 @@ class ModuleDependenciesCache {
/// Query all dependencies
ModuleDependencyIDSetVector
getAllDependencies(const ModuleDependencyID &moduleID) const;

/// Query all Clang module dependencies.
ModuleDependencyIDSetVector
getClangDependencies(const ModuleDependencyID &moduleID) const;

/// Query all directly-imported Swift dependencies
llvm::ArrayRef<ModuleDependencyID>
getImportedSwiftDependencies(const ModuleDependencyID &moduleID) const;
Expand Down
16 changes: 11 additions & 5 deletions include/swift/Basic/LangOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ namespace swift {
/// Maximum number of typo corrections we are allowed to perform.
/// This is disabled by default until we can get typo-correction working within acceptable performance bounds.
unsigned TypoCorrectionLimit = 0;

/// Should access control be respected?
bool EnableAccessControl = true;

Expand Down Expand Up @@ -260,7 +260,7 @@ namespace swift {

/// Emit a remark when indexing a system module.
bool EnableIndexingSystemModuleRemarks = false;

/// Emit a remark on early exit in explicit interface build
bool EnableSkipExplicitInterfaceModuleBuildRemarks = false;

Expand Down Expand Up @@ -691,7 +691,7 @@ namespace swift {
void clearAllPlatformConditionValues() {
PlatformConditionValues.clear();
}

/// Returns the value for the given platform condition or an empty string.
StringRef getPlatformConditionValue(PlatformConditionKind Kind) const;

Expand Down Expand Up @@ -871,7 +871,7 @@ namespace swift {
/// 4.2 GHz Intel Core i7.
/// (It's arbitrary, but will keep the compiler from taking too much time.)
unsigned SwitchCheckingInvocationThreshold = 200000;

/// If true, the time it takes to type-check each function will be dumped
/// to llvm::errs().
bool DebugTimeFunctionBodies = false;
Expand Down Expand Up @@ -922,7 +922,7 @@ namespace swift {

/// Enable experimental operator designated types feature.
bool EnableOperatorDesignatedTypes = false;

/// Disable constraint system performance hacks.
bool DisableConstraintSolverPerformanceHacks = false;

Expand Down Expand Up @@ -967,6 +967,9 @@ namespace swift {
/// The bridging header or PCH that will be imported.
std::string BridgingHeader;

/// The bridging header PCH file.
std::string BridgingHeaderPCH;

/// When automatically generating a precompiled header from the bridging
/// header, place it in this directory.
std::string PrecompiledHeaderOutputDir;
Expand Down Expand Up @@ -1088,6 +1091,9 @@ namespace swift {
/// compilation source targets.
std::vector<std::string>
getReducedExtraArgsForSwiftModuleDependency() const;

/// Get PCH input path. Return empty string if there is no PCH input.
std::string getPCHInputPath() const;
};

} // end namespace swift
Expand Down
4 changes: 4 additions & 0 deletions include/swift/ClangImporter/ClangImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -506,6 +506,9 @@ class ClangImporter final : public ClangModuleLoader {
/// information will be augmented with information about the given
/// textual header inputs.
///
/// \param bridgingHeaderContent an optional buffer that pass the briding
/// heaer content to the scanner instead of relying on the filename.
///
/// \param clangScanningTool The clang dependency scanner.
///
/// \param cache The module dependencies cache to update, with information
Expand All @@ -514,6 +517,7 @@ class ClangImporter final : public ClangModuleLoader {
/// \returns \c true if an error occurred, \c false otherwise
bool getHeaderDependencies(
ModuleDependencyID moduleID,
std::optional<std::string> bridgingHeaderContent,
clang::tooling::dependencies::DependencyScanningTool &clangScanningTool,
ModuleDependenciesCache &cache,
ModuleDependencyIDSetVector &headerClangModuleDependencies,
Expand Down
10 changes: 6 additions & 4 deletions include/swift/DependencyScan/ModuleDependencyScanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ class ModuleDependencyScanner {
resolveAllClangModuleDependencies(ArrayRef<ModuleDependencyID> swiftModules,
ModuleDependenciesCache &cache,
ModuleDependencyIDSetVector &discoveredClangModules);
void
resolveHeaderDependencies(ArrayRef<ModuleDependencyID> swiftModules,
ModuleDependenciesCache &cache,
ModuleDependencyIDSetVector &discoveredHeaderDependencyClangModules);
void resolveHeaderDependencies(
const ModuleDependencyID &rootModuleID,
ArrayRef<ModuleDependencyID> swiftModules, ModuleDependenciesCache &cache,
ModuleDependencyIDSetVector &discoveredHeaderDependencyClangModules);
void
resolveSwiftOverlayDependencies(ArrayRef<ModuleDependencyID> swiftModules,
ModuleDependenciesCache &cache,
Expand Down Expand Up @@ -171,6 +171,8 @@ class ModuleDependencyScanner {
std::mutex WorkersLock;
/// Count of filesystem queries performed
std::atomic<unsigned> NumLookups = 0;
/// If using auto bridging header chaining.
bool BridgingHeaderChaining = false;
};

} // namespace swift
3 changes: 3 additions & 0 deletions include/swift/Frontend/FrontendOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ class FrontendOptions {
/// An Objective-C header to import and make implicitly visible.
std::string ImplicitObjCHeaderPath;

/// An Objective-C pch to import and make implicitly visible.
std::string ImplicitObjCPCHPath;

/// The map of aliases and real names of imported or referenced modules.
llvm::StringMap<StringRef> ModuleAliasMap;

Expand Down
11 changes: 7 additions & 4 deletions include/swift/Option/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,12 @@ def verify_incremental_dependencies :
Flag<["-"], "verify-incremental-dependencies">,
Flags<[FrontendOption, HelpHidden]>,
HelpText<"Enable the dependency verifier for each frontend job">;

def strict_implicit_module_context :
Flag<["-"], "strict-implicit-module-context">,
Flags<[FrontendOption, HelpHidden]>,
HelpText<"Enable the strict forwarding of compilation context to downstream implicit module dependencies">;

def no_strict_implicit_module_context :
Flag<["-"], "no-strict-implicit-module-context">,
Flags<[FrontendOption, HelpHidden]>,
Expand Down Expand Up @@ -315,7 +315,7 @@ def tools_directory : Separate<["-"], "tools-directory">,

def D : JoinedOrSeparate<["-"], "D">, Flags<[FrontendOption]>,
HelpText<"Marks a conditional compilation flag as true">;

def e : Separate<["-"], "e">, Flags<[NewDriverOnlyOption]>,
HelpText<"Executes a line of code provided on the command line">;

Expand Down Expand Up @@ -353,6 +353,9 @@ def import_objc_header : Separate<["-"], "import-objc-header">,
def import_bridging_header : Separate<["-"], "import-bridging-header">,
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
Alias<import_objc_header>;
def import_pch : Separate<["-"], "import-pch">,
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
HelpText<"Import bridging header PCH file">;

def pch_output_dir: Separate<["-"], "pch-output-dir">,
Flags<[FrontendOption, HelpHidden, ArgumentIsPath]>,
Expand Down Expand Up @@ -2117,7 +2120,7 @@ def external_plugin_path : Separate<["-"], "external-plugin-path">, Group<plugin
Flags<[FrontendOption, ArgumentIsPath, SwiftSymbolGraphExtractOption, SwiftAPIDigesterOption]>,
HelpText<"Add directory to the plugin search path with a plugin server executable">,
MetaVarName<"<path>#<plugin-server-path>">;

def cas_backend: Flag<["-"], "cas-backend">,
Flags<[FrontendOption, NoDriverOption]>,
HelpText<"Enable using CASBackend for object file output">;
Expand Down
7 changes: 6 additions & 1 deletion include/swift/Serialization/SerializedModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ class SerializedASTFile final : public LoadedFile {
getFilenameForPrivateDecl(const Decl *decl) const override;

virtual TypeDecl *lookupLocalType(StringRef MangledName) const override;

virtual OpaqueTypeDecl *
lookupOpaqueResultType(StringRef MangledName) override;

Expand Down Expand Up @@ -577,6 +577,11 @@ bool extractCompilerFlagsFromInterface(

/// Extract the user module version number from an interface file.
llvm::VersionTuple extractUserModuleVersionFromInterface(StringRef moduleInterfacePath);

/// Extract embedded bridging header from binary module.
std::string
extractEmbeddedBridgingHeaderContent(std::unique_ptr<llvm::MemoryBuffer> file,
ASTContext &Context);
} // end namespace swift

#endif
4 changes: 2 additions & 2 deletions lib/AST/ModuleDependencies.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -770,14 +770,14 @@ ModuleDependenciesCache::findDependency(
}
return std::nullopt;
}

assert(kind.has_value() && "Expected dependencies kind for lookup.");
std::optional<const ModuleDependencyInfo *> optionalDep = std::nullopt;
const auto &map = getDependenciesMap(kind.value());
auto known = map.find(moduleName);
if (known != map.end())
optionalDep = &(known->second);

// During a scan, only produce the cached source module info for the current
// module under scan.
if (optionalDep.has_value()) {
Expand Down
12 changes: 12 additions & 0 deletions lib/Basic/LangOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "swift/Basic/LangOptions.h"
#include "swift/AST/DiagnosticEngine.h"
#include "swift/Basic/Feature.h"
#include "swift/Basic/FileTypes.h"
#include "swift/Basic/Platform.h"
#include "swift/Basic/PlaygroundOption.h"
#include "swift/Basic/Range.h"
Expand Down Expand Up @@ -814,3 +815,14 @@ ClangImporterOptions::getReducedExtraArgsForSwiftModuleDependency() const {

return filtered_args;
}

std::string ClangImporterOptions::getPCHInputPath() const {
if (!BridgingHeaderPCH.empty())
return BridgingHeaderPCH;

if (llvm::sys::path::extension(BridgingHeader)
.ends_with(file_types::getExtension(file_types::TY_PCH)))
return BridgingHeader;

return {};
}
29 changes: 15 additions & 14 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -476,11 +476,10 @@ void importer::getNormalInvocationArguments(
ClangImporterOptions &importerOpts = ctx.ClangImporterOpts;
auto languageVersion = ctx.LangOpts.EffectiveLanguageVersion;

if (isPCHFilenameExtension(importerOpts.BridgingHeader)) {
invocationArgStrs.insert(invocationArgStrs.end(), {
"-include-pch", importerOpts.BridgingHeader
});
}
auto bridgingPCH = importerOpts.getPCHInputPath();
if (!bridgingPCH.empty())
invocationArgStrs.insert(invocationArgStrs.end(),
{"-include-pch", bridgingPCH});

// If there are no shims in the resource dir, add a search path in the SDK.
SmallString<128> shimsPath(searchPathOpts.RuntimeResourcePath);
Expand Down Expand Up @@ -1066,9 +1065,10 @@ void ClangImporter::addClangInvovcationDependencies(
std::optional<std::string>
ClangImporter::getPCHFilename(const ClangImporterOptions &ImporterOptions,
StringRef SwiftPCHHash, bool &isExplicit) {
if (isPCHFilenameExtension(ImporterOptions.BridgingHeader)) {
auto bridgingPCH = ImporterOptions.getPCHInputPath();
if (!bridgingPCH.empty()) {
isExplicit = true;
return ImporterOptions.BridgingHeader;
return bridgingPCH;
}
isExplicit = false;

Expand Down Expand Up @@ -1302,16 +1302,17 @@ ClangImporter::create(ASTContext &ctx,
new ClangImporter(ctx, tracker, dwarfImporterDelegate)};
auto &importerOpts = ctx.ClangImporterOpts;

if (isPCHFilenameExtension(importerOpts.BridgingHeader)) {
importer->Impl.setSinglePCHImport(importerOpts.BridgingHeader);
auto bridgingPCH = importerOpts.getPCHInputPath();
if (!bridgingPCH.empty()) {
importer->Impl.setSinglePCHImport(bridgingPCH);
importer->Impl.IsReadingBridgingPCH = true;
if (tracker) {
// Currently ignoring dependency on bridging .pch files because they are
// temporaries; if and when they are no longer temporaries, this condition
// should be removed.
auto &coll = static_cast<ClangImporterDependencyCollector &>(
*tracker->getClangCollector());
coll.excludePath(importerOpts.BridgingHeader);
coll.excludePath(bridgingPCH);
}
}

Expand Down Expand Up @@ -6328,7 +6329,7 @@ static bool isImplValid(ExtensionDecl *ext) {
// This is diagnosed in AttributeChecker::visitObjCImplementationAttr().
if (!attr->isEarlyAdopter() && !attr->CategoryName.empty())
return false;

return !attr->isCategoryNameInvalid();
}

Expand Down Expand Up @@ -7928,7 +7929,7 @@ CxxRecordSemantics::evaluate(Evaluator &evaluator,
if (hasIteratorAPIAttr(cxxDecl) || isIterator(cxxDecl)) {
return CxxRecordSemanticsKind::Iterator;
}

if (hasCopyTypeOperations(cxxDecl)) {
return CxxRecordSemanticsKind::Owned;
}
Expand Down Expand Up @@ -7985,7 +7986,7 @@ bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) {

if (hasCustomCopyOrMoveConstructor(decl) || hasOwnedValueAttr(decl))
return true;

auto checkType = [](clang::QualType t) {
if (auto recordType = dyn_cast<clang::RecordType>(t.getCanonicalType())) {
if (auto cxxRecord =
Expand All @@ -8006,7 +8007,7 @@ bool anySubobjectsSelfContained(const clang::CXXRecordDecl *decl) {
if (checkType(base.getType()))
return true;
}

return false;
}

Expand Down
Loading

0 comments on commit c58fd27

Please sign in to comment.