From 5f7834de562eeda3689fba0824008e1bcd7958b8 Mon Sep 17 00:00:00 2001 From: Xiang Li Date: Thu, 14 Dec 2023 06:50:32 -0800 Subject: [PATCH] [lit][SPIRV] convert runCodeTest to lit and remove dependence on effcee (#6077) Convert runCodeTest to lit FileCheck test and remove all the code related to runCodeTest. Remove effcee and re2 from git submodule since nothing is dependent on them after the change. --- .gitmodules | 6 - external/CMakeLists.txt | 45 --- external/effcee | 1 - external/re2 | 1 - .../test/CodeGenSPIRV/InlinedCodeTest.hlsl | 12 + .../InlinedCodeWithErrorTest.hlsl | 12 + .../test/CodeGenSPIRV/PositionInVSTests.hlsl | 53 ++++ .../SourceCodeWithoutFilePath.hlsl | 4 + tools/clang/unittests/SPIRV/CMakeLists.txt | 6 +- .../unittests/SPIRV/CodeGenSpirvTest.cpp | 167 ----------- .../clang/unittests/SPIRV/FileTestFixture.cpp | 207 ------------- tools/clang/unittests/SPIRV/FileTestFixture.h | 81 ------ tools/clang/unittests/SPIRV/FileTestUtils.cpp | 274 ------------------ tools/clang/unittests/SPIRV/FileTestUtils.h | 104 ------- 14 files changed, 82 insertions(+), 891 deletions(-) delete mode 160000 external/effcee delete mode 160000 external/re2 create mode 100644 tools/clang/test/CodeGenSPIRV/InlinedCodeTest.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/InlinedCodeWithErrorTest.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/PositionInVSTests.hlsl create mode 100644 tools/clang/test/CodeGenSPIRV/SourceCodeWithoutFilePath.hlsl delete mode 100644 tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp delete mode 100644 tools/clang/unittests/SPIRV/FileTestFixture.cpp delete mode 100644 tools/clang/unittests/SPIRV/FileTestFixture.h delete mode 100644 tools/clang/unittests/SPIRV/FileTestUtils.cpp delete mode 100644 tools/clang/unittests/SPIRV/FileTestUtils.h diff --git a/.gitmodules b/.gitmodules index 0e86b34f49..a20c118a72 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,12 +7,6 @@ [submodule "external/googletest"] path = external/googletest url = https://github.com/google/googletest -[submodule "external/re2"] - path = external/re2 - url = https://github.com/google/re2 -[submodule "external/effcee"] - path = external/effcee - url = https://github.com/google/effcee [submodule "external/DirectX-Headers"] path = external/DirectX-Headers url = https://github.com/microsoft/DirectX-Headers.git diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index ba1a5db603..a8b2638e3d 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -72,49 +72,4 @@ if (${ENABLE_SPIRV_CODEGEN}) set_property(TARGET ${target} PROPERTY FOLDER "External dependencies") endforeach() - # We need Effcee for SPIR-V codegen testing. - if (${SPIRV_BUILD_TESTS}) - # re2 is needed since it's required by effcee. - set(DXC_RE2_DIR "${DXC_EXTERNAL_ROOT_DIR}/re2" CACHE STRING "Location of RE2 source") - set(DXC_EFFCEE_DIR "${DXC_EXTERNAL_ROOT_DIR}/effcee" CACHE STRING "Location of Effcee source") - - if (NOT TARGET re2) - if (IS_DIRECTORY ${DXC_RE2_DIR}) - # Avoid exception handling warning from MSVC. - # This add_compile_options() will only affect the current directory and its subdirectories. - if (WIN32) - add_compile_options(/EHs) - else(WIN32) - # Disable all warnings in subproject RE2 - add_compile_options(-w) - endif(WIN32) - # Don't build/run re2's tests. - set(RE2_BUILD_TESTING OFF CACHE BOOL "Skip RE2 tests") - add_subdirectory(${DXC_RE2_DIR} EXCLUDE_FROM_ALL) - endif() - endif() - - if (NOT TARGET effcee) - if (IS_DIRECTORY ${DXC_EFFCEE_DIR}) - # Configure effcee - set(EFFCEE_RE2_DIR "${DXC_RE2_DIR}" CACHE STRING "Location of RE2 for effcee") - set(EFFCEE_ENABLE_SHARED_CRT ON CACHE BOOL "Enable using shared C Runtime") - # Don't build/run effcee's tests. - set(EFFCEE_BUILD_TESTING OFF CACHE BOOL "Skip effcee tests") - set(EFFCEE_BUILD_SAMPLES OFF CACHE BOOL "Skip building effcee examples") - add_subdirectory(${DXC_EFFCEE_DIR} EXCLUDE_FROM_ALL) - endif() - endif() - - # Organize these targets better in Visual Studio - set(SPIRV_TEST_DEP_TARGETS - effcee - re2 - ) - foreach(target ${SPIRV_TEST_DEP_TARGETS}) - set_property(TARGET ${target} PROPERTY FOLDER "External dependencies") - endforeach() - - endif() - endif() diff --git a/external/effcee b/external/effcee deleted file mode 160000 index 66edefd2bb..0000000000 --- a/external/effcee +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 66edefd2bb641de8a2f46b476de21f227fc03a28 diff --git a/external/re2 b/external/re2 deleted file mode 160000 index b76a3eac1d..0000000000 --- a/external/re2 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b76a3eac1dfc7f0fe1d6a64cb59eab868056f099 diff --git a/tools/clang/test/CodeGenSPIRV/InlinedCodeTest.hlsl b/tools/clang/test/CodeGenSPIRV/InlinedCodeTest.hlsl new file mode 100644 index 0000000000..33702854ca --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/InlinedCodeTest.hlsl @@ -0,0 +1,12 @@ +// RUN: %dxc -T ps_6_0 -E PSMain -fcgl %s -spirv | FileCheck %s + +struct PSInput +{ + float4 color : COLOR; +}; + +// CHECK: OpFunctionCall %v4float %src_PSMain +float4 PSMain(PSInput input) : SV_TARGET +{ + return input.color; +} diff --git a/tools/clang/test/CodeGenSPIRV/InlinedCodeWithErrorTest.hlsl b/tools/clang/test/CodeGenSPIRV/InlinedCodeWithErrorTest.hlsl new file mode 100644 index 0000000000..5755a7e379 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/InlinedCodeWithErrorTest.hlsl @@ -0,0 +1,12 @@ +// RUN: not %dxc -T ps_6_0 -E PSMain -fcgl %s -spirv 2>&1 | FileCheck %s + +struct PSInput +{ + float4 color : COLOR; +}; + +// CHECK: error: cannot initialize return object of type 'float4' with an lvalue of type 'PSInput' +float4 PSMain(PSInput input) : SV_TARGET +{ + return input; +} \ No newline at end of file diff --git a/tools/clang/test/CodeGenSPIRV/PositionInVSTests.hlsl b/tools/clang/test/CodeGenSPIRV/PositionInVSTests.hlsl new file mode 100644 index 0000000000..b9a84bfe41 --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/PositionInVSTests.hlsl @@ -0,0 +1,53 @@ +// RUN: not %dxc -T vs_6_2 -E main -DTY=float -DARRAY=[4] -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -DTY=double4 -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -DTY=int4 -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -DTY=float1x4 -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -DTY=float3 -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -DTY=InvalidType -fcgl %s -spirv 2>&1 | FileCheck %s + +// RUN: %dxc -T vs_6_2 -E main -DTY=ValidType -fcgl %s -spirv | FileCheck %s --check-prefix=VALID_TY + +// RUN: %dxc -T vs_6_2 -E main -DTY=float4 -fcgl %s -spirv | FileCheck %s --check-prefix=VALID_FLOAT +// RUN: %dxc -T vs_6_2 -E main -DTY=min10float4 -fcgl %s -spirv | FileCheck %s --check-prefix=VALID_FLOAT +// RUN: %dxc -T vs_6_2 -E main -DTY=min16float4 -fcgl %s -spirv | FileCheck %s --check-prefix=VALID_FLOAT +// RUN: %dxc -T vs_6_2 -E main -DTY=half4 -fcgl %s -spirv | FileCheck %s --check-prefix=VALID_FLOAT + +// RUN: not %dxc -T vs_6_2 -E main -enable-16bit-types -DTY=half4 -fcgl %s -spirv 2>&1 | FileCheck %s +// RUN: not %dxc -T vs_6_2 -E main -enable-16bit-types -DTY=min10float4 -fcgl %s -spirv 2>&1 | FileCheck %s + + +// CHECK: error: SV_Position must be a 4-component 32-bit float vector or a composite which recursively contains only such a vector + +// VALID_TY: %ValidType = OpTypeStruct %v4float +// VALID_TY: %output = OpTypeStruct %ValidType + +// VALID_FLOAT: %output = OpTypeStruct %v4float + + + + +struct InvalidType { + float3 x; +}; + +struct ValidType { + float4 x; +}; + +#ifndef ARRAY +#define ARRAY +#endif + +#define POSITION TY x ARRAY + +struct output { + POSITION; +}; + + + +output main() : SV_Position +{ + output result; + return result; +} \ No newline at end of file diff --git a/tools/clang/test/CodeGenSPIRV/SourceCodeWithoutFilePath.hlsl b/tools/clang/test/CodeGenSPIRV/SourceCodeWithoutFilePath.hlsl new file mode 100644 index 0000000000..1cc54a4feb --- /dev/null +++ b/tools/clang/test/CodeGenSPIRV/SourceCodeWithoutFilePath.hlsl @@ -0,0 +1,4 @@ +// RUN: %dxc -T ps_6_0 -E PSMain -Zi -fcgl %s -spirv | FileCheck %s + +float4 PSMain(float4 color : COLOR) : SV_TARGET { return color; } +// CHECK: float4 PSMain(float4 color : COLOR) : SV_TARGET { return color; } diff --git a/tools/clang/unittests/SPIRV/CMakeLists.txt b/tools/clang/unittests/SPIRV/CMakeLists.txt index 97da9cc892..1e6e7107ab 100644 --- a/tools/clang/unittests/SPIRV/CMakeLists.txt +++ b/tools/clang/unittests/SPIRV/CMakeLists.txt @@ -7,9 +7,6 @@ set(LLVM_LINK_COMPONENTS ) add_clang_unittest(ClangSPIRVTests - CodeGenSpirvTest.cpp - FileTestFixture.cpp - FileTestUtils.cpp SpirvBasicBlockTest.cpp SpirvContextTest.cpp SpirvTestOptions.cpp @@ -28,7 +25,6 @@ target_link_libraries(ClangSPIRVTests clangSPIRV clangTooling dxcompiler - effcee SPIRV-Tools ) @@ -38,7 +34,7 @@ target_link_libraries(ClangSPIRVTests add_dependencies(ClangSPIRVTests dxcompiler) target_include_directories(ClangSPIRVTests - PRIVATE ${SPIRV_TOOLS_INCLUDE_DIR} ${DXC_EFFCEE_DIR}) + PRIVATE ${SPIRV_TOOLS_INCLUDE_DIR}) if (NOT CLANG_INCLUDE_TESTS) set_output_directory(ClangSPIRVTests diff --git a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp b/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp deleted file mode 100644 index ca3bf4be2e..0000000000 --- a/tools/clang/unittests/SPIRV/CodeGenSpirvTest.cpp +++ /dev/null @@ -1,167 +0,0 @@ -//===- unittests/SPIRV/CodeGenSPIRVTest.cpp ---- Run CodeGenSPIRV tests ---===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "FileTestFixture.h" - -namespace { -using clang::spirv::FileTest; - -// === Partial output tests === - -TEST_F(FileTest, InlinedCodeTest) { - const std::string command(R"(// RUN: %dxc -T ps_6_0 -E PSMain)"); - const std::string code = command + R"( -struct PSInput -{ - float4 color : COLOR; -}; - -// CHECK: OpFunctionCall %v4float %src_PSMain -float4 PSMain(PSInput input) : SV_TARGET -{ - return input.color; -})"; - runCodeTest(code); -} - -TEST_F(FileTest, InlinedCodeWithErrorTest) { - const std::string command(R"(// RUN: %dxc -T ps_6_0 -E PSMain)"); - const std::string code = command + R"( -struct PSInput -{ - float4 color : COLOR; -}; - -// CHECK: error: cannot initialize return object of type 'float4' with an lvalue of type 'PSInput' -float4 PSMain(PSInput input) : SV_TARGET -{ - return input; -})"; - runCodeTest(code, Expect::Failure); -} - -std::string getVertexPositionTypeTestShader(const std::string &subType, - const std::string &positionType, - const std::string &check, - bool use16bit) { - const std::string code = std::string(R"(// RUN: %dxc -T vs_6_2 -E main)") + - (use16bit ? R"( -enable-16bit-types)" : R"()") + R"( -)" + subType + R"( -struct output { -)" + positionType + R"( -}; - -output main() : SV_Position -{ - output result; - return result; -} -)" + check; - return code; -} - -const char *kInvalidPositionTypeForVSErrorMessage = - "// CHECK: error: SV_Position must be a 4-component 32-bit float vector or " - "a composite which recursively contains only such a vector"; - -TEST_F(FileTest, PositionInVSWithArrayType) { - runCodeTest( - getVertexPositionTypeTestShader( - "", "float x[4];", kInvalidPositionTypeForVSErrorMessage, false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithDoubleType) { - runCodeTest( - getVertexPositionTypeTestShader( - "", "double4 x;", kInvalidPositionTypeForVSErrorMessage, false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithIntType) { - runCodeTest(getVertexPositionTypeTestShader( - "", "int4 x;", kInvalidPositionTypeForVSErrorMessage, false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithMatrixType) { - runCodeTest( - getVertexPositionTypeTestShader( - "", "float1x4 x;", kInvalidPositionTypeForVSErrorMessage, false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithInvalidFloatVectorType) { - runCodeTest( - getVertexPositionTypeTestShader( - "", "float3 x;", kInvalidPositionTypeForVSErrorMessage, false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithInvalidInnerStructType) { - runCodeTest(getVertexPositionTypeTestShader( - R"( -struct InvalidType { - float3 x; -};)", - "InvalidType x;", kInvalidPositionTypeForVSErrorMessage, - false), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithValidInnerStructType) { - runCodeTest(getVertexPositionTypeTestShader(R"( -struct validType { - float4 x; -};)", - "validType x;", R"( -// CHECK: %validType = OpTypeStruct %v4float -// CHECK: %output = OpTypeStruct %validType -)", - false)); -} -TEST_F(FileTest, PositionInVSWithValidFloatType) { - runCodeTest(getVertexPositionTypeTestShader("", "float4 x;", R"( -// CHECK: %output = OpTypeStruct %v4float -)", - false)); -} -TEST_F(FileTest, PositionInVSWithValidMin10Float4Type) { - runCodeTest(getVertexPositionTypeTestShader("", "min10float4 x;", R"( -// CHECK: %output = OpTypeStruct %v4float -)", - false)); -} -TEST_F(FileTest, PositionInVSWithValidMin16Float4Type) { - runCodeTest(getVertexPositionTypeTestShader("", "min16float4 x;", R"( -// CHECK: %output = OpTypeStruct %v4float -)", - false)); -} -TEST_F(FileTest, PositionInVSWithValidHalf4Type) { - runCodeTest(getVertexPositionTypeTestShader("", "half4 x;", R"( -// CHECK: %output = OpTypeStruct %v4float -)", - false)); -} -TEST_F(FileTest, PositionInVSWithInvalidHalf4Type) { - runCodeTest(getVertexPositionTypeTestShader( - "", "half4 x;", kInvalidPositionTypeForVSErrorMessage, true), - Expect::Failure); -} -TEST_F(FileTest, PositionInVSWithInvalidMin10Float4Type) { - runCodeTest( - getVertexPositionTypeTestShader( - "", "min10float4 x;", kInvalidPositionTypeForVSErrorMessage, true), - Expect::Failure); -} -TEST_F(FileTest, SourceCodeWithoutFilePath) { - const std::string command(R"(// RUN: %dxc -T ps_6_0 -E PSMain -Zi)"); - const std::string code = command + R"( -float4 PSMain(float4 color : COLOR) : SV_TARGET { return color; } -// CHECK: float4 PSMain(float4 color : COLOR) : SV_TARGET { return color; } -)"; - runCodeTest(code); -} - -} // namespace diff --git a/tools/clang/unittests/SPIRV/FileTestFixture.cpp b/tools/clang/unittests/SPIRV/FileTestFixture.cpp deleted file mode 100644 index 7ff56a434d..0000000000 --- a/tools/clang/unittests/SPIRV/FileTestFixture.cpp +++ /dev/null @@ -1,207 +0,0 @@ -//===- FileTestFixture.cpp ------------- File Test Fixture Implementation -===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "FileTestFixture.h" - -#include - -#include "FileTestUtils.h" -#include "effcee/effcee.h" - -namespace clang { -namespace spirv { - -bool FileTest::parseInputFile() { - std::stringstream inputSS; - std::ifstream inputFile; - inputFile.exceptions(std::ifstream::failbit); - - try { - inputFile.open(inputFilePath); - inputSS << inputFile.rdbuf(); - } catch (...) { - fprintf( - stderr, - "Error: Exception occurred while opening/reading the input file %s\n", - inputFilePath.c_str()); - return false; - } - - // Close the input file. - inputFile.close(); - checkCommands = inputSS.str(); - return parseCommand(); -} - -bool FileTest::parseCommand() { - // Effcee skips any input line which doesn't have a CHECK directive, therefore - // we can pass the entire input to effcee. This way, any warning/error message - // provided by effcee also reflects the correct line number in the input file. - const char hlslStartLabel[] = "// RUN:"; - const auto runCmdStartPos = checkCommands.find(hlslStartLabel); - if (runCmdStartPos != std::string::npos) { - const auto runCmdEndPos = checkCommands.find('\n', runCmdStartPos); - const auto runCommand = checkCommands.substr(runCmdStartPos, runCmdEndPos); - if (!utils::processRunCommandArgs(runCommand, &targetProfile, &entryPoint, - &targetEnv, &restArgs)) { - // An error has occured when parsing the Run command. - return false; - } - } else { - fprintf(stderr, "Error: Missing \"RUN:\" command.\n"); - return false; - } - - // Everything was successful. - return true; -} - -void FileTest::runFileTest(llvm::StringRef filename, Expect expect) { - bool runValidation = true; - if (beforeHLSLLegalization) - assert(runValidation); - - inputFilePath = utils::getAbsPathOfInputDataFile(filename); - - // Parse the input file. - ASSERT_TRUE(parseInputFile()); - - // Feed the HLSL source into the Compiler. - std::string errorMessages; - const bool compileOk = utils::compileFileWithSpirvGeneration( - inputFilePath, entryPoint, targetProfile, restArgs, &generatedBinary, - &errorMessages); - - checkTestResult(filename, compileOk, errorMessages, expect, runValidation); -} - -void FileTest::runCodeTest(llvm::StringRef code, Expect expect, - bool runValidation) { - if (beforeHLSLLegalization) - assert(runValidation); - - inputFilePath = "(Inlined HLSL code)"; - - checkCommands = code; - ASSERT_TRUE(parseCommand()); - - // Feed the HLSL source into the Compiler. - std::string errorMessages; - const bool compileOk = utils::compileCodeWithSpirvGeneration( - inputFilePath, code, entryPoint, targetProfile, restArgs, - &generatedBinary, &errorMessages); - - checkTestResult(inputFilePath, compileOk, errorMessages, expect, - runValidation); -} - -void FileTest::checkTestResult(llvm::StringRef filename, const bool compileOk, - const std::string &errorMessages, Expect expect, - bool runValidation) { - effcee::Result result(effcee::Result::Status::Ok); - - if (expect == Expect::Success) { - ASSERT_TRUE(compileOk); - - // Disassemble the generated SPIR-V binary. - ASSERT_TRUE( - utils::disassembleSpirvBinary(generatedBinary, &generatedSpirvAsm, - true /* generateHeader */, targetEnv)); - - auto options = effcee::Options() - .SetChecksName(filename.str()) - .SetInputName(""); - - // Run CHECK commands via effcee on disassembly. - result = effcee::Match(generatedSpirvAsm, checkCommands, options); - - // Print effcee's error message (if any). - if (result.status() != effcee::Result::Status::Ok) { - fprintf(stderr, "%s\n", result.message().c_str()); - } - - // All checks must have passed. - ASSERT_EQ(result.status(), effcee::Result::Status::Ok); - - // HLSL Change: Explicit braces - if (runValidation) { - EXPECT_TRUE(utils::validateSpirvBinary(targetEnv, generatedBinary, - beforeHLSLLegalization, glLayout, - dxLayout, scalarLayout)); - } - } else if (expect == Expect::Warning) { - ASSERT_TRUE(compileOk); - - // Still check that we can disassemble the generated SPIR-V binary. - ASSERT_TRUE(utils::disassembleSpirvBinary( - generatedBinary, &generatedSpirvAsm, true /* generateHeader */)); - - auto options = effcee::Options() - .SetChecksName(filename.str()) - .SetInputName(""); - - // Run CHECK commands via effcee on warning messages. - result = effcee::Match(errorMessages, checkCommands, options); - - // Print effcee's error message (if any). - if (result.status() != effcee::Result::Status::Ok) { - fprintf(stderr, "%s\n", result.message().c_str()); - } - - // All checks must have passed. - ASSERT_EQ(result.status(), effcee::Result::Status::Ok); - - // HLSL Change: explicit braces - if (runValidation) { - EXPECT_TRUE(utils::validateSpirvBinary(targetEnv, generatedBinary, - beforeHLSLLegalization, glLayout, - dxLayout, scalarLayout)); - } - } else if (expect == Expect::Failure) { - ASSERT_FALSE(compileOk); - - auto options = effcee::Options() - .SetChecksName(filename.str()) - .SetInputName(""); - - // Run CHECK commands via effcee on error messages. - result = effcee::Match(errorMessages, checkCommands, options); - - // Print effcee's error message (if any). - if (result.status() != effcee::Result::Status::Ok) { - fprintf(stderr, "%s\n", result.message().c_str()); - } - - // All checks must have passed. - ASSERT_EQ(result.status(), effcee::Result::Status::Ok); - } else { - ASSERT_TRUE(compileOk); - - // Disassemble the generated SPIR-V binary. - ASSERT_TRUE(utils::disassembleSpirvBinary( - generatedBinary, &generatedSpirvAsm, true /* generateHeader */)); - - std::string valMessages; - EXPECT_FALSE(utils::validateSpirvBinary( - targetEnv, generatedBinary, beforeHLSLLegalization, glLayout, dxLayout, - scalarLayout, &valMessages)); - auto options = effcee::Options() - .SetChecksName(filename.str()) - .SetInputName(""); - - // Run CHECK commands via effcee on error messages. - result = effcee::Match(valMessages, checkCommands, options); - - // All checks over validation message must have passed. - ASSERT_EQ(result.status(), effcee::Result::Status::Ok); - } -} - -} // end namespace spirv -} // end namespace clang diff --git a/tools/clang/unittests/SPIRV/FileTestFixture.h b/tools/clang/unittests/SPIRV/FileTestFixture.h deleted file mode 100644 index 242e94581d..0000000000 --- a/tools/clang/unittests/SPIRV/FileTestFixture.h +++ /dev/null @@ -1,81 +0,0 @@ -//===- FileTestFixute.h ---- Test Fixture for File Check style tests ------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNITTESTS_SPIRV_FILE_TEST_FIXTURE_H -#define LLVM_CLANG_UNITTESTS_SPIRV_FILE_TEST_FIXTURE_H - -#include "spirv-tools/libspirv.h" -#include "llvm/ADT/StringRef.h" -#include "gtest/gtest.h" - -namespace clang { -namespace spirv { - -class FileTest : public ::testing::Test { -public: - /// \brief Expected test result to be - enum class Expect { - Success, // Success (with or without warnings) - check disassembly - Warning, // Success (with warnings) - check warning message - Failure, // Failure (with errors) - check error message - ValFailure, // Validation failure (with errors) - check error message - }; - - FileTest() - : targetEnv(SPV_ENV_VULKAN_1_0), beforeHLSLLegalization(false), - glLayout(false), dxLayout(false), scalarLayout(false) {} - - void setBeforeHLSLLegalization() { beforeHLSLLegalization = true; } - - /// \brief Runs a test with the given input HLSL file. - /// - /// The first line of HLSL code must start with "// RUN:" and following DXC - /// arguments to run the test. Next lines must be proper HLSL code for the - /// test. It uses file check style output check e.g., "// CHECK: ...". - void runFileTest(llvm::StringRef path, Expect expect = Expect::Success); - - /// \brief Runs a test with the given HLSL code. - /// - /// The first line of code must start with "// RUN:" and following DXC - /// arguments to run the test. Next lines must be proper HLSL code for the - /// test. It uses file check style output check e.g., "// CHECK: ...". - void runCodeTest(llvm::StringRef code, Expect expect = Expect::Success, - bool runValidation = true); - -private: - /// \brief Reads in the given input file and parses the command to get - /// arguments to run DXC. - bool parseInputFile(); - /// \brief Parses the command and gets arguments to run DXC. - bool parseCommand(); - /// \brief Checks the compile result. Reports whether the expected compile - /// result matches the actual result and whether the expected validation - /// result matches the actual one or not. - void checkTestResult(llvm::StringRef filename, const bool compileOk, - const std::string &errorMessages, Expect expect, - bool runValidation); - - std::string targetProfile; ///< Target profile (argument of -T) - std::string entryPoint; ///< Entry point name (argument of -E) - std::vector restArgs; ///< All the other arguments - std::string inputFilePath; ///< Path to the input test file - std::vector generatedBinary; ///< The generated SPIR-V Binary - std::string checkCommands; ///< CHECK commands that verify output - std::string generatedSpirvAsm; ///< Disassembled binary (SPIR-V code) - spv_target_env targetEnv; ///< Environment to validate against - bool beforeHLSLLegalization; - bool glLayout; - bool dxLayout; - bool scalarLayout; -}; - -} // end namespace spirv -} // end namespace clang - -#endif diff --git a/tools/clang/unittests/SPIRV/FileTestUtils.cpp b/tools/clang/unittests/SPIRV/FileTestUtils.cpp deleted file mode 100644 index a43fdb216c..0000000000 --- a/tools/clang/unittests/SPIRV/FileTestUtils.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//===- FileTestUtils.cpp ---- Implementation of FileTestUtils -------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "FileTestUtils.h" - -#include -#include - -#include "dxc/Support/HLSLOptions.h" - -#include "SpirvTestOptions.h" -#include "gtest/gtest.h" - -namespace clang { -namespace spirv { -namespace utils { - -bool disassembleSpirvBinary(std::vector &binary, - std::string *generatedSpirvAsm, bool generateHeader, - spv_target_env target_env) { - spvtools::SpirvTools spirvTools(target_env); - spirvTools.SetMessageConsumer( - [](spv_message_level_t, const char *, const spv_position_t &, - const char *message) { fprintf(stdout, "%s\n", message); }); - uint32_t options = SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES; - if (!generateHeader) - options |= SPV_BINARY_TO_TEXT_OPTION_NO_HEADER; - return spirvTools.Disassemble(binary, generatedSpirvAsm, options); -} - -bool validateSpirvBinary(spv_target_env env, std::vector &binary, - bool beforeHlslLegalization, bool glLayout, - bool dxLayout, bool scalarLayout, - std::string *message) { - spvtools::ValidatorOptions options; - options.SetBeforeHlslLegalization(beforeHlslLegalization); - if (dxLayout || scalarLayout) { - options.SetScalarBlockLayout(true); - } else if (glLayout) { - // The default for spirv-val. - } else { - options.SetRelaxBlockLayout(true); - } - spvtools::SpirvTools spirvTools(env); - spirvTools.SetMessageConsumer([message](spv_message_level_t, const char *, - const spv_position_t &, - const char *msg) { - if (message) - *message = msg; - else - fprintf(stdout, "%s\n", msg); - }); - return spirvTools.Validate(binary.data(), binary.size(), options); -} - -bool processRunCommandArgs(const llvm::StringRef runCommandLine, - std::string *targetProfile, std::string *entryPoint, - spv_target_env *targetEnv, - std::vector *restArgs) { - std::istringstream buf(runCommandLine); - std::istream_iterator start(buf), end; - std::vector tokens(start, end); - if (tokens.size() < 3 || tokens[1].find("RUN") == std::string::npos || - tokens[2].find("%dxc") == std::string::npos) { - fprintf(stderr, "The only supported format is: \"// RUN: %%dxc -T " - " -E \"\n"); - return false; - } - - std::ostringstream rest; - for (uint32_t i = 3; i < tokens.size(); ++i) { - if (tokens[i] == "-T" && (++i) < tokens.size()) { - *targetProfile = tokens[i]; - } else if (tokens[i] == "-E" && (++i) < tokens.size()) { - *entryPoint = tokens[i]; - } else if (tokens[i].substr(0, 17) == "-fspv-target-env=") { - std::string targetEnvStr = tokens[i].substr(17); - if (targetEnvStr == "vulkan1.0") - *targetEnv = SPV_ENV_VULKAN_1_0; - else if (targetEnvStr == "vulkan1.1") - *targetEnv = SPV_ENV_VULKAN_1_1; - else if (targetEnvStr == "vulkan1.1spirv1.4") - *targetEnv = SPV_ENV_VULKAN_1_1_SPIRV_1_4; - else if (targetEnvStr == "vulkan1.2") - *targetEnv = SPV_ENV_VULKAN_1_2; - else if (targetEnvStr == "vulkan1.3") - *targetEnv = SPV_ENV_UNIVERSAL_1_6; - else if (targetEnvStr == "universal1.5") - *targetEnv = SPV_ENV_UNIVERSAL_1_5; - else { - fprintf(stderr, "Error: Found unknown target environment.\n"); - return false; - } - // Also push target environment to restArgs so that it gets passed to the - // compile command. - restArgs->push_back(tokens[i]); - } else { - restArgs->push_back(tokens[i]); - } - } - - if (targetProfile->empty()) { - fprintf(stderr, "Error: Missing target profile argument (-T).\n"); - return false; - } - // lib_6_* profile doesn't need an entryPoint - if (targetProfile->c_str()[0] != 'l' && entryPoint->empty()) { - fprintf(stderr, "Error: Missing entry point argument (-E).\n"); - return false; - } - return true; -} - -void convertIDxcBlobToUint32(const CComPtr &blob, - std::vector *binaryWords) { - size_t num32BitWords = (blob->GetBufferSize() + 3) / 4; - std::string binaryStr((char *)blob->GetBufferPointer(), - blob->GetBufferSize()); - binaryStr.resize(num32BitWords * 4, 0); - binaryWords->resize(num32BitWords, 0); - memcpy(binaryWords->data(), binaryStr.data(), binaryStr.size()); -} - -std::string getAbsPathOfInputDataFile(const llvm::StringRef filename) { - - std::string path = clang::spirv::testOptions::inputDataDir; - -#ifdef _WIN32 - const char sep = '\\'; - std::replace(path.begin(), path.end(), '/', '\\'); -#else - const char sep = '/'; -#endif - - if (path[path.size() - 1] != sep) { - path = path + sep; - } - path += filename; - return path; -} - -bool compileFileWithSpirvGeneration(const llvm::StringRef inputFilePath, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages) { - return compileWithSpirvGeneration({inputFilePath, ""}, entryPoint, - targetProfile, restArgs, generatedBinary, - errorMessages); -} - -bool compileCodeWithSpirvGeneration(const llvm::StringRef inputFilePath, - const llvm::StringRef code, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages) { - return compileWithSpirvGeneration({inputFilePath, code}, entryPoint, - targetProfile, restArgs, generatedBinary, - errorMessages); -} - -bool compileWithSpirvGeneration(const SourceCodeInfo &srcInfo, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages) { - std::wstring srcFile(srcInfo.inputFilePath.begin(), - srcInfo.inputFilePath.end()); - std::wstring entry(entryPoint.begin(), entryPoint.end()); - std::wstring profile(targetProfile.begin(), targetProfile.end()); - - std::vector rest; - for (const auto &arg : restArgs) - rest.emplace_back(arg.begin(), arg.end()); - - bool success = true; - - try { - dxc::DxcDllSupport dllSupport; - IFT(dllSupport.Initialize()); - - if (hlsl::options::initHlslOptTable()) - throw std::bad_alloc(); - - CComPtr pLibrary; - CComPtr pCompiler; - CComPtr pResult; - CComPtr pErrorBuffer; - CComPtr pCompiledBlob; - CComPtr pIncludeHandler; - HRESULT resultStatus; - - bool requires_opt = false; - for (const auto &arg : rest) - if (arg == L"-O3" || arg == L"-O0" || arg.substr(0, 8) == L"-Oconfig") - requires_opt = true; - - std::vector flags; - // lib_6_* profile doesn't need an entryPoint - if (profile.c_str()[0] != 'l') { - flags.push_back(L"-E"); - flags.push_back(entry.c_str()); - } - flags.push_back(L"-T"); - flags.push_back(profile.c_str()); - flags.push_back(L"-spirv"); - // Disable legalization and optimization for testing, unless the caller - // wants to run a specific optimization recipe (with -Oconfig). - if (!requires_opt) - flags.push_back(L"-fcgl"); - // Disable validation. We'll run it manually. - flags.push_back(L"-Vd"); - for (const auto &arg : rest) - flags.push_back(arg.c_str()); - - IFT(dllSupport.CreateInstance(CLSID_DxcLibrary, &pLibrary)); - - CComPtr pSource; - if (srcInfo.code.empty()) { - IFT(pLibrary->CreateBlobFromFile(srcFile.c_str(), nullptr, &pSource)); - } else { - IFT(pLibrary->CreateBlobWithEncodingOnHeapCopy( - srcInfo.code.data(), static_cast(srcInfo.code.size()), - CP_UTF8, &pSource)); - } - - IFT(pLibrary->CreateIncludeHandler(&pIncludeHandler)); - IFT(dllSupport.CreateInstance(CLSID_DxcCompiler, &pCompiler)); - IFT(pCompiler->Compile(pSource, srcFile.c_str(), entry.c_str(), - profile.c_str(), flags.data(), flags.size(), nullptr, - 0, pIncludeHandler, &pResult)); - - // Compilation is done. We can clean up the HlslOptTable. - hlsl::options::cleanupHlslOptTable(); - - // Get compilation results. - IFT(pResult->GetStatus(&resultStatus)); - - // Get diagnostics string. - IFT(pResult->GetErrorBuffer(&pErrorBuffer)); - const std::string diagnostics((char *)pErrorBuffer->GetBufferPointer(), - pErrorBuffer->GetBufferSize()); - *errorMessages = diagnostics; - - if (SUCCEEDED(resultStatus)) { - CComPtr pStdErr; - IFT(pResult->GetResult(&pCompiledBlob)); - convertIDxcBlobToUint32(pCompiledBlob, generatedBinary); - success = true; - } else { - success = false; - } - } catch (...) { - // An exception has occured while running the compiler with SPIR-V - // Generation - success = false; - } - - return success; -} - -} // end namespace utils -} // end namespace spirv -} // end namespace clang diff --git a/tools/clang/unittests/SPIRV/FileTestUtils.h b/tools/clang/unittests/SPIRV/FileTestUtils.h deleted file mode 100644 index f2dbb05b7a..0000000000 --- a/tools/clang/unittests/SPIRV/FileTestUtils.h +++ /dev/null @@ -1,104 +0,0 @@ -//===- FileTestUtils.h ---- Utilities For Running File Tests --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_UNITTESTS_SPIRV_FILETESTUTILS_H -#define LLVM_CLANG_UNITTESTS_SPIRV_FILETESTUTILS_H - -#include -#include - -#include "dxc/Support/Global.h" -#include "dxc/Support/WinIncludes.h" -#include "dxc/Support/dxcapi.use.h" -#include "spirv-tools/libspirv.hpp" -#include "llvm/ADT/StringRef.h" - -namespace clang { -namespace spirv { -namespace utils { - -/// \brief Passes the given SPIR-V binary to SPIR-V tools disassembler. The -/// SPIR-V assembly is returned via 'generatedSpirvAsm' argument. -/// Returns true on success, and false on failure. -bool disassembleSpirvBinary(std::vector &binary, - std::string *generatedSpirvAsm, - bool generateHeader = false, - spv_target_env = SPV_ENV_VULKAN_1_1); - -/// \brief Runs the SPIR-V Tools validation on the given SPIR-V binary. -/// Returns true if validation is successful; false otherwise. -bool validateSpirvBinary(spv_target_env, std::vector &binary, - bool beforeHlslLegalization, bool glLayout, - bool dxLayout, bool scalarLayout, - std::string *message = nullptr); - -/// \brief Parses the Target Profile, Entry Point, and Target Environment from -/// the Run command returns the target profile, entry point, target environment, -/// and the rest via arguments. Returns true on success, and false otherwise. -bool processRunCommandArgs(const llvm::StringRef runCommandLine, - std::string *targetProfile, std::string *entryPoint, - spv_target_env *targetEnv, - std::vector *restArgs); - -/// \brief Converts an IDxcBlob into a vector of 32-bit unsigned integers which -/// is returned via the 'binaryWords' argument. -void convertIDxcBlobToUint32(const CComPtr &blob, - std::vector *binaryWords); - -/// \brief Returns the absolute path to the input file of the test. -/// The input file is expected to be located in the directory given by the -/// testOptions::inputDataDir -std::string getAbsPathOfInputDataFile(const llvm::StringRef filename); - -/// \brief Passes the HLSL input file to the DXC compiler with SPIR-V CodeGen. -/// Returns the generated SPIR-V binary via 'generatedBinary' argument. -/// Returns true on success, and false on failure. Writes error messages to -/// errorMessages and stderr on failure. -bool compileFileWithSpirvGeneration(const llvm::StringRef inputFilePath, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages); - -/// \brief Passes the string HLSL code to the DXC compiler with SPIR-V CodeGen. -/// Returns the generated SPIR-V binary via 'generatedBinary' argument. -/// Returns true on success, and false on failure. Writes error messages to -/// errorMessages and stderr on failure. -bool compileCodeWithSpirvGeneration(const llvm::StringRef inputFilePath, - const llvm::StringRef code, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages); - -/// \brief A struct to keep the input file path and HLSL code information. -struct SourceCodeInfo { - const llvm::StringRef inputFilePath; - const llvm::StringRef code; -}; - -/// \brief Passes the HLSL source information to the DXC compiler with SPIR-V -/// CodeGen. Returns the generated SPIR-V binary via 'generatedBinary' argument. -/// Returns true on success, and false on failure. Writes error messages to -/// errorMessages and stderr on failure. If srcInfo.code is an empty string, it -/// reads the HLSL input from srcInfo.inputFilePath file. -bool compileWithSpirvGeneration(const SourceCodeInfo &srcInfo, - const llvm::StringRef entryPoint, - const llvm::StringRef targetProfile, - const std::vector &restArgs, - std::vector *generatedBinary, - std::string *errorMessages); - -} // end namespace utils -} // end namespace spirv -} // end namespace clang - -#endif