237 lines · cpp
1//===- unittests/Driver/DXCModeTest.cpp --- DXC Mode tests ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Unit tests for driver DXCMode.10//11//===----------------------------------------------------------------------===//12 13#include "clang/Basic/DiagnosticIDs.h"14#include "clang/Basic/DiagnosticOptions.h"15#include "clang/Basic/LLVM.h"16#include "clang/Basic/TargetOptions.h"17#include "clang/Driver/Compilation.h"18#include "clang/Driver/CreateInvocationFromArgs.h"19#include "clang/Driver/Driver.h"20#include "clang/Driver/ToolChain.h"21#include "clang/Frontend/CompilerInstance.h"22#include "llvm/Support/VirtualFileSystem.h"23#include "llvm/Support/raw_ostream.h"24#include "gtest/gtest.h"25#include <memory>26 27#include "SimpleDiagnosticConsumer.h"28 29using namespace clang;30using namespace clang::driver;31 32static void validateTargetProfile(33 StringRef TargetProfile, StringRef ExpectTriple,34 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> &InMemoryFileSystem,35 DiagnosticsEngine &Diags) {36 Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem);37 std::unique_ptr<Compilation> C{TheDriver.BuildCompilation(38 {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl", "-Vd"})};39 EXPECT_TRUE(C);40 EXPECT_STREQ(TheDriver.getTargetTriple().c_str(), ExpectTriple.data());41 EXPECT_EQ(Diags.getNumErrors(), 0u);42}43 44static void validateTargetProfile(45 StringRef TargetProfile, StringRef ExpectError,46 IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> &InMemoryFileSystem,47 DiagnosticsEngine &Diags, SimpleDiagnosticConsumer *DiagConsumer,48 unsigned NumOfErrors) {49 Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem);50 std::unique_ptr<Compilation> C{TheDriver.BuildCompilation(51 {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl", "-Vd"})};52 EXPECT_TRUE(C);53 EXPECT_EQ(Diags.getNumErrors(), NumOfErrors);54 EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), ExpectError.data());55 DiagConsumer->clear();56}57 58TEST(DxcModeTest, TargetProfileValidation) {59 auto InMemoryFileSystem =60 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();61 62 InMemoryFileSystem->addFile("foo.hlsl", 0,63 llvm::MemoryBuffer::getMemBuffer("\n"));64 65 auto *DiagConsumer = new SimpleDiagnosticConsumer;66 DiagnosticOptions DiagOpts;67 DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagConsumer);68 69 validateTargetProfile("-Tvs_6_0", "dxilv1.0--shadermodel6.0-vertex",70 InMemoryFileSystem, Diags);71 validateTargetProfile("-Ths_6_1", "dxilv1.1--shadermodel6.1-hull",72 InMemoryFileSystem, Diags);73 validateTargetProfile("-Tds_6_2", "dxilv1.2--shadermodel6.2-domain",74 InMemoryFileSystem, Diags);75 validateTargetProfile("-Tds_6_2", "dxilv1.2--shadermodel6.2-domain",76 InMemoryFileSystem, Diags);77 validateTargetProfile("-Tgs_6_3", "dxilv1.3--shadermodel6.3-geometry",78 InMemoryFileSystem, Diags);79 validateTargetProfile("-Tps_6_4", "dxilv1.4--shadermodel6.4-pixel",80 InMemoryFileSystem, Diags);81 validateTargetProfile("-Tcs_6_5", "dxilv1.5--shadermodel6.5-compute",82 InMemoryFileSystem, Diags);83 validateTargetProfile("-Tms_6_6", "dxilv1.6--shadermodel6.6-mesh",84 InMemoryFileSystem, Diags);85 validateTargetProfile("-Tas_6_7", "dxilv1.7--shadermodel6.7-amplification",86 InMemoryFileSystem, Diags);87 validateTargetProfile("-Tcs_6_8", "dxilv1.8--shadermodel6.8-compute",88 InMemoryFileSystem, Diags);89 validateTargetProfile("-Tlib_6_x", "dxilv1.9--shadermodel6.15-library",90 InMemoryFileSystem, Diags);91 92 // Invalid tests.93 validateTargetProfile("-Tpss_6_1", "invalid profile : pss_6_1",94 InMemoryFileSystem, Diags, DiagConsumer, 1);95 96 validateTargetProfile("-Tps_6_x", "invalid profile : ps_6_x",97 InMemoryFileSystem, Diags, DiagConsumer, 2);98 validateTargetProfile("-Tlib_6_1", "invalid profile : lib_6_1",99 InMemoryFileSystem, Diags, DiagConsumer, 3);100 validateTargetProfile("-Tfoo", "invalid profile : foo", InMemoryFileSystem,101 Diags, DiagConsumer, 4);102 validateTargetProfile("", "target profile option (-T) is missing",103 InMemoryFileSystem, Diags, DiagConsumer, 5);104}105 106TEST(DxcModeTest, ValidatorVersionValidation) {107 auto InMemoryFileSystem =108 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();109 110 InMemoryFileSystem->addFile("foo.hlsl", 0,111 llvm::MemoryBuffer::getMemBuffer("\n"));112 113 auto *DiagConsumer = new SimpleDiagnosticConsumer;114 DiagnosticOptions DiagOpts;115 DiagnosticsEngine Diags(DiagnosticIDs::create(), DiagOpts, DiagConsumer);116 Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem);117 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(118 {"clang", "--driver-mode=dxc", "-Tlib_6_7", "foo.hlsl"}));119 EXPECT_TRUE(C);120 EXPECT_TRUE(!C->containsError());121 122 auto &TC = C->getDefaultToolChain();123 bool ContainsError = false;124 auto Args = TheDriver.ParseArgStrings({"-validator-version", "1.1"}, false,125 ContainsError);126 EXPECT_FALSE(ContainsError);127 auto DAL = std::make_unique<llvm::opt::DerivedArgList>(Args);128 for (auto *A : Args)129 DAL->append(A);130 131 std::unique_ptr<llvm::opt::DerivedArgList> TranslatedArgs{132 TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)};133 EXPECT_NE(TranslatedArgs, nullptr);134 if (TranslatedArgs) {135 auto *A =136 TranslatedArgs->getLastArg(clang::options::OPT_dxil_validator_version);137 EXPECT_NE(A, nullptr);138 if (A) {139 EXPECT_STREQ(A->getValue(), "1.1");140 }141 }142 EXPECT_EQ(Diags.getNumErrors(), 0u);143 144 // Invalid tests.145 Args = TheDriver.ParseArgStrings({"-validator-version", "0.1"}, false,146 ContainsError);147 EXPECT_FALSE(ContainsError);148 DAL = std::make_unique<llvm::opt::DerivedArgList>(Args);149 for (auto *A : Args)150 DAL->append(A);151 152 TranslatedArgs.reset(153 TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));154 EXPECT_EQ(Diags.getNumErrors(), 1u);155 EXPECT_STREQ(156 DiagConsumer->Errors.back().c_str(),157 "invalid validator version : 0.1; if validator major version is 0, "158 "minor version must also be 0");159 DiagConsumer->clear();160 161 Args = TheDriver.ParseArgStrings({"-validator-version", "1"}, false,162 ContainsError);163 EXPECT_FALSE(ContainsError);164 DAL = std::make_unique<llvm::opt::DerivedArgList>(Args);165 for (auto *A : Args)166 DAL->append(A);167 168 TranslatedArgs.reset(169 TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));170 EXPECT_EQ(Diags.getNumErrors(), 2u);171 EXPECT_STREQ(DiagConsumer->Errors.back().c_str(),172 "invalid validator version : 1; format of validator version is "173 "\"<major>.<minor>\" (ex:\"1.4\")");174 DiagConsumer->clear();175 176 Args = TheDriver.ParseArgStrings({"-validator-version", "-Tlib_6_7"}, false,177 ContainsError);178 EXPECT_FALSE(ContainsError);179 DAL = std::make_unique<llvm::opt::DerivedArgList>(Args);180 for (auto *A : Args)181 DAL->append(A);182 183 TranslatedArgs.reset(184 TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));185 EXPECT_EQ(Diags.getNumErrors(), 3u);186 EXPECT_STREQ(187 DiagConsumer->Errors.back().c_str(),188 "invalid validator version : -Tlib_6_7; format of validator version is "189 "\"<major>.<minor>\" (ex:\"1.4\")");190 DiagConsumer->clear();191 192 Args = TheDriver.ParseArgStrings({"-validator-version", "foo"}, false,193 ContainsError);194 EXPECT_FALSE(ContainsError);195 DAL = std::make_unique<llvm::opt::DerivedArgList>(Args);196 for (auto *A : Args)197 DAL->append(A);198 199 TranslatedArgs.reset(200 TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None));201 EXPECT_EQ(Diags.getNumErrors(), 4u);202 EXPECT_STREQ(203 DiagConsumer->Errors.back().c_str(),204 "invalid validator version : foo; format of validator version is "205 "\"<major>.<minor>\" (ex:\"1.4\")");206 DiagConsumer->clear();207}208 209TEST(DxcModeTest, DefaultEntry) {210 auto InMemoryFileSystem =211 llvm::makeIntrusiveRefCnt<llvm::vfs::InMemoryFileSystem>();212 213 InMemoryFileSystem->addFile("foo.hlsl", 0,214 llvm::MemoryBuffer::getMemBuffer("\n"));215 216 const char *Args[] = {"clang", "--driver-mode=dxc", "-Tcs_6_7", "foo.hlsl"};217 218 DiagnosticOptions DiagOpts;219 IntrusiveRefCntPtr<DiagnosticsEngine> Diags =220 CompilerInstance::createDiagnostics(*InMemoryFileSystem, DiagOpts);221 222 CreateInvocationOptions CIOpts;223 CIOpts.Diags = Diags;224 std::unique_ptr<CompilerInvocation> CInvok =225 createInvocation(Args, std::move(CIOpts));226 EXPECT_TRUE(CInvok);227 // Make sure default entry is "main".228 EXPECT_STREQ(CInvok->getTargetOpts().HLSLEntry.c_str(), "main");229 230 const char *EntryArgs[] = {"clang", "--driver-mode=dxc", "-Ebar", "-Tcs_6_7",231 "foo.hlsl"};232 CInvok = createInvocation(EntryArgs, std::move(CIOpts));233 EXPECT_TRUE(CInvok);234 // Make sure "-E" will set entry.235 EXPECT_STREQ(CInvok->getTargetOpts().HLSLEntry.c_str(), "bar");236}237