[clang] 721651b - [HLSL][clang][Driver] Support target profile command line option.

Chris Bieneman via cfe-commits cfe-commits at lists.llvm.org
Fri Apr 15 12:18:26 PDT 2022


Author: Xiang Li
Date: 2022-04-15T14:18:18-05:00
New Revision: 721651be246e26efd767c3ec55c8f06c7b5a9a3d

URL: https://github.com/llvm/llvm-project/commit/721651be246e26efd767c3ec55c8f06c7b5a9a3d
DIFF: https://github.com/llvm/llvm-project/commit/721651be246e26efd767c3ec55c8f06c7b5a9a3d.diff

LOG: [HLSL][clang][Driver] Support target profile command line option.

The target profile option(/T) decide the shader model when compile hlsl.
The format is shaderKind_major_minor like ps_6_1.
The shader model is saved as llvm::Triple is clang/llvm like
dxil-unknown-shadermodel6.1-hull.
The main job to support the option is translating ps_6_1 into
shadermodel6.1-pixel.
That is done inside tryParseProfile  at HLSL.cpp.

To integrate the option into clang Driver, a new DriverMode DxcMode is
created. When DxcMode is enabled, OSType for TargetTriple will be
forced into Triple::ShaderModel. And new ToolChain HLSLToolChain will
be created when OSType is Triple::ShaderModel.

In HLSLToolChain, ComputeEffectiveClangTriple is overridden to call
tryParseProfile when targetProfile option is set.

To make test work, Fo option is added and .hlsl is added for active
-xhlsl.

Reviewed By: beanz

Differential Revision: https://reviews.llvm.org/D122865

Patch by: Xiang Li <python3kgae at outlook.com>

Added: 
    clang/lib/Driver/ToolChains/HLSL.cpp
    clang/lib/Driver/ToolChains/HLSL.h

Modified: 
    clang/include/clang/Basic/DiagnosticDriverKinds.td
    clang/include/clang/Driver/Driver.h
    clang/include/clang/Driver/Options.h
    clang/include/clang/Driver/Options.td
    clang/lib/Driver/CMakeLists.txt
    clang/lib/Driver/Driver.cpp
    clang/lib/Driver/ToolChain.cpp
    clang/lib/Driver/Types.cpp
    clang/test/lit.cfg.py
    clang/unittests/Driver/ToolChainTest.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td
index 64af4c84672fe..cb53804d9e4f8 100644
--- a/clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -657,4 +657,7 @@ def warn_drv_fjmc_for_elf_only : Warning<
 def err_drv_target_variant_invalid : Error<
   "unsupported '%0' value '%1'; use 'ios-macabi' instead">;
 
+def err_drv_invalid_directx_shader_module : Error<
+  "invalid profile : %0">;
+
 }

