Skip to content

Commit 99f545a

Browse files
authored
Merge pull request #65930 from artemcm/SeparateClangTargetHandlingForIRGen
[Explicit Module Builds] Ensure IRGen uses Swift compiler's target triple when '-clang-target' is set.
2 parents e22cf2e + f2cf55a commit 99f545a

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
@@ -50,6 +50,7 @@ namespace clang {
5050
class VisibleDeclConsumer;
5151
class DeclarationName;
5252
class CompilerInvocation;
53+
class TargetOptions;
5354
namespace tooling {
5455
namespace dependencies {
5556
struct ModuleDeps;
@@ -173,7 +174,7 @@ class ClangImporter final : public ClangModuleLoader {
173174
DWARFImporterDelegate *dwarfImporterDelegate = nullptr);
174175

175176
static std::vector<std::string>
176-
getClangArguments(ASTContext &ctx);
177+
getClangArguments(ASTContext &ctx, bool ignoreClangTarget = false);
177178

178179
static std::unique_ptr<clang::CompilerInvocation>
179180
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
@@ -723,11 +723,11 @@ getEmbedBitcodeInvocationArguments(std::vector<std::string> &invocationArgStrs,
723723
void
724724
importer::addCommonInvocationArguments(
725725
std::vector<std::string> &invocationArgStrs,
726-
ASTContext &ctx) {
726+
ASTContext &ctx, bool ignoreClangTarget) {
727727
using ImporterImpl = ClangImporter::Implementation;
728728
llvm::Triple triple = ctx.LangOpts.Target;
729729
// Use clang specific target triple if given.
730-
if (ctx.LangOpts.ClangTarget.has_value()) {
730+
if (ctx.LangOpts.ClangTarget.has_value() && !ignoreClangTarget) {
731731
triple = ctx.LangOpts.ClangTarget.value();
732732
}
733733
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
@@ -975,7 +975,7 @@ Optional<std::string> ClangImporter::getOrCreatePCH(
975975
}
976976

977977
std::vector<std::string>
978-
ClangImporter::getClangArguments(ASTContext &ctx) {
978+
ClangImporter::getClangArguments(ASTContext &ctx, bool ignoreClangTarget) {
979979
std::vector<std::string> invocationArgStrs;
980980
// Clang expects this to be like an actual command line. So we need to pass in
981981
// "clang" for argv[0]
@@ -996,7 +996,7 @@ ClangImporter::getClangArguments(ASTContext &ctx) {
996996
getEmbedBitcodeInvocationArguments(invocationArgStrs, ctx);
997997
break;
998998
}
999-
addCommonInvocationArguments(invocationArgStrs, ctx);
999+
addCommonInvocationArguments(invocationArgStrs, ctx, ignoreClangTarget);
10001000
return invocationArgStrs;
10011001
}
10021002

@@ -1099,15 +1099,6 @@ ClangImporter::create(ASTContext &ctx,
10991099
std::unique_ptr<ClangImporter> importer{
11001100
new ClangImporter(ctx, tracker, dwarfImporterDelegate)};
11011101
auto &importerOpts = ctx.ClangImporterOpts;
1102-
importer->Impl.ClangArgs = getClangArguments(ctx);
1103-
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
1104-
if (importerOpts.DumpClangDiagnostics) {
1105-
llvm::errs() << "'";
1106-
llvm::interleave(
1107-
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
1108-
[] { llvm::errs() << "' '"; });
1109-
llvm::errs() << "'\n";
1110-
}
11111102

11121103
if (isPCHFilenameExtension(importerOpts.BridgingHeader)) {
11131104
importer->Impl.setSinglePCHImport(importerOpts.BridgingHeader);
@@ -1147,6 +1138,15 @@ ClangImporter::create(ASTContext &ctx,
11471138

11481139
// Create a new Clang compiler invocation.
11491140
{
1141+
importer->Impl.ClangArgs = getClangArguments(ctx);
1142+
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
1143+
if (importerOpts.DumpClangDiagnostics) {
1144+
llvm::errs() << "'";
1145+
llvm::interleave(
1146+
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
1147+
[] { llvm::errs() << "' '"; });
1148+
llvm::errs() << "'\n";
1149+
}
11501150
importer->Impl.Invocation = createClangInvocation(
11511151
importer.get(), importerOpts, VFS, invocationArgStrs);
11521152
if (!importer->Impl.Invocation)
@@ -1222,6 +1222,27 @@ ClangImporter::create(ASTContext &ctx,
12221222
clang::SourceLocation());
12231223
clangDiags.setFatalsAsError(ctx.Diags.getShowDiagnosticsAfterFatalError());
12241224

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

12261247
// Create the associated action.
12271248
importer->Impl.Action.reset(new ParsingAction(ctx, *importer,
@@ -1880,7 +1901,7 @@ bool ClangImporter::canImportModule(ImportPath::Module modulePath,
18801901
clang::Module *m;
18811902
auto &ctx = Impl.getClangASTContext();
18821903
auto &lo = ctx.getLangOpts();
1883-
auto &ti = getTargetInfo();
1904+
auto &ti = getModuleAvailabilityTarget();
18841905

18851906
auto available = clangModule->isAvailable(lo, ti, r, mh, m);
18861907
if (!available)
@@ -3688,10 +3709,14 @@ StringRef ClangModuleUnit::getLoadedFilename() const {
36883709
return StringRef();
36893710
}
36903711

3691-
clang::TargetInfo &ClangImporter::getTargetInfo() const {
3712+
clang::TargetInfo &ClangImporter::getModuleAvailabilityTarget() const {
36923713
return Impl.Instance->getTarget();
36933714
}
36943715

3716+
clang::TargetInfo &ClangImporter::getTargetInfo() const {
3717+
return *Impl.getSwiftTargetInfo();
3718+
}
3719+
36953720
clang::ASTContext &ClangImporter::getClangASTContext() const {
36963721
return Impl.getClangASTContext();
36973722
}
@@ -3721,8 +3746,8 @@ clang::Sema &ClangImporter::getClangSema() const {
37213746
return Impl.getClangSema();
37223747
}
37233748

3724-
clang::CodeGenOptions &ClangImporter::getClangCodeGenOpts() const {
3725-
return Impl.getClangCodeGenOpts();
3749+
clang::CodeGenOptions &ClangImporter::getCodeGenOpts() const {
3750+
return *Impl.getSwiftCodeGenOptions();
37263751
}
37273752

37283753
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

@@ -1814,7 +1838,8 @@ void getNormalInvocationArguments(std::vector<std::string> &invocationArgStrs,
18141838

18151839
/// Add command-line arguments common to all imports of Clang code.
18161840
void addCommonInvocationArguments(std::vector<std::string> &invocationArgStrs,
1817-
ASTContext &ctx);
1841+
ASTContext &ctx,
1842+
bool ignoreClangTarget);
18181843

18191844
/// Finds a particular kind of nominal by looking through typealiases.
18201845
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)