diff --git a/clang/include/clang/Basic/TargetInfo.h b/clang/include/clang/Basic/TargetInfo.h --- a/clang/include/clang/Basic/TargetInfo.h +++ b/clang/include/clang/Basic/TargetInfo.h @@ -235,6 +235,8 @@ unsigned MaxOpenCLWorkGroupSize; + Optional DarwinTargetVariantTriple; + // TargetInfo Constructor. Default initializes all fields. TargetInfo(const llvm::Triple &T); @@ -1608,6 +1610,21 @@ /// Whether target allows debuginfo types for decl only variables/functions. virtual bool allowDebugInfoForExternalRef() const { return false; } + /// Returns the darwin target variant triple, the variant of the deployment + /// target for which the code is being compiled. + const llvm::Triple *getDarwinTargetVariantTriple() const { + return DarwinTargetVariantTriple ? DarwinTargetVariantTriple.getPointer() + : nullptr; + } + + /// Returns the version of the darwin target variant SDK which was used during + /// the compilation if one was specified, or an empty version otherwise. + const Optional getDarwinTargetVariantSDKVersion() const { + return !getTargetOpts().DarwinTargetVariantSDKVersion.empty() + ? getTargetOpts().DarwinTargetVariantSDKVersion + : Optional(); + } + protected: /// Copy type and layout related info. void copyAuxTarget(const TargetInfo *Aux); diff --git a/clang/include/clang/Basic/TargetOptions.h b/clang/include/clang/Basic/TargetOptions.h --- a/clang/include/clang/Basic/TargetOptions.h +++ b/clang/include/clang/Basic/TargetOptions.h @@ -91,6 +91,13 @@ /// * CUDA compilation uses it to control parts of CUDA compilation /// in clang that depend on specific version of the CUDA SDK. llvm::VersionTuple SDKVersion; + + /// The name of the darwin target- ariant triple to compile for. + std::string DarwinTargetVariantTriple; + + /// The version of the darwin target variant SDK which was used during the + /// compilation. + llvm::VersionTuple DarwinTargetVariantSDKVersion; }; } // end namespace clang diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4777,6 +4777,13 @@ MarshallingInfoString>; def target_sdk_version_EQ : Joined<["-"], "target-sdk-version=">, HelpText<"The version of target SDK used for compilation">; +def darwin_target_variant_triple : Separate<["-"], "darwin-target-variant-triple">, + HelpText<"Specify the darwin target variant triple">, + MarshallingInfoString>, + Normalizer<"normalizeTriple">; +def darwin_target_variant_sdk_version_EQ : Joined<["-"], + "darwin-target-variant-sdk-version=">, + HelpText<"The version of darwin target variant SDK used for compilation">; } diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -731,6 +731,10 @@ Target->setCommandLineOpenCLOpts(); Target->setMaxAtomicWidth(); + if (!Opts->DarwinTargetVariantTriple.empty()) + Target->DarwinTargetVariantTriple = + llvm::Triple(Opts->DarwinTargetVariantTriple); + if (!Target->validateTarget(Diags)) return nullptr; diff --git a/clang/lib/CodeGen/ModuleBuilder.cpp b/clang/lib/CodeGen/ModuleBuilder.cpp --- a/clang/lib/CodeGen/ModuleBuilder.cpp +++ b/clang/lib/CodeGen/ModuleBuilder.cpp @@ -146,6 +146,11 @@ const auto &SDKVersion = Ctx->getTargetInfo().getSDKVersion(); if (!SDKVersion.empty()) M->setSDKVersion(SDKVersion); + if (const auto *TVT = Ctx->getTargetInfo().getDarwinTargetVariantTriple()) + M->setDarwinTargetVariantTriple(TVT->getTriple()); + if (auto TVSDKVersion = + Ctx->getTargetInfo().getDarwinTargetVariantSDKVersion()) + M->setDarwinTargetVariantSDKVersion(*TVSDKVersion); Builder.reset(new CodeGen::CodeGenModule(Context, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags, CoverageInfo)); diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4404,6 +4404,9 @@ if (!Opts.SDKVersion.empty()) GenerateArg(Args, OPT_target_sdk_version_EQ, Opts.SDKVersion.getAsString(), SA); + if (!Opts.DarwinTargetVariantSDKVersion.empty()) + GenerateArg(Args, OPT_darwin_target_variant_sdk_version_EQ, + Opts.DarwinTargetVariantSDKVersion.getAsString(), SA); } static bool ParseTargetArgs(TargetOptions &Opts, ArgList &Args, @@ -4431,6 +4434,15 @@ else Opts.SDKVersion = Version; } + if (Arg *A = + Args.getLastArg(options::OPT_darwin_target_variant_sdk_version_EQ)) { + llvm::VersionTuple Version; + if (Version.tryParse(A->getValue())) + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + else + Opts.DarwinTargetVariantSDKVersion = Version; + } return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/CodeGen/darwin-target-variant.c b/clang/test/CodeGen/darwin-target-variant.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/darwin-target-variant.c @@ -0,0 +1,6 @@ +// RUN: %clang_cc1 -triple x86_64-apple-macos11 -darwin-target-variant-triple x86_64-apple-ios14-macabi -target-sdk-version=11.1 -darwin-target-variant-sdk-version=14.1 -emit-llvm -o - %s | FileCheck %s + +// CHECK: !llvm.module.flags = !{!0, !1, !2 +// CHECK: !0 = !{i32 2, !"SDK Version", [2 x i32] [i32 11, i32 1]} +// CHECK: !1 = !{i32 4, !"darwin.target_variant.triple", !"x86_64-apple-ios14-macabi"} +// CHECK: !2 = !{i32 2, !"darwin.target_variant.SDK Version", [2 x i32] [i32 14, i32 1]} diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -939,10 +939,17 @@ /// @returns a string containing the target variant triple. StringRef getDarwinTargetVariantTriple() const; + /// Set the target variant triple which is a string describing a variant of + /// the target host platform. + void setDarwinTargetVariantTriple(StringRef T); + /// Get the target variant version build SDK version metadata. /// /// An empty version is returned if no such metadata is attached. VersionTuple getDarwinTargetVariantSDKVersion() const; + + /// Set the target variant version build SDK version metadata. + void setDarwinTargetVariantSDKVersion(VersionTuple Version); }; /// Given "llvm.used" or "llvm.compiler.used" as a global name, collect the diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -734,7 +734,7 @@ addModuleFlag(ModFlagBehavior::Error, "override-stack-alignment", Align); } -void Module::setSDKVersion(const VersionTuple &V) { +static void addSDKVersionMD(const VersionTuple &V, Module &M, StringRef Name) { SmallVector Entries; Entries.push_back(V.getMajor()); if (auto Minor = V.getMinor()) { @@ -744,8 +744,12 @@ // Ignore the 'build' component as it can't be represented in the object // file. } - addModuleFlag(ModFlagBehavior::Warning, "SDK Version", - ConstantDataArray::get(Context, Entries)); + M.addModuleFlag(Module::ModFlagBehavior::Warning, Name, + ConstantDataArray::get(M.getContext(), Entries)); +} + +void Module::setSDKVersion(const VersionTuple &V) { + addSDKVersionMD(V, *this, "SDK Version"); } static VersionTuple getSDKVersionMD(Metadata *MD) { @@ -818,6 +822,15 @@ return ""; } +void Module::setDarwinTargetVariantTriple(StringRef T) { + addModuleFlag(ModFlagBehavior::Override, "darwin.target_variant.triple", + MDString::get(getContext(), T)); +} + VersionTuple Module::getDarwinTargetVariantSDKVersion() const { return getSDKVersionMD(getModuleFlag("darwin.target_variant.SDK Version")); } + +void Module::setDarwinTargetVariantSDKVersion(VersionTuple Version) { + addSDKVersionMD(Version, *this, "darwin.target_variant.SDK Version"); +}