diff --git a/opencl/test/unit_test/program/process_elf_binary_tests.cpp b/opencl/test/unit_test/program/process_elf_binary_tests.cpp index 89c402a07f..8286b6ed0a 100644 --- a/opencl/test/unit_test/program/process_elf_binary_tests.cpp +++ b/opencl/test/unit_test/program/process_elf_binary_tests.cpp @@ -5,6 +5,7 @@ * */ +#include "shared/source/compiler_interface/intermediate_representations.h" #include "shared/source/device/device.h" #include "shared/source/device_binary_format/elf/elf.h" #include "shared/source/device_binary_format/elf/elf_decoder.h" @@ -13,11 +14,13 @@ #include "shared/source/helpers/string.h" #include "shared/test/common/helpers/test_files.h" #include "shared/test/common/mocks/mock_device.h" +#include "shared/test/common/mocks/mock_elf.h" #include "shared/test/unit_test/device_binary_format/patchtokens_tests.h" #include "shared/test/unit_test/helpers/gtest_helpers.h" #include "opencl/test/unit_test/mocks/mock_cl_device.h" #include "opencl/test/unit_test/mocks/mock_program.h" +#include "opencl/test/unit_test/test_files/patch_list.h" #include "compiler_options.h" #include "gtest/gtest.h" @@ -26,6 +29,52 @@ using namespace NEO; +enum class enabledIrFormat { + NONE, + ENABLE_SPIRV, + ENABLE_LLVM +}; + +template +struct MockElfBinaryPatchtokens { + MockElfBinaryPatchtokens(const HardwareInfo &hwInfo) : MockElfBinaryPatchtokens(std::string{}, hwInfo){}; + MockElfBinaryPatchtokens(const std::string &buildOptions, const HardwareInfo &hwInfo) { + mockDevBinaryHeader.Device = hwInfo.platform.eRenderCoreFamily; + mockDevBinaryHeader.GPUPointerSizeInBytes = sizeof(void *); + mockDevBinaryHeader.Version = iOpenCL::CURRENT_ICBE_VERSION; + constexpr size_t mockDevBinaryDataSize = sizeof(mockDevBinaryHeader) + mockDataSize; + constexpr size_t mockSpirvBinaryDataSize = sizeof(spirvMagic) + mockDataSize; + constexpr size_t mockLlvmBinaryDataSize = sizeof(llvmBcMagic) + mockDataSize; + + char mockDevBinaryData[mockDevBinaryDataSize]; + memcpy_s(mockDevBinaryData, mockDevBinaryDataSize, &mockDevBinaryHeader, sizeof(mockDevBinaryHeader)); + memset(mockDevBinaryData + sizeof(mockDevBinaryHeader), '\x01', mockDataSize); + + char mockSpirvBinaryData[mockSpirvBinaryDataSize]; + memcpy_s(mockSpirvBinaryData, mockSpirvBinaryDataSize, spirvMagic.data(), spirvMagic.size()); + memset(mockSpirvBinaryData + spirvMagic.size(), '\x02', mockDataSize); + + char mockLlvmBinaryData[mockLlvmBinaryDataSize]; + memcpy_s(mockLlvmBinaryData, mockLlvmBinaryDataSize, llvmBcMagic.data(), llvmBcMagic.size()); + memset(mockLlvmBinaryData + llvmBcMagic.size(), '\x03', mockDataSize); + + Elf::ElfEncoder enc; + enc.getElfFileHeader().identity = Elf::ElfFileHeaderIdentity(Elf::EI_CLASS_64); + enc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE; + enc.appendSection(Elf::SHT_OPENCL_DEV_BINARY, Elf::SectionNamesOpenCl::deviceBinary, ArrayRef::fromAny(mockDevBinaryData, mockDevBinaryDataSize)); + if (irFormat == enabledIrFormat::ENABLE_SPIRV) + enc.appendSection(Elf::SHT_OPENCL_SPIRV, Elf::SectionNamesOpenCl::spirvObject, ArrayRef::fromAny(mockSpirvBinaryData, mockSpirvBinaryDataSize)); + else if (irFormat == enabledIrFormat::ENABLE_LLVM) + enc.appendSection(Elf::SHT_OPENCL_LLVM_BINARY, Elf::SectionNamesOpenCl::llvmObject, ArrayRef::fromAny(mockLlvmBinaryData, mockLlvmBinaryDataSize)); + if (false == buildOptions.empty()) + enc.appendSection(Elf::SHT_OPENCL_OPTIONS, Elf::SectionNamesOpenCl::buildOptions, ArrayRef::fromAny(buildOptions.data(), buildOptions.size())); + storage = enc.encode(); + } + static constexpr size_t mockDataSize = 0x10; + SProgramBinaryHeader mockDevBinaryHeader = SProgramBinaryHeader{MAGIC_CL, 0, 0, 0, 0, 0, 0}; + std::vector storage; +}; + class ProcessElfBinaryTests : public ::testing::Test { public: void SetUp() override { @@ -52,15 +101,14 @@ TEST_F(ProcessElfBinaryTests, GivenInvalidBinaryWhenCreatingProgramFromBinaryThe } TEST_F(ProcessElfBinaryTests, GivenValidBinaryWhenCreatingProgramFromBinaryThenSuccessIsReturned) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin"); + auto mockElf = std::make_unique>(device->getHardwareInfo()); + auto pBinary = mockElf->storage; + auto binarySize = mockElf->storage.size(); - size_t binarySize = 0; - auto pBinary = loadDataFromFile(filePath.c_str(), binarySize); - cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); + cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device); EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); + EXPECT_EQ(0, memcmp(pBinary.data(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); } TEST_F(ProcessElfBinaryTests, GivenValidSpirBinaryWhenCreatingProgramFromBinaryThenSuccessIsReturned) { @@ -119,19 +167,17 @@ class ProcessElfBinaryTestsWithBinaryType : public ::testing::TestWithParam(MockDevice::createWithNewExecutionEnvironment(nullptr, rootDeviceIndex)); program = std::make_unique(nullptr, false, toClDeviceVector(*device)); } - std::unique_ptr program; std::unique_ptr device; const uint32_t rootDeviceIndex = 1; }; TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThenProgramIsProperlyResolved) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin"); + auto mockElf = std::make_unique>(device->getHardwareInfo()); + auto pBinary = mockElf->storage; + auto binarySize = mockElf->storage.size(); - size_t binarySize = 0; - auto pBinary = loadDataFromFile(filePath.c_str(), binarySize); - cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); + cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device); auto options = program->options; auto genBinary = makeCopy(program->buildInfos[rootDeviceIndex].unpackedDeviceBinary.get(), program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize); auto genBinarySize = program->buildInfos[rootDeviceIndex].unpackedDeviceBinarySize; @@ -140,7 +186,7 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe EXPECT_EQ(CL_SUCCESS, retVal); ASSERT_EQ(binarySize, program->buildInfos[rootDeviceIndex].packedDeviceBinarySize); - EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); + EXPECT_EQ(0, memcmp(pBinary.data(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); // delete program's elf reference to force a resolve program->buildInfos[rootDeviceIndex].packedDeviceBinary.reset(); @@ -178,7 +224,6 @@ TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThe ASSERT_EQ(options.size(), decodedOptions.size()); ASSERT_EQ(genBinarySize, decodedDeviceBinary.size()); ASSERT_EQ(irBinarySize, decodedIr.size()); - EXPECT_EQ(0, memcmp(genBinary.get(), decodedDeviceBinary.begin(), genBinarySize)); EXPECT_EQ(0, memcmp(irBinary.get(), decodedIr.begin(), irBinarySize)); } @@ -187,34 +232,12 @@ INSTANTIATE_TEST_CASE_P(ResolveBinaryTests, ProcessElfBinaryTestsWithBinaryType, ::testing::ValuesIn(BinaryTypeValues)); -TEST_F(ProcessElfBinaryTests, GivenMultipleCallsWhenCreatingProgramFromBinaryThenEachProgramIsCorrect) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd16_", ".bin"); - - size_t binarySize = 0; - auto pBinary = loadDataFromFile(filePath.c_str(), binarySize); - cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); - - EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); - - std::string filePath2; - retrieveBinaryKernelFilename(filePath2, "simple_arg_int_", ".bin"); - - pBinary = loadDataFromFile(filePath2.c_str(), binarySize); - retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); - - EXPECT_EQ(CL_SUCCESS, retVal); - EXPECT_EQ(0, memcmp(pBinary.get(), program->buildInfos[rootDeviceIndex].packedDeviceBinary.get(), binarySize)); -} - TEST_F(ProcessElfBinaryTests, GivenEmptyBuildOptionsWhenCreatingProgramFromBinaryThenSuccessIsReturned) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "simple_kernels_", ".bin"); + auto mockElf = std::make_unique>(device->getHardwareInfo()); + auto pBinary = mockElf->storage; + auto binarySize = mockElf->storage.size(); - size_t binarySize = 0; - auto pBinary = loadDataFromFile(filePath.c_str(), binarySize); - cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); + cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device); EXPECT_EQ(CL_SUCCESS, retVal); const auto &options = program->getOptions(); @@ -223,16 +246,15 @@ TEST_F(ProcessElfBinaryTests, GivenEmptyBuildOptionsWhenCreatingProgramFromBinar } TEST_F(ProcessElfBinaryTests, GivenNonEmptyBuildOptionsWhenCreatingProgramFromBinaryThenSuccessIsReturned) { - std::string filePath; - retrieveBinaryKernelFilename(filePath, "simple_kernels_opts_", ".bin"); + auto buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1"); + auto mockElf = std::make_unique>(buildOptionsNotEmpty, device->getHardwareInfo()); + auto pBinary = mockElf->storage; + auto binarySize = mockElf->storage.size(); - size_t binarySize = 0; - auto pBinary = loadDataFromFile(filePath.c_str(), binarySize); - cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize, *device); + cl_int retVal = program->createProgramFromBinary(pBinary.data(), binarySize, *device); EXPECT_EQ(CL_SUCCESS, retVal); const auto &options = program->getOptions(); - std::string buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1"); EXPECT_TRUE(hasSubstr(options, buildOptionsNotEmpty)); } @@ -256,4 +278,4 @@ TEST_F(ProcessElfBinaryTests, GivenBinaryWhenIncompatiblePatchtokenVerionThenPro cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size(), *device); EXPECT_EQ(CL_INVALID_BINARY, retVal); } -} +} \ No newline at end of file