diff  --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h
index 6f24f649ea544..b33b64cd9e6a2 100644
--- a/clang/include/clang/Driver/Driver.h
+++ b/clang/include/clang/Driver/Driver.h
@@ -68,7 +68,8 @@ class Driver {
     GXXMode,
     CPPMode,
     CLMode,
-    FlangMode
+    FlangMode,
+    DXCMode
   } Mode;
 
   enum SaveTempsMode {
@@ -195,6 +196,9 @@ class Driver {
   /// Other modes fall back to calling gcc which in turn calls gfortran.
   bool IsFlangMode() const { return Mode == FlangMode; }
 
+  /// Whether the driver should follow dxc.exe like behavior.
+  bool IsDXCMode() const { return Mode == DXCMode; }
+
   /// Only print tool bindings, don't build any jobs.
   unsigned CCCPrintBindings : 1;
 

diff  --git a/clang/include/clang/Driver/Options.h b/clang/include/clang/Driver/Options.h
index 056660192ac5f..f9b9632ee7cbe 100644
--- a/clang/include/clang/Driver/Options.h
+++ b/clang/include/clang/Driver/Options.h
@@ -35,7 +35,8 @@ enum ClangFlags {
   FlangOption = (1 << 14),
   FC1Option = (1 << 15),
   FlangOnlyOption = (1 << 16),
-  Ignored = (1 << 17),
+  DXCOption = (1 << 17),
+  Ignored = (1 << 18),
 };
 
 enum ID {

diff  --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index 104c8ea8483d1..f454bd038ecf8 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -49,6 +49,10 @@ def CC1Option : OptionFlag;
 // CC1AsOption - This option should be accepted by clang -cc1as.
 def CC1AsOption : OptionFlag;
 
+// DXCOption - This is a dxc.exe compatibility option. Options with this flag
+// are made available when the driver is running in DXC compatibility mode.
+def DXCOption : OptionFlag;
+
 // NoDriverOption - This option should not be accepted by the driver.
 def NoDriverOption : OptionFlag;
 
@@ -6686,3 +6690,33 @@ def _SLASH_Ze : CLFlag<"Ze">;
 def _SLASH_Zg : CLFlag<"Zg">;
 def _SLASH_ZI : CLFlag<"ZI">;
 def _SLASH_ZW : CLJoined<"ZW">;
+
+//===----------------------------------------------------------------------===//
+// clang-dxc Options
+//===----------------------------------------------------------------------===//
+
+def dxc_Group : OptionGroup<"<clang-dxc options>">, Flags<[DXCOption]>,
+  HelpText<"dxc compatibility options">;
+
+class DXCJoinedOrSeparate<string name> : Option<["/", "-"], name,
+  KIND_JOINED_OR_SEPARATE>, Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>;
+
+def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>,
+  Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>, Alias<help>,
+  HelpText<"Display available options">;
+
+
+def Fo : DXCJoinedOrSeparate<"Fo">, Alias<o>,
+  HelpText<"Output object file.">;
+
+def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">,
+  HelpText<"Set target profile.">,
+  Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7,"
+         "vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7,"
+         "gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7,"
+         "hs_6_0, hs_6_1, hs_6_2, hs_6_3, hs_6_4, hs_6_5, hs_6_6, hs_6_7,"
+         "ds_6_0, ds_6_1, ds_6_2, ds_6_3, ds_6_4, ds_6_5, ds_6_6, ds_6_7,"
+         "cs_6_0, cs_6_1, cs_6_2, cs_6_3, cs_6_4, cs_6_5, cs_6_6, cs_6_7,"
+         "lib_6_3, lib_6_4, lib_6_5, lib_6_6, lib_6_7, lib_6_x,"
+         "ms_6_5, ms_6_6, ms_6_7,"
+         "as_6_5, as_6_6, as_6_7">;

diff  --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt
index dc6d370810abb..18c9b2d042f6c 100644
--- a/clang/lib/Driver/CMakeLists.txt
+++ b/clang/lib/Driver/CMakeLists.txt
@@ -60,6 +60,7 @@ add_clang_library(clangDriver
   ToolChains/HIPAMD.cpp
   ToolChains/HIPSPV.cpp
   ToolChains/Hexagon.cpp
+  ToolChains/HLSL.cpp
   ToolChains/Hurd.cpp
   ToolChains/Linux.cpp
   ToolChains/MipsLinux.cpp

diff  --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 8de1a364092dc..0095e87b6ba00 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -26,6 +26,7 @@
 #include "ToolChains/Gnu.h"
 #include "ToolChains/HIPAMD.h"
 #include "ToolChains/HIPSPV.h"
+#include "ToolChains/HLSL.h"
 #include "ToolChains/Haiku.h"
 #include "ToolChains/Hexagon.h"
 #include "ToolChains/Hurd.h"
@@ -232,6 +233,7 @@ void Driver::setDriverMode(StringRef Value) {
                    .Case("cpp", CPPMode)
                    .Case("cl", CLMode)
                    .Case("flang", FlangMode)
+                   .Case("dxc", DXCMode)
                    .Default(None))
     Mode = *M;
   else
@@ -1190,7 +1192,14 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
     T.setEnvironment(llvm::Triple::MSVC);
     T.setObjectFormat(llvm::Triple::COFF);
     TargetTriple = T.str();
+  } else if (IsDXCMode()) {
+    // clang-dxc target is build from target_profile option.
+    // Just set OS to shader model to select HLSLToolChain.
+    llvm::Triple T(TargetTriple);
+    T.setOS(llvm::Triple::ShaderModel);
+    TargetTriple = T.str();
   }
+
   if (const Arg *A = Args.getLastArg(options::OPT_target))
     TargetTriple = A->getValue();
   if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir))
@@ -5684,6 +5693,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
     case llvm::Triple::ZOS:
       TC = std::make_unique<toolchains::ZOS>(*this, Target, Args);
       break;
+    case llvm::Triple::ShaderModel:
+      TC = std::make_unique<toolchains::HLSLToolChain>(*this, Target, Args);
+      break;
     default:
       // Of these targets, Hexagon is the only one that might have
       // an OS of Linux, in which case it got handled above already.
@@ -5902,7 +5914,13 @@ Driver::getIncludeExcludeOptionFlagMasks(bool IsClCompatMode) const {
   } else {
     ExcludedFlagsBitmask |= options::CLOption;
   }
-
+  if (IsDXCMode()) {
+    // Include DXC and Core options.
+    IncludedFlagsBitmask |= options::DXCOption;
+    IncludedFlagsBitmask |= options::CoreOption;
+  } else {
+    ExcludedFlagsBitmask |= options::DXCOption;
+  }
   return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask);
 }
 

