-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Rdar 29016063 precompile bridging header #5977
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
Rdar 29016063 precompile bridging header #5977
Conversation
@swift-ci please smoke test |
88a64a3
to
f390300
Compare
f390300
to
da9dee8
Compare
a43605f
to
ffc97d7
Compare
ffc97d7
to
1163e7f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many comments but overall it all makes sense. Nice work, Graydon!
@@ -417,6 +417,10 @@ def emit_sib : Flag<["-"], "emit-sib">, | |||
def emit_sibgen : Flag<["-"], "emit-sibgen">, | |||
HelpText<"Emit serialized AST + raw SIL file(s)">, ModeOpt, | |||
Flags<[FrontendOption, NoInteractiveOption, DoesNotAffectIncrementalBuild]>; | |||
def emit_pch : Flag<["-"], "emit-pch">, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need to bother making this a driver option at all. It's easy enough to test invoking the frontend directly, and no outside tool should need to rely on doing it manually.
@@ -482,6 +484,14 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, | |||
Opts.setSingleOutputFilename("-"); | |||
break; | |||
|
|||
case FrontendOptions::EmitPCH: { | |||
if (Opts.OutputFilenames.empty()) | |||
Opts.setSingleOutputFilename("-"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PCH is a non-textual format, so it shouldn't default to stdout.
@@ -311,7 +311,13 @@ void CompilerInstance::performSema() { | |||
Module *importedHeaderModule = nullptr; | |||
StringRef implicitHeaderPath = options.ImplicitObjCHeaderPath; | |||
if (!implicitHeaderPath.empty()) { | |||
if (!clangImporter->importBridgingHeader(implicitHeaderPath, MainModule)) { | |||
bool failed = false; | |||
if (llvm::sys::path::extension(implicitHeaderPath).endswith(PCH_EXTENSION)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I would sink this logic inside importBridgingHeader
. The less the frontend knows about gory Clang details the better.
@@ -237,6 +237,10 @@ def disable_swift_bridge_attr : Flag<["-"], "disable-swift-bridge-attr">, | |||
Flags<[FrontendOption, HelpHidden]>, | |||
HelpText<"Disable using the swift bridge attribute">; | |||
|
|||
def disable_bridging_pch : Flag<["-"], "disable-bridging-pch">, | |||
Flags<[FrontendOption, HelpHidden]>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a FrontendOption. :-)
// JobActions so they don't try to free it. That in turn means we need | ||
// to transfer ownership of all the JobActions' existing inputs to the | ||
// Actions array, since the JobActions either own or don't own _all_ | ||
// of their inputs. Ownership can't vary input-by-input. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you tag this with a FIXME? I want to go back and clear up the Action ownership muck at some point.
A->getValue()) { | ||
Arg Tmp(A->getOption(), A->getSpelling(), A->getIndex(), | ||
IJ->getOutput().getPrimaryOutputFilename().c_str(), A); | ||
Tmp.render(context.Args, Arguments); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just doing this manually is fine.
Arguments.push_back("-import-objc-header");
Arguments.push_Back(IJ->getOutput().getPrimaryOutputFilename().c_str());
// REQUIRES: objc_interop | ||
// RUN: rm -rf %t && mkdir -p %t/tmp | ||
|
||
// First test the explicit frontend-based bridging PCH generation and use works |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add tests under test/Driver/ using -driver-print-actions
and -driver-print-jobs
, so that we can see the individual steps being generated properly.
@@ -79,6 +79,11 @@ WARNING(unresolvable_clang_decl,none, | |||
"imported declaration '%0' could not be mapped to '%1'", | |||
(StringRef, StringRef)) | |||
|
|||
WARNING(implicit_bridging_header_imported_from_module,none, | |||
"implicit import of bridging header '%0' via module '%1' " | |||
"is deprecated, will be removed in a later version of Swift", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Grammar nitpick: let's go with and
instead of the comma.
if (implicitImport && !allParsedDecls.empty()) { | ||
SwiftContext.Diags.diagnose( | ||
diagLoc, diag::implicit_bridging_header_imported_from_module, | ||
headerName, adapter->getNameStr()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Maybe we should just print the last path component of the header here.
- Instead of using
getNameStr()
, you could change the diagnostic to take an Identifier.
@@ -14,7 +14,7 @@ | |||
|
|||
// XFAIL: linux | |||
|
|||
import MixedWithHeader | |||
import MixedWithHeader // expected-warning {{implicit import of bridging header}} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please check the entire diagnostic in at least one of these tests, even if you have to use FileCheck to do it (to avoid embedding a full path).
1163e7f
to
ef4a7bf
Compare
Updated to address all review comments. Much improved, thanks! |
@swift-ci please smoke test |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, Graydon. Nice work!
for (auto *IJ : context.Inputs) { | ||
if (!IJ->getOutput().getAnyOutputForType(types::TY_PCH).empty()) { | ||
Arguments.push_back("-import-objc-header"); | ||
addInputsOfType(Arguments, context.Inputs, types::TY_PCH); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does bug me a little that we end up searching the input list twice here, but I guess it will usually be short. You could also have addInputsOfType
return a boolean or a count, though (and explicitly get the value out of the argument in the non-PCH case, rather than forwarding with AddLastArg
).
c072691
to
6666f98
Compare
@@ -53,6 +53,9 @@ ERROR(bridging_header_error,Fatal, | |||
WARNING(could_not_rewrite_bridging_header,none, | |||
"failed to serialize bridging header; " | |||
"target may not be debuggable outside of its original project", ()) | |||
ERROR(bridging_header_pch_error,Fatal, | |||
"failed to emit PCH file '%0' for bridging header '%1'", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to write "precompiled header" here, instead of "PCH"? There's a chance end users could see this error, and they might not be familiar with the acronym.
@@ -218,6 +223,14 @@ class ClangImporter final : public ClangModuleLoader { | |||
std::string getBridgingHeaderContents(StringRef headerPath, off_t &fileSize, | |||
time_t &fileModTime); | |||
|
|||
/// Makes a temporary replica of the ClangImporter's CompilerInstance, reads | |||
/// an Objective-C header file into the replica and emits a PCH file of its |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These docblocks are fantastic!
nit-pick: Sorry to harp on about acronyms, but I noticed "PCH" isn't in docs/Lexicon.rst
, either. I think that some Swift contributors might not be immediately familiar with the concept of a precompiled header. Since this pull request is the first use of "PCH" in a docblock in this codebase, I'd suggest adding the acronym to the Lexicon as well.
if (llvm::sys::path::extension(importerOpts.BridgingHeader).endswith( | ||
PCH_EXTENSION)) | ||
clangPP.setPredefines(""); | ||
// FIXME: This is missing implicit includes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this FIXME still true? This is about there being -include
options passed via -Xcc
and the importer not exposing the contents.
// processing. | ||
for (auto CM : Impl.PCHReadModules) { | ||
auto L = nextSyntheticImportLocation(); | ||
getClangPreprocessor().makeModuleVisible(CM, L); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't it already be visible thanks to the PCH? You may be able to get away with just calling finishLoadingClangModule
.
@@ -272,6 +272,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation | |||
const bool InferImportAsMember; | |||
const bool DisableSwiftBridgeAttr; | |||
|
|||
bool IsReadingBridgingPCH; | |||
llvm::DenseSet<clang::Module *> PCHReadModules; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use a SetVector or even a regular SmallVector here. Order probably matters for determinism in diagnostics, if not normal name lookup.
9ea6133
to
058eafc
Compare
8c6d1ec
to
9b2912e
Compare
@swift-ci test |
Build failed |
Build failed |
We're trying to get rid of implicit bridging-header imports, as a feature. These are IMPORTED_HEADER blocks left in modules built with bridging headers, that trigger re-importing the bridging header into any client that imports the module. As a half-way measure to deprecating them, we add a warning here that triggers when an implicit bridging-header import occurs that is _not_ suppressed as redundant by clang.
This happens fairly regularly in unit testing scenarios.
9b2912e
to
5f747ea
Compare
@swift-ci please test and merge |
This is a preliminary implementation of PCH-for-bridging-headers; the point is to accelerate non-WMO builds with large bridging headers, which spend a nontrivial amount of time re-importing the header for each frontend job.
Caveats:
Still, I'm posting for early feedback since it's past the point of "working" and seems tidy / non-crashy enough to play with / evaluate.
rdar://problem/29016063