1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
/*
* Copyright (C) 2020-2025 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/device_binary_format/ar/ar_decoder.h"
#include "shared/source/device_binary_format/device_binary_formats.h"
#include "shared/source/helpers/product_config_helper.h"
#include "shared/source/helpers/string.h"
#include <cstring>
#include <optional>
namespace NEO {
void searchForBinary(Ar::Ar &archiveData, const ConstStringRef filter, Ar::ArFileEntryHeaderAndData *&matched) {
for (auto &file : archiveData.files) {
if (file.fileName.startsWith(filter.str().c_str())) {
matched = &file;
return;
}
}
}
template <>
bool isDeviceBinaryFormat<NEO::DeviceBinaryFormat::archive>(const ArrayRef<const uint8_t> binary) {
return NEO::Ar::isAr(binary);
}
template <>
SingleDeviceBinary unpackSingleDeviceBinary<NEO::DeviceBinaryFormat::archive>(const ArrayRef<const uint8_t> archive,
const ConstStringRef requestedProductAbbreviation,
const TargetDevice &requestedTargetDevice,
std::string &outErrReason,
std::string &outWarning) {
auto archiveData = NEO::Ar::decodeAr(archive, outErrReason, outWarning);
if (nullptr == archiveData.magic) {
return {};
}
ConstStringRef filterGenericIrFileName{"generic_ir"};
Ar::ArFileEntryHeaderAndData *matchedGenericIr = nullptr;
searchForBinary(archiveData, filterGenericIrFileName, matchedGenericIr);
SingleDeviceBinary binaryForRecompilation{};
auto tryPlatform = [&](ConstStringRef platformAbbreviation) -> std::optional<SingleDeviceBinary> {
std::string pointerSize = ((requestedTargetDevice.maxPointerSizeInBytes == 8) ? "64" : "32");
std::string filterPointerSizeAndMajorMinorRevision = pointerSize + "." + ProductConfigHelper::parseMajorMinorRevisionValue(requestedTargetDevice.aotConfig);
std::string filterPointerSizeAndMajorMinor = pointerSize + "." + ProductConfigHelper::parseMajorMinorValue(requestedTargetDevice.aotConfig);
std::string filterPointerSizeAndPlatform = pointerSize + "." + platformAbbreviation.str();
std::string filterPointerSizeAndPlatformAndStepping = filterPointerSizeAndPlatform + "." + std::to_string(requestedTargetDevice.stepping);
Ar::ArFileEntryHeaderAndData *matchedFiles[4] = {};
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndMajorMinorRevision = matchedFiles[0];
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndPlatformAndStepping = matchedFiles[1];
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndMajorMinor = matchedFiles[2];
Ar::ArFileEntryHeaderAndData *&matchedPointerSizeAndPlatform = matchedFiles[3];
searchForBinary(archiveData, ConstStringRef(filterPointerSizeAndMajorMinorRevision), matchedPointerSizeAndMajorMinorRevision);
searchForBinary(archiveData, ConstStringRef(filterPointerSizeAndPlatformAndStepping), matchedPointerSizeAndPlatformAndStepping);
searchForBinary(archiveData, ConstStringRef(filterPointerSizeAndMajorMinor), matchedPointerSizeAndMajorMinor);
searchForBinary(archiveData, ConstStringRef(filterPointerSizeAndPlatform), matchedPointerSizeAndPlatform);
std::string unpackErrors;
std::string unpackWarnings;
for (auto matchedFile : matchedFiles) {
if (nullptr == matchedFile) {
continue;
}
auto unpacked = unpackSingleDeviceBinary(matchedFile->fileData, platformAbbreviation,
requestedTargetDevice, unpackErrors, unpackWarnings);
if (!unpacked.deviceBinary.empty()) {
if ((matchedFile != matchedPointerSizeAndPlatformAndStepping) &&
(matchedFile != matchedPointerSizeAndMajorMinorRevision)) {
outWarning = "Couldn't find perfectly matched binary in AR, using best usable";
}
if (unpacked.intermediateRepresentation.empty() && matchedGenericIr) {
std::string irErrors, irWarnings;
auto genericIrResult = unpackSingleDeviceBinary(matchedGenericIr->fileData, platformAbbreviation,
requestedTargetDevice, irErrors, irWarnings);
if (!genericIrResult.intermediateRepresentation.empty()) {
unpacked.intermediateRepresentation = genericIrResult.intermediateRepresentation;
}
}
unpacked.packedTargetDeviceBinary =
ArrayRef<const uint8_t>(matchedFile->fileData.begin(), matchedFile->fileData.size());
return unpacked;
}
if (binaryForRecompilation.intermediateRepresentation.empty() &&
!unpacked.intermediateRepresentation.empty()) {
binaryForRecompilation = unpacked;
}
}
return std::nullopt;
};
if (auto primary = tryPlatform(requestedProductAbbreviation); primary.has_value()) {
return *primary;
}
auto compatibilityFallbackAbbreviations =
ProductConfigHelper::getCompatibilityFallbackProductAbbreviations(requestedProductAbbreviation.str());
for (const auto &compatAbbrev : compatibilityFallbackAbbreviations) {
if (compatAbbrev == requestedProductAbbreviation.str()) {
continue;
}
ConstStringRef compatRef{compatAbbrev};
if (auto compatResult = tryPlatform(compatRef); compatResult.has_value()) {
return *compatResult;
}
}
if (!binaryForRecompilation.intermediateRepresentation.empty()) {
return binaryForRecompilation;
}
if (matchedGenericIr) {
std::string irErrors, irWarnings;
auto genericIrResult = unpackSingleDeviceBinary(matchedGenericIr->fileData, requestedProductAbbreviation,
requestedTargetDevice, irErrors, irWarnings);
if (!genericIrResult.intermediateRepresentation.empty()) {
return genericIrResult;
}
}
outErrReason = "Couldn't find matching binary in AR archive";
return {};
}
template <>
DecodeError decodeSingleDeviceBinary<NEO::DeviceBinaryFormat::archive>(ProgramInfo &dst, const SingleDeviceBinary &src, std::string &outErrReason, std::string &outWarning, const GfxCoreHelper &gfxCoreHelper) {
// packed binary format
outErrReason = "Device binary format is packed";
return DecodeError::invalidBinary;
}
} // namespace NEO
|