diff  --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp
index f4415a30eb9d4..d45a90048dcbe 100644
--- a/clang/lib/Driver/ToolChain.cpp
+++ b/clang/lib/Driver/ToolChain.cpp
@@ -153,6 +153,7 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName, size_t &Pos) {
       {"cl", "--driver-mode=cl"},
       {"++", "--driver-mode=g++"},
       {"flang", "--driver-mode=flang"},
+      {"clang-dxc", "--driver-mode=dxc"},
   };
 
   for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i) {

diff  --git a/clang/lib/Driver/ToolChains/HLSL.cpp b/clang/lib/Driver/ToolChains/HLSL.cpp
new file mode 100644
index 0000000000000..a2a2a3a7bf552
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/HLSL.cpp
@@ -0,0 +1,133 @@
+//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "HLSL.h"
+#include "CommonArgs.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+
+using namespace clang::driver;
+using namespace clang::driver::tools;
+using namespace clang::driver::toolchains;
+using namespace clang;
+using namespace llvm::opt;
+using namespace llvm;
+
+namespace {
+
+const unsigned OfflineLibMinor = 0xF;
+
+bool isLegalShaderModel(Triple &T) {
+  if (T.getOS() != Triple::OSType::ShaderModel)
+    return false;
+
+  auto Version = T.getOSVersion();
+  if (Version.getBuild())
+    return false;
+  if (Version.getSubminor())
+    return false;
+
+  auto Kind = T.getEnvironment();
+
+  switch (Kind) {
+  default:
+    return false;
+  case Triple::EnvironmentType::Vertex:
+  case Triple::EnvironmentType::Hull:
+  case Triple::EnvironmentType::Domain:
+  case Triple::EnvironmentType::Geometry:
+  case Triple::EnvironmentType::Pixel:
+  case Triple::EnvironmentType::Compute: {
+    VersionTuple MinVer(4, 0);
+    return MinVer <= Version;
+  } break;
+  case Triple::EnvironmentType::Library: {
+    VersionTuple SM6x(6, OfflineLibMinor);
+    if (Version == SM6x)
+      return true;
+
+    VersionTuple MinVer(6, 3);
+    return MinVer <= Version;
+  } break;
+  case Triple::EnvironmentType::Amplification:
+  case Triple::EnvironmentType::Mesh: {
+    VersionTuple MinVer(6, 5);
+    return MinVer <= Version;
+  } break;
+  }
+  return false;
+}
+
+std::string tryParseProfile(StringRef Profile) {
+  // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
+  SmallVector<StringRef, 3> Parts;
+  Profile.split(Parts, "_");
+  if (Parts.size() != 3)
+    return "";
+
+  Triple::EnvironmentType Kind =
+      StringSwitch<Triple::EnvironmentType>(Parts[0])
+          .Case("ps", Triple::EnvironmentType::Pixel)
+          .Case("vs", Triple::EnvironmentType::Vertex)
+          .Case("gs", Triple::EnvironmentType::Geometry)
+          .Case("hs", Triple::EnvironmentType::Hull)
+          .Case("ds", Triple::EnvironmentType::Domain)
+          .Case("cs", Triple::EnvironmentType::Compute)
+          .Case("lib", Triple::EnvironmentType::Library)
+          .Case("ms", Triple::EnvironmentType::Mesh)
+          .Case("as", Triple::EnvironmentType::Amplification)
+          .Default(Triple::EnvironmentType::UnknownEnvironment);
+  if (Kind == Triple::EnvironmentType::UnknownEnvironment)
+    return "";
+
+  unsigned long long Major = 0;
+  if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
+    return "";
+
+  unsigned long long Minor = 0;
+  if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)
+    Minor = OfflineLibMinor;
+  else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
+    return "";
+
+  // dxil-unknown-shadermodel-hull
+  llvm::Triple T;
+  T.setArch(Triple::ArchType::dxil);
+  T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +
+              VersionTuple(Major, Minor).getAsString());
+  T.setEnvironment(Kind);
+  if (isLegalShaderModel(T))
+    return T.getTriple();
+  else
+    return "";
+}
+
+} // namespace
+
+/// DirectX Toolchain
+HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+                             const ArgList &Args)
+    : ToolChain(D, Triple, Args) {}
+
+std::string
+HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
+                                           types::ID InputType) const {
+  if (Arg *A = Args.getLastArg(options::OPT_target_profile)) {
+    StringRef Profile = A->getValue();
+    std::string Triple = tryParseProfile(Profile);
+    if (Triple == "") {
+      getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile;
+      Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType);
+    }
+    A->claim();
+    return Triple;
+  } else {
+    return ToolChain::ComputeEffectiveClangTriple(Args, InputType);
+  }
+}

diff  --git a/clang/lib/Driver/ToolChains/HLSL.h b/clang/lib/Driver/ToolChains/HLSL.h
new file mode 100644
index 0000000000000..052003f53ae05
--- /dev/null
+++ b/clang/lib/Driver/ToolChains/HLSL.h
@@ -0,0 +1,37 @@
+//===--- HLSL.h - HLSL ToolChain Implementations ----------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H
+
+#include "clang/Driver/ToolChain.h"
+
+namespace clang {
+namespace driver {
+
+namespace toolchains {
+
+class LLVM_LIBRARY_VISIBILITY HLSLToolChain : public ToolChain {
+public:
+  HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
+                const llvm::opt::ArgList &Args);
+  bool isPICDefault() const override { return false; }
+  bool isPIEDefault(const llvm::opt::ArgList &Args) const override {
+    return false;
+  }
+  bool isPICDefaultForced() const override { return false; }
+
+  std::string ComputeEffectiveClangTriple(const llvm::opt::ArgList &Args,
+                                          types::ID InputType) const override;
+};
+
+} // end namespace toolchains
+} // end namespace driver
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_HLSL_H

diff  --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp
index 8f6adc6c2ad1e..befdc50faa9c5 100644
--- a/clang/lib/Driver/Types.cpp
+++ b/clang/lib/Driver/Types.cpp
@@ -332,6 +332,7 @@ types::ID types::lookupTypeForExtension(llvm::StringRef Ext) {
            .Case("c++m", TY_CXXModule)
            .Case("cppm", TY_CXXModule)
            .Case("cxxm", TY_CXXModule)
+           .Case("hlsl", TY_HLSL)
            .Default(TY_INVALID);
 }
 

diff  --git a/clang/test/lit.cfg.py b/clang/test/lit.cfg.py
index 44b26e7822714..afc119cd4166d 100644
--- a/clang/test/lit.cfg.py
+++ b/clang/test/lit.cfg.py
@@ -67,6 +67,8 @@
     'clang-tblgen', 'clang-scan-deps', 'opt', 'llvm-ifs', 'yaml2obj',
     ToolSubst('%clang_extdef_map', command=FindTool(
         'clang-extdef-mapping'), unresolved='ignore'),
+    ToolSubst('%clang_dxc', command=config.clang,
+        extra_args=['--driver-mode=dxc']),
 ]
 
 if config.clang_examples:

diff  --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp
index 286ad84e92d67..3d9d266ef3161 100644
--- a/clang/unittests/Driver/ToolChainTest.cpp
+++ b/clang/unittests/Driver/ToolChainTest.cpp
@@ -300,6 +300,12 @@ TEST(ToolChainTest, GetTargetAndMode) {
   EXPECT_TRUE(Res.ModeSuffix == "clang-cl");
   EXPECT_STREQ(Res.DriverMode, "--driver-mode=cl");
   EXPECT_FALSE(Res.TargetIsValid);
+
+  Res = ToolChain::getTargetAndModeFromProgramName("clang-dxc");
+  EXPECT_TRUE(Res.TargetPrefix.empty());
+  EXPECT_TRUE(Res.ModeSuffix == "clang-dxc");
+  EXPECT_STREQ(Res.DriverMode, "--driver-mode=dxc");
+  EXPECT_FALSE(Res.TargetIsValid);
 }
 
 TEST(ToolChainTest, CommandOutput) {
@@ -361,4 +367,141 @@ TEST(GetDriverMode, PrefersLastDriverMode) {
   EXPECT_EQ(getDriverMode(Args[0], llvm::makeArrayRef(Args).slice(1)), "bar");
 }
 
+TEST(DxcModeTest, TargetProfileValidation) {
+  IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+  struct SimpleDiagnosticConsumer : public DiagnosticConsumer {
+    void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel,
+                          const Diagnostic &Info) override {
+      if (DiagLevel == DiagnosticsEngine::Level::Error) {
+        Errors.emplace_back();
+        Info.FormatDiagnostic(Errors.back());
+      } else {
+        Msgs.emplace_back();
+        Info.FormatDiagnostic(Msgs.back());
+      }
+    }
+    void clear() override {
+      Msgs.clear();
+      Errors.clear();
+      DiagnosticConsumer::clear();
+    }
+    std::vector<SmallString<32>> Msgs;
+    std::vector<SmallString<32>> Errors;
+  };
+
+  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
+      new llvm::vfs::InMemoryFileSystem);
+
+  InMemoryFileSystem->addFile("foo.hlsl", 0,
+                              llvm::MemoryBuffer::getMemBuffer("\n"));
+
+  auto *DiagConsumer = new SimpleDiagnosticConsumer;
+  IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
+  DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer);
+  Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem);
+  std::unique_ptr<Compilation> C(
+      TheDriver.BuildCompilation({"clang", "--driver-mode=dxc", "foo.hlsl"}));
+  EXPECT_TRUE(C);
+  EXPECT_TRUE(!C->containsError());
+
+  auto &TC = C->getDefaultToolChain();
+  bool ContainsError = false;
+  auto Args = TheDriver.ParseArgStrings({"-Tvs_6_0"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  auto Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.0-vertex");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Ths_6_1"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.1-hull");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tds_6_2"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.2-domain");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tgs_6_3"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.3-geometry");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tps_6_4"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.4-pixel");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tcs_6_5"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.5-compute");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tms_6_6"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.6-mesh");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tas_6_7"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.7-amplification");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  Args = TheDriver.ParseArgStrings({"-Tlib_6_x"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "dxil--shadermodel6.15-library");
+  EXPECT_EQ(Diags.getNumErrors(), 0u);
+
+  // Invalid tests.
+  Args = TheDriver.ParseArgStrings({"-Tpss_6_1"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel");
+  EXPECT_EQ(Diags.getNumErrors(), 1u);
+  EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : pss_6_1");
+  Diags.Clear();
+  DiagConsumer->clear();
+
+  Args = TheDriver.ParseArgStrings({"-Tps_6_x"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel");
+  EXPECT_EQ(Diags.getNumErrors(), 2u);
+  EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : ps_6_x");
+  Diags.Clear();
+  DiagConsumer->clear();
+
+  Args = TheDriver.ParseArgStrings({"-Tlib_6_1"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel");
+  EXPECT_EQ(Diags.getNumErrors(), 3u);
+  EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : lib_6_1");
+  Diags.Clear();
+  DiagConsumer->clear();
+
+  Args = TheDriver.ParseArgStrings({"-Tfoo"}, false, ContainsError);
+  EXPECT_FALSE(ContainsError);
+  Triple = TC.ComputeEffectiveClangTriple(Args);
+  EXPECT_STREQ(Triple.c_str(), "unknown-unknown-shadermodel");
+  EXPECT_EQ(Diags.getNumErrors(), 4u);
+  EXPECT_STREQ(DiagConsumer->Errors.back().data(), "invalid profile : foo");
+  Diags.Clear();
+  DiagConsumer->clear();
+}
+
 } // end anonymous namespace.


        


More information about the cfe-commits mailing list