Skip to content

Commit 57cc0c1

Browse files
authored
Merge pull request #65957 from artemcm/59SeparateClangTargetHandlingForIRGen
[5.9 🍒][Explicit Module Builds] Ensure IRGen uses Swift compiler's target triple when '-clang-target' is set.
2 parents 1de0c05 + 7a7339e commit 57cc0c1

File tree

5 files changed

+111
-26
lines changed

5 files changed

+111
-26
lines changed

include/swift/AST/ClangModuleLoader.h

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,21 @@ class ClangModuleLoader : public ModuleLoader {
124124
using ModuleLoader::ModuleLoader;
125125

126126
public:
127-
virtual clang::TargetInfo &getTargetInfo() const = 0;
127+
/// This module loader's Clang instance may be configured with a different
128+
/// (higher) OS version than the compilation target itself in order to be able
129+
/// to load pre-compiled Clang modules that are aligned with the broader SDK,
130+
/// and match the SDK deployment target against which Swift modules are also
131+
/// built.
132+
///
133+
/// In this case, we must use the Swift compiler's OS version triple when
134+
/// performing codegen, and the importer's Clang instance OS version triple
135+
/// during module loading. `getModuleAvailabilityTarget` is for module-loading
136+
/// clients only, and uses the latter.
137+
///
138+
/// (The implementing `ClangImporter` class maintains separate Target info
139+
/// for use by IRGen/CodeGen clients)
140+
virtual clang::TargetInfo &getModuleAvailabilityTarget() const = 0;
141+
128142
virtual clang::ASTContext &getClangASTContext() const = 0;
129143
virtual clang::Preprocessor &getClangPreprocessor() const = 0;
130144
virtual clang::Sema &getClangSema() const = 0;

include/swift/ClangImporter/ClangImporter.h

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ namespace clang {
4949
class VisibleDeclConsumer;
5050
class DeclarationName;
5151
class CompilerInvocation;
52+
class TargetOptions;
5253
namespace tooling {
5354
namespace dependencies {
5455
struct ModuleDeps;
@@ -172,7 +173,7 @@ class ClangImporter final : public ClangModuleLoader {
172173
DWARFImporterDelegate *dwarfImporterDelegate = nullptr);
173174

174175
static std::vector<std::string>
175-
getClangArguments(ASTContext &ctx);
176+
getClangArguments(ASTContext &ctx, bool ignoreClangTarget = false);
176177

177178
static std::unique_ptr<clang::CompilerInvocation>
178179
createClangInvocation(ClangImporter *importer,
@@ -445,13 +446,33 @@ class ClangImporter final : public ClangModuleLoader {
445446
StringRef moduleName,
446447
ModuleDependencyKind moduleKind,
447448
ModuleDependenciesCache &cache);
448-
449-
clang::TargetInfo &getTargetInfo() const override;
449+
clang::TargetInfo &getModuleAvailabilityTarget() const override;
450450
clang::ASTContext &getClangASTContext() const override;
451451
clang::Preprocessor &getClangPreprocessor() const override;
452452
clang::Sema &getClangSema() const override;
453453
const clang::CompilerInstance &getClangInstance() const override;
454-
clang::CodeGenOptions &getClangCodeGenOpts() const;
454+
455+
/// ClangImporter's Clang instance may be configured with a different
456+
/// (higher) OS version than the compilation target itself in order to be able
457+
/// to load pre-compiled Clang modules that are aligned with the broader SDK,
458+
/// and match the SDK deployment target against which Swift modules are also
459+
/// built.
460+
///
461+
/// In this case, we must use the Swift compiler's OS version triple when
462+
/// performing codegen, and the importer's Clang instance OS version triple
463+
/// during module loading.
464+
///
465+
/// `ClangImporter`'s `Implementation` keeps track of a distinct `TargetInfo`
466+
/// and `CodeGenOpts` containers that are meant to be used by clients in
467+
/// IRGen. When a separate `-clang-target` is not set, they are defined to be
468+
/// copies of the `ClangImporter`'s built-in module-loading Clang instance.
469+
/// When `-clang-target` is set, they are configured with the Swift
470+
/// compilation's target triple and OS version (but otherwise identical)
471+
/// instead. To distinguish IRGen clients from module loading clients,
472+
/// `getModuleAvailabilityTarget` should be used instead by module-loading
473+
/// clients.
474+
clang::TargetInfo &getTargetInfo() const;
475+
clang::CodeGenOptions &getCodeGenOpts() const;
455476

456477
std::string getClangModuleHash() const;
457478

lib/ClangImporter/ClangImporter.cpp

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -716,11 +716,11 @@ getEmbedBitcodeInvocationArguments(std::vector<std::string> &invocationArgStrs,
716716
void
717717
importer::addCommonInvocationArguments(
718718
std::vector<std::string> &invocationArgStrs,
719-
ASTContext &ctx) {
719+
ASTContext &ctx, bool ignoreClangTarget) {
720720
using ImporterImpl = ClangImporter::Implementation;
721721
llvm::Triple triple = ctx.LangOpts.Target;
722722
// Use clang specific target triple if given.
723-
if (ctx.LangOpts.ClangTarget.has_value()) {
723+
if (ctx.LangOpts.ClangTarget.has_value() && !ignoreClangTarget) {
724724
triple = ctx.LangOpts.ClangTarget.value();
725725
}
726726
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
@@ -970,7 +970,7 @@ ClangImporter::getOrCreatePCH(const ClangImporterOptions &ImporterOptions,
970970
}
971971

972972
std::vector<std::string>
973-
ClangImporter::getClangArguments(ASTContext &ctx) {
973+
ClangImporter::getClangArguments(ASTContext &ctx, bool ignoreClangTarget) {
974974
std::vector<std::string> invocationArgStrs;
975975
// Clang expects this to be like an actual command line. So we need to pass in
976976
// "clang" for argv[0]
@@ -991,7 +991,7 @@ ClangImporter::getClangArguments(ASTContext &ctx) {
991991
getEmbedBitcodeInvocationArguments(invocationArgStrs, ctx);
992992
break;
993993
}
994-
addCommonInvocationArguments(invocationArgStrs, ctx);
994+
addCommonInvocationArguments(invocationArgStrs, ctx, ignoreClangTarget);
995995
return invocationArgStrs;
996996
}
997997

@@ -1094,15 +1094,6 @@ ClangImporter::create(ASTContext &ctx,
10941094
std::unique_ptr<ClangImporter> importer{
10951095
new ClangImporter(ctx, tracker, dwarfImporterDelegate)};
10961096
auto &importerOpts = ctx.ClangImporterOpts;
1097-
importer->Impl.ClangArgs = getClangArguments(ctx);
1098-
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
1099-
if (importerOpts.DumpClangDiagnostics) {
1100-
llvm::errs() << "'";
1101-
llvm::interleave(
1102-
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
1103-
[] { llvm::errs() << "' '"; });
1104-
llvm::errs() << "'\n";
1105-
}
11061097

11071098
if (isPCHFilenameExtension(importerOpts.BridgingHeader)) {
11081099
importer->Impl.setSinglePCHImport(importerOpts.BridgingHeader);
@@ -1142,6 +1133,15 @@ ClangImporter::create(ASTContext &ctx,
11421133

11431134
// Create a new Clang compiler invocation.
11441135
{
1136+
importer->Impl.ClangArgs = getClangArguments(ctx);
1137+
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
1138+
if (importerOpts.DumpClangDiagnostics) {
1139+
llvm::errs() << "'";
1140+
llvm::interleave(
1141+
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
1142+
[] { llvm::errs() << "' '"; });
1143+
llvm::errs() << "'\n";
1144+
}
11451145
importer->Impl.Invocation = createClangInvocation(
11461146
importer.get(), importerOpts, VFS, invocationArgStrs);
11471147
if (!importer->Impl.Invocation)
@@ -1217,6 +1217,27 @@ ClangImporter::create(ASTContext &ctx,
12171217
clang::SourceLocation());
12181218
clangDiags.setFatalsAsError(ctx.Diags.getShowDiagnosticsAfterFatalError());
12191219

1220+
// Use Clang to configure/save options for Swift IRGen/CodeGen
1221+
if (ctx.LangOpts.ClangTarget.has_value()) {
1222+
// If '-clang-target' is set, create a mock invocation with the Swift triple
1223+
// to configure CodeGen and Target options for Swift compilation.
1224+
auto swiftTargetClangArgs = getClangArguments(ctx, true);
1225+
ArrayRef<std::string> invocationArgStrs = swiftTargetClangArgs;
1226+
auto swiftTargetClangInvocation = createClangInvocation(
1227+
importer.get(), importerOpts, VFS, invocationArgStrs);
1228+
if (!swiftTargetClangInvocation)
1229+
return nullptr;
1230+
importer->Impl.setSwiftTargetInfo(clang::TargetInfo::CreateTargetInfo(
1231+
clangDiags, swiftTargetClangInvocation->TargetOpts));
1232+
importer->Impl.setSwiftCodeGenOptions(new clang::CodeGenOptions(
1233+
swiftTargetClangInvocation->getCodeGenOpts()));
1234+
} else {
1235+
// Just use the existing Invocation's directly
1236+
importer->Impl.setSwiftTargetInfo(clang::TargetInfo::CreateTargetInfo(
1237+
clangDiags, importer->Impl.Invocation->TargetOpts));
1238+
importer->Impl.setSwiftCodeGenOptions(
1239+
new clang::CodeGenOptions(importer->Impl.Invocation->getCodeGenOpts()));
1240+
}
12201241

12211242
// Create the associated action.
12221243
importer->Impl.Action.reset(new ParsingAction(ctx, *importer,
@@ -1875,7 +1896,7 @@ bool ClangImporter::canImportModule(ImportPath::Module modulePath,
18751896
clang::Module *m;
18761897
auto &ctx = Impl.getClangASTContext();
18771898
auto &lo = ctx.getLangOpts();
1878-
auto &ti = getTargetInfo();
1899+
auto &ti = getModuleAvailabilityTarget();
18791900

18801901
auto available = clangModule->isAvailable(lo, ti, r, mh, m);
18811902
if (!available)
@@ -3683,10 +3704,14 @@ StringRef ClangModuleUnit::getLoadedFilename() const {
36833704
return StringRef();
36843705
}
36853706

3686-
clang::TargetInfo &ClangImporter::getTargetInfo() const {
3707+
clang::TargetInfo &ClangImporter::getModuleAvailabilityTarget() const {
36873708
return Impl.Instance->getTarget();
36883709
}
36893710

3711+
clang::TargetInfo &ClangImporter::getTargetInfo() const {
3712+
return *Impl.getSwiftTargetInfo();
3713+
}
3714+
36903715
clang::ASTContext &ClangImporter::getClangASTContext() const {
36913716
return Impl.getClangASTContext();
36923717
}
@@ -3716,8 +3741,8 @@ clang::Sema &ClangImporter::getClangSema() const {
37163741
return Impl.getClangSema();
37173742
}
37183743

3719-
clang::CodeGenOptions &ClangImporter::getClangCodeGenOpts() const {
3720-
return Impl.getClangCodeGenOpts();
3744+
clang::CodeGenOptions &ClangImporter::getCodeGenOpts() const {
3745+
return *Impl.getSwiftCodeGenOptions();
37213746
}
37223747

37233748
std::string ClangImporter::getClangModuleHash() const {

lib/ClangImporter/ImporterImpl.h

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "clang/AST/DeclVisitor.h"
4040
#include "clang/AST/RecursiveASTVisitor.h"
4141
#include "clang/Basic/IdentifierTable.h"
42+
#include "clang/Basic/TargetInfo.h"
4243
#include "clang/Frontend/CompilerInstance.h"
4344
#include "clang/Serialization/ModuleFileExtension.h"
4445
#include "llvm/ADT/APSInt.h"
@@ -588,6 +589,29 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
588589
return Instance.get();
589590
}
590591

592+
private:
593+
/// The Importer may be configured to load modules of a different OS Version
594+
/// than the underlying Swift compilation. This is the `TargetOptions`
595+
/// corresponding to the instantiating Swift compilation's triple. These are
596+
/// to be used by all IRGen/CodeGen clients of `ClangImporter`.
597+
std::unique_ptr<clang::TargetInfo> CodeGenTargetInfo;
598+
std::unique_ptr<clang::CodeGenOptions> CodeGenOpts;
599+
600+
public:
601+
void setSwiftTargetInfo(clang::TargetInfo *SwiftTargetInfo) {
602+
CodeGenTargetInfo.reset(SwiftTargetInfo);
603+
}
604+
clang::TargetInfo *getSwiftTargetInfo() const {
605+
return CodeGenTargetInfo.get();
606+
}
607+
608+
void setSwiftCodeGenOptions(clang::CodeGenOptions *SwiftCodeGenOpts) {
609+
CodeGenOpts.reset(SwiftCodeGenOpts);
610+
}
611+
clang::CodeGenOptions *getSwiftCodeGenOptions() const {
612+
return CodeGenOpts.get();
613+
}
614+
591615
private:
592616
/// Generation number that is used for crude versioning.
593617
///
@@ -835,7 +859,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
835859
return Instance->getPreprocessor();
836860
}
837861

838-
clang::CodeGenOptions &getClangCodeGenOpts() const {
862+
clang::CodeGenOptions &getCodeGenOpts() const {
839863
return Instance->getCodeGenOpts();
840864
}
841865

@@ -1811,7 +1835,8 @@ void getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
18111835

18121836
/// Add command-line arguments common to all imports of Clang code.
18131837
void addCommonInvocationArguments(std::vector<std::string> &invocationArgStrs,
1814-
ASTContext &ctx);
1838+
ASTContext &ctx,
1839+
bool ignoreClangTarget);
18151840

18161841
/// Finds a particular kind of nominal by looking through typealiases.
18171842
template <typename T>

lib/IRGen/IRGenModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ static llvm::StructType *createStructType(IRGenModule &IGM,
8686
}
8787

8888
static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
89-
llvm::LLVMContext &LLVMContext,
89+
llvm::LLVMContext &LLVMContext,
9090
const IRGenOptions &Opts,
9191
StringRef ModuleName,
9292
StringRef PD) {
@@ -95,7 +95,7 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
9595
assert(Importer && "No clang module loader!");
9696
auto &ClangContext = Importer->getClangASTContext();
9797

98-
auto &CGO = Importer->getClangCodeGenOpts();
98+
auto &CGO = Importer->getCodeGenOpts();
9999
if (CGO.OpaquePointers) {
100100
LLVMContext.setOpaquePointers(true);
101101
} else {

0 commit comments

Comments
 (0)