Skip to content

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

Merged

Conversation

graydon
Copy link
Contributor

@graydon graydon commented Nov 30, 2016

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:

  • Not sure the implementation strategy is really what anyone wanted
  • Probably fails to handle a bunch of invalid args / errors / invalid file situations
  • SourceKit and any other clients that want access to source info for the bridging header are neglected
  • No confirmation yet that it's any faster for the cases we're concerned about
  • Inadequate tests

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

@graydon
Copy link
Contributor Author

graydon commented Nov 30, 2016

@swift-ci please smoke test

@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from 88a64a3 to f390300 Compare November 30, 2016 01:31
@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from f390300 to da9dee8 Compare December 8, 2016 17:43
@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch 3 times, most recently from a43605f to ffc97d7 Compare December 22, 2016 06:49
@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from ffc97d7 to 1163e7f Compare January 4, 2017 21:07
Copy link
Contributor

@jrose-apple jrose-apple left a 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">,
Copy link
Contributor

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("-");
Copy link
Contributor

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)) {
Copy link
Contributor

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]>,
Copy link
Contributor

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.
Copy link
Contributor

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);
Copy link
Contributor

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
Copy link
Contributor

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",
Copy link
Contributor

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());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. Maybe we should just print the last path component of the header here.
  2. 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}}
Copy link
Contributor

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).

@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from 1163e7f to ef4a7bf Compare January 5, 2017 04:15
@graydon
Copy link
Contributor Author

graydon commented Jan 5, 2017

Updated to address all review comments. Much improved, thanks!

@graydon
Copy link
Contributor Author

graydon commented Jan 5, 2017

@swift-ci please smoke test

Copy link
Contributor

@jrose-apple jrose-apple left a 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);
Copy link
Contributor

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).

@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch 2 times, most recently from c072691 to 6666f98 Compare January 6, 2017 21:21
@@ -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'",
Copy link
Contributor

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
Copy link
Contributor

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.
Copy link
Contributor

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);
Copy link
Contributor

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;
Copy link
Contributor

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.

@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from 9ea6133 to 058eafc Compare January 11, 2017 19:31
@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch 2 times, most recently from 8c6d1ec to 9b2912e Compare January 13, 2017 00:58
@ematejska
Copy link
Contributor

@swift-ci test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - ef4a7bf04f7bd36b89872506221caa1b23b2bdd1
Test requested by - @ematejska

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - ef4a7bf04f7bd36b89872506221caa1b23b2bdd1
Test requested by - @ematejska

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.
@graydon graydon force-pushed the rdar-29016063-precompile-bridging-header branch from 9b2912e to 5f747ea Compare January 14, 2017 03:46
@graydon graydon changed the title (Don't merge yet) Rdar 29016063 precompile bridging header Rdar 29016063 precompile bridging header Jan 14, 2017
@graydon
Copy link
Contributor Author

graydon commented Jan 14, 2017

@swift-ci please test and merge

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants