mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-24 12:23:05 +08:00
Program refactor
* Decouple binary program handling from Program object * Add binary formats multiplexer * Improve Elf format support Change-Id: Ic22aff40173532e14825d70b82ec53fcc5fa9fdf
This commit is contained in:
2
Jenkinsfile
vendored
2
Jenkinsfile
vendored
@@ -1,5 +1,5 @@
|
||||
#!groovy
|
||||
dependenciesRevision='b44862a6724fe290b73ef3b4db9e02076384abef-1368'
|
||||
strategy='EQUAL'
|
||||
allowedCD=253
|
||||
allowedCD=219
|
||||
allowedF=11
|
||||
|
||||
@@ -13,6 +13,7 @@ set(NEO_COMPILER_INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface.inl
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/create_main.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/default_cache_config.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_options/compiler_options_base.h
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -106,8 +106,9 @@ class CompilerInterface {
|
||||
CompilerInterface &operator=(CompilerInterface &&) = delete;
|
||||
virtual ~CompilerInterface();
|
||||
|
||||
static CompilerInterface *createInstance(std::unique_ptr<CompilerCache> cache, bool requireFcl) {
|
||||
auto instance = new CompilerInterface();
|
||||
template <typename CompilerInterfaceT = CompilerInterface>
|
||||
static CompilerInterfaceT *createInstance(std::unique_ptr<CompilerCache> cache, bool requireFcl) {
|
||||
auto instance = new CompilerInterfaceT();
|
||||
if (!instance->initialize(std::move(cache), requireFcl)) {
|
||||
delete instance;
|
||||
instance = nullptr;
|
||||
@@ -137,7 +138,7 @@ class CompilerInterface {
|
||||
MOCKABLE_VIRTUAL TranslationOutput::ErrorCode getSipKernelBinary(NEO::Device &device, SipKernelType type, std::vector<char> &retBinary);
|
||||
|
||||
protected:
|
||||
bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl);
|
||||
MOCKABLE_VIRTUAL bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl);
|
||||
MOCKABLE_VIRTUAL bool loadFcl();
|
||||
MOCKABLE_VIRTUAL bool loadIgc();
|
||||
|
||||
|
||||
36
core/compiler_interface/intermediate_representations.h
Normal file
36
core/compiler_interface/intermediate_representations.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/utilities/arrayref.h"
|
||||
#include "core/utilities/const_stringref.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
static constexpr ConstStringRef llvmBcMagic = "BC\xc0\xde";
|
||||
static constexpr ConstStringRef spirvMagic = "\x07\x23\x02\x03";
|
||||
static constexpr ConstStringRef spirvMagicInv = "\x03\x02\x23\x07";
|
||||
|
||||
inline bool hasSameMagic(ConstStringRef expectedMagic, ArrayRef<const uint8_t> binary) {
|
||||
auto binaryMagicLen = std::min(expectedMagic.size(), binary.size());
|
||||
ConstStringRef binaryMagic(reinterpret_cast<const char *>(binary.begin()), binaryMagicLen);
|
||||
return expectedMagic == binaryMagic;
|
||||
}
|
||||
|
||||
inline bool isLlvmBitcode(ArrayRef<const uint8_t> binary) {
|
||||
return hasSameMagic(llvmBcMagic, binary);
|
||||
}
|
||||
|
||||
inline bool isSpirVBitcode(ArrayRef<const uint8_t> binary) {
|
||||
return hasSameMagic(spirvMagic, binary) || hasSameMagic(spirvMagicInv, binary);
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -6,11 +6,22 @@
|
||||
|
||||
set(NEO_DEVICE_BINARY_FORMAT
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${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.inl
|
||||
${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})
|
||||
|
||||
158
core/device_binary_format/device_binary_format_ocl_elf.cpp
Normal file
158
core/device_binary_format/device_binary_format_ocl_elf.cpp
Normal file
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/compiler_support.h"
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.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 "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/device_binary_format/patchtokens_dumper.h"
|
||||
#include "core/device_binary_format/patchtokens_validator.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#include "core/program/program_info_from_patchtokens.h"
|
||||
#include "runtime/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
core/device_binary_format/device_binary_formats.cpp
Normal file
16
core/device_binary_format/device_binary_formats.cpp
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/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
|
||||
153
core/device_binary_format/device_binary_formats.h
Normal file
153
core/device_binary_format/device_binary_formats.h
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/utilities/arrayref.h"
|
||||
#include "core/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
|
||||
};
|
||||
|
||||
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>);
|
||||
|
||||
inline bool isAnyDeviceBinaryFormat(const ArrayRef<const uint8_t> binary) {
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::OclElf>(binary)) {
|
||||
return true;
|
||||
}
|
||||
if (isDeviceBinaryFormat<DeviceBinaryFormat::Patchtokens>(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 &);
|
||||
|
||||
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 {
|
||||
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;
|
||||
}
|
||||
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 &);
|
||||
|
||||
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 {
|
||||
outErrReason = "Unknown format";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
343
core/device_binary_format/elf/elf.h
Normal file
343
core/device_binary_format/elf/elf.h
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// Abstract: Defines the types used for ELF headers/sections.
|
||||
#pragma once
|
||||
|
||||
#include "core/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
core/device_binary_format/elf/elf_decoder.cpp
Normal file
89
core/device_binary_format/elf/elf_decoder.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
|
||||
#include "core/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
core/device_binary_format/elf/elf_decoder.h
Normal file
67
core/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 "core/device_binary_format/elf/elf.h"
|
||||
#include "core/utilities/arrayref.h"
|
||||
#include "core/utilities/const_stringref.h"
|
||||
#include "core/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
core/device_binary_format/elf/elf_encoder.cpp
Normal file
178
core/device_binary_format/elf/elf_encoder.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
|
||||
#include "core/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
core/device_binary_format/elf/elf_encoder.h
Normal file
72
core/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 "core/device_binary_format/elf/elf.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/utilities/arrayref.h"
|
||||
#include "core/utilities/const_stringref.h"
|
||||
#include "core/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
core/device_binary_format/elf/ocl_elf.h
Normal file
59
core/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 "core/device_binary_format/elf/elf.h"
|
||||
#include "core/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
|
||||
@@ -63,7 +63,7 @@ inline KernelArgFromPatchtokens &getKernelArg(KernelFromPatchtokens &kernel, siz
|
||||
if (arg.objectType == ArgObjectType::None) {
|
||||
arg.objectType = type;
|
||||
} else if ((arg.objectType != type) && (type != ArgObjectType::None)) {
|
||||
kernel.decodeStatus = DecoderError::InvalidBinary;
|
||||
kernel.decodeStatus = DecodeError::InvalidBinary;
|
||||
DBG_LOG(LogPatchTokens, "\n Mismatched metadata for kernel arg :", argNum);
|
||||
DEBUG_BREAK_IF(true);
|
||||
}
|
||||
@@ -425,7 +425,7 @@ inline bool decodeToken(const SPatchItemHeader *token, KernelFromPatchtokens &ou
|
||||
} break;
|
||||
}
|
||||
|
||||
return out.decodeStatus != DecoderError::InvalidBinary;
|
||||
return out.decodeStatus != DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
inline bool decodeToken(const SPatchItemHeader *token, ProgramFromPatchtokens &out) {
|
||||
@@ -475,7 +475,7 @@ inline size_t getPatchTokenTotalSize<ProgramFromPatchtokens>(PatchTokensStreamRe
|
||||
? 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<SPatchAllocateConstantMemorySurfaceProgramBinaryInfo>(token)
|
||||
return stream.enoughDataLeft<SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo>(token)
|
||||
? tokSize + reinterpret_cast<const SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo *>(token)->InlineDataSize
|
||||
: std::numeric_limits<size_t>::max();
|
||||
}
|
||||
@@ -499,12 +499,12 @@ inline bool decodePatchList(PatchTokensStreamReader patchListStream, OutT &out)
|
||||
return decodeSuccess;
|
||||
}
|
||||
|
||||
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPatchtokens &out) {
|
||||
PatchTokensStreamReader stream{data};
|
||||
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> kernelBlob, KernelFromPatchtokens &out) {
|
||||
PatchTokensStreamReader stream{kernelBlob};
|
||||
auto decodePos = stream.data.begin();
|
||||
out.decodeStatus = DecoderError::Undefined;
|
||||
out.decodeStatus = DecodeError::Undefined;
|
||||
if (stream.notEnoughDataLeft<SKernelBinaryHeaderCommon>(decodePos)) {
|
||||
out.decodeStatus = DecoderError::InvalidBinary;
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -513,7 +513,7 @@ bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPat
|
||||
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 = DecoderError::InvalidBinary;
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -539,11 +539,11 @@ bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> data, KernelFromPat
|
||||
out.blobs.patchList = ArrayRef<const uint8_t>(decodePos, out.header->PatchListSize);
|
||||
|
||||
if (false == decodePatchList(out.blobs.patchList, out)) {
|
||||
out.decodeStatus = DecoderError::InvalidBinary;
|
||||
out.decodeStatus = DecodeError::InvalidBinary;
|
||||
return false;
|
||||
}
|
||||
|
||||
out.decodeStatus = DecoderError::Success;
|
||||
out.decodeStatus = DecodeError::Success;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -586,12 +586,12 @@ inline bool decodeKernels(ProgramFromPatchtokens &decodedProgram) {
|
||||
return decodeSuccess;
|
||||
}
|
||||
|
||||
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> blob, ProgramFromPatchtokens &out) {
|
||||
out.blobs.programInfo = blob;
|
||||
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 ? DecoderError::Success : DecoderError::InvalidBinary;
|
||||
out.decodeStatus = decodeSuccess ? DecodeError::Success : DecodeError::InvalidBinary;
|
||||
|
||||
return decodeSuccess;
|
||||
}
|
||||
@@ -631,6 +631,15 @@ const KernelArgAttributesFromPatchtokens getInlineData(const SPatchKernelArgumen
|
||||
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
|
||||
|
||||
@@ -7,10 +7,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/helpers/ptr_math.h"
|
||||
#include "core/utilities/arrayref.h"
|
||||
#include "core/utilities/stackvec.h"
|
||||
|
||||
#include "igfxfmid.h"
|
||||
#include "patch_g7.h"
|
||||
#include "patch_list.h"
|
||||
#include "patch_shared.h"
|
||||
@@ -19,6 +21,7 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
namespace NEO {
|
||||
|
||||
@@ -26,12 +29,6 @@ namespace PatchTokenBinary {
|
||||
|
||||
using namespace iOpenCL;
|
||||
|
||||
enum class DecoderError {
|
||||
Success = 0,
|
||||
Undefined = 1,
|
||||
InvalidBinary = 2,
|
||||
};
|
||||
|
||||
enum class ArgObjectType : uint32_t {
|
||||
None = 0,
|
||||
Buffer,
|
||||
@@ -100,7 +97,7 @@ struct KernelArgFromPatchtokens {
|
||||
using StackVecKernelArgs = StackVec<KernelArgFromPatchtokens, 12>;
|
||||
|
||||
struct KernelFromPatchtokens {
|
||||
DecoderError decodeStatus = DecoderError::Undefined;
|
||||
DecodeError decodeStatus = DecodeError::Undefined;
|
||||
|
||||
const SKernelBinaryHeaderCommon *header = nullptr;
|
||||
ArrayRef<const char> name;
|
||||
@@ -167,7 +164,7 @@ struct KernelFromPatchtokens {
|
||||
};
|
||||
|
||||
struct ProgramFromPatchtokens {
|
||||
DecoderError decodeStatus = DecoderError::Undefined;
|
||||
DecodeError decodeStatus = DecodeError::Undefined;
|
||||
|
||||
const SProgramBinaryHeader *header = nullptr;
|
||||
struct {
|
||||
@@ -195,8 +192,8 @@ struct KernelArgAttributesFromPatchtokens {
|
||||
ArrayRef<const char> typeQualifiers;
|
||||
};
|
||||
|
||||
bool decodeKernelFromPatchtokensBlob(ArrayRef<const uint8_t> blob, KernelFromPatchtokens &out);
|
||||
bool decodeProgramFromPatchtokensBlob(ArrayRef<const uint8_t> blob, ProgramFromPatchtokens &out);
|
||||
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);
|
||||
|
||||
@@ -214,6 +211,12 @@ inline const uint8_t *getInlineData(const SPatchString *ptr) {
|
||||
|
||||
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
|
||||
|
||||
@@ -710,21 +710,6 @@ void dumpVecIfNotEmpty(const T &vector, const std::string &vectorName, std::stri
|
||||
}
|
||||
}
|
||||
|
||||
const char *asString(DecoderError err) {
|
||||
switch (err) {
|
||||
default:
|
||||
DEBUG_BREAK_IF(err != DecoderError::InvalidBinary);
|
||||
return "with invalid binary";
|
||||
break;
|
||||
case DecoderError::Success:
|
||||
return "decoded successfully";
|
||||
break;
|
||||
case DecoderError::Undefined:
|
||||
return "in undefined status";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
std::string asString(const ProgramFromPatchtokens &prog) {
|
||||
std::stringstream stream;
|
||||
stream << "Program of size : " << prog.blobs.programInfo.size()
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/*
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "core/device_binary_format/patchtokens_validator.h"
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/helpers/hw_info.h"
|
||||
@@ -19,35 +19,23 @@ namespace NEO {
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
|
||||
enum class ValidatorError {
|
||||
Success = 0,
|
||||
Undefined = 1,
|
||||
InvalidBinary = 2,
|
||||
NotEnoughSlm = 3,
|
||||
};
|
||||
bool allowUnhandledTokens = true;
|
||||
|
||||
constexpr bool isDeviceSupported(GFXCORE_FAMILY device) {
|
||||
return (device < (sizeof(familyEnabled) / sizeof(familyEnabled[0]))) && familyEnabled[device];
|
||||
}
|
||||
|
||||
template <typename UknownTokenValidatorT>
|
||||
inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
size_t sharedLocalMemorySize,
|
||||
const UknownTokenValidatorT &tokenValidator,
|
||||
DecodeError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
std::string &outErrReason, std::string &outWarnings) {
|
||||
if (decodedProgram.decodeStatus != PatchTokenBinary::DecoderError::Success) {
|
||||
if (decodedProgram.decodeStatus != DecodeError::Success) {
|
||||
outErrReason = "ProgramFromPatchtokens wasn't successfully decoded";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::InvalidBinary;
|
||||
}
|
||||
|
||||
if (decodedProgram.programScopeTokens.allocateConstantMemorySurface.size() > 1) {
|
||||
outErrReason = "Unhandled number of global constants surfaces > 1";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if (decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size() > 1) {
|
||||
outErrReason = "Unhandled number of global variables surfaces > 1";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
for (const auto &globalConstantPointerToken : decodedProgram.programScopeTokens.constantPointer) {
|
||||
@@ -59,7 +47,7 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
|
||||
if (isUnhandled) {
|
||||
outErrReason = "Unhandled SPatchConstantPointerProgramBinaryInfo";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,50 +60,45 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
|
||||
if (isUnhandled) {
|
||||
outErrReason = "Unhandled SPatchGlobalPointerProgramBinaryInfo";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &unhandledToken : decodedProgram.unhandledTokens) {
|
||||
if (false == tokenValidator.isSafeToSkipUnhandledToken(unhandledToken->Token)) {
|
||||
outErrReason = "Unhandled required program-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
return ValidatorError::InvalidBinary;
|
||||
} else {
|
||||
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 ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if ((decodedProgram.header->GPUPointerSizeInBytes != 4U) && (decodedProgram.header->GPUPointerSizeInBytes != 8U)) {
|
||||
outErrReason = "Invalid pointer size";
|
||||
return ValidatorError::InvalidBinary;
|
||||
}
|
||||
|
||||
if (false == isDeviceSupported(static_cast<GFXCORE_FAMILY>(decodedProgram.header->Device))) {
|
||||
outErrReason = "Unsupported device binary, device GFXCORE_FAMILY : " + std::to_string(decodedProgram.header->Device);
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
for (const auto &decodedKernel : decodedProgram.kernels) {
|
||||
if (decodedKernel.decodeStatus != PatchTokenBinary::DecoderError::Success) {
|
||||
if (decodedKernel.decodeStatus != DecodeError::Success) {
|
||||
outErrReason = "KernelFromPatchtokens wasn't successfully decoded";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
UNRECOVERABLE_IF(nullptr == decodedKernel.header);
|
||||
if (hasInvalidChecksum(decodedKernel)) {
|
||||
outErrReason = "KernelFromPatchtokens has invalid checksum";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
|
||||
if (nullptr == decodedKernel.tokens.executionEnvironment) {
|
||||
outErrReason = "Missing execution environment";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
} else {
|
||||
switch (decodedKernel.tokens.executionEnvironment->LargestCompiledSIMDSize) {
|
||||
case 1:
|
||||
@@ -128,14 +111,7 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
break;
|
||||
default:
|
||||
outErrReason = "Invalid LargestCompiledSIMDSize";
|
||||
return ValidatorError::InvalidBinary;
|
||||
}
|
||||
}
|
||||
|
||||
if (decodedKernel.tokens.allocateLocalSurface) {
|
||||
if (sharedLocalMemorySize < decodedKernel.tokens.allocateLocalSurface->TotalInlineLocalMemorySize) {
|
||||
outErrReason = "KernelFromPatchtokens requires too much SLM";
|
||||
return ValidatorError::NotEnoughSlm;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,26 +123,26 @@ inline ValidatorError validate(const ProgramFromPatchtokens &decodedProgram,
|
||||
auto accessQualifier = KernelArgMetadata::parseAccessQualifier(parseLimitedString(argInfoInlineData.accessQualifier.begin(), argInfoInlineData.accessQualifier.size()));
|
||||
if (KernelArgMetadata::AccessQualifier::Unknown == accessQualifier) {
|
||||
outErrReason = "Unhandled access qualifier";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
auto addressQualifier = KernelArgMetadata::parseAddressSpace(parseLimitedString(argInfoInlineData.addressQualifier.begin(), argInfoInlineData.addressQualifier.size()));
|
||||
if (KernelArgMetadata::AddressSpaceQualifier::Unknown == addressQualifier) {
|
||||
outErrReason = "Unhandled address qualifier";
|
||||
return ValidatorError::InvalidBinary;
|
||||
return DecodeError::UnhandledBinary;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto &unhandledToken : decodedKernel.unhandledTokens) {
|
||||
if (false == tokenValidator.isSafeToSkipUnhandledToken(unhandledToken->Token)) {
|
||||
outErrReason = "Unhandled required kernel-scope Patch Token : " + std::to_string(unhandledToken->Token);
|
||||
return ValidatorError::InvalidBinary;
|
||||
} else {
|
||||
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 ValidatorError::Success;
|
||||
return DecodeError::Success;
|
||||
}
|
||||
|
||||
} // namespace PatchTokenBinary
|
||||
26
core/device_binary_format/patchtokens_validator.h
Normal file
26
core/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 "core/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
|
||||
@@ -1,23 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2017-2019 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
add_library(elflib STATIC EXCLUDE_FROM_ALL
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/reader.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/reader.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/types.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/writer.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/writer.h
|
||||
)
|
||||
|
||||
create_project_source_tree(elflib)
|
||||
|
||||
target_include_directories(elflib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_include_directories(elflib PRIVATE ${NEO_SOURCE_DIR})
|
||||
|
||||
set_target_properties(elflib PROPERTIES FOLDER "elflib")
|
||||
|
||||
set_target_properties(elflib PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
@@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "reader.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace CLElfLib {
|
||||
CElfReader::CElfReader(ElfBinaryStorage &elfBinary) {
|
||||
validateElfBinary(elfBinary);
|
||||
}
|
||||
|
||||
void CElfReader::validateElfBinary(ElfBinaryStorage &elfBinary) {
|
||||
const char *nameTable = nullptr;
|
||||
const char *end = nullptr;
|
||||
size_t ourSize = 0u;
|
||||
size_t entrySize = 0u;
|
||||
size_t indexedSectionHeaderOffset = 0u;
|
||||
beginBinary = elfBinary.data();
|
||||
|
||||
if (elfBinary.size() >= sizeof(SElf64Header)) {
|
||||
// calculate a pointer to the end
|
||||
end = beginBinary + elfBinary.size();
|
||||
elf64Header = reinterpret_cast<const SElf64Header *>(elfBinary.data());
|
||||
|
||||
if (!((elf64Header->Identity[ELFConstants::idIdxMagic0] == ELFConstants::elfMag0) &&
|
||||
(elf64Header->Identity[ELFConstants::idIdxMagic1] == ELFConstants::elfMag1) &&
|
||||
(elf64Header->Identity[ELFConstants::idIdxMagic2] == ELFConstants::elfMag2) &&
|
||||
(elf64Header->Identity[ELFConstants::idIdxMagic3] == ELFConstants::elfMag3) &&
|
||||
(elf64Header->Identity[ELFConstants::idIdxClass] == static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64)))) {
|
||||
throw ElfException();
|
||||
}
|
||||
ourSize += elf64Header->ElfHeaderSize;
|
||||
} else {
|
||||
throw ElfException();
|
||||
}
|
||||
|
||||
entrySize = elf64Header->SectionHeaderEntrySize;
|
||||
|
||||
if (elf64Header->SectionNameTableIndex < elf64Header->NumSectionHeaderEntries) {
|
||||
indexedSectionHeaderOffset = static_cast<size_t>(elf64Header->SectionHeadersOffset) + (elf64Header->SectionNameTableIndex * entrySize);
|
||||
|
||||
if ((beginBinary + indexedSectionHeaderOffset) <= end) {
|
||||
nameTable = beginBinary + indexedSectionHeaderOffset;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint16_t i = 0u; i < elf64Header->NumSectionHeaderEntries; ++i) {
|
||||
indexedSectionHeaderOffset = static_cast<size_t>(elf64Header->SectionHeadersOffset) + (i * entrySize);
|
||||
|
||||
// check section header offset
|
||||
if ((beginBinary + indexedSectionHeaderOffset) > end) {
|
||||
throw ElfException();
|
||||
}
|
||||
|
||||
const SElf64SectionHeader *sectionHeader = nullptr;
|
||||
|
||||
sectionHeader = reinterpret_cast<const SElf64SectionHeader *>(beginBinary + indexedSectionHeaderOffset);
|
||||
|
||||
// check section data
|
||||
if ((beginBinary + sectionHeader->DataOffset + sectionHeader->DataSize) > end) {
|
||||
throw ElfException();
|
||||
}
|
||||
|
||||
// check section name index
|
||||
if ((nameTable + sectionHeader->Name) > end) {
|
||||
throw ElfException();
|
||||
}
|
||||
|
||||
SElf64SectionHeader stringSectionHeader = {0};
|
||||
stringSectionHeader.Type = sectionHeader->Type;
|
||||
stringSectionHeader.Flags = sectionHeader->Flags;
|
||||
stringSectionHeader.DataOffset = sectionHeader->DataOffset;
|
||||
stringSectionHeader.DataSize = sectionHeader->DataSize;
|
||||
stringSectionHeader.Name = sectionHeader->Name;
|
||||
sectionHeaders.push_back(std::move(stringSectionHeader));
|
||||
|
||||
// tally up the sizes
|
||||
ourSize += static_cast<size_t>(sectionHeader->DataSize);
|
||||
ourSize += static_cast<size_t>(entrySize);
|
||||
}
|
||||
|
||||
if (ourSize != elfBinary.size()) {
|
||||
throw ElfException();
|
||||
}
|
||||
}
|
||||
|
||||
char *CElfReader::getSectionData(Elf64_Off dataOffset) {
|
||||
return beginBinary + dataOffset;
|
||||
}
|
||||
|
||||
const SElf64Header *CElfReader::getElfHeader() {
|
||||
return elf64Header;
|
||||
}
|
||||
|
||||
} // namespace CLElfLib
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
namespace CLElfLib {
|
||||
using ElfSectionHeaderStorage = std::vector<SElf64SectionHeader>;
|
||||
/******************************************************************************\
|
||||
|
||||
Class: CElfReader
|
||||
|
||||
Description: Class to provide simpler interaction with the ELF standard
|
||||
binary object. SElf64Header defines the ELF header type and
|
||||
SElf64SectionHeader defines the section header type.
|
||||
|
||||
\******************************************************************************/
|
||||
class CElfReader {
|
||||
public:
|
||||
CElfReader(ElfBinaryStorage &elfBinary);
|
||||
ElfSectionHeaderStorage &getSectionHeaders() {
|
||||
return sectionHeaders;
|
||||
}
|
||||
|
||||
const SElf64Header *getElfHeader();
|
||||
char *getSectionData(Elf64_Off dataOffset);
|
||||
|
||||
protected:
|
||||
void validateElfBinary(ElfBinaryStorage &elfBinary);
|
||||
|
||||
ElfSectionHeaderStorage sectionHeaders;
|
||||
char *beginBinary;
|
||||
const SElf64Header *elf64Header;
|
||||
};
|
||||
} // namespace CLElfLib
|
||||
196
core/elf/types.h
196
core/elf/types.h
@@ -1,196 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
// Abstract: Defines the types used for ELF headers/sections.
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
#include <vector>
|
||||
|
||||
namespace CLElfLib {
|
||||
struct ElfException : std::exception {
|
||||
};
|
||||
|
||||
using ElfBinaryStorage = std::vector<char>;
|
||||
/******************************************************************************\
|
||||
ELF Enumerates
|
||||
\******************************************************************************/
|
||||
|
||||
// E_ID_IDX - Defines a file as being ELF
|
||||
enum class E_ID_IDX : uint32_t {
|
||||
ID_IDX_MAGIC0 = 0,
|
||||
ID_IDX_MAGIC1 = 1,
|
||||
ID_IDX_MAGIC2 = 2,
|
||||
ID_IDX_MAGIC3 = 3,
|
||||
ID_IDX_CLASS = 4,
|
||||
ID_IDX_VERSION = 5,
|
||||
ID_IDX_OSABI = 6,
|
||||
ID_IDX_ABI_VERSION = 7,
|
||||
ID_IDX_PADDING = 8,
|
||||
ID_IDX_NUM_BYTES = 16,
|
||||
};
|
||||
|
||||
// E_EHT_CLASS - Describes what data types the ELF structures will use.
|
||||
enum class E_EH_CLASS : uint32_t {
|
||||
EH_CLASS_NONE = 0,
|
||||
EH_CLASS_32 = 1, // Use Elf32 data types
|
||||
EH_CLASS_64 = 2, // Use Elf64 data types
|
||||
};
|
||||
|
||||
// E_EHT_TYPE - List of pre-defined types header types.
|
||||
// OS-specific codes start at 0xfe00 and run to 0xfeff.
|
||||
// Processor-specific codes start at 0xff00 and end at 0xffff.
|
||||
enum class E_EH_TYPE : uint16_t {
|
||||
EH_TYPE_NONE = 0,
|
||||
EH_TYPE_RELOCATABLE = 1,
|
||||
EH_TYPE_EXECUTABLE = 2,
|
||||
EH_TYPE_DYNAMIC = 3,
|
||||
EH_TYPE_CORE = 4,
|
||||
EH_TYPE_OPENCL_SOURCE = 0xff01, // format used to pass CL text sections to FE
|
||||
EH_TYPE_OPENCL_OBJECTS = 0xff02, // format used to pass LLVM objects / store LLVM binary output
|
||||
EH_TYPE_OPENCL_LIBRARY = 0xff03, // format used to store LLVM archive output
|
||||
EH_TYPE_OPENCL_EXECUTABLE = 0xff04, // format used to store executable output
|
||||
EH_TYPE_OPENCL_DEBUG = 0xff05, // format used to store debug output
|
||||
};
|
||||
|
||||
// E_EH_MACHINE - List of pre-defined machine types.
|
||||
// For OpenCL, currently, we do not need this information, so this is not
|
||||
// fully defined.
|
||||
enum class E_EH_MACHINE : uint16_t {
|
||||
EH_MACHINE_NONE = 0,
|
||||
//EHT_MACHINE_LO_RSVD = 1, // Beginning of range of reserved types.
|
||||
//EHT_MACHINE_HI_RSVD = 200, // End of range of reserved types.
|
||||
};
|
||||
|
||||
// E_EHT_VERSION - ELF header version options.
|
||||
enum class E_EHT_VERSION : uint32_t {
|
||||
EH_VERSION_INVALID = 0,
|
||||
EH_VERSION_CURRENT = 1,
|
||||
};
|
||||
|
||||
// E_SH_TYPE - List of pre-defined section header types.
|
||||
// Processor-specific codes start at 0xff00 and end at 0xffff.
|
||||
enum class E_SH_TYPE : uint32_t {
|
||||
SH_TYPE_NULL = 0,
|
||||
SH_TYPE_PROG_BITS = 1,
|
||||
SH_TYPE_SYM_TBL = 2,
|
||||
SH_TYPE_STR_TBL = 3,
|
||||
SH_TYPE_RELO_ADDS = 4,
|
||||
SH_TYPE_HASH = 5,
|
||||
SH_TYPE_DYN = 6,
|
||||
SH_TYPE_NOTE = 7,
|
||||
SH_TYPE_NOBITS = 8,
|
||||
SH_TYPE_RELO_NO_ADDS = 9,
|
||||
SH_TYPE_SHLIB = 10,
|
||||
SH_TYPE_DYN_SYM_TBL = 11,
|
||||
SH_TYPE_INIT = 14,
|
||||
SH_TYPE_FINI = 15,
|
||||
SH_TYPE_PRE_INIT = 16,
|
||||
SH_TYPE_GROUP = 17,
|
||||
SH_TYPE_SYMTBL_SHNDX = 18,
|
||||
SH_TYPE_OPENCL_SOURCE = 0xff000000, // CL source to link into LLVM binary
|
||||
SH_TYPE_OPENCL_HEADER = 0xff000001, // CL header to link into LLVM binary
|
||||
SH_TYPE_OPENCL_LLVM_TEXT = 0xff000002, // LLVM text
|
||||
SH_TYPE_OPENCL_LLVM_BINARY = 0xff000003, // LLVM byte code
|
||||
SH_TYPE_OPENCL_LLVM_ARCHIVE = 0xff000004, // LLVM archives(s)
|
||||
SH_TYPE_OPENCL_DEV_BINARY = 0xff000005, // Device binary (coherent by default)
|
||||
SH_TYPE_OPENCL_OPTIONS = 0xff000006, // CL Options
|
||||
SH_TYPE_OPENCL_PCH = 0xff000007, // PCH (pre-compiled headers)
|
||||
SH_TYPE_OPENCL_DEV_DEBUG = 0xff000008, // Device debug
|
||||
SH_TYPE_SPIRV = 0xff000009, // SPIRV
|
||||
SH_TYPE_NON_COHERENT_DEV_BINARY = 0xff00000a, // Non-coherent Device binary
|
||||
};
|
||||
|
||||
// E_SH_FLAG - List of section header flags.
|
||||
enum class E_SH_FLAG : uint64_t {
|
||||
SH_FLAG_NONE = 0x0,
|
||||
SH_FLAG_WRITE = 0x1,
|
||||
SH_FLAG_ALLOC = 0x2,
|
||||
SH_FLAG_EXEC_INSTR = 0x4,
|
||||
SH_FLAG_MERGE = 0x8,
|
||||
SH_FLAG_STRINGS = 0x10,
|
||||
SH_FLAG_INFO_LINK = 0x20,
|
||||
SH_FLAG_LINK_ORDER = 0x40,
|
||||
SH_FLAG_OS_NONCONFORM = 0x100,
|
||||
SH_FLAG_GROUP = 0x200,
|
||||
SH_FLAG_TLS = 0x400,
|
||||
SH_FLAG_MASK_OS = 0x0ff00000,
|
||||
SH_FLAG_MASK_PROC = 0xf0000000,
|
||||
};
|
||||
|
||||
/******************************************************************************\
|
||||
ELF-64 Data Types
|
||||
\******************************************************************************/
|
||||
#if !defined(_UAPI_LINUX_ELF_H)
|
||||
typedef uint64_t Elf64_Addr;
|
||||
typedef uint64_t Elf64_Off;
|
||||
typedef uint32_t Elf64_Word;
|
||||
typedef int32_t Elf64_Sword;
|
||||
typedef uint64_t Elf64_Xword;
|
||||
typedef uint16_t Elf64_Short; // Renaming Elf64_Half to Elf64_Short to avoid a conflict with Android
|
||||
#endif
|
||||
|
||||
/******************************************************************************\
|
||||
ELF Constants
|
||||
\******************************************************************************/
|
||||
namespace ELFConstants {
|
||||
static const unsigned char elfMag0 = 0x7f; // ELFHeader.Identity[ELF_ID_MAGIC0]
|
||||
static const unsigned char elfMag1 = 'E'; // ELFHeader.Identity[ELF_ID_MAGIC1]
|
||||
static const unsigned char elfMag2 = 'L'; // ELFHeader.Identity[ELF_ID_MAGIC2]
|
||||
static const unsigned char elfMag3 = 'F'; // ELFHeader.Identity[ELF_ID_MAGIC3]
|
||||
static const unsigned int elfAlignBytes = 16; // Alignment set to 16-bytes
|
||||
|
||||
static const uint32_t idIdxMagic0 = 0;
|
||||
static const uint32_t idIdxMagic1 = 1;
|
||||
static const uint32_t idIdxMagic2 = 2;
|
||||
static const uint32_t idIdxMagic3 = 3;
|
||||
static const uint32_t idIdxClass = 4;
|
||||
static const uint32_t idIdxVersion = 5;
|
||||
static const uint32_t idIdxOsabi = 6;
|
||||
static const uint32_t idIdxAbiVersion = 7;
|
||||
static const uint32_t idIdxPadding = 8;
|
||||
static const uint32_t idIdxNumBytes = 16;
|
||||
} // namespace ELFConstants
|
||||
|
||||
/******************************************************************************\
|
||||
ELF-64 Header
|
||||
\******************************************************************************/
|
||||
struct SElf64Header {
|
||||
unsigned char Identity[ELFConstants::idIdxNumBytes];
|
||||
E_EH_TYPE Type;
|
||||
E_EH_MACHINE Machine;
|
||||
Elf64_Word Version;
|
||||
Elf64_Addr EntryAddress;
|
||||
Elf64_Off ProgramHeadersOffset;
|
||||
Elf64_Off SectionHeadersOffset;
|
||||
Elf64_Word Flags;
|
||||
Elf64_Short ElfHeaderSize;
|
||||
Elf64_Short ProgramHeaderEntrySize;
|
||||
Elf64_Short NumProgramHeaderEntries;
|
||||
Elf64_Short SectionHeaderEntrySize;
|
||||
Elf64_Short NumSectionHeaderEntries;
|
||||
Elf64_Short SectionNameTableIndex;
|
||||
};
|
||||
|
||||
/******************************************************************************\
|
||||
ELF-64 Section Header
|
||||
\******************************************************************************/
|
||||
struct SElf64SectionHeader {
|
||||
Elf64_Word Name;
|
||||
E_SH_TYPE Type;
|
||||
E_SH_FLAG Flags;
|
||||
Elf64_Addr Address;
|
||||
Elf64_Off DataOffset;
|
||||
Elf64_Xword DataSize;
|
||||
Elf64_Word Link;
|
||||
Elf64_Word Info;
|
||||
Elf64_Xword Alignment;
|
||||
Elf64_Xword EntrySize;
|
||||
};
|
||||
|
||||
} // namespace CLElfLib
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "writer.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
// Need for linux compatibility with memcpy_s
|
||||
#include "core/helpers/string.h"
|
||||
|
||||
namespace CLElfLib {
|
||||
void CElfWriter::resolveBinary(ElfBinaryStorage &binary) {
|
||||
SElf64SectionHeader *curSectionHeader = nullptr;
|
||||
char *data = nullptr;
|
||||
char *stringTable = nullptr;
|
||||
char *curString = nullptr;
|
||||
|
||||
if (binary.size() < getTotalBinarySize()) {
|
||||
binary.resize(getTotalBinarySize());
|
||||
}
|
||||
|
||||
// get a pointer to the first section header
|
||||
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(binary.data() + sizeof(SElf64Header));
|
||||
|
||||
// get a pointer to the data
|
||||
data = binary.data() +
|
||||
sizeof(SElf64Header) +
|
||||
((numSections + 1) * sizeof(SElf64SectionHeader)); // +1 to account for string table entry
|
||||
|
||||
// get a pointer to the string table
|
||||
stringTable = binary.data() + sizeof(SElf64Header) +
|
||||
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
|
||||
dataSize;
|
||||
|
||||
curString = stringTable;
|
||||
|
||||
// Walk through the section nodes
|
||||
while (nodeQueue.empty() == false) {
|
||||
// Copy data into the section header
|
||||
const auto &queueFront = nodeQueue.front();
|
||||
|
||||
curSectionHeader->Type = queueFront.type;
|
||||
curSectionHeader->Flags = queueFront.flag;
|
||||
curSectionHeader->DataSize = queueFront.dataSize;
|
||||
curSectionHeader->DataOffset = data - binary.data();
|
||||
curSectionHeader->Name = static_cast<Elf64_Word>(curString - stringTable);
|
||||
curSectionHeader = reinterpret_cast<SElf64SectionHeader *>(reinterpret_cast<unsigned char *>(curSectionHeader) + sizeof(SElf64SectionHeader));
|
||||
|
||||
// copy the data, move the data pointer
|
||||
memcpy_s(data, queueFront.dataSize, queueFront.data.c_str(), queueFront.dataSize);
|
||||
data += queueFront.dataSize;
|
||||
|
||||
// copy the name into the string table, move the string pointer
|
||||
if (queueFront.name.size() > 0) {
|
||||
memcpy_s(curString, queueFront.name.size(), queueFront.name.c_str(), queueFront.name.size());
|
||||
curString += queueFront.name.size();
|
||||
}
|
||||
*(curString++) = '\0'; // NOLINT
|
||||
|
||||
nodeQueue.pop();
|
||||
}
|
||||
|
||||
// add the string table section header
|
||||
SElf64SectionHeader stringSectionHeader = {0};
|
||||
stringSectionHeader.Type = E_SH_TYPE::SH_TYPE_STR_TBL;
|
||||
stringSectionHeader.Flags = E_SH_FLAG::SH_FLAG_NONE;
|
||||
stringSectionHeader.DataOffset = stringTable - &binary[0];
|
||||
stringSectionHeader.DataSize = stringTableSize;
|
||||
stringSectionHeader.Name = 0;
|
||||
|
||||
// Copy into the last section header
|
||||
memcpy_s(curSectionHeader, sizeof(SElf64SectionHeader),
|
||||
&stringSectionHeader, sizeof(SElf64SectionHeader));
|
||||
|
||||
// Add to our section number
|
||||
numSections++;
|
||||
|
||||
// patch up the ELF header
|
||||
patchElfHeader(*reinterpret_cast<SElf64Header *>(binary.data()));
|
||||
}
|
||||
|
||||
void CElfWriter::patchElfHeader(SElf64Header &binary) {
|
||||
// Setup the identity
|
||||
binary.Identity[ELFConstants::idIdxMagic0] = ELFConstants::elfMag0;
|
||||
binary.Identity[ELFConstants::idIdxMagic1] = ELFConstants::elfMag1;
|
||||
binary.Identity[ELFConstants::idIdxMagic2] = ELFConstants::elfMag2;
|
||||
binary.Identity[ELFConstants::idIdxMagic3] = ELFConstants::elfMag3;
|
||||
binary.Identity[ELFConstants::idIdxClass] = static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64);
|
||||
binary.Identity[ELFConstants::idIdxVersion] = static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT);
|
||||
|
||||
// Add other non-zero info
|
||||
binary.Type = type;
|
||||
binary.Machine = machine;
|
||||
binary.Flags = static_cast<uint32_t>(flag);
|
||||
binary.ElfHeaderSize = static_cast<uint32_t>(sizeof(SElf64Header));
|
||||
binary.SectionHeaderEntrySize = static_cast<uint32_t>(sizeof(SElf64SectionHeader));
|
||||
binary.NumSectionHeaderEntries = numSections;
|
||||
binary.SectionHeadersOffset = static_cast<uint32_t>(sizeof(SElf64Header));
|
||||
binary.SectionNameTableIndex = numSections - 1; // last index
|
||||
}
|
||||
} // namespace CLElfLib
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "types.h"
|
||||
|
||||
#include <queue>
|
||||
#include <string>
|
||||
|
||||
namespace CLElfLib {
|
||||
struct SSectionNode {
|
||||
E_SH_TYPE type = E_SH_TYPE::SH_TYPE_NULL;
|
||||
E_SH_FLAG flag = E_SH_FLAG::SH_FLAG_NONE;
|
||||
std::string name;
|
||||
std::string data;
|
||||
uint32_t dataSize = 0u;
|
||||
|
||||
SSectionNode() = default;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
SSectionNode(E_SH_TYPE type, E_SH_FLAG flag, T1 &&name, T2 &&data, uint32_t dataSize)
|
||||
: type(type), flag(flag), name(std::forward<T1>(name)), data(std::forward<T2>(data)), dataSize(dataSize) {}
|
||||
|
||||
~SSectionNode() = default;
|
||||
};
|
||||
|
||||
/******************************************************************************\
|
||||
|
||||
Class: CElfWriter
|
||||
|
||||
Description: Class to provide simpler interaction with the ELF standard
|
||||
binary object. SElf64Header defines the ELF header type and
|
||||
SElf64SectionHeader defines the section header type.
|
||||
|
||||
\******************************************************************************/
|
||||
class CElfWriter {
|
||||
public:
|
||||
CElfWriter(
|
||||
E_EH_TYPE type,
|
||||
E_EH_MACHINE machine,
|
||||
Elf64_Xword flag) : type(type), machine(machine), flag(flag) {
|
||||
addSection(SSectionNode());
|
||||
}
|
||||
|
||||
~CElfWriter() {}
|
||||
|
||||
template <typename T>
|
||||
void addSection(T &§ionNode) {
|
||||
size_t nameSize = 0;
|
||||
uint32_t dataSize = 0;
|
||||
|
||||
nameSize = sectionNode.name.size() + 1u;
|
||||
dataSize = sectionNode.dataSize;
|
||||
|
||||
// push the node onto the queue
|
||||
nodeQueue.push(std::forward<T>(sectionNode));
|
||||
|
||||
// increment the sizes for each section
|
||||
this->dataSize += dataSize;
|
||||
stringTableSize += nameSize;
|
||||
numSections++;
|
||||
}
|
||||
|
||||
void resolveBinary(ElfBinaryStorage &binary);
|
||||
|
||||
size_t getTotalBinarySize() {
|
||||
return sizeof(SElf64Header) +
|
||||
((numSections + 1) * sizeof(SElf64SectionHeader)) + // +1 to account for string table entry
|
||||
dataSize + stringTableSize;
|
||||
}
|
||||
|
||||
protected:
|
||||
E_EH_TYPE type = E_EH_TYPE::EH_TYPE_NONE;
|
||||
E_EH_MACHINE machine = E_EH_MACHINE::EH_MACHINE_NONE;
|
||||
Elf64_Xword flag = 0U;
|
||||
|
||||
std::queue<SSectionNode> nodeQueue;
|
||||
|
||||
uint32_t dataSize = 0U;
|
||||
uint32_t numSections = 0U;
|
||||
size_t stringTableSize = 0U;
|
||||
|
||||
void patchElfHeader(SElf64Header &pBinary);
|
||||
};
|
||||
} // namespace CLElfLib
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -94,13 +94,13 @@ inline int memmove_s(void *dst, size_t numberOfElements, const void *src, size_t
|
||||
|
||||
#endif
|
||||
|
||||
template <typename T = char[]>
|
||||
inline std::unique_ptr<T> makeCopy(const void *src, size_t size) {
|
||||
template <typename T = char>
|
||||
inline std::unique_ptr<T[]> makeCopy(const void *src, size_t size) {
|
||||
if (size == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
using ElT = typename std::remove_all_extents<T>::type;
|
||||
std::unique_ptr<T> copiedData(reinterpret_cast<ElT *>(new char[size]));
|
||||
std::unique_ptr<T[]> copiedData(new ElT[size]);
|
||||
memcpy_s(copiedData.get(), size, src, size);
|
||||
return copiedData;
|
||||
}
|
||||
|
||||
@@ -18,4 +18,24 @@ ProgramInfo::~ProgramInfo() {
|
||||
kernelInfos.clear();
|
||||
}
|
||||
|
||||
size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo) {
|
||||
uint32_t ret = 0U;
|
||||
for (const auto &kernelInfo : programInfo.kernelInfos) {
|
||||
if (nullptr == kernelInfo->patchInfo.localsurface) {
|
||||
continue;
|
||||
}
|
||||
ret = std::max(ret, kernelInfo->patchInfo.localsurface->TotalInlineLocalMemorySize);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo) {
|
||||
for (const auto &kernelInfo : programInfo.kernelInfos) {
|
||||
if (WorkloadInfo::undefinedOffset != kernelInfo->workloadInfo.localMemoryStatelessWindowStartAddressOffset) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -8,8 +8,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "core/compiler_interface/linker.h"
|
||||
#include "core/utilities/stackvec.h"
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
@@ -42,4 +42,7 @@ struct ProgramInfo {
|
||||
std::vector<KernelInfo *> kernelInfos;
|
||||
};
|
||||
|
||||
size_t getMaxInlineSlmNeeded(const ProgramInfo &programInfo);
|
||||
bool requiresLocalMemoryWindowVA(const ProgramInfo &programInfo);
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -25,11 +25,11 @@ bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens
|
||||
return false;
|
||||
}
|
||||
|
||||
void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, const DeviceInfoKernelPayloadConstants &constants, uint32_t kernelNum) {
|
||||
void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram, uint32_t kernelNum) {
|
||||
auto kernelInfo = std::make_unique<KernelInfo>();
|
||||
const PatchTokenBinary::KernelFromPatchtokens &decodedKernel = decodedProgram.kernels[kernelNum];
|
||||
|
||||
NEO::populateKernelInfo(*kernelInfo, decodedKernel, decodedProgram.header->GPUPointerSizeInBytes, constants);
|
||||
NEO::populateKernelInfo(*kernelInfo, decodedKernel, decodedProgram.header->GPUPointerSizeInBytes);
|
||||
|
||||
if (decodedKernel.tokens.programSymbolTable) {
|
||||
dst.prepareLinkerInputStorage();
|
||||
@@ -44,9 +44,9 @@ void populateSingleKernelInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramF
|
||||
dst.kernelInfos.push_back(kernelInfo.release());
|
||||
}
|
||||
|
||||
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants) {
|
||||
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src) {
|
||||
for (uint32_t i = 0; i < src.kernels.size(); ++i) {
|
||||
populateSingleKernelInfo(dst, src, constants, i);
|
||||
populateSingleKernelInfo(dst, src, i);
|
||||
}
|
||||
|
||||
if (src.programScopeTokens.allocateConstantMemorySurface.empty() == false) {
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
namespace NEO {
|
||||
|
||||
struct ProgramInfo;
|
||||
struct DeviceInfoKernelPayloadConstants;
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
struct ProgramFromPatchtokens;
|
||||
@@ -25,6 +24,6 @@ inline uint64_t readMisalignedUint64(const uint64_t *address) {
|
||||
|
||||
bool requiresLocalMemoryWindowVA(const PatchTokenBinary::ProgramFromPatchtokens &src);
|
||||
|
||||
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src, const DeviceInfoKernelPayloadConstants &constants);
|
||||
void populateProgramInfo(ProgramInfo &dst, const PatchTokenBinary::ProgramFromPatchtokens &src);
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2019 Intel Corporation
|
||||
# Copyright (C) 2019-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
@@ -9,6 +9,7 @@ set(NEO_CORE_COMPILER_INTERFACE_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_cache_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_options_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/intermediate_representations_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker_mock.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/linker_tests.cpp
|
||||
)
|
||||
|
||||
@@ -133,6 +133,15 @@ TEST(CompilerInterface, WhenInitializeIsCalledThenFailIfOneOfRequiredCompilersIs
|
||||
EXPECT_FALSE(initSuccess);
|
||||
}
|
||||
|
||||
TEST(CompilerInterfaceCreateInstance, WhenInitializeFailedThenReturnNull) {
|
||||
struct FailInitializeCompilerInterface : CompilerInterface {
|
||||
bool initialize(std::unique_ptr<CompilerCache> cache, bool requireFcl) override {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
EXPECT_EQ(nullptr, CompilerInterface::createInstance<FailInitializeCompilerInterface>(std::make_unique<CompilerCache>(CompilerCacheConfig{}), false));
|
||||
}
|
||||
|
||||
TEST_F(CompilerInterfaceTest, WhenCompilingToIsaThenSuccessIsReturned) {
|
||||
TranslationOutput translationOutput;
|
||||
auto err = pCompilerInterface->build(*pDevice, inputArgs, translationOutput);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(HasSameMagic, WhenMagicIsMatchedThenReturnTrue) {
|
||||
EXPECT_TRUE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcdefg").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenBinaryIsNullptrThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", {}));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenBinaryIsShorterThanExpectedMagicThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("ab").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(HasSameMagic, WhenMagicIsNotMatchedThenReturnFalse) {
|
||||
EXPECT_FALSE(NEO::hasSameMagic("abcd", ArrayRef<const char>("abcefg").toArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
static constexpr uint8_t llvmBinary[] = "BC\xc0\xde ";
|
||||
|
||||
TEST(IsLlvmBitcode, WhenLlvmMagicWasFoundThenBinaryIsValidLLvm) {
|
||||
EXPECT_TRUE(NEO::isLlvmBitcode(llvmBinary));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>(llvmBinary, 2)));
|
||||
}
|
||||
|
||||
TEST(IsLlvmBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
const uint8_t notLlvmBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(notLlvmBinary));
|
||||
}
|
||||
|
||||
static constexpr uint32_t spirv[16] = {0x03022307};
|
||||
static constexpr uint32_t spirvInvEndianes[16] = {0x07230203};
|
||||
|
||||
TEST(IsSpirVBitcode, WhenSpirvMagicWasFoundThenBinaryIsValidSpirv) {
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirv), sizeof(spirv))));
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), sizeof(spirvInvEndianes))));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryIsNullptrThenBinaryIsNotValidSpirv) {
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidSpirv) {
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), 2)));
|
||||
}
|
||||
|
||||
TEST(IsSpirVBitcode, WhenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidSpirv) {
|
||||
const uint8_t notSpirvBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(notSpirvBinary));
|
||||
}
|
||||
@@ -6,6 +6,11 @@
|
||||
|
||||
set(NEO_DEVICE_BINARY_FORMAT_TESTS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elf/elf_encoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_ocl_elf_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_format_patchtokens_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/device_binary_formats_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_decoder_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_dumper_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patchtokens_tests.h
|
||||
|
||||
@@ -0,0 +1,397 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <tuple>
|
||||
|
||||
TEST(IsDeviceBinaryFormatOclElf, GivenElfThenReturnsTrueIfProperElfFileTypeDetected) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_DEBUG;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_SOURCE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_NONE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_EXEC;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode()));
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_32> elfEnc32;
|
||||
elfEnc32.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(elfEnc32.encode()));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, WhenFailedToDecodeElfThenUnpackingFails) {
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>({}, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Invalid or missing ELF header", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenNotOclElfThenUnpackingFails) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Not OCL ELF file type", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfThenSetsProperOutputFormat) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(NEO::spirvMagic.begin(), NEO::spirvMagic.size()));
|
||||
auto elfData = elfEnc64.encode();
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclLibrary, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(unpackResult.intermediateRepresentation));
|
||||
EXPECT_EQ(NEO::spirvMagic.size(), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, ArrayRef<const uint8_t>::fromAny(NEO::llvmBcMagic.begin(), NEO::llvmBcMagic.size()));
|
||||
elfData = elfEnc64.encode();
|
||||
unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclCompiledObject, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(NEO::isLlvmBitcode(unpackResult.intermediateRepresentation));
|
||||
EXPECT_EQ(NEO::llvmBcMagic.size(), unpackResult.intermediateRepresentation.size());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenValidOclElfExecutableThenReadsAllSectionProperly) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
targetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
|
||||
const uint8_t intermediateRepresentation[] = "235711";
|
||||
const uint8_t debugData[] = "313739";
|
||||
std::string buildOptions = "buildOpts";
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
|
||||
{
|
||||
auto encWithLlvm = elfEnc64;
|
||||
encWithLlvm.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, NEO::Elf::SectionNamesOpenCl::llvmObject, intermediateRepresentation);
|
||||
auto elfData = encWithLlvm.encode();
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
|
||||
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
|
||||
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
|
||||
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
|
||||
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
|
||||
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
|
||||
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
|
||||
}
|
||||
{
|
||||
auto encWithSpirV = elfEnc64;
|
||||
encWithSpirV.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
|
||||
auto elfData = encWithSpirV.encode();
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfData, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpackResult.deviceBinary.size());
|
||||
ASSERT_EQ(sizeof(debugData), unpackResult.debugData.size());
|
||||
ASSERT_EQ(buildOptions.size() + 1, unpackResult.buildOptions.size());
|
||||
ASSERT_EQ(sizeof(intermediateRepresentation), unpackResult.intermediateRepresentation.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpackResult.deviceBinary.begin(), unpackResult.deviceBinary.size()));
|
||||
EXPECT_STREQ(buildOptions.c_str(), unpackResult.buildOptions.begin());
|
||||
EXPECT_EQ(0, memcmp(debugData, unpackResult.debugData.begin(), unpackResult.debugData.size()));
|
||||
EXPECT_EQ(0, memcmp(intermediateRepresentation, unpackResult.intermediateRepresentation.begin(), unpackResult.intermediateRepresentation.size()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWithUnhandledSectionThenUnpackingFails) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_NOBITS, "my_data", {});
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Unhandled ELF section", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryOclElf, GivenOclElfExecutableWhenPatchtokensBinaryIsBrokenThenReadsAllSectionProperly) {
|
||||
const uint8_t intermediateRepresentation[] = "235711";
|
||||
const uint8_t debugData[] = "313739";
|
||||
const uint8_t deviceBinary[] = "not_patchtokens";
|
||||
std::string buildOptions = "buildOpts";
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, deviceBinary);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, buildOptions);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_DEBUG, NEO::Elf::SectionNamesOpenCl::buildOptions, debugData);
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, intermediateRepresentation);
|
||||
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(elfEnc64.encode(), "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_FALSE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_FALSE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryOclElf, WhenUsedAsSingleDeviceBinaryThenDecodingFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc64;
|
||||
elfEnc64.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc64.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
auto elfData = elfEnc64.encode();
|
||||
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
targetDevice.stepping = patchtokensProgram.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
|
||||
NEO::SingleDeviceBinary deviceBinary;
|
||||
deviceBinary.targetDevice = targetDevice;
|
||||
deviceBinary.deviceBinary = elfData;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::DecodeError error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(programInfo, deviceBinary, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Device binary format is packed", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingEmptyDataThenEmptyOclElfIsEmitted) {
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(0U, elf.elfFileHeader->shNum);
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWithUnknownIntermediateRepresentationThenFail) {
|
||||
const uint8_t intermediateRepresentation[] = "not_llvm_and_not_spirv";
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
singleBinary.intermediateRepresentation = intermediateRepresentation;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_FALSE(packErrors.empty());
|
||||
EXPECT_STREQ("Unknown intermediate representation format", packErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryWitIntermediateRepresentationThenChoosesProperSectionBasedOnMagic) {
|
||||
using namespace NEO::Elf;
|
||||
auto spirV = NEO::spirvMagic;
|
||||
auto llvmBc = NEO::llvmBcMagic;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
{
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_FALSE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto spirVSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
ASSERT_NE(nullptr, spirVSection);
|
||||
ASSERT_EQ(spirV.size(), spirVSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(spirV.begin(), spirVSection->data.begin(), spirV.size()));
|
||||
}
|
||||
|
||||
{
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(llvmBc.begin(), llvmBc.size());
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_FALSE(packedData.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
|
||||
ASSERT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packedData));
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
EXPECT_EQ(NEO::Elf::ET_OPENCL_EXECUTABLE, elf.elfFileHeader->type);
|
||||
EXPECT_EQ(3U, elf.elfFileHeader->shNum);
|
||||
|
||||
auto llvmSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_LLVM_BINARY; });
|
||||
ASSERT_NE(nullptr, llvmSection);
|
||||
ASSERT_EQ(llvmBc.size(), llvmSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(llvmBc.begin(), llvmSection->data.begin(), llvmBc.size()));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinaryOclElf, WhenPackingBinaryThenSectionsAreProperlyPopulated) {
|
||||
using namespace NEO::Elf;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
|
||||
auto spirV = NEO::spirvMagic;
|
||||
const uint8_t debugData[] = "313739";
|
||||
const uint8_t deviceBinary[] = "23571113";
|
||||
std::string buildOptions = "buildOpts";
|
||||
singleBinary.intermediateRepresentation = ArrayRef<const uint8_t>::fromAny(spirV.begin(), spirV.size());
|
||||
singleBinary.debugData = debugData;
|
||||
singleBinary.deviceBinary = deviceBinary;
|
||||
singleBinary.buildOptions = buildOptions;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packedData = NEO::packDeviceBinary<NEO::DeviceBinaryFormat::OclElf>(singleBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
|
||||
std::string decodeElfErrors;
|
||||
std::string decodeElfWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(packedData, decodeElfErrors, decodeElfWarnings);
|
||||
EXPECT_TRUE(decodeElfErrors.empty());
|
||||
EXPECT_TRUE(decodeElfWarnings.empty());
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
|
||||
auto spirvSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_SPIRV; });
|
||||
|
||||
auto deviceBinarySection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_BINARY; });
|
||||
|
||||
auto deviceDebugSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_DEV_DEBUG; });
|
||||
|
||||
auto buildOptionsSection = std::find_if(elf.sectionHeaders.begin(), elf.sectionHeaders.end(),
|
||||
[](const Elf<>::SectionHeaderAndData §ion) { return section.header->type == NEO::Elf::SHT_OPENCL_OPTIONS; });
|
||||
|
||||
ASSERT_NE(nullptr, spirvSection);
|
||||
ASSERT_EQ(spirV.size(), spirvSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(spirV.begin(), spirvSection->data.begin(), spirV.size()));
|
||||
|
||||
ASSERT_NE(nullptr, deviceBinarySection);
|
||||
ASSERT_EQ(sizeof(deviceBinary), deviceBinarySection->data.size());
|
||||
EXPECT_EQ(0, memcmp(deviceBinary, deviceBinarySection->data.begin(), sizeof(deviceBinary)));
|
||||
|
||||
ASSERT_NE(nullptr, deviceDebugSection);
|
||||
ASSERT_EQ(sizeof(debugData), deviceDebugSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(debugData, deviceDebugSection->data.begin(), sizeof(debugData)));
|
||||
|
||||
ASSERT_NE(nullptr, buildOptionsSection);
|
||||
ASSERT_EQ(buildOptions.size(), buildOptionsSection->data.size());
|
||||
EXPECT_EQ(0, memcmp(buildOptions.c_str(), buildOptionsSection->data.begin(), buildOptions.size()));
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(IsDeviceBinaryFormatPatchtokens, GiveValidBinaryReturnTrue) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage));
|
||||
}
|
||||
|
||||
TEST(IsDeviceBinaryFormatPatchtokens, GiveInvalidBinaryReturnTrue) {
|
||||
const uint8_t binary[] = "not_patchtokens";
|
||||
EXPECT_FALSE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::Patchtokens>(binary));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenFailedToDecodeHeaderThenUnpackingFails) {
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>({}, "", {}, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_STREQ("Invalid program header", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryAndMatchedWithRequestedTargetDeviceThenReturnSelf) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpackResult.format);
|
||||
EXPECT_EQ(targetDevice.coreFamily, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(targetDevice.stepping, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(targetDevice.maxPointerSizeInBytes, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_FALSE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_EQ(programTokens.storage.data(), unpackResult.deviceBinary.begin());
|
||||
EXPECT_EQ(programTokens.storage.size(), unpackResult.deviceBinary.size());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_TRUE(unpackErrors.empty());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryForDifferentCoreFamilyDeviceThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device + 1);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPatchTokensVerionThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
programTokens.headerMutable->Version += 1;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = programTokens.header->GPUPointerSizeInBytes;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinaryPatchtokens, WhenValidBinaryWithUnsupportedPointerSizeThenUnpackingFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
programTokens.headerMutable->GPUPointerSizeInBytes = 8U;
|
||||
NEO::TargetDevice targetDevice;
|
||||
targetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(programTokens.header->Device);
|
||||
targetDevice.stepping = programTokens.header->SteppingId;
|
||||
targetDevice.maxPointerSizeInBytes = 4U;
|
||||
|
||||
std::string unpackErrors;
|
||||
std::string unpackWarnings;
|
||||
auto unpackResult = NEO::unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programTokens.storage, "", targetDevice, unpackErrors, unpackWarnings);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpackResult.format);
|
||||
EXPECT_EQ(IGFX_UNKNOWN_CORE, unpackResult.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpackResult.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpackResult.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(unpackResult.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpackResult.debugData.empty());
|
||||
EXPECT_TRUE(unpackResult.intermediateRepresentation.empty());
|
||||
EXPECT_TRUE(unpackResult.buildOptions.empty());
|
||||
EXPECT_TRUE(unpackWarnings.empty());
|
||||
EXPECT_FALSE(unpackErrors.empty());
|
||||
EXPECT_STREQ("Unhandled target device", unpackErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenInvalidBinaryThenReturnError) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, error);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinaryPatchtokens, GivenValidBinaryThenOutputIsProperlyPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::SingleDeviceBinary singleBinary;
|
||||
singleBinary.deviceBinary = programTokens.storage;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto error = NEO::decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::Patchtokens>(programInfo, singleBinary, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, error);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
ASSERT_EQ(1U, programInfo.kernelInfos.size());
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "test.h"
|
||||
|
||||
TEST(DecodeError, WhenStringRepresentationIsNeededThenAsStringEncodesProperly) {
|
||||
EXPECT_STREQ("decoded successfully", NEO::asString(NEO::DecodeError::Success));
|
||||
EXPECT_STREQ("in undefined status", NEO::asString(NEO::DecodeError::Undefined));
|
||||
EXPECT_STREQ("with invalid binary", NEO::asString(NEO::DecodeError::InvalidBinary));
|
||||
EXPECT_STREQ("with unhandled binary", NEO::asString(NEO::DecodeError::UnhandledBinary));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenNoneOfKnownFormatsThenReturnsFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnyDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnyDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isAnyDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenUnknownBinaryThenReturnError) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(data, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.deviceBinary.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, unpacked.format);
|
||||
EXPECT_EQ(0U, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(0U, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(4U, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_STREQ("Unknown format", outErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenPatchtoknsBinaryThenReturnSelf) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
requestedTargetDevice.stepping = patchtokensProgram.header->Device;
|
||||
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(patchtokensProgram.storage, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_FALSE(unpacked.deviceBinary.empty());
|
||||
EXPECT_EQ(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin());
|
||||
EXPECT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_TRUE(outErrors.empty());
|
||||
}
|
||||
|
||||
TEST(UnpackSingleDeviceBinary, GivenOclElfBinaryThenReturnPatchtokensBinary) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
|
||||
ConstStringRef requestedProductAbbreviation = "unk";
|
||||
NEO::TargetDevice requestedTargetDevice;
|
||||
requestedTargetDevice.coreFamily = static_cast<GFXCORE_FAMILY>(patchtokensProgram.header->Device);
|
||||
requestedTargetDevice.stepping = patchtokensProgram.header->Device;
|
||||
requestedTargetDevice.maxPointerSizeInBytes = patchtokensProgram.header->GPUPointerSizeInBytes;
|
||||
std::string outErrors;
|
||||
std::string outWarnings;
|
||||
auto elfData = elfEnc.encode();
|
||||
auto unpacked = NEO::unpackSingleDeviceBinary(elfData, requestedProductAbbreviation, requestedTargetDevice, outErrors, outWarnings);
|
||||
EXPECT_TRUE(unpacked.buildOptions.empty());
|
||||
EXPECT_TRUE(unpacked.debugData.empty());
|
||||
EXPECT_TRUE(unpacked.intermediateRepresentation.empty());
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, unpacked.format);
|
||||
EXPECT_EQ(requestedTargetDevice.coreFamily, unpacked.targetDevice.coreFamily);
|
||||
EXPECT_EQ(requestedTargetDevice.stepping, unpacked.targetDevice.stepping);
|
||||
EXPECT_EQ(patchtokensProgram.header->GPUPointerSizeInBytes, unpacked.targetDevice.maxPointerSizeInBytes);
|
||||
EXPECT_TRUE(outWarnings.empty());
|
||||
EXPECT_TRUE(outErrors.empty());
|
||||
|
||||
EXPECT_FALSE(unpacked.deviceBinary.empty());
|
||||
ASSERT_EQ(patchtokensProgram.storage.size(), unpacked.deviceBinary.size());
|
||||
EXPECT_EQ(0, memcmp(patchtokensProgram.storage.data(), unpacked.deviceBinary.begin(), unpacked.deviceBinary.size()));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsFalse) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_FALSE(NEO::isAnyPackedDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnyPackedDeviceBinaryFormat, GivenOclElfFormatThenReturnsTrue) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_TRUE(NEO::isAnyPackedDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(data));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenPatchTokensFormatThenReturnsTrue) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
EXPECT_TRUE(NEO::isAnySingleDeviceBinaryFormat(patchtokensProgram.storage));
|
||||
}
|
||||
|
||||
TEST(IsAnySingleDeviceBinaryFormat, GivenOclElfFormatThenReturnsFalse) {
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
EXPECT_FALSE(NEO::isAnySingleDeviceBinaryFormat(elfEnc.encode()));
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenUnknownFormatThenReturnFalse) {
|
||||
const uint8_t data[] = "none of known formats";
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = data;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Unknown, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("Unknown format", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenPatchTokensFormatThenDecodingSucceeds) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = patchtokensProgram.storage;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::Patchtokens, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
}
|
||||
|
||||
TEST(DecodeSingleDeviceBinary, GivenOclElfFormatThenDecodingFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram patchtokensProgram;
|
||||
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEnc;
|
||||
elfEnc.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEnc.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, patchtokensProgram.storage);
|
||||
|
||||
auto elfData = elfEnc.encode();
|
||||
NEO::ProgramInfo programInfo;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
NEO::SingleDeviceBinary bin;
|
||||
bin.deviceBinary = elfData;
|
||||
NEO::DecodeError status;
|
||||
NEO::DeviceBinaryFormat format;
|
||||
std::tie(status, format) = NEO::decodeSingleDeviceBinary(programInfo, bin, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, status);
|
||||
EXPECT_EQ(NEO::DeviceBinaryFormat::OclElf, format);
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
EXPECT_STREQ("Device binary format is packed", decodeErrors.c_str());
|
||||
}
|
||||
|
||||
TEST(PackDeviceBinary, GivenRequestToPackThenUsesOclElfFormat) {
|
||||
NEO::SingleDeviceBinary deviceBinary;
|
||||
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
auto packed = NEO::packDeviceBinary(deviceBinary, packErrors, packWarnings);
|
||||
EXPECT_TRUE(packErrors.empty());
|
||||
EXPECT_TRUE(packWarnings.empty());
|
||||
EXPECT_TRUE(NEO::isDeviceBinaryFormat<NEO::DeviceBinaryFormat::OclElf>(packed));
|
||||
}
|
||||
343
core/unit_tests/device_binary_format/elf/elf_decoder_tests.cpp
Normal file
343
core/unit_tests/device_binary_format/elf/elf_decoder_tests.cpp
Normal file
@@ -0,0 +1,343 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO::Elf;
|
||||
|
||||
TEST(ElfDecoder, WhenEmptyDataThenElfHeaderDecodingFails) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(empty));
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidHaderThenElfHeaderDecodingSucceeds) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(&header64, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(&header32, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotEngoughDataThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
auto header64Data = ArrayRef<const uint8_t>::fromAny(&header64, 1U);
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>(header64Data.begin(), header64Data.begin() + header64Data.size() - 1)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
auto header32Data = ArrayRef<const uint8_t>::fromAny(&header32, 1U);
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>(header32Data.begin(), header32Data.begin() + header32Data.size() - 1)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenInvalidElfMagicThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.identity.magic[0] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[1] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[2] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
header.identity.magic[3] = 5;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
|
||||
header = ElfFileHeader<EI_CLASS_64>{};
|
||||
EXPECT_EQ(&header, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenMismatchedClassThenElfHeaderDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(nullptr, decodeElfFileHeader<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotElfThenCheckNumBitsReturnsClassNone) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_EQ(EI_CLASS_NONE, getElfNumBits(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidElfThenCheckNumBitsReturnsProperClass) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_EQ(EI_CLASS_64, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_EQ(EI_CLASS_32, getElfNumBits(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenNotElfThenIsElfReturnsFalse) {
|
||||
ArrayRef<const uint8_t> empty;
|
||||
EXPECT_FALSE(isElf(empty));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidElfThenIsElfReturnsTrue) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header64, 1U)));
|
||||
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
EXPECT_TRUE(isElf(ArrayRef<const uint8_t>::fromAny(&header32, 1U)));
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidEmptyElfThenHeaderIsProperlyDecodedAndNoWarningsOrErrorsEmitted) {
|
||||
ElfFileHeader<EI_CLASS_64> header64;
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header64, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(&header64, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
|
||||
decodeWarnings.clear();
|
||||
decodeErrors.clear();
|
||||
ElfFileHeader<EI_CLASS_32> header32;
|
||||
auto elf32 = decodeElf<EI_CLASS_32>(ArrayRef<const uint8_t>::fromAny(&header32, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(&header32, elf32.elfFileHeader);
|
||||
EXPECT_TRUE(elf32.programHeaders.empty());
|
||||
EXPECT_TRUE(elf32.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenInvalidElfHeaderThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.identity.magic[0] = 5;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Invalid or missing ELF header", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableOffsetThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = sizeof(header) + 1;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableOffsetThenDecodingFails) {
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = sizeof(header) + 1;
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(ArrayRef<const uint8_t>::fromAny(&header, 1U), decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidProgramHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
programHeader0.fileSz = sizeof(programHeader0) * 2;
|
||||
programHeader0.offset = header.phOff;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.programHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(programHeader0) *>(storage.data() + header.phOff), elf64.programHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(programHeader1) *>(storage.data() + header.phOff + header.phEntSize), elf64.programHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.programHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.programHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + programHeader0.offset, elf64.programHeaders[0].data.begin());
|
||||
EXPECT_EQ(programHeader0.fileSz, elf64.programHeaders[0].data.size());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderTableEntriesThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 3;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsProgramHeaderDataThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.phOff = header.ehSize;
|
||||
header.phNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader0;
|
||||
programHeader0.fileSz = sizeof(programHeader0) * 2;
|
||||
programHeader0.offset = header.phOff;
|
||||
ElfProgramHeader<EI_CLASS_64> programHeader1;
|
||||
programHeader1.fileSz = sizeof(programHeader0) * 3;
|
||||
programHeader1.offset = header.phOff;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader0), reinterpret_cast<const uint8_t *>(&programHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&programHeader1), reinterpret_cast<const uint8_t *>(&programHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds program header offset/filesz, program header idx : 1", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenValidSectionHeaderTableEntriesThenDecodingSucceedsAndNoWarningsOrErrorsEmitted) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.sectionHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
|
||||
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderTableEntriesThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 3;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section headers table", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenOutOfBoundsSectionHeaderDataThenDecodingFails) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
sectionHeader1.size = sizeof(sectionHeader0) * 3;
|
||||
sectionHeader1.offset = header.shOff;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(nullptr, elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(elf64.sectionHeaders.empty());
|
||||
ASSERT_FALSE(decodeErrors.empty());
|
||||
EXPECT_STREQ("Out of bounds section header offset/size, section header idx : 1", decodeErrors.c_str());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
}
|
||||
|
||||
TEST(ElfDecoder, WhenSectionDoesNotHaveDataInFileThenDataIsSetAsEmpty) {
|
||||
std::vector<uint8_t> storage;
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.shOff = header.ehSize;
|
||||
header.shNum = 2;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(&header), reinterpret_cast<const uint8_t *>(&header + 1));
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader0;
|
||||
sectionHeader0.size = sizeof(sectionHeader0) * 2;
|
||||
sectionHeader0.offset = header.shOff;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionHeader1;
|
||||
sectionHeader1.size = sizeof(sectionHeader0) * 3;
|
||||
sectionHeader1.offset = header.shOff;
|
||||
sectionHeader1.type = SHT_NOBITS;
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader0), reinterpret_cast<const uint8_t *>(§ionHeader0 + 1));
|
||||
storage.insert(storage.end(), reinterpret_cast<const uint8_t *>(§ionHeader1), reinterpret_cast<const uint8_t *>(§ionHeader1 + 1));
|
||||
|
||||
std::string decodeWarnings;
|
||||
std::string decodeErrors;
|
||||
auto elf64 = decodeElf<EI_CLASS_64>(storage, decodeErrors, decodeWarnings);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(header) *>(storage.data()), elf64.elfFileHeader);
|
||||
EXPECT_TRUE(elf64.programHeaders.empty());
|
||||
EXPECT_TRUE(decodeErrors.empty());
|
||||
EXPECT_TRUE(decodeWarnings.empty());
|
||||
ASSERT_EQ(2U, elf64.sectionHeaders.size());
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader0) *>(storage.data() + header.shOff), elf64.sectionHeaders[0].header);
|
||||
EXPECT_EQ(reinterpret_cast<decltype(sectionHeader1) *>(storage.data() + header.shOff + header.shEntSize), elf64.sectionHeaders[1].header);
|
||||
EXPECT_TRUE(elf64.sectionHeaders[1].data.empty());
|
||||
EXPECT_FALSE(elf64.sectionHeaders[0].data.empty());
|
||||
EXPECT_EQ(storage.data() + sectionHeader0.offset, elf64.sectionHeaders[0].data.begin());
|
||||
EXPECT_EQ(sectionHeader0.size, elf64.sectionHeaders[0].data.size());
|
||||
}
|
||||
457
core/unit_tests/device_binary_format/elf/elf_encoder_tests.cpp
Normal file
457
core/unit_tests/device_binary_format/elf/elf_encoder_tests.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
/*
|
||||
* Copyright (C) 2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/utilities/range.h"
|
||||
#include "test.h"
|
||||
|
||||
using namespace NEO::Elf;
|
||||
|
||||
TEST(ElfEncoder, WhenEmptyDataThenEncodedElfContainsOnlyHeader) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto &identity64 = header64.identity;
|
||||
EXPECT_EQ(elfMagic[0], identity64.magic[0]);
|
||||
EXPECT_EQ(elfMagic[1], identity64.magic[1]);
|
||||
EXPECT_EQ(elfMagic[2], identity64.magic[2]);
|
||||
EXPECT_EQ(elfMagic[3], identity64.magic[3]);
|
||||
EXPECT_EQ(EI_CLASS_64, identity64.eClass);
|
||||
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity64.data);
|
||||
EXPECT_EQ(EV_CURRENT, identity64.version);
|
||||
EXPECT_EQ(0U, identity64.osAbi);
|
||||
EXPECT_EQ(0U, identity64.abiVersion);
|
||||
EXPECT_EQ(ET_NONE, header64.type);
|
||||
EXPECT_EQ(EM_NONE, header64.machine);
|
||||
EXPECT_EQ(1U, header64.version);
|
||||
EXPECT_EQ(0U, header64.entry);
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
|
||||
EXPECT_EQ(0U, header64.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
|
||||
EXPECT_EQ(0U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
ElfEncoder<EI_CLASS_32> elfEncoder32(false, false);
|
||||
auto elfData32 = elfEncoder32.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), elfData32.size());
|
||||
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
|
||||
auto &identity32 = header32.identity;
|
||||
EXPECT_EQ(elfMagic[0], identity32.magic[0]);
|
||||
EXPECT_EQ(elfMagic[1], identity32.magic[1]);
|
||||
EXPECT_EQ(elfMagic[2], identity32.magic[2]);
|
||||
EXPECT_EQ(elfMagic[3], identity32.magic[3]);
|
||||
EXPECT_EQ(EI_CLASS_32, identity32.eClass);
|
||||
EXPECT_EQ(EI_DATA_LITTLE_ENDIAN, identity32.data);
|
||||
EXPECT_EQ(EV_CURRENT, identity32.version);
|
||||
EXPECT_EQ(0U, identity32.osAbi);
|
||||
EXPECT_EQ(0U, identity32.abiVersion);
|
||||
EXPECT_EQ(ET_NONE, header32.type);
|
||||
EXPECT_EQ(EM_NONE, header32.machine);
|
||||
EXPECT_EQ(1U, header32.version);
|
||||
EXPECT_EQ(0U, header32.entry);
|
||||
EXPECT_EQ(0U, header32.phOff);
|
||||
EXPECT_EQ(0U, header32.shOff);
|
||||
EXPECT_EQ(0U, header32.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>), header32.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_32>), header32.phEntSize);
|
||||
EXPECT_EQ(0U, header32.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_32>), header32.shEntSize);
|
||||
EXPECT_EQ(0U, header32.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header32.shStrNdx);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNotNeededThenNotEmitted) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, GivenRequestForUndefAndSectionHeaderNamesSectionsWhenNeededThenEmitted) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
elfEncoder64.appendSection(SHT_NULL, ".my_name_is_important", {});
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
char expectedSectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(0U, header64.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>), header64.ehSize);
|
||||
EXPECT_EQ(sizeof(ElfProgramHeader<EI_CLASS_64>), header64.phEntSize);
|
||||
EXPECT_EQ(0U, header64.phNum);
|
||||
EXPECT_EQ(sizeof(ElfSectionHeader<EI_CLASS_64>), header64.shEntSize);
|
||||
EXPECT_EQ(3U, header64.shNum);
|
||||
EXPECT_EQ(2U, header64.shStrNdx);
|
||||
auto §Undef64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto §SkipMe64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
auto §SectionNames64 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
const char *sectionNames64Data = reinterpret_cast<char *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>));
|
||||
|
||||
EXPECT_EQ(0U, sectUndef64.name);
|
||||
EXPECT_EQ(SHT_NULL, sectUndef64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectUndef64.flags);
|
||||
EXPECT_EQ(0U, sectUndef64.addr);
|
||||
EXPECT_EQ(0U, sectUndef64.offset);
|
||||
EXPECT_EQ(0U, sectUndef64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectUndef64.link);
|
||||
EXPECT_EQ(0U, sectUndef64.info);
|
||||
EXPECT_EQ(0U, sectUndef64.addralign);
|
||||
EXPECT_EQ(0U, sectUndef64.entsize);
|
||||
|
||||
EXPECT_EQ(11U, sectSkipMe64.name);
|
||||
EXPECT_EQ(SHT_NULL, sectSkipMe64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectSkipMe64.flags);
|
||||
EXPECT_EQ(0U, sectSkipMe64.addr);
|
||||
EXPECT_EQ(0U, sectSkipMe64.offset);
|
||||
EXPECT_EQ(0U, sectSkipMe64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectSkipMe64.link);
|
||||
EXPECT_EQ(0U, sectSkipMe64.info);
|
||||
EXPECT_EQ(8U, sectSkipMe64.addralign);
|
||||
EXPECT_EQ(0U, sectSkipMe64.entsize);
|
||||
|
||||
EXPECT_EQ(1U, sectSectionNames64.name);
|
||||
EXPECT_EQ(SHT_STRTAB, sectSectionNames64.type);
|
||||
EXPECT_EQ(SHF_NONE, sectSectionNames64.flags);
|
||||
EXPECT_EQ(0U, sectSectionNames64.addr);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_64>), sectSectionNames64.offset);
|
||||
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames64.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectSectionNames64.link);
|
||||
EXPECT_EQ(0U, sectSectionNames64.info);
|
||||
EXPECT_EQ(8U, sectSectionNames64.addralign);
|
||||
EXPECT_EQ(0U, sectSectionNames64.entsize);
|
||||
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames64Data, sizeof(expectedSectionNamesData)));
|
||||
|
||||
ElfEncoder<EI_CLASS_32> elfEncoder32(true, true);
|
||||
elfEncoder32.appendSection(SHT_NULL, ".my_name_is_important", {});
|
||||
auto elfData32 = elfEncoder32.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>) + alignUp(sizeof(expectedSectionNamesData), 8), elfData32.size());
|
||||
auto &header32 = *reinterpret_cast<ElfFileHeader<EI_CLASS_32> *>(elfData32.data());
|
||||
EXPECT_EQ(header32.ehSize, header32.shOff);
|
||||
auto §SectionNames32 = *reinterpret_cast<ElfSectionHeader<EI_CLASS_32> *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 2 * sizeof(ElfSectionHeader<EI_CLASS_32>));
|
||||
const char *sectionNames32Data = reinterpret_cast<char *>(elfData32.data() + sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>));
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_32>) + 3 * sizeof(ElfSectionHeader<EI_CLASS_32>), sectSectionNames32.offset);
|
||||
EXPECT_EQ(sizeof(expectedSectionNamesData), sectSectionNames32.size);
|
||||
EXPECT_EQ(0, memcmp(expectedSectionNamesData, sectionNames32Data, sizeof(expectedSectionNamesData)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithDataThenOffsetsAreProperlyUpdated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §ProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto sectProgBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>);
|
||||
EXPECT_EQ(0U, sectProgBits.name);
|
||||
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
|
||||
EXPECT_EQ(0U, sectProgBits.addr);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfSectionHeader<EI_CLASS_64>), sectProgBits.offset);
|
||||
EXPECT_EQ(sizeof(data), sectProgBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
|
||||
EXPECT_EQ(0U, sectProgBits.info);
|
||||
EXPECT_EQ(8U, sectProgBits.addralign);
|
||||
EXPECT_EQ(0U, sectProgBits.entsize);
|
||||
EXPECT_EQ(0, memcmp(data, sectProgBitsData, sizeof(data)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithoutDataThenOffsetsAreLeftIntact) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
elfEncoder64.appendSection(SHT_PROGBITS, ".my_name_is_not_important", {});
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §ProgBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectProgBits.name);
|
||||
EXPECT_EQ(SHT_PROGBITS, sectProgBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectProgBits.flags);
|
||||
EXPECT_EQ(0U, sectProgBits.addr);
|
||||
EXPECT_EQ(0U, sectProgBits.offset);
|
||||
EXPECT_EQ(0U, sectProgBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectProgBits.link);
|
||||
EXPECT_EQ(0U, sectProgBits.info);
|
||||
EXPECT_EQ(8U, sectProgBits.addralign);
|
||||
EXPECT_EQ(0U, sectProgBits.entsize);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionWithNoBitsTypeThenDataIsIgnored) {
|
||||
{
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(SHT_NOBITS, ".my_name_is_not_important", data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.phOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.shOff);
|
||||
EXPECT_EQ(1U, header64.shNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto §NoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectNoBits.name);
|
||||
EXPECT_EQ(SHT_NOBITS, sectNoBits.type);
|
||||
EXPECT_EQ(SHF_NONE, sectNoBits.flags);
|
||||
EXPECT_EQ(0U, sectNoBits.addr);
|
||||
EXPECT_EQ(0U, sectNoBits.offset);
|
||||
EXPECT_EQ(0U, sectNoBits.size);
|
||||
EXPECT_EQ(SHN_UNDEF, sectNoBits.link);
|
||||
EXPECT_EQ(0U, sectNoBits.info);
|
||||
EXPECT_EQ(8U, sectNoBits.addralign);
|
||||
EXPECT_EQ(0U, sectNoBits.entsize);
|
||||
}
|
||||
|
||||
{
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSection(static_cast<uint32_t>(SHT_NOBITS), ".my_name_is_not_important", data).size = sizeof(data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfSectionHeader<EI_CLASS_64>), elfData64.size());
|
||||
|
||||
auto §NoBits = *reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(0U, sectNoBits.offset);
|
||||
EXPECT_EQ(sizeof(data), sectNoBits.size);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSegmentWithDataThenOffsetsAreProperlyUpdated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
const uint8_t data[] = "235711131719";
|
||||
elfEncoder64.appendSegment(PT_LOAD, data);
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>) + alignUp(sizeof(data), 8), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.phOff);
|
||||
EXPECT_EQ(1U, header64.phNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
auto segLoadBitsData = elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>);
|
||||
EXPECT_EQ(PT_LOAD, segLoad.type);
|
||||
EXPECT_EQ(PF_NONE, segLoad.flags);
|
||||
EXPECT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + sizeof(ElfProgramHeader<EI_CLASS_64>), segLoad.offset);
|
||||
EXPECT_EQ(0U, segLoad.vAddr);
|
||||
EXPECT_EQ(0U, segLoad.pAddr);
|
||||
EXPECT_EQ(sizeof(data), segLoad.fileSz);
|
||||
EXPECT_EQ(0U, segLoad.memSz);
|
||||
EXPECT_EQ(8U, segLoad.align);
|
||||
EXPECT_EQ(0, memcmp(data, segLoadBitsData, sizeof(data)));
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSegmentWithoutDataThenOffsetsAreLeftIntact) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, false);
|
||||
elfEncoder64.appendSegment(PT_LOAD, {});
|
||||
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
ASSERT_EQ(sizeof(ElfFileHeader<EI_CLASS_64>) + 1 * sizeof(ElfProgramHeader<EI_CLASS_64>), elfData64.size());
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
EXPECT_EQ(0U, header64.shOff);
|
||||
EXPECT_EQ(header64.ehSize, header64.phOff);
|
||||
EXPECT_EQ(1U, header64.phNum);
|
||||
EXPECT_EQ(SHN_UNDEF, header64.shStrNdx);
|
||||
|
||||
auto &segLoad = *reinterpret_cast<ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + sizeof(ElfFileHeader<EI_CLASS_64>));
|
||||
EXPECT_EQ(PT_LOAD, segLoad.type);
|
||||
EXPECT_EQ(PF_NONE, segLoad.flags);
|
||||
EXPECT_EQ(0U, segLoad.offset);
|
||||
EXPECT_EQ(0U, segLoad.vAddr);
|
||||
EXPECT_EQ(0U, segLoad.pAddr);
|
||||
EXPECT_EQ(0U, segLoad.fileSz);
|
||||
EXPECT_EQ(0U, segLoad.memSz);
|
||||
EXPECT_EQ(8U, segLoad.align);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingBothSectionAndSegmentThenProperElfIsEmited) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143";
|
||||
const uint8_t sectionNamesData[] = "\0.shstrtab\0.my_name_is_important";
|
||||
|
||||
ElfFileHeader<EI_CLASS_64> header;
|
||||
header.type = ET_EXEC;
|
||||
header.entry = 16U;
|
||||
header.phOff = static_cast<decltype(header.phOff)>(sizeof(header));
|
||||
header.shOff = static_cast<decltype(header.shOff)>(sizeof(header) + sizeof(ElfProgramHeader<EI_CLASS_64>));
|
||||
header.flags = 4U;
|
||||
header.phNum = 1U;
|
||||
header.shNum = 3U;
|
||||
header.shStrNdx = 2U;
|
||||
|
||||
ElfProgramHeader<EI_CLASS_64> segment;
|
||||
segment.type = PT_LOAD;
|
||||
segment.flags = PF_R | PF_X;
|
||||
segment.offset = static_cast<decltype(segment.offset)>(header.shOff + sizeof(ElfSectionHeader<EI_CLASS_64>) * 3);
|
||||
segment.vAddr = 4096U;
|
||||
segment.pAddr = 4096U * 16;
|
||||
segment.fileSz = static_cast<decltype(segment.fileSz)>(sizeof(segmentData));
|
||||
segment.memSz = 8192U;
|
||||
segment.align = 8U;
|
||||
|
||||
ElfSectionHeader<EI_CLASS_64> sectionUndef;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionProgBits;
|
||||
sectionProgBits.name = 11U;
|
||||
sectionProgBits.type = SHT_PROGBITS;
|
||||
sectionProgBits.flags = SHF_ALLOC;
|
||||
sectionProgBits.addr = 16U;
|
||||
sectionProgBits.offset = static_cast<decltype(sectionProgBits.offset)>(segment.offset + alignUp(static_cast<size_t>(segment.fileSz), static_cast<size_t>(segment.align)));
|
||||
sectionProgBits.size = static_cast<decltype(sectionProgBits.size)>(sizeof(sectionData));
|
||||
sectionProgBits.link = SHN_UNDEF;
|
||||
sectionProgBits.info = 0U;
|
||||
sectionProgBits.addralign = 16U;
|
||||
sectionProgBits.entsize = 0U;
|
||||
ElfSectionHeader<EI_CLASS_64> sectionSectionNames;
|
||||
sectionSectionNames.name = 1U;
|
||||
sectionSectionNames.type = SHT_STRTAB;
|
||||
sectionSectionNames.flags = SHF_NONE;
|
||||
sectionSectionNames.addr = 0U;
|
||||
sectionSectionNames.offset = static_cast<decltype(sectionSectionNames.offset)>(sectionProgBits.offset + alignUp(static_cast<size_t>(sectionProgBits.size), static_cast<size_t>(sectionProgBits.addralign)));
|
||||
sectionSectionNames.size = static_cast<decltype(sectionSectionNames.size)>(sizeof(sectionNamesData));
|
||||
sectionSectionNames.link = SHN_UNDEF;
|
||||
sectionSectionNames.info = 0U;
|
||||
sectionSectionNames.addralign = 8U;
|
||||
sectionSectionNames.entsize = 0U;
|
||||
|
||||
std::vector<uint8_t> handMade;
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&header), reinterpret_cast<uint8_t *>(&header + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(&segment), reinterpret_cast<uint8_t *>(&segment + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionUndef), reinterpret_cast<uint8_t *>(§ionUndef + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionProgBits), reinterpret_cast<uint8_t *>(§ionProgBits + 1));
|
||||
handMade.insert(handMade.end(), reinterpret_cast<uint8_t *>(§ionSectionNames), reinterpret_cast<uint8_t *>(§ionSectionNames + 1));
|
||||
handMade.insert(handMade.end(), segmentData, segmentData + sizeof(segmentData));
|
||||
handMade.resize(static_cast<size_t>(sectionProgBits.offset), 0U);
|
||||
handMade.insert(handMade.end(), sectionData, sectionData + sizeof(sectionData));
|
||||
handMade.resize(static_cast<size_t>(sectionSectionNames.offset), 0U);
|
||||
handMade.insert(handMade.end(), sectionNamesData, sectionNamesData + sizeof(sectionNamesData));
|
||||
handMade.resize(static_cast<size_t>(sectionSectionNames.offset + alignUp(sizeof(sectionNamesData), 8U)), 0U);
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64;
|
||||
{
|
||||
auto &encodedHeader = elfEncoder64.getElfFileHeader();
|
||||
encodedHeader.type = ET_EXEC;
|
||||
encodedHeader.entry = 16U;
|
||||
encodedHeader.flags = 4U;
|
||||
|
||||
auto &encodedSegment = elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
encodedSegment.type = PT_LOAD;
|
||||
encodedSegment.flags = PF_R | PF_X;
|
||||
encodedSegment.vAddr = 4096U;
|
||||
encodedSegment.pAddr = 4096U * 16;
|
||||
encodedSegment.memSz = 8192U;
|
||||
encodedSegment.align = 8U;
|
||||
|
||||
ElfSectionHeader<EI_CLASS_64> encodedSectionProgBits;
|
||||
encodedSectionProgBits.name = elfEncoder64.appendSectionName(".my_name_is_important");
|
||||
encodedSectionProgBits.type = SHT_PROGBITS;
|
||||
encodedSectionProgBits.flags = SHF_ALLOC;
|
||||
encodedSectionProgBits.addr = 16U;
|
||||
encodedSectionProgBits.link = SHN_UNDEF;
|
||||
encodedSectionProgBits.info = 0U;
|
||||
encodedSectionProgBits.addralign = 16U;
|
||||
encodedSectionProgBits.entsize = 0U;
|
||||
|
||||
elfEncoder64.appendSection(encodedSectionProgBits, sectionData);
|
||||
}
|
||||
|
||||
auto generated = elfEncoder64.encode();
|
||||
|
||||
EXPECT_EQ(handMade, generated);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenDefaultAlignmentIsRaisedThenSegmentDataAbideByIt) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143475";
|
||||
|
||||
static constexpr size_t alignment = 128U;
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
|
||||
elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
|
||||
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
|
||||
auto programHeaders = reinterpret_cast<NEO::Elf::ElfProgramHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.phOff));
|
||||
for (const auto §ion : NEO::CreateRange(sectionHeaders, header64.shNum)) {
|
||||
EXPECT_EQ(0U, section.offset % 8U);
|
||||
}
|
||||
for (const auto &segment : NEO::CreateRange(programHeaders, header64.phNum)) {
|
||||
EXPECT_EQ(0U, segment.offset % alignment);
|
||||
EXPECT_LE(alignment, segment.align);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenDefaultAlignmentIsLoweredThenSectionAndSegmentDataAbideByIt) {
|
||||
const uint8_t segmentData[] = "235711131719";
|
||||
const uint8_t sectionData[] = "232931374143475";
|
||||
|
||||
static constexpr size_t alignment = 1U;
|
||||
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true, alignment);
|
||||
elfEncoder64.appendSegment(PT_LOAD, segmentData);
|
||||
|
||||
elfEncoder64.appendSection(NEO::Elf::SHT_PROGBITS, "my_name_is_important", sectionData);
|
||||
auto elfData64 = elfEncoder64.encode();
|
||||
|
||||
auto &header64 = *reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData64.data());
|
||||
auto sectionHeaders = reinterpret_cast<NEO::Elf::ElfSectionHeader<EI_CLASS_64> *>(elfData64.data() + static_cast<size_t>(header64.shOff));
|
||||
NEO::Elf::ElfSectionHeader<EI_CLASS_64> *sectionNamesSection = sectionHeaders + header64.shStrNdx;
|
||||
size_t unpaddedSize = sizeof(ElfFileHeader<EI_CLASS_64>) + 3 * sizeof(NEO::Elf::ElfSectionHeader<EI_CLASS_64>) + sizeof(NEO::Elf::ElfProgramHeader<EI_CLASS_64>);
|
||||
unpaddedSize += sizeof(segmentData) + sizeof(sectionData) + static_cast<size_t>(sectionNamesSection->size);
|
||||
EXPECT_EQ(unpaddedSize, elfData64.size());
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingEmptySectionNameThenAlwaysReturn0AsOffset) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(false, true);
|
||||
auto offset0 = elfEncoder64.appendSectionName({});
|
||||
auto offset1 = elfEncoder64.appendSectionName({});
|
||||
auto offset2 = elfEncoder64.appendSectionName({});
|
||||
EXPECT_EQ(0U, offset0);
|
||||
EXPECT_EQ(0U, offset1);
|
||||
EXPECT_EQ(0U, offset2);
|
||||
}
|
||||
|
||||
TEST(ElfEncoder, WhenAppendingSectionNameThenEmplacedStringIsAlwaysNullterminated) {
|
||||
ElfEncoder<EI_CLASS_64> elfEncoder64(true, true);
|
||||
auto strOffset = elfEncoder64.appendSectionName(ConstStringRef("abc", 2));
|
||||
auto strOffset2 = elfEncoder64.appendSectionName(ConstStringRef("de", 3));
|
||||
auto strOffset3 = elfEncoder64.appendSectionName(ConstStringRef("g"));
|
||||
elfEncoder64.appendSection(SHT_NOBITS, "my_name_is_important", {});
|
||||
EXPECT_EQ(strOffset + 3, strOffset2);
|
||||
EXPECT_EQ(strOffset2 + 3, strOffset3);
|
||||
auto elfData = elfEncoder64.encode();
|
||||
auto header = reinterpret_cast<ElfFileHeader<EI_CLASS_64> *>(elfData.data());
|
||||
|
||||
auto sectionNamesSection = reinterpret_cast<ElfSectionHeader<EI_CLASS_64> *>(elfData.data() + static_cast<size_t>(header->shOff + header->shStrNdx * header->shEntSize));
|
||||
EXPECT_STREQ("ab", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset));
|
||||
EXPECT_STREQ("de", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset2));
|
||||
EXPECT_STREQ("g", reinterpret_cast<const char *>(elfData.data() + sectionNamesSection->offset + strOffset3));
|
||||
}
|
||||
@@ -191,7 +191,7 @@ TEST(KernelDecoder, GivenValidEmptyKernelThenDecodingOfHeaderSucceeds) {
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
ASSERT_NE(nullptr, decodedKernel.header);
|
||||
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
|
||||
EXPECT_EQ(kernelToEncode.name, decodedKernel.name);
|
||||
@@ -211,7 +211,7 @@ TEST(KernelDecoder, GivenEmptyKernelWhenBlobSmallerThanKernelHeaderThenDecodingF
|
||||
kernelToEncode.blobs.kernelInfo.begin() + sizeof(iOpenCL::SKernelBinaryHeader) - 1);
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(brokenBlob, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProperlySet) {
|
||||
@@ -246,7 +246,7 @@ TEST(KernelDecoder, GivenValidKernelWithHeapsThenDecodingSucceedsAndHeapsAreProp
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
|
||||
EXPECT_EQ(kernelToEncode.header, decodedKernel.header);
|
||||
EXPECT_EQ(0U, decodedKernel.unhandledTokens.size());
|
||||
@@ -274,37 +274,37 @@ TEST(KernelDecoder, GivenEmptyKernelWhenBlobDoesntHaveEnoughSpaceForHeaderDataTh
|
||||
kernelHeader->KernelNameSize = outOfBoundsSize;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->KernelNameSize = originalHeader.KernelNameSize;
|
||||
|
||||
kernelHeader->KernelHeapSize = outOfBoundsSize;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->KernelHeapSize = originalHeader.KernelHeapSize;
|
||||
|
||||
kernelHeader->GeneralStateHeapSize = outOfBoundsSize;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->GeneralStateHeapSize = originalHeader.GeneralStateHeapSize;
|
||||
|
||||
kernelHeader->DynamicStateHeapSize = outOfBoundsSize;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->DynamicStateHeapSize = originalHeader.DynamicStateHeapSize;
|
||||
|
||||
kernelHeader->SurfaceStateHeapSize = outOfBoundsSize;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->SurfaceStateHeapSize = originalHeader.SurfaceStateHeapSize;
|
||||
|
||||
kernelHeader->PatchListSize = outOfBoundsSize;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToEncode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
kernelHeader->PatchListSize = originalHeader.PatchListSize;
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ TEST(KernelDecoder, GivenKernelWithValidKernelPatchtokensThenDecodingSucceedsAnd
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
EXPECT_EQ(ptrOffset(storage.data(), patchListOffset), decodedKernel.blobs.patchList.begin());
|
||||
EXPECT_EQ(ptrOffset(storage.data(), storage.size()), decodedKernel.blobs.patchList.end());
|
||||
@@ -398,7 +398,7 @@ TEST(KernelDecoder, GivenKernelWithValidStringPatchtokensThenDecodingSucceedsAnd
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -446,7 +446,7 @@ TEST(KernelDecoder, GivenKernelWithValidArgInfoPatchtokensThenDecodingSucceedsAn
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -507,7 +507,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgPatchtokensThenDecodingSucceeds
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -589,7 +589,7 @@ TEST(KernelDecoder, GivenKernelWithValidNonArgCrossThreadDataPatchtokensThenDeco
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -644,7 +644,7 @@ TEST(KernelDecoder, GivenKernelWithArgCrossThreadDataPatchtokensWhenSourceIndexI
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
ASSERT_EQ(5U, decodedKernel.unhandledTokens.size());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -670,7 +670,7 @@ TEST(KernelDecoder, GivenKernelWithUnkownPatchtokensThenDecodingSucceedsButToken
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
ASSERT_EQ(2U, decodedKernel.unhandledTokens.size());
|
||||
|
||||
auto base = storage.data();
|
||||
@@ -716,7 +716,7 @@ TEST(KernelDecoder, GivenKernelWithValidObjectArgMetadataPatchtokensThenDecoding
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
ASSERT_EQ(4U, decodedKernel.tokens.kernelArgs.size());
|
||||
@@ -776,14 +776,14 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
decodedKernel = {};
|
||||
@@ -791,77 +791,77 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_IMAGE_WIDTH;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_SAMPLER_ADDRESS_MODE;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
|
||||
decodedKernel = {};
|
||||
arg0Metadata0->Type = iOpenCL::DATA_PARAMETER_SUM_OF_LOCAL_MEMORY_OBJECT_ARGUMENT_SIZES;
|
||||
arg0Metadata1->Type = iOpenCL::DATA_PARAMETER_BUFFER_STATEFUL;
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingFailsAndStops) {
|
||||
@@ -883,7 +883,7 @@ TEST(KernelDecoder, GivenKernelWithMismatchedArgMetadataPatchtokensThenDecodingF
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
}
|
||||
|
||||
@@ -905,7 +905,7 @@ TEST(KernelDecoder, GivenKernelWithByValArgMetadataPatchtokensThenDecodingSuccee
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
ASSERT_EQ(2U, decodedKernel.tokens.kernelArgs.size());
|
||||
@@ -940,7 +940,7 @@ TEST(KernelDecoder, GivenKernelWithVmeMetadataPatchtokensThenDecodingSucceedsAnd
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
|
||||
ASSERT_EQ(1U, decodedKernel.tokens.kernelArgs.size());
|
||||
@@ -971,7 +971,7 @@ TEST(KernelDecoder, GivenKernelWithOutOfBoundsTokenThenDecodingFails) {
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens decodedKernel;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(storage, decodedKernel);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedKernel.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenValidEmptyProgramThenDecodingOfHeaderSucceeds) {
|
||||
@@ -980,7 +980,7 @@ TEST(ProgramDecoder, GivenValidEmptyProgramThenDecodingOfHeaderSucceeds) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
ASSERT_NE(nullptr, decodedProgram.header);
|
||||
EXPECT_EQ(programToEncode.header, decodedProgram.header);
|
||||
@@ -998,7 +998,7 @@ TEST(ProgramDecoder, GivenProgramWhenBlobSmallerThanProgramHeaderThenDecodingFai
|
||||
programToEncode.blobs.programInfo.begin() + sizeof(iOpenCL::SProgramBinaryHeader) - 1);
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(brokenBlob, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithInvaidProgramMagicThenDecodingFails) {
|
||||
@@ -1007,7 +1007,7 @@ TEST(ProgramDecoder, GivenProgramWithInvaidProgramMagicThenDecodingFails) {
|
||||
programToEncode.headerMutable->Magic += 1;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWhenBlobDoesntHaveEnoughSpaceForPatchListThenDecodingFails) {
|
||||
@@ -1016,7 +1016,7 @@ TEST(ProgramDecoder, GivenProgramWhenBlobDoesntHaveEnoughSpaceForPatchListThenDe
|
||||
programToEncode.headerMutable->PatchListSize = static_cast<uint32_t>(programToEncode.blobs.patchList.size() + 1);
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
||||
@@ -1024,7 +1024,7 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateConstantMemorySurface.size());
|
||||
EXPECT_EQ(programToEncode.programScopeTokens.allocateConstantMemorySurface[0], decodedProgram.programScopeTokens.allocateConstantMemorySurface[0]);
|
||||
@@ -1038,7 +1038,7 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
|
||||
programToEncode.recalcTokPtr();
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
|
||||
auto base = programToEncode.storage.data();
|
||||
@@ -1047,13 +1047,22 @@ TEST(ProgramDecoder, GivenValidProgramWithConstantSurfacesThenDecodingSucceedsAn
|
||||
EXPECT_TRUE(tokenOffsetMatched(base, secondConstantSurfaceOff, decodedProgram.programScopeTokens.allocateConstantMemorySurface[1]));
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithConstantSurfaceWhenBlobSmallerThanNeededForPatchTokenThenDecodingFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
programToEncode.headerMutable->PatchListSize -= programToEncode.constSurfMutable->InlineDataSize + 1;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithConstantSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface programToEncode;
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
programToEncode.headerMutable->PatchListSize -= 1;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndTokensAreProperlyAssigned) {
|
||||
@@ -1061,7 +1070,7 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
ASSERT_EQ(1U, decodedProgram.programScopeTokens.allocateGlobalMemorySurface.size());
|
||||
EXPECT_EQ(programToEncode.programScopeTokens.allocateGlobalMemorySurface[0], decodedProgram.programScopeTokens.allocateGlobalMemorySurface[0]);
|
||||
@@ -1075,7 +1084,7 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
|
||||
programToEncode.recalcTokPtr();
|
||||
decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
|
||||
auto base = programToEncode.storage.data();
|
||||
@@ -1084,13 +1093,22 @@ TEST(ProgramDecoder, GivenValidProgramWithGlobalSurfacesThenDecodingSucceedsAndT
|
||||
EXPECT_TRUE(tokenOffsetMatched(base, secondGlobalSurfaceOff, decodedProgram.programScopeTokens.allocateGlobalMemorySurface[1]));
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithGlobalSurfaceWhenBlobSmallerThanNeededForPatchTokenThenDecodingFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
programToEncode.headerMutable->PatchListSize -= programToEncode.globalSurfMutable->InlineDataSize + 1;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithGlobalSurfaceWhenBlobSmallerThanNeededForInlineDataThenDecodingFails) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface programToEncode;
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
programToEncode.headerMutable->PatchListSize -= 1;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenValidProgramWithPatchtokensThenDecodingSucceedsAndTokensAreProperlyAssinged) {
|
||||
@@ -1106,7 +1124,7 @@ TEST(ProgramDecoder, GivenValidProgramWithPatchtokensThenDecodingSucceedsAndToke
|
||||
programToEncode.recalcTokPtr();
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
auto base = programToEncode.storage.data();
|
||||
|
||||
@@ -1128,7 +1146,7 @@ TEST(ProgramDecoder, GivenProgramWithUnkownPatchtokensThenDecodingSucceedsButTok
|
||||
programToEncode.constSurfMutable->Size += programToEncode.constSurfMutable->InlineDataSize;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
ASSERT_EQ(1U, decodedProgram.unhandledTokens.size());
|
||||
EXPECT_EQ(programToEncode.constSurfMutable, decodedProgram.unhandledTokens[0]);
|
||||
}
|
||||
@@ -1138,12 +1156,12 @@ TEST(ProgramDecoder, GivenValidProgramWithKernelThenDecodingSucceedsAndTokensAre
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
ASSERT_EQ(1U, decodedProgram.header->NumberOfKernels);
|
||||
ASSERT_EQ(1U, decodedProgram.kernels.size());
|
||||
auto decodedKernel = decodedProgram.kernels[0];
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel.unhandledTokens.empty());
|
||||
EXPECT_NE(nullptr, decodedKernel.tokens.allocateLocalSurface);
|
||||
}
|
||||
@@ -1155,18 +1173,18 @@ TEST(ProgramDecoder, GivenValidProgramWithTwoKernelsWhenThenDecodingSucceeds) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
|
||||
ASSERT_EQ(2U, decodedProgram.kernels.size());
|
||||
|
||||
auto decodedKernel0 = decodedProgram.kernels[0];
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel0.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel0.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel0.unhandledTokens.empty());
|
||||
EXPECT_NE(nullptr, decodedKernel0.tokens.allocateLocalSurface);
|
||||
|
||||
auto decodedKernel1 = decodedProgram.kernels[0];
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel1.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel1.decodeStatus);
|
||||
EXPECT_TRUE(decodedKernel1.unhandledTokens.empty());
|
||||
EXPECT_NE(nullptr, decodedKernel1.tokens.allocateLocalSurface);
|
||||
}
|
||||
@@ -1177,7 +1195,7 @@ TEST(ProgramDecoder, GivenPatchTokenWithZeroSizeThenDecodingFailsAndStops) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
}
|
||||
|
||||
TEST(ProgramDecoder, GivenProgramWithMultipleKernelsWhenFailsToDecodeKernelThenDecodingFailsAndStops) {
|
||||
@@ -1188,7 +1206,7 @@ TEST(ProgramDecoder, GivenProgramWithMultipleKernelsWhenFailsToDecodeKernelThenD
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram;
|
||||
bool decodeSuccess = NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToEncode.storage, decodedProgram);
|
||||
EXPECT_FALSE(decodeSuccess);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, decodedProgram.decodeStatus);
|
||||
EXPECT_TRUE(decodedProgram.unhandledTokens.empty());
|
||||
EXPECT_EQ(2U, decodedProgram.header->NumberOfKernels);
|
||||
EXPECT_EQ(1U, decodedProgram.kernels.size());
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
TEST(ProgramDumper, GivenEmptyProgramThenProperlyCreatesDumpStringWithWarnig) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens emptyProgram = {};
|
||||
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
|
||||
emptyProgram.decodeStatus = NEO::DecodeError::Undefined;
|
||||
std::string generated = NEO::PatchTokenBinary::asString(emptyProgram);
|
||||
const char *expected =
|
||||
R"===(Program of size : 0 in undefined status
|
||||
@@ -24,7 +24,7 @@ Kernels section size : 0
|
||||
)===";
|
||||
EXPECT_STREQ(expected, generated.c_str());
|
||||
|
||||
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
|
||||
emptyProgram.decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
generated = NEO::PatchTokenBinary::asString(emptyProgram);
|
||||
expected =
|
||||
R"===(Program of size : 0 with invalid binary
|
||||
@@ -34,7 +34,7 @@ Kernels section size : 0
|
||||
)===";
|
||||
EXPECT_STREQ(expected, generated.c_str());
|
||||
|
||||
emptyProgram.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
|
||||
emptyProgram.decodeStatus = NEO::DecodeError::Success;
|
||||
generated = NEO::PatchTokenBinary::asString(emptyProgram);
|
||||
expected =
|
||||
R"===(Program of size : 0 decoded successfully
|
||||
@@ -47,7 +47,7 @@ Kernels section size : 0
|
||||
|
||||
TEST(KernelDumper, GivenEmptyKernelThenProperlyCreatesDumpStringWithWarnig) {
|
||||
NEO::PatchTokenBinary::KernelFromPatchtokens emptyKernel = {};
|
||||
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
|
||||
emptyKernel.decodeStatus = NEO::DecodeError::Undefined;
|
||||
std::string generated = NEO::PatchTokenBinary::asString(emptyKernel);
|
||||
const char *expected =
|
||||
R"===(Kernel of size : 0 in undefined status
|
||||
@@ -56,7 +56,7 @@ Kernel-scope tokens section size : 0
|
||||
)===";
|
||||
EXPECT_STREQ(expected, generated.c_str());
|
||||
|
||||
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
|
||||
emptyKernel.decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
generated = NEO::PatchTokenBinary::asString(emptyKernel);
|
||||
expected =
|
||||
R"===(Kernel of size : 0 with invalid binary
|
||||
@@ -65,7 +65,7 @@ Kernel-scope tokens section size : 0
|
||||
)===";
|
||||
EXPECT_STREQ(expected, generated.c_str());
|
||||
|
||||
emptyKernel.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
|
||||
emptyKernel.decodeStatus = NEO::DecodeError::Success;
|
||||
generated = NEO::PatchTokenBinary::asString(emptyKernel);
|
||||
expected =
|
||||
R"===(Kernel of size : 0 decoded successfully
|
||||
@@ -2084,7 +2084,7 @@ TEST(PatchTokenDumper, GivenAnyTokenThenDumpingIsHandled) {
|
||||
kernelToken->Token = i;
|
||||
decodedKernel = {};
|
||||
NEO::PatchTokenBinary::decodeKernelFromPatchtokensBlob(kernelToDecode.blobs.kernelInfo, decodedKernel);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedKernel.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedKernel.decodeStatus);
|
||||
if (decodedKernel.unhandledTokens.empty()) {
|
||||
auto dump = NEO::PatchTokenBinary::asString(decodedKernel);
|
||||
EXPECT_EQ(std::string::npos, dump.find("struct SPatchItemHeader")) << "Update patchtokens_dumper.cpp with definition of new patchtoken : " << i;
|
||||
@@ -2095,7 +2095,7 @@ TEST(PatchTokenDumper, GivenAnyTokenThenDumpingIsHandled) {
|
||||
programToken->Token = i;
|
||||
decodedProgram = {};
|
||||
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(programToDecode.blobs.programInfo, decodedProgram);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::DecoderError::Success, decodedProgram.decodeStatus);
|
||||
EXPECT_EQ(NEO::DecodeError::Success, decodedProgram.decodeStatus);
|
||||
if (decodedProgram.unhandledTokens.empty()) {
|
||||
auto dump = NEO::PatchTokenBinary::asString(decodedProgram);
|
||||
EXPECT_EQ(std::string::npos, dump.find("struct SPatchItemHeader")) << "Update patchtokens_dumper.cpp with definition of new patchtoken : " << i;
|
||||
|
||||
@@ -83,7 +83,7 @@ struct ValidEmptyProgram : NEO::PatchTokenBinary::ProgramFromPatchtokens {
|
||||
headerTok.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
headerTok.Device = renderCoreFamily;
|
||||
headerTok.GPUPointerSizeInBytes = sizeof(uintptr_t);
|
||||
this->decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
|
||||
this->decodeStatus = NEO::DecodeError::Success;
|
||||
|
||||
storage.insert(storage.end(), reinterpret_cast<uint8_t *>(&headerTok), reinterpret_cast<uint8_t *>((&headerTok) + 1));
|
||||
recalcTokPtr();
|
||||
@@ -228,7 +228,7 @@ struct ValidEmptyKernel {
|
||||
execEnvTokInl.LargestCompiledSIMDSize = 32U;
|
||||
execEnvTokInl.CompiledSIMD32 = 1U;
|
||||
headerTokInl.PatchListSize = sizeof(execEnvTokInl);
|
||||
ret.decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
|
||||
ret.decodeStatus = NEO::DecodeError::Success;
|
||||
ret.name = "test_kernel";
|
||||
headerTokInl.KernelNameSize = static_cast<uint32_t>(ret.name.size());
|
||||
|
||||
@@ -253,7 +253,7 @@ struct ValidProgramWithKernel : ValidEmptyProgram {
|
||||
this->headerMutable->NumberOfKernels = 1;
|
||||
kernOffset = storage.size();
|
||||
this->kernels.push_back(ValidEmptyKernel::create(storage));
|
||||
this->kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Success;
|
||||
this->kernels[0].decodeStatus = NEO::DecodeError::Success;
|
||||
kernExecEnvOffset = ptrDiff(this->kernels[0].blobs.patchList.begin(), storage.data());
|
||||
recalcTokPtr();
|
||||
}
|
||||
|
||||
@@ -6,26 +6,17 @@
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/device_binary_format/patchtokens_validator.inl"
|
||||
#include "core/device_binary_format/patchtokens_validator.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
struct UknownTokenValidator {
|
||||
UknownTokenValidator(bool isSafeToSkip = true) : isSafeToSkip(isSafeToSkip) {
|
||||
}
|
||||
bool isSafeToSkipUnhandledToken(uint32_t token) const {
|
||||
return isSafeToSkip;
|
||||
}
|
||||
bool isSafeToSkip = true;
|
||||
};
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -34,16 +25,16 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidOrUnknownStatusThenValidationF
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
prog.decodeStatus = NEO::DecodeError::Undefined;
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
warning.clear();
|
||||
|
||||
prog.decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
prog.decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::DecodeError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("ProgramFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -52,7 +43,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleConstantSurfaceThenValida
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -63,7 +54,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleConstantSurfacesThenValidatio
|
||||
|
||||
iOpenCL::SPatchAllocateConstantMemorySurfaceProgramBinaryInfo constSurface2 = *prog.programScopeTokens.allocateConstantMemorySurface[0];
|
||||
prog.programScopeTokens.allocateConstantMemorySurface.push_back(&constSurface2);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled number of global constants surfaces > 1", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -72,7 +63,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithASingleGlobalSurfaceThenValidati
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -83,7 +74,7 @@ TEST(PatchtokensValidator, GivenProgramWithMultipleGlobalSurfacesThenValidationF
|
||||
|
||||
iOpenCL::SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo globSurface2 = *prog.programScopeTokens.allocateGlobalMemorySurface[0];
|
||||
prog.programScopeTokens.allocateGlobalMemorySurface.push_back(&globSurface2);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled number of global variables surfaces > 1", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -92,7 +83,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidConstantPointerThenValidati
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -102,7 +93,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferIndexThen
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->BufferIndex = 1;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -112,36 +103,36 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGpuPointerSizeThenValidationFa
|
||||
std::string error, warning;
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 0U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Invalid pointer size", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 1U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 2U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 3U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 4U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 5U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 6U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 7U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 8U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
|
||||
prog.headerMutable->GPUPointerSizeInBytes = 9U;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferIndexThenValidationFails) {
|
||||
@@ -149,7 +140,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerConstantBufferI
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->ConstantBufferIndex = 1;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -159,7 +150,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerBufferTypeThenV
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -169,7 +160,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidConstantPointerOffsetThenValid
|
||||
std::string error, warning;
|
||||
|
||||
prog.constantPointerMutable->ConstantPointerOffset = prog.constSurfMutable->InlineDataSize;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -179,7 +170,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutConstantSurfaceButWithConstantPoin
|
||||
std::string error, warning;
|
||||
|
||||
prog.programScopeTokens.allocateConstantMemorySurface.clear();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchConstantPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -188,7 +179,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithValidGlobalPointerThenValidation
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -197,7 +188,7 @@ TEST(PatchtokensValidator, GivenValidProgramWithMixedGlobalVarAndConstSurfacesAn
|
||||
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -207,13 +198,13 @@ TEST(PatchtokensValidator, GivenInvalidProgramWithMixedGlobalVarAndConstSurfaces
|
||||
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer progGlobalVar;
|
||||
progGlobalVar.globalPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_CONSTANT_BUFFER;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progGlobalVar, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progGlobalVar, error, warning));
|
||||
EXPECT_FALSE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer progConstVar;
|
||||
progConstVar.constantPointerMutable->BufferType = iOpenCL::PROGRAM_SCOPE_GLOBAL_BUFFER;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(progConstVar, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(progConstVar, error, warning));
|
||||
EXPECT_FALSE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -223,7 +214,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferIndexThenVa
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->BufferIndex = 1;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -233,7 +224,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerGlobalBufferIndex
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->GlobalBufferIndex = 1;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -243,7 +234,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerBufferTypeThenVal
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->BufferType = iOpenCL::NUM_PROGRAM_SCOPE_BUFFER_TYPE;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -253,7 +244,7 @@ TEST(PatchtokensValidator, GivenProgramWithInvalidGlobalPointerOffsetThenValidat
|
||||
std::string error, warning;
|
||||
|
||||
prog.globalPointerMutable->GlobalPointerOffset = prog.globalSurfMutable->InlineDataSize;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -263,7 +254,7 @@ TEST(PatchtokensValidator, GivenProgramWithoutGlobalSurfaceButWithGlobalPointerT
|
||||
std::string error, warning;
|
||||
|
||||
prog.programScopeTokens.allocateGlobalMemorySurface.clear();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("Unhandled SPatchGlobalPointerProgramBinaryInfo", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -275,7 +266,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.unhandledTokens.push_back(&unknownToken);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = false;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedError = "Unhandled required program-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -288,7 +282,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithUnknownPatchTokenWhenUknownToken
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.unhandledTokens.push_back(&unknownToken);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = true;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedWarning = "Unknown program-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
|
||||
@@ -299,28 +296,17 @@ TEST(PatchtokensValidator, GivenProgramWithUnsupportedPatchTokenVersionThenValid
|
||||
std::string error, warning;
|
||||
|
||||
prog.headerMutable->Version = std::numeric_limits<uint32_t>::max();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled Version of Patchtokens: expected: " + std::to_string(iOpenCL::CURRENT_ICBE_VERSION) + ", got: " + std::to_string(prog.header->Version);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithUnsupportedPlatformThenValidationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.headerMutable->Device = IGFX_MAX_CORE;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
auto expectedError = "Unsupported device binary, device GFXCORE_FAMILY : " + std::to_string(prog.header->Device);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_EQ(0U, warning.size());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelThenValidationSucceeds) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -329,16 +315,16 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidOrUnknownSt
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
|
||||
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::Undefined;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
prog.kernels[0].decodeStatus = NEO::DecodeError::Undefined;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
warning.clear();
|
||||
|
||||
prog.kernels[0].decodeStatus = NEO::PatchTokenBinary::DecoderError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
prog.kernels[0].decodeStatus = NEO::DecodeError::InvalidBinary;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens wasn't successfully decoded", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -348,7 +334,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelHasInvalidChecksumThe
|
||||
std::string error, warning;
|
||||
|
||||
prog.kernelHeaderMutable->CheckSum += 1;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens has invalid checksum", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -357,22 +343,12 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelUsingSlmThenValidationSucc
|
||||
PatchTokensTestData::ValidProgramWithKernelUsingSlm prog;
|
||||
std::string error, warning;
|
||||
|
||||
size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
|
||||
//size_t slmSizeAvailable = 1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenProgramWithKernelUsingSlmWhenKernelRequiresTooMuchSlmThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernelUsingSlm prog;
|
||||
std::string error, warning;
|
||||
|
||||
size_t slmSizeAvailable = -1 + prog.kernels[0].tokens.allocateLocalSurface->TotalInlineLocalMemorySize;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::NotEnoughSlm, NEO::PatchTokenBinary::validate(prog, slmSizeAvailable, UknownTokenValidator(), error, warning));
|
||||
EXPECT_STREQ("KernelFromPatchtokens requires too much SLM", error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchTokenWhenUknownTokenCantBeSkippedThenValidationFails) {
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
@@ -380,7 +356,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(false), error, warning));
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = false;
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedError = "Unhandled required kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_STREQ(expectedError.c_str(), error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -393,7 +372,10 @@ TEST(PatchtokensValidator, GivenValidProgramWithKernelContainingUnknownPatchToke
|
||||
iOpenCL::SPatchItemHeader unknownToken = {};
|
||||
unknownToken.Token = iOpenCL::NUM_PATCH_TOKENS + 1;
|
||||
prog.kernels[0].unhandledTokens.push_back(&unknownToken);
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
auto prevValue = NEO::PatchTokenBinary::allowUnhandledTokens;
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = true;
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
NEO::PatchTokenBinary::allowUnhandledTokens = prevValue;
|
||||
auto expectedWarning = "Unknown kernel-scope Patch Token : " + std::to_string(unknownToken.Token);
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_STREQ(expectedWarning.c_str(), warning.c_str());
|
||||
@@ -403,7 +385,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelArgsHasProperQualifie
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -412,7 +394,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelAndArgThenKernelArgInfoIsOption
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg prog;
|
||||
std::string error, warning;
|
||||
prog.kernels[0].tokens.kernelArgs[0].argInfo = nullptr;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
@@ -422,7 +404,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAddress
|
||||
std::string error, warning;
|
||||
prog.arg0InfoAddressQualifierMutable[2] = '\0';
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled address qualifier";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -433,7 +415,7 @@ TEST(PatchtokensValidator, GivenProgramWithKernelWhenKernelsArgHasUnknownAccessQ
|
||||
std::string error, warning;
|
||||
prog.arg0InfoAccessQualifierMutable[2] = '\0';
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Unhandled access qualifier";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -443,7 +425,7 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentIsMissingThenValid
|
||||
PatchTokensTestData::ValidProgramWithKernel prog;
|
||||
std::string error, warning;
|
||||
prog.kernels[0].tokens.executionEnvironment = nullptr;
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Missing execution environment";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -454,7 +436,7 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSize
|
||||
std::string error, warning;
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 0U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
auto expectedError = "Invalid LargestCompiledSIMDSize";
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
@@ -462,77 +444,81 @@ TEST(PatchtokensValidator, GivenKernelWhenExecutionEnvironmentHasInvalidSimdSize
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 1U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 2U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 3U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 4U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 5U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 6U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 7U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 8U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 9U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::InvalidBinary, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::UnhandledBinary, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_STREQ(expectedError, error.c_str());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 16U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
|
||||
error.clear();
|
||||
prog.kernelExecEnvMutable->LargestCompiledSIMDSize = 32U;
|
||||
prog.recalcTokPtr();
|
||||
EXPECT_EQ(NEO::PatchTokenBinary::ValidatorError::Success, NEO::PatchTokenBinary::validate(prog, 0U, UknownTokenValidator(true), error, warning));
|
||||
EXPECT_EQ(NEO::DecodeError::Success, NEO::PatchTokenBinary::validate(prog, error, warning));
|
||||
EXPECT_TRUE(error.empty());
|
||||
EXPECT_TRUE(warning.empty());
|
||||
}
|
||||
|
||||
TEST(PatchtokensValidator, GivenDefaultStateThenUnhandledPatchtokensAreAllowed) {
|
||||
EXPECT_TRUE(NEO::PatchTokenBinary::allowUnhandledTokens);
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenRequiresLocalMemoryWindowVAIsC
|
||||
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsSurfaceThenGlobalConstantsSectionIsPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurface programTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programTokens);
|
||||
EXPECT_EQ(programInfo.globalConstants.size, programTokens.programScopeTokens.allocateConstantMemorySurface[0]->InlineDataSize);
|
||||
EXPECT_EQ(programInfo.globalConstants.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateConstantMemorySurface[0]));
|
||||
EXPECT_TRUE(programInfo.kernelInfos.empty());
|
||||
@@ -56,7 +56,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstants
|
||||
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesSurfaceThenGlobalConstantsSectionIsPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurface programTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programTokens);
|
||||
EXPECT_EQ(programInfo.globalVariables.size, programTokens.programScopeTokens.allocateGlobalMemorySurface[0]->InlineDataSize);
|
||||
EXPECT_EQ(programInfo.globalVariables.initData, NEO::PatchTokenBinary::getInlineData(programTokens.programScopeTokens.allocateGlobalMemorySurface[0]));
|
||||
EXPECT_TRUE(programInfo.kernelInfos.empty());
|
||||
@@ -66,7 +66,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariables
|
||||
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstantsPointersThenLinkerInputContainsProperRelocations) {
|
||||
PatchTokensTestData::ValidProgramWithConstantSurfaceAndPointer programFromTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
EXPECT_TRUE(programInfo.kernelInfos.empty());
|
||||
ASSERT_NE(nullptr, programInfo.linkerInput);
|
||||
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
|
||||
@@ -81,7 +81,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalConstants
|
||||
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariablesPointersThenLinkerInputContainsProperRelocations) {
|
||||
PatchTokensTestData::ValidProgramWithGlobalSurfaceAndPointer programFromTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
EXPECT_TRUE(programInfo.kernelInfos.empty());
|
||||
ASSERT_NE(nullptr, programInfo.linkerInput);
|
||||
ASSERT_EQ(1U, programInfo.linkerInput->getDataRelocations().size());
|
||||
@@ -96,7 +96,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresGlobalVariables
|
||||
TEST(PopulateProgramInfoFromPatchtokensTests, WhenProgramRequiresMixedGlobalVarAndConstPointersThenLinkerInputContainsProperRelocations) {
|
||||
PatchTokensTestData::ValidProgramWithMixedGlobalVarAndConstSurfacesAndPointers programFromTokens;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
EXPECT_TRUE(programInfo.kernelInfos.empty());
|
||||
ASSERT_NE(nullptr, programInfo.linkerInput);
|
||||
|
||||
@@ -135,7 +135,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithSpecificPointerSiz
|
||||
{
|
||||
programFromTokens.headerMutable->GPUPointerSizeInBytes = 8;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
ASSERT_NE(nullptr, programInfo.linkerInput);
|
||||
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr64bit, programInfo.linkerInput->getTraits().pointerSize);
|
||||
}
|
||||
@@ -143,7 +143,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithSpecificPointerSiz
|
||||
{
|
||||
programFromTokens.headerMutable->GPUPointerSizeInBytes = 4;
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
ASSERT_NE(nullptr, programInfo.linkerInput);
|
||||
EXPECT_EQ(NEO::LinkerInput::Traits::Ptr32bit, programInfo.linkerInput->getTraits().pointerSize);
|
||||
}
|
||||
@@ -173,7 +173,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithProgramSymbolTable
|
||||
receivedNumEntries = numEntries;
|
||||
return true;
|
||||
};
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
|
||||
ASSERT_EQ(mockLinkerInput, programInfo.linkerInput.get());
|
||||
EXPECT_EQ(1U, mockLinkerInput->decodeGlobalVariablesSymbolTableMockConfig.timesCalled);
|
||||
@@ -186,7 +186,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsThenKernelI
|
||||
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
|
||||
programFromTokens.kernels.push_back(programFromTokens.kernels[0]);
|
||||
NEO::ProgramInfo programInfo = {};
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
ASSERT_EQ(3U, programInfo.kernelInfos.size());
|
||||
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[0]->gpuPointerSize);
|
||||
EXPECT_EQ(programFromTokens.header->GPUPointerSizeInBytes, programInfo.kernelInfos[1]->gpuPointerSize);
|
||||
@@ -232,7 +232,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelH
|
||||
receivedSegmentIds.push_back(instructionsSegmentId);
|
||||
return true;
|
||||
};
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
ASSERT_EQ(2U, mockLinkerInput->decodeExportedFunctionsSymbolTableMockConfig.timesCalled);
|
||||
ASSERT_EQ(2U, receivedData.size());
|
||||
|
||||
@@ -283,7 +283,7 @@ TEST(PopulateProgramInfoFromPatchtokensTests, GivenProgramWithKernelsWhenKernelH
|
||||
receivedSegmentIds.push_back(instructionsSegmentId);
|
||||
return true;
|
||||
};
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programFromTokens);
|
||||
ASSERT_EQ(2U, mockLinkerInput->decodeRelocationTableMockConfig.timesCalled);
|
||||
ASSERT_EQ(2U, receivedData.size());
|
||||
|
||||
|
||||
@@ -6,11 +6,12 @@
|
||||
*/
|
||||
|
||||
#include "core/program/program_info.h"
|
||||
#include "runtime/program/kernel_info.h"
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
TEST(ProgramInfoTests, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
|
||||
TEST(ProgramInfoTests, WhenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
EXPECT_EQ(nullptr, programInfo.linkerInput);
|
||||
programInfo.prepareLinkerInputStorage();
|
||||
@@ -19,3 +20,45 @@ TEST(ProgramInfoTests, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInp
|
||||
programInfo.prepareLinkerInputStorage();
|
||||
EXPECT_EQ(prevLinkerInput, programInfo.linkerInput.get());
|
||||
}
|
||||
|
||||
TEST(GetMaxInlineSlmNeeded, GivenProgramWithoutKernelsThenReturn0) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
EXPECT_EQ(0U, NEO::getMaxInlineSlmNeeded(programInfo));
|
||||
}
|
||||
|
||||
TEST(GetMaxInlineSlmNeeded, GivenProgramWithKernelsNotRequirignSlmThenReturn0) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
|
||||
EXPECT_EQ(0U, NEO::getMaxInlineSlmNeeded(programInfo));
|
||||
}
|
||||
|
||||
TEST(GetMaxInlineSlmNeeded, GivenProgramWithKernelsThenReturnMaxOfInlineSlmNeededByKernels) {
|
||||
iOpenCL::SPatchAllocateLocalSurface slmTokens[3] = {};
|
||||
slmTokens[0].TotalInlineLocalMemorySize = 16;
|
||||
slmTokens[1].TotalInlineLocalMemorySize = 64;
|
||||
slmTokens[2].TotalInlineLocalMemorySize = 32;
|
||||
NEO::ProgramInfo programInfo;
|
||||
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
|
||||
programInfo.kernelInfos[0]->patchInfo.localsurface = &slmTokens[0];
|
||||
programInfo.kernelInfos[1]->patchInfo.localsurface = &slmTokens[1];
|
||||
programInfo.kernelInfos[2]->patchInfo.localsurface = &slmTokens[2];
|
||||
EXPECT_EQ(64U, NEO::getMaxInlineSlmNeeded(programInfo));
|
||||
}
|
||||
|
||||
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithoutKernelsThenReturnFalse) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(programInfo));
|
||||
}
|
||||
|
||||
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithKernelsNotLocalMemoryWindowVAThenReturnFalse) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
|
||||
EXPECT_FALSE(NEO::requiresLocalMemoryWindowVA(programInfo));
|
||||
}
|
||||
|
||||
TEST(RequiresLocalMemoryWindowVA, GivenProgramWithKernelsWhenSomeOfKernelRequireLocalMemoryWidnowVAThenReturnTrue) {
|
||||
NEO::ProgramInfo programInfo;
|
||||
programInfo.kernelInfos = {new NEO::KernelInfo(), new NEO::KernelInfo(), new NEO::KernelInfo()};
|
||||
programInfo.kernelInfos[1]->workloadInfo.localMemoryStatelessWindowStartAddressOffset = 0U;
|
||||
EXPECT_TRUE(NEO::requiresLocalMemoryWindowVA(programInfo));
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -73,3 +73,28 @@ TEST(ConstStringRef, WhenComparingAgainstContainersThenUsesLexicographicOrdering
|
||||
EXPECT_TRUE(strTex != constStrText);
|
||||
EXPECT_TRUE(constStrText != strTex);
|
||||
}
|
||||
|
||||
TEST(ConstStringRef, WhenStrIsCalledThenEmitsProperString) {
|
||||
static constexpr ConstStringRef constStrText("Text");
|
||||
std::string str = constStrText.str();
|
||||
EXPECT_EQ(4U, str.size());
|
||||
EXPECT_STREQ("Text", str.c_str());
|
||||
}
|
||||
|
||||
TEST(ConstStringRef, WhenDefaultInitializedThenEmpty) {
|
||||
ConstStringRef str;
|
||||
EXPECT_TRUE(str.empty());
|
||||
}
|
||||
|
||||
TEST(ConstStringRef, WhenCopyConstructedThenIdenticalAsOrigin) {
|
||||
static constexpr ConstStringRef a("Text");
|
||||
static constexpr ConstStringRef b(a);
|
||||
EXPECT_EQ(a, b);
|
||||
}
|
||||
|
||||
TEST(ConstStringRef, WhenCopyAsignedThenIdenticalAsOrigin) {
|
||||
static constexpr ConstStringRef a("Text");
|
||||
ConstStringRef b("OtherText");
|
||||
b = a;
|
||||
EXPECT_EQ(a, b);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -1598,6 +1598,16 @@ TEST(ArrayRef, WrapContainers) {
|
||||
ASSERT_EQ(35, sum(ar3));
|
||||
}
|
||||
|
||||
TEST(ArrayRef, GivenEmptyContainerThenArrayRefIsEmpty) {
|
||||
StackVec<int, 5> stackVec;
|
||||
ArrayRef<int> arrayRef(stackVec);
|
||||
EXPECT_TRUE(arrayRef.empty());
|
||||
|
||||
const StackVec<int, 5> &constStackVec = stackVec;
|
||||
ArrayRef<const int> constArrayRef(constStackVec);
|
||||
EXPECT_TRUE(constArrayRef.empty());
|
||||
}
|
||||
|
||||
TEST(ArrayRef, ImplicitCoversionToArrayrefOfConst) {
|
||||
int carray[] = {5, 6, 7, 8, 9};
|
||||
ArrayRef<int> arrayRef(carray);
|
||||
@@ -1698,3 +1708,25 @@ TEST(Range, GivenRangeThenValidStandardIteratorsAreAvailable) {
|
||||
EXPECT_EQ(&*vec.begin(), &*rangeFromVec.begin());
|
||||
EXPECT_EQ(&*vec.rbegin(), &*rangeFromVec.rbegin());
|
||||
}
|
||||
|
||||
TEST(ArrayRef, WhenFromAnyIsCalledThenPointerIsReinterpretedAndSizeIsAdjusted) {
|
||||
uint32_t x[2] = {};
|
||||
auto arrayRefU8 = ArrayRef<const uint8_t>::fromAny(x, 2);
|
||||
EXPECT_EQ(8U, arrayRefU8.size());
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(x), arrayRefU8.begin());
|
||||
}
|
||||
|
||||
TEST(ArrayRef, WhenToArrayRefIsCalledThenPointerIsReinterpretedAndSizeIsAdjusted) {
|
||||
uint32_t x[2] = {};
|
||||
auto arrayRefU32 = ArrayRef<const uint32_t>::fromAny(x, 2);
|
||||
auto arrayRefU8 = arrayRefU32.toArrayRef<const uint8_t>();
|
||||
EXPECT_EQ(8U, arrayRefU8.size());
|
||||
EXPECT_EQ(reinterpret_cast<uint8_t *>(x), arrayRefU8.begin());
|
||||
}
|
||||
|
||||
TEST(ArrayRef, WhenClearedThenEmpty) {
|
||||
uint32_t x[2] = {};
|
||||
auto arrayRefU32 = ArrayRef<const uint32_t>::fromAny(x, 2);
|
||||
arrayRefU32.clear();
|
||||
EXPECT_TRUE(arrayRefU32.empty());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
* Copyright (C) 2018-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -38,6 +38,11 @@ class ArrayRef {
|
||||
: begIt((ctr.size() > 0) ? &*ctr.begin() : nullptr), endIt((ctr.size() > 0) ? (&*(ctr.end() - 1) + 1) : nullptr) {
|
||||
}
|
||||
|
||||
template <typename SequentialContainerType>
|
||||
ArrayRef(const SequentialContainerType &ctr)
|
||||
: begIt((ctr.size() > 0) ? &*ctr.begin() : nullptr), endIt((ctr.size() > 0) ? (&*(ctr.end() - 1) + 1) : nullptr) {
|
||||
}
|
||||
|
||||
template <size_t Size>
|
||||
ArrayRef(DataType (&array)[Size])
|
||||
: begIt(&array[0]), endIt(&array[Size]) {
|
||||
@@ -55,6 +60,10 @@ class ArrayRef {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
endIt = begIt;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return endIt - begIt;
|
||||
}
|
||||
@@ -96,6 +105,18 @@ class ArrayRef {
|
||||
return ArrayRef<const DataType>(begIt, endIt);
|
||||
}
|
||||
|
||||
template <typename AnyT>
|
||||
static ArrayRef<DataType> fromAny(AnyT *any, size_t anyCount) {
|
||||
static_assert((sizeof(AnyT) == sizeof(DataType)) || ((sizeof(AnyT) % sizeof(DataType)) == 0), "Unhandled type conversion");
|
||||
return ArrayRef<DataType>(reinterpret_cast<iterator>(any), (anyCount * sizeof(AnyT)) / sizeof(DataType));
|
||||
}
|
||||
|
||||
template <typename AnyT>
|
||||
ArrayRef<AnyT> toArrayRef() {
|
||||
static_assert((sizeof(AnyT) == sizeof(DataType)) || ((sizeof(DataType) % sizeof(AnyT)) == 0), "Unhandled type conversion");
|
||||
return ArrayRef<AnyT>(reinterpret_cast<typename ArrayRef<AnyT>::iterator>(begIt), (this->size() * sizeof(DataType)) / sizeof(AnyT));
|
||||
}
|
||||
|
||||
private:
|
||||
DataType *begIt = nullptr;
|
||||
DataType *endIt = nullptr;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -22,6 +22,18 @@ constexpr size_t constLength(const char *string) {
|
||||
|
||||
class ConstStringRef {
|
||||
public:
|
||||
constexpr ConstStringRef() {
|
||||
}
|
||||
|
||||
constexpr ConstStringRef(const ConstStringRef &rhs) : ptr(rhs.ptr), len(rhs.len) {
|
||||
}
|
||||
|
||||
ConstStringRef &operator=(const ConstStringRef &rhs) {
|
||||
this->ptr = rhs.ptr;
|
||||
this->len = rhs.len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <size_t Length>
|
||||
constexpr ConstStringRef(const char (&array)[Length]) noexcept
|
||||
: ptr(array), len(((Length > 0) && (array[Length - 1] == '\0')) ? (Length - 1) : Length) {
|
||||
@@ -43,6 +55,10 @@ class ConstStringRef {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
std::string str() const {
|
||||
return std::string(ptr, len);
|
||||
}
|
||||
|
||||
constexpr size_t size() const noexcept {
|
||||
return len;
|
||||
}
|
||||
@@ -64,8 +80,8 @@ class ConstStringRef {
|
||||
}
|
||||
|
||||
protected:
|
||||
const char *const ptr;
|
||||
const size_t len;
|
||||
const char *ptr = nullptr;
|
||||
size_t len = 0U;
|
||||
};
|
||||
|
||||
constexpr bool equals(const ConstStringRef &lhs, const ConstStringRef &rhs) {
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
project(ocloc)
|
||||
|
||||
set(CLOC_SRCS_LIB
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/elf.h
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/elf_decoder.h
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/elf_decoder.cpp
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/elf_encoder.h
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/elf_encoder.cpp
|
||||
${NEO_SOURCE_DIR}/core/device_binary_format/elf/ocl_elf.h
|
||||
${NEO_SOURCE_DIR}/core/helpers/abort.cpp
|
||||
${NEO_SOURCE_DIR}/core/helpers/debug_helpers.cpp
|
||||
${NEO_SOURCE_DIR}/core/helpers/file_io.cpp
|
||||
@@ -126,8 +132,6 @@ if(UNIX)
|
||||
target_link_libraries(ocloc dl pthread)
|
||||
endif()
|
||||
|
||||
target_link_libraries(ocloc elflib)
|
||||
|
||||
set_target_properties(ocloc PROPERTIES FOLDER "offline_compiler")
|
||||
|
||||
add_custom_target(copy_compiler_files DEPENDS ${NEO__IGC_TARGETS})
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
#include "binary_decoder.h"
|
||||
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/ptr_math.h"
|
||||
#include "offline_compiler/offline_compiler.h"
|
||||
@@ -31,9 +32,9 @@ void BinaryDecoder::setMessagePrinter(const MessagePrinter &messagePrinter) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T readUnaligned(void *ptr) {
|
||||
T readUnaligned(const void *ptr) {
|
||||
T retVal = 0;
|
||||
uint8_t *tmp1 = reinterpret_cast<uint8_t *>(ptr);
|
||||
const uint8_t *tmp1 = reinterpret_cast<const uint8_t *>(ptr);
|
||||
uint8_t *tmp2 = reinterpret_cast<uint8_t *>(&retVal);
|
||||
for (uint8_t i = 0; i < sizeof(T); ++i) {
|
||||
*(tmp2++) = *(tmp1++);
|
||||
@@ -52,7 +53,7 @@ int BinaryDecoder::decode() {
|
||||
return processBinary(devBinPtr, ptmFile);
|
||||
}
|
||||
|
||||
void BinaryDecoder::dumpField(void *&binaryPtr, const PTField &field, std::ostream &ptmFile) {
|
||||
void BinaryDecoder::dumpField(const void *&binaryPtr, const PTField &field, std::ostream &ptmFile) {
|
||||
ptmFile << '\t' << static_cast<int>(field.size) << ' ';
|
||||
switch (field.size) {
|
||||
case 1: {
|
||||
@@ -82,29 +83,33 @@ void BinaryDecoder::dumpField(void *&binaryPtr, const PTField &field, std::ostre
|
||||
binaryPtr = ptrOffset(binaryPtr, field.size);
|
||||
}
|
||||
|
||||
void *BinaryDecoder::getDevBinary() {
|
||||
const void *BinaryDecoder::getDevBinary() {
|
||||
binary = readBinaryFile(binaryFile);
|
||||
char *data = nullptr;
|
||||
CLElfLib::CElfReader elfReader(binary);
|
||||
for (const auto §ionHeader : elfReader.getSectionHeaders()) { //Finding right section
|
||||
switch (sectionHeader.Type) {
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY: {
|
||||
const void *data = nullptr;
|
||||
std::string decoderErrors;
|
||||
std::string decoderWarnings;
|
||||
auto input = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.data()), binary.size());
|
||||
auto elf = NEO::Elf::decodeElf<NEO::Elf::EI_CLASS_64>(input, decoderErrors, decoderWarnings);
|
||||
for (const auto §ionHeader : elf.sectionHeaders) { //Finding right section
|
||||
auto sectionData = ArrayRef<const char>(reinterpret_cast<const char *>(sectionHeader.data.begin()), sectionHeader.data.size());
|
||||
switch (sectionHeader.header->type) {
|
||||
case NEO::Elf::SHT_OPENCL_LLVM_BINARY: {
|
||||
std::ofstream ofs(pathToDump + "llvm.bin", std::ios::binary);
|
||||
ofs.write(elfReader.getSectionData(sectionHeader.DataOffset), sectionHeader.DataSize);
|
||||
ofs.write(sectionData.begin(), sectionData.size());
|
||||
break;
|
||||
}
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV: {
|
||||
case NEO::Elf::SHT_OPENCL_SPIRV: {
|
||||
std::ofstream ofs(pathToDump + "spirv.bin", std::ios::binary);
|
||||
ofs.write(elfReader.getSectionData(sectionHeader.DataOffset), sectionHeader.DataSize);
|
||||
ofs.write(sectionData.begin(), sectionData.size());
|
||||
break;
|
||||
}
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS: {
|
||||
case NEO::Elf::SHT_OPENCL_OPTIONS: {
|
||||
std::ofstream ofs(pathToDump + "build.bin", std::ios::binary);
|
||||
ofs.write(elfReader.getSectionData(sectionHeader.DataOffset), sectionHeader.DataSize);
|
||||
ofs.write(sectionData.begin(), sectionData.size());
|
||||
break;
|
||||
}
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY: {
|
||||
data = elfReader.getSectionData(sectionHeader.DataOffset);
|
||||
case NEO::Elf::SHT_OPENCL_DEV_BINARY: {
|
||||
data = sectionData.begin();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -323,7 +328,7 @@ Examples:
|
||||
NEO::getDevicesTypes().c_str());
|
||||
}
|
||||
|
||||
int BinaryDecoder::processBinary(void *&ptr, std::ostream &ptmFile) {
|
||||
int BinaryDecoder::processBinary(const void *&ptr, std::ostream &ptmFile) {
|
||||
ptmFile << "ProgramBinaryHeader:\n";
|
||||
uint32_t numberOfKernels = 0, patchListSize = 0, device = 0;
|
||||
for (const auto &v : programHeader.fields) {
|
||||
@@ -351,7 +356,7 @@ int BinaryDecoder::processBinary(void *&ptr, std::ostream &ptmFile) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BinaryDecoder::processKernel(void *&ptr, std::ostream &ptmFile) {
|
||||
void BinaryDecoder::processKernel(const void *&ptr, std::ostream &ptmFile) {
|
||||
uint32_t KernelNameSize = 0, KernelPatchListSize = 0, KernelHeapSize = 0, KernelHeapUnpaddedSize = 0,
|
||||
GeneralStateHeapSize = 0, DynamicStateHeapSize = 0, SurfaceStateHeapSize = 0;
|
||||
ptmFile << "KernelBinaryHeader:\n";
|
||||
@@ -419,7 +424,7 @@ void BinaryDecoder::processKernel(void *&ptr, std::ostream &ptmFile) {
|
||||
readPatchTokens(ptr, KernelPatchListSize, ptmFile);
|
||||
}
|
||||
|
||||
void BinaryDecoder::readPatchTokens(void *&patchListPtr, uint32_t patchListSize, std::ostream &ptmFile) {
|
||||
void BinaryDecoder::readPatchTokens(const void *&patchListPtr, uint32_t patchListSize, std::ostream &ptmFile) {
|
||||
auto endPatchListPtr = ptrOffset(patchListPtr, patchListSize);
|
||||
while (patchListPtr != endPatchListPtr) {
|
||||
auto patchTokenPtr = patchListPtr;
|
||||
@@ -456,7 +461,7 @@ void BinaryDecoder::readPatchTokens(void *&patchListPtr, uint32_t patchListSize,
|
||||
|
||||
if (patchListPtr > patchTokenPtr) {
|
||||
ptmFile << "\tHex";
|
||||
uint8_t *byte = reinterpret_cast<uint8_t *>(patchTokenPtr);
|
||||
const uint8_t *byte = reinterpret_cast<const uint8_t *>(patchTokenPtr);
|
||||
while (ptrDiff(patchListPtr, patchTokenPtr) != 0) {
|
||||
ptmFile << ' ' << std::hex << +*(byte++);
|
||||
patchTokenPtr = ptrOffset(patchTokenPtr, sizeof(uint8_t));
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "core/elf/types.h"
|
||||
|
||||
#include "helper.h"
|
||||
#include "iga_wrapper.h"
|
||||
#include "offline_compiler/decoder/helper.h"
|
||||
#include "offline_compiler/decoder/iga_wrapper.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -46,20 +44,20 @@ class BinaryDecoder {
|
||||
protected:
|
||||
bool ignoreIsaPadding = false;
|
||||
BinaryHeader programHeader, kernelHeader;
|
||||
CLElfLib::ElfBinaryStorage binary;
|
||||
std::vector<char> binary;
|
||||
std::unique_ptr<IgaWrapper> iga;
|
||||
PTMap patchTokens;
|
||||
std::string binaryFile, pathToPatch, pathToDump;
|
||||
MessagePrinter messagePrinter;
|
||||
|
||||
void dumpField(void *&binaryPtr, const PTField &field, std::ostream &ptmFile);
|
||||
void dumpField(const void *&binaryPtr, const PTField &field, std::ostream &ptmFile);
|
||||
uint8_t getSize(const std::string &typeStr);
|
||||
void *getDevBinary();
|
||||
const void *getDevBinary();
|
||||
void parseTokens();
|
||||
void printHelp();
|
||||
int processBinary(void *&ptr, std::ostream &ptmFile);
|
||||
void processKernel(void *&ptr, std::ostream &ptmFile);
|
||||
void readPatchTokens(void *&patchListPtr, uint32_t patchListSize, std::ostream &ptmFile);
|
||||
int processBinary(const void *&ptr, std::ostream &ptmFile);
|
||||
void processKernel(const void *&ptr, std::ostream &ptmFile);
|
||||
void readPatchTokens(const void *&patchListPtr, uint32_t patchListSize, std::ostream &ptmFile);
|
||||
uint32_t readStructFields(const std::vector<std::string> &patchList,
|
||||
const size_t &structPos, std::vector<PTField> &fields);
|
||||
};
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
|
||||
#include "binary_encoder.h"
|
||||
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/hash.h"
|
||||
@@ -74,17 +75,14 @@ bool BinaryEncoder::copyBinaryToBinary(const std::string &srcFileName, std::ostr
|
||||
}
|
||||
|
||||
int BinaryEncoder::createElf() {
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> ElfEncoder;
|
||||
ElfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
|
||||
//Build Options
|
||||
if (fileExists(pathToDump + "build.bin")) {
|
||||
auto binary = readBinaryFile(pathToDump + "build.bin");
|
||||
std::string data(binary.begin(), binary.end());
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
"BuildOptions",
|
||||
data,
|
||||
static_cast<uint32_t>(data.size())));
|
||||
ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, "BuildOptions",
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.data()), binary.size()));
|
||||
} else {
|
||||
messagePrinter.printf("Warning! Missing build section.\n");
|
||||
}
|
||||
@@ -92,20 +90,13 @@ int BinaryEncoder::createElf() {
|
||||
//LLVM or SPIRV
|
||||
if (fileExists(pathToDump + "llvm.bin")) {
|
||||
auto binary = readBinaryFile(pathToDump + "llvm.bin");
|
||||
std::string data(binary.begin(), binary.end());
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
"Intel(R) OpenCL LLVM Object",
|
||||
data,
|
||||
static_cast<uint32_t>(data.size())));
|
||||
ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, "Intel(R) OpenCL LLVM Object",
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.data()), binary.size()));
|
||||
} else if (fileExists(pathToDump + "spirv.bin")) {
|
||||
auto binary = readBinaryFile(pathToDump + "spirv.bin");
|
||||
std::string data(binary.begin(), binary.end());
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
"SPIRV Object",
|
||||
data,
|
||||
static_cast<uint32_t>(data.size())));
|
||||
ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, "SPIRV Object",
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.data()), binary.size()));
|
||||
} else {
|
||||
messagePrinter.printf("Warning! Missing llvm/spirv section.\n");
|
||||
}
|
||||
@@ -113,20 +104,15 @@ int BinaryEncoder::createElf() {
|
||||
//Device Binary
|
||||
if (fileExists(pathToDump + "device_binary.bin")) {
|
||||
auto binary = readBinaryFile(pathToDump + "device_binary.bin");
|
||||
std::string data(binary.begin(), binary.end());
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
"Intel(R) OpenCL Device Binary",
|
||||
data,
|
||||
static_cast<uint32_t>(data.size())));
|
||||
ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, "Intel(R) OpenCL Device Binary",
|
||||
ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(binary.data()), binary.size()));
|
||||
} else {
|
||||
messagePrinter.printf("Missing device_binary.bin\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Resolve Elf Binary
|
||||
std::vector<char> elfBinary;
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
auto elfBinary = ElfEncoder.encode();
|
||||
|
||||
std::ofstream elfFile(elfName, std::ios::binary);
|
||||
if (!elfFile.good()) {
|
||||
@@ -134,7 +120,7 @@ int BinaryEncoder::createElf() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
elfFile.write(elfBinary.data(), elfBinary.size());
|
||||
elfFile.write(reinterpret_cast<const char *>(elfBinary.data()), elfBinary.size());
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
#include "offline_compiler.h"
|
||||
|
||||
#include "core/debug_settings/debug_settings_manager.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/hw_info.h"
|
||||
@@ -726,31 +728,45 @@ void OfflineCompiler::storeBinary(
|
||||
}
|
||||
|
||||
bool OfflineCompiler::generateElfBinary() {
|
||||
bool retVal = true;
|
||||
|
||||
if (!genBinary || !genBinarySize) {
|
||||
retVal = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (retVal) {
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
SingleDeviceBinary binary = {};
|
||||
binary.buildOptions = this->options;
|
||||
binary.intermediateRepresentation = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->irBinary), this->irBinarySize);
|
||||
binary.deviceBinary = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->genBinary), this->genBinarySize);
|
||||
binary.debugData = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->debugDataBinary), this->debugDataBinarySize);
|
||||
std::string packErrors;
|
||||
std::string packWarnings;
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast<uint32_t>(strlen(options.c_str()) + 1u)));
|
||||
std::string irBinaryTemp = irBinary ? std::string(irBinary, irBinarySize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL LLVM Object", std::move(irBinaryTemp), static_cast<uint32_t>(irBinarySize)));
|
||||
|
||||
// Add the device binary if it exists
|
||||
if (genBinary) {
|
||||
std::string genBinaryTemp = genBinary ? std::string(genBinary, genBinarySize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
|
||||
using namespace 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()));
|
||||
}
|
||||
|
||||
elfBinarySize = elfWriter.getTotalBinarySize();
|
||||
elfBinary.resize(elfBinarySize);
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
if (binary.intermediateRepresentation.empty() == false) {
|
||||
if (isSpirV) {
|
||||
ElfEncoder.appendSection(SHT_OPENCL_SPIRV, SectionNamesOpenCl::spirvObject, binary.intermediateRepresentation);
|
||||
} else {
|
||||
ElfEncoder.appendSection(SHT_OPENCL_LLVM_BINARY, SectionNamesOpenCl::llvmObject, binary.intermediateRepresentation);
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
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);
|
||||
}
|
||||
|
||||
this->elfBinary = ElfEncoder.encode();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OfflineCompiler::writeOutAllFiles() {
|
||||
@@ -821,7 +837,7 @@ void OfflineCompiler::writeOutAllFiles() {
|
||||
writeDataToFile(
|
||||
elfOutputFile.c_str(),
|
||||
elfBinary.data(),
|
||||
elfBinarySize);
|
||||
elfBinary.size());
|
||||
}
|
||||
|
||||
if (debugDataBinary) {
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "core/elf/writer.h"
|
||||
|
||||
#include "cif/common/cif_main.h"
|
||||
#include "ocl_igc_interface/fcl_ocl_device_ctx.h"
|
||||
#include "ocl_igc_interface/igc_ocl_device_ctx.h"
|
||||
@@ -98,8 +96,7 @@ class OfflineCompiler {
|
||||
bool outputNoSuffix = false;
|
||||
bool forceStatelessToStatefulOptimization = false;
|
||||
|
||||
CLElfLib::ElfBinaryStorage elfBinary;
|
||||
size_t elfBinarySize = 0;
|
||||
std::vector<uint8_t> elfBinary;
|
||||
char *genBinary = nullptr;
|
||||
size_t genBinarySize = 0;
|
||||
char *irBinary = nullptr;
|
||||
|
||||
@@ -48,7 +48,6 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
target_link_libraries(${NEO_STATIC_LIB_NAME} elflib)
|
||||
if(DEFINED AUB_STREAM_DIR)
|
||||
target_link_libraries(${NEO_STATIC_LIB_NAME} ${AUB_STREAM_PROJECT_NAME})
|
||||
endif()
|
||||
|
||||
@@ -30,7 +30,6 @@ set(RUNTIME_SRCS_DLL_BASE
|
||||
${NEO_SOURCE_DIR}/runtime/api/api.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/compiler_interface/default_cache_config.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/helpers/built_ins_helper.cpp
|
||||
${NEO_SOURCE_DIR}/runtime/program/evaluate_unhandled_token.cpp
|
||||
|
||||
${GTPIN_INIT_FILE}
|
||||
${HW_SRC_LINK}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (C) 2018-2019 Intel Corporation
|
||||
# Copyright (C) 2018-2020 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
@@ -25,9 +25,8 @@ set(RUNTIME_SRCS_PROGRAM
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/patch_info.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_handler.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/printf_handler.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_elf_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_gen_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_spir_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_device_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/process_intermediate_binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/program.h
|
||||
)
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "core/utilities/time_measure_wrapper.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
@@ -125,8 +126,7 @@ cl_int Program::build(
|
||||
this->irBinarySize = compilerOuput.intermediateRepresentation.size;
|
||||
this->isSpirV = compilerOuput.intermediateCodeType == IGC::CodeType::spirV;
|
||||
}
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->replaceDeviceBinary(std::move(compilerOuput.deviceBinary.mem), compilerOuput.deviceBinary.size);
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,10 @@
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
#include "runtime/helpers/validators.h"
|
||||
@@ -30,9 +33,6 @@ cl_int Program::compile(
|
||||
void(CL_CALLBACK *funcNotify)(cl_program program, void *userData),
|
||||
void *userData) {
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
cl_program program;
|
||||
Program *pHeaderProgObj;
|
||||
size_t compileDataSize;
|
||||
|
||||
do {
|
||||
if (((deviceList == nullptr) && (numDevices != 0)) ||
|
||||
@@ -89,43 +89,35 @@ cl_int Program::compile(
|
||||
}
|
||||
|
||||
// create ELF writer to process all sources to be compiled
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_SOURCE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
CLElfLib::SSectionNode sectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "CLMain", sourceCode, static_cast<uint32_t>(sourceCode.size() + 1u));
|
||||
|
||||
// add main program's source
|
||||
elfWriter.addSection(sectionNode);
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, true, 1U);
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_SOURCE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SOURCE, "CLMain", sourceCode);
|
||||
|
||||
for (cl_uint i = 0; i < numInputHeaders; i++) {
|
||||
program = inputHeaders[i];
|
||||
auto program = inputHeaders[i];
|
||||
if (program == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
pHeaderProgObj = castToObject<Program>(program);
|
||||
auto pHeaderProgObj = castToObject<Program>(program);
|
||||
if (pHeaderProgObj == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
sectionNode.name = headerIncludeNames[i];
|
||||
sectionNode.type = CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_HEADER;
|
||||
sectionNode.flag = CLElfLib::E_SH_FLAG::SH_FLAG_NONE;
|
||||
// collect required data from the header
|
||||
retVal = pHeaderProgObj->getSource(sectionNode.data);
|
||||
|
||||
std::string includeHeaderSource;
|
||||
retVal = pHeaderProgObj->getSource(includeHeaderSource);
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
sectionNode.dataSize = static_cast<uint32_t>(sectionNode.data.size());
|
||||
elfWriter.addSection(sectionNode);
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_HEADER, ConstStringRef(headerIncludeNames[i], strlen(headerIncludeNames[i])), includeHeaderSource);
|
||||
}
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
compileDataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage compileData(compileDataSize);
|
||||
elfWriter.resolveBinary(compileData);
|
||||
std::vector<uint8_t> compileData = elfEncoder.encode();
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (!pCompilerInterface) {
|
||||
@@ -148,7 +140,7 @@ cl_int Program::compile(
|
||||
}
|
||||
}
|
||||
|
||||
inputArgs.src = ArrayRef<const char>(compileData.data(), compileDataSize);
|
||||
inputArgs.src = ArrayRef<const char>(reinterpret_cast<const char *>(compileData.data()), compileData.size());
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options.c_str(), options.length());
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions.c_str(), internalOptions.length());
|
||||
|
||||
|
||||
@@ -144,11 +144,9 @@ T *Program::createFromGenBinary(
|
||||
if (CL_SUCCESS == retVal) {
|
||||
program = new T(executionEnvironment, context, isBuiltIn);
|
||||
program->numDevices = 1;
|
||||
program->genBinary = makeCopy(binary, size);
|
||||
program->genBinarySize = size;
|
||||
program->replaceDeviceBinary(makeCopy(binary, size), size);
|
||||
program->isCreatedFromBinary = true;
|
||||
program->programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
program->isProgramBinaryResolved = true;
|
||||
program->buildStatus = CL_BUILD_SUCCESS;
|
||||
program->createdFrom = CreatedFrom::BINARY;
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Program::isSafeToSkipUnhandledToken(unsigned int token) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -36,10 +36,10 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARIES:
|
||||
resolveProgramBinary();
|
||||
pSrc = elfBinary.data();
|
||||
packDeviceBinary();
|
||||
pSrc = packedDeviceBinary.get();
|
||||
retSize = sizeof(void **);
|
||||
srcSize = elfBinarySize;
|
||||
srcSize = packedDeviceBinarySize;
|
||||
if (paramValue != nullptr) {
|
||||
if (paramValueSize < retSize) {
|
||||
retVal = CL_INVALID_VALUE;
|
||||
@@ -51,8 +51,8 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_SIZES:
|
||||
resolveProgramBinary();
|
||||
pSrc = &elfBinarySize;
|
||||
packDeviceBinary();
|
||||
pSrc = &packedDeviceBinarySize;
|
||||
retSize = srcSize = sizeof(size_t *);
|
||||
break;
|
||||
|
||||
@@ -116,13 +116,11 @@ cl_int Program::getInfo(cl_program_info paramName, size_t paramValueSize,
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_DEBUG_INFO_SIZES_INTEL:
|
||||
resolveProgramBinary();
|
||||
retSize = srcSize = sizeof(debugDataSize);
|
||||
pSrc = &debugDataSize;
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_DEBUG_INFO_INTEL:
|
||||
resolveProgramBinary();
|
||||
pSrc = debugData.get();
|
||||
retSize = numDevices * sizeof(void **);
|
||||
srcSize = debugDataSize;
|
||||
|
||||
@@ -425,6 +425,37 @@ bool KernelInfo::createKernelAllocation(uint32_t rootDeviceIndex, MemoryManager
|
||||
return memoryManager->copyMemoryToAllocation(kernelAllocation, heapInfo.pKernelHeap, kernelIsaSize);
|
||||
}
|
||||
|
||||
void KernelInfo::apply(const DeviceInfoKernelPayloadConstants &constants) {
|
||||
if (nullptr == this->crossThreadData) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t privateMemoryStatelessSizeOffset = this->workloadInfo.privateMemoryStatelessSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowSizeOffset = this->workloadInfo.localMemoryStatelessWindowSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowStartAddressOffset = this->workloadInfo.localMemoryStatelessWindowStartAddressOffset;
|
||||
|
||||
if (localMemoryStatelessWindowStartAddressOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uintptr_t *)&(this->crossThreadData[localMemoryStatelessWindowStartAddressOffset]) = reinterpret_cast<uintptr_t>(constants.slmWindow);
|
||||
}
|
||||
|
||||
if (localMemoryStatelessWindowSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[localMemoryStatelessWindowSizeOffset]) = constants.slmWindowSize;
|
||||
}
|
||||
|
||||
uint32_t privateMemorySize = 0U;
|
||||
if (this->patchInfo.pAllocateStatelessPrivateSurface) {
|
||||
privateMemorySize = this->patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize * constants.computeUnitsUsedForScratch * this->getMaxSimdSize();
|
||||
}
|
||||
|
||||
if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[privateMemoryStatelessSizeOffset]) = privateMemorySize;
|
||||
}
|
||||
|
||||
if (this->workloadInfo.maxWorkGroupSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(this->crossThreadData[this->workloadInfo.maxWorkGroupSizeOffset]) = constants.maxWorkGroupSize;
|
||||
}
|
||||
}
|
||||
|
||||
std::string concatenateKernelNames(ArrayRef<KernelInfo *> kernelInfos) {
|
||||
std::string semiColonDelimitedKernelNameStr;
|
||||
|
||||
|
||||
@@ -188,6 +188,7 @@ struct KernelInfo {
|
||||
}
|
||||
|
||||
bool createKernelAllocation(uint32_t rootDeviceIndex, MemoryManager *memoryManager);
|
||||
void apply(const DeviceInfoKernelPayloadConstants &constants);
|
||||
|
||||
std::string name;
|
||||
std::string attributes;
|
||||
|
||||
@@ -141,8 +141,7 @@ void populateKernelInfoArg(KernelInfo &dstKernelInfo, KernelArgInfo &dstKernelIn
|
||||
dstKernelInfoArg.offsetObjectId = getOffset(src.objectId);
|
||||
}
|
||||
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
|
||||
const DeviceInfoKernelPayloadConstants &constants) {
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes) {
|
||||
UNRECOVERABLE_IF(nullptr == src.header);
|
||||
dst.heapInfo.pKernelHeader = src.header;
|
||||
dst.name = std::string(src.name.begin(), src.name.end()).c_str();
|
||||
@@ -220,31 +219,6 @@ void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatch
|
||||
uint32_t crossThreadDataSize = dst.patchInfo.dataParameterStream->DataParameterStreamSize;
|
||||
dst.crossThreadData = new char[crossThreadDataSize];
|
||||
memset(dst.crossThreadData, 0x00, crossThreadDataSize);
|
||||
|
||||
uint32_t privateMemoryStatelessSizeOffset = dst.workloadInfo.privateMemoryStatelessSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowSizeOffset = dst.workloadInfo.localMemoryStatelessWindowSizeOffset;
|
||||
uint32_t localMemoryStatelessWindowStartAddressOffset = dst.workloadInfo.localMemoryStatelessWindowStartAddressOffset;
|
||||
|
||||
if (localMemoryStatelessWindowStartAddressOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uintptr_t *)&(dst.crossThreadData[localMemoryStatelessWindowStartAddressOffset]) = reinterpret_cast<uintptr_t>(constants.slmWindow);
|
||||
}
|
||||
|
||||
if (localMemoryStatelessWindowSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(dst.crossThreadData[localMemoryStatelessWindowSizeOffset]) = constants.slmWindowSize;
|
||||
}
|
||||
|
||||
uint32_t privateMemorySize = 0U;
|
||||
if (dst.patchInfo.pAllocateStatelessPrivateSurface) {
|
||||
privateMemorySize = dst.patchInfo.pAllocateStatelessPrivateSurface->PerThreadPrivateMemorySize * constants.computeUnitsUsedForScratch * dst.getMaxSimdSize();
|
||||
}
|
||||
|
||||
if (privateMemoryStatelessSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(dst.crossThreadData[privateMemoryStatelessSizeOffset]) = privateMemorySize;
|
||||
}
|
||||
|
||||
if (dst.workloadInfo.maxWorkGroupSizeOffset != WorkloadInfo::undefinedOffset) {
|
||||
*(uint32_t *)&(dst.crossThreadData[dst.workloadInfo.maxWorkGroupSizeOffset]) = constants.maxWorkGroupSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,14 +11,12 @@
|
||||
|
||||
namespace NEO {
|
||||
|
||||
struct DeviceInfoKernelPayloadConstants;
|
||||
struct KernelInfo;
|
||||
|
||||
namespace PatchTokenBinary {
|
||||
struct KernelFromPatchtokens;
|
||||
}
|
||||
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes,
|
||||
const DeviceInfoKernelPayloadConstants &constant);
|
||||
void populateKernelInfo(KernelInfo &dst, const PatchTokenBinary::KernelFromPatchtokens &src, uint32_t gpuPointerSizeInBytes);
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -6,7 +6,9 @@
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/execution_environment/execution_environment.h"
|
||||
#include "core/utilities/stackvec.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
@@ -30,9 +32,6 @@ cl_int Program::link(
|
||||
void(CL_CALLBACK *funcNotify)(cl_program program, void *userData),
|
||||
void *userData) {
|
||||
cl_int retVal = CL_SUCCESS;
|
||||
cl_program program;
|
||||
Program *pInputProgObj;
|
||||
size_t dataSize;
|
||||
bool isCreateLibrary;
|
||||
|
||||
do {
|
||||
@@ -73,16 +72,17 @@ cl_int Program::link(
|
||||
|
||||
buildStatus = CL_BUILD_IN_PROGRESS;
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, false, 1U);
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
|
||||
StackVec<const Program *, 16> inputProgramsInternal;
|
||||
for (cl_uint i = 0; i < numInputPrograms; i++) {
|
||||
program = inputPrograms[i];
|
||||
auto program = inputPrograms[i];
|
||||
if (program == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
}
|
||||
pInputProgObj = castToObject<Program>(program);
|
||||
auto pInputProgObj = castToObject<Program>(program);
|
||||
if (pInputProgObj == nullptr) {
|
||||
retVal = CL_INVALID_PROGRAM;
|
||||
break;
|
||||
@@ -93,16 +93,15 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(pInputProgObj->getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(pInputProgObj->irBinary.get(), pInputProgObj->irBinarySize), static_cast<uint32_t>(pInputProgObj->irBinarySize)));
|
||||
auto sectionType = pInputProgObj->getIsSpirV() ? NEO::Elf::SHT_OPENCL_SPIRV : NEO::Elf::SHT_OPENCL_LLVM_BINARY;
|
||||
ConstStringRef sectionName = pInputProgObj->getIsSpirV() ? NEO::Elf::SectionNamesOpenCl::spirvObject : NEO::Elf::SectionNamesOpenCl::llvmObject;
|
||||
elfEncoder.appendSection(sectionType, sectionName, ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(pInputProgObj->irBinary.get()), pInputProgObj->irBinarySize));
|
||||
}
|
||||
if (retVal != CL_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
|
||||
dataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage data(dataSize);
|
||||
elfWriter.resolveBinary(data);
|
||||
auto clLinkInput = elfEncoder.encode();
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (!pCompilerInterface) {
|
||||
@@ -112,7 +111,7 @@ cl_int Program::link(
|
||||
|
||||
TranslationInput inputArgs = {IGC::CodeType::elf, IGC::CodeType::undefined};
|
||||
|
||||
inputArgs.src = ArrayRef<const char>(data.data(), dataSize);
|
||||
inputArgs.src = ArrayRef<const char>(reinterpret_cast<const char *>(clLinkInput.data()), clLinkInput.size());
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options.c_str(), options.length());
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions.c_str(), internalOptions.length());
|
||||
|
||||
@@ -127,8 +126,7 @@ cl_int Program::link(
|
||||
break;
|
||||
}
|
||||
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->replaceDeviceBinary(std::move(compilerOuput.deviceBinary.mem), compilerOuput.deviceBinary.size);
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
|
||||
|
||||
@@ -5,27 +5,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/device_binary_format/patchtokens_dumper.h"
|
||||
#include "core/device_binary_format/patchtokens_validator.inl"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#include "core/helpers/ptr_math.h"
|
||||
#include "core/helpers/string.h"
|
||||
#include "core/memory_manager/unified_memory_manager.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/program/program_info_from_patchtokens.h"
|
||||
#include "core/program/program_initialization.h"
|
||||
#include "runtime/context/context.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
#include "runtime/gtpin/gtpin_notify.h"
|
||||
#include "runtime/memory_manager/memory_manager.h"
|
||||
#include "runtime/program/kernel_info.h"
|
||||
#include "runtime/program/kernel_info_from_patchtokens.h"
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
#include "patch_list.h"
|
||||
#include "patch_shared.h"
|
||||
#include "program_debug_data.h"
|
||||
|
||||
#include <algorithm>
|
||||
@@ -56,26 +50,6 @@ const KernelInfo *Program::getKernelInfo(size_t ordinal) const {
|
||||
return kernelInfoArray[ordinal];
|
||||
}
|
||||
|
||||
cl_int Program::isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const {
|
||||
std::string validatorErrMessage;
|
||||
std::string validatorWarnings;
|
||||
auto availableSlm = this->pDevice ? static_cast<size_t>(this->pDevice->getDeviceInfo().localMemSize) : 0U;
|
||||
auto validatorErr = PatchTokenBinary::validate(decodedProgram, availableSlm, *this, validatorErrMessage, validatorWarnings);
|
||||
if (validatorWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", validatorWarnings.c_str());
|
||||
}
|
||||
if (validatorErr != PatchTokenBinary::ValidatorError::Success) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", validatorErrMessage.c_str());
|
||||
switch (validatorErr) {
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
case PatchTokenBinary::ValidatorError::NotEnoughSlm:
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::linkBinary() {
|
||||
if (linkerInput == nullptr) {
|
||||
return CL_SUCCESS;
|
||||
@@ -146,6 +120,10 @@ cl_int Program::linkBinary() {
|
||||
}
|
||||
|
||||
cl_int Program::processGenBinary() {
|
||||
if (nullptr == this->unpackedDeviceBinary) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
cleanCurrentKernelInfo();
|
||||
if (this->constantSurface || this->globalSurface) {
|
||||
pDevice->getMemoryManager()->freeGraphicsMemory(this->constantSurface);
|
||||
@@ -154,41 +132,45 @@ cl_int Program::processGenBinary() {
|
||||
this->globalSurface = nullptr;
|
||||
}
|
||||
|
||||
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(genBinary.get()), genBinarySize);
|
||||
ProgramInfo programInfo;
|
||||
auto ret = this->processPatchTokensBinary(blob, programInfo);
|
||||
if (CL_SUCCESS != ret) {
|
||||
return ret;
|
||||
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->unpackedDeviceBinary.get()), this->unpackedDeviceBinarySize);
|
||||
SingleDeviceBinary binary = {};
|
||||
binary.deviceBinary = blob;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
|
||||
DecodeError decodeError;
|
||||
DeviceBinaryFormat singleDeviceBinaryFormat;
|
||||
std::tie(decodeError, singleDeviceBinaryFormat) = NEO::decodeSingleDeviceBinary(programInfo, binary, decodeErrors, decodeWarnings);
|
||||
if (decodeWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
|
||||
}
|
||||
|
||||
if (DecodeError::Success != decodeError) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
return this->processProgramInfo(programInfo);
|
||||
}
|
||||
|
||||
cl_int Program::processPatchTokensBinary(ArrayRef<const uint8_t> src, ProgramInfo &dst) {
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens decodedProgram = {};
|
||||
NEO::PatchTokenBinary::decodeProgramFromPatchtokensBlob(src, decodedProgram);
|
||||
DBG_LOG(LogPatchTokens, NEO::PatchTokenBinary::asString(decodedProgram).c_str());
|
||||
cl_int retVal = this->isHandled(decodedProgram);
|
||||
if (CL_SUCCESS != retVal) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::processProgramInfo(ProgramInfo &src) {
|
||||
size_t slmNeeded = getMaxInlineSlmNeeded(src);
|
||||
size_t slmAvailable = 0U;
|
||||
NEO::DeviceInfoKernelPayloadConstants deviceInfoConstants;
|
||||
if (this->pDevice) {
|
||||
slmAvailable = static_cast<size_t>(this->pDevice->getDeviceInfo().localMemSize);
|
||||
deviceInfoConstants.maxWorkGroupSize = (uint32_t)this->pDevice->getDeviceInfo().maxWorkGroupSize;
|
||||
deviceInfoConstants.computeUnitsUsedForScratch = this->pDevice->getDeviceInfo().computeUnitsUsedForScratch;
|
||||
deviceInfoConstants.slmWindowSize = (uint32_t)this->pDevice->getDeviceInfo().localMemSize;
|
||||
if (requiresLocalMemoryWindowVA(decodedProgram)) {
|
||||
if (requiresLocalMemoryWindowVA(src)) {
|
||||
deviceInfoConstants.slmWindow = this->executionEnvironment.memoryManager->getReservedMemory(MemoryConstants::slmWindowSize, MemoryConstants::slmWindowAlignment);
|
||||
}
|
||||
}
|
||||
|
||||
NEO::populateProgramInfo(dst, decodedProgram, deviceInfoConstants);
|
||||
|
||||
return CL_SUCCESS;
|
||||
if (slmNeeded > slmAvailable) {
|
||||
return CL_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
cl_int Program::processProgramInfo(ProgramInfo &src) {
|
||||
this->linkerInput = std::move(src.linkerInput);
|
||||
this->kernelInfoArray = std::move(src.kernelInfos);
|
||||
auto svmAllocsManager = context ? context->getSVMAllocsManager() : nullptr;
|
||||
@@ -221,23 +203,13 @@ cl_int Program::processProgramInfo(ProgramInfo &src) {
|
||||
if (kernelInfo->requiresSubgroupIndependentForwardProgress()) {
|
||||
subgroupKernelInfoArray.push_back(kernelInfo);
|
||||
}
|
||||
|
||||
kernelInfo->apply(deviceInfoConstants);
|
||||
}
|
||||
|
||||
return linkBinary();
|
||||
}
|
||||
|
||||
bool Program::validateGenBinaryDevice(GFXCORE_FAMILY device) const {
|
||||
bool isValid = familyEnabled[device];
|
||||
|
||||
return isValid;
|
||||
}
|
||||
|
||||
bool Program::validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenBinaryHeader) const {
|
||||
return pGenBinaryHeader->Magic == MAGIC_CL &&
|
||||
pGenBinaryHeader->Version == CURRENT_ICBE_VERSION &&
|
||||
validateGenBinaryDevice(static_cast<GFXCORE_FAMILY>(pGenBinaryHeader->Device));
|
||||
}
|
||||
|
||||
void Program::processDebugData() {
|
||||
if (debugData != nullptr) {
|
||||
SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast<SProgramDebugDataHeaderIGC *>(debugData.get());
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "common/compiler_support.h"
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/helpers/string.h"
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
cl_int Program::processElfBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
uint32_t &binaryVersion) {
|
||||
const CLElfLib::SElf64Header *pElfHeader = nullptr;
|
||||
|
||||
binaryVersion = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
|
||||
elfBinarySize = binarySize;
|
||||
elfBinary = CLElfLib::ElfBinaryStorage(reinterpret_cast<const char *>(pBinary), reinterpret_cast<const char *>(reinterpret_cast<const char *>(pBinary) + binarySize));
|
||||
|
||||
try {
|
||||
CLElfLib::CElfReader elfReader(elfBinary);
|
||||
|
||||
pElfHeader = elfReader.getElfHeader();
|
||||
|
||||
switch (pElfHeader->Type) {
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
break;
|
||||
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
break;
|
||||
|
||||
case CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS:
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
// section 0 is always null
|
||||
for (size_t i = 1u; i < elfReader.getSectionHeaders().size(); ++i) {
|
||||
const auto §ionHeader = elfReader.getSectionHeaders()[i];
|
||||
switch (sectionHeader.Type) {
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV:
|
||||
this->isSpirV = true;
|
||||
CPP_ATTRIBUTE_FALLTHROUGH;
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY:
|
||||
if (sectionHeader.DataSize > 0) {
|
||||
this->irBinary = makeCopy(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
this->irBinarySize = static_cast<size_t>(sectionHeader.DataSize);
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY:
|
||||
if (sectionHeader.DataSize > 0 && validateGenBinaryHeader(reinterpret_cast<iOpenCL::SProgramBinaryHeader *>(elfReader.getSectionData(sectionHeader.DataOffset)))) {
|
||||
this->genBinary = makeCopy(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
this->genBinarySize = static_cast<size_t>(sectionHeader.DataSize);
|
||||
isCreatedFromBinary = true;
|
||||
} else {
|
||||
binaryVersion = reinterpret_cast<iOpenCL::SProgramBinaryHeader *>(elfReader.getSectionData(sectionHeader.DataOffset))->Version;
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS:
|
||||
if (sectionHeader.DataSize > 0) {
|
||||
options = std::string(elfReader.getSectionData(sectionHeader.DataOffset), static_cast<size_t>(sectionHeader.DataSize));
|
||||
}
|
||||
break;
|
||||
|
||||
case CLElfLib::E_SH_TYPE::SH_TYPE_STR_TBL:
|
||||
// We can skip the string table
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
}
|
||||
|
||||
isProgramBinaryResolved = true;
|
||||
|
||||
// Create an empty build log since program is effectively built
|
||||
updateBuildLog(pDevice, "", 1);
|
||||
} catch (const CLElfLib::ElfException &) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::resolveProgramBinary() {
|
||||
CLElfLib::E_EH_TYPE headerType;
|
||||
|
||||
if (isProgramBinaryResolved == false) {
|
||||
elfBinary.clear();
|
||||
elfBinarySize = 0;
|
||||
|
||||
switch (programBinaryType) {
|
||||
case CL_PROGRAM_BINARY_TYPE_EXECUTABLE:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE;
|
||||
|
||||
if (!genBinary || !genBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_TYPE_LIBRARY:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY;
|
||||
|
||||
if (!irBinary || !irBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
case CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT:
|
||||
headerType = CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS;
|
||||
|
||||
if (!irBinary || !irBinarySize) {
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(headerType, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", options, static_cast<uint32_t>(strlen(options.c_str()) + 1u)));
|
||||
std::string irBinaryTemp = irBinary ? std::string(irBinary.get(), irBinarySize) : "";
|
||||
// Add the LLVM component if available
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(getIsSpirV() ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE,
|
||||
headerType == CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY ? "Intel(R) OpenCL LLVM Archive" : "Intel(R) OpenCL LLVM Object", std::move(irBinaryTemp), static_cast<uint32_t>(irBinarySize)));
|
||||
// Add the device binary if it exists
|
||||
if (genBinary) {
|
||||
std::string genBinaryTemp = genBinary ? std::string(genBinary.get(), genBinarySize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
|
||||
}
|
||||
|
||||
// Add the device debug data if it exists
|
||||
if (debugData != nullptr) {
|
||||
std::string debugDataTemp = debugData ? std::string(debugData.get(), debugDataSize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_DEBUG, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Debug", std::move(debugDataTemp), static_cast<uint32_t>(debugDataSize)));
|
||||
}
|
||||
|
||||
elfBinarySize = elfWriter.getTotalBinarySize();
|
||||
elfBinary = CLElfLib::ElfBinaryStorage(elfBinarySize);
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
isProgramBinaryResolved = true;
|
||||
} else {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
25
runtime/program/process_intermediate_binary.cpp
Normal file
25
runtime/program/process_intermediate_binary.cpp
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
cl_int Program::processSpirBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
bool isSpirV) {
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
|
||||
this->irBinary = makeCopy(pBinary, binarySize);
|
||||
this->irBinarySize = binarySize;
|
||||
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
this->isSpirV = isSpirV;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -1,42 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Program::isValidSpirvBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
const uint32_t magicWord[2] = {0x03022307, 0x07230203};
|
||||
bool retVal = false;
|
||||
|
||||
if (pBinary && (binarySize > sizeof(uint32_t))) {
|
||||
if ((memcmp(pBinary, &magicWord[0], sizeof(uint32_t)) == 0) ||
|
||||
(memcmp(pBinary, &magicWord[1], sizeof(uint32_t)) == 0)) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::processSpirBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize,
|
||||
bool isSpirV) {
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
|
||||
this->irBinary = makeCopy(pBinary, binarySize);
|
||||
this->irBinarySize = binarySize;
|
||||
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
this->isSpirV = isSpirV;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -8,7 +8,10 @@
|
||||
#include "program.h"
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device_binary_format/device_binary_formats.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/debug_helpers.h"
|
||||
#include "core/helpers/hw_helper.h"
|
||||
#include "core/helpers/string.h"
|
||||
@@ -43,22 +46,6 @@ Program::Program(ExecutionEnvironment &executionEnvironment, Context *context, b
|
||||
blockKernelManager = new BlockKernelManager();
|
||||
pDevice = context ? context->getDevice(0) : nullptr;
|
||||
numDevices = 1;
|
||||
elfBinarySize = 0;
|
||||
genBinary = nullptr;
|
||||
genBinarySize = 0;
|
||||
irBinary = nullptr;
|
||||
irBinarySize = 0;
|
||||
debugData = nullptr;
|
||||
debugDataSize = 0;
|
||||
buildStatus = CL_BUILD_NONE;
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_NONE;
|
||||
isCreatedFromBinary = false;
|
||||
isProgramBinaryResolved = false;
|
||||
constantSurface = nullptr;
|
||||
globalSurface = nullptr;
|
||||
globalVarTotalSize = 0;
|
||||
programOptionVersion = 12u;
|
||||
allowNonUniform = false;
|
||||
char paramValue[32] = {};
|
||||
bool force32BitAddressess = false;
|
||||
|
||||
@@ -111,8 +98,6 @@ Program::Program(ExecutionEnvironment &executionEnvironment, Context *context, b
|
||||
}
|
||||
|
||||
Program::~Program() {
|
||||
elfBinarySize = 0;
|
||||
|
||||
cleanCurrentKernelInfo();
|
||||
|
||||
freeBlockResources();
|
||||
@@ -146,28 +131,68 @@ cl_int Program::createProgramFromBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
cl_int retVal = CL_INVALID_PROGRAM;
|
||||
uint32_t binaryVersion = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
if (Program::isValidLlvmBinary(pBinary, binarySize)) {
|
||||
retVal = processSpirBinary(pBinary, binarySize, false);
|
||||
} else if (Program::isValidSpirvBinary(pBinary, binarySize)) {
|
||||
retVal = processSpirBinary(pBinary, binarySize, true);
|
||||
this->irBinary.reset();
|
||||
this->irBinarySize = 0U;
|
||||
this->isSpirV = false;
|
||||
this->unpackedDeviceBinary.reset();
|
||||
this->unpackedDeviceBinarySize = 0U;
|
||||
this->packedDeviceBinary.reset();
|
||||
this->packedDeviceBinarySize = 0U;
|
||||
|
||||
ArrayRef<const uint8_t> archive(reinterpret_cast<const uint8_t *>(pBinary), binarySize);
|
||||
bool isSpirV = NEO::isSpirVBitcode(archive);
|
||||
|
||||
if (isSpirV || NEO::isLlvmBitcode(archive)) {
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
retVal = processSpirBinary(archive.begin(), archive.size(), isSpirV);
|
||||
} else if (isAnyDeviceBinaryFormat(archive)) {
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
this->isCreatedFromBinary = true;
|
||||
|
||||
auto productAbbreviation = hardwarePrefix[pDevice->getHardwareInfo().platform.eProductFamily];
|
||||
|
||||
TargetDevice targetDevice = {};
|
||||
targetDevice.coreFamily = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
|
||||
targetDevice.stepping = pDevice->getHardwareInfo().platform.usRevId;
|
||||
targetDevice.maxPointerSizeInBytes = sizeof(uintptr_t);
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto singleDeviceBinary = unpackSingleDeviceBinary(archive, ConstStringRef(productAbbreviation, strlen(productAbbreviation)), targetDevice,
|
||||
decodeErrors, decodeWarnings);
|
||||
if (decodeWarnings.empty() == false) {
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
|
||||
}
|
||||
|
||||
if (singleDeviceBinary.intermediateRepresentation.empty() && singleDeviceBinary.deviceBinary.empty()) {
|
||||
retVal = CL_INVALID_BINARY;
|
||||
printDebugString(DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
|
||||
} else {
|
||||
bool rebuildRequired = DebugManager.flags.RebuildPrecompiledKernels.get();
|
||||
retVal = processElfBinary(pBinary, binarySize, binaryVersion);
|
||||
if (retVal == CL_SUCCESS) {
|
||||
isCreatedFromBinary = true;
|
||||
} else if (binaryVersion != iOpenCL::CURRENT_ICBE_VERSION) {
|
||||
// Version of compiler used to create program binary is invalid,
|
||||
// needs to recompile program binary from its IR (if available).
|
||||
// if recompile fails propagate error retVal from previous function
|
||||
rebuildRequired = true;
|
||||
}
|
||||
|
||||
if (rebuildRequired) {
|
||||
if (rebuildProgramFromIr() == CL_SUCCESS) {
|
||||
retVal = CL_SUCCESS;
|
||||
this->irBinary = makeCopy(reinterpret_cast<const char *>(singleDeviceBinary.intermediateRepresentation.begin()), singleDeviceBinary.intermediateRepresentation.size());
|
||||
this->irBinarySize = singleDeviceBinary.intermediateRepresentation.size();
|
||||
this->isSpirV = NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->irBinary.get()), this->irBinarySize));
|
||||
this->options = singleDeviceBinary.buildOptions.str();
|
||||
|
||||
if ((false == singleDeviceBinary.deviceBinary.empty()) && (false == DebugManager.flags.RebuildPrecompiledKernels.get())) {
|
||||
this->unpackedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(singleDeviceBinary.deviceBinary.begin()), singleDeviceBinary.deviceBinary.size());
|
||||
this->unpackedDeviceBinarySize = singleDeviceBinary.deviceBinary.size();
|
||||
this->packedDeviceBinary = makeCopy<char>(reinterpret_cast<const char *>(archive.begin()), archive.size());
|
||||
this->packedDeviceBinarySize = archive.size();
|
||||
} else {
|
||||
this->isCreatedFromBinary = false;
|
||||
}
|
||||
|
||||
switch (singleDeviceBinary.format) {
|
||||
default:
|
||||
break;
|
||||
case DeviceBinaryFormat::OclLibrary:
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_LIBRARY;
|
||||
break;
|
||||
case DeviceBinaryFormat::OclCompiledObject:
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,60 +200,6 @@ cl_int Program::createProgramFromBinary(
|
||||
return retVal;
|
||||
}
|
||||
|
||||
cl_int Program::rebuildProgramFromIr() {
|
||||
size_t dataSize;
|
||||
|
||||
isSpirV = false;
|
||||
if (Program::isValidSpirvBinary(irBinary.get(), irBinarySize)) {
|
||||
isSpirV = true;
|
||||
} else if (false == Program::isValidLlvmBinary(irBinary.get(), irBinarySize)) {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_OBJECTS, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(isSpirV ? CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV : CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_LLVM_BINARY,
|
||||
CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "", std::string(irBinary.get(), irBinarySize), static_cast<uint32_t>(irBinarySize)));
|
||||
|
||||
dataSize = elfWriter.getTotalBinarySize();
|
||||
CLElfLib::ElfBinaryStorage data(dataSize);
|
||||
elfWriter.resolveBinary(data);
|
||||
|
||||
CompilerInterface *pCompilerInterface = this->executionEnvironment.getCompilerInterface();
|
||||
if (nullptr == pCompilerInterface) {
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
TranslationInput inputArgs = {IGC::CodeType::elf, IGC::CodeType::oclGenBin};
|
||||
inputArgs.src = ArrayRef<const char>(data);
|
||||
inputArgs.apiOptions = ArrayRef<const char>(options);
|
||||
inputArgs.internalOptions = ArrayRef<const char>(internalOptions);
|
||||
|
||||
TranslationOutput compilerOuput = {};
|
||||
auto err = pCompilerInterface->link(this->pDevice->getDevice(), inputArgs, compilerOuput);
|
||||
this->updateBuildLog(this->pDevice, compilerOuput.frontendCompilerLog.c_str(), compilerOuput.frontendCompilerLog.size());
|
||||
this->updateBuildLog(this->pDevice, compilerOuput.backendCompilerLog.c_str(), compilerOuput.backendCompilerLog.size());
|
||||
if (TranslationOutput::ErrorCode::Success != err) {
|
||||
return asClError(err);
|
||||
}
|
||||
|
||||
this->genBinary = std::move(compilerOuput.deviceBinary.mem);
|
||||
this->genBinarySize = compilerOuput.deviceBinary.size;
|
||||
this->debugData = std::move(compilerOuput.debugData.mem);
|
||||
this->debugDataSize = compilerOuput.debugData.size;
|
||||
|
||||
auto retVal = processGenBinary();
|
||||
if (retVal != CL_SUCCESS) {
|
||||
return retVal;
|
||||
}
|
||||
|
||||
programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE;
|
||||
isCreatedFromBinary = true;
|
||||
isProgramBinaryResolved = true;
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
cl_int Program::setProgramSpecializationConstant(cl_uint specId, size_t specSize, const void *specValue) {
|
||||
if (!isSpirV) {
|
||||
return CL_INVALID_PROGRAM;
|
||||
@@ -270,22 +241,6 @@ cl_int Program::updateSpecializationConstant(cl_uint specId, size_t specSize, co
|
||||
return CL_INVALID_SPEC_ID;
|
||||
}
|
||||
|
||||
bool Program::isValidLlvmBinary(
|
||||
const void *pBinary,
|
||||
size_t binarySize) {
|
||||
|
||||
const char *pLlvmMagic = "BC\xc0\xde";
|
||||
bool retVal = false;
|
||||
|
||||
if (pBinary && (binarySize > (strlen(pLlvmMagic) + 1))) {
|
||||
if (strstr((char *)pBinary, pLlvmMagic) != nullptr) {
|
||||
retVal = true;
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void Program::setDevice(Device *device) {
|
||||
this->pDevice = device->getSpecializedDevice<ClDevice>();
|
||||
}
|
||||
@@ -456,4 +411,61 @@ void Program::updateNonUniformFlag(const Program **inputPrograms, size_t numInpu
|
||||
this->allowNonUniform = allowNonUniform;
|
||||
}
|
||||
|
||||
void Program::replaceDeviceBinary(std::unique_ptr<char[]> newBinary, size_t newBinarySize) {
|
||||
if (isAnyPackedDeviceBinaryFormat(ArrayRef<const uint8_t>(reinterpret_cast<uint8_t *>(newBinary.get()), newBinarySize))) {
|
||||
this->packedDeviceBinary = std::move(newBinary);
|
||||
this->packedDeviceBinarySize = newBinarySize;
|
||||
this->unpackedDeviceBinary.reset();
|
||||
this->unpackedDeviceBinarySize = 0U;
|
||||
} else {
|
||||
this->packedDeviceBinary.reset();
|
||||
this->packedDeviceBinarySize = 0U;
|
||||
this->unpackedDeviceBinary = std::move(newBinary);
|
||||
this->unpackedDeviceBinarySize = newBinarySize;
|
||||
}
|
||||
}
|
||||
|
||||
cl_int Program::packDeviceBinary() {
|
||||
if (nullptr != packedDeviceBinary) {
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
auto gfxCore = pDevice->getHardwareInfo().platform.eRenderCoreFamily;
|
||||
auto stepping = pDevice->getHardwareInfo().platform.usRevId;
|
||||
|
||||
if (nullptr != this->unpackedDeviceBinary.get()) {
|
||||
SingleDeviceBinary singleDeviceBinary;
|
||||
singleDeviceBinary.buildOptions = this->options;
|
||||
singleDeviceBinary.targetDevice.coreFamily = gfxCore;
|
||||
singleDeviceBinary.targetDevice.stepping = stepping;
|
||||
singleDeviceBinary.deviceBinary = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->unpackedDeviceBinary.get()), this->unpackedDeviceBinarySize);
|
||||
singleDeviceBinary.intermediateRepresentation = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->irBinary.get()), this->irBinarySize);
|
||||
std::string packWarnings;
|
||||
std::string packErrors;
|
||||
auto packedDeviceBinary = NEO::packDeviceBinary(singleDeviceBinary, packErrors, packWarnings);
|
||||
if (packedDeviceBinary.empty()) {
|
||||
DEBUG_BREAK_IF(true);
|
||||
return CL_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
this->packedDeviceBinary = makeCopy(packedDeviceBinary.data(), packedDeviceBinary.size());
|
||||
this->packedDeviceBinarySize = packedDeviceBinary.size();
|
||||
} else if (nullptr != this->irBinary.get()) {
|
||||
NEO::Elf::ElfEncoder<> elfEncoder(true, true, 1U);
|
||||
if (this->programBinaryType == CL_PROGRAM_BINARY_TYPE_LIBRARY) {
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
} else {
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_OBJECTS;
|
||||
}
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(this->irBinary.get(), this->irBinarySize));
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, this->options);
|
||||
auto elfData = elfEncoder.encode();
|
||||
this->packedDeviceBinary = makeCopy(elfData.data(), elfData.size());
|
||||
this->packedDeviceBinarySize = elfData.size();
|
||||
} else {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
#pragma once
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/compiler_interface/linker.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/program/program_info.h"
|
||||
#include "core/utilities/const_stringref.h"
|
||||
#include "runtime/api/cl_types.h"
|
||||
@@ -132,7 +132,6 @@ class Program : public BaseObject<_cl_program> {
|
||||
std::unordered_map<std::string, BuiltinDispatchInfoBuilder *> &builtinsMap);
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int processGenBinary();
|
||||
MOCKABLE_VIRTUAL cl_int processPatchTokensBinary(ArrayRef<const uint8_t> src, ProgramInfo &dst);
|
||||
MOCKABLE_VIRTUAL cl_int processProgramInfo(ProgramInfo &dst);
|
||||
|
||||
cl_int compile(cl_uint numDevices, const cl_device_id *deviceList, const char *buildOptions,
|
||||
@@ -181,7 +180,6 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
void setDevice(Device *device);
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int processElfBinary(const void *pBinary, size_t binarySize, uint32_t &binaryVersion);
|
||||
cl_int processSpirBinary(const void *pBinary, size_t binarySize, bool isSpirV);
|
||||
|
||||
cl_int getSource(std::string &binary) const;
|
||||
@@ -238,8 +236,6 @@ class Program : public BaseObject<_cl_program> {
|
||||
kernelDebugEnabled = true;
|
||||
}
|
||||
|
||||
static bool isValidLlvmBinary(const void *pBinary, size_t binarySize);
|
||||
static bool isValidSpirvBinary(const void *pBinary, size_t binarySize);
|
||||
bool isKernelDebugEnabled() {
|
||||
return kernelDebugEnabled;
|
||||
}
|
||||
@@ -260,24 +256,17 @@ class Program : public BaseObject<_cl_program> {
|
||||
return this->linkerInput.get();
|
||||
}
|
||||
|
||||
MOCKABLE_VIRTUAL bool isSafeToSkipUnhandledToken(unsigned int token) const;
|
||||
MOCKABLE_VIRTUAL void replaceDeviceBinary(std::unique_ptr<char[]> newBinary, size_t newBinarySize);
|
||||
|
||||
protected:
|
||||
Program(ExecutionEnvironment &executionEnvironment);
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int createProgramFromBinary(const void *pBinary, size_t binarySize);
|
||||
|
||||
cl_int resolveProgramBinary();
|
||||
cl_int packDeviceBinary();
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int linkBinary();
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const;
|
||||
|
||||
MOCKABLE_VIRTUAL cl_int rebuildProgramFromIr();
|
||||
|
||||
bool validateGenBinaryDevice(GFXCORE_FAMILY device) const;
|
||||
bool validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenBinaryHeader) const;
|
||||
|
||||
void separateBlockKernels();
|
||||
|
||||
void updateNonUniformFlag();
|
||||
@@ -293,19 +282,20 @@ class Program : public BaseObject<_cl_program> {
|
||||
|
||||
static const std::string clOptNameClVer;
|
||||
|
||||
cl_program_binary_type programBinaryType;
|
||||
cl_program_binary_type programBinaryType = CL_PROGRAM_BINARY_TYPE_NONE;
|
||||
bool isSpirV = false;
|
||||
CLElfLib::ElfBinaryStorage elfBinary;
|
||||
size_t elfBinarySize;
|
||||
|
||||
std::unique_ptr<char[]> genBinary;
|
||||
size_t genBinarySize;
|
||||
|
||||
std::unique_ptr<char[]> irBinary;
|
||||
size_t irBinarySize;
|
||||
size_t irBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> unpackedDeviceBinary;
|
||||
size_t unpackedDeviceBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> packedDeviceBinary;
|
||||
size_t packedDeviceBinarySize = 0U;
|
||||
|
||||
std::unique_ptr<char[]> debugData;
|
||||
size_t debugDataSize;
|
||||
size_t debugDataSize = 0U;
|
||||
|
||||
CreatedFrom createdFrom = CreatedFrom::UNKNOWN;
|
||||
|
||||
@@ -313,23 +303,22 @@ class Program : public BaseObject<_cl_program> {
|
||||
std::vector<KernelInfo *> parentKernelInfoArray;
|
||||
std::vector<KernelInfo *> subgroupKernelInfoArray;
|
||||
|
||||
GraphicsAllocation *constantSurface;
|
||||
GraphicsAllocation *globalSurface;
|
||||
GraphicsAllocation *constantSurface = nullptr;
|
||||
GraphicsAllocation *globalSurface = nullptr;
|
||||
GraphicsAllocation *exportedFunctionsSurface = nullptr;
|
||||
|
||||
size_t globalVarTotalSize;
|
||||
size_t globalVarTotalSize = 0U;
|
||||
|
||||
cl_build_status buildStatus;
|
||||
bool isCreatedFromBinary;
|
||||
bool isProgramBinaryResolved;
|
||||
cl_build_status buildStatus = CL_BUILD_NONE;
|
||||
bool isCreatedFromBinary = false;
|
||||
|
||||
std::string sourceCode;
|
||||
std::string options;
|
||||
std::string internalOptions;
|
||||
static const std::vector<ConstStringRef> internalOptionsToExtract;
|
||||
|
||||
uint32_t programOptionVersion;
|
||||
bool allowNonUniform;
|
||||
uint32_t programOptionVersion = 12U;
|
||||
bool allowNonUniform = false;
|
||||
|
||||
std::unique_ptr<LinkerInput> linkerInput;
|
||||
Linker::RelocatedSymbolsMap symbols;
|
||||
@@ -341,13 +330,13 @@ class Program : public BaseObject<_cl_program> {
|
||||
CIF::RAII::UPtr_t<CIF::Builtins::BufferSimple> specConstantsSizes;
|
||||
CIF::RAII::UPtr_t<CIF::Builtins::BufferSimple> specConstantsValues;
|
||||
|
||||
BlockKernelManager *blockKernelManager;
|
||||
BlockKernelManager *blockKernelManager = nullptr;
|
||||
ExecutionEnvironment &executionEnvironment;
|
||||
Context *context;
|
||||
ClDevice *pDevice;
|
||||
cl_uint numDevices;
|
||||
Context *context = nullptr;
|
||||
ClDevice *pDevice = nullptr;
|
||||
cl_uint numDevices = 0U;
|
||||
|
||||
bool isBuiltIn;
|
||||
bool isBuiltIn = false;
|
||||
bool kernelDebugEnabled = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation
|
||||
* Copyright (C) 2019-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -8,7 +8,18 @@
|
||||
#pragma once
|
||||
#include "core/debug_settings/debug_settings_manager.h"
|
||||
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
namespace NEO {
|
||||
class Kernel;
|
||||
struct MultiDispatchInfo;
|
||||
|
||||
template <DebugFunctionalityLevel DebugLevel>
|
||||
class FileLogger {
|
||||
public:
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
*/
|
||||
|
||||
#include "core/compiler_interface/compiler_interface.h"
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device/device.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_encoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "runtime/context/context.h"
|
||||
#include "unit_tests/elflib/elf_binary_simulator.h"
|
||||
#include "unit_tests/helpers/kernel_binary_helper.h"
|
||||
#include "unit_tests/helpers/test_files.h"
|
||||
|
||||
@@ -98,8 +101,12 @@ TEST_F(clGetProgramBuildInfoTests, givenElfBinaryWhenclGetProgramBuildInfoIsCall
|
||||
cl_program pProgram = nullptr;
|
||||
cl_int binaryStatus = CL_INVALID_VALUE;
|
||||
|
||||
CLElfLib::ElfBinaryStorage elfBinary;
|
||||
MockElfBinary(elfBinary);
|
||||
NEO::Elf::ElfEncoder<NEO::Elf::EI_CLASS_64> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_LIBRARY;
|
||||
const uint8_t data[4] = {};
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, NEO::Elf::SectionNamesOpenCl::buildOptions, data);
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, NEO::Elf::SectionNamesOpenCl::spirvObject, ArrayRef<const uint8_t>::fromAny(NEO::spirvMagic.begin(), NEO::spirvMagic.size()));
|
||||
auto elfBinary = elfEncoder.encode();
|
||||
|
||||
const size_t binarySize = elfBinary.size();
|
||||
const unsigned char *elfBinaryTemp = reinterpret_cast<unsigned char *>(elfBinary.data());
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
#
|
||||
# Copyright (C) 2017-2019 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
#
|
||||
|
||||
project(elflib_tests)
|
||||
|
||||
set(CLELFLIB_UNIT_TESTS_SRCS
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/elflib_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
|
||||
${NEO_SOURCE_DIR}/unit_tests/fixtures/memory_management_fixture.cpp
|
||||
${NEO_SOURCE_DIR}/unit_tests/fixtures/memory_management_fixture.h
|
||||
${NEO_SOURCE_DIR}/core/unit_tests/helpers/memory_management.cpp
|
||||
${NEO_SOURCE_DIR}/core/unit_tests/helpers/memory_management.h
|
||||
)
|
||||
|
||||
add_executable(elflib_tests ${CLELFLIB_UNIT_TESTS_SRCS})
|
||||
target_link_libraries(elflib_tests gmock-gtest elflib)
|
||||
set_property(TARGET elflib_tests APPEND_STRING PROPERTY COMPILE_FLAGS ${ASAN_FLAGS})
|
||||
|
||||
if(UNIX)
|
||||
target_link_libraries(elflib_tests ${IGDRCL_EXTRA_LIBS})
|
||||
endif()
|
||||
|
||||
add_custom_target(run_elflib_tests ALL DEPENDS unit_tests elflib_tests)
|
||||
add_custom_command(
|
||||
TARGET run_elflib_tests
|
||||
POST_BUILD
|
||||
COMMAND elflib_tests ${IGDRCL_TESTS_LISTENER_OPTION}
|
||||
)
|
||||
add_dependencies(run_unit_tests run_elflib_tests)
|
||||
|
||||
set_target_properties(elflib_tests PROPERTIES FOLDER "elflib")
|
||||
set_target_properties(run_elflib_tests PROPERTIES FOLDER "elflib")
|
||||
create_project_source_tree(elflib_tests ${NEO_SOURCE_DIR}/unit_tests)
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "core/elf/types.h"
|
||||
#include "core/elf/writer.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
void MockElfBinary(CLElfLib::ElfBinaryStorage &elfBinary) {
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_OPTIONS, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "BuildOptions", "\0", 1u));
|
||||
|
||||
elfBinary.resize(elfWriter.getTotalBinarySize());
|
||||
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
}
|
||||
} // namespace NEO
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/elf/writer.h"
|
||||
#include "unit_tests/fixtures/memory_management_fixture.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace CLElfLib;
|
||||
|
||||
struct ElfTests : public MemoryManagementFixture,
|
||||
public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
MemoryManagementFixture::SetUp();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
MemoryManagementFixture::TearDown();
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionIsAdded) {
|
||||
class MockElfWriter : public CElfWriter {
|
||||
public:
|
||||
MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
|
||||
using CElfWriter::nodeQueue;
|
||||
};
|
||||
|
||||
MockElfWriter writer;
|
||||
std::string data{"data pattern"};
|
||||
|
||||
writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "Steve", data, static_cast<uint32_t>(data.size())));
|
||||
|
||||
ASSERT_EQ(2u, writer.nodeQueue.size());
|
||||
// remove first (default) section
|
||||
writer.nodeQueue.pop();
|
||||
EXPECT_EQ(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, writer.nodeQueue.front().type);
|
||||
EXPECT_EQ(E_SH_FLAG::SH_FLAG_WRITE, writer.nodeQueue.front().flag);
|
||||
EXPECT_EQ("Steve", writer.nodeQueue.front().name);
|
||||
EXPECT_EQ(data, writer.nodeQueue.front().data);
|
||||
EXPECT_EQ(static_cast<uint32_t>(data.size()), writer.nodeQueue.front().dataSize);
|
||||
}
|
||||
|
||||
TEST_F(ElfTests, givenCElfWriterWhenPatchElfHeaderThenDefaultAreSet) {
|
||||
class MockElfWriter : public CElfWriter {
|
||||
public:
|
||||
MockElfWriter() : CElfWriter(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0) {}
|
||||
using CElfWriter::patchElfHeader;
|
||||
};
|
||||
|
||||
MockElfWriter writer;
|
||||
|
||||
SElf64Header elfHeader;
|
||||
|
||||
writer.patchElfHeader(elfHeader);
|
||||
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic0] == ELFConstants::elfMag0);
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic1] == ELFConstants::elfMag1);
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic2] == ELFConstants::elfMag2);
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxMagic3] == ELFConstants::elfMag3);
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxClass] == static_cast<uint32_t>(E_EH_CLASS::EH_CLASS_64));
|
||||
EXPECT_TRUE(elfHeader.Identity[ELFConstants::idIdxVersion] == static_cast<uint32_t>(E_EHT_VERSION::EH_VERSION_CURRENT));
|
||||
|
||||
EXPECT_TRUE(elfHeader.Type == E_EH_TYPE::EH_TYPE_EXECUTABLE);
|
||||
EXPECT_TRUE(elfHeader.Machine == E_EH_MACHINE::EH_MACHINE_NONE);
|
||||
EXPECT_TRUE(elfHeader.Flags == static_cast<uint32_t>(0));
|
||||
EXPECT_TRUE(elfHeader.ElfHeaderSize == static_cast<uint32_t>(sizeof(SElf64Header)));
|
||||
EXPECT_TRUE(elfHeader.SectionHeaderEntrySize == static_cast<uint32_t>(sizeof(SElf64SectionHeader)));
|
||||
EXPECT_TRUE(elfHeader.NumSectionHeaderEntries == 1);
|
||||
EXPECT_TRUE(elfHeader.SectionHeadersOffset == static_cast<uint32_t>(sizeof(SElf64Header)));
|
||||
EXPECT_TRUE(elfHeader.SectionNameTableIndex == 0);
|
||||
}
|
||||
|
||||
TEST_F(ElfTests, givenSectionDataWhenWriteToBinaryThenSectionCanBeReadByID) {
|
||||
CElfWriter writer(E_EH_TYPE::EH_TYPE_EXECUTABLE, E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
char sectionData[16];
|
||||
memset(sectionData, 0xdeadbeef, 4);
|
||||
|
||||
writer.addSection(SSectionNode(E_SH_TYPE::SH_TYPE_OPENCL_SOURCE, E_SH_FLAG::SH_FLAG_WRITE, "", std::string(sectionData, 16u), 16u));
|
||||
|
||||
size_t binarySize = writer.getTotalBinarySize();
|
||||
|
||||
ElfBinaryStorage binary(binarySize);
|
||||
writer.resolveBinary(binary);
|
||||
|
||||
CElfReader elfReader(binary);
|
||||
|
||||
char *pData = elfReader.getSectionData(elfReader.getSectionHeaders()[1].DataOffset);
|
||||
|
||||
EXPECT_EQ(16u, elfReader.getSectionHeaders()[1].DataSize);
|
||||
for (unsigned int i = 0; i < elfReader.getSectionHeaders()[1].DataSize; i++) {
|
||||
EXPECT_EQ(sectionData[i], pData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(ElfTests, givenInvalidBinaryStorageThenExceptionIsThrown) {
|
||||
ElfBinaryStorage binary;
|
||||
|
||||
EXPECT_THROW(CElfReader elfReader(binary), ElfException);
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "unit_tests/custom_event_listener.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int retVal = 0;
|
||||
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
::testing::TestEventListeners &listeners = ::testing::UnitTest::GetInstance()->listeners();
|
||||
::testing::TestEventListener *default_listner = listeners.default_result_printer();
|
||||
|
||||
CCustomEventListener *customEventListener = new CCustomEventListener(default_listner);
|
||||
|
||||
listeners.Release(listeners.default_result_printer());
|
||||
listeners.Append(customEventListener);
|
||||
|
||||
retVal = RUN_ALL_TESTS();
|
||||
|
||||
return retVal;
|
||||
}
|
||||
@@ -81,7 +81,7 @@ void KernelDataTest::buildAndDecode() {
|
||||
// now build a program with this kernel data
|
||||
iOpenCL::SProgramBinaryHeader header = {};
|
||||
NEO::PatchTokenBinary::ProgramFromPatchtokens programFromPatchtokens;
|
||||
programFromPatchtokens.decodeStatus = PatchTokenBinary::DecoderError::Success;
|
||||
programFromPatchtokens.decodeStatus = DecodeError::Success;
|
||||
programFromPatchtokens.header = &header;
|
||||
programFromPatchtokens.kernels.resize(1);
|
||||
auto &kernelFromPatchtokens = *programFromPatchtokens.kernels.rbegin();
|
||||
@@ -90,7 +90,7 @@ void KernelDataTest::buildAndDecode() {
|
||||
EXPECT_TRUE(decodeSuccess);
|
||||
|
||||
ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programFromPatchtokens, DeviceInfoKernelPayloadConstants());
|
||||
NEO::populateProgramInfo(programInfo, programFromPatchtokens);
|
||||
error = program->processProgramInfo(programInfo);
|
||||
EXPECT_EQ(CL_SUCCESS, error);
|
||||
|
||||
|
||||
@@ -987,8 +987,8 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenKernelWithoutSSHIsUsedThenK
|
||||
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
|
||||
pProgram->genBinary = makeCopy(reinterpret_cast<char *>(programTokens.storage.data()), programTokens.storage.size());
|
||||
pProgram->genBinarySize = programTokens.storage.size();
|
||||
pProgram->unpackedDeviceBinary = makeCopy(reinterpret_cast<char *>(programTokens.storage.data()), programTokens.storage.size());
|
||||
pProgram->unpackedDeviceBinarySize = programTokens.storage.size();
|
||||
retVal = pProgram->processGenBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
@@ -1112,8 +1112,8 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenKernelWithExecEnvIsUsedThen
|
||||
uint64_t hashValue = Hash::hash(reinterpret_cast<const char *>(pKernelBin), kernelBinSize);
|
||||
pKHdr->CheckSum = static_cast<uint32_t>(hashValue & 0xFFFFFFFF);
|
||||
|
||||
pProgram->genBinary = makeCopy(&binary[0], binSize);
|
||||
pProgram->genBinarySize = binSize;
|
||||
pProgram->unpackedDeviceBinary = makeCopy(&binary[0], binSize);
|
||||
pProgram->unpackedDeviceBinarySize = binSize;
|
||||
retVal = pProgram->processGenBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
@@ -2039,8 +2039,8 @@ TEST_F(GTPinTests, givenInitializedGTPinInterfaceWhenLowMemoryConditionOccursThe
|
||||
|
||||
PatchTokensTestData::ValidProgramWithKernel programTokens;
|
||||
|
||||
pProgram->genBinary = makeCopy(programTokens.storage.data(), programTokens.storage.size());
|
||||
pProgram->genBinarySize = programTokens.storage.size();
|
||||
pProgram->unpackedDeviceBinary = makeCopy(programTokens.storage.data(), programTokens.storage.size());
|
||||
pProgram->unpackedDeviceBinarySize = programTokens.storage.size();
|
||||
retVal = pProgram->processGenBinary();
|
||||
if (retVal == CL_OUT_OF_HOST_MEMORY) {
|
||||
auto nonFailingAlloc = MemoryManagement::nonfailingAllocation;
|
||||
|
||||
@@ -40,7 +40,6 @@ set(IGDRCL_SRCS_LIB_ULT
|
||||
${NEO_SOURCE_DIR}/unit_tests/libult/source_level_debugger_library.h
|
||||
${NEO_SOURCE_DIR}/unit_tests/libult/ult_aub_command_stream_receiver.h
|
||||
${NEO_SOURCE_DIR}/unit_tests/libult/ult_command_stream_receiver.h
|
||||
${NEO_SOURCE_DIR}/unit_tests/program/evaluate_unhandled_token_ult.cpp
|
||||
${NEO_SOURCE_DIR}/unit_tests/utilities/debug_settings_reader_creator.cpp
|
||||
${NEO_CORE_DIRECTORY}/unit_tests/helpers/memory_leak_listener.cpp
|
||||
${NEO_CORE_DIRECTORY}/unit_tests/helpers/memory_leak_listener.h
|
||||
|
||||
@@ -104,7 +104,7 @@ Program *GlobalMockSipProgram::getSipProgramWithCustomBinary() {
|
||||
programTokens.kernels[0].name = name;
|
||||
|
||||
NEO::ProgramInfo programInfo;
|
||||
NEO::populateProgramInfo(programInfo, programTokens, {});
|
||||
NEO::populateProgramInfo(programInfo, programTokens);
|
||||
|
||||
Program *ret = new Program(executionEnvironment, nullptr, false);
|
||||
ret->processProgramInfo(programInfo);
|
||||
|
||||
@@ -6,8 +6,10 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "core/device/device.h"
|
||||
#include "core/helpers/hash.h"
|
||||
#include "core/helpers/string.h"
|
||||
#include "runtime/device/cl_device.h"
|
||||
#include "runtime/program/kernel_info.h"
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
@@ -28,8 +30,6 @@ class MockProgram : public Program {
|
||||
using Program::internalOptionsToExtract;
|
||||
using Program::isKernelDebugEnabled;
|
||||
using Program::linkBinary;
|
||||
using Program::rebuildProgramFromIr;
|
||||
using Program::resolveProgramBinary;
|
||||
using Program::separateBlockKernels;
|
||||
using Program::updateNonUniformFlag;
|
||||
|
||||
@@ -40,19 +40,18 @@ class MockProgram : public Program {
|
||||
using Program::context;
|
||||
using Program::debugData;
|
||||
using Program::debugDataSize;
|
||||
using Program::elfBinary;
|
||||
using Program::elfBinarySize;
|
||||
using Program::exportedFunctionsSurface;
|
||||
using Program::extractInternalOptions;
|
||||
using Program::genBinary;
|
||||
using Program::genBinarySize;
|
||||
using Program::getKernelInfo;
|
||||
using Program::globalSurface;
|
||||
using Program::irBinary;
|
||||
using Program::irBinarySize;
|
||||
using Program::isProgramBinaryResolved;
|
||||
using Program::isSpirV;
|
||||
using Program::linkerInput;
|
||||
using Program::options;
|
||||
using Program::packDeviceBinary;
|
||||
using Program::packedDeviceBinary;
|
||||
using Program::packedDeviceBinarySize;
|
||||
using Program::pDevice;
|
||||
using Program::programBinaryType;
|
||||
using Program::sourceCode;
|
||||
@@ -60,6 +59,8 @@ class MockProgram : public Program {
|
||||
using Program::specConstantsSizes;
|
||||
using Program::specConstantsValues;
|
||||
using Program::symbols;
|
||||
using Program::unpackedDeviceBinary;
|
||||
using Program::unpackedDeviceBinarySize;
|
||||
|
||||
template <typename... T>
|
||||
MockProgram(T &&... args) : Program(std::forward<T>(args)...) {
|
||||
@@ -138,15 +139,16 @@ class MockProgram : public Program {
|
||||
return Program::isOptionValueValid(option, value);
|
||||
}
|
||||
|
||||
cl_int isHandled(const PatchTokenBinary::ProgramFromPatchtokens &decodedProgram) const override {
|
||||
if (skipValidationOfBinary) {
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
return Program::isHandled(decodedProgram);
|
||||
cl_int rebuildProgramFromIr() {
|
||||
this->isCreatedFromBinary = false;
|
||||
this->buildStatus = CL_BUILD_NONE;
|
||||
this->programBinaryType = CL_PROGRAM_BINARY_TYPE_INTERMEDIATE;
|
||||
std::unordered_map<std::string, BuiltinDispatchInfoBuilder *> builtins;
|
||||
auto &device = this->pDevice->getDevice();
|
||||
return this->build(&device, this->options.c_str(), false, builtins);
|
||||
}
|
||||
|
||||
bool contextSet = false;
|
||||
bool skipValidationOfBinary = false;
|
||||
int isFlagOptionOverride = -1;
|
||||
int isOptionValueValidOverride = -1;
|
||||
};
|
||||
|
||||
@@ -83,7 +83,7 @@ target_include_directories(ocloc_tests PRIVATE
|
||||
)
|
||||
target_compile_definitions(ocloc_tests PUBLIC MOCKABLE_VIRTUAL=virtual $<TARGET_PROPERTY:ocloc,INTERFACE_COMPILE_DEFINITIONS>)
|
||||
|
||||
target_link_libraries(ocloc_tests gmock-gtest elflib)
|
||||
target_link_libraries(ocloc_tests gmock-gtest)
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(ocloc_tests dbghelp)
|
||||
|
||||
@@ -217,7 +217,7 @@ TEST(DecoderTests, GivenValidBinaryWhenReadingPatchTokensFromBinaryThenBinaryIsR
|
||||
PTptr->fields.push_back(PTField{4, "First"});
|
||||
PTptr->fields.push_back(PTField{4, "Second"});
|
||||
decoder.patchTokens.insert(std::pair<uint8_t, std::unique_ptr<PatchToken>>(4, std::move(PTptr)));
|
||||
void *ptr = reinterpret_cast<void *>(binary.data());
|
||||
const void *ptr = reinterpret_cast<void *>(binary.data());
|
||||
decoder.readPatchTokens(ptr, 28, out);
|
||||
std::string s = "Example patchtoken:\n\t4 Token 4\n\t4 Size 16\n\t4 First 1234\n\t4 Second 5678\nUnidentified PatchToken:\n\t4 Token 2\n\t4 Size 12\n\tHex ff ff ff ff\n";
|
||||
EXPECT_EQ(s, out.str());
|
||||
@@ -242,7 +242,7 @@ TEST(DecoderTests, GivenValidBinaryWithoutPatchTokensWhenProcessingBinaryThenBin
|
||||
|
||||
std::string binaryString = binarySS.str();
|
||||
std::vector<unsigned char> binary(binaryString.begin(), binaryString.end());
|
||||
auto ptr = reinterpret_cast<void *>(binary.data());
|
||||
const void *ptr = reinterpret_cast<void *>(binary.data());
|
||||
int retVal = decoder.processBinary(ptr, ptmFile);
|
||||
EXPECT_EQ(0, retVal);
|
||||
|
||||
@@ -291,7 +291,7 @@ TEST(DecoderTests, GivenValidBinaryWhenProcessingBinaryThenProgramAndKernelAndPa
|
||||
decoder.pathToDump = "non_existing_folder/";
|
||||
decoder.parseTokens();
|
||||
|
||||
auto ptr = reinterpret_cast<void *>(binary.data());
|
||||
const void *ptr = reinterpret_cast<void *>(binary.data());
|
||||
int retVal = decoder.processBinary(ptr, ptmFile);
|
||||
EXPECT_EQ(0, retVal);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
* Copyright (C) 2017-2020 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
@@ -15,6 +15,7 @@ namespace NEO {
|
||||
class MockOfflineCompiler : public OfflineCompiler {
|
||||
public:
|
||||
using OfflineCompiler::deviceName;
|
||||
using OfflineCompiler::elfBinary;
|
||||
using OfflineCompiler::fclDeviceCtx;
|
||||
using OfflineCompiler::generateFilePathForIr;
|
||||
using OfflineCompiler::generateOptsSuffix;
|
||||
@@ -80,14 +81,6 @@ class MockOfflineCompiler : public OfflineCompiler {
|
||||
return OfflineCompiler::generateElfBinary();
|
||||
}
|
||||
|
||||
char *getElfBinary() {
|
||||
return elfBinary.data();
|
||||
}
|
||||
|
||||
size_t getElfBinarySize() {
|
||||
return elfBinarySize;
|
||||
}
|
||||
|
||||
char *getGenBinary() {
|
||||
return genBinary;
|
||||
}
|
||||
|
||||
@@ -768,14 +768,12 @@ TEST(OfflineCompilerTest, generateElfBinary) {
|
||||
|
||||
mockOfflineCompiler->storeGenBinary(&binHeader, binSize);
|
||||
|
||||
EXPECT_EQ(nullptr, mockOfflineCompiler->getElfBinary());
|
||||
EXPECT_EQ(0u, mockOfflineCompiler->getElfBinarySize());
|
||||
EXPECT_TRUE(mockOfflineCompiler->elfBinary.empty());
|
||||
|
||||
retVal = mockOfflineCompiler->generateElfBinary();
|
||||
EXPECT_TRUE(retVal);
|
||||
|
||||
EXPECT_NE(nullptr, mockOfflineCompiler->getElfBinary());
|
||||
EXPECT_NE(0u, mockOfflineCompiler->getElfBinarySize());
|
||||
EXPECT_FALSE(mockOfflineCompiler->elfBinary.empty());
|
||||
}
|
||||
|
||||
TEST(OfflineCompilerTest, givenLlvmInputOptionPassedWhenCmdLineParsedThenInputFileLlvmIsSetTrue) {
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
set(IGDRCL_SRCS_tests_program
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/block_kernel_manager_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/evaluate_unhandled_token_tests.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_data.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_data_OCL2_0.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_tests.cpp
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017-2019 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
*/
|
||||
|
||||
#include "runtime/program/program.h"
|
||||
|
||||
namespace NEO {
|
||||
|
||||
bool Program::isSafeToSkipUnhandledToken(unsigned int token) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace NEO
|
||||
@@ -16,7 +16,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidEmptyKernelFromPatchtokensThenReturnEm
|
||||
std::vector<uint8_t> storage;
|
||||
auto src = PatchTokensTestData::ValidEmptyKernel::create(storage);
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src, 4, {});
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
|
||||
NEO::KernelInfo expectedKernelInfo = {};
|
||||
expectedKernelInfo.name = std::string(src.name.begin()).c_str();
|
||||
@@ -29,7 +29,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidEmptyKernelFromPatchtokensThenReturnEm
|
||||
TEST(KernelInfoFromPatchTokens, GivenValidKernelWithArgThenMetadataIsProperlyPopulated) {
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4, {});
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AddressSpaceQualifier::Global, dst.kernelArgInfo[0].metadata.addressQualifier);
|
||||
@@ -52,7 +52,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidKernelWithImageArgThenArgAccessQualifi
|
||||
imageArg.Writeable = false;
|
||||
src.kernels[0].tokens.kernelArgs[0].objectArg = &imageArg;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4, {});
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
@@ -66,7 +66,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidKernelWithImageArgWhenArgInfoIsMissing
|
||||
{
|
||||
imageArg.Writeable = false;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4, {});
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadOnly, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
@@ -74,7 +74,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidKernelWithImageArgWhenArgInfoIsMissing
|
||||
{
|
||||
imageArg.Writeable = true;
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4, {});
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_EQ(NEO::KernelArgMetadata::AccessQualifier::ReadWrite, dst.kernelArgInfo[0].metadata.accessQualifier);
|
||||
}
|
||||
@@ -84,7 +84,7 @@ TEST(KernelInfoFromPatchTokens, GivenValidKernelWithNonDelimitedArgTypeThenUsesA
|
||||
PatchTokensTestData::ValidProgramWithKernelAndArg src;
|
||||
src.arg0TypeMutable[4] = '*';
|
||||
NEO::KernelInfo dst = {};
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4, {});
|
||||
NEO::populateKernelInfo(dst, src.kernels[0], 4);
|
||||
ASSERT_EQ(1U, dst.kernelArgInfo.size());
|
||||
EXPECT_STREQ("int**", dst.kernelArgInfo[0].metadataExtended->type.c_str());
|
||||
}
|
||||
@@ -96,7 +96,7 @@ TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWithEmptySizeThenTokenIs
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 0U;
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4, {});
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
EXPECT_EQ(nullptr, dst.crossThreadData);
|
||||
}
|
||||
|
||||
@@ -107,7 +107,7 @@ TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWithNonEmptySizeThenCros
|
||||
src.tokens.dataParameterStream = &dataParameterStream;
|
||||
dataParameterStream.DataParameterStreamSize = 256U;
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4, {});
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
EXPECT_NE(nullptr, dst.crossThreadData);
|
||||
}
|
||||
|
||||
@@ -147,8 +147,9 @@ TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWhenTokensRequiringDevic
|
||||
src.tokens.crossThreadPayloadArgs.maxWorkGroupSize = &maxWorkgroupSize;
|
||||
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4, deviceInfoConstants);
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
ASSERT_NE(nullptr, dst.crossThreadData);
|
||||
dst.apply(deviceInfoConstants);
|
||||
uint32_t expectedPrivateMemorySize = privateSurface.PerThreadPrivateMemorySize * deviceInfoConstants.computeUnitsUsedForScratch * src.tokens.executionEnvironment->LargestCompiledSIMDSize;
|
||||
EXPECT_EQ(expectedPrivateMemorySize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + privateMemorySize.Offset));
|
||||
EXPECT_EQ(deviceInfoConstants.slmWindowSize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + localMemoryWindowsSize.Offset));
|
||||
@@ -176,8 +177,9 @@ TEST(KernelInfoFromPatchTokens, GivenDataParameterStreamWhenPrivateSurfaceIsNotA
|
||||
src.tokens.crossThreadPayloadArgs.privateMemoryStatelessSize = &privateMemorySize;
|
||||
|
||||
NEO::KernelInfo dst;
|
||||
NEO::populateKernelInfo(dst, src, 4, deviceInfoConstants);
|
||||
NEO::populateKernelInfo(dst, src, 4);
|
||||
ASSERT_NE(nullptr, dst.crossThreadData);
|
||||
dst.apply(deviceInfoConstants);
|
||||
uint32_t expectedPrivateMemorySize = 0U;
|
||||
EXPECT_EQ(expectedPrivateMemorySize, *reinterpret_cast<uint32_t *>(dst.crossThreadData + privateMemorySize.Offset));
|
||||
}
|
||||
@@ -191,7 +193,7 @@ TEST(KernelInfoFromPatchTokens, GivenKernelWithGtpinInfoTokenThenKernelInfoIsPro
|
||||
kernelTokens.tokens.gtpinInfo = >pinInfo;
|
||||
|
||||
NEO::KernelInfo kernelInfo = {};
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(uintptr_t), {});
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(void *));
|
||||
EXPECT_NE(nullptr, kernelInfo.igcInfoForGtpin);
|
||||
}
|
||||
|
||||
@@ -208,7 +210,7 @@ TEST(KernelInfoFromPatchTokens, GivenKernelWithGlobalObjectArgThenKernelInfoIsPr
|
||||
kernelTokens.tokens.kernelArgs.resize(2);
|
||||
kernelTokens.tokens.kernelArgs[1].objectArg = &globalMemArg;
|
||||
NEO::KernelInfo kernelInfo = {};
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(uintptr_t), {});
|
||||
NEO::populateKernelInfo(kernelInfo, kernelTokens, sizeof(void *));
|
||||
EXPECT_TRUE(kernelInfo.usesSsh);
|
||||
EXPECT_EQ(1U, kernelInfo.argumentsToPatchNum);
|
||||
ASSERT_EQ(2U, kernelInfo.kernelArgInfo.size());
|
||||
|
||||
@@ -6,10 +6,14 @@
|
||||
*/
|
||||
|
||||
#include "core/device/device.h"
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/device_binary_format/elf/elf.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/helpers/file_io.h"
|
||||
#include "core/helpers/string.h"
|
||||
#include "core/unit_tests/device_binary_format/patchtokens_tests.h"
|
||||
#include "unit_tests/helpers/test_files.h"
|
||||
#include "unit_tests/mocks/mock_device.h"
|
||||
#include "unit_tests/mocks/mock_program.h"
|
||||
|
||||
#include "compiler_options.h"
|
||||
@@ -22,52 +26,44 @@ using namespace NEO;
|
||||
class ProcessElfBinaryTests : public ::testing::Test {
|
||||
public:
|
||||
void SetUp() override {
|
||||
executionEnvironment = std::make_unique<ExecutionEnvironment>();
|
||||
program = std::make_unique<MockProgram>(*executionEnvironment);
|
||||
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
program->pDevice = device.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<ExecutionEnvironment> executionEnvironment;
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<ClDevice> device;
|
||||
};
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, NullBinary) {
|
||||
uint32_t binaryVersion;
|
||||
cl_int retVal = program->processElfBinary(nullptr, 0, binaryVersion);
|
||||
|
||||
cl_int retVal = program->createProgramFromBinary(nullptr, 0);
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, InvalidBinary) {
|
||||
uint32_t binaryVersion;
|
||||
char pBinary[] = "thisistotallyinvalid\0";
|
||||
size_t binarySize = strnlen_s(pBinary, 21);
|
||||
cl_int retVal = program->processElfBinary(pBinary, binarySize, binaryVersion);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary, binarySize);
|
||||
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, ValidBinary) {
|
||||
uint32_t binaryVersion;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd8_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->elfBinary.data(), binarySize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
|
||||
//clCreateProgramWithIL => SPIR-V stored as source code
|
||||
const uint32_t spirvBinary[2] = {0x03022307, 0x07230203};
|
||||
size_t spirvBinarySize = sizeof(spirvBinary);
|
||||
auto isSpirV = Program::isValidSpirvBinary(spirvBinary, spirvBinarySize);
|
||||
EXPECT_TRUE(isSpirV);
|
||||
|
||||
//clCompileProgram => SPIR-V stored as IR binary
|
||||
program->isSpirV = true;
|
||||
@@ -79,21 +75,22 @@ TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
|
||||
EXPECT_TRUE(program->getIsSpirV());
|
||||
|
||||
//clGetProgramInfo => SPIR-V stored as ELF binary
|
||||
cl_int retVal = program->resolveProgramBinary();
|
||||
cl_int retVal = program->packDeviceBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_FALSE(program->elfBinary.empty());
|
||||
EXPECT_NE(0u, program->elfBinarySize);
|
||||
EXPECT_NE(nullptr, program->packedDeviceBinary);
|
||||
EXPECT_NE(0u, program->packedDeviceBinarySize);
|
||||
|
||||
//use ELF reader to parse and validate ELF binary
|
||||
CLElfLib::CElfReader elfReader(program->elfBinary);
|
||||
const CLElfLib::SElf64Header *elf64Header = elfReader.getElfHeader();
|
||||
ASSERT_NE(nullptr, elf64Header);
|
||||
EXPECT_EQ(elf64Header->Type, CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_LIBRARY);
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(program->packedDeviceBinary.get()), program->packedDeviceBinarySize), decodeErrors, decodeWarnings);
|
||||
auto header = elf.elfFileHeader;
|
||||
ASSERT_NE(nullptr, header);
|
||||
|
||||
//check if ELF binary contains section SH_TYPE_SPIRV
|
||||
//check if ELF binary contains section SECTION_HEADER_TYPE_SPIRV
|
||||
bool hasSpirvSection = false;
|
||||
for (const auto &elfSectionHeader : elfReader.getSectionHeaders()) {
|
||||
if (elfSectionHeader.Type == CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV) {
|
||||
for (const auto &elfSectionHeader : elf.sectionHeaders) {
|
||||
if (elfSectionHeader.header->type == NEO::Elf::SHT_OPENCL_SPIRV) {
|
||||
hasSpirvSection = true;
|
||||
break;
|
||||
}
|
||||
@@ -102,10 +99,8 @@ TEST_F(ProcessElfBinaryTests, ValidSpirvBinary) {
|
||||
|
||||
//clCreateProgramWithBinary => new program should recognize SPIR-V binary
|
||||
program->isSpirV = false;
|
||||
uint32_t elfBinaryVersion;
|
||||
auto pElfBinary = std::unique_ptr<char>(new char[program->elfBinarySize]);
|
||||
memcpy_s(pElfBinary.get(), program->elfBinarySize, program->elfBinary.data(), program->elfBinarySize);
|
||||
retVal = program->processElfBinary(pElfBinary.get(), program->elfBinarySize, elfBinaryVersion);
|
||||
auto elfBinary = makeCopy(program->packedDeviceBinary.get(), program->packedDeviceBinarySize);
|
||||
retVal = program->createProgramFromBinary(elfBinary.get(), program->packedDeviceBinarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_TRUE(program->getIsSpirV());
|
||||
}
|
||||
@@ -118,49 +113,71 @@ unsigned int BinaryTypeValues[] = {
|
||||
class ProcessElfBinaryTestsWithBinaryType : public ::testing::TestWithParam<unsigned int> {
|
||||
public:
|
||||
void SetUp() override {
|
||||
executionEnvironment = std::make_unique<ExecutionEnvironment>();
|
||||
program = std::make_unique<MockProgram>(*executionEnvironment);
|
||||
device = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
program = std::make_unique<MockProgram>(*device->getExecutionEnvironment());
|
||||
program->pDevice = device.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<ExecutionEnvironment> executionEnvironment;
|
||||
std::unique_ptr<MockProgram> program;
|
||||
std::unique_ptr<ClDevice> device;
|
||||
};
|
||||
|
||||
TEST_P(ProcessElfBinaryTestsWithBinaryType, GivenBinaryTypeWhenResolveProgramThenProgramIsProperlyResolved) {
|
||||
uint32_t binaryVersion;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd8_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
|
||||
const auto &options = program->getOptions();
|
||||
size_t optionsSize = strlen(options.c_str()) + 1;
|
||||
auto pTmpGenBinary = new char[program->genBinarySize];
|
||||
auto pTmpIrBinary = new char[program->irBinarySize];
|
||||
auto pTmpOptions = new char[optionsSize];
|
||||
|
||||
memcpy_s(pTmpGenBinary, program->genBinarySize, program->genBinary.get(), program->genBinarySize);
|
||||
memcpy_s(pTmpIrBinary, program->irBinarySize, program->irBinary.get(), program->irBinarySize);
|
||||
memcpy_s(pTmpOptions, optionsSize, options.c_str(), optionsSize);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
auto options = program->options;
|
||||
auto genBinary = makeCopy(program->unpackedDeviceBinary.get(), program->unpackedDeviceBinarySize);
|
||||
auto genBinarySize = program->unpackedDeviceBinarySize;
|
||||
auto irBinary = makeCopy(program->irBinary.get(), program->irBinarySize);
|
||||
auto irBinarySize = program->irBinarySize;
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->elfBinary.data(), binarySize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
ASSERT_EQ(binarySize, program->packedDeviceBinarySize);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
|
||||
// delete program's elf reference to force a resolve
|
||||
program->isProgramBinaryResolved = false;
|
||||
program->packedDeviceBinary.reset();
|
||||
program->packedDeviceBinarySize = 0U;
|
||||
program->programBinaryType = GetParam();
|
||||
retVal = program->resolveProgramBinary();
|
||||
retVal = program->packDeviceBinary();
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pTmpGenBinary, program->genBinary.get(), program->genBinarySize));
|
||||
EXPECT_EQ(0, memcmp(pTmpIrBinary, program->irBinary.get(), program->irBinarySize));
|
||||
EXPECT_EQ(0, memcmp(pTmpOptions, options.c_str(), optionsSize));
|
||||
ASSERT_NE(nullptr, program->packedDeviceBinary);
|
||||
|
||||
delete[] pTmpGenBinary;
|
||||
delete[] pTmpIrBinary;
|
||||
delete[] pTmpOptions;
|
||||
std::string decodeErrors;
|
||||
std::string decodeWarnings;
|
||||
auto elf = NEO::Elf::decodeElf(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(program->packedDeviceBinary.get()), program->packedDeviceBinarySize), decodeErrors, decodeWarnings);
|
||||
ASSERT_NE(nullptr, elf.elfFileHeader);
|
||||
ArrayRef<const uint8_t> decodedIr;
|
||||
ArrayRef<const uint8_t> decodedDeviceBinary;
|
||||
ArrayRef<const uint8_t> decodedOptions;
|
||||
for (auto §ion : elf.sectionHeaders) {
|
||||
switch (section.header->type) {
|
||||
default:
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_LLVM_BINARY:
|
||||
decodedIr = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_SPIRV:
|
||||
decodedIr = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_DEV_BINARY:
|
||||
decodedDeviceBinary = section.data;
|
||||
break;
|
||||
case NEO::Elf::SHT_OPENCL_OPTIONS:
|
||||
decodedDeviceBinary = section.data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT_EQ(options.size(), decodedOptions.size());
|
||||
ASSERT_EQ(genBinarySize, decodedDeviceBinary.size());
|
||||
ASSERT_EQ(irBinarySize, decodedIr.size());
|
||||
|
||||
EXPECT_EQ(0, memcmp(genBinary.get(), decodedDeviceBinary.begin(), genBinarySize));
|
||||
EXPECT_EQ(0, memcmp(irBinary.get(), decodedIr.begin(), irBinarySize));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ResolveBinaryTests,
|
||||
@@ -168,85 +185,72 @@ INSTANTIATE_TEST_CASE_P(ResolveBinaryTests,
|
||||
::testing::ValuesIn(BinaryTypeValues));
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BackToBack) {
|
||||
uint32_t binaryVersion;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd8_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->elfBinary.data(), binarySize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
|
||||
std::string filePath2;
|
||||
retrieveBinaryKernelFilename(filePath2, "simple_arg_int_", ".bin");
|
||||
|
||||
pBinary = loadDataFromFile(filePath2.c_str(), binarySize);
|
||||
retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->elfBinary.data(), binarySize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
EXPECT_EQ(0, memcmp(pBinary.get(), program->packedDeviceBinary.get(), binarySize));
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BuildOptionsEmpty) {
|
||||
uint32_t binaryVersion;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "simple_kernels_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
const auto &options = program->getOptions();
|
||||
size_t optionsSize = strlen(options.c_str()) + 1;
|
||||
EXPECT_EQ(0, memcmp("", options.c_str(), optionsSize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, BuildOptionsNotEmpty) {
|
||||
uint32_t binaryVersion;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "simple_kernels_opts_", ".bin");
|
||||
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
cl_int retVal = program->processElfBinary(pBinary.get(), binarySize, binaryVersion);
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
const auto &options = program->getOptions();
|
||||
size_t optionsSize = strlen(options.c_str()) + 1;
|
||||
std::string buildOptionsNotEmpty = CompilerOptions::concatenate(CompilerOptions::optDisable, "-DDEF_WAS_SPECIFIED=1");
|
||||
EXPECT_EQ(0, memcmp(buildOptionsNotEmpty.c_str(), options.c_str(), optionsSize));
|
||||
EXPECT_NE(0u, binaryVersion);
|
||||
EXPECT_STREQ(buildOptionsNotEmpty.c_str(), options.c_str());
|
||||
}
|
||||
|
||||
TEST_F(ProcessElfBinaryTests, GivenBinaryWhenInvalidCURRENT_ICBE_VERSIONThenInvalidCURRENT_ICBE_VERSIONTIsReturned) {
|
||||
uint32_t binaryVersion;
|
||||
CLElfLib::ElfBinaryStorage elfBinary;
|
||||
|
||||
CLElfLib::CElfWriter elfWriter(CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE, CLElfLib::E_EH_MACHINE::EH_MACHINE_NONE, 0);
|
||||
|
||||
char *genBinary;
|
||||
size_t genBinarySize = sizeof(SProgramBinaryHeader);
|
||||
SProgramBinaryHeader genBinaryHeader = {0};
|
||||
genBinaryHeader.Magic = iOpenCL::MAGIC_CL;
|
||||
genBinaryHeader.Version = iOpenCL::CURRENT_ICBE_VERSION - 3u;
|
||||
genBinary = reinterpret_cast<char *>(&genBinaryHeader);
|
||||
|
||||
if (genBinary) {
|
||||
std::string genBinaryTemp = genBinary ? std::string(genBinary, genBinarySize) : "";
|
||||
elfWriter.addSection(CLElfLib::SSectionNode(CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY, CLElfLib::E_SH_FLAG::SH_FLAG_NONE, "Intel(R) OpenCL Device Binary", std::move(genBinaryTemp), static_cast<uint32_t>(genBinarySize)));
|
||||
TEST_F(ProcessElfBinaryTests, GivenBinaryWhenIncompatiblePatchtokenVerionThenProramCreationFails) {
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
{
|
||||
NEO::Elf::ElfEncoder<> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, programTokens.storage);
|
||||
auto elfBinary = elfEncoder.encode();
|
||||
cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
elfBinary.resize(elfWriter.getTotalBinarySize());
|
||||
elfWriter.resolveBinary(elfBinary);
|
||||
|
||||
cl_int retVal = program->processElfBinary(elfBinary.data(), elfBinary.size(), binaryVersion);
|
||||
|
||||
{
|
||||
programTokens.headerMutable->Version -= 1;
|
||||
NEO::Elf::ElfEncoder<> elfEncoder;
|
||||
elfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE;
|
||||
elfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, NEO::Elf::SectionNamesOpenCl::deviceBinary, programTokens.storage);
|
||||
auto elfBinary = elfEncoder.encode();
|
||||
cl_int retVal = program->createProgramFromBinary(elfBinary.data(), elfBinary.size());
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
EXPECT_EQ(binaryVersion, iOpenCL::CURRENT_ICBE_VERSION - 3u);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,8 +153,8 @@ void ProgramDataTestBase::buildAndDecodeProgramPatchList() {
|
||||
pCurPtr += programPatchListSize;
|
||||
|
||||
//as we use mock compiler in unit test, replace the genBinary here.
|
||||
pProgram->genBinary = makeCopy(pProgramData, headerSize + programBinaryHeader.PatchListSize);
|
||||
pProgram->genBinarySize = headerSize + programBinaryHeader.PatchListSize;
|
||||
pProgram->unpackedDeviceBinary = makeCopy(pProgramData, headerSize + programBinaryHeader.PatchListSize);
|
||||
pProgram->unpackedDeviceBinarySize = headerSize + programBinaryHeader.PatchListSize;
|
||||
|
||||
error = pProgram->processGenBinary();
|
||||
patchlistDecodeErrorCode = error;
|
||||
@@ -401,7 +401,7 @@ TEST(ProgramScopeMetadataTest, WhenPatchingGlobalSurfaceThenPickProperSourceBuff
|
||||
ProgramInfo programInfo;
|
||||
MockProgram program(execEnv);
|
||||
program.pDevice = &device;
|
||||
NEO::populateProgramInfo(programInfo, decodedProgram, DeviceInfoKernelPayloadConstants{});
|
||||
NEO::populateProgramInfo(programInfo, decodedProgram);
|
||||
program.processProgramInfo(programInfo);
|
||||
ASSERT_NE(nullptr, program.globalSurface);
|
||||
ASSERT_NE(nullptr, program.constantSurface);
|
||||
@@ -476,7 +476,6 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPoi
|
||||
uint32_t sentinel = 0x17192329U;
|
||||
globalSurfaceStorage[0] = 0U;
|
||||
globalSurfaceStorage[1] = sentinel;
|
||||
this->pProgram->skipValidationOfBinary = true;
|
||||
|
||||
pProgram->linkerInput = std::move(programInfo.linkerInput);
|
||||
pProgram->linkBinary();
|
||||
|
||||
@@ -7,8 +7,10 @@
|
||||
|
||||
#include "unit_tests/program/program_tests.h"
|
||||
|
||||
#include "core/compiler_interface/intermediate_representations.h"
|
||||
#include "core/device_binary_format/elf/elf_decoder.h"
|
||||
#include "core/device_binary_format/elf/ocl_elf.h"
|
||||
#include "core/device_binary_format/patchtokens_decoder.h"
|
||||
#include "core/elf/reader.h"
|
||||
#include "core/gmm_helper/gmm_helper.h"
|
||||
#include "core/helpers/aligned_memory.h"
|
||||
#include "core/helpers/hash.h"
|
||||
@@ -1509,61 +1511,7 @@ TEST(ProgramFromBinaryTests, givenBinaryWithInvalidICBEThenErrorIsReturned) {
|
||||
}
|
||||
}
|
||||
|
||||
class FailProgram : public Program {
|
||||
public:
|
||||
FailProgram(ExecutionEnvironment &executionEnvironment, Context *context, bool isBuiltIn = false) : Program(executionEnvironment, context, isBuiltIn) {}
|
||||
cl_int rebuildProgramFromIr() override {
|
||||
return CL_INVALID_PROGRAM;
|
||||
}
|
||||
// make method visible
|
||||
cl_int createProgramFromBinary(const void *pBinary, size_t binarySize) override {
|
||||
return Program::createProgramFromBinary(pBinary, binarySize);
|
||||
}
|
||||
cl_int processElfBinary(const void *pBinary, size_t binarySize, uint32_t &binaryVersion) override {
|
||||
binaryVersion--;
|
||||
// we should return anything but not CL_SUCCESS
|
||||
return CL_INVALID_BINARY;
|
||||
}
|
||||
};
|
||||
|
||||
TEST(ProgramFromBinaryTests, CreateWithBinary_FailRecompile) {
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
SProgramBinaryHeader binHeader;
|
||||
memset(&binHeader, 0, sizeof(binHeader));
|
||||
binHeader.Magic = iOpenCL::MAGIC_CL;
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
binHeader.Device = platformDevices[0]->platform.eRenderCoreFamily;
|
||||
binHeader.GPUPointerSizeInBytes = 8;
|
||||
binHeader.NumberOfKernels = 0;
|
||||
binHeader.SteppingId = 0;
|
||||
binHeader.PatchListSize = 0;
|
||||
size_t binSize = sizeof(SProgramBinaryHeader);
|
||||
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
std::unique_ptr<FailProgram> pProgram(FailProgram::createFromGenBinary<FailProgram>(executionEnvironment, nullptr, &binHeader, binSize, false, &retVal));
|
||||
ASSERT_NE(nullptr, pProgram.get());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION - 1;
|
||||
retVal = pProgram->createProgramFromBinary(&binHeader, binSize);
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
}
|
||||
|
||||
TEST(ProgramFromBinaryTests, givenEmptyProgramThenErrorIsReturned) {
|
||||
class TestedProgram : public Program {
|
||||
public:
|
||||
TestedProgram(ExecutionEnvironment &executionEnvironment, Context *context, bool isBuiltIn) : Program(executionEnvironment, context, isBuiltIn) {}
|
||||
char *setGenBinary(char *binary) {
|
||||
auto res = genBinary.get();
|
||||
genBinary.release();
|
||||
genBinary.reset(binary);
|
||||
return res;
|
||||
}
|
||||
void setGenBinarySize(size_t size) {
|
||||
genBinarySize = size;
|
||||
}
|
||||
};
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
SProgramBinaryHeader binHeader;
|
||||
@@ -1578,14 +1526,13 @@ TEST(ProgramFromBinaryTests, givenEmptyProgramThenErrorIsReturned) {
|
||||
size_t binSize = sizeof(SProgramBinaryHeader);
|
||||
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
std::unique_ptr<TestedProgram> pProgram(TestedProgram::createFromGenBinary<TestedProgram>(executionEnvironment, nullptr, &binHeader, binSize, false, &retVal));
|
||||
std::unique_ptr<MockProgram> pProgram(MockProgram::createFromGenBinary<MockProgram>(executionEnvironment, nullptr, &binHeader, binSize, false, &retVal));
|
||||
ASSERT_NE(nullptr, pProgram.get());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
auto originalPtr = pProgram->setGenBinary(nullptr);
|
||||
pProgram->unpackedDeviceBinary.reset(nullptr);
|
||||
retVal = pProgram->processGenBinary();
|
||||
EXPECT_EQ(CL_INVALID_BINARY, retVal);
|
||||
pProgram->setGenBinary(originalPtr);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(ProgramFromBinaryTests,
|
||||
@@ -1942,64 +1889,13 @@ TEST_F(ProgramTests, givenProgramFromGenBinaryWhenSLMSizeIsBiggerThenDeviceLimit
|
||||
patchtokensProgram.slmMutable->TotalInlineLocalMemorySize = static_cast<uint32_t>(pDevice->getDeviceInfo().localMemSize * 2);
|
||||
patchtokensProgram.recalcTokPtr();
|
||||
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment(), nullptr, false);
|
||||
program->genBinary = makeCopy(patchtokensProgram.storage.data(), patchtokensProgram.storage.size());
|
||||
program->genBinarySize = patchtokensProgram.storage.size();
|
||||
program->unpackedDeviceBinary = makeCopy(patchtokensProgram.storage.data(), patchtokensProgram.storage.size());
|
||||
program->unpackedDeviceBinarySize = patchtokensProgram.storage.size();
|
||||
auto retVal = program->processGenBinary();
|
||||
|
||||
EXPECT_EQ(CL_OUT_OF_RESOURCES, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, ValidBinaryWithIGCVersionEqual0) {
|
||||
cl_int retVal;
|
||||
|
||||
auto program = std::make_unique<MockProgram>(*pDevice->getExecutionEnvironment());
|
||||
EXPECT_NE(nullptr, program);
|
||||
cl_device_id deviceId = pContext->getDevice(0);
|
||||
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
|
||||
program->setDevice(pDevice);
|
||||
|
||||
// Load a binary program file
|
||||
size_t binarySize = 0;
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd8_", ".bin");
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
EXPECT_NE(0u, binarySize);
|
||||
program->elfBinary = CLElfLib::ElfBinaryStorage(pBinary.get(), pBinary.get() + binarySize);
|
||||
|
||||
// Find its OpenCL program data and mark that the data were created with unknown compiler version,
|
||||
// which means that the program has to be rebuild from its IR binary
|
||||
CLElfLib::CElfReader elfReader(program->elfBinary);
|
||||
const CLElfLib::SElf64Header *elf64Header = elfReader.getElfHeader();
|
||||
char *pSectionData = nullptr;
|
||||
SProgramBinaryHeader *pBHdr = nullptr;
|
||||
EXPECT_NE(nullptr, elf64Header);
|
||||
EXPECT_EQ(elf64Header->Type, CLElfLib::E_EH_TYPE::EH_TYPE_OPENCL_EXECUTABLE);
|
||||
|
||||
for (const auto &elfHeaderSection : elfReader.getSectionHeaders()) {
|
||||
if (elfHeaderSection.Type != CLElfLib::E_SH_TYPE::SH_TYPE_OPENCL_DEV_BINARY) {
|
||||
continue;
|
||||
}
|
||||
pSectionData = elfReader.getSectionData(elfHeaderSection.DataOffset);
|
||||
EXPECT_NE(nullptr, pSectionData);
|
||||
EXPECT_NE(0u, elfHeaderSection.DataSize);
|
||||
pBHdr = (SProgramBinaryHeader *)pSectionData;
|
||||
pBHdr->Version = 0; // Simulate compiler Version = 0
|
||||
break;
|
||||
}
|
||||
EXPECT_NE(nullptr, pBHdr);
|
||||
|
||||
// Create program from modified binary, is should be successfully rebuilt
|
||||
retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Get IR binary and modify its header magic,
|
||||
// then ask to rebuild program from its IR binary - it should fail
|
||||
char *pIrBinary = program->irBinary.get();
|
||||
(*pIrBinary)--;
|
||||
retVal = program->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_INVALID_PROGRAM, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, RebuildBinaryButNoCompilerInterface) {
|
||||
auto noCompilerInterfaceExecutionEnvironment = std::make_unique<MockCompIfaceExecutionEnvironment>(nullptr);
|
||||
auto program = std::make_unique<MockProgram>(*noCompilerInterfaceExecutionEnvironment);
|
||||
@@ -2021,42 +1917,9 @@ TEST_F(ProgramTests, RebuildBinaryButNoCompilerInterface) {
|
||||
|
||||
// Ask to rebuild program from its IR binary - it should fail (no Compiler Interface)
|
||||
retVal = program->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_OUT_OF_HOST_MEMORY, retVal);
|
||||
EXPECT_NE(CL_SUCCESS, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, RebuildBinaryWithRebuildError) {
|
||||
class MyCompilerInterface : public CompilerInterface {
|
||||
public:
|
||||
MyCompilerInterface(){};
|
||||
~MyCompilerInterface() override{};
|
||||
|
||||
TranslationOutput::ErrorCode link(const NEO::Device &device, const TranslationInput &input, TranslationOutput &output) override {
|
||||
return TranslationOutput::ErrorCode::LinkFailure;
|
||||
}
|
||||
};
|
||||
|
||||
auto cip = std::make_unique<MyCompilerInterface>();
|
||||
MockCompIfaceExecutionEnvironment executionEnvironment(cip.get());
|
||||
auto program = std::make_unique<MockProgram>(executionEnvironment);
|
||||
cl_device_id deviceId = pContext->getDevice(0);
|
||||
ClDevice *pDevice = castToObject<ClDevice>(deviceId);
|
||||
program->setDevice(pDevice);
|
||||
|
||||
// Load a binary program file
|
||||
std::string filePath;
|
||||
retrieveBinaryKernelFilename(filePath, "CopyBuffer_simd8_", ".bin");
|
||||
size_t binarySize = 0;
|
||||
auto pBinary = loadDataFromFile(filePath.c_str(), binarySize);
|
||||
EXPECT_NE(0u, binarySize);
|
||||
|
||||
// Create program from loaded binary
|
||||
cl_int retVal = program->createProgramFromBinary(pBinary.get(), binarySize);
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
// Ask to rebuild program from its IR binary - it should fail (linking error)
|
||||
retVal = program->rebuildProgramFromIr();
|
||||
EXPECT_EQ(CL_LINK_PROGRAM_FAILURE, retVal);
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, BuildProgramWithReraFlag) {
|
||||
auto cip = std::make_unique<MockCompilerInterfaceCaptureBuildOptions>();
|
||||
@@ -2373,44 +2236,44 @@ TEST_F(ProgramTests, createFromILWhenCreatingProgramFromBinaryThenProperFlagIsSi
|
||||
prog->release();
|
||||
}
|
||||
|
||||
static const char llvmBinary[] = "BC\xc0\xde ";
|
||||
static const uint8_t llvmBinary[] = "BC\xc0\xde ";
|
||||
|
||||
TEST(isValidLlvmBinary, whenLlvmMagicWasFoundThenBinaryIsValidLLvm) {
|
||||
EXPECT_TRUE(Program::isValidLlvmBinary(llvmBinary, sizeof(llvmBinary)));
|
||||
EXPECT_TRUE(NEO::isLlvmBitcode(llvmBinary));
|
||||
}
|
||||
|
||||
TEST(isValidLlvmBinary, whenBinaryIsNullptrThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(Program::isValidLlvmBinary(nullptr, sizeof(llvmBinary)));
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(isValidLlvmBinary, whenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(Program::isValidLlvmBinary(llvmBinary, 2));
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(ArrayRef<const uint8_t>(llvmBinary, 2)));
|
||||
}
|
||||
|
||||
TEST(isValidLlvmBinary, whenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
char notLlvmBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(Program::isValidLlvmBinary(notLlvmBinary, sizeof(notLlvmBinary)));
|
||||
const uint8_t notLlvmBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isLlvmBitcode(notLlvmBinary));
|
||||
}
|
||||
|
||||
const uint32_t spirv[16] = {0x03022307};
|
||||
const uint32_t spirvInvEndianes[16] = {0x07230203};
|
||||
|
||||
TEST(isValidSpirvBinary, whenSpirvMagicWasFoundThenBinaryIsValidSpirv) {
|
||||
EXPECT_TRUE(Program::isValidSpirvBinary(spirv, sizeof(spirv)));
|
||||
EXPECT_TRUE(Program::isValidSpirvBinary(spirvInvEndianes, sizeof(spirvInvEndianes)));
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirv), sizeof(spirv))));
|
||||
EXPECT_TRUE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), sizeof(spirvInvEndianes))));
|
||||
}
|
||||
|
||||
TEST(isValidSpirvBinary, whenBinaryIsNullptrThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(Program::isValidSpirvBinary(nullptr, sizeof(spirv)));
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>()));
|
||||
}
|
||||
|
||||
TEST(isValidSpirvBinary, whenBinaryIsShorterThanLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
EXPECT_FALSE(Program::isValidSpirvBinary(spirv, 2));
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(&spirvInvEndianes), 2)));
|
||||
}
|
||||
|
||||
TEST(isValidSpirvBinary, whenBinaryDoesNotContainLllvMagicThenBinaryIsNotValidLLvm) {
|
||||
char notSpirvBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(Program::isValidSpirvBinary(notSpirvBinary, sizeof(notSpirvBinary)));
|
||||
const uint8_t notSpirvBinary[] = "ABCDEFGHIJKLMNO";
|
||||
EXPECT_FALSE(NEO::isSpirVBitcode(notSpirvBinary));
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, linkingTwoValidSpirvProgramsReturnsValidProgram) {
|
||||
@@ -2622,20 +2485,11 @@ TEST_F(ProgramTests, givenProgramWithSpirvWhenRebuildProgramIsCalledThenSpirvPat
|
||||
program->isSpirV = true;
|
||||
auto buildRet = program->rebuildProgramFromIr();
|
||||
EXPECT_NE(CL_SUCCESS, buildRet);
|
||||
|
||||
CLElfLib::ElfBinaryStorage elfBin(receivedInput.begin(), receivedInput.end());
|
||||
CLElfLib::CElfReader elfReader(elfBin);
|
||||
|
||||
char *spvSectionData = nullptr;
|
||||
size_t spvSectionDataSize = 0;
|
||||
for (const auto &elfSectionHeader : elfReader.getSectionHeaders()) {
|
||||
if (elfSectionHeader.Type == CLElfLib::E_SH_TYPE::SH_TYPE_SPIRV) {
|
||||
spvSectionData = elfReader.getSectionData(elfSectionHeader.DataOffset);
|
||||
spvSectionDataSize = static_cast<size_t>(elfSectionHeader.DataSize);
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(sizeof(spirv), spvSectionDataSize);
|
||||
EXPECT_EQ(0, memcmp(spirv, spvSectionData, spvSectionDataSize));
|
||||
ASSERT_EQ(sizeof(spirv), receivedInput.size());
|
||||
EXPECT_EQ(0, memcmp(spirv, receivedInput.c_str(), receivedInput.size()));
|
||||
ASSERT_EQ(1U, compilerInterface->requestedTranslationCtxs.size());
|
||||
EXPECT_EQ(IGC::CodeType::spirV, compilerInterface->requestedTranslationCtxs[0].first);
|
||||
EXPECT_EQ(IGC::CodeType::oclGenBin, compilerInterface->requestedTranslationCtxs[0].second);
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, whenRebuildingProgramThenStoreDeviceBinaryProperly) {
|
||||
@@ -2659,12 +2513,12 @@ TEST_F(ProgramTests, whenRebuildingProgramThenStoreDeviceBinaryProperly) {
|
||||
uint32_t ir[16] = {0x03022307, 0x23471113, 0x17192329};
|
||||
program->irBinary = makeCopy(ir, sizeof(ir));
|
||||
program->irBinarySize = sizeof(ir);
|
||||
EXPECT_EQ(nullptr, program->genBinary);
|
||||
EXPECT_EQ(0U, program->genBinarySize);
|
||||
EXPECT_EQ(nullptr, program->unpackedDeviceBinary);
|
||||
EXPECT_EQ(0U, program->unpackedDeviceBinarySize);
|
||||
program->rebuildProgramFromIr();
|
||||
ASSERT_NE(nullptr, program->genBinary);
|
||||
ASSERT_EQ(sizeof(binaryToReturn), program->genBinarySize);
|
||||
EXPECT_EQ(0, memcmp(binaryToReturn, program->genBinary.get(), program->genBinarySize));
|
||||
ASSERT_NE(nullptr, program->unpackedDeviceBinary);
|
||||
ASSERT_EQ(sizeof(binaryToReturn), program->unpackedDeviceBinarySize);
|
||||
EXPECT_EQ(0, memcmp(binaryToReturn, program->unpackedDeviceBinary.get(), program->unpackedDeviceBinarySize));
|
||||
}
|
||||
|
||||
TEST_F(ProgramTests, givenProgramWhenInternalOptionsArePassedThenTheyAreAddedToProgramInternalOptions) {
|
||||
@@ -2672,7 +2526,7 @@ TEST_F(ProgramTests, givenProgramWhenInternalOptionsArePassedThenTheyAreAddedToP
|
||||
MockProgram program(executionEnvironment);
|
||||
program.getInternalOptions().erase();
|
||||
EXPECT_EQ(nullptr, program.getDevicePtr());
|
||||
std::string buildOptions(NEO::CompilerOptions::gtpinRera);
|
||||
std::string buildOptions = NEO::CompilerOptions::gtpinRera.str();
|
||||
program.extractInternalOptions(buildOptions);
|
||||
EXPECT_STREQ(program.getInternalOptions().c_str(), NEO::CompilerOptions::gtpinRera.data());
|
||||
}
|
||||
@@ -2756,73 +2610,44 @@ TEST_F(ProgramTests, givenProgramWhenBuiltThenAdditionalOptionsAreApplied) {
|
||||
EXPECT_EQ(1u, program.applyAdditionalOptionsCalled);
|
||||
}
|
||||
|
||||
struct RebuildProgram : public Program {
|
||||
using Program::createProgramFromBinary;
|
||||
RebuildProgram(ExecutionEnvironment &executionEnvironment, Context *context, bool isBuiltIn = false) : Program(executionEnvironment, context, isBuiltIn) {}
|
||||
cl_int rebuildProgramFromIr() override {
|
||||
rebuildProgramFromIrCalled = true;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
cl_int processElfBinary(const void *pBinary, size_t binarySize, uint32_t &binaryVersion) override {
|
||||
processElfBinaryCalled = true;
|
||||
return CL_SUCCESS;
|
||||
}
|
||||
bool rebuildProgramFromIrCalled = false;
|
||||
bool processElfBinaryCalled = false;
|
||||
};
|
||||
|
||||
TEST(RebuildProgramFromIrTests, givenBinaryProgramWhenKernelRebulildIsForcedThenRebuildProgramFromIrCalled) {
|
||||
TEST(CreateProgramFromBinaryTests, givenBinaryProgramWhenKernelRebulildIsForcedThenDeviceBinaryIsNotUsed) {
|
||||
DebugManagerStateRestore dbgRestorer;
|
||||
DebugManager.flags.RebuildPrecompiledKernels.set(true);
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
SProgramBinaryHeader binHeader;
|
||||
memset(&binHeader, 0, sizeof(binHeader));
|
||||
binHeader.Magic = iOpenCL::MAGIC_CL;
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
binHeader.Device = platformDevices[0]->platform.eRenderCoreFamily;
|
||||
binHeader.GPUPointerSizeInBytes = 8;
|
||||
binHeader.NumberOfKernels = 0;
|
||||
binHeader.SteppingId = 0;
|
||||
binHeader.PatchListSize = 0;
|
||||
size_t binSize = sizeof(SProgramBinaryHeader);
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
std::unique_ptr<RebuildProgram> pProgram(RebuildProgram::createFromGenBinary<RebuildProgram>(executionEnvironment, nullptr, &binHeader, binSize, false, &retVal));
|
||||
auto clDevice = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
std::unique_ptr<MockProgram> pProgram(Program::createFromGenBinary<MockProgram>(*clDevice->getExecutionEnvironment(), nullptr, programTokens.storage.data(), programTokens.storage.size(), false, &retVal));
|
||||
pProgram->pDevice = clDevice.get();
|
||||
ASSERT_NE(nullptr, pProgram.get());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
retVal = pProgram->createProgramFromBinary(&binHeader, binSize);
|
||||
retVal = pProgram->createProgramFromBinary(programTokens.storage.data(), programTokens.storage.size());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_TRUE(pProgram->processElfBinaryCalled);
|
||||
EXPECT_TRUE(pProgram->rebuildProgramFromIrCalled);
|
||||
EXPECT_EQ(nullptr, pProgram->unpackedDeviceBinary.get());
|
||||
EXPECT_EQ(0U, pProgram->unpackedDeviceBinarySize);
|
||||
EXPECT_EQ(nullptr, pProgram->packedDeviceBinary);
|
||||
EXPECT_EQ(0U, pProgram->packedDeviceBinarySize);
|
||||
}
|
||||
|
||||
TEST(RebuildProgramFromIrTests, givenBinaryProgramWhenKernelRebulildIsNotForcedThenRebuildProgramFromIrNotCalled) {
|
||||
TEST(CreateProgramFromBinaryTests, givenBinaryProgramWhenKernelRebulildIsNotForcedThenDeviceBinaryIsUsed) {
|
||||
cl_int retVal = CL_INVALID_BINARY;
|
||||
|
||||
SProgramBinaryHeader binHeader;
|
||||
memset(&binHeader, 0, sizeof(binHeader));
|
||||
binHeader.Magic = iOpenCL::MAGIC_CL;
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
binHeader.Device = platformDevices[0]->platform.eRenderCoreFamily;
|
||||
binHeader.GPUPointerSizeInBytes = 8;
|
||||
binHeader.NumberOfKernels = 0;
|
||||
binHeader.SteppingId = 0;
|
||||
binHeader.PatchListSize = 0;
|
||||
size_t binSize = sizeof(SProgramBinaryHeader);
|
||||
PatchTokensTestData::ValidEmptyProgram programTokens;
|
||||
|
||||
ExecutionEnvironment executionEnvironment;
|
||||
std::unique_ptr<RebuildProgram> pProgram(RebuildProgram::createFromGenBinary<RebuildProgram>(executionEnvironment, nullptr, &binHeader, binSize, false, &retVal));
|
||||
auto clDevice = std::make_unique<MockClDevice>(MockDevice::createWithNewExecutionEnvironment<MockDevice>(nullptr));
|
||||
std::unique_ptr<MockProgram> pProgram(Program::createFromGenBinary<MockProgram>(*clDevice->getExecutionEnvironment(), nullptr, programTokens.storage.data(), programTokens.storage.size(), false, &retVal));
|
||||
pProgram->pDevice = clDevice.get();
|
||||
ASSERT_NE(nullptr, pProgram.get());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
|
||||
binHeader.Version = iOpenCL::CURRENT_ICBE_VERSION;
|
||||
retVal = pProgram->createProgramFromBinary(&binHeader, binSize);
|
||||
retVal = pProgram->createProgramFromBinary(programTokens.storage.data(), programTokens.storage.size());
|
||||
EXPECT_EQ(CL_SUCCESS, retVal);
|
||||
EXPECT_TRUE(pProgram->processElfBinaryCalled);
|
||||
EXPECT_FALSE(pProgram->rebuildProgramFromIrCalled);
|
||||
EXPECT_NE(nullptr, reinterpret_cast<uint8_t *>(pProgram->unpackedDeviceBinary.get()));
|
||||
EXPECT_EQ(programTokens.storage.size(), pProgram->unpackedDeviceBinarySize);
|
||||
EXPECT_NE(nullptr, reinterpret_cast<uint8_t *>(pProgram->packedDeviceBinary.get()));
|
||||
EXPECT_EQ(programTokens.storage.size(), pProgram->packedDeviceBinarySize);
|
||||
}
|
||||
|
||||
struct SpecializationConstantProgramMock : public MockProgram {
|
||||
|
||||
Reference in New Issue
Block a user