Zebin: return error on parsing empty vector entries in zeInfo

This commit prevents a yaml parsing error in case a data type is passed
after empty vetor type data entry with the same indendation. In this
case, a parsing error will be returned.
- Corrected .ze_info section in valid empty program (zebin mock)
- Minor ults refactor in order to use mock zebin program with valid
.ze_info

Related-To: NEO-6735
Signed-off-by: Kacper Nowak <kacper.nowak@intel.com>
This commit is contained in:
Kacper Nowak
2022-04-07 13:20:02 +00:00
committed by Compute-Runtime-Automation
parent 002e6d5205
commit 1a33fc0dc7
11 changed files with 74 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) 2020-2021 Intel Corporation
* Copyright (C) 2020-2022 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
@@ -340,9 +340,18 @@ void finalizeNode(NodeId nodeId, const TokensCache &tokens, NodesCache &outNodes
++node.numChildren;
}
bool isEmptyVector(const Token &token, size_t lineId, std::string &outError) {
if (isVectorDataType(token)) {
outError = constructYamlError(lineId, token.pos, token.pos + token.len, "Vector data type expects to have at least one value starting with -");
return false;
}
return true;
}
bool buildTree(const LinesCache &lines, const TokensCache &tokens, NodesCache &outNodes, std::string &outErrReason, std::string &outWarning) {
StackVec<NodeId, 64> nesting;
size_t lineId = 0U;
size_t lastUsedLine = 0u;
outNodes.resize(1);
outNodes.rbegin()->id = 0U;
outNodes.rbegin()->firstChildId = 1U;
@@ -358,6 +367,9 @@ bool buildTree(const LinesCache &lines, const TokensCache &tokens, NodesCache &o
auto currLineIndent = lines[lineId].indent;
if (currLineIndent == outNodes.rbegin()->indent) {
if (lineId > 0u && false == isEmptyVector(tokens[lines[lastUsedLine].first], lastUsedLine, outErrReason)) {
return false;
}
outNodes.reserve(outNodes.size() + 1);
auto &prev = *outNodes.rbegin();
auto &parent = outNodes[*nesting.rbegin()];
@@ -426,6 +438,7 @@ bool buildTree(const LinesCache &lines, const TokensCache &tokens, NodesCache &o
outNodes.rbegin()->value = lines[lineId].first + 1;
}
}
lastUsedLine = lineId;
++lineId;
}
@@ -433,7 +446,6 @@ bool buildTree(const LinesCache &lines, const TokensCache &tokens, NodesCache &o
finalizeNode(*nesting.rbegin(), tokens, outNodes, outErrReason, outWarning);
nesting.pop_back();
}
if (1U == outNodes.size()) {
outWarning.append("NEO::Yaml : Text has no data\n");
outNodes.clear();

View File

@@ -11,6 +11,7 @@
#include "shared/source/utilities/const_stringref.h"
#include "shared/source/utilities/stackvec.h"
#include <array>
#include <iterator>
#include <string>
@@ -205,6 +206,24 @@ constexpr bool operator!=(char matcher, Token token) {
return token != matcher;
}
constexpr bool isVectorDataType(const Token &token) {
auto tokenString = ConstStringRef(token.pos, token.len);
constexpr std::array<const char *, 7> vectorAttributesNames = {
"kernels",
"functions",
"global_host_access_table",
"payload_arguments",
"per_thread_payload_arguments",
"binding_table_indices",
"per_thread_memory_buffers"};
for (const auto &type : vectorAttributesNames) {
if (equals(tokenString, type)) {
return true;
}
}
return false;
}
struct Line {
enum class LineType : uint8_t { Empty,
Comment,

View File

@@ -2567,7 +2567,7 @@ TEST(DecodeSingleDeviceBinaryZebin, GivenEmptyInZeInfoThenEmitsWarning) {
TEST(DecodeSingleDeviceBinaryZebin, GivenUnknownEntryInZeInfoGlobalScopeThenEmitsWarning) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = std::string("some_entry : a\nkernels : \nversion:\'") + toString(zeInfoDecoderVersion) + "\'\n";
auto brokenZeInfo = std::string("some_entry : a\nkernels : \n - name : valid_empty_kernel\n execution_env : \n simd_size : 32\n grf_count : 128\nversion:\'") + toString(zeInfoDecoderVersion) + "\'\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo;
@@ -2601,7 +2601,7 @@ TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoDoesNotContainKernelsSectionThenEm
TEST(DecodeSingleDeviceBinaryZebin, WhenZeInfoContainsMultipleKernelSectionsThenFails) {
ZebinTestData::ValidEmptyProgram zebin;
zebin.removeSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo);
auto brokenZeInfo = std::string("version:\'") + toString(zeInfoDecoderVersion) + "\'\nkernels:\nkernels:\n";
auto brokenZeInfo = std::string("version:\'") + toString(zeInfoDecoderVersion) + "\'\nkernels : \n - name : valid_empty_kernel\n execution_env : \n simd_size : 32\n grf_count : 128\n" + "\nkernels : \n - name : valid_empty_kernel\n execution_env : \n simd_size : 32\n grf_count : 128\n...\n";
zebin.appendSection(NEO::Elf::SHT_ZEBIN::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, ArrayRef<const uint8_t>::fromAny(brokenZeInfo.data(), brokenZeInfo.size()));
NEO::ProgramInfo programInfo;
@@ -5544,3 +5544,25 @@ functions:
EXPECT_STREQ(expectedError, errors.c_str());
EXPECT_TRUE(warnings.empty()) << warnings;
}
TEST(ParsingEmptyOptionalVectorTypesZeInfo, givenEmptyOptionalVectorDataEntryInZeInfoWithSamePreviousIndentationWhenParsingZeInfoThenFalsIsReturnedAndErrorPrinted) {
NEO::Yaml::YamlParser parser;
bool parseResult = true;
std::string errors;
std::string warnings;
NEO::ConstStringRef zeInfoMissingEntrySamePrevInd = R"===(---
kernels:
- name: some_kernel
execution_env:
simd_size: 8
per_thread_payload_arguments:
binding_table_indices:
- bti_value: 0
arg_index: 0
...
)===";
parseResult = parser.parse(zeInfoMissingEntrySamePrevInd, errors, warnings);
ASSERT_FALSE(parseResult);
EXPECT_STREQ("NEO::Yaml : Could not parse line : [5] : [per_thread_payload_arguments:] <-- parser position on error. Reason : Vector data type expects to have at least one value starting with -\n", errors.c_str());
}

View File

@@ -28,12 +28,15 @@ inline std::string toString(NEO::Elf::ZebinKernelMetadata::Types::Version versio
namespace ZebinTestData {
struct ValidEmptyProgram {
static constexpr char kernelName[19] = "valid_empty_kernel";
ValidEmptyProgram() {
NEO::Elf::ElfEncoder<> enc;
enc.getElfFileHeader().type = NEO::Elf::ET_ZEBIN_EXE;
enc.getElfFileHeader().machine = productFamily;
auto zeInfo = std::string{"---\nversion : \'" + toString(NEO::zeInfoDecoderVersion) + "\'" + "\nkernels : \n...\n"};
auto zeInfo = std::string{"---\nversion : \'" + toString(NEO::zeInfoDecoderVersion) + "\'" + "\nkernels : \n - name : " + kernelName + "\n execution_env : \n simd_size : 32\n grf_count : 128\n...\n"};
enc.appendSection(NEO::Elf::SHT_ZEBIN_ZEINFO, NEO::Elf::SectionsNamesZebin::zeInfo, zeInfo);
enc.appendSection(NEO::Elf::SHT_PROGBITS, NEO::Elf::SectionsNamesZebin::textPrefix.str() + "valid_empty_kernel", zeInfo);
storage = enc.encode();
recalcPtr();
}