mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-28 16:48:45 +08:00
feat(zebin): add support for build options section
This change: * Adds support for build options section in zebinary - using build options in binary when rebuilding. * Appends "-cl-intel-allow-zebin" flag to build options when zebin is used. Resolves: NEO-6916 Signed-off-by: Krystian Chmielewski <krystian.chmielewski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
0d82216f43
commit
e007ba499f
@@ -8,6 +8,7 @@
|
||||
#include "shared/source/device_binary_format/device_binary_formats.h"
|
||||
#include "shared/source/device_binary_format/elf/elf.h"
|
||||
#include "shared/source/device_binary_format/elf/zebin_elf.h"
|
||||
#include "shared/source/helpers/ptr_math.h"
|
||||
#include "shared/source/helpers/string.h"
|
||||
#include "shared/source/program/program_info.h"
|
||||
#include "shared/test/common/test_macros/test.h"
|
||||
@@ -54,7 +55,7 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenUnhandledElfTypeThenUnpackingFails) {
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Unhandled elf type", unpackErrors.c_str());
|
||||
EXPECT_STREQ("Unhandled elf type\n", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, WhenValidBinaryAndMatchedWithRequestedTargetDeviceThenReturnSelf) {
|
||||
@@ -125,7 +126,8 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenValidBinaryForDifferentDeviceThenUnpacki
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
EXPECT_STREQ("Unhandled target device\n", unpackErrors.c_str());
|
||||
unpackErrors.clear();
|
||||
|
||||
zebin.machine = static_cast<decltype(zebin.machine)>(IGFX_GEN9_CORE);
|
||||
NEO::Elf::ZebinTargetFlags targetFlags;
|
||||
@@ -144,7 +146,7 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenValidBinaryForDifferentDeviceThenUnpacki
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
EXPECT_STREQ("Unhandled target device\n", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, WhenValidBinaryWithUnsupportedPointerSizeThenUnpackingFails) {
|
||||
@@ -169,7 +171,7 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenValidBinaryWithUnsupportedPointerSizeThe
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
EXPECT_STREQ("Unhandled target device\n", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, WhenNotRequestedThenDontValidateDeviceRevision) {
|
||||
@@ -245,7 +247,8 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenRequestedThenValidateRevision) {
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
EXPECT_STREQ("Unhandled target device\n", unpackErrors.c_str());
|
||||
unpackErrors.clear();
|
||||
|
||||
targetDevice.stepping = 8U;
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<const uint8_t>::fromAny(&zebin, 1U), "", targetDevice, unpackErrors, unpackWarnings);
|
||||
@@ -259,9 +262,9 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenRequestedThenValidateRevision) {
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
|
||||
EXPECT_STREQ("Unhandled target device\n", unpackErrors.c_str());
|
||||
unpackErrors.clear();
|
||||
|
||||
targetDevice.stepping = 5U;
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(ArrayRef<const uint8_t>::fromAny(&zebin, 1U), "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Zebin, unpackResult.format);
|
||||
@@ -359,11 +362,52 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenMachineIsIntelGTAndIntelGTNoteSectionIsV
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, WhenZebinIsNotValidForTargetAndHasSPIRVThenSetIRAndBuildOptions) {
|
||||
TEST(UnpackSingleDeviceBinaryZebin, GivenZebinWithSpirvAndBuildOptionsThenUnpackThemProperly) {
|
||||
ZebinTestData::ValidEmptyProgram zebin;
|
||||
const uint8_t spirvData[30] = {0xd};
|
||||
zebin.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, spirvData);
|
||||
|
||||
NEO::ConstStringRef buildOptions = "-cl-kernel-arg-info -cl-fast-relaxed-math";
|
||||
zebin.appendSection(NEO::Elf::SHT_ZEBIN_MISC, NEO::Elf::SectionsNamesZebin::buildOptions,
|
||||
{reinterpret_cast<const uint8_t *>(buildOptions.data()), buildOptions.size()});
|
||||
|
||||
auto elfHdrs = reinterpret_cast<NEO::Elf::ElfSectionHeader<NEO::Elf::EI_CLASS_64> *>(
|
||||
ptrOffset(zebin.storage.data(), static_cast<size_t>(zebin.elfHeader->shOff)));
|
||||
auto spirvHdr = elfHdrs[3];
|
||||
auto buildOptionsHdr = elfHdrs[4];
|
||||
ASSERT_EQ(NEO::Elf::SHT_ZEBIN_SPIRV, spirvHdr.type);
|
||||
ASSERT_EQ(NEO::Elf::SHT_ZEBIN_MISC, buildOptionsHdr.type);
|
||||
|
||||
zebin.elfHeader->type = NEO::Elf::ET_ZEBIN_EXE;
|
||||
zebin.elfHeader->machine = IGFX_SKYLAKE;
|
||||
NEO::TargetDevice targetDevice = {};
|
||||
targetDevice.productFamily = static_cast<PRODUCT_FAMILY>(zebin.elfHeader->machine);
|
||||
targetDevice.maxPointerSizeInBytes = 8;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(zebin.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Zebin, unpackResult.format);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
|
||||
EXPECT_FALSE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_EQ(zebin.storage.data(), unpackResult.deviceBinary.begin());
|
||||
|
||||
EXPECT_FALSE(unpackResult.buildOptions.empty());
|
||||
auto buildOptionsPtr = reinterpret_cast<const char *>(ptrOffset(zebin.storage.data(), static_cast<size_t>(buildOptionsHdr.offset)));
|
||||
EXPECT_EQ(buildOptionsPtr, unpackResult.buildOptions.begin());
|
||||
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
auto spirvPtr = ptrOffset(zebin.storage.data(), static_cast<size_t>(spirvHdr.offset));
|
||||
EXPECT_EQ(spirvPtr, unpackResult.intermediateRepresentation.begin());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, GivenZebinForDifferentTargetDeviceWithIntermediateRepresentationThenDeviceBinaryIsEmptyIrIsSetAndWarningAboutRebuildIsReturned) {
|
||||
ZebinTestData::ValidEmptyProgram zebin;
|
||||
const uint8_t spirvData[30] = {0xd};
|
||||
auto spirvHdr = zebin.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, spirvData);
|
||||
|
||||
zebin.elfHeader->type = NEO::Elf::ET_ZEBIN_EXE;
|
||||
zebin.elfHeader->machine = IGFX_UNKNOWN;
|
||||
|
||||
@@ -375,9 +419,34 @@ TEST(UnpackSingleDeviceBinaryZebin, WhenZebinIsNotValidForTargetAndHasSPIRVThenS
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(zebin.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Zebin, unpackResult.format);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_STREQ("Invalid target device. Rebuilding from intermediate representation.\n", unpackWarnings.c_str());
|
||||
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(0, memcmp(spirvData, unpackResult.intermediateRepresentation.begin(), sizeof(spirvData)));
|
||||
EXPECT_STREQ(NEO::CompilerOptions::allowZebin.begin(), unpackResult.buildOptions.begin());
|
||||
auto spirvPtr = ptrOffset(zebin.storage.data(), static_cast<size_t>(spirvHdr.offset));
|
||||
EXPECT_EQ(spirvPtr, unpackResult.intermediateRepresentation.begin());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryZebin, GivenMiscZebinSectionWithNameDifferentThanBuildOptionsThenItIsIgnored) {
|
||||
ZebinTestData::ValidEmptyProgram zebin;
|
||||
uint8_t secData;
|
||||
zebin.appendSection(NEO::Elf::SHT_ZEBIN_MISC, "not_build_options", ArrayRef<uint8_t>{&secData, 1U});
|
||||
|
||||
zebin.elfHeader->type = NEO::Elf::ET_ZEBIN_EXE;
|
||||
zebin.elfHeader->machine = IGFX_SKYLAKE;
|
||||
NEO::TargetDevice targetDevice = {};
|
||||
targetDevice.productFamily = static_cast<PRODUCT_FAMILY>(zebin.elfHeader->machine);
|
||||
targetDevice.maxPointerSizeInBytes = 8;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Zebin>(zebin.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Zebin, unpackResult.format);
|
||||
EXPECT_TRUE(unpackErrors.empty()) << unpackErrors;
|
||||
EXPECT_TRUE(unpackWarnings.empty()) << unpackWarnings;
|
||||
|
||||
EXPECT_FALSE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_EQ(zebin.storage.data(), unpackResult.deviceBinary.begin());
|
||||
}
|
||||
|
||||
@@ -93,6 +93,7 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) {
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_SPIRV, NEO::Elf::SectionsNamesZebin::spv, std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_GTPIN_INFO, NEO::Elf::SectionsNamesZebin::gtpinInfo, std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_VISA_ASM, NEO::Elf::SectionsNamesZebin::vIsaAsmPrefix.str() + "someKernel", std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_MISC, NEO::Elf::SectionsNamesZebin::buildOptions, std::string{});
|
||||
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_REL, NEO::Elf::SpecialSectionNames::relPrefix.str() + "someKernel", std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_RELA, NEO::Elf::SpecialSectionNames::relaPrefix.str() + "someKernel", std::string{});
|
||||
@@ -117,6 +118,7 @@ TEST(ExtractZebinSections, GivenKnownSectionsThenCapturesThemProperly) {
|
||||
ASSERT_EQ(1U, sections.zeInfoSections.size());
|
||||
ASSERT_EQ(1U, sections.symtabSections.size());
|
||||
ASSERT_EQ(1U, sections.spirvSections.size());
|
||||
ASSERT_EQ(1U, sections.buildOptionsSection.size());
|
||||
|
||||
auto stringSection = decodedElf.sectionHeaders[decodedElf.elfFileHeader->shStrNdx];
|
||||
const char *strings = stringSection.data.toArrayRef<const char>().begin();
|
||||
@@ -153,6 +155,29 @@ TEST(ExtractZebinSections, GivenMispelledConstDataSectionThenAllowItButEmitError
|
||||
EXPECT_STREQ(".data.global_const", strings + sections.constDataSections[0]->header->name);
|
||||
}
|
||||
|
||||
TEST(ExtractZebinSections, GivenUnknownMiscSectionThenEmitWarning) {
|
||||
NEO::Elf::ElfEncoder<> elfEncoder;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "someKernel", std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_SYMTAB, NEO::Elf::SectionsNamesZebin::symtab, std::string{});
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, std::string{});
|
||||
ConstStringRef unknownMiscSectionName = "unknown_misc_section";
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_ZEBIN_MISC, unknownMiscSectionName, std::string{});
|
||||
|
||||
auto encodedElf = elfEncoder.encode();
|
||||
std::string elfDecodeErrors;
|
||||
std::string elfDecodeWarnings;
|
||||
auto decodedElf = NEO::Elf::decodeElf(encodedElf, elfDecodeErrors, elfDecodeWarnings);
|
||||
|
||||
NEO::ZebinSections sections;
|
||||
std::string errors;
|
||||
std::string warnings;
|
||||
auto decodeError = NEO::extractZebinSections(decodedElf, sections, errors, warnings);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodeError);
|
||||
EXPECT_TRUE(errors.empty()) << errors;
|
||||
const auto expectedWarning = "DeviceBinaryFormat::Zebin : unhandled SHT_ZEBIN_MISC section : " + unknownMiscSectionName.str() + " currently supports only : " + NEO::Elf::SectionsNamesZebin::buildOptions.str() + ".\n";
|
||||
EXPECT_STREQ(expectedWarning.c_str(), warnings.c_str());
|
||||
}
|
||||
|
||||
TEST(ValidateZebinSectionsCount, GivenEmptyZebinThenReturnSuccess) {
|
||||
NEO::ZebinSections sections;
|
||||
std::string errors;
|
||||
|
||||
Reference in New Issue
Block a user