Skip to content

Commit 4617828

Browse files
committed
[Bridging PCH] Pass .pch bridging headers to clang -import-pch
1 parent 7ac9b16 commit 4617828

File tree

4 files changed

+83
-14
lines changed

4 files changed

+83
-14
lines changed

include/swift/ClangImporter/ClangImporterOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class ClangImporterOptions {
3535
/// Equivalent to Clang's -mcpu=.
3636
std::string TargetCPU;
3737

38+
// The bridging header or PCH that will be imported.
39+
std::string BridgingHeader;
40+
3841
/// \see Mode
3942
enum class Modes {
4043
/// Set up Clang for importing modules into Swift and generating IR from

lib/ClangImporter/ClangImporter.cpp

Lines changed: 74 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "swift/Parse/Lexer.h"
3636
#include "swift/Parse/Parser.h"
3737
#include "swift/Config.h"
38+
#include "swift/Strings.h"
3839
#include "clang/AST/ASTContext.h"
3940
#include "clang/AST/Mangle.h"
4041
#include "clang/Basic/CharInfo.h"
@@ -123,9 +124,25 @@ namespace {
123124
}
124125
};
125126

127+
class PCHDeserializationCallbacks : public clang::ASTDeserializationListener {
128+
ClangImporter::Implementation &Impl;
129+
public:
130+
explicit PCHDeserializationCallbacks(ClangImporter::Implementation &impl)
131+
: Impl(impl) {}
132+
void ModuleImportRead(clang::serialization::SubmoduleID ID,
133+
clang::SourceLocation ImportLoc) {
134+
if (Impl.IsReadingBridgingPCH) {
135+
Impl.PCHImportedSubmodules.push_back(ID);
136+
}
137+
}
138+
};
139+
126140
class HeaderParsingASTConsumer : public clang::ASTConsumer {
127141
SmallVector<clang::DeclGroupRef, 4> DeclGroups;
142+
PCHDeserializationCallbacks PCHCallbacks;
128143
public:
144+
explicit HeaderParsingASTConsumer(ClangImporter::Implementation &impl)
145+
: PCHCallbacks(impl) {}
129146
void
130147
HandleTopLevelDeclInObjCContainer(clang::DeclGroupRef decls) override {
131148
DeclGroups.push_back(decls);
@@ -135,15 +152,40 @@ namespace {
135152
return DeclGroups;
136153
}
137154

155+
clang::ASTDeserializationListener *GetASTDeserializationListener() override {
156+
return &PCHCallbacks;
157+
}
158+
138159
void reset() {
139160
DeclGroups.clear();
140161
}
141162
};
142163

143164
class ParsingAction : public clang::ASTFrontendAction {
165+
ASTContext &Ctx;
166+
ClangImporter &Importer;
167+
ClangImporter::Implementation &Impl;
168+
public:
169+
explicit ParsingAction(ASTContext &ctx,
170+
ClangImporter &importer,
171+
ClangImporter::Implementation &impl)
172+
: Ctx(ctx), Importer(importer), Impl(impl) {}
144173
std::unique_ptr<clang::ASTConsumer>
145174
CreateASTConsumer(clang::CompilerInstance &CI, StringRef InFile) override {
146-
return llvm::make_unique<HeaderParsingASTConsumer>();
175+
return llvm::make_unique<HeaderParsingASTConsumer>(Impl);
176+
}
177+
bool BeginSourceFileAction(CompilerInstance &CI,
178+
StringRef Filename) override {
179+
// Prefer frameworks over plain headers.
180+
// We add search paths here instead of when building the initial invocation
181+
// so that (a) we use the same code as search paths for imported modules,
182+
// and (b) search paths are always added after -Xcc options.
183+
SearchPathOptions &searchPathOpts = Ctx.SearchPathOpts;
184+
for (auto path : searchPathOpts.FrameworkSearchPaths)
185+
Importer.addSearchPath(path, /*isFramework*/true);
186+
for (auto path : searchPathOpts.ImportSearchPaths)
187+
Importer.addSearchPath(path, /*isFramework*/false);
188+
return true;
147189
}
148190
};
149191

@@ -318,6 +360,14 @@ getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
318360

319361
auto languageVersion = ctx.LangOpts.EffectiveLanguageVersion;
320362

363+
if (llvm::sys::path::extension(importerOpts.BridgingHeader).endswith(
364+
PCH_EXTENSION)) {
365+
invocationArgStrs.insert(
366+
invocationArgStrs.end(),
367+
{ "-include-pch", importerOpts.BridgingHeader }
368+
);
369+
}
370+
321371
// Construct the invocation arguments for the current target.
322372
// Add target-independent options first.
323373
invocationArgStrs.insert(
@@ -622,6 +672,11 @@ ClangImporter::create(ASTContext &ctx,
622672
for (auto &argStr : invocationArgStrs)
623673
invocationArgs.push_back(argStr.c_str());
624674

675+
if (llvm::sys::path::extension(importerOpts.BridgingHeader).endswith(
676+
PCH_EXTENSION)) {
677+
importer->Impl.IsReadingBridgingPCH = true;
678+
}
679+
625680
// FIXME: These can't be controlled from the command line.
626681
llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOpts{
627682
new clang::DiagnosticOptions
@@ -681,7 +736,8 @@ ClangImporter::create(ASTContext &ctx,
681736
instance.setInvocation(&*invocation);
682737

683738
// Create the associated action.
684-
importer->Impl.Action.reset(new ParsingAction);
739+
importer->Impl.Action.reset(new ParsingAction(ctx, *importer,
740+
importer->Impl));
685741
auto *action = importer->Impl.Action.get();
686742

687743
// Execute the action. We effectively inline most of
@@ -736,16 +792,6 @@ ClangImporter::create(ASTContext &ctx,
736792
importer->Impl.SwiftContext, importer->Impl.platformAvailability,
737793
importer->Impl.getClangSema(), importer->Impl.InferImportAsMember));
738794

739-
// Prefer frameworks over plain headers.
740-
// We add search paths here instead of when building the initial invocation
741-
// so that (a) we use the same code as search paths for imported modules,
742-
// and (b) search paths are always added after -Xcc options.
743-
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
744-
for (auto path : searchPathOpts.FrameworkSearchPaths)
745-
importer->addSearchPath(path, /*isFramework*/true);
746-
for (auto path : searchPathOpts.ImportSearchPaths)
747-
importer->addSearchPath(path, /*isFramework*/false);
748-
749795
// FIXME: These decls are not being parsed correctly since (a) some of the
750796
// callbacks are still being added, and (b) the logic to parse them has
751797
// changed.
@@ -792,6 +838,8 @@ ClangImporter::create(ASTContext &ctx,
792838
new (ctx) ClangModuleUnit(*importedHeaderModule, *importer, nullptr);
793839
importedHeaderModule->addFile(*importer->Impl.ImportedHeaderUnit);
794840

841+
importer->Impl.IsReadingBridgingPCH = false;
842+
795843
return importer;
796844
}
797845

@@ -926,6 +974,19 @@ bool ClangImporter::importHeader(StringRef header, Module *adapter,
926974
bool ClangImporter::importBridgingHeader(StringRef header, Module *adapter,
927975
SourceLoc diagLoc,
928976
bool trackParsedSymbols) {
977+
if (llvm::sys::path::extension(header).endswith(PCH_EXTENSION)) {
978+
// We already imported this with -include-pch above, so we should have
979+
// collected a bunch of PCH-encoded module imports that we need to
980+
// replay to the HeaderImportCallbacks for processing.
981+
Impl.ImportedHeaderOwners.push_back(adapter);
982+
clang::ASTReader &R = *Impl.Instance->getModuleManager();
983+
HeaderImportCallbacks CB(*this, Impl);
984+
for (auto ID : Impl.PCHImportedSubmodules) {
985+
CB.handleImport(R.getSubmodule(ID));
986+
}
987+
Impl.PCHImportedSubmodules.clear();
988+
return false;
989+
}
929990
clang::FileManager &fileManager = Impl.Instance->getFileManager();
930991
const clang::FileEntry *headerFile = fileManager.getFile(header,
931992
/*OpenFile=*/true);
@@ -1273,6 +1334,7 @@ ClangImporter::Implementation::Implementation(ASTContext &ctx,
12731334
ImportForwardDeclarations(opts.ImportForwardDeclarations),
12741335
InferImportAsMember(opts.InferImportAsMember),
12751336
DisableSwiftBridgeAttr(opts.DisableSwiftBridgeAttr),
1337+
IsReadingBridgingPCH(false),
12761338
CurrentVersion(nameVersionFromOptions(ctx.LangOpts)),
12771339
BridgingHeaderLookupTable(new SwiftLookupTable(nullptr)),
12781340
platformAvailability(ctx.LangOpts),

lib/ClangImporter/ImporterImpl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,9 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
272272
const bool InferImportAsMember;
273273
const bool DisableSwiftBridgeAttr;
274274

275+
bool IsReadingBridgingPCH;
276+
llvm::SmallVector<clang::serialization::SubmoduleID, 2> PCHImportedSubmodules;
277+
275278
const Version CurrentVersion;
276279

277280
constexpr static const char * const moduleImportBufferName =

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -766,7 +766,7 @@ static bool ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
766766
Opts.ImportUnderlyingModule |= Args.hasArg(OPT_import_underlying_module);
767767
Opts.SILSerializeAll |= Args.hasArg(OPT_sil_serialize_all);
768768

769-
if (const Arg *A = Args.getLastArg(OPT_import_objc_header)) {
769+
if (const Arg *A = Args.getLastArgNoClaim(OPT_import_objc_header)) {
770770
Opts.ImplicitObjCHeaderPath = A->getValue();
771771
Opts.SerializeBridgingHeader |=
772772
!Opts.PrimaryInput && !Opts.ModuleOutputPath.empty();
@@ -993,7 +993,8 @@ static bool ParseClangImporterArgs(ClangImporterOptions &Opts,
993993

994994
if (Args.hasArg(OPT_embed_bitcode))
995995
Opts.Mode = ClangImporterOptions::Modes::EmbedBitcode;
996-
996+
if (auto *A = Args.getLastArg(OPT_import_objc_header))
997+
Opts.BridgingHeader = A->getValue();
997998
Opts.DisableSwiftBridgeAttr |= Args.hasArg(OPT_disable_swift_bridge_attr);
998999

9991000
Opts.DisableModulesValidateSystemHeaders |= Args.hasArg(OPT_disable_modules_validate_system_headers);

0 commit comments

Comments
 (0)