mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-29 17:13:29 +08:00
Reorganization directory structure [3/n]
Change-Id: If3dfa3f6007f8810a6a1ae1a4f0c7da38544648d
This commit is contained in:
33
shared/source/device_binary_format/CMakeLists.txt
Normal file
33
shared/source/device_binary_format/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
#
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
set(NEO_DEVICE_BINARY_FORMAT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_decoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_encoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ar/ar_encoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ocl_elf.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_patchtokens.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_validator.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/ocl_elf.h
|
||||
)
|
||||
|
||||
set_property(GLOBAL PROPERTY NEO_DEVICE_BINARY_FORMAT ${NEO_DEVICE_BINARY_FORMAT})
|
||||
37
shared/source/device_binary_format/ar/ar.h
Normal file
37
shared/source/device_binary_format/ar/ar.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utilities/const_stringref.h"
|
||||
|
||||
namespace NEO {
|
||||
namespace Ar {
|
||||
|
||||
static constexpr ConstStringRef arMagic = "!<arch>\n";
|
||||
static constexpr ConstStringRef arFileEntryTrailingMagic = "\x60\x0A";
|
||||
|
||||
struct ArFileEntryHeader {
|
||||
char identifier[16] = {'/', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
|
||||
char fileModificationTimestamp[12] = {'0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
|
||||
char ownerId[6] = {'0', ' ', ' ', ' ', ' ', ' '};
|
||||
char groupId[6] = {'0', ' ', ' ', ' ', ' ', ' '};
|
||||
char fileMode[8] = {'6', '4', '4', ' ', ' ', ' ', ' ', ' '};
|
||||
char fileSizeInBytes[10] = {'0', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '};
|
||||
char trailingMagic[2] = {arFileEntryTrailingMagic[0], arFileEntryTrailingMagic[1]};
|
||||
};
|
||||
static_assert(60U == sizeof(ArFileEntryHeader), "");
|
||||
|
||||
namespace SpecialFileNames {
|
||||
static constexpr ConstStringRef longFileNamesFile = "//";
|
||||
static const char longFileNamePrefix = '/';
|
||||
static const char fileNameTerminator = '/';
|
||||
} // namespace SpecialFileNames
|
||||
|
||||
} // namespace Ar
|
||||
|
||||
} // namespace NEO
|
||||
71
shared/source/device_binary_format/ar/ar_decoder.cpp
Normal file
71
shared/source/device_binary_format/ar/ar_decoder.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/ar/ar_decoder.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace NEO {
|
||||
namespace Ar {
|
||||
|
||||
Ar decodeAr(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarnings) {
|
||||
if (false == isAr(binary)) {
|
||||
outErrReason = "Not an AR archive - mismatched file signature";
|
||||
return {};
|
||||
}
|
||||
|
||||
Ar ret;
|
||||
ret.magic = reinterpret_cast<const char *>(binary.begin());
|
||||
|
||||
const uint8_t *decodePos = binary.begin() + arMagic.size();
|
||||
while (decodePos + sizeof(ArFileEntryHeader) <= binary.end()) {
|
||||
auto fileEntryHeader = reinterpret_cast<const ArFileEntryHeader *>(decodePos);
|
||||
auto fileEntryDataPos = decodePos + sizeof(ArFileEntryHeader);
|
||||
uint64_t fileSize = readDecimal<sizeof(fileEntryHeader->fileSizeInBytes)>(fileEntryHeader->fileSizeInBytes);
|
||||
if (fileSize + (fileEntryDataPos - binary.begin()) > binary.size()) {
|
||||
outErrReason = "Corrupt AR archive - out of bounds data of file entry with idenfitier '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (ConstStringRef(fileEntryHeader->trailingMagic) != arFileEntryTrailingMagic) {
|
||||
outWarnings.append("File entry header with identifier '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "' has invalid header trailing string");
|
||||
}
|
||||
|
||||
ArFileEntryHeaderAndData fileEntry = {};
|
||||
fileEntry.fileName = readUnpaddedString<sizeof(fileEntryHeader->identifier)>(fileEntryHeader->identifier);
|
||||
fileEntry.fullHeader = fileEntryHeader;
|
||||
fileEntry.fileData = ArrayRef<const uint8_t>(fileEntryDataPos, static_cast<size_t>(fileSize));
|
||||
|
||||
if (fileEntry.fileName.empty()) {
|
||||
if (SpecialFileNames::longFileNamesFile == ConstStringRef(fileEntryHeader->identifier, 2U)) {
|
||||
fileEntry.fileName = SpecialFileNames::longFileNamesFile;
|
||||
ret.longFileNamesEntry = fileEntry;
|
||||
} else {
|
||||
outErrReason = "Corrupt AR archive - file entry does not have identifier : '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'";
|
||||
return {};
|
||||
}
|
||||
} else {
|
||||
if (SpecialFileNames::longFileNamePrefix == fileEntry.fileName[0]) {
|
||||
auto longFileNamePos = readDecimal<sizeof(fileEntryHeader->identifier) - 1>(fileEntryHeader->identifier + 1);
|
||||
fileEntry.fileName = readLongFileName(ConstStringRef(reinterpret_cast<const char *>(ret.longFileNamesEntry.fileData.begin()), ret.longFileNamesEntry.fileData.size()), static_cast<size_t>(longFileNamePos));
|
||||
if (fileEntry.fileName.empty()) {
|
||||
outErrReason = "Corrupt AR archive - long file name entry has broken identifier : '" + std::string(fileEntryHeader->identifier, sizeof(fileEntryHeader->identifier)) + "'";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
ret.files.push_back(fileEntry);
|
||||
}
|
||||
|
||||
decodePos = fileEntryDataPos + fileSize;
|
||||
decodePos += fileSize & 1U; // implicit 2-byte alignment
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Ar
|
||||
|
||||
} // namespace NEO
|
||||
86
shared/source/device_binary_format/ar/ar_decoder.h
Normal file
86
shared/source/device_binary_format/ar/ar_decoder.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "compiler_interface/intermediate_representations.h"
|
||||
#include "device_binary_format/ar/ar.h"
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/stackvec.h"
|
||||
|
||||
namespace NEO {
|
||||
namespace Ar {
|
||||
|
||||
struct ArFileEntryHeaderAndData {
|
||||
ConstStringRef fileName;
|
||||
ArrayRef<const uint8_t> fileData;
|
||||
|
||||
const ArFileEntryHeader *fullHeader = nullptr;
|
||||
};
|
||||
|
||||
struct Ar {
|
||||
const char *magic = nullptr;
|
||||
StackVec<ArFileEntryHeaderAndData, 32> files;
|
||||
ArFileEntryHeaderAndData longFileNamesEntry;
|
||||
};
|
||||
|
||||
inline bool isAr(const ArrayRef<const uint8_t> binary) {
|
||||
return NEO::hasSameMagic(arMagic, binary);
|
||||
}
|
||||
|
||||
template <uint32_t MaxLength>
|
||||
inline uint64_t readDecimal(const char *decimalAsString) {
|
||||
uint64_t ret = 0U;
|
||||
for (uint32_t i = 0; i < MaxLength; ++i) {
|
||||
if (('\0' == decimalAsString[i]) || (' ' == decimalAsString[i])) {
|
||||
break;
|
||||
}
|
||||
ret = ret * 10 + (decimalAsString[i] - '0');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
inline bool isStringPadding(char character) {
|
||||
switch (character) {
|
||||
default:
|
||||
return false;
|
||||
case ' ':
|
||||
return true;
|
||||
case '\0':
|
||||
return true;
|
||||
case '/':
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <uint32_t MaxLength>
|
||||
inline ConstStringRef readUnpaddedString(const char *paddedString) {
|
||||
uint32_t unpaddedSize = MaxLength - 1;
|
||||
for (; unpaddedSize > 0U; --unpaddedSize) {
|
||||
if (false == isStringPadding(paddedString[unpaddedSize])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (false == isStringPadding(paddedString[unpaddedSize])) {
|
||||
++unpaddedSize;
|
||||
}
|
||||
return ConstStringRef(paddedString, unpaddedSize);
|
||||
}
|
||||
|
||||
inline ConstStringRef readLongFileName(ConstStringRef longFileNamesSection, size_t offset) {
|
||||
size_t end = offset;
|
||||
while ((end < longFileNamesSection.size()) && (longFileNamesSection[end] != SpecialFileNames::fileNameTerminator)) {
|
||||
++end;
|
||||
}
|
||||
return ConstStringRef(longFileNamesSection.begin() + offset, end - offset);
|
||||
}
|
||||
|
||||
Ar decodeAr(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarnings);
|
||||
|
||||
} // namespace Ar
|
||||
|
||||
} // namespace NEO
|
||||
64
shared/source/device_binary_format/ar/ar_encoder.cpp
Normal file
64
shared/source/device_binary_format/ar/ar_encoder.cpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/ar/ar_encoder.h"
|
||||
|
||||
#include "helpers/debug_helpers.h"
|
||||
#include "helpers/string.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
namespace Ar {
|
||||
|
||||
ArFileEntryHeader *ArEncoder::appendFileEntry(const ConstStringRef fileName, const ArrayRef<const uint8_t> fileData) {
|
||||
if (fileName.size() > sizeof(ArFileEntryHeader::identifier) - 1) {
|
||||
return nullptr; // encoding long identifiers is not supported
|
||||
}
|
||||
if (fileName.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto alignedFileSize = fileData.size() + (fileData.size() & 1U);
|
||||
ArFileEntryHeader header = {};
|
||||
|
||||
if (padTo8Bytes && (0 != ((fileEntries.size() + sizeof(ArFileEntryHeader)) % 8))) {
|
||||
ArFileEntryHeader paddingHeader = {};
|
||||
auto paddingName = "pad_" + std::to_string(paddingEntry++);
|
||||
UNRECOVERABLE_IF(paddingName.length() > sizeof(paddingHeader.identifier));
|
||||
memcpy_s(paddingHeader.identifier, sizeof(paddingHeader.identifier), paddingName.c_str(), paddingName.size());
|
||||
paddingHeader.identifier[paddingName.size()] = SpecialFileNames::fileNameTerminator;
|
||||
size_t paddingSize = 8U - ((fileEntries.size() + 2 * sizeof(ArFileEntryHeader)) % 8);
|
||||
auto padSizeString = std::to_string(paddingSize);
|
||||
memcpy_s(paddingHeader.fileSizeInBytes, sizeof(paddingHeader.fileSizeInBytes), padSizeString.c_str(), padSizeString.size());
|
||||
this->fileEntries.reserve(this->fileEntries.size() + sizeof(paddingHeader) + paddingSize + sizeof(header) + alignedFileSize);
|
||||
this->fileEntries.insert(this->fileEntries.end(), reinterpret_cast<uint8_t *>(&paddingHeader), reinterpret_cast<uint8_t *>(&paddingHeader + 1));
|
||||
this->fileEntries.resize(this->fileEntries.size() + paddingSize, ' ');
|
||||
}
|
||||
|
||||
memcpy_s(header.identifier, sizeof(header.identifier), fileName.begin(), fileName.size());
|
||||
header.identifier[fileName.size()] = SpecialFileNames::fileNameTerminator;
|
||||
auto sizeString = std::to_string(fileData.size());
|
||||
UNRECOVERABLE_IF(sizeString.length() > sizeof(header.fileSizeInBytes));
|
||||
memcpy_s(header.fileSizeInBytes, sizeof(header.fileSizeInBytes), sizeString.c_str(), sizeString.size());
|
||||
this->fileEntries.reserve(this->fileEntries.size() + sizeof(header) + alignedFileSize);
|
||||
auto newFileHeaderOffset = this->fileEntries.size();
|
||||
this->fileEntries.insert(this->fileEntries.end(), reinterpret_cast<uint8_t *>(&header), reinterpret_cast<uint8_t *>(&header + 1));
|
||||
this->fileEntries.insert(this->fileEntries.end(), fileData.begin(), fileData.end());
|
||||
this->fileEntries.resize(this->fileEntries.size() + alignedFileSize - fileData.size(), 0U); // implicit 2-byte alignment
|
||||
return reinterpret_cast<ArFileEntryHeader *>(this->fileEntries.data() + newFileHeaderOffset);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ArEncoder::encode() const {
|
||||
std::vector<uint8_t> ret;
|
||||
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(arMagic.begin()), reinterpret_cast<const uint8_t *>(arMagic.end()));
|
||||
ret.insert(ret.end(), this->fileEntries.begin(), this->fileEntries.end());
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace Ar
|
||||
} // namespace NEO
|
||||
33
shared/source/device_binary_format/ar/ar_encoder.h
Normal file
33
shared/source/device_binary_format/ar/ar_encoder.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device_binary_format/ar/ar.h"
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/const_stringref.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
namespace Ar {
|
||||
|
||||
struct ArEncoder {
|
||||
ArEncoder(bool padTo8Bytes = false) : padTo8Bytes(padTo8Bytes) {}
|
||||
ArFileEntryHeader *appendFileEntry(const ConstStringRef fileName, const ArrayRef<const uint8_t> fileData);
|
||||
std::vector<uint8_t> encode() const;
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> fileEntries;
|
||||
bool padTo8Bytes = false;
|
||||
uint32_t paddingEntry = 0U;
|
||||
};
|
||||
|
||||
} // namespace Ar
|
||||
|
||||
} // namespace NEO
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/ar/ar.h"
|
||||
#include "device_binary_format/ar/ar_decoder.h"
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t> binary) {
|
||||
return NEO::Ar::isAr(binary);
|
||||
}
|
||||
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
|
||||
std::string &outErrReason, std::string &outWarning) {
|
||||
auto archiveData = NEO::Ar::decodeAr(archive, outErrReason, outWarning);
|
||||
if (nullptr == archiveData.magic) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string pointerSize = ((requestedTargetDevice.maxPointerSizeInBytes == 8) ? "64" : "32");
|
||||
std::string filterPointerSizeAndPlatform = pointerSize + "." + requestedProductAbbreviation.str();
|
||||
std::string filterPointerSizeAndPlatformAndStepping = filterPointerSizeAndPlatform + "." + std::to_string(requestedTargetDevice.stepping);
|
||||
|
||||
Ar::ArFileEntryHeaderAndData *matchedFiles[2] = {};
|
||||
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndPlatformAndStepping = matchedFiles[0]; // best match
|
||||
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndPlatform = matchedFiles[1];
|
||||
for (auto &f : archiveData.files) {
|
||||
if (ConstStringRef(f.fileName.begin(), filterPointerSizeAndPlatform.size()) != filterPointerSizeAndPlatform) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ConstStringRef(f.fileName.begin(), filterPointerSizeAndPlatformAndStepping.size()) != filterPointerSizeAndPlatformAndStepping) {
|
||||
matchedPointerSizeAndPlatform = &f;
|
||||
continue;
|
||||
}
|
||||
matchedPointerSizeAndPlatformAndStepping = &f;
|
||||
}
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
for (auto matchedFile : matchedFiles) {
|
||||
if (nullptr == matchedFile) {
|
||||
continue;
|
||||
}
|
||||
auto unpacked = unpackSingleDeviceBinary(matchedFile->fileData, requestedProductAbbreviation, requestedTargetDevice, unpackErrors, unpackWarnings);
|
||||
if (false == unpacked.deviceBinary.empty()) {
|
||||
if (matchedFile != matchedPointerSizeAndPlatformAndStepping) {
|
||||
outWarning = "Couldn't find perfectly matched binary (right stepping) in AR, using best usable";
|
||||
}
|
||||
return unpacked;
|
||||
}
|
||||
}
|
||||
|
||||
outErrReason = "Couldn't find matching binary in AR archive";
|
||||
return {};
|
||||
}
|
||||
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Archive>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
|
||||
// packed binary format
|
||||
outErrReason = "Device binary format is packed";
|
||||
return DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "compiler_interface/intermediate_representations.h"
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
#include "device_binary_format/elf/elf_decoder.h"
|
||||
#include "device_binary_format/elf/elf_encoder.h"
|
||||
#include "device_binary_format/elf/ocl_elf.h"
|
||||
#include "utilities/compiler_support.h"
|
||||
|
||||
#include <tuple>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t> binary) {
|
||||
auto header = Elf::decodeElfFileHeader<Elf::EI_CLASS_64>(binary);
|
||||
if (nullptr == header) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (header->type) {
|
||||
default:
|
||||
return false;
|
||||
case Elf::ET_OPENCL_EXECUTABLE:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case Elf::ET_OPENCL_LIBRARY:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case Elf::ET_OPENCL_OBJECTS:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
|
||||
std::string &outErrReason, std::string &outWarning) {
|
||||
auto elf = Elf::decodeElf<Elf::EI_CLASS_64>(archive, outErrReason, outWarning);
|
||||
if (nullptr == elf.elfFileHeader) {
|
||||
return {};
|
||||
}
|
||||
|
||||
SingleDeviceBinary ret;
|
||||
switch (elf.elfFileHeader->type) {
|
||||
default:
|
||||
outErrReason = "Not OCL ELF file type";
|
||||
return {};
|
||||
|
||||
case Elf::ET_OPENCL_EXECUTABLE:
|
||||
ret.format = NEO::DeviceBinaryFormat::Patchtokens;
|
||||
break;
|
||||
|
||||
case Elf::ET_OPENCL_LIBRARY:
|
||||
ret.format = NEO::DeviceBinaryFormat::OclLibrary;
|
||||
break;
|
||||
|
||||
case Elf::ET_OPENCL_OBJECTS:
|
||||
ret.format = NEO::DeviceBinaryFormat::OclCompiledObject;
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto &elfSectionHeader : elf.sectionHeaders) {
|
||||
auto sectionData = elfSectionHeader.data;
|
||||
switch (elfSectionHeader.header->type) {
|
||||
case Elf::SHT_OPENCL_SPIRV:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case Elf::SHT_OPENCL_LLVM_BINARY:
|
||||
ret.intermediateRepresentation = sectionData;
|
||||
break;
|
||||
|
||||
case Elf::SHT_OPENCL_DEV_BINARY:
|
||||
ret.deviceBinary = sectionData;
|
||||
break;
|
||||
|
||||
case Elf::SHT_OPENCL_OPTIONS:
|
||||
ret.buildOptions = ConstStringRef(reinterpret_cast<const char *>(sectionData.begin()), sectionData.size());
|
||||
break;
|
||||
|
||||
case Elf::SHT_OPENCL_DEV_DEBUG:
|
||||
ret.debugData = sectionData;
|
||||
break;
|
||||
|
||||
case Elf::SHT_STRTAB:
|
||||
// ignoring intentionally - identifying sections by types
|
||||
continue;
|
||||
|
||||
case Elf::SHT_NULL:
|
||||
// ignoring intentionally, inactive section, probably UNDEF
|
||||
continue;
|
||||
|
||||
default:
|
||||
outErrReason = "Unhandled ELF section";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (NEO::DeviceBinaryFormat::Patchtokens != ret.format) {
|
||||
ret.deviceBinary.clear();
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (false == ret.deviceBinary.empty()) {
|
||||
auto unpackedOclDevBin = unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(ret.deviceBinary, requestedProductAbbreviation, requestedTargetDevice,
|
||||
outErrReason, outWarning);
|
||||
if (unpackedOclDevBin.deviceBinary.empty()) {
|
||||
ret.deviceBinary.clear();
|
||||
ret.debugData.clear();
|
||||
} else {
|
||||
ret.targetDevice = unpackedOclDevBin.targetDevice;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
|
||||
// packed binary format
|
||||
outErrReason = "Device binary format is packed";
|
||||
return DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
template <>
|
||||
std::vector<uint8_t> packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning) {
|
||||
using namespace NEO::Elf;
|
||||
NEO::Elf::ElfEncoder<EI_CLASS_64> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = ET_OPENCL_EXECUTABLE;
|
||||
if (binary.buildOptions.empty() == false) {
|
||||
elfEncoder.appendSection(SHT_OPENCL_OPTIONS, SectionNamesOpenCl::buildOptions,
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.buildOptions.data()), binary.buildOptions.size()));
|
||||
}
|
||||
|
||||
if (binary.intermediateRepresentation.empty() == false) {
|
||||
if (NEO::isSpirVBitcode(binary.intermediateRepresentation)) {
|
||||
elfEncoder.appendSection(SHT_OPENCL_SPIRV, SectionNamesOpenCl::spirvObject, binary.intermediateRepresentation);
|
||||
} else if (NEO::isLlvmBitcode(binary.intermediateRepresentation)) {
|
||||
elfEncoder.appendSection(SHT_OPENCL_LLVM_BINARY, SectionNamesOpenCl::llvmObject, binary.intermediateRepresentation);
|
||||
} else {
|
||||
outErrReason = "Unknown intermediate representation format";
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
if (binary.debugData.empty() == false) {
|
||||
elfEncoder.appendSection(SHT_OPENCL_DEV_DEBUG, SectionNamesOpenCl::deviceDebug, binary.debugData);
|
||||
}
|
||||
|
||||
if (binary.deviceBinary.empty() == false) {
|
||||
elfEncoder.appendSection(SHT_OPENCL_DEV_BINARY, SectionNamesOpenCl::deviceBinary, binary.deviceBinary);
|
||||
}
|
||||
|
||||
return elfEncoder.encode();
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
#include "device_binary_format/patchtokens_decoder.h"
|
||||
#include "device_binary_format/patchtokens_dumper.h"
|
||||
#include "device_binary_format/patchtokens_validator.h"
|
||||
#include "helpers/debug_helpers.h"
|
||||
#include "program/program_info_from_patchtokens.h"
|
||||
#include "opencl/source/utilities/logger.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t> binary) {
|
||||
return NEO::PatchTokenBinary::isValidPatchTokenBinary(binary);
|
||||
}
|
||||
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
|
||||
std::string &outErrReason, std::string &outWarning) {
|
||||
auto programHeader = NEO::PatchTokenBinary::decodeProgramHeader(archive);
|
||||
if (nullptr == programHeader) {
|
||||
outErrReason = "Invalid program header";
|
||||
return {};
|
||||
}
|
||||
bool validForTarget = (requestedTargetDevice.coreFamily == static_cast<GFXCORE_FAMILY>(programHeader->Device));
|
||||
validForTarget &= (requestedTargetDevice.maxPointerSizeInBytes >= programHeader->GPUPointerSizeInBytes);
|
||||
validForTarget &= (iOpenCL::CURRENT_ICBE_VERSION == programHeader->Version);
|
||||
if (false == validForTarget) {
|
||||
outErrReason = "Unhandled target device";
|
||||
return {};
|
||||
}
|
||||
SingleDeviceBinary ret = {};
|
||||
ret.targetDevice = requestedTargetDevice;
|
||||
ret.format = NEO::DeviceBinaryFormat::Patchtokens;
|
||||
ret.deviceBinary = archive;
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram = {};
|
||||
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(src.deviceBinary, decodedProgram);
|
||||
DBG_LOG(LogPatchTokens, NEO::PatchTokenBinary::asString(decodedProgram).c_str());
|
||||
|
||||
std::string validatorWarnings;
|
||||
std::string validatorErrMessage;
|
||||
auto validatorErr = PatchTokenBinary::validate(decodedProgram, outErrReason, outWarning);
|
||||
if (DecodeError::Success != validatorErr) {
|
||||
return validatorErr;
|
||||
}
|
||||
|
||||
NEO::populateProgramInfo(dst, decodedProgram);
|
||||
|
||||
return DecodeError::Success;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
16
shared/source/device_binary_format/device_binary_formats.cpp
Normal file
16
shared/source/device_binary_format/device_binary_formats.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning) {
|
||||
return packDeviceBinary<DeviceBinaryFormat::OclElf>(binary, outErrReason, outWarning);
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
171
shared/source/device_binary_format/device_binary_formats.h
Normal file
171
shared/source/device_binary_format/device_binary_formats.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/const_stringref.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <igfxfmid.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace NEO {
|
||||
struct ProgramInfo;
|
||||
|
||||
enum class DeviceBinaryFormat : uint8_t {
|
||||
Unknown,
|
||||
OclElf,
|
||||
OclLibrary,
|
||||
OclCompiledObject,
|
||||
Patchtokens,
|
||||
Archive
|
||||
};
|
||||
|
||||
enum class DecodeError : uint8_t {
|
||||
Success,
|
||||
Undefined,
|
||||
InvalidBinary,
|
||||
UnhandledBinary
|
||||
};
|
||||
|
||||
inline const char *asString(DecodeError err) {
|
||||
switch (err) {
|
||||
default:
|
||||
return "with invalid binary";
|
||||
break;
|
||||
case DecodeError::UnhandledBinary:
|
||||
return "with unhandled binary";
|
||||
break;
|
||||
case DecodeError::Success:
|
||||
return "decoded successfully";
|
||||
break;
|
||||
case DecodeError::Undefined:
|
||||
return "in undefined status";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct TargetDevice {
|
||||
GFXCORE_FAMILY coreFamily = IGFX_UNKNOWN_CORE;
|
||||
uint32_t stepping = 0U;
|
||||
uint32_t maxPointerSizeInBytes = 4U;
|
||||
};
|
||||
|
||||
struct SingleDeviceBinary {
|
||||
DeviceBinaryFormat format = DeviceBinaryFormat::Unknown;
|
||||
ArrayRef<const uint8_t> deviceBinary;
|
||||
ArrayRef<const uint8_t> debugData;
|
||||
ArrayRef<const uint8_t> intermediateRepresentation;
|
||||
ConstStringRef buildOptions;
|
||||
TargetDevice targetDevice;
|
||||
};
|
||||
|
||||
template <DeviceBinaryFormat Format>
|
||||
bool isDeviceBinaryFormat(const ArrayRef<const uint8_t> binary);
|
||||
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>);
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>);
|
||||
template <>
|
||||
bool isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>);
|
||||
|
||||
inline bool isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
|
||||
return true;
|
||||
}
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(binary)) {
|
||||
return true;
|
||||
}
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <DeviceBinaryFormat Format>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
|
||||
std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
|
||||
template <>
|
||||
SingleDeviceBinary unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(const ArrayRef<const uint8_t>, const ConstStringRef, const TargetDevice &, std::string &, std::string &);
|
||||
|
||||
inline SingleDeviceBinary unpackSingleDeviceBinary(const ArrayRef<const uint8_t> archive, const ConstStringRef requestedProductAbbreviation, const TargetDevice &requestedTargetDevice,
|
||||
std::string &outErrReason, std::string &outWarning) {
|
||||
SingleDeviceBinary ret = {};
|
||||
ret.format = DeviceBinaryFormat::Unknown;
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(archive)) {
|
||||
return unpackSingleDeviceBinary<DeviceBinaryFormat::OclElf>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
|
||||
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(archive)) {
|
||||
return unpackSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
|
||||
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(archive)) {
|
||||
return unpackSingleDeviceBinary<DeviceBinaryFormat::Archive>(archive, requestedProductAbbreviation, requestedTargetDevice, outErrReason, outWarning);
|
||||
} else {
|
||||
outErrReason = "Unknown format";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <DeviceBinaryFormat Format>
|
||||
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
template <>
|
||||
std::vector<uint8_t> packDeviceBinary<DeviceBinaryFormat::OclElf>(const SingleDeviceBinary, std::string &, std::string &);
|
||||
|
||||
std::vector<uint8_t> packDeviceBinary(const SingleDeviceBinary binary, std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
inline bool isAnyPackedDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
|
||||
return true;
|
||||
}
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(binary)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isAnySingleDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
|
||||
return (false == isAnyPackedDeviceBinaryFormat(binary)) && isAnyDeviceBinaryFormat(binary);
|
||||
}
|
||||
|
||||
template <DeviceBinaryFormat Format>
|
||||
DecodeError decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning);
|
||||
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
|
||||
template <>
|
||||
DecodeError decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(ProgramInfo &, const SingleDeviceBinary &, std::string &, std::string &);
|
||||
|
||||
inline std::pair<DecodeError, DeviceBinaryFormat> decodeSingleDeviceBinary(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning) {
|
||||
std::pair<DecodeError, DeviceBinaryFormat> ret;
|
||||
ret.first = DecodeError::InvalidBinary;
|
||||
ret.second = DeviceBinaryFormat::Unknown;
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(src.deviceBinary)) {
|
||||
ret.second = DeviceBinaryFormat::OclElf;
|
||||
ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::OclElf>(dst, src, outErrReason, outWarning);
|
||||
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(src.deviceBinary)) {
|
||||
ret.second = DeviceBinaryFormat::Patchtokens;
|
||||
ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Patchtokens>(dst, src, outErrReason, outWarning);
|
||||
} else if (isDeviceBinaryFormat<DeviceBinaryFormat::Archive>(src.deviceBinary)) {
|
||||
ret.second = DeviceBinaryFormat::Archive;
|
||||
ret.first = decodeSingleDeviceBinary<DeviceBinaryFormat::Archive>(dst, src, outErrReason, outWarning);
|
||||
} else {
|
||||
outErrReason = "Unknown format";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
342
shared/source/device_binary_format/elf/elf.h
Normal file
342
shared/source/device_binary_format/elf/elf.h
Normal file
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "utilities/const_stringref.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
// Elf identifier class
|
||||
enum ELF_IDENTIFIER_CLASS : uint8_t {
|
||||
EI_CLASS_NONE = 0, // undefined
|
||||
EI_CLASS_32 = 1, // 32-bit elf file
|
||||
EI_CLASS_64 = 2, // 64-bit elf file
|
||||
};
|
||||
|
||||
// Elf identifier data
|
||||
enum ELF_IDENTIFIER_DATA : uint8_t {
|
||||
EI_DATA_NONE = 0, // undefined
|
||||
EI_DATA_LITTLE_ENDIAN = 1, // little-endian
|
||||
EI_DATA_BIG_ENDIAN = 2, // big-endian
|
||||
};
|
||||
|
||||
// Target machine
|
||||
enum ELF_MACHINE : uint16_t {
|
||||
EM_NONE = 0, // No specific instrution set
|
||||
};
|
||||
|
||||
// Elf version
|
||||
enum ELF_VERSION_ : uint8_t {
|
||||
EV_INVALID = 0, // undefined
|
||||
EV_CURRENT = 1, // current
|
||||
};
|
||||
|
||||
// Elf type
|
||||
enum ELF_TYPE : uint16_t {
|
||||
ET_NONE = 0, // undefined
|
||||
ET_REL = 1, // relocatable
|
||||
ET_EXEC = 2, // executable
|
||||
ET_DYN = 3, // shared object
|
||||
ET_CORE = 4, // core file
|
||||
ET_LOPROC = 0xff00, // start of processor-specific type
|
||||
ET_OPENCL_RESERVED_START = 0xff01, // start of Intel OCL ELF_TYPES
|
||||
ET_OPENCL_RESERVED_END = 0xff05, // end of Intel OCL ELF_TYPES
|
||||
ET_HIPROC = 0xffff // end of processor-specific types
|
||||
};
|
||||
|
||||
// Section header type
|
||||
enum SECTION_HEADER_TYPE : uint32_t {
|
||||
SHT_NULL = 0, // inactive section header
|
||||
SHT_PROGBITS = 1, // program data
|
||||
SHT_SYMTAB = 2, // symbol table
|
||||
SHT_STRTAB = 3, // string table
|
||||
SHT_RELA = 4, // relocation entries with add
|
||||
SHT_HASH = 5, // symbol hash table
|
||||
SHT_DYNAMIC = 6, // dynamic linking info
|
||||
SHT_NOTE = 7, // notes
|
||||
SHT_NOBITS = 8, // program "no data" space (bss)
|
||||
SHT_REL = 9, // relocation entries (without add)
|
||||
SHT_SHLIB = 10, // reserved
|
||||
SHT_DYNSYM = 11, // dynamic linker symbol table
|
||||
SHT_INIT_ARRAY = 14, // array of constructors
|
||||
SHT_FINI_ARRAY = 15, // array of destructors
|
||||
SHT_PREINIT_ARRAY = 16, // aaray of pre-constructors
|
||||
SHT_GROUP = 17, // section group
|
||||
SHT_SYMTAB_SHNDX = 18, // extended section indices
|
||||
SHT_NUM = 19, // number of defined types
|
||||
SHT_LOOS = 0x60000000, // start of os-specifc
|
||||
SHT_OPENCL_RESERVED_START = 0xff000000, // start of Intel OCL SHT_TYPES
|
||||
SHT_OPENCL_RESERVED_END = 0xff00000a // end of Intel OCL SHT_TYPES
|
||||
};
|
||||
|
||||
enum SPECIAL_SECTION_HEADER_NUMBER : uint16_t {
|
||||
SHN_UNDEF = 0U, // undef section
|
||||
};
|
||||
|
||||
enum SECTION_HEADER_FLAGS : uint32_t {
|
||||
SHF_NONE = 0x0, // no flags
|
||||
SHF_WRITE = 0x1, // writeable data
|
||||
SHF_ALLOC = 0x2, // occupies memory during execution
|
||||
SHF_EXECINSTR = 0x4, // executable machine instructions
|
||||
SHF_MERGE = 0x10, // data of section can be merged
|
||||
SHF_STRINGS = 0x20, // data of section is null-terminated strings
|
||||
SHF_INFO_LINK = 0x40, // section's sh_info is valid index
|
||||
SHF_LINK_ORDER = 0x80, // has ordering requirements
|
||||
SHF_OS_NONCONFORM = 0x100, // requires os-specific processing
|
||||
SHF_GROUP = 0x200, // section is part of section group
|
||||
SHF_TLS = 0x400, // thread-local storage
|
||||
SHF_MASKOS = 0x0ff00000, // operating-system-specific flags
|
||||
SHF_MASKPROC = 0xf0000000, // processor-specific flags
|
||||
};
|
||||
|
||||
enum PROGRAM_HEADER_TYPE {
|
||||
PT_NULL = 0x0, // unused segment
|
||||
PT_LOAD = 0x1, // loadable segment
|
||||
PT_DYNAMIC = 0x2, // dynamic linking information
|
||||
PT_INTERP = 0x3, // path name to invoke as an interpreter
|
||||
PT_NOTE = 0x4, // auxiliary information
|
||||
PT_SHLIB = 0x5, // reserved
|
||||
PT_PHDR = 0x6, // location and of programe header table
|
||||
PT_TLS = 0x7, // thread-local storage template
|
||||
PT_LOOS = 0x60000000, // start os-specifc segments
|
||||
PT_HIOS = 0x6FFFFFFF, // end of os-specific segments
|
||||
PT_LOPROC = 0x70000000, // start processor-specific segments
|
||||
PT_HIPROC = 0x7FFFFFFF // end processor-specific segments
|
||||
};
|
||||
|
||||
enum PROGRAM_HEADER_FLAGS : uint32_t {
|
||||
PF_NONE = 0x0, // all access denied
|
||||
PF_X = 0x1, // execute
|
||||
PF_W = 0x2, // write
|
||||
PF_R = 0x4, // read
|
||||
PF_MASKOS = 0x0ff00000, // operating-system-specific flags
|
||||
PF_MASKPROC = 0xf0000000 // processor-specific flags
|
||||
|
||||
};
|
||||
|
||||
constexpr const char elfMagic[4] = {0x7f, 'E', 'L', 'F'};
|
||||
|
||||
struct ElfFileHeaderIdentity {
|
||||
ElfFileHeaderIdentity(ELF_IDENTIFIER_CLASS classBits)
|
||||
: eClass(classBits) {
|
||||
}
|
||||
char magic[4] = {elfMagic[0], elfMagic[1], elfMagic[2], elfMagic[3]}; // should match elfMagic
|
||||
uint8_t eClass = EI_CLASS_NONE; // 32- or 64-bit format
|
||||
uint8_t data = EI_DATA_LITTLE_ENDIAN; // endianness
|
||||
uint8_t version = EV_CURRENT; // elf file version
|
||||
uint8_t osAbi = 0U; // target system
|
||||
uint8_t abiVersion = 0U; // abi
|
||||
char padding[7] = {}; // pad to 16 bytes
|
||||
};
|
||||
static_assert(sizeof(ElfFileHeaderIdentity) == 16, "");
|
||||
|
||||
template <int NumBits>
|
||||
struct ElfProgramHeaderTypes;
|
||||
|
||||
template <>
|
||||
struct ElfProgramHeaderTypes<EI_CLASS_32> {
|
||||
using Type = uint32_t;
|
||||
using Flags = uint32_t;
|
||||
using Offset = uint32_t;
|
||||
using VAddr = uint32_t;
|
||||
using PAddr = uint32_t;
|
||||
using FileSz = uint32_t;
|
||||
using MemSz = uint32_t;
|
||||
using Align = uint32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ElfProgramHeaderTypes<EI_CLASS_64> {
|
||||
using Type = uint32_t;
|
||||
using Flags = uint32_t;
|
||||
using Offset = uint64_t;
|
||||
using VAddr = uint64_t;
|
||||
using PAddr = uint64_t;
|
||||
using FileSz = uint64_t;
|
||||
using MemSz = uint64_t;
|
||||
using Align = uint64_t;
|
||||
};
|
||||
|
||||
template <int NumBits>
|
||||
struct ElfProgramHeader;
|
||||
|
||||
template <>
|
||||
struct ElfProgramHeader<EI_CLASS_32> {
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::Type type = PT_NULL; // type of segment
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::Offset offset = 0U; // absolute offset of segment data in file
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::VAddr vAddr = 0U; // VA of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::PAddr pAddr = 0U; // PA of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::FileSz fileSz = 0U; // size of segment in file
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::MemSz memSz = 0U; // size of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::Flags flags = PF_NONE; // segment-dependent flags
|
||||
ElfProgramHeaderTypes<EI_CLASS_32>::Align align = 1U; // alignment
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ElfProgramHeader<EI_CLASS_64> {
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::Type type = PT_NULL; // type of segment
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::Flags flags = PF_NONE; // segment-dependent flags
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::Offset offset = 0U; // absolute offset of segment data in file
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::VAddr vAddr = 0U; // VA of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::PAddr pAddr = 0U; // PA of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::FileSz fileSz = 0U; // size of segment in file
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::MemSz memSz = 0U; // size of segment in memory
|
||||
ElfProgramHeaderTypes<EI_CLASS_64>::Align align = 1U; // alignment
|
||||
};
|
||||
|
||||
static_assert(sizeof(ElfProgramHeader<EI_CLASS_32>) == 0x20, "");
|
||||
static_assert(sizeof(ElfProgramHeader<EI_CLASS_64>) == 0x38, "");
|
||||
|
||||
template <int NumBits>
|
||||
struct ElfSectionHeaderTypes;
|
||||
|
||||
template <>
|
||||
struct ElfSectionHeaderTypes<EI_CLASS_32> {
|
||||
using Name = uint32_t;
|
||||
using Type = uint32_t;
|
||||
using Flags = uint32_t;
|
||||
using Addr = uint32_t;
|
||||
using Offset = uint32_t;
|
||||
using Size = uint32_t;
|
||||
using Link = uint32_t;
|
||||
using Info = uint32_t;
|
||||
using AddrAlign = uint32_t;
|
||||
using EntSize = uint32_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ElfSectionHeaderTypes<EI_CLASS_64> {
|
||||
using Name = uint32_t;
|
||||
using Type = uint32_t;
|
||||
using Flags = uint64_t;
|
||||
using Addr = uint64_t;
|
||||
using Offset = uint64_t;
|
||||
using Size = uint64_t;
|
||||
using Link = uint32_t;
|
||||
using Info = uint32_t;
|
||||
using AddrAlign = uint64_t;
|
||||
using EntSize = uint64_t;
|
||||
};
|
||||
|
||||
template <int NumBits>
|
||||
struct ElfSectionHeader {
|
||||
typename ElfSectionHeaderTypes<NumBits>::Name name = 0U; // offset to string in string section names
|
||||
typename ElfSectionHeaderTypes<NumBits>::Type type = SHT_NULL; // section type
|
||||
typename ElfSectionHeaderTypes<NumBits>::Flags flags = SHF_NONE; // section flags
|
||||
typename ElfSectionHeaderTypes<NumBits>::Addr addr = 0U; // VA of section in memory
|
||||
typename ElfSectionHeaderTypes<NumBits>::Offset offset = 0U; // absolute offset of section data in file
|
||||
typename ElfSectionHeaderTypes<NumBits>::Size size = 0U; // size of section's data
|
||||
typename ElfSectionHeaderTypes<NumBits>::Link link = SHN_UNDEF; // index of associated section
|
||||
typename ElfSectionHeaderTypes<NumBits>::Info info = 0U; // extra information
|
||||
typename ElfSectionHeaderTypes<NumBits>::AddrAlign addralign = 0U; // section alignment
|
||||
typename ElfSectionHeaderTypes<NumBits>::EntSize entsize = 0U; // section's entries size
|
||||
};
|
||||
|
||||
static_assert(sizeof(ElfSectionHeader<EI_CLASS_32>) == 0x28, "");
|
||||
static_assert(sizeof(ElfSectionHeader<EI_CLASS_64>) == 0x40, "");
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
struct ElfFileHeaderTypes;
|
||||
|
||||
template <>
|
||||
struct ElfFileHeaderTypes<EI_CLASS_32> {
|
||||
using Type = uint16_t;
|
||||
using Machine = uint16_t;
|
||||
using Version = uint32_t;
|
||||
using Entry = uint32_t;
|
||||
using PhOff = uint32_t;
|
||||
using ShOff = uint32_t;
|
||||
using Flags = uint32_t;
|
||||
using EhSize = uint16_t;
|
||||
using PhEntSize = uint16_t;
|
||||
using PhNum = uint16_t;
|
||||
using ShEntSize = uint16_t;
|
||||
using ShNum = uint16_t;
|
||||
using ShStrNdx = uint16_t;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ElfFileHeaderTypes<EI_CLASS_64> {
|
||||
using Type = uint16_t;
|
||||
using Machine = uint16_t;
|
||||
using Version = uint32_t;
|
||||
using Entry = uint64_t;
|
||||
using PhOff = uint64_t;
|
||||
using ShOff = uint64_t;
|
||||
using Flags = uint32_t;
|
||||
using EhSize = uint16_t;
|
||||
using PhEntSize = uint16_t;
|
||||
using PhNum = uint16_t;
|
||||
using ShEntSize = uint16_t;
|
||||
using ShNum = uint16_t;
|
||||
using ShStrNdx = uint16_t;
|
||||
};
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
struct ElfFileHeader {
|
||||
ElfFileHeaderIdentity identity = ElfFileHeaderIdentity(NumBits); // elf file identity
|
||||
typename ElfFileHeaderTypes<NumBits>::Type type = ET_NONE; // elf file type
|
||||
typename ElfFileHeaderTypes<NumBits>::Machine machine = EM_NONE; // target machine
|
||||
typename ElfFileHeaderTypes<NumBits>::Version version = 1U; // elf file version
|
||||
typename ElfFileHeaderTypes<NumBits>::Entry entry = 0U; // entry point (start address)
|
||||
typename ElfFileHeaderTypes<NumBits>::PhOff phOff = 0U; // absolute offset to program header table in file
|
||||
typename ElfFileHeaderTypes<NumBits>::ShOff shOff = 0U; // absolute offset to section header table in file
|
||||
typename ElfFileHeaderTypes<NumBits>::Flags flags = 0U; // target-dependent flags
|
||||
typename ElfFileHeaderTypes<NumBits>::EhSize ehSize = sizeof(ElfFileHeader<NumBits>); // header size
|
||||
typename ElfFileHeaderTypes<NumBits>::PhEntSize phEntSize = sizeof(ElfProgramHeader<NumBits>); // size of entries in program header table
|
||||
typename ElfFileHeaderTypes<NumBits>::PhNum phNum = 0U; // number of entries in pogram header table
|
||||
typename ElfFileHeaderTypes<NumBits>::ShEntSize shEntSize = sizeof(ElfSectionHeader<NumBits>); // size of entries section header table
|
||||
typename ElfFileHeaderTypes<NumBits>::ShNum shNum = 0U; // number of entries in section header table
|
||||
typename ElfFileHeaderTypes<NumBits>::ShStrNdx shStrNdx = SHN_UNDEF; // index of section header table with section names
|
||||
};
|
||||
|
||||
static_assert(sizeof(ElfFileHeader<EI_CLASS_32>) == 0x34, "");
|
||||
static_assert(sizeof(ElfFileHeader<EI_CLASS_64>) == 0x40, "");
|
||||
|
||||
namespace SpecialSectionNames {
|
||||
static constexpr ConstStringRef bss = ".bss"; // uninitialized memory
|
||||
static constexpr ConstStringRef comment = ".comment"; // version control information
|
||||
static constexpr ConstStringRef data = ".data"; // initialized memory
|
||||
static constexpr ConstStringRef data1 = ".data1"; // initialized memory
|
||||
static constexpr ConstStringRef debug = ".debug"; // debug symbols
|
||||
static constexpr ConstStringRef dynamic = ".dynamic"; // dynamic linking information
|
||||
static constexpr ConstStringRef dynstr = ".dynstr"; // strings for dynamic linking
|
||||
static constexpr ConstStringRef dynsym = ".dynsym"; // dynamic linking symbol table
|
||||
static constexpr ConstStringRef fini = ".fini"; // executable instructions of program termination
|
||||
static constexpr ConstStringRef finiArray = ".fini_array"; // function pointers of termination array
|
||||
static constexpr ConstStringRef got = ".got"; // global offset table
|
||||
static constexpr ConstStringRef hash = ".hash"; // symnol hash table
|
||||
static constexpr ConstStringRef init = ".init"; // executable instructions of program initializaion
|
||||
static constexpr ConstStringRef initArray = ".init_array"; // function pointers of initialization array
|
||||
static constexpr ConstStringRef interp = ".interp"; // path name of program interpreter
|
||||
static constexpr ConstStringRef line = ".line"; // line number info for symbolic debugging
|
||||
static constexpr ConstStringRef note = ".note"; // note section
|
||||
static constexpr ConstStringRef plt = ".plt"; // procedure linkage table
|
||||
static constexpr ConstStringRef preinitArray = ".preinit_array"; // function pointers of pre-initialization array
|
||||
static constexpr ConstStringRef relPrefix = ".rel"; // prefix of .relNAME - relocations for NAME section
|
||||
static constexpr ConstStringRef relaPrefix = ".rela"; // prefix of .relaNAME - rela relocations for NAME section
|
||||
static constexpr ConstStringRef rodata = ".rodata"; // read-only data
|
||||
static constexpr ConstStringRef rodata1 = ".rodata1"; // read-only data
|
||||
static constexpr ConstStringRef shStrTab = ".shstrtab"; // section names (strings)
|
||||
static constexpr ConstStringRef strtab = ".strtab"; // strings
|
||||
static constexpr ConstStringRef symtab = ".symtab"; // symbol table
|
||||
static constexpr ConstStringRef symtabShndx = ".symtab_shndx"; // special symbol table section index array
|
||||
static constexpr ConstStringRef tbss = ".tbss"; // uninitialized thread-local data
|
||||
static constexpr ConstStringRef tadata = ".tdata"; // initialided thread-local data
|
||||
static constexpr ConstStringRef tdata1 = ".tdata1"; // initialided thread-local data
|
||||
static constexpr ConstStringRef text = ".text"; // executable instructions
|
||||
} // namespace SpecialSectionNames
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
89
shared/source/device_binary_format/elf/elf_decoder.cpp
Normal file
89
shared/source/device_binary_format/elf/elf_decoder.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/elf/elf_decoder.h"
|
||||
|
||||
#include "helpers/ptr_math.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
const ElfFileHeader<NumBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary) {
|
||||
if (binary.size() < sizeof(ElfFileHeader<NumBits>)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const ElfFileHeader<NumBits> *header = reinterpret_cast<const ElfFileHeader<NumBits> *>(binary.begin());
|
||||
bool validHeader = (header->identity.magic[0] == elfMagic[0]);
|
||||
validHeader &= (header->identity.magic[1] == elfMagic[1]);
|
||||
validHeader &= (header->identity.magic[2] == elfMagic[2]);
|
||||
validHeader &= (header->identity.magic[3] == elfMagic[3]);
|
||||
validHeader &= (header->identity.eClass == NumBits);
|
||||
|
||||
return validHeader ? header : nullptr;
|
||||
}
|
||||
|
||||
template const ElfFileHeader<EI_CLASS_32> *decodeElfFileHeader<EI_CLASS_32>(const ArrayRef<const uint8_t>);
|
||||
template const ElfFileHeader<EI_CLASS_64> *decodeElfFileHeader<EI_CLASS_64>(const ArrayRef<const uint8_t>);
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
Elf<NumBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarning) {
|
||||
Elf<NumBits> ret = {};
|
||||
ret.elfFileHeader = decodeElfFileHeader<NumBits>(binary);
|
||||
if (nullptr == ret.elfFileHeader) {
|
||||
outErrReason = "Invalid or missing ELF header";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (ret.elfFileHeader->phOff + ret.elfFileHeader->phNum * ret.elfFileHeader->phEntSize > binary.size()) {
|
||||
outErrReason = "Out of bounds program headers table";
|
||||
return {};
|
||||
}
|
||||
|
||||
if (ret.elfFileHeader->shOff + ret.elfFileHeader->shNum * ret.elfFileHeader->shEntSize > binary.size()) {
|
||||
outErrReason = "Out of bounds section headers table";
|
||||
return {};
|
||||
}
|
||||
|
||||
const ElfProgramHeader<NumBits> *programHeader = reinterpret_cast<const ElfProgramHeader<NumBits> *>(binary.begin() + ret.elfFileHeader->phOff);
|
||||
for (decltype(ret.elfFileHeader->phNum) i = 0; i < ret.elfFileHeader->phNum; ++i) {
|
||||
if (programHeader->offset + programHeader->fileSz > binary.size()) {
|
||||
outErrReason = "Out of bounds program header offset/filesz, program header idx : " + std::to_string(i);
|
||||
return {};
|
||||
}
|
||||
ArrayRef<const uint8_t> data(binary.begin() + programHeader->offset, static_cast<size_t>(programHeader->fileSz));
|
||||
ret.programHeaders.push_back({programHeader, data});
|
||||
programHeader = ptrOffset(programHeader, ret.elfFileHeader->phEntSize);
|
||||
}
|
||||
|
||||
const ElfSectionHeader<NumBits> *sectionHeader = reinterpret_cast<const ElfSectionHeader<NumBits> *>(binary.begin() + ret.elfFileHeader->shOff);
|
||||
for (decltype(ret.elfFileHeader->shNum) i = 0; i < ret.elfFileHeader->shNum; ++i) {
|
||||
ArrayRef<const uint8_t> data;
|
||||
if (SHT_NOBITS != sectionHeader->type) {
|
||||
if (sectionHeader->offset + sectionHeader->size > binary.size()) {
|
||||
outErrReason = "Out of bounds section header offset/size, section header idx : " + std::to_string(i);
|
||||
return {};
|
||||
}
|
||||
data = ArrayRef<const uint8_t>(binary.begin() + sectionHeader->offset, static_cast<size_t>(sectionHeader->size));
|
||||
}
|
||||
ret.sectionHeaders.push_back({sectionHeader, data});
|
||||
sectionHeader = ptrOffset(sectionHeader, ret.elfFileHeader->shEntSize);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template Elf<EI_CLASS_32> decodeElf<EI_CLASS_32>(const ArrayRef<const uint8_t>, std::string &, std::string &);
|
||||
template Elf<EI_CLASS_64> decodeElf<EI_CLASS_64>(const ArrayRef<const uint8_t>, std::string &, std::string &);
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
67
shared/source/device_binary_format/elf/elf_decoder.h
Normal file
67
shared/source/device_binary_format/elf/elf_decoder.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "device_binary_format/elf/elf.h"
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/const_stringref.h"
|
||||
#include "utilities/stackvec.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
|
||||
struct Elf {
|
||||
struct ProgramHeaderAndData {
|
||||
const ElfProgramHeader<NumBits> *header = nullptr;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
struct SectionHeaderAndData {
|
||||
const ElfSectionHeader<NumBits> *header;
|
||||
ArrayRef<const uint8_t> data;
|
||||
};
|
||||
|
||||
const ElfFileHeader<NumBits> *elfFileHeader = nullptr;
|
||||
StackVec<ProgramHeaderAndData, 32> programHeaders;
|
||||
StackVec<SectionHeaderAndData, 32> sectionHeaders;
|
||||
};
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
|
||||
const ElfFileHeader<NumBits> *decodeElfFileHeader(const ArrayRef<const uint8_t> binary);
|
||||
extern template const ElfFileHeader<EI_CLASS_32> *decodeElfFileHeader<EI_CLASS_32>(const ArrayRef<const uint8_t>);
|
||||
extern template const ElfFileHeader<EI_CLASS_64> *decodeElfFileHeader<EI_CLASS_64>(const ArrayRef<const uint8_t>);
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
|
||||
Elf<NumBits> decodeElf(const ArrayRef<const uint8_t> binary, std::string &outErrReason, std::string &outWarning);
|
||||
extern template Elf<EI_CLASS_32> decodeElf<EI_CLASS_32>(const ArrayRef<const uint8_t>, std::string &, std::string &);
|
||||
extern template Elf<EI_CLASS_64> decodeElf<EI_CLASS_64>(const ArrayRef<const uint8_t>, std::string &, std::string &);
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
inline bool isElf(const ArrayRef<const uint8_t> binary) {
|
||||
return (nullptr != decodeElfFileHeader<NumBits>(binary));
|
||||
}
|
||||
|
||||
inline bool isElf(const ArrayRef<const uint8_t> binary) {
|
||||
return isElf<EI_CLASS_32>(binary) || isElf<EI_CLASS_64>(binary);
|
||||
}
|
||||
|
||||
inline ELF_IDENTIFIER_CLASS getElfNumBits(const ArrayRef<const uint8_t> binary) {
|
||||
if (isElf<EI_CLASS_32>(binary)) {
|
||||
return EI_CLASS_32;
|
||||
} else if (isElf<EI_CLASS_64>(binary)) {
|
||||
return EI_CLASS_64;
|
||||
}
|
||||
return EI_CLASS_NONE;
|
||||
}
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
178
shared/source/device_binary_format/elf/elf_encoder.cpp
Normal file
178
shared/source/device_binary_format/elf/elf_encoder.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/elf/elf_encoder.h"
|
||||
|
||||
#include "utilities/range.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
ElfEncoder<NumBits>::ElfEncoder(bool addUndefSectionHeader, bool addHeaderSectionNamesSection, uint64_t defaultDataAlignemnt)
|
||||
: addUndefSectionHeader(addUndefSectionHeader), addHeaderSectionNamesSection(addHeaderSectionNamesSection), defaultDataAlignment(defaultDataAlignemnt) {
|
||||
// add special strings
|
||||
UNRECOVERABLE_IF(defaultDataAlignment == 0);
|
||||
stringTable.push_back('\0');
|
||||
specialStringsOffsets.undef = 0U;
|
||||
specialStringsOffsets.shStrTab = this->appendSectionName(SpecialSectionNames::shStrTab);
|
||||
|
||||
if (addUndefSectionHeader) {
|
||||
ElfSectionHeader<NumBits> undefSection;
|
||||
sectionHeaders.push_back(undefSection);
|
||||
}
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
void ElfEncoder<NumBits>::appendSection(const ElfSectionHeader<NumBits> §ionHeader, const ArrayRef<const uint8_t> sectionData) {
|
||||
sectionHeaders.push_back(sectionHeader);
|
||||
if ((SHT_NOBITS != sectionHeader.type) && (false == sectionData.empty())) {
|
||||
auto sectionDataAlignment = std::min<uint64_t>(defaultDataAlignment, 8U);
|
||||
auto alignedOffset = alignUp(this->data.size(), static_cast<size_t>(sectionDataAlignment));
|
||||
auto alignedSize = alignUp(sectionData.size(), static_cast<size_t>(sectionDataAlignment));
|
||||
this->data.reserve(alignedOffset + alignedSize);
|
||||
this->data.resize(alignedOffset, 0U);
|
||||
this->data.insert(this->data.end(), sectionData.begin(), sectionData.end());
|
||||
this->data.resize(alignedOffset + alignedSize, 0U);
|
||||
sectionHeaders.rbegin()->offset = static_cast<decltype(sectionHeaders.rbegin()->offset)>(alignedOffset);
|
||||
sectionHeaders.rbegin()->size = static_cast<decltype(sectionHeaders.rbegin()->size)>(sectionData.size());
|
||||
}
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
void ElfEncoder<NumBits>::appendSegment(const ElfProgramHeader<NumBits> &programHeader, const ArrayRef<const uint8_t> segmentData) {
|
||||
maxDataAlignmentNeeded = std::max<uint64_t>(maxDataAlignmentNeeded, static_cast<uint64_t>(programHeader.align));
|
||||
programHeaders.push_back(programHeader);
|
||||
if (false == segmentData.empty()) {
|
||||
UNRECOVERABLE_IF(programHeader.align == 0);
|
||||
auto alignedOffset = alignUp(this->data.size(), static_cast<size_t>(programHeader.align));
|
||||
auto alignedSize = alignUp(segmentData.size(), static_cast<size_t>(programHeader.align));
|
||||
this->data.reserve(alignedOffset + alignedSize);
|
||||
this->data.resize(alignedOffset, 0U);
|
||||
this->data.insert(this->data.end(), segmentData.begin(), segmentData.end());
|
||||
this->data.resize(alignedOffset + alignedSize, 0U);
|
||||
programHeaders.rbegin()->offset = static_cast<decltype(programHeaders.rbegin()->offset)>(alignedOffset);
|
||||
programHeaders.rbegin()->fileSz = static_cast<decltype(programHeaders.rbegin()->fileSz)>(segmentData.size());
|
||||
}
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
ElfSectionHeader<NumBits> &ElfEncoder<NumBits>::appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
|
||||
ElfSectionHeader<NumBits> section = {};
|
||||
section.type = static_cast<decltype(section.type)>(sectionType);
|
||||
section.flags = static_cast<decltype(section.flags)>(SHF_NONE);
|
||||
section.offset = 0U;
|
||||
section.name = appendSectionName(sectionLabel);
|
||||
section.addralign = 8U;
|
||||
appendSection(section, sectionData);
|
||||
return *sectionHeaders.rbegin();
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
ElfProgramHeader<NumBits> &ElfEncoder<NumBits>::appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef<const uint8_t> segmentData) {
|
||||
ElfProgramHeader<NumBits> segment = {};
|
||||
segment.type = static_cast<decltype(segment.type)>(segmentType);
|
||||
segment.flags = static_cast<decltype(segment.flags)>(PF_NONE);
|
||||
segment.offset = 0U;
|
||||
segment.align = static_cast<decltype(segment.align)>(defaultDataAlignment);
|
||||
appendSegment(segment, segmentData);
|
||||
return *programHeaders.rbegin();
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
uint32_t ElfEncoder<NumBits>::appendSectionName(ConstStringRef str) {
|
||||
if (str.empty() || (false == addHeaderSectionNamesSection)) {
|
||||
return specialStringsOffsets.undef;
|
||||
}
|
||||
uint32_t offset = static_cast<uint32_t>(stringTable.size());
|
||||
stringTable.insert(stringTable.end(), str.begin(), str.end());
|
||||
if (str[str.size() - 1] != '\0') {
|
||||
stringTable.push_back('\0');
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits>
|
||||
std::vector<uint8_t> ElfEncoder<NumBits>::encode() const {
|
||||
ElfFileHeader<NumBits> elfFileHeader = this->elfFileHeader;
|
||||
StackVec<ElfProgramHeader<NumBits>, 32> programHeaders = this->programHeaders;
|
||||
StackVec<ElfSectionHeader<NumBits>, 32> sectionHeaders = this->sectionHeaders;
|
||||
|
||||
if (addUndefSectionHeader && (1U == sectionHeaders.size())) {
|
||||
sectionHeaders.clear();
|
||||
}
|
||||
|
||||
ElfSectionHeader<NumBits> sectionHeaderNamesSection;
|
||||
size_t alignedSectionNamesDataSize = 0U;
|
||||
size_t dataPaddingBeforeSectionNames = 0U;
|
||||
if ((false == sectionHeaders.empty()) && addHeaderSectionNamesSection) {
|
||||
auto alignedDataSize = alignUp(data.size(), static_cast<size_t>(defaultDataAlignment));
|
||||
dataPaddingBeforeSectionNames = alignedDataSize - data.size();
|
||||
sectionHeaderNamesSection.type = SHT_STRTAB;
|
||||
sectionHeaderNamesSection.name = specialStringsOffsets.shStrTab;
|
||||
sectionHeaderNamesSection.offset = static_cast<decltype(sectionHeaderNamesSection.offset)>(alignedDataSize);
|
||||
sectionHeaderNamesSection.size = static_cast<decltype(sectionHeaderNamesSection.size)>(stringTable.size());
|
||||
sectionHeaderNamesSection.addralign = static_cast<decltype(sectionHeaderNamesSection.addralign)>(defaultDataAlignment);
|
||||
elfFileHeader.shStrNdx = static_cast<decltype(elfFileHeader.shStrNdx)>(sectionHeaders.size());
|
||||
sectionHeaders.push_back(sectionHeaderNamesSection);
|
||||
alignedSectionNamesDataSize = alignUp(stringTable.size(), static_cast<size_t>(sectionHeaderNamesSection.addralign));
|
||||
}
|
||||
|
||||
elfFileHeader.phNum = static_cast<decltype(elfFileHeader.phNum)>(programHeaders.size());
|
||||
elfFileHeader.shNum = static_cast<decltype(elfFileHeader.shNum)>(sectionHeaders.size());
|
||||
|
||||
auto programHeadersOffset = elfFileHeader.ehSize;
|
||||
auto sectionHeadersOffset = programHeadersOffset + elfFileHeader.phEntSize * elfFileHeader.phNum;
|
||||
|
||||
if (false == programHeaders.empty()) {
|
||||
elfFileHeader.phOff = static_cast<decltype(elfFileHeader.phOff)>(programHeadersOffset);
|
||||
}
|
||||
if (false == sectionHeaders.empty()) {
|
||||
elfFileHeader.shOff = static_cast<decltype(elfFileHeader.shOff)>(sectionHeadersOffset);
|
||||
}
|
||||
|
||||
auto dataOffset = alignUp(sectionHeadersOffset + elfFileHeader.shEntSize * elfFileHeader.shNum, static_cast<size_t>(maxDataAlignmentNeeded));
|
||||
auto stringTabOffset = dataOffset + data.size();
|
||||
|
||||
std::vector<uint8_t> ret;
|
||||
ret.reserve(stringTabOffset + alignedSectionNamesDataSize);
|
||||
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&elfFileHeader), reinterpret_cast<uint8_t *>(&elfFileHeader + 1));
|
||||
ret.resize(programHeadersOffset, 0U);
|
||||
|
||||
for (auto &programHeader : programHeaders) {
|
||||
if (0 != programHeader.fileSz) {
|
||||
programHeader.offset = static_cast<decltype(programHeader.offset)>(programHeader.offset + dataOffset);
|
||||
}
|
||||
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(&programHeader), reinterpret_cast<uint8_t *>(&programHeader + 1));
|
||||
ret.resize(ret.size() + elfFileHeader.phEntSize - sizeof(programHeader), 0U);
|
||||
}
|
||||
|
||||
for (auto §ionHeader : sectionHeaders) {
|
||||
if ((SHT_NOBITS != sectionHeader.type) && (0 != sectionHeader.size)) {
|
||||
sectionHeader.offset = static_cast<decltype(sectionHeader.offset)>(sectionHeader.offset + dataOffset);
|
||||
}
|
||||
ret.insert(ret.end(), reinterpret_cast<uint8_t *>(§ionHeader), reinterpret_cast<uint8_t *>(§ionHeader + 1));
|
||||
ret.resize(ret.size() + elfFileHeader.shEntSize - sizeof(sectionHeader), 0U);
|
||||
}
|
||||
|
||||
ret.resize(dataOffset, 0U);
|
||||
ret.insert(ret.end(), data.begin(), data.end());
|
||||
ret.resize(ret.size() + dataPaddingBeforeSectionNames, 0U);
|
||||
ret.insert(ret.end(), reinterpret_cast<const uint8_t *>(stringTable.data()), reinterpret_cast<const uint8_t *>(stringTable.data() + static_cast<size_t>(sectionHeaderNamesSection.size)));
|
||||
ret.resize(ret.size() + alignedSectionNamesDataSize - static_cast<size_t>(sectionHeaderNamesSection.size), 0U);
|
||||
return ret;
|
||||
}
|
||||
|
||||
template struct ElfEncoder<EI_CLASS_32>;
|
||||
template struct ElfEncoder<EI_CLASS_64>;
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
72
shared/source/device_binary_format/elf/elf_encoder.h
Normal file
72
shared/source/device_binary_format/elf/elf_encoder.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "device_binary_format/elf/elf.h"
|
||||
#include "helpers/aligned_memory.h"
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/const_stringref.h"
|
||||
#include "utilities/stackvec.h"
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
template <ELF_IDENTIFIER_CLASS NumBits = EI_CLASS_64>
|
||||
struct ElfEncoder {
|
||||
ElfEncoder(bool addUndefSectionHeader = true, bool addHeaderSectionNamesSection = true, uint64_t defaultDataAlignment = 8U);
|
||||
|
||||
void appendSection(const ElfSectionHeader<NumBits> §ionHeader, const ArrayRef<const uint8_t> sectionData);
|
||||
void appendSegment(const ElfProgramHeader<NumBits> &programHeader, const ArrayRef<const uint8_t> segmentData);
|
||||
|
||||
ElfSectionHeader<NumBits> &appendSection(SECTION_HEADER_TYPE sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData);
|
||||
ElfProgramHeader<NumBits> &appendSegment(PROGRAM_HEADER_TYPE segmentType, const ArrayRef<const uint8_t> segmentData);
|
||||
|
||||
template <typename SectionHeaderEnumT>
|
||||
ElfSectionHeader<NumBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const ArrayRef<const uint8_t> sectionData) {
|
||||
return appendSection(static_cast<SECTION_HEADER_TYPE>(sectionType), sectionLabel, sectionData);
|
||||
}
|
||||
|
||||
template <typename SectionHeaderEnumT>
|
||||
ElfSectionHeader<NumBits> &appendSection(SectionHeaderEnumT sectionType, ConstStringRef sectionLabel, const std::string §ionData) {
|
||||
return appendSection(static_cast<SECTION_HEADER_TYPE>(sectionType), sectionLabel,
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(sectionData.c_str()), sectionData.size() + 1));
|
||||
}
|
||||
|
||||
uint32_t appendSectionName(ConstStringRef str);
|
||||
|
||||
std::vector<uint8_t> encode() const;
|
||||
|
||||
ElfFileHeader<NumBits> &getElfFileHeader() {
|
||||
return elfFileHeader;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool addUndefSectionHeader = false;
|
||||
bool addHeaderSectionNamesSection = false;
|
||||
uint64_t defaultDataAlignment = 8U;
|
||||
uint64_t maxDataAlignmentNeeded = 1U;
|
||||
ElfFileHeader<NumBits> elfFileHeader;
|
||||
StackVec<ElfProgramHeader<NumBits>, 32> programHeaders;
|
||||
StackVec<ElfSectionHeader<NumBits>, 32> sectionHeaders;
|
||||
std::vector<uint8_t> data;
|
||||
std::vector<char> stringTable;
|
||||
struct {
|
||||
uint32_t shStrTab = 0;
|
||||
uint32_t undef = 0;
|
||||
} specialStringsOffsets;
|
||||
};
|
||||
|
||||
extern template struct ElfEncoder<EI_CLASS_32>;
|
||||
extern template struct ElfEncoder<EI_CLASS_64>;
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
59
shared/source/device_binary_format/elf/ocl_elf.h
Normal file
59
shared/source/device_binary_format/elf/ocl_elf.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// Abstract: Defines the types used for ELF headers/sections.
|
||||
#pragma once
|
||||
|
||||
#include "device_binary_format/elf/elf.h"
|
||||
#include "utilities/const_stringref.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace Elf {
|
||||
|
||||
enum ELF_TYPE_OPENCL : uint16_t {
|
||||
ET_OPENCL_SOURCE = 0xff01, // format used to pass CL text sections to FE
|
||||
ET_OPENCL_OBJECTS = 0xff02, // format used to pass LLVM objects / store LLVM binary output
|
||||
ET_OPENCL_LIBRARY = 0xff03, // format used to store LLVM archive output
|
||||
ET_OPENCL_EXECUTABLE = 0xff04, // format used to store executable output
|
||||
ET_OPENCL_DEBUG = 0xff05, // format used to store debug output
|
||||
};
|
||||
static_assert(sizeof(ELF_TYPE_OPENCL) == sizeof(ELF_TYPE), "");
|
||||
static_assert(static_cast<uint16_t>(ET_OPENCL_SOURCE) == static_cast<uint16_t>(ET_OPENCL_RESERVED_START), "");
|
||||
static_assert(static_cast<uint16_t>(ET_OPENCL_DEBUG) == static_cast<uint16_t>(ET_OPENCL_RESERVED_END), "");
|
||||
|
||||
enum SHT_OPENCL : uint32_t {
|
||||
SHT_OPENCL_SOURCE = 0xff000000, // CL source to link into LLVM binary
|
||||
SHT_OPENCL_HEADER = 0xff000001, // CL header to link into LLVM binary
|
||||
SHT_OPENCL_LLVM_TEXT = 0xff000002, // LLVM text
|
||||
SHT_OPENCL_LLVM_BINARY = 0xff000003, // LLVM byte code
|
||||
SHT_OPENCL_LLVM_ARCHIVE = 0xff000004, // LLVM archives(s)
|
||||
SHT_OPENCL_DEV_BINARY = 0xff000005, // Device binary (coherent by default)
|
||||
SHT_OPENCL_OPTIONS = 0xff000006, // CL Options
|
||||
SHT_OPENCL_PCH = 0xff000007, // PCH (pre-compiled headers)
|
||||
SHT_OPENCL_DEV_DEBUG = 0xff000008, // Device debug
|
||||
SHT_OPENCL_SPIRV = 0xff000009, // SPIRV
|
||||
SHT_NON_COHERENT_DEV_BINARY = 0xff00000a, // Non-coherent Device binary
|
||||
};
|
||||
static_assert(sizeof(SHT_OPENCL) == sizeof(SECTION_HEADER_TYPE), "");
|
||||
static_assert(static_cast<uint32_t>(SHT_OPENCL_SOURCE) == static_cast<uint32_t>(SHT_OPENCL_RESERVED_START), "");
|
||||
static_assert(static_cast<uint32_t>(SHT_NON_COHERENT_DEV_BINARY) == static_cast<uint32_t>(SHT_OPENCL_RESERVED_END), "");
|
||||
|
||||
namespace SectionNamesOpenCl {
|
||||
static constexpr ConstStringRef buildOptions = "BuildOptions";
|
||||
static constexpr ConstStringRef spirvObject = "SPIRV Object";
|
||||
static constexpr ConstStringRef llvmObject = "Intel(R) OpenCL LLVM Object";
|
||||
static constexpr ConstStringRef deviceDebug = "Intel(R) OpenCL Device Debug";
|
||||
static constexpr ConstStringRef deviceBinary = "Intel(R) OpenCL Device Binary";
|
||||
} // namespace SectionNamesOpenCl
|
||||
|
||||
} // namespace Elf
|
||||
|
||||
} // namespace NEO
|
||||
645
shared/source/device_binary_format/patchtokens_decoder.cpp
Normal file
645
shared/source/device_binary_format/patchtokens_decoder.cpp
Normal file
@@ -0,0 +1,645 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "patchtokens_decoder.h"
|
||||
|
||||
#include "debug_settings/debug_settings_manager.h"
|
||||
#include "helpers/debug_helpers.h"
|
||||
#include "helpers/hash.h"
|
||||
#include "helpers/ptr_math.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
struct PatchTokensStreamReader {
|
||||
const ArrayRef<const uint8_t> data;
|
||||
PatchTokensStreamReader(ArrayRef<const uint8_t> data) : data(data) {}
|
||||
|
||||
template <typename DecodePosT>
|
||||
bool notEnoughDataLeft(DecodePosT *decodePos, size_t requestedSize) {
|
||||
return getDataSizeLeft(decodePos) < requestedSize;
|
||||
}
|
||||
|
||||
template <typename T, typename DecodePosT>
|
||||
constexpr bool notEnoughDataLeft(DecodePosT *decodePos) {
|
||||
return notEnoughDataLeft(decodePos, sizeof(T));
|
||||
}
|
||||
|
||||
template <typename... ArgsT>
|
||||
bool enoughDataLeft(ArgsT &&... args) {
|
||||
return false == notEnoughDataLeft(std::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... ArgsT>
|
||||
bool enoughDataLeft(ArgsT &&... args) {
|
||||
return false == notEnoughDataLeft<T>(std::forward<ArgsT>(args)...);
|
||||
}
|
||||
|
||||
template <typename DecodePosT>
|
||||
size_t getDataSizeLeft(DecodePosT *decodePos) {
|
||||
auto dataConsumed = ptrDiff(decodePos, data.begin());
|
||||
UNRECOVERABLE_IF(dataConsumed > data.size());
|
||||
return data.size() - dataConsumed;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
inline void assignToken(const T *&dst, const SPatchItemHeader *src) {
|
||||
dst = reinterpret_cast<const T *>(src);
|
||||
}
|
||||
|
||||
inline KernelArgFromPatchtokens &getKernelArg(KernelFromPatchtokens &kernel, size_t argNum, ArgObjectType type = ArgObjectType::None, ArgObjectTypeSpecialized typeSpecialized = ArgObjectTypeSpecialized::None) {
|
||||
if (kernel.tokens.kernelArgs.size() < argNum + 1) {
|
||||
kernel.tokens.kernelArgs.resize(argNum + 1);
|
||||
}
|
||||
auto &arg = kernel.tokens.kernelArgs[argNum];
|
||||
if (arg.objectType == ArgObjectType::None) {
|
||||
arg.objectType = type;
|
||||
} else if ((arg.objectType != type) && (type != ArgObjectType::None)) {
|
||||
kernel.decodeStatus = DecodeError::InvalidBinary;
|
||||
DBG_LOG(LogPatchTokens, "\n Mismatched metadata for kernel arg :", argNum);
|
||||
DEBUG_BREAK_IF(true);
|
||||
}
|
||||
|
||||
if (arg.objectTypeSpecialized == ArgObjectTypeSpecialized::None) {
|
||||
arg.objectTypeSpecialized = typeSpecialized;
|
||||
} else if (typeSpecialized != ArgObjectTypeSpecialized::None) {
|
||||
UNRECOVERABLE_IF(arg.objectTypeSpecialized != typeSpecialized);
|
||||
}
|
||||
|
||||
return arg;
|
||||
}
|
||||
|
||||
inline void assignArgInfo(KernelFromPatchtokens &kernel, const SPatchItemHeader *src) {
|
||||
auto argInfoToken = reinterpret_cast<const SPatchKernelArgumentInfo *>(src);
|
||||
getKernelArg(kernel, argInfoToken->ArgumentNumber, ArgObjectType::None).argInfo = argInfoToken;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline uint32_t getArgNum(const SPatchItemHeader *argToken) {
|
||||
return reinterpret_cast<const T *>(argToken)->ArgumentNumber;
|
||||
}
|
||||
|
||||
inline void assignArg(KernelFromPatchtokens &kernel, const SPatchItemHeader *src) {
|
||||
uint32_t argNum = 0;
|
||||
ArgObjectType type = ArgObjectType::Buffer;
|
||||
switch (src->Token) {
|
||||
default:
|
||||
UNRECOVERABLE_IF(src->Token != PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT);
|
||||
argNum = getArgNum<SPatchSamplerKernelArgument>(src);
|
||||
type = ArgObjectType::Sampler;
|
||||
break;
|
||||
case PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
argNum = getArgNum<SPatchImageMemoryObjectKernelArgument>(src);
|
||||
type = ArgObjectType::Image;
|
||||
break;
|
||||
case PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
argNum = getArgNum<SPatchGlobalMemoryObjectKernelArgument>(src);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
argNum = getArgNum<SPatchStatelessGlobalMemoryObjectKernelArgument>(src);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
argNum = getArgNum<SPatchStatelessConstantMemoryObjectKernelArgument>(src);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT:
|
||||
argNum = getArgNum<SPatchStatelessDeviceQueueKernelArgument>(src);
|
||||
break;
|
||||
}
|
||||
|
||||
getKernelArg(kernel, argNum, type).objectArg = src;
|
||||
}
|
||||
|
||||
inline void assignToken(StackVecStrings &stringVec, const SPatchItemHeader *src) {
|
||||
auto stringToken = reinterpret_cast<const SPatchString *>(src);
|
||||
if (stringVec.size() < stringToken->Index + 1) {
|
||||
stringVec.resize(stringToken->Index + 1);
|
||||
}
|
||||
stringVec[stringToken->Index] = stringToken;
|
||||
}
|
||||
|
||||
template <size_t S>
|
||||
inline void assignTokenInArray(const SPatchDataParameterBuffer *(&tokensArray)[S], const SPatchDataParameterBuffer *src, StackVecUnhandledTokens &unhandledTokens) {
|
||||
auto sourceIndex = src->SourceOffset >> 2;
|
||||
if (sourceIndex >= S) {
|
||||
DBG_LOG(LogPatchTokens, "\n .Type", "Unhandled sourceIndex ", sourceIndex);
|
||||
DEBUG_BREAK_IF(true);
|
||||
unhandledTokens.push_back(src);
|
||||
return;
|
||||
}
|
||||
assignToken(tokensArray[sourceIndex], src);
|
||||
}
|
||||
|
||||
template <typename PatchT, size_t NumInlineEl>
|
||||
inline void addTok(StackVec<const PatchT *, NumInlineEl> &tokensVec, const SPatchItemHeader *src) {
|
||||
tokensVec.push_back(reinterpret_cast<const PatchT *>(src));
|
||||
}
|
||||
|
||||
inline void decodeKernelDataParameterToken(const SPatchDataParameterBuffer *token, KernelFromPatchtokens &out) {
|
||||
auto &crossthread = out.tokens.crossThreadPayloadArgs;
|
||||
auto sourceIndex = token->SourceOffset >> 2;
|
||||
auto argNum = token->ArgumentNumber;
|
||||
|
||||
switch (token->Type) {
|
||||
default:
|
||||
DBG_LOG(LogPatchTokens, "\n .Type", "Unhandled SPatchDataParameterBuffer ", token->Type);
|
||||
DEBUG_BREAK_IF(true);
|
||||
out.unhandledTokens.push_back(token);
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_KERNEL_ARGUMENT:
|
||||
getKernelArg(out, argNum, ArgObjectType::None).byValMap.push_back(token);
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_LOCAL_WORK_SIZE: {
|
||||
if (sourceIndex >= 3) {
|
||||
DBG_LOG(LogPatchTokens, "\n .Type", "Unhandled sourceIndex ", sourceIndex);
|
||||
DEBUG_BREAK_IF(true);
|
||||
out.unhandledTokens.push_back(token);
|
||||
return;
|
||||
}
|
||||
auto localWorkSizeArray = (crossthread.localWorkSize[sourceIndex] == nullptr)
|
||||
? crossthread.localWorkSize
|
||||
: crossthread.localWorkSize2;
|
||||
localWorkSizeArray[sourceIndex] = token;
|
||||
break;
|
||||
}
|
||||
|
||||
case DATA_PARAMETER_GLOBAL_WORK_OFFSET:
|
||||
assignTokenInArray(crossthread.globalWorkOffset, token, out.unhandledTokens);
|
||||
break;
|
||||
case DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE:
|
||||
assignTokenInArray(crossthread.enqueuedLocalWorkSize, token, out.unhandledTokens);
|
||||
break;
|
||||
case DATA_PARAMETER_GLOBAL_WORK_SIZE:
|
||||
assignTokenInArray(crossthread.globalWorkSize, token, out.unhandledTokens);
|
||||
break;
|
||||
case DATA_PARAMETER_NUM_WORK_GROUPS:
|
||||
assignTokenInArray(crossthread.numWorkGroups, token, out.unhandledTokens);
|
||||
break;
|
||||
case DATA_PARAMETER_MAX_WORKGROUP_SIZE:
|
||||
crossthread.maxWorkGroupSize = token;
|
||||
break;
|
||||
case DATA_PARAMETER_WORK_DIMENSIONS:
|
||||
crossthread.workDimensions = token;
|
||||
break;
|
||||
case DATA_PARAMETER_SIMD_SIZE:
|
||||
crossthread.simdSize = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_PRIVATE_MEMORY_STATELESS_SIZE:
|
||||
crossthread.privateMemoryStatelessSize = token;
|
||||
break;
|
||||
case DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_SIZE:
|
||||
crossthread.localMemoryStatelessWindowSize = token;
|
||||
break;
|
||||
case DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_START_ADDRESS:
|
||||
crossthread.localMemoryStatelessWindowStartAddress = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_OBJECT_ID:
|
||||
getKernelArg(out, argNum, ArgObjectType::None).objectId = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES: {
|
||||
auto &kernelArg = getKernelArg(out, argNum, ArgObjectType::Slm);
|
||||
kernelArg.byValMap.push_back(token);
|
||||
kernelArg.metadata.slm.token = token;
|
||||
} break;
|
||||
|
||||
case DATA_PARAMETER_BUFFER_OFFSET:
|
||||
getKernelArg(out, argNum, ArgObjectType::Buffer).metadata.buffer.bufferOffset = token;
|
||||
break;
|
||||
case DATA_PARAMETER_BUFFER_STATEFUL:
|
||||
getKernelArg(out, argNum, ArgObjectType::Buffer).metadata.buffer.pureStateful = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_IMAGE_WIDTH:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.width = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_HEIGHT:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.height = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_DEPTH:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.depth = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_CHANNEL_DATA_TYPE:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.channelDataType = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_CHANNEL_ORDER:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.channelOrder = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_ARRAY_SIZE:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.arraySize = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_NUM_SAMPLES:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.numSamples = token;
|
||||
break;
|
||||
case DATA_PARAMETER_IMAGE_NUM_MIP_LEVELS:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.numMipLevels = token;
|
||||
break;
|
||||
case DATA_PARAMETER_FLAT_IMAGE_BASEOFFSET:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.flatBaseOffset = token;
|
||||
break;
|
||||
case DATA_PARAMETER_FLAT_IMAGE_WIDTH:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.flatWidth = token;
|
||||
break;
|
||||
case DATA_PARAMETER_FLAT_IMAGE_HEIGHT:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.flatHeight = token;
|
||||
break;
|
||||
case DATA_PARAMETER_FLAT_IMAGE_PITCH:
|
||||
getKernelArg(out, argNum, ArgObjectType::Image).metadata.image.flatPitch = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_SAMPLER_COORDINATE_SNAP_WA_REQUIRED:
|
||||
getKernelArg(out, argNum, ArgObjectType::Sampler).metadata.sampler.coordinateSnapWaRequired = token;
|
||||
break;
|
||||
case DATA_PARAMETER_SAMPLER_ADDRESS_MODE:
|
||||
getKernelArg(out, argNum, ArgObjectType::Sampler).metadata.sampler.addressMode = token;
|
||||
break;
|
||||
case DATA_PARAMETER_SAMPLER_NORMALIZED_COORDS:
|
||||
getKernelArg(out, argNum, ArgObjectType::Sampler).metadata.sampler.normalizedCoords = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_VME_MB_BLOCK_TYPE:
|
||||
getKernelArg(out, argNum, ArgObjectType::None, ArgObjectTypeSpecialized::Vme).metadataSpecialized.vme.mbBlockType = token;
|
||||
break;
|
||||
case DATA_PARAMETER_VME_SUBPIXEL_MODE:
|
||||
getKernelArg(out, argNum, ArgObjectType::None, ArgObjectTypeSpecialized::Vme).metadataSpecialized.vme.subpixelMode = token;
|
||||
break;
|
||||
case DATA_PARAMETER_VME_SAD_ADJUST_MODE:
|
||||
getKernelArg(out, argNum, ArgObjectType::None, ArgObjectTypeSpecialized::Vme).metadataSpecialized.vme.sadAdjustMode = token;
|
||||
break;
|
||||
case DATA_PARAMETER_VME_SEARCH_PATH_TYPE:
|
||||
getKernelArg(out, argNum, ArgObjectType::None, ArgObjectTypeSpecialized::Vme).metadataSpecialized.vme.searchPathType = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_PARENT_EVENT:
|
||||
crossthread.parentEvent = token;
|
||||
break;
|
||||
case DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE:
|
||||
crossthread.childBlockSimdSize.push_back(token);
|
||||
break;
|
||||
case DATA_PARAMETER_PREFERRED_WORKGROUP_MULTIPLE:
|
||||
crossthread.preferredWorkgroupMultiple = token;
|
||||
break;
|
||||
|
||||
case DATA_PARAMETER_NUM_HARDWARE_THREADS:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_PRINTF_SURFACE_SIZE:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_IMAGE_SRGB_CHANNEL_ORDER:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_STAGE_IN_GRID_ORIGIN:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_STAGE_IN_GRID_SIZE:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_LOCAL_ID:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_EXECUTION_MASK:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_VME_IMAGE_TYPE:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case DATA_PARAMETER_VME_MB_SKIP_BLOCK_TYPE:
|
||||
// ignored intentionally
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inline bool decodeToken(const SPatchItemHeader *token, KernelFromPatchtokens &out) {
|
||||
switch (token->Token) {
|
||||
default: {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "Unknown kernel-scope Patch Token: %d\n", token->Token);
|
||||
DEBUG_BREAK_IF(true);
|
||||
out.unhandledTokens.push_back(token);
|
||||
break;
|
||||
}
|
||||
case PATCH_TOKEN_SAMPLER_STATE_ARRAY:
|
||||
assignToken(out.tokens.samplerStateArray, token);
|
||||
break;
|
||||
case PATCH_TOKEN_BINDING_TABLE_STATE:
|
||||
assignToken(out.tokens.bindingTableState, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE:
|
||||
assignToken(out.tokens.allocateLocalSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_MEDIA_VFE_STATE:
|
||||
assignToken(out.tokens.mediaVfeState[0], token);
|
||||
break;
|
||||
case PATCH_TOKEN_MEDIA_VFE_STATE_SLOT1:
|
||||
assignToken(out.tokens.mediaVfeState[1], token);
|
||||
break;
|
||||
case PATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD:
|
||||
assignToken(out.tokens.mediaInterfaceDescriptorLoad, token);
|
||||
break;
|
||||
case PATCH_TOKEN_INTERFACE_DESCRIPTOR_DATA:
|
||||
assignToken(out.tokens.interfaceDescriptorData, token);
|
||||
break;
|
||||
case PATCH_TOKEN_THREAD_PAYLOAD:
|
||||
assignToken(out.tokens.threadPayload, token);
|
||||
break;
|
||||
case PATCH_TOKEN_EXECUTION_ENVIRONMENT:
|
||||
assignToken(out.tokens.executionEnvironment, token);
|
||||
break;
|
||||
|
||||
case PATCH_TOKEN_KERNEL_ATTRIBUTES_INFO:
|
||||
assignToken(out.tokens.kernelAttributesInfo, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_PRIVATE_MEMORY:
|
||||
assignToken(out.tokens.allocateStatelessPrivateSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_CONSTANT_MEMORY_SURFACE_WITH_INITIALIZATION:
|
||||
assignToken(out.tokens.allocateStatelessConstantMemorySurfaceWithInitialization, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_GLOBAL_MEMORY_SURFACE_WITH_INITIALIZATION:
|
||||
assignToken(out.tokens.allocateStatelessGlobalMemorySurfaceWithInitialization, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_PRINTF_SURFACE:
|
||||
assignToken(out.tokens.allocateStatelessPrintfSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_EVENT_POOL_SURFACE:
|
||||
assignToken(out.tokens.allocateStatelessEventPoolSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_STATELESS_DEFAULT_DEVICE_QUEUE_SURFACE:
|
||||
assignToken(out.tokens.allocateStatelessDefaultDeviceQueueSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_STRING:
|
||||
assignToken(out.tokens.strings, token);
|
||||
break;
|
||||
case PATCH_TOKEN_INLINE_VME_SAMPLER_INFO:
|
||||
assignToken(out.tokens.inlineVmeSamplerInfo, token);
|
||||
break;
|
||||
case PATCH_TOKEN_GTPIN_FREE_GRF_INFO:
|
||||
assignToken(out.tokens.gtpinFreeGrfInfo, token);
|
||||
break;
|
||||
case PATCH_TOKEN_GTPIN_INFO:
|
||||
assignToken(out.tokens.gtpinInfo, token);
|
||||
break;
|
||||
case PATCH_TOKEN_STATE_SIP:
|
||||
assignToken(out.tokens.stateSip, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_SIP_SURFACE:
|
||||
assignToken(out.tokens.allocateSystemThreadSurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_PROGRAM_SYMBOL_TABLE:
|
||||
assignToken(out.tokens.programSymbolTable, token);
|
||||
break;
|
||||
case PATCH_TOKEN_PROGRAM_RELOCATION_TABLE:
|
||||
assignToken(out.tokens.programRelocationTable, token);
|
||||
break;
|
||||
case PATCH_TOKEN_KERNEL_ARGUMENT_INFO:
|
||||
assignArgInfo(out, token);
|
||||
break;
|
||||
|
||||
case PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case PATCH_TOKEN_STATELESS_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case PATCH_TOKEN_STATELESS_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT:
|
||||
assignArg(out, token);
|
||||
break;
|
||||
|
||||
case PATCH_TOKEN_DATA_PARAMETER_STREAM:
|
||||
assignToken(out.tokens.dataParameterStream, token);
|
||||
break;
|
||||
case PATCH_TOKEN_DATA_PARAMETER_BUFFER: {
|
||||
auto tokDataP = reinterpret_cast<const SPatchDataParameterBuffer *>(token);
|
||||
decodeKernelDataParameterToken(tokDataP, out);
|
||||
} break;
|
||||
|
||||
case PATCH_TOKEN_ALLOCATE_SYNC_BUFFER: {
|
||||
assignToken(out.tokens.allocateSyncBuffer, token);
|
||||
} break;
|
||||
}
|
||||
|
||||
return out.decodeStatus != DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
inline bool decodeToken(const SPatchItemHeader *token, ProgramFromPatchtokens &out) {
|
||||
auto &progTok = out.programScopeTokens;
|
||||
switch (token->Token) {
|
||||
default: {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "Unknown program-scope Patch Token: %d\n", token->Token);
|
||||
DEBUG_BREAK_IF(true);
|
||||
out.unhandledTokens.push_back(token);
|
||||
break;
|
||||
}
|
||||
case PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO:
|
||||
addTok(progTok.allocateConstantMemorySurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO:
|
||||
addTok(progTok.allocateGlobalMemorySurface, token);
|
||||
break;
|
||||
case PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO:
|
||||
addTok(progTok.globalPointer, token);
|
||||
break;
|
||||
case PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO:
|
||||
addTok(progTok.constantPointer, token);
|
||||
break;
|
||||
case PATCH_TOKEN_PROGRAM_SYMBOL_TABLE:
|
||||
assignToken(progTok.symbolTable, token);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename DecodeContext>
|
||||
inline size_t getPatchTokenTotalSize(PatchTokensStreamReader stream, const SPatchItemHeader *token);
|
||||
|
||||
template <>
|
||||
inline size_t getPatchTokenTotalSize<KernelFromPatchtokens>(PatchTokensStreamReader stream, const SPatchItemHeader *token) {
|
||||
return token->Size;
|
||||
}
|
||||
|
||||
template <>
|
||||
inline size_t getPatchTokenTotalSize<ProgramFromPatchtokens>(PatchTokensStreamReader stream, const SPatchItemHeader *token) {
|
||||
size_t tokSize = token->Size;
|
||||
switch (token->Token) {
|
||||
default:
|
||||
return tokSize;
|
||||
case PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO:
|
||||
return stream.enoughDataLeft<SPatchAllocateConstantMemorySurfaceProgramBinaryInfo>(token)
|
||||
? tokSize + reinterpret_cast<const SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *>(token)->InlineDataSize
|
||||
: std::numeric_limits<size_t>::max();
|
||||
case PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO:
|
||||
return stream.enoughDataLeft<SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo>(token)
|
||||
? tokSize + reinterpret_cast<const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *>(token)->InlineDataSize
|
||||
: std::numeric_limits<size_t>::max();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename OutT>
|
||||
inline bool decodePatchList(PatchTokensStreamReader patchListStream, OutT &out) {
|
||||
auto decodePos = patchListStream.data.begin();
|
||||
auto decodeEnd = patchListStream.data.end();
|
||||
|
||||
bool decodeSuccess = true;
|
||||
while ((decodePos + sizeof(SPatchItemHeader) <= decodeEnd) && decodeSuccess) {
|
||||
auto token = reinterpret_cast<const SPatchItemHeader *>(decodePos);
|
||||
size_t tokenTotalSize = getPatchTokenTotalSize<OutT>(patchListStream, token);
|
||||
decodeSuccess = patchListStream.enoughDataLeft(decodePos, tokenTotalSize);
|
||||
decodeSuccess = decodeSuccess && (tokenTotalSize > 0U);
|
||||
decodeSuccess = decodeSuccess && decodeToken(token, out);
|
||||
decodePos = ptrOffset(decodePos, tokenTotalSize);
|
||||
}
|
||||
|
||||
return decodeSuccess;
|
||||
}
|
||||
|
||||
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> kernelBlob, KernelFromPatchtokens &out) {
|
||||
PatchTokensStreamReader stream{kernelBlob};
|
||||
auto decodePos = stream.data.begin();
|
||||
out.decodeStatus = DecodeError::Undefined;
|
||||
if (stream.notEnoughDataLeft<SKernelBinaryHeaderCommon>(decodePos)) {
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
out.header = reinterpret_cast<const SKernelBinaryHeaderCommon *>(decodePos);
|
||||
|
||||
auto kernelInfoBlobSize = sizeof(SKernelBinaryHeaderCommon) + out.header->KernelNameSize + out.header->KernelHeapSize + out.header->GeneralStateHeapSize + out.header->DynamicStateHeapSize + out.header->SurfaceStateHeapSize + out.header->PatchListSize;
|
||||
|
||||
if (stream.notEnoughDataLeft(decodePos, kernelInfoBlobSize)) {
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
out.blobs.kernelInfo = ArrayRef<const uint8_t>(stream.data.begin(), kernelInfoBlobSize);
|
||||
decodePos = ptrOffset(decodePos, sizeof(SKernelBinaryHeaderCommon));
|
||||
|
||||
auto kernelName = reinterpret_cast<const char *>(decodePos);
|
||||
out.name = ArrayRef<const char>(kernelName, out.header->KernelNameSize);
|
||||
decodePos = ptrOffset(decodePos, out.name.size());
|
||||
|
||||
out.isa = ArrayRef<const uint8_t>(decodePos, out.header->KernelHeapSize);
|
||||
decodePos = ptrOffset(decodePos, out.isa.size());
|
||||
|
||||
out.heaps.generalState = ArrayRef<const uint8_t>(decodePos, out.header->GeneralStateHeapSize);
|
||||
decodePos = ptrOffset(decodePos, out.heaps.generalState.size());
|
||||
|
||||
out.heaps.dynamicState = ArrayRef<const uint8_t>(decodePos, out.header->DynamicStateHeapSize);
|
||||
decodePos = ptrOffset(decodePos, out.heaps.dynamicState.size());
|
||||
|
||||
out.heaps.surfaceState = ArrayRef<const uint8_t>(decodePos, out.header->SurfaceStateHeapSize);
|
||||
decodePos = ptrOffset(decodePos, out.heaps.surfaceState.size());
|
||||
|
||||
out.blobs.patchList = ArrayRef<const uint8_t>(decodePos, out.header->PatchListSize);
|
||||
|
||||
if (false == decodePatchList(out.blobs.patchList, out)) {
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
out.decodeStatus = DecodeError::Success;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool decodeProgramHeader(ProgramFromPatchtokens &decodedProgram) {
|
||||
auto decodePos = decodedProgram.blobs.programInfo.begin();
|
||||
PatchTokensStreamReader stream{decodedProgram.blobs.programInfo};
|
||||
if (stream.notEnoughDataLeft<SProgramBinaryHeader>(decodePos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
decodedProgram.header = reinterpret_cast<const SProgramBinaryHeader *>(decodePos);
|
||||
if (decodedProgram.header->Magic != MAGIC_CL) {
|
||||
return false;
|
||||
}
|
||||
decodePos = ptrOffset(decodePos, sizeof(SProgramBinaryHeader));
|
||||
|
||||
if (stream.notEnoughDataLeft(decodePos, decodedProgram.header->PatchListSize)) {
|
||||
return false;
|
||||
}
|
||||
decodedProgram.blobs.patchList = ArrayRef<const uint8_t>(decodePos, decodedProgram.header->PatchListSize);
|
||||
decodePos = ptrOffset(decodePos, decodedProgram.blobs.patchList.size());
|
||||
|
||||
decodedProgram.blobs.kernelsInfo = ArrayRef<const uint8_t>(decodePos, stream.getDataSizeLeft(decodePos));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool decodeKernels(ProgramFromPatchtokens &decodedProgram) {
|
||||
auto numKernels = decodedProgram.header->NumberOfKernels;
|
||||
decodedProgram.kernels.reserve(decodedProgram.header->NumberOfKernels);
|
||||
const uint8_t *decodePos = decodedProgram.blobs.kernelsInfo.begin();
|
||||
bool decodeSuccess = true;
|
||||
PatchTokensStreamReader stream{decodedProgram.blobs.kernelsInfo};
|
||||
for (uint32_t i = 0; (i < numKernels) && decodeSuccess; i++) {
|
||||
decodedProgram.kernels.resize(decodedProgram.kernels.size() + 1);
|
||||
auto &currKernelInfo = *decodedProgram.kernels.rbegin();
|
||||
auto kernelDataLeft = ArrayRef<const uint8_t>(decodePos, stream.getDataSizeLeft(decodePos));
|
||||
decodeSuccess = decodeKernelFromPatchtokensBlob(kernelDataLeft, currKernelInfo);
|
||||
decodePos = ptrOffset(decodePos, currKernelInfo.blobs.kernelInfo.size());
|
||||
}
|
||||
return decodeSuccess;
|
||||
}
|
||||
|
||||
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> programBlob, ProgramFromPatchtokens &out) {
|
||||
out.blobs.programInfo = programBlob;
|
||||
bool decodeSuccess = decodeProgramHeader(out);
|
||||
decodeSuccess = decodeSuccess && decodeKernels(out);
|
||||
decodeSuccess = decodeSuccess && decodePatchList(out.blobs.patchList, out);
|
||||
out.decodeStatus = decodeSuccess ? DecodeError::Success : DecodeError::InvalidBinary;
|
||||
|
||||
return decodeSuccess;
|
||||
}
|
||||
|
||||
uint32_t calcKernelChecksum(const ArrayRef<const uint8_t> kernelBlob) {
|
||||
UNRECOVERABLE_IF(kernelBlob.size() <= sizeof(SKernelBinaryHeaderCommon));
|
||||
auto dataToHash = ArrayRef<const uint8_t>(ptrOffset(kernelBlob.begin(), sizeof(SKernelBinaryHeaderCommon)), kernelBlob.end());
|
||||
uint64_t hashValue = Hash::hash(reinterpret_cast<const char *>(dataToHash.begin()), dataToHash.size());
|
||||
uint32_t checksum = hashValue & 0xFFFFFFFF;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
bool hasInvalidChecksum(const KernelFromPatchtokens &decodedKernel) {
|
||||
uint32_t decodedChecksum = decodedKernel.header->CheckSum;
|
||||
uint32_t calculatedChecksum = NEO::PatchTokenBinary::calcKernelChecksum(decodedKernel.blobs.kernelInfo);
|
||||
return decodedChecksum != calculatedChecksum;
|
||||
}
|
||||
|
||||
const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumentInfo *ptr) {
|
||||
KernelArgAttributesFromPatchtokens ret = {};
|
||||
UNRECOVERABLE_IF(ptr == nullptr);
|
||||
auto decodePos = reinterpret_cast<const char *>(ptr + 1);
|
||||
auto bounds = reinterpret_cast<const char *>(ptr) + ptr->Size;
|
||||
ret.addressQualifier = ArrayRef<const char>(decodePos, std::min(decodePos + ptr->AddressQualifierSize, bounds));
|
||||
decodePos += ret.addressQualifier.size();
|
||||
|
||||
ret.accessQualifier = ArrayRef<const char>(decodePos, std::min(decodePos + ptr->AccessQualifierSize, bounds));
|
||||
decodePos += ret.accessQualifier.size();
|
||||
|
||||
ret.argName = ArrayRef<const char>(decodePos, std::min(decodePos + ptr->ArgumentNameSize, bounds));
|
||||
decodePos += ret.argName.size();
|
||||
|
||||
ret.typeName = ArrayRef<const char>(decodePos, std::min(decodePos + ptr->TypeNameSize, bounds));
|
||||
decodePos += ret.typeName.size();
|
||||
|
||||
ret.typeQualifiers = ArrayRef<const char>(decodePos, std::min(decodePos + ptr->TypeQualifierSize, bounds));
|
||||
return ret;
|
||||
}
|
||||
|
||||
const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob) {
|
||||
ProgramFromPatchtokens program;
|
||||
program.blobs.programInfo = programBlob;
|
||||
if (false == decodeProgramHeader(program)) {
|
||||
return nullptr;
|
||||
}
|
||||
return program.header;
|
||||
}
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
222
shared/source/device_binary_format/patchtokens_decoder.h
Normal file
222
shared/source/device_binary_format/patchtokens_decoder.h
Normal file
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
#include "helpers/ptr_math.h"
|
||||
#include "utilities/arrayref.h"
|
||||
#include "utilities/stackvec.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
#include "patch_g7.h"
|
||||
#include "patch_list.h"
|
||||
#include "patch_shared.h"
|
||||
#include "program_debug_data.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
using namespace iOpenCL;
|
||||
|
||||
enum class ArgObjectType : uint32_t {
|
||||
None = 0,
|
||||
Buffer,
|
||||
Image,
|
||||
Sampler,
|
||||
Slm
|
||||
};
|
||||
|
||||
enum class ArgObjectTypeSpecialized : uint32_t {
|
||||
None = 0,
|
||||
Vme
|
||||
};
|
||||
|
||||
using StackVecUnhandledTokens = StackVec<const SPatchItemHeader *, 4>;
|
||||
using StackVecByValMap = StackVec<const SPatchDataParameterBuffer *, 8>;
|
||||
using StackVecStrings = StackVec<const SPatchString *, 4>;
|
||||
|
||||
struct KernelArgFromPatchtokens {
|
||||
const SPatchKernelArgumentInfo *argInfo = nullptr;
|
||||
const SPatchItemHeader *objectArg = nullptr;
|
||||
const SPatchDataParameterBuffer *objectId = nullptr;
|
||||
ArgObjectType objectType = ArgObjectType::None;
|
||||
ArgObjectTypeSpecialized objectTypeSpecialized = ArgObjectTypeSpecialized::None;
|
||||
StackVecByValMap byValMap;
|
||||
union {
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *width;
|
||||
const SPatchDataParameterBuffer *height;
|
||||
const SPatchDataParameterBuffer *depth;
|
||||
const SPatchDataParameterBuffer *channelDataType;
|
||||
const SPatchDataParameterBuffer *channelOrder;
|
||||
const SPatchDataParameterBuffer *arraySize;
|
||||
const SPatchDataParameterBuffer *numSamples;
|
||||
const SPatchDataParameterBuffer *numMipLevels;
|
||||
const SPatchDataParameterBuffer *flatBaseOffset;
|
||||
const SPatchDataParameterBuffer *flatWidth;
|
||||
const SPatchDataParameterBuffer *flatHeight;
|
||||
const SPatchDataParameterBuffer *flatPitch;
|
||||
} image;
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *bufferOffset;
|
||||
const SPatchDataParameterBuffer *pureStateful;
|
||||
} buffer;
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *coordinateSnapWaRequired;
|
||||
const SPatchDataParameterBuffer *addressMode;
|
||||
const SPatchDataParameterBuffer *normalizedCoords;
|
||||
} sampler;
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *token;
|
||||
} slm;
|
||||
static_assert((sizeof(image) > sizeof(buffer)) && (sizeof(image) > sizeof(sampler)) && (sizeof(image) > sizeof(slm)),
|
||||
"Union initialization based on image wont' initialize whole struct");
|
||||
} metadata = {};
|
||||
|
||||
union {
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *mbBlockType;
|
||||
const SPatchDataParameterBuffer *subpixelMode;
|
||||
const SPatchDataParameterBuffer *sadAdjustMode;
|
||||
const SPatchDataParameterBuffer *searchPathType;
|
||||
} vme;
|
||||
} metadataSpecialized = {};
|
||||
};
|
||||
|
||||
using StackVecKernelArgs = StackVec<KernelArgFromPatchtokens, 12>;
|
||||
|
||||
struct KernelFromPatchtokens {
|
||||
DecodeError decodeStatus = DecodeError::Undefined;
|
||||
|
||||
const SKernelBinaryHeaderCommon *header = nullptr;
|
||||
ArrayRef<const char> name;
|
||||
ArrayRef<const uint8_t> isa;
|
||||
|
||||
struct {
|
||||
ArrayRef<const uint8_t> generalState;
|
||||
ArrayRef<const uint8_t> dynamicState;
|
||||
ArrayRef<const uint8_t> surfaceState;
|
||||
} heaps;
|
||||
|
||||
struct {
|
||||
ArrayRef<const uint8_t> kernelInfo;
|
||||
ArrayRef<const uint8_t> patchList;
|
||||
} blobs;
|
||||
|
||||
struct {
|
||||
const SPatchSamplerStateArray *samplerStateArray = nullptr;
|
||||
const SPatchBindingTableState *bindingTableState = nullptr;
|
||||
const SPatchAllocateLocalSurface *allocateLocalSurface = nullptr;
|
||||
const SPatchMediaVFEState *mediaVfeState[2] = {nullptr, nullptr};
|
||||
const SPatchMediaInterfaceDescriptorLoad *mediaInterfaceDescriptorLoad = nullptr;
|
||||
const SPatchInterfaceDescriptorData *interfaceDescriptorData = nullptr;
|
||||
const SPatchThreadPayload *threadPayload = nullptr;
|
||||
const SPatchExecutionEnvironment *executionEnvironment = nullptr;
|
||||
const SPatchDataParameterStream *dataParameterStream = nullptr;
|
||||
const SPatchKernelAttributesInfo *kernelAttributesInfo = nullptr;
|
||||
const SPatchAllocateStatelessPrivateSurface *allocateStatelessPrivateSurface = nullptr;
|
||||
const SPatchAllocateStatelessConstantMemorySurfaceWithInitialization *allocateStatelessConstantMemorySurfaceWithInitialization = nullptr;
|
||||
const SPatchAllocateStatelessGlobalMemorySurfaceWithInitialization *allocateStatelessGlobalMemorySurfaceWithInitialization = nullptr;
|
||||
const SPatchAllocateStatelessPrintfSurface *allocateStatelessPrintfSurface = nullptr;
|
||||
const SPatchAllocateStatelessEventPoolSurface *allocateStatelessEventPoolSurface = nullptr;
|
||||
const SPatchAllocateStatelessDefaultDeviceQueueSurface *allocateStatelessDefaultDeviceQueueSurface = nullptr;
|
||||
const SPatchAllocateSyncBuffer *allocateSyncBuffer = nullptr;
|
||||
const SPatchItemHeader *inlineVmeSamplerInfo = nullptr;
|
||||
const SPatchGtpinFreeGRFInfo *gtpinFreeGrfInfo = nullptr;
|
||||
const SPatchStateSIP *stateSip = nullptr;
|
||||
const SPatchAllocateSystemThreadSurface *allocateSystemThreadSurface = nullptr;
|
||||
const SPatchItemHeader *gtpinInfo = nullptr;
|
||||
const SPatchFunctionTableInfo *programSymbolTable = nullptr;
|
||||
const SPatchFunctionTableInfo *programRelocationTable = nullptr;
|
||||
StackVecKernelArgs kernelArgs;
|
||||
StackVecStrings strings;
|
||||
struct {
|
||||
const SPatchDataParameterBuffer *localWorkSize[3] = {};
|
||||
const SPatchDataParameterBuffer *localWorkSize2[3] = {};
|
||||
const SPatchDataParameterBuffer *enqueuedLocalWorkSize[3] = {};
|
||||
const SPatchDataParameterBuffer *numWorkGroups[3] = {};
|
||||
const SPatchDataParameterBuffer *globalWorkOffset[3] = {};
|
||||
const SPatchDataParameterBuffer *globalWorkSize[3] = {};
|
||||
const SPatchDataParameterBuffer *maxWorkGroupSize = nullptr;
|
||||
const SPatchDataParameterBuffer *workDimensions = nullptr;
|
||||
const SPatchDataParameterBuffer *simdSize = nullptr;
|
||||
const SPatchDataParameterBuffer *parentEvent = nullptr;
|
||||
const SPatchDataParameterBuffer *privateMemoryStatelessSize = nullptr;
|
||||
const SPatchDataParameterBuffer *localMemoryStatelessWindowSize = nullptr;
|
||||
const SPatchDataParameterBuffer *localMemoryStatelessWindowStartAddress = nullptr;
|
||||
const SPatchDataParameterBuffer *preferredWorkgroupMultiple = nullptr;
|
||||
StackVec<const SPatchDataParameterBuffer *, 4> childBlockSimdSize;
|
||||
} crossThreadPayloadArgs;
|
||||
} tokens;
|
||||
|
||||
StackVecUnhandledTokens unhandledTokens;
|
||||
};
|
||||
|
||||
struct ProgramFromPatchtokens {
|
||||
DecodeError decodeStatus = DecodeError::Undefined;
|
||||
|
||||
const SProgramBinaryHeader *header = nullptr;
|
||||
struct {
|
||||
ArrayRef<const uint8_t> programInfo;
|
||||
ArrayRef<const uint8_t> patchList;
|
||||
ArrayRef<const uint8_t> kernelsInfo;
|
||||
} blobs;
|
||||
|
||||
struct {
|
||||
StackVec<const SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *, 2> allocateConstantMemorySurface;
|
||||
StackVec<const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *, 2> allocateGlobalMemorySurface;
|
||||
StackVec<const SPatchConstantPointerProgramBinaryInfo *, 4> constantPointer;
|
||||
StackVec<const SPatchGlobalPointerProgramBinaryInfo *, 4> globalPointer;
|
||||
const SPatchFunctionTableInfo *symbolTable = nullptr;
|
||||
} programScopeTokens;
|
||||
StackVec<KernelFromPatchtokens, 2> kernels;
|
||||
StackVec<const SPatchItemHeader *, 4> unhandledTokens;
|
||||
};
|
||||
|
||||
struct KernelArgAttributesFromPatchtokens {
|
||||
ArrayRef<const char> addressQualifier;
|
||||
ArrayRef<const char> accessQualifier;
|
||||
ArrayRef<const char> argName;
|
||||
ArrayRef<const char> typeName;
|
||||
ArrayRef<const char> typeQualifiers;
|
||||
};
|
||||
|
||||
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> kernelBlob, KernelFromPatchtokens &out);
|
||||
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> programBlob, ProgramFromPatchtokens &out);
|
||||
uint32_t calcKernelChecksum(const ArrayRef<const uint8_t> kernelBlob);
|
||||
bool hasInvalidChecksum(const KernelFromPatchtokens &decodedKernel);
|
||||
|
||||
inline const uint8_t *getInlineData(const SPatchAllocateConstantMemorySurfaceProgramBinaryInfo *ptr) {
|
||||
return ptrOffset(reinterpret_cast<const uint8_t *>(ptr), sizeof(SPatchAllocateConstantMemorySurfaceProgramBinaryInfo));
|
||||
}
|
||||
|
||||
inline const uint8_t *getInlineData(const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *ptr) {
|
||||
return ptrOffset(reinterpret_cast<const uint8_t *>(ptr), sizeof(SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo));
|
||||
}
|
||||
|
||||
inline const uint8_t *getInlineData(const SPatchString *ptr) {
|
||||
return ptrOffset(reinterpret_cast<const uint8_t *>(ptr), sizeof(SPatchString));
|
||||
}
|
||||
|
||||
const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumentInfo *ptr);
|
||||
|
||||
const iOpenCL::SProgramBinaryHeader *decodeProgramHeader(const ArrayRef<const uint8_t> programBlob);
|
||||
|
||||
inline bool isValidPatchTokenBinary(const ArrayRef<const uint8_t> programBlob) {
|
||||
return nullptr != decodeProgramHeader(programBlob);
|
||||
}
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
882
shared/source/device_binary_format/patchtokens_dumper.cpp
Normal file
882
shared/source/device_binary_format/patchtokens_dumper.cpp
Normal file
@@ -0,0 +1,882 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "patchtokens_dumper.h"
|
||||
|
||||
#include "patchtokens_decoder.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
#define CASE_TOK_STR(TOK) \
|
||||
case TOK: \
|
||||
return std::to_string(TOK) + "(" + #TOK + ")"; \
|
||||
break;
|
||||
|
||||
std::string asString(PATCH_TOKEN token) {
|
||||
switch (token) {
|
||||
default:
|
||||
return std::to_string(token);
|
||||
CASE_TOK_STR(PATCH_TOKEN_UNKNOWN);
|
||||
CASE_TOK_STR(PATCH_TOKEN_MEDIA_STATE_POINTERS);
|
||||
CASE_TOK_STR(PATCH_TOKEN_STATE_SIP);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CS_URB_STATE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CONSTANT_BUFFER);
|
||||
CASE_TOK_STR(PATCH_TOKEN_SAMPLER_STATE_ARRAY);
|
||||
CASE_TOK_STR(PATCH_TOKEN_INTERFACE_DESCRIPTOR);
|
||||
CASE_TOK_STR(PATCH_TOKEN_VFE_STATE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_BINDING_TABLE_STATE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_SCRATCH_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_SIP_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_LOCAL_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_DATA_PARAMETER_BUFFER);
|
||||
CASE_TOK_STR(PATCH_TOKEN_MEDIA_VFE_STATE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_MEDIA_INTERFACE_DESCRIPTOR_LOAD);
|
||||
CASE_TOK_STR(PATCH_TOKEN_MEDIA_CURBE_LOAD);
|
||||
CASE_TOK_STR(PATCH_TOKEN_INTERFACE_DESCRIPTOR_DATA);
|
||||
CASE_TOK_STR(PATCH_TOKEN_THREAD_PAYLOAD);
|
||||
CASE_TOK_STR(PATCH_TOKEN_EXECUTION_ENVIRONMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_PRIVATE_MEMORY);
|
||||
CASE_TOK_STR(PATCH_TOKEN_DATA_PARAMETER_STREAM);
|
||||
CASE_TOK_STR(PATCH_TOKEN_KERNEL_ARGUMENT_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_KERNEL_ATTRIBUTES_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_STRING);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_PRINTF_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_STATELESS_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_STATELESS_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_PRINTF_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CB_MAPPING);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CB2CR_GATHER_TABLE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_EVENT_POOL_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_NULL_SURFACE_LOCATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_PRIVATE_MEMORY);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_GLOBAL_MEMORY_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_CONSTANT_MEMORY_SURFACE_WITH_INITIALIZATION);
|
||||
CASE_TOK_STR(PATCH_TOKEN_ALLOCATE_STATELESS_DEFAULT_DEVICE_QUEUE_SURFACE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(PATCH_TOKEN_GLOBAL_POINTER_PROGRAM_BINARY_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CONSTANT_POINTER_PROGRAM_BINARY_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_CONSTRUCTOR_DESTRUCTOR_KERNEL_PROGRAM_BINARY_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_INLINE_VME_SAMPLER_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_GTPIN_FREE_GRF_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_GTPIN_INFO);
|
||||
CASE_TOK_STR(PATCH_TOKEN_PROGRAM_SYMBOL_TABLE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_PROGRAM_RELOCATION_TABLE);
|
||||
CASE_TOK_STR(PATCH_TOKEN_MEDIA_VFE_STATE_SLOT1);
|
||||
}
|
||||
}
|
||||
|
||||
std::string asString(DATA_PARAMETER_TOKEN dataParameter) {
|
||||
switch (dataParameter) {
|
||||
default:
|
||||
return std::to_string(dataParameter);
|
||||
CASE_TOK_STR(DATA_PARAMETER_TOKEN_UNKNOWN);
|
||||
CASE_TOK_STR(DATA_PARAMETER_KERNEL_ARGUMENT);
|
||||
CASE_TOK_STR(DATA_PARAMETER_LOCAL_WORK_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_GLOBAL_WORK_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_NUM_WORK_GROUPS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_WORK_DIMENSIONS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_LOCAL_ID);
|
||||
CASE_TOK_STR(DATA_PARAMETER_EXECUTION_MASK);
|
||||
CASE_TOK_STR(DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_WIDTH);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_HEIGHT);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_DEPTH);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_CHANNEL_DATA_TYPE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_CHANNEL_ORDER);
|
||||
CASE_TOK_STR(DATA_PARAMETER_FLAT_IMAGE_BASEOFFSET);
|
||||
CASE_TOK_STR(DATA_PARAMETER_FLAT_IMAGE_WIDTH);
|
||||
CASE_TOK_STR(DATA_PARAMETER_FLAT_IMAGE_HEIGHT);
|
||||
CASE_TOK_STR(DATA_PARAMETER_FLAT_IMAGE_PITCH);
|
||||
CASE_TOK_STR(DATA_PARAMETER_SAMPLER_ADDRESS_MODE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_SAMPLER_NORMALIZED_COORDS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_GLOBAL_WORK_OFFSET);
|
||||
CASE_TOK_STR(DATA_PARAMETER_NUM_HARDWARE_THREADS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_ARRAY_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_PRINTF_SURFACE_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_NUM_SAMPLES);
|
||||
CASE_TOK_STR(DATA_PARAMETER_SAMPLER_COORDINATE_SNAP_WA_REQUIRED);
|
||||
CASE_TOK_STR(DATA_PARAMETER_PARENT_EVENT);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_MB_BLOCK_TYPE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_SUBPIXEL_MODE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_SAD_ADJUST_MODE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_SEARCH_PATH_TYPE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_NUM_MIP_LEVELS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_ENQUEUED_LOCAL_WORK_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_MAX_WORKGROUP_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_PREFERRED_WORKGROUP_MULTIPLE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_START_ADDRESS);
|
||||
CASE_TOK_STR(DATA_PARAMETER_LOCAL_MEMORY_STATELESS_WINDOW_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_PRIVATE_MEMORY_STATELESS_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_SIMD_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_OBJECT_ID);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_IMAGE_TYPE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_VME_MB_SKIP_BLOCK_TYPE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_CHILD_BLOCK_SIMD_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_IMAGE_SRGB_CHANNEL_ORDER);
|
||||
CASE_TOK_STR(DATA_PARAMETER_STAGE_IN_GRID_ORIGIN);
|
||||
CASE_TOK_STR(DATA_PARAMETER_STAGE_IN_GRID_SIZE);
|
||||
CASE_TOK_STR(DATA_PARAMETER_BUFFER_OFFSET);
|
||||
CASE_TOK_STR(DATA_PARAMETER_BUFFER_STATEFUL);
|
||||
}
|
||||
}
|
||||
#undef CASE_TOK_STR
|
||||
|
||||
void dump(const SProgramBinaryHeader &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SProgramBinaryHeader {\n";
|
||||
out << indent << " uint32_t Magic; // = " << value.Magic << "\n";
|
||||
out << indent << " uint32_t Version; // = " << value.Version << "\n";
|
||||
out << indent << "\n";
|
||||
out << indent << " uint32_t Device; // = " << value.Device << "\n";
|
||||
out << indent << " uint32_t GPUPointerSizeInBytes; // = " << value.GPUPointerSizeInBytes << "\n";
|
||||
out << indent << "\n";
|
||||
out << indent << " uint32_t NumberOfKernels; // = " << value.NumberOfKernels << "\n";
|
||||
out << indent << "\n";
|
||||
out << indent << " uint32_t SteppingId; // = " << value.SteppingId << "\n";
|
||||
out << indent << "\n";
|
||||
out << indent << " uint32_t PatchListSize; // = " << value.PatchListSize << "\n";
|
||||
out << indent << "};\n";
|
||||
}
|
||||
|
||||
void dump(const SKernelBinaryHeader &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SKernelBinaryHeader {\n";
|
||||
out << indent << " uint32_t CheckSum;// = " << value.CheckSum << "\n";
|
||||
out << indent << " uint64_t ShaderHashCode;// = " << value.ShaderHashCode << "\n";
|
||||
out << indent << " uint32_t KernelNameSize;// = " << value.KernelNameSize << "\n";
|
||||
out << indent << " uint32_t PatchListSize;// = " << value.PatchListSize << "\n";
|
||||
out << indent << "};\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchDataParameterBuffer &value, std::stringstream &out, const std::string &indent);
|
||||
void dump(const SPatchItemHeader &value, std::stringstream &out, const std::string &indent) {
|
||||
if (value.Token == iOpenCL::PATCH_TOKEN_DATA_PARAMETER_BUFFER) {
|
||||
dump(static_cast<const SPatchDataParameterBuffer &>(value), out, indent);
|
||||
return;
|
||||
}
|
||||
out << indent << "struct SPatchItemHeader {\n";
|
||||
out << indent << " uint32_t Token;// = " << asString(static_cast<PATCH_TOKEN>(value.Token)) << "\n";
|
||||
out << indent << " uint32_t Size;// = " << value.Size << "\n";
|
||||
out << indent << "};\n";
|
||||
}
|
||||
|
||||
void dumpPatchItemHeaderInline(const SPatchItemHeader &value, std::stringstream &out, const std::string &indent) {
|
||||
out << "Token=" << asString(static_cast<PATCH_TOKEN>(value.Token)) << ", Size=" << value.Size;
|
||||
}
|
||||
|
||||
void dump(const SPatchGlobalMemoryObjectKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchGlobalMemoryObjectKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchImageMemoryObjectKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchImageMemoryObjectKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t Type;// = " << value.Type << "\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t Writeable;// = " << value.Writeable << "\n";
|
||||
out << indent << " uint32_t Transformable;// = " << value.Transformable << "\n";
|
||||
out << indent << " uint32_t needBindlessHandle;// = " << value.needBindlessHandle << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << " uint32_t btiOffset;// = " << value.btiOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchSamplerKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchSamplerKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t Type;// = " << value.Type << "\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t needBindlessHandle;// = " << value.needBindlessHandle << "\n";
|
||||
out << indent << " uint32_t TextureMask;// = " << value.TextureMask << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << " uint32_t btiOffset;// = " << value.btiOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchDataParameterBuffer &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchDataParameterBuffer :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Type;// = " << asString(static_cast<DATA_PARAMETER_TOKEN>(value.Type)) << "\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t DataSize;// = " << value.DataSize << "\n";
|
||||
out << indent << " uint32_t SourceOffset;// = " << value.SourceOffset << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchKernelArgumentInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
auto toStr = [](ArrayRef<const char> &src) { return std::string(src.begin(), src.end()); };
|
||||
auto inlineData = getInlineData(&value);
|
||||
out << indent << "struct SPatchKernelArgumentInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t AddressQualifierSize;// = " << value.AddressQualifierSize << " : [" << toStr(inlineData.addressQualifier) << "]\n";
|
||||
out << indent << " uint32_t AccessQualifierSize;// = " << value.AccessQualifierSize << " : [" << toStr(inlineData.accessQualifier) << "]\n";
|
||||
out << indent << " uint32_t ArgumentNameSize;// = " << value.ArgumentNameSize << " : [" << toStr(inlineData.argName) << "]\n";
|
||||
out << indent << " uint32_t TypeNameSize;// = " << value.TypeNameSize << " : [" << toStr(inlineData.typeName) << "]\n";
|
||||
out << indent << " uint32_t TypeQualifierSize;// = " << value.TypeQualifierSize << " : [" << toStr(inlineData.typeQualifiers) << "]\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchKernelAttributesInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchKernelAttributesInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t AttributesSize;// = " << value.AttributesSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchMediaInterfaceDescriptorLoad &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchMediaInterfaceDescriptorLoad :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t InterfaceDescriptorDataOffset;// = " << value.InterfaceDescriptorDataOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchInterfaceDescriptorData &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchInterfaceDescriptorData :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t SamplerStateOffset;// = " << value.SamplerStateOffset << "\n";
|
||||
out << indent << " uint32_t KernelOffset;// = " << value.KernelOffset << "\n";
|
||||
out << indent << " uint32_t BindingTableOffset;// = " << value.BindingTableOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchDataParameterStream &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchDataParameterStream :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t DataParameterStreamSize;// = " << value.DataParameterStreamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchStateSIP &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchStateSIP :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t SystemKernelOffset;// = " << value.SystemKernelOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchSamplerStateArray &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchSamplerStateArray :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t Count;// = " << value.Count << "\n";
|
||||
out << indent << " uint32_t BorderColorOffset;// = " << value.BorderColorOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchBindingTableState &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchBindingTableState :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t Count;// = " << value.Count << "\n";
|
||||
out << indent << " uint32_t SurfaceStateOffset;// = " << value.SurfaceStateOffset << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateSystemThreadSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateSystemThreadSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t PerThreadSystemThreadSurfaceSize;// = " << value.PerThreadSystemThreadSurfaceSize << "\n";
|
||||
out << indent << " uint32_t BTI;// = " << value.BTI << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateLocalSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateLocalSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Offset;// = " << value.Offset << "\n";
|
||||
out << indent << " uint32_t TotalInlineLocalMemorySize;// = " << value.TotalInlineLocalMemorySize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchThreadPayload &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchThreadPayload :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t HeaderPresent;// = " << value.HeaderPresent << "\n";
|
||||
out << indent << " uint32_t LocalIDXPresent;// = " << value.LocalIDXPresent << "\n";
|
||||
out << indent << " uint32_t LocalIDYPresent;// = " << value.LocalIDYPresent << "\n";
|
||||
out << indent << " uint32_t LocalIDZPresent;// = " << value.LocalIDZPresent << "\n";
|
||||
out << indent << " uint32_t LocalIDFlattenedPresent;// = " << value.LocalIDFlattenedPresent << "\n";
|
||||
out << indent << " uint32_t IndirectPayloadStorage;// = " << value.IndirectPayloadStorage << "\n";
|
||||
out << indent << " uint32_t UnusedPerThreadConstantPresent;// = " << value.UnusedPerThreadConstantPresent << "\n";
|
||||
out << indent << " uint32_t GetLocalIDPresent;// = " << value.GetLocalIDPresent << "\n";
|
||||
out << indent << " uint32_t GetGroupIDPresent;// = " << value.GetGroupIDPresent << "\n";
|
||||
out << indent << " uint32_t GetGlobalOffsetPresent;// = " << value.GetGlobalOffsetPresent << "\n";
|
||||
out << indent << " uint32_t StageInGridOriginPresent;// = " << value.StageInGridOriginPresent << "\n";
|
||||
out << indent << " uint32_t StageInGridSizePresent;// = " << value.StageInGridSizePresent << "\n";
|
||||
out << indent << " uint32_t OffsetToSkipPerThreadDataLoad;// = " << value.OffsetToSkipPerThreadDataLoad << "\n";
|
||||
out << indent << " uint32_t OffsetToSkipSetFFIDGP;// = " << value.OffsetToSkipSetFFIDGP << "\n";
|
||||
out << indent << " uint32_t PassInlineData;// = " << value.PassInlineData << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchExecutionEnvironment &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchExecutionEnvironment :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t RequiredWorkGroupSizeX;// = " << value.RequiredWorkGroupSizeX << "\n";
|
||||
out << indent << " uint32_t RequiredWorkGroupSizeY;// = " << value.RequiredWorkGroupSizeY << "\n";
|
||||
out << indent << " uint32_t RequiredWorkGroupSizeZ;// = " << value.RequiredWorkGroupSizeZ << "\n";
|
||||
out << indent << " uint32_t LargestCompiledSIMDSize;// = " << value.LargestCompiledSIMDSize << "\n";
|
||||
out << indent << " uint32_t CompiledSubGroupsNumber;// = " << value.CompiledSubGroupsNumber << "\n";
|
||||
out << indent << " uint32_t HasBarriers;// = " << value.HasBarriers << "\n";
|
||||
out << indent << " uint32_t DisableMidThreadPreemption;// = " << value.DisableMidThreadPreemption << "\n";
|
||||
out << indent << " uint32_t CompiledSIMD8;// = " << value.CompiledSIMD8 << "\n";
|
||||
out << indent << " uint32_t CompiledSIMD16;// = " << value.CompiledSIMD16 << "\n";
|
||||
out << indent << " uint32_t CompiledSIMD32;// = " << value.CompiledSIMD32 << "\n";
|
||||
out << indent << " uint32_t HasDeviceEnqueue;// = " << value.HasDeviceEnqueue << "\n";
|
||||
out << indent << " uint32_t MayAccessUndeclaredResource;// = " << value.MayAccessUndeclaredResource << "\n";
|
||||
out << indent << " uint32_t UsesFencesForReadWriteImages;// = " << value.UsesFencesForReadWriteImages << "\n";
|
||||
out << indent << " uint32_t UsesStatelessSpillFill;// = " << value.UsesStatelessSpillFill << "\n";
|
||||
out << indent << " uint32_t UsesMultiScratchSpaces;// = " << value.UsesMultiScratchSpaces << "\n";
|
||||
out << indent << " uint32_t IsCoherent;// = " << value.IsCoherent << "\n";
|
||||
out << indent << " uint32_t IsInitializer;// = " << value.IsInitializer << "\n";
|
||||
out << indent << " uint32_t IsFinalizer;// = " << value.IsFinalizer << "\n";
|
||||
out << indent << " uint32_t SubgroupIndependentForwardProgressRequired;// = " << value.SubgroupIndependentForwardProgressRequired << "\n";
|
||||
out << indent << " uint32_t CompiledForGreaterThan4GBBuffers;// = " << value.CompiledForGreaterThan4GBBuffers << "\n";
|
||||
out << indent << " uint32_t NumGRFRequired;// = " << value.NumGRFRequired << "\n";
|
||||
out << indent << " uint32_t WorkgroupWalkOrderDims;// = " << value.WorkgroupWalkOrderDims << "\n";
|
||||
out << indent << " uint32_t HasGlobalAtomics;// = " << value.HasGlobalAtomics << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchString &value, std::stringstream &out, const std::string &indent) {
|
||||
const char *strBeg = reinterpret_cast<const char *>((&value) + 1);
|
||||
std::string strValue = std::string(strBeg, strBeg + value.StringSize);
|
||||
out << indent << "struct SPatchString :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Index;// = " << value.Index << "\n";
|
||||
out << indent << " uint32_t StringSize;// = " << value.StringSize << " : [" << strValue << "]"
|
||||
<< "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchStatelessGlobalMemoryObjectKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchStatelessGlobalMemoryObjectKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchStatelessConstantMemoryObjectKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchStatelessConstantMemoryObjectKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessGlobalMemorySurfaceWithInitialization &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessGlobalMemorySurfaceWithInitialization :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t GlobalBufferIndex;// = " << value.GlobalBufferIndex << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessConstantMemorySurfaceWithInitialization &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessConstantMemorySurfaceWithInitialization :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ConstantBufferIndex;// = " << value.ConstantBufferIndex << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t Type;// = " << value.Type << "\n";
|
||||
out << indent << " uint32_t GlobalBufferIndex;// = " << value.GlobalBufferIndex << "\n";
|
||||
out << indent << " uint32_t InlineDataSize;// = " << value.InlineDataSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateConstantMemorySurfaceProgramBinaryInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateConstantMemorySurfaceProgramBinaryInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ConstantBufferIndex;// = " << value.ConstantBufferIndex << "\n";
|
||||
out << indent << " uint32_t InlineDataSize;// = " << value.InlineDataSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchGlobalPointerProgramBinaryInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchGlobalPointerProgramBinaryInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t GlobalBufferIndex;// = " << value.GlobalBufferIndex << "\n";
|
||||
out << indent << " uint64_t GlobalPointerOffset;// = " << value.GlobalPointerOffset << "\n";
|
||||
out << indent << " uint32_t BufferType;// = " << value.BufferType << "\n";
|
||||
out << indent << " uint32_t BufferIndex;// = " << value.BufferIndex << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchConstantPointerProgramBinaryInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchConstantPointerProgramBinaryInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ConstantBufferIndex;// = " << value.ConstantBufferIndex << "\n";
|
||||
out << indent << " uint64_t ConstantPointerOffset;// = " << value.ConstantPointerOffset << "\n";
|
||||
out << indent << " uint32_t BufferType;// = " << value.BufferType << "\n";
|
||||
out << indent << " uint32_t BufferIndex;// = " << value.BufferIndex << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessPrintfSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessPrintfSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t PrintfSurfaceIndex;// = " << value.PrintfSurfaceIndex << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessPrivateSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessPrivateSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << " uint32_t PerThreadPrivateMemorySize;// = " << value.PerThreadPrivateMemorySize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchMediaVFEState &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchMediaVFEState :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ScratchSpaceOffset;// = " << value.ScratchSpaceOffset << "\n";
|
||||
out << indent << " uint32_t PerThreadScratchSpace;// = " << value.PerThreadScratchSpace << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessEventPoolSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessEventPoolSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t EventPoolSurfaceIndex;// = " << value.EventPoolSurfaceIndex << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchAllocateStatelessDefaultDeviceQueueSurface &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchAllocateStatelessDefaultDeviceQueueSurface :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchStatelessDeviceQueueKernelArgument &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchStatelessDeviceQueueKernelArgument :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t ArgumentNumber;// = " << value.ArgumentNumber << "\n";
|
||||
out << indent << " uint32_t SurfaceStateHeapOffset;// = " << value.SurfaceStateHeapOffset << "\n";
|
||||
out << indent << " uint32_t DataParamOffset;// = " << value.DataParamOffset << "\n";
|
||||
out << indent << " uint32_t DataParamSize;// = " << value.DataParamSize << "\n";
|
||||
out << indent << " uint32_t LocationIndex;// = " << value.LocationIndex << "\n";
|
||||
out << indent << " uint32_t LocationIndex2;// = " << value.LocationIndex2 << "\n";
|
||||
out << indent << " uint32_t IsEmulationArgument;// = " << value.IsEmulationArgument << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchGtpinFreeGRFInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchGtpinFreeGRFInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t BufferSize;// = " << value.BufferSize << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
void dump(const SPatchFunctionTableInfo &value, std::stringstream &out, const std::string &indent) {
|
||||
out << indent << "struct SPatchFunctionTableInfo :\n";
|
||||
out << indent << " SPatchItemHeader (";
|
||||
dumpPatchItemHeaderInline(value, out, "");
|
||||
out << ")\n"
|
||||
<< indent << "{\n";
|
||||
out << indent << " uint32_t NumEntries;// = " << value.NumEntries << "\n";
|
||||
out << indent << "}\n";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dumpOrNull(const T *value, const std::string &messageIfNull, std::stringstream &out, const std::string &indent) {
|
||||
if (value == nullptr) {
|
||||
if (messageIfNull.empty() == false) {
|
||||
out << indent << messageIfNull;
|
||||
}
|
||||
return;
|
||||
}
|
||||
dump(*value, out, indent);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dumpOrNullObjArg(const T *value, std::stringstream &out, const std::string &indent) {
|
||||
if (value == nullptr) {
|
||||
return;
|
||||
}
|
||||
switch (value->Token) {
|
||||
default:
|
||||
UNRECOVERABLE_IF(value->Token != PATCH_TOKEN_SAMPLER_KERNEL_ARGUMENT);
|
||||
dumpOrNull(reinterpret_cast<const SPatchSamplerKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
case PATCH_TOKEN_IMAGE_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
dumpOrNull(reinterpret_cast<const SPatchImageMemoryObjectKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
case PATCH_TOKEN_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
dumpOrNull(reinterpret_cast<const SPatchGlobalMemoryObjectKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_GLOBAL_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
dumpOrNull(reinterpret_cast<const SPatchStatelessGlobalMemoryObjectKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_CONSTANT_MEMORY_OBJECT_KERNEL_ARGUMENT:
|
||||
dumpOrNull(reinterpret_cast<const SPatchStatelessConstantMemoryObjectKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
case PATCH_TOKEN_STATELESS_DEVICE_QUEUE_KERNEL_ARGUMENT:
|
||||
dumpOrNull(reinterpret_cast<const SPatchStatelessDeviceQueueKernelArgument *>(value), "", out, indent);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, size_t Size>
|
||||
void dumpOrNullArrayIfNotEmpty(T (&value)[Size], const std::string &arrayName, std::stringstream &out, const std::string &indent) {
|
||||
bool allEmpty = true;
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
allEmpty = allEmpty && (value[i] == nullptr);
|
||||
}
|
||||
if (allEmpty) {
|
||||
return;
|
||||
}
|
||||
out << indent << arrayName << " [" << Size << "] :\n";
|
||||
for (size_t i = 0; i < Size; ++i) {
|
||||
if (value[i] == nullptr) {
|
||||
continue;
|
||||
}
|
||||
out << indent << " + [" << i << "]:\n";
|
||||
dump(*value[i], out, indent + " | ");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void dumpVecIfNotEmpty(const T &vector, const std::string &vectorName, std::stringstream &out, const std::string &indent) {
|
||||
if (vector.size() == 0) {
|
||||
return;
|
||||
}
|
||||
out << indent << vectorName << " [" << vector.size() << "] :\n";
|
||||
for (size_t i = 0; i < vector.size(); ++i) {
|
||||
out << indent << " + [" << i << "]:\n";
|
||||
dumpOrNull(vector[i], "DECODER INTERNAL ERROR\n", out, indent + " | ");
|
||||
}
|
||||
}
|
||||
|
||||
std::string asString(const ProgramFromPatchtokens &prog) {
|
||||
std::stringstream stream;
|
||||
stream << "Program of size : " << prog.blobs.programInfo.size()
|
||||
<< " " << asString(prog.decodeStatus) << "\n";
|
||||
dumpOrNull(prog.header, "WARNING : Program header is missing\n", stream, "");
|
||||
stream << "Program-scope tokens section size : " << prog.blobs.patchList.size() << "\n";
|
||||
dumpVecIfNotEmpty(prog.unhandledTokens, "WARNING : Unhandled program-scope tokens detected", stream, " ");
|
||||
dumpVecIfNotEmpty(prog.programScopeTokens.allocateConstantMemorySurface, "Inline Costant Surface(s)", stream, " ");
|
||||
dumpVecIfNotEmpty(prog.programScopeTokens.constantPointer, "Inline Costant Surface - self relocations", stream, " ");
|
||||
dumpVecIfNotEmpty(prog.programScopeTokens.allocateGlobalMemorySurface, "Inline Global Variable Surface(s)", stream, " ");
|
||||
dumpVecIfNotEmpty(prog.programScopeTokens.globalPointer, "Inline Global Variable Surface - self relocations", stream, " ");
|
||||
dumpOrNull(prog.programScopeTokens.symbolTable, "", stream, " ");
|
||||
stream << "Kernels section size : " << prog.blobs.kernelsInfo.size() << "\n";
|
||||
for (size_t i = 0; i < prog.kernels.size(); ++i) {
|
||||
stream << "kernel[" << i << "] " << (prog.kernels[i].name.size() > 0 ? std::string(prog.kernels[i].name.begin(), prog.kernels[i].name.end()).c_str() : "<UNNAMED>") << ":\n";
|
||||
stream << asString(prog.kernels[i]);
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string asString(const KernelFromPatchtokens &kern) {
|
||||
std::stringstream stream;
|
||||
std::string indentLevel1 = " ";
|
||||
stream << "Kernel of size : " << kern.blobs.kernelInfo.size() << " "
|
||||
<< " " << asString(kern.decodeStatus) << "\n";
|
||||
dumpOrNull(kern.header, "WARNING : Kernel header is missing\n", stream, "");
|
||||
stream << "Kernel-scope tokens section size : " << kern.blobs.patchList.size() << "\n";
|
||||
dumpVecIfNotEmpty(kern.unhandledTokens, "WARNING : Unhandled kernel-scope tokens detected", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.executionEnvironment, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.threadPayload, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.samplerStateArray, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.bindingTableState, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateLocalSurface, "", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.mediaVfeState, "mediaVfeState", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.mediaInterfaceDescriptorLoad, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.interfaceDescriptorData, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.kernelAttributesInfo, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessPrivateSurface, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessConstantMemorySurfaceWithInitialization, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessGlobalMemorySurfaceWithInitialization, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessPrintfSurface, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessEventPoolSurface, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateStatelessDefaultDeviceQueueSurface, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.inlineVmeSamplerInfo, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.gtpinFreeGrfInfo, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.stateSip, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.allocateSystemThreadSurface, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.gtpinInfo, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.programSymbolTable, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.programRelocationTable, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.dataParameterStream, "", stream, indentLevel1);
|
||||
dumpVecIfNotEmpty(kern.tokens.strings, "String literals", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.localWorkSize, "localWorkSize", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.localWorkSize2, "localWorkSize2", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.enqueuedLocalWorkSize, "enqueuedLocalWorkSize", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.numWorkGroups, "numWorkGroups", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.globalWorkOffset, "globalWorkOffset", stream, indentLevel1);
|
||||
dumpOrNullArrayIfNotEmpty(kern.tokens.crossThreadPayloadArgs.globalWorkSize, "globalWorkSize", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.maxWorkGroupSize, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.workDimensions, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.simdSize, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.parentEvent, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.privateMemoryStatelessSize, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowSize, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.localMemoryStatelessWindowStartAddress, "", stream, indentLevel1);
|
||||
dumpOrNull(kern.tokens.crossThreadPayloadArgs.preferredWorkgroupMultiple, "", stream, indentLevel1);
|
||||
dumpVecIfNotEmpty(kern.tokens.crossThreadPayloadArgs.childBlockSimdSize, "Child block simd size(s)", stream, indentLevel1);
|
||||
|
||||
if (kern.tokens.kernelArgs.size() != 0) {
|
||||
stream << "Kernel arguments [" << kern.tokens.kernelArgs.size() << "] :\n";
|
||||
for (size_t i = 0; i < kern.tokens.kernelArgs.size(); ++i) {
|
||||
stream << " + kernelArg[" << i << "]:\n";
|
||||
stream << asString(kern.tokens.kernelArgs[i], indentLevel1 + "| ");
|
||||
}
|
||||
}
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
std::string asString(ArgObjectType type, ArgObjectTypeSpecialized typeSpecialized) {
|
||||
std::string typeAsStr;
|
||||
switch (type) {
|
||||
default:
|
||||
UNRECOVERABLE_IF(ArgObjectType::None != type);
|
||||
return "unspecified";
|
||||
case ArgObjectType::Buffer:
|
||||
typeAsStr = "BUFFER";
|
||||
break;
|
||||
case ArgObjectType::Image:
|
||||
typeAsStr = "IMAGE";
|
||||
break;
|
||||
case ArgObjectType::Sampler:
|
||||
typeAsStr = "SAMPLER";
|
||||
break;
|
||||
case ArgObjectType::Slm:
|
||||
typeAsStr = "SLM";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (typeSpecialized) {
|
||||
default:
|
||||
UNRECOVERABLE_IF(ArgObjectTypeSpecialized::None != typeSpecialized);
|
||||
break;
|
||||
case ArgObjectTypeSpecialized::Vme:
|
||||
typeAsStr += " [ VME ]";
|
||||
}
|
||||
|
||||
return typeAsStr;
|
||||
}
|
||||
|
||||
std::string asString(const KernelArgFromPatchtokens &arg, const std::string &indent) {
|
||||
std::stringstream stream;
|
||||
stream << indent << "Kernel argument of type " << asString(arg.objectType, arg.objectTypeSpecialized) << "\n";
|
||||
std::string indentLevel1 = indent + " ";
|
||||
std::string indentLevel2 = indentLevel1 + " ";
|
||||
dumpOrNull(arg.argInfo, "", stream, indentLevel1);
|
||||
dumpOrNullObjArg(arg.objectArg, stream, indentLevel1);
|
||||
dumpOrNull(arg.objectId, "", stream, indentLevel1);
|
||||
switch (arg.objectType) {
|
||||
default:
|
||||
break;
|
||||
case ArgObjectType::Buffer:
|
||||
stream << indentLevel1 << "Buffer Metadata:\n";
|
||||
dumpOrNull(arg.metadata.buffer.bufferOffset, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.buffer.pureStateful, "", stream, indentLevel2);
|
||||
break;
|
||||
case ArgObjectType::Image:
|
||||
stream << indentLevel1 << "Image Metadata:\n";
|
||||
dumpOrNull(arg.metadata.image.width, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.height, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.depth, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.channelDataType, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.channelOrder, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.arraySize, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.numSamples, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.numMipLevels, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.flatBaseOffset, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.flatWidth, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.flatHeight, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.image.flatPitch, "", stream, indentLevel2);
|
||||
break;
|
||||
case ArgObjectType::Sampler:
|
||||
stream << indentLevel1 << "Sampler Metadata:\n";
|
||||
dumpOrNull(arg.metadata.sampler.addressMode, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.sampler.coordinateSnapWaRequired, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadata.sampler.normalizedCoords, "", stream, indentLevel2);
|
||||
break;
|
||||
case ArgObjectType::Slm:
|
||||
stream << indentLevel1 << "Slm Metadata:\n";
|
||||
dumpOrNull(arg.metadata.slm.token, "", stream, indentLevel2);
|
||||
break;
|
||||
}
|
||||
switch (arg.objectTypeSpecialized) {
|
||||
default:
|
||||
break;
|
||||
case ArgObjectTypeSpecialized::Vme:
|
||||
stream << indentLevel1 << "Vme Metadata:\n";
|
||||
dumpOrNull(arg.metadataSpecialized.vme.mbBlockType, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadataSpecialized.vme.sadAdjustMode, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadataSpecialized.vme.searchPathType, "", stream, indentLevel2);
|
||||
dumpOrNull(arg.metadataSpecialized.vme.subpixelMode, "", stream, indentLevel2);
|
||||
break;
|
||||
}
|
||||
|
||||
dumpVecIfNotEmpty(arg.byValMap, " Data passed by value ", stream, indentLevel1);
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
26
shared/source/device_binary_format/patchtokens_dumper.h
Normal file
26
shared/source/device_binary_format/patchtokens_dumper.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
struct ProgramFromPatchtokens;
|
||||
struct KernelFromPatchtokens;
|
||||
struct KernelArgFromPatchtokens;
|
||||
|
||||
std::string asString(const ProgramFromPatchtokens &prog);
|
||||
std::string asString(const KernelFromPatchtokens &kern);
|
||||
std::string asString(const KernelArgFromPatchtokens &arg, const std::string &indent);
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
150
shared/source/device_binary_format/patchtokens_validator.cpp
Normal file
150
shared/source/device_binary_format/patchtokens_validator.cpp
Normal file
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "device_binary_format/patchtokens_validator.h"
|
||||
|
||||
#include "device_binary_format/patchtokens_decoder.h"
|
||||
#include "helpers/hw_info.h"
|
||||
#include "opencl/source/program/kernel_arg_info.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
bool allowUnhandledTokens = true;
|
||||
|
||||
DecodeError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
std::string &outErrReason, std::string &outWarnings) {
|
||||
if (decodedProgram.decodeStatus != DecodeError::Success) {
|
||||
outErrReason = "ProgramFromPatchtokens wasn't successfully decoded";
|
||||
return DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
if (decodedProgram.programScopeTokens.allocateConstantMemorySurface.size() > 1) {
|
||||
outErrReason = "Unhandled number of global constants surfaces > 1";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size() > 1) {
|
||||
outErrReason = "Unhandled number of global variables surfaces > 1";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
for (const auto &globalConstantPointerToken : decodedProgram.programScopeTokens.constantPointer) {
|
||||
bool isUnhandled = (globalConstantPointerToken->ConstantBufferIndex != 0);
|
||||
isUnhandled |= (globalConstantPointerToken->BufferIndex != 0);
|
||||
isUnhandled |= (globalConstantPointerToken->BufferType != PROGRAM_SCOPE_CONSTANT_BUFFER) && (globalConstantPointerToken->BufferType != PROGRAM_SCOPE_GLOBAL_BUFFER);
|
||||
isUnhandled |= (globalConstantPointerToken->BufferType == PROGRAM_SCOPE_GLOBAL_BUFFER) && (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.empty());
|
||||
isUnhandled |= (decodedProgram.programScopeTokens.allocateConstantMemorySurface.empty()) || decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize < globalConstantPointerToken->ConstantPointerOffset + sizeof(uint32_t);
|
||||
|
||||
if (isUnhandled) {
|
||||
outErrReason = "Unhandled SPatchConstantPointerProgramBinaryInfo";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &globalVariablePointerToken : decodedProgram.programScopeTokens.globalPointer) {
|
||||
bool isUnhandled = (globalVariablePointerToken->GlobalBufferIndex != 0);
|
||||
isUnhandled |= (globalVariablePointerToken->BufferIndex != 0);
|
||||
isUnhandled |= (globalVariablePointerToken->BufferType != PROGRAM_SCOPE_GLOBAL_BUFFER) && (globalVariablePointerToken->BufferType != PROGRAM_SCOPE_CONSTANT_BUFFER);
|
||||
isUnhandled |= (globalVariablePointerToken->BufferType == PROGRAM_SCOPE_CONSTANT_BUFFER) && (decodedProgram.programScopeTokens.allocateConstantMemorySurface.empty());
|
||||
isUnhandled |= (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.empty()) || decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize < globalVariablePointerToken->GlobalPointerOffset + sizeof(uint32_t);
|
||||
|
||||
if (isUnhandled) {
|
||||
outErrReason = "Unhandled SPatchGlobalPointerProgramBinaryInfo";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &unhandledToken : decodedProgram.unhandledTokens) {
|
||||
if (allowUnhandledTokens) {
|
||||
outWarnings = "Unknown program-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
} else {
|
||||
outErrReason = "Unhandled required program-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
UNRECOVERABLE_IF(nullptr == decodedProgram.header);
|
||||
if (decodedProgram.header->Version != CURRENT_ICBE_VERSION) {
|
||||
outErrReason = "Unhandled Version of Patchtokens: expected: " + std::to_string(CURRENT_ICBE_VERSION) + ", got: " + std::to_string(decodedProgram.header->Version);
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if ((decodedProgram.header->GPUPointerSizeInBytes != 4U) && (decodedProgram.header->GPUPointerSizeInBytes != 8U)) {
|
||||
outErrReason = "Invalid pointer size";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
for (const auto &decodedKernel : decodedProgram.kernels) {
|
||||
if (decodedKernel.decodeStatus != DecodeError::Success) {
|
||||
outErrReason = "KernelFromPatchtokens wasn't successfully decoded";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
UNRECOVERABLE_IF(nullptr == decodedKernel.header);
|
||||
if (hasInvalidChecksum(decodedKernel)) {
|
||||
outErrReason = "KernelFromPatchtokens has invalid checksum";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if (nullptr == decodedKernel.tokens.executionEnvironment) {
|
||||
outErrReason = "Missing execution environment";
|
||||
return DecodeError::UnhandledBinary;
|
||||
} else {
|
||||
switch (decodedKernel.tokens.executionEnvironment->LargestCompiledSIMDSize) {
|
||||
case 1:
|
||||
break;
|
||||
case 8:
|
||||
break;
|
||||
case 16:
|
||||
break;
|
||||
case 32:
|
||||
break;
|
||||
default:
|
||||
outErrReason = "Invalid LargestCompiledSIMDSize";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &kernelArg : decodedKernel.tokens.kernelArgs) {
|
||||
if (kernelArg.argInfo == nullptr) {
|
||||
continue;
|
||||
}
|
||||
auto argInfoInlineData = getInlineData(kernelArg.argInfo);
|
||||
auto accessQualifier = KernelArgMetadata::parseAccessQualifier(parseLimitedString(argInfoInlineData.accessQualifier.begin(), argInfoInlineData.accessQualifier.size()));
|
||||
if (KernelArgMetadata::AccessQualifier::Unknown == accessQualifier) {
|
||||
outErrReason = "Unhandled access qualifier";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
auto addressQualifier = KernelArgMetadata::parseAddressSpace(parseLimitedString(argInfoInlineData.addressQualifier.begin(), argInfoInlineData.addressQualifier.size()));
|
||||
if (KernelArgMetadata::AddressSpaceQualifier::Unknown == addressQualifier) {
|
||||
outErrReason = "Unhandled address qualifier";
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &unhandledToken : decodedKernel.unhandledTokens) {
|
||||
if (allowUnhandledTokens) {
|
||||
outWarnings = "Unknown kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
} else {
|
||||
outErrReason = "Unhandled required kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return DecodeError::Success;
|
||||
}
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
26
shared/source/device_binary_format/patchtokens_validator.h
Normal file
26
shared/source/device_binary_format/patchtokens_validator.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "device_binary_format/device_binary_formats.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
extern bool allowUnhandledTokens;
|
||||
|
||||
struct ProgramFromPatchtokens;
|
||||
|
||||
DecodeError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
std::string &outErrReason, std::string &outWarnings);
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
|
||||
} // namespace NEO
|
||||
Reference in New Issue
Block a user