10ac597f3SChris Bieneman //===- unittests/Driver/DXCModeTest.cpp --- DXC Mode tests ----------------===// 20ac597f3SChris Bieneman // 30ac597f3SChris Bieneman // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40ac597f3SChris Bieneman // See https://llvm.org/LICENSE.txt for license information. 50ac597f3SChris Bieneman // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60ac597f3SChris Bieneman // 70ac597f3SChris Bieneman //===----------------------------------------------------------------------===// 80ac597f3SChris Bieneman // 90ac597f3SChris Bieneman // Unit tests for driver DXCMode. 100ac597f3SChris Bieneman // 110ac597f3SChris Bieneman //===----------------------------------------------------------------------===// 120ac597f3SChris Bieneman 130ac597f3SChris Bieneman #include "clang/Basic/DiagnosticIDs.h" 140ac597f3SChris Bieneman #include "clang/Basic/DiagnosticOptions.h" 150ac597f3SChris Bieneman #include "clang/Basic/LLVM.h" 160ac597f3SChris Bieneman #include "clang/Basic/TargetOptions.h" 170ac597f3SChris Bieneman #include "clang/Driver/Compilation.h" 180ac597f3SChris Bieneman #include "clang/Driver/Driver.h" 190ac597f3SChris Bieneman #include "clang/Driver/ToolChain.h" 200ac597f3SChris Bieneman #include "clang/Frontend/CompilerInstance.h" 210ac597f3SChris Bieneman #include "llvm/Support/VirtualFileSystem.h" 220ac597f3SChris Bieneman #include "llvm/Support/raw_ostream.h" 230ac597f3SChris Bieneman #include "gtest/gtest.h" 240ac597f3SChris Bieneman #include <memory> 250ac597f3SChris Bieneman 260ac597f3SChris Bieneman #include "SimpleDiagnosticConsumer.h" 270ac597f3SChris Bieneman 280ac597f3SChris Bieneman using namespace clang; 290ac597f3SChris Bieneman using namespace clang::driver; 300ac597f3SChris Bieneman 310ac597f3SChris Bieneman static void validateTargetProfile( 320ac597f3SChris Bieneman StringRef TargetProfile, StringRef ExpectTriple, 330ac597f3SChris Bieneman IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> &InMemoryFileSystem, 340ac597f3SChris Bieneman DiagnosticsEngine &Diags) { 350ac597f3SChris Bieneman Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); 360ac597f3SChris Bieneman std::unique_ptr<Compilation> C{TheDriver.BuildCompilation( 37d5a7439eSXiang Li {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl", "-Vd"})}; 380ac597f3SChris Bieneman EXPECT_TRUE(C); 390ac597f3SChris Bieneman EXPECT_STREQ(TheDriver.getTargetTriple().c_str(), ExpectTriple.data()); 400ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 0u); 410ac597f3SChris Bieneman } 420ac597f3SChris Bieneman 430ac597f3SChris Bieneman static void validateTargetProfile( 440ac597f3SChris Bieneman StringRef TargetProfile, StringRef ExpectError, 450ac597f3SChris Bieneman IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> &InMemoryFileSystem, 460ac597f3SChris Bieneman DiagnosticsEngine &Diags, SimpleDiagnosticConsumer *DiagConsumer, 470ac597f3SChris Bieneman unsigned NumOfErrors) { 480ac597f3SChris Bieneman Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); 490ac597f3SChris Bieneman std::unique_ptr<Compilation> C{TheDriver.BuildCompilation( 50d5a7439eSXiang Li {"clang", "--driver-mode=dxc", TargetProfile.data(), "foo.hlsl", "-Vd"})}; 510ac597f3SChris Bieneman EXPECT_TRUE(C); 520ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), NumOfErrors); 530ac597f3SChris Bieneman EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), ExpectError.data()); 540ac597f3SChris Bieneman DiagConsumer->clear(); 550ac597f3SChris Bieneman } 560ac597f3SChris Bieneman 570ac597f3SChris Bieneman TEST(DxcModeTest, TargetProfileValidation) { 580ac597f3SChris Bieneman IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 590ac597f3SChris Bieneman 600ac597f3SChris Bieneman IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 610ac597f3SChris Bieneman new llvm::vfs::InMemoryFileSystem); 620ac597f3SChris Bieneman 630ac597f3SChris Bieneman InMemoryFileSystem->addFile("foo.hlsl", 0, 640ac597f3SChris Bieneman llvm::MemoryBuffer::getMemBuffer("\n")); 650ac597f3SChris Bieneman 660ac597f3SChris Bieneman auto *DiagConsumer = new SimpleDiagnosticConsumer; 670ac597f3SChris Bieneman IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 680ac597f3SChris Bieneman DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer); 690ac597f3SChris Bieneman 706d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tvs_6_0", "dxilv1.0--shadermodel6.0-vertex", 710ac597f3SChris Bieneman InMemoryFileSystem, Diags); 726d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Ths_6_1", "dxilv1.1--shadermodel6.1-hull", 730ac597f3SChris Bieneman InMemoryFileSystem, Diags); 746d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tds_6_2", "dxilv1.2--shadermodel6.2-domain", 750ac597f3SChris Bieneman InMemoryFileSystem, Diags); 766d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tds_6_2", "dxilv1.2--shadermodel6.2-domain", 770ac597f3SChris Bieneman InMemoryFileSystem, Diags); 786d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tgs_6_3", "dxilv1.3--shadermodel6.3-geometry", 790ac597f3SChris Bieneman InMemoryFileSystem, Diags); 806d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tps_6_4", "dxilv1.4--shadermodel6.4-pixel", 810ac597f3SChris Bieneman InMemoryFileSystem, Diags); 826d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tcs_6_5", "dxilv1.5--shadermodel6.5-compute", 830ac597f3SChris Bieneman InMemoryFileSystem, Diags); 846d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tms_6_6", "dxilv1.6--shadermodel6.6-mesh", 850ac597f3SChris Bieneman InMemoryFileSystem, Diags); 866d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tas_6_7", "dxilv1.7--shadermodel6.7-amplification", 870ac597f3SChris Bieneman InMemoryFileSystem, Diags); 886d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tcs_6_8", "dxilv1.8--shadermodel6.8-compute", 896d890148SS. Bharadwaj Yadavalli InMemoryFileSystem, Diags); 906d890148SS. Bharadwaj Yadavalli validateTargetProfile("-Tlib_6_x", "dxilv1.8--shadermodel6.15-library", 910ac597f3SChris Bieneman InMemoryFileSystem, Diags); 920ac597f3SChris Bieneman 930ac597f3SChris Bieneman // Invalid tests. 940ac597f3SChris Bieneman validateTargetProfile("-Tpss_6_1", "invalid profile : pss_6_1", 950ac597f3SChris Bieneman InMemoryFileSystem, Diags, DiagConsumer, 1); 960ac597f3SChris Bieneman 970ac597f3SChris Bieneman validateTargetProfile("-Tps_6_x", "invalid profile : ps_6_x", 980ac597f3SChris Bieneman InMemoryFileSystem, Diags, DiagConsumer, 2); 990ac597f3SChris Bieneman validateTargetProfile("-Tlib_6_1", "invalid profile : lib_6_1", 1000ac597f3SChris Bieneman InMemoryFileSystem, Diags, DiagConsumer, 3); 1010ac597f3SChris Bieneman validateTargetProfile("-Tfoo", "invalid profile : foo", InMemoryFileSystem, 1020ac597f3SChris Bieneman Diags, DiagConsumer, 4); 1030ac597f3SChris Bieneman validateTargetProfile("", "target profile option (-T) is missing", 1040ac597f3SChris Bieneman InMemoryFileSystem, Diags, DiagConsumer, 5); 1050ac597f3SChris Bieneman } 1060ac597f3SChris Bieneman 1070ac597f3SChris Bieneman TEST(DxcModeTest, ValidatorVersionValidation) { 1080ac597f3SChris Bieneman IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); 1090ac597f3SChris Bieneman 1100ac597f3SChris Bieneman IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 1110ac597f3SChris Bieneman new llvm::vfs::InMemoryFileSystem); 1120ac597f3SChris Bieneman 1130ac597f3SChris Bieneman InMemoryFileSystem->addFile("foo.hlsl", 0, 1140ac597f3SChris Bieneman llvm::MemoryBuffer::getMemBuffer("\n")); 1150ac597f3SChris Bieneman 1160ac597f3SChris Bieneman auto *DiagConsumer = new SimpleDiagnosticConsumer; 1170ac597f3SChris Bieneman IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); 1180ac597f3SChris Bieneman DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagConsumer); 1190ac597f3SChris Bieneman Driver TheDriver("/bin/clang", "", Diags, "", InMemoryFileSystem); 1200ac597f3SChris Bieneman std::unique_ptr<Compilation> C(TheDriver.BuildCompilation( 1210ac597f3SChris Bieneman {"clang", "--driver-mode=dxc", "-Tlib_6_7", "foo.hlsl"})); 1220ac597f3SChris Bieneman EXPECT_TRUE(C); 1230ac597f3SChris Bieneman EXPECT_TRUE(!C->containsError()); 1240ac597f3SChris Bieneman 1250ac597f3SChris Bieneman auto &TC = C->getDefaultToolChain(); 1260ac597f3SChris Bieneman bool ContainsError = false; 1270ac597f3SChris Bieneman auto Args = TheDriver.ParseArgStrings({"-validator-version", "1.1"}, false, 1280ac597f3SChris Bieneman ContainsError); 1290ac597f3SChris Bieneman EXPECT_FALSE(ContainsError); 1300ac597f3SChris Bieneman auto DAL = std::make_unique<llvm::opt::DerivedArgList>(Args); 1310ac597f3SChris Bieneman for (auto *A : Args) 1320ac597f3SChris Bieneman DAL->append(A); 1330ac597f3SChris Bieneman 1340ac597f3SChris Bieneman std::unique_ptr<llvm::opt::DerivedArgList> TranslatedArgs{ 1350ac597f3SChris Bieneman TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)}; 1360ac597f3SChris Bieneman EXPECT_NE(TranslatedArgs, nullptr); 1370ac597f3SChris Bieneman if (TranslatedArgs) { 1380ac597f3SChris Bieneman auto *A = TranslatedArgs->getLastArg( 1390ac597f3SChris Bieneman clang::driver::options::OPT_dxil_validator_version); 1400ac597f3SChris Bieneman EXPECT_NE(A, nullptr); 141c8a23ec0SMichael Platings if (A) { 1420ac597f3SChris Bieneman EXPECT_STREQ(A->getValue(), "1.1"); 1430ac597f3SChris Bieneman } 144c8a23ec0SMichael Platings } 1450ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 0u); 1460ac597f3SChris Bieneman 1470ac597f3SChris Bieneman // Invalid tests. 1480ac597f3SChris Bieneman Args = TheDriver.ParseArgStrings({"-validator-version", "0.1"}, false, 1490ac597f3SChris Bieneman ContainsError); 1500ac597f3SChris Bieneman EXPECT_FALSE(ContainsError); 1510ac597f3SChris Bieneman DAL = std::make_unique<llvm::opt::DerivedArgList>(Args); 1520ac597f3SChris Bieneman for (auto *A : Args) 1530ac597f3SChris Bieneman DAL->append(A); 1540ac597f3SChris Bieneman 1550ac597f3SChris Bieneman TranslatedArgs.reset( 1560ac597f3SChris Bieneman TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)); 1570ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 1u); 158b49ce9c3SAaron Ballman EXPECT_STREQ( 159b49ce9c3SAaron Ballman DiagConsumer->Errors.back().c_str(), 16010be6c96SAaron Ballman "invalid validator version : 0.1; if validator major version is 0, " 161b49ce9c3SAaron Ballman "minor version must also be 0"); 1620ac597f3SChris Bieneman DiagConsumer->clear(); 1630ac597f3SChris Bieneman 1640ac597f3SChris Bieneman Args = TheDriver.ParseArgStrings({"-validator-version", "1"}, false, 1650ac597f3SChris Bieneman ContainsError); 1660ac597f3SChris Bieneman EXPECT_FALSE(ContainsError); 1670ac597f3SChris Bieneman DAL = std::make_unique<llvm::opt::DerivedArgList>(Args); 1680ac597f3SChris Bieneman for (auto *A : Args) 1690ac597f3SChris Bieneman DAL->append(A); 1700ac597f3SChris Bieneman 1710ac597f3SChris Bieneman TranslatedArgs.reset( 1720ac597f3SChris Bieneman TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)); 1730ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 2u); 1740ac597f3SChris Bieneman EXPECT_STREQ(DiagConsumer->Errors.back().c_str(), 175b49ce9c3SAaron Ballman "invalid validator version : 1; format of validator version is " 176b49ce9c3SAaron Ballman "\"<major>.<minor>\" (ex:\"1.4\")"); 1770ac597f3SChris Bieneman DiagConsumer->clear(); 1780ac597f3SChris Bieneman 1790ac597f3SChris Bieneman Args = TheDriver.ParseArgStrings({"-validator-version", "-Tlib_6_7"}, false, 1800ac597f3SChris Bieneman ContainsError); 1810ac597f3SChris Bieneman EXPECT_FALSE(ContainsError); 1820ac597f3SChris Bieneman DAL = std::make_unique<llvm::opt::DerivedArgList>(Args); 1830ac597f3SChris Bieneman for (auto *A : Args) 1840ac597f3SChris Bieneman DAL->append(A); 1850ac597f3SChris Bieneman 1860ac597f3SChris Bieneman TranslatedArgs.reset( 1870ac597f3SChris Bieneman TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)); 1880ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 3u); 1890ac597f3SChris Bieneman EXPECT_STREQ( 1900ac597f3SChris Bieneman DiagConsumer->Errors.back().c_str(), 191b49ce9c3SAaron Ballman "invalid validator version : -Tlib_6_7; format of validator version is " 192b49ce9c3SAaron Ballman "\"<major>.<minor>\" (ex:\"1.4\")"); 1930ac597f3SChris Bieneman DiagConsumer->clear(); 1940ac597f3SChris Bieneman 1950ac597f3SChris Bieneman Args = TheDriver.ParseArgStrings({"-validator-version", "foo"}, false, 1960ac597f3SChris Bieneman ContainsError); 1970ac597f3SChris Bieneman EXPECT_FALSE(ContainsError); 1980ac597f3SChris Bieneman DAL = std::make_unique<llvm::opt::DerivedArgList>(Args); 1990ac597f3SChris Bieneman for (auto *A : Args) 2000ac597f3SChris Bieneman DAL->append(A); 2010ac597f3SChris Bieneman 2020ac597f3SChris Bieneman TranslatedArgs.reset( 2030ac597f3SChris Bieneman TC.TranslateArgs(*DAL, "0", Action::OffloadKind::OFK_None)); 2040ac597f3SChris Bieneman EXPECT_EQ(Diags.getNumErrors(), 4u); 2050ac597f3SChris Bieneman EXPECT_STREQ( 2060ac597f3SChris Bieneman DiagConsumer->Errors.back().c_str(), 207b49ce9c3SAaron Ballman "invalid validator version : foo; format of validator version is " 208b49ce9c3SAaron Ballman "\"<major>.<minor>\" (ex:\"1.4\")"); 2090ac597f3SChris Bieneman DiagConsumer->clear(); 2100ac597f3SChris Bieneman } 2110ac597f3SChris Bieneman 2120ac597f3SChris Bieneman TEST(DxcModeTest, DefaultEntry) { 2130ac597f3SChris Bieneman IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem( 2140ac597f3SChris Bieneman new llvm::vfs::InMemoryFileSystem); 2150ac597f3SChris Bieneman 2160ac597f3SChris Bieneman InMemoryFileSystem->addFile("foo.hlsl", 0, 2170ac597f3SChris Bieneman llvm::MemoryBuffer::getMemBuffer("\n")); 2180ac597f3SChris Bieneman 2190ac597f3SChris Bieneman const char *Args[] = {"clang", "--driver-mode=dxc", "-Tcs_6_7", "foo.hlsl"}; 2200ac597f3SChris Bieneman 2210ac597f3SChris Bieneman IntrusiveRefCntPtr<DiagnosticsEngine> Diags = 222*df9a14d7SKadir Cetinkaya CompilerInstance::createDiagnostics(*InMemoryFileSystem, 223*df9a14d7SKadir Cetinkaya new DiagnosticOptions()); 2240ac597f3SChris Bieneman 2250ac597f3SChris Bieneman CreateInvocationOptions CIOpts; 2260ac597f3SChris Bieneman CIOpts.Diags = Diags; 2270ac597f3SChris Bieneman std::unique_ptr<CompilerInvocation> CInvok = 2280ac597f3SChris Bieneman createInvocation(Args, std::move(CIOpts)); 2290ac597f3SChris Bieneman EXPECT_TRUE(CInvok); 2300ac597f3SChris Bieneman // Make sure default entry is "main". 2310ac597f3SChris Bieneman EXPECT_STREQ(CInvok->getTargetOpts().HLSLEntry.c_str(), "main"); 2320ac597f3SChris Bieneman 2330ac597f3SChris Bieneman const char *EntryArgs[] = {"clang", "--driver-mode=dxc", "-Ebar", "-Tcs_6_7", 2340ac597f3SChris Bieneman "foo.hlsl"}; 2350ac597f3SChris Bieneman CInvok = createInvocation(EntryArgs, std::move(CIOpts)); 2360ac597f3SChris Bieneman EXPECT_TRUE(CInvok); 2370ac597f3SChris Bieneman // Make sure "-E" will set entry. 2380ac597f3SChris Bieneman EXPECT_STREQ(CInvok->getTargetOpts().HLSLEntry.c_str(), "bar"); 2390ac597f3SChris Bieneman } 240