Skip to content

[Explicit Module Builds] Ensure IRGen uses Swift compiler's target triple when '-clang-target' is set. #65930

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
merged 1 commit into from
May 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion include/swift/AST/ClangModuleLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,21 @@ class ClangModuleLoader : public ModuleLoader {
using ModuleLoader::ModuleLoader;

public:
virtual clang::TargetInfo &getTargetInfo() const = 0;
/// This module loader's Clang instance may be configured with a different
/// (higher) OS version than the compilation target itself in order to be able
/// to load pre-compiled Clang modules that are aligned with the broader SDK,
/// and match the SDK deployment target against which Swift modules are also
/// built.
///
/// In this case, we must use the Swift compiler's OS version triple when
/// performing codegen, and the importer's Clang instance OS version triple
/// during module loading. `getModuleAvailabilityTarget` is for module-loading
/// clients only, and uses the latter.
///
/// (The implementing `ClangImporter` class maintains separate Target info
/// for use by IRGen/CodeGen clients)
virtual clang::TargetInfo &getModuleAvailabilityTarget() const = 0;

virtual clang::ASTContext &getClangASTContext() const = 0;
virtual clang::Preprocessor &getClangPreprocessor() const = 0;
virtual clang::Sema &getClangSema() const = 0;
Expand Down
29 changes: 25 additions & 4 deletions include/swift/ClangImporter/ClangImporter.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ namespace clang {
class VisibleDeclConsumer;
class DeclarationName;
class CompilerInvocation;
class TargetOptions;
namespace tooling {
namespace dependencies {
struct ModuleDeps;
Expand Down Expand Up @@ -173,7 +174,7 @@ class ClangImporter final : public ClangModuleLoader {
DWARFImporterDelegate *dwarfImporterDelegate = nullptr);

static std::vector<std::string>
getClangArguments(ASTContext &ctx);
getClangArguments(ASTContext &ctx, bool ignoreClangTarget = false);

static std::unique_ptr<clang::CompilerInvocation>
createClangInvocation(ClangImporter *importer,
Expand Down Expand Up @@ -445,13 +446,33 @@ class ClangImporter final : public ClangModuleLoader {
StringRef moduleName,
ModuleDependencyKind moduleKind,
ModuleDependenciesCache &cache);

clang::TargetInfo &getTargetInfo() const override;
clang::TargetInfo &getModuleAvailabilityTarget() const override;
clang::ASTContext &getClangASTContext() const override;
clang::Preprocessor &getClangPreprocessor() const override;
clang::Sema &getClangSema() const override;
const clang::CompilerInstance &getClangInstance() const override;
clang::CodeGenOptions &getClangCodeGenOpts() const;

/// ClangImporter's Clang instance may be configured with a different
/// (higher) OS version than the compilation target itself in order to be able
/// to load pre-compiled Clang modules that are aligned with the broader SDK,
/// and match the SDK deployment target against which Swift modules are also
/// built.
///
/// In this case, we must use the Swift compiler's OS version triple when
/// performing codegen, and the importer's Clang instance OS version triple
/// during module loading.
///
/// `ClangImporter`'s `Implementation` keeps track of a distinct `TargetInfo`
/// and `CodeGenOpts` containers that are meant to be used by clients in
/// IRGen. When a separate `-clang-target` is not set, they are defined to be
/// copies of the `ClangImporter`'s built-in module-loading Clang instance.
/// When `-clang-target` is set, they are configured with the Swift
/// compilation's target triple and OS version (but otherwise identical)
/// instead. To distinguish IRGen clients from module loading clients,
/// `getModuleAvailabilityTarget` should be used instead by module-loading
/// clients.
clang::TargetInfo &getTargetInfo() const;
clang::CodeGenOptions &getCodeGenOpts() const;

std::string getClangModuleHash() const;

Expand Down
59 changes: 42 additions & 17 deletions lib/ClangImporter/ClangImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -718,11 +718,11 @@ getEmbedBitcodeInvocationArguments(std::vector<std::string> &invocationArgStrs,
void
importer::addCommonInvocationArguments(
std::vector<std::string> &invocationArgStrs,
ASTContext &ctx) {
ASTContext &ctx, bool ignoreClangTarget) {
using ImporterImpl = ClangImporter::Implementation;
llvm::Triple triple = ctx.LangOpts.Target;
// Use clang specific target triple if given.
if (ctx.LangOpts.ClangTarget.has_value()) {
if (ctx.LangOpts.ClangTarget.has_value() && !ignoreClangTarget) {
triple = ctx.LangOpts.ClangTarget.value();
}
SearchPathOptions &searchPathOpts = ctx.SearchPathOpts;
Expand Down Expand Up @@ -970,7 +970,7 @@ Optional<std::string> ClangImporter::getOrCreatePCH(
}

std::vector<std::string>
ClangImporter::getClangArguments(ASTContext &ctx) {
ClangImporter::getClangArguments(ASTContext &ctx, bool ignoreClangTarget) {
std::vector<std::string> invocationArgStrs;
// Clang expects this to be like an actual command line. So we need to pass in
// "clang" for argv[0]
Expand All @@ -991,7 +991,7 @@ ClangImporter::getClangArguments(ASTContext &ctx) {
getEmbedBitcodeInvocationArguments(invocationArgStrs, ctx);
break;
}
addCommonInvocationArguments(invocationArgStrs, ctx);
addCommonInvocationArguments(invocationArgStrs, ctx, ignoreClangTarget);
return invocationArgStrs;
}

Expand Down Expand Up @@ -1094,15 +1094,6 @@ ClangImporter::create(ASTContext &ctx,
std::unique_ptr<ClangImporter> importer{
new ClangImporter(ctx, tracker, dwarfImporterDelegate)};
auto &importerOpts = ctx.ClangImporterOpts;
importer->Impl.ClangArgs = getClangArguments(ctx);
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
if (importerOpts.DumpClangDiagnostics) {
llvm::errs() << "'";
llvm::interleave(
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
[] { llvm::errs() << "' '"; });
llvm::errs() << "'\n";
}

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

// Create a new Clang compiler invocation.
{
importer->Impl.ClangArgs = getClangArguments(ctx);
ArrayRef<std::string> invocationArgStrs = importer->Impl.ClangArgs;
if (importerOpts.DumpClangDiagnostics) {
llvm::errs() << "'";
llvm::interleave(
invocationArgStrs, [](StringRef arg) { llvm::errs() << arg; },
[] { llvm::errs() << "' '"; });
llvm::errs() << "'\n";
}
importer->Impl.Invocation = createClangInvocation(
importer.get(), importerOpts, VFS, invocationArgStrs);
if (!importer->Impl.Invocation)
Expand Down Expand Up @@ -1217,6 +1217,27 @@ ClangImporter::create(ASTContext &ctx,
clang::SourceLocation());
clangDiags.setFatalsAsError(ctx.Diags.getShowDiagnosticsAfterFatalError());

// Use Clang to configure/save options for Swift IRGen/CodeGen
if (ctx.LangOpts.ClangTarget.has_value()) {
// If '-clang-target' is set, create a mock invocation with the Swift triple
// to configure CodeGen and Target options for Swift compilation.
auto swiftTargetClangArgs = getClangArguments(ctx, true);
ArrayRef<std::string> invocationArgStrs = swiftTargetClangArgs;
auto swiftTargetClangInvocation = createClangInvocation(
importer.get(), importerOpts, VFS, invocationArgStrs);
if (!swiftTargetClangInvocation)
return nullptr;
importer->Impl.setSwiftTargetInfo(clang::TargetInfo::CreateTargetInfo(
clangDiags, swiftTargetClangInvocation->TargetOpts));
importer->Impl.setSwiftCodeGenOptions(new clang::CodeGenOptions(
swiftTargetClangInvocation->getCodeGenOpts()));
} else {
// Just use the existing Invocation's directly
importer->Impl.setSwiftTargetInfo(clang::TargetInfo::CreateTargetInfo(
clangDiags, importer->Impl.Invocation->TargetOpts));
importer->Impl.setSwiftCodeGenOptions(
new clang::CodeGenOptions(importer->Impl.Invocation->getCodeGenOpts()));
}

// Create the associated action.
importer->Impl.Action.reset(new ParsingAction(ctx, *importer,
Expand Down Expand Up @@ -1872,7 +1893,7 @@ bool ClangImporter::canImportModule(ImportPath::Module modulePath,
clang::Module *m;
auto &ctx = Impl.getClangASTContext();
auto &lo = ctx.getLangOpts();
auto &ti = getTargetInfo();
auto &ti = getModuleAvailabilityTarget();

auto available = clangModule->isAvailable(lo, ti, r, mh, m);
if (!available)
Expand Down Expand Up @@ -3687,10 +3708,14 @@ StringRef ClangModuleUnit::getLoadedFilename() const {
return StringRef();
}

clang::TargetInfo &ClangImporter::getTargetInfo() const {
clang::TargetInfo &ClangImporter::getModuleAvailabilityTarget() const {
return Impl.Instance->getTarget();
}

clang::TargetInfo &ClangImporter::getTargetInfo() const {
return *Impl.getSwiftTargetInfo();
}

clang::ASTContext &ClangImporter::getClangASTContext() const {
return Impl.getClangASTContext();
}
Expand Down Expand Up @@ -3720,8 +3745,8 @@ clang::Sema &ClangImporter::getClangSema() const {
return Impl.getClangSema();
}

clang::CodeGenOptions &ClangImporter::getClangCodeGenOpts() const {
return Impl.getClangCodeGenOpts();
clang::CodeGenOptions &ClangImporter::getCodeGenOpts() const {
return *Impl.getSwiftCodeGenOptions();
}

std::string ClangImporter::getClangModuleHash() const {
Expand Down
29 changes: 27 additions & 2 deletions lib/ClangImporter/ImporterImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/RecursiveASTVisitor.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Serialization/ModuleFileExtension.h"
#include "llvm/ADT/APSInt.h"
Expand Down Expand Up @@ -588,6 +589,29 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
return Instance.get();
}

private:
/// The Importer may be configured to load modules of a different OS Version
/// than the underlying Swift compilation. This is the `TargetOptions`
/// corresponding to the instantiating Swift compilation's triple. These are
/// to be used by all IRGen/CodeGen clients of `ClangImporter`.
std::unique_ptr<clang::TargetInfo> CodeGenTargetInfo;
std::unique_ptr<clang::CodeGenOptions> CodeGenOpts;

public:
void setSwiftTargetInfo(clang::TargetInfo *SwiftTargetInfo) {
CodeGenTargetInfo.reset(SwiftTargetInfo);
}
clang::TargetInfo *getSwiftTargetInfo() const {
return CodeGenTargetInfo.get();
}

void setSwiftCodeGenOptions(clang::CodeGenOptions *SwiftCodeGenOpts) {
CodeGenOpts.reset(SwiftCodeGenOpts);
}
clang::CodeGenOptions *getSwiftCodeGenOptions() const {
return CodeGenOpts.get();
}

private:
/// Generation number that is used for crude versioning.
///
Expand Down Expand Up @@ -835,7 +859,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
return Instance->getPreprocessor();
}

clang::CodeGenOptions &getClangCodeGenOpts() const {
clang::CodeGenOptions &getCodeGenOpts() const {
return Instance->getCodeGenOpts();
}

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

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

/// Finds a particular kind of nominal by looking through typealiases.
template <typename T>
Expand Down
4 changes: 2 additions & 2 deletions lib/IRGen/IRGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static llvm::StructType *createStructType(IRGenModule &IGM,
}

static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
llvm::LLVMContext &LLVMContext,
llvm::LLVMContext &LLVMContext,
const IRGenOptions &Opts,
StringRef ModuleName,
StringRef PD) {
Expand All @@ -95,7 +95,7 @@ static clang::CodeGenerator *createClangCodeGenerator(ASTContext &Context,
assert(Importer && "No clang module loader!");
auto &ClangContext = Importer->getClangASTContext();

auto &CGO = Importer->getClangCodeGenOpts();
auto &CGO = Importer->getCodeGenOpts();
if (CGO.OpaquePointers) {
LLVMContext.setOpaquePointers(true);
} else {
Expand Down