feature: zeDriverGetLastErrorDescription error messages (module)

When there is a PRINT_DEBUG_MESSAGE message in module that is
applicable to the user, it is now also set to
Driver::zeDriverGetLastErrorDescription.
ULTs are also added to verify that setErrorDescription successfully
stores the error message.

Related-To: LOCI-4653

Signed-off-by: Zhang, Winston <winston.zhang@intel.com>
This commit is contained in:
Zhang, Winston 2023-07-26 19:43:26 +00:00 committed by Compute-Runtime-Automation
parent 60b7c14c22
commit 8962c95000
6 changed files with 77 additions and 1 deletions

View File

@ -75,6 +75,7 @@ struct DriverHandle : BaseDriver {
virtual int setErrorDescription(const char *fmt, ...) = 0;
virtual ze_result_t getErrorDescription(const char **ppString) = 0;
virtual ze_result_t clearErrorDescription() = 0;
static DriverHandle *fromHandle(ze_driver_handle_t handle) { return static_cast<DriverHandle *>(handle); }
inline ze_driver_handle_t toHandle() { return this; }

View File

@ -954,4 +954,12 @@ ze_result_t DriverHandleImp::getErrorDescription(const char **ppString) {
return ZE_RESULT_SUCCESS;
}
ze_result_t DriverHandleImp::clearErrorDescription() {
auto threadId = std::this_thread::get_id();
if (errorDescs.find(threadId) != errorDescs.end()) {
errorDescs[threadId].clear();
}
return ZE_RESULT_SUCCESS;
}
} // namespace L0

View File

@ -153,6 +153,7 @@ struct DriverHandleImp : public DriverHandle {
std::mutex errorDescsMutex;
int setErrorDescription(const char *fmt, ...) override;
ze_result_t getErrorDescription(const char **ppString) override;
ze_result_t clearErrorDescription() override;
};
extern struct DriverHandleImp *GlobalDriver;

View File

@ -40,6 +40,7 @@
#include "level_zero/core/source/device/device.h"
#include "level_zero/core/source/driver/driver_handle.h"
#include "level_zero/core/source/driver/driver_handle_imp.h"
#include "level_zero/core/source/gfx_core_helpers/l0_gfx_core_helper.h"
#include "level_zero/core/source/kernel/kernel.h"
#include "level_zero/core/source/module/module_build_log.h"
@ -181,7 +182,9 @@ bool ModuleTranslationUnit::processSpecConstantInfo(NEO::CompilerInterface *comp
ze_result_t ModuleTranslationUnit::compileGenBinary(NEO::TranslationInput inputArgs, bool staticLink) {
auto compilerInterface = device->getNEODevice()->getCompilerInterface();
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
if (!compilerInterface) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
@ -200,6 +203,7 @@ ze_result_t ModuleTranslationUnit::compileGenBinary(NEO::TranslationInput inputA
this->updateBuildLog(compilerOuput.backendCompilerLog);
if (NEO::TranslationOutput::ErrorCode::Success != compilerErr) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
@ -216,7 +220,9 @@ ze_result_t ModuleTranslationUnit::compileGenBinary(NEO::TranslationInput inputA
ze_result_t ModuleTranslationUnit::staticLinkSpirV(std::vector<const char *> inputSpirVs, std::vector<uint32_t> inputModuleSizes, const char *buildOptions, const char *internalBuildOptions,
std::vector<const ze_module_constants_t *> specConstants) {
auto compilerInterface = device->getNEODevice()->getCompilerInterface();
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
if (!compilerInterface) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
@ -225,6 +231,7 @@ ze_result_t ModuleTranslationUnit::staticLinkSpirV(std::vector<const char *> inp
for (uint32_t i = 0; i < static_cast<uint32_t>(specConstants.size()); i++) {
auto specConstantResult = this->processSpecConstantInfo(compilerInterface, specConstants[i], inputSpirVs[i], inputModuleSizes[i]);
if (!specConstantResult) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
}
@ -243,12 +250,15 @@ ze_result_t ModuleTranslationUnit::buildFromSpirV(const char *input, uint32_t in
const ze_module_constants_t *pConstants) {
const auto &neoDevice = device->getNEODevice();
auto compilerInterface = neoDevice->getCompilerInterface();
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
if (!compilerInterface) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_DEPENDENCY_UNAVAILABLE;
}
auto specConstantResult = this->processSpecConstantInfo(compilerInterface, pConstants, input, inputSize);
if (!specConstantResult) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
@ -258,6 +268,7 @@ ze_result_t ModuleTranslationUnit::buildFromSpirV(const char *input, uint32_t in
if (isZebinAllowed == false) {
const auto &rootDevice = neoDevice->getRootDevice();
if (!rootDevice->getCompilerInterface()->addOptionDisableZebin(this->options, internalOptions)) {
driverHandle->setErrorDescription("Cannot build zebinary for this device with debugger enabled. Remove \"-ze-intel-enable-zebin\" build flag\n");
updateBuildLog("Cannot build zebinary for this device with debugger enabled. Remove \"-ze-intel-enable-zebin\" build flag");
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
@ -281,10 +292,12 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz
ArrayRef<const uint8_t> archive(reinterpret_cast<const uint8_t *>(input), inputSize);
auto singleDeviceBinary = unpackSingleDeviceBinary(archive, NEO::ConstStringRef(productAbbreviation, strlen(productAbbreviation)), targetDevice,
decodeErrors, decodeWarnings);
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
if (decodeWarnings.empty() == false) {
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeWarnings.c_str());
}
if (singleDeviceBinary.intermediateRepresentation.empty() && singleDeviceBinary.deviceBinary.empty()) {
driverHandle->setErrorDescription("%s\n", decodeErrors.c_str());
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
} else {
@ -305,6 +318,7 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz
bool rebuild = NEO::DebugManager.flags.RebuildPrecompiledKernels.get() && irBinarySize != 0;
rebuild |= NEO::isRebuiltToPatchtokensRequired(device->getNEODevice(), archive, this->options, this->isBuiltIn, false);
if (rebuild && irBinarySize == 0) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_INVALID_NATIVE_BINARY;
}
if ((false == singleDeviceBinary.deviceBinary.empty()) && (false == rebuild)) {
@ -330,6 +344,7 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz
return buildFromSpirV(this->irBinary.get(), static_cast<uint32_t>(this->irBinarySize), this->options.c_str(), "", nullptr);
} else {
if (processUnpackedBinary() != ZE_RESULT_SUCCESS) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
return ZE_RESULT_SUCCESS;
@ -337,7 +352,9 @@ ze_result_t ModuleTranslationUnit::createFromNativeBinary(const char *input, siz
}
ze_result_t ModuleTranslationUnit::processUnpackedBinary() {
const auto driverHandle = static_cast<DriverHandleImp *>(device->getDriverHandle());
if (0 == unpackedDeviceBinarySize) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
auto blob = ArrayRef<const uint8_t>(reinterpret_cast<const uint8_t *>(this->unpackedDeviceBinary.get()), this->unpackedDeviceBinarySize);
@ -356,6 +373,7 @@ ze_result_t ModuleTranslationUnit::processUnpackedBinary() {
}
if (NEO::DecodeError::Success != decodeError) {
driverHandle->setErrorDescription("%s\n", decodeErrors.c_str());
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "%s\n", decodeErrors.c_str());
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
@ -377,6 +395,8 @@ ze_result_t ModuleTranslationUnit::processUnpackedBinary() {
}
if (slmNeeded > slmAvailable) {
driverHandle->setErrorDescription("Size of SLM (%u) larger than available (%u)\n",
static_cast<uint32_t>(slmNeeded), static_cast<uint32_t>(slmAvailable));
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Size of SLM (%u) larger than available (%u)\n",
static_cast<uint32_t>(slmNeeded), static_cast<uint32_t>(slmAvailable));
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
@ -414,6 +434,7 @@ ze_result_t ModuleTranslationUnit::processUnpackedBinary() {
std::string packErrors;
auto packedDeviceBinary = NEO::packDeviceBinary(singleDeviceBinary, packErrors, packWarnings);
if (packedDeviceBinary.empty()) {
driverHandle->clearErrorDescription();
DEBUG_BREAK_IF(true);
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
@ -772,20 +793,24 @@ void ModuleImp::updateBuildLog(NEO::Device *neoDevice) {
ze_result_t ModuleImp::createKernel(const ze_kernel_desc_t *desc,
ze_kernel_handle_t *kernelHandle) {
ze_result_t res;
const auto driverHandle = static_cast<DriverHandleImp *>((this->getDevice())->getDriverHandle());
if (!isFullyLinked) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_INVALID_MODULE_UNLINKED;
}
auto kernel = Kernel::create(productFamily, this, desc, &res);
if (res == ZE_RESULT_SUCCESS) {
*kernelHandle = kernel->toHandle();
} else {
driverHandle->clearErrorDescription();
}
auto localMemSize = static_cast<uint32_t>(this->getDevice()->getNEODevice()->getDeviceInfo().localMemSize);
for (const auto &kernelImmutableData : this->getKernelImmutableDataVector()) {
auto slmInlineSize = kernelImmutableData->getDescriptor().kernelAttributes.slmInlineSize;
if (slmInlineSize > 0 && localMemSize < slmInlineSize) {
driverHandle->setErrorDescription("Size of SLM (%u) larger than available (%u)\n", slmInlineSize, localMemSize);
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Size of SLM (%u) larger than available (%u)\n", slmInlineSize, localMemSize);
res = ZE_RESULT_ERROR_OUT_OF_DEVICE_MEMORY;
break;
@ -949,6 +974,7 @@ bool ModuleImp::linkBinary() {
}
ze_result_t ModuleImp::getFunctionPointer(const char *pFunctionName, void **pfnFunction) {
const auto driverHandle = static_cast<DriverHandleImp *>((this->getDevice())->getDriverHandle());
// Check if the function is in the exported symbol table
auto symbolIt = symbols.find(pFunctionName);
if ((symbolIt != symbols.end()) && (symbolIt->second.symbol.segment == NEO::SegmentType::Instructions)) {
@ -972,6 +998,7 @@ ze_result_t ModuleImp::getFunctionPointer(const char *pFunctionName, void **pfnF
if (*pfnFunction == nullptr) {
if (!this->isFunctionSymbolExportEnabled) {
driverHandle->setErrorDescription("Function Pointers Not Supported Without Compiler flag %s\n", BuildOptions::enableLibraryCompile.str().c_str());
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Function Pointers Not Supported Without Compiler flag %s\n", BuildOptions::enableLibraryCompile.str().c_str());
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
@ -983,6 +1010,7 @@ ze_result_t ModuleImp::getFunctionPointer(const char *pFunctionName, void **pfnF
ze_result_t ModuleImp::getGlobalPointer(const char *pGlobalName, size_t *pSize, void **pPtr) {
uint64_t address;
size_t size;
const auto driverHandle = static_cast<DriverHandleImp *>((this->getDevice())->getDriverHandle());
auto hostSymbolIt = hostGlobalSymbolsMap.find(pGlobalName);
if (hostSymbolIt != hostGlobalSymbolsMap.end()) {
@ -992,13 +1020,16 @@ ze_result_t ModuleImp::getGlobalPointer(const char *pGlobalName, size_t *pSize,
auto deviceSymbolIt = symbols.find(pGlobalName);
if (deviceSymbolIt != symbols.end()) {
if (deviceSymbolIt->second.symbol.segment == NEO::SegmentType::Instructions) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_INVALID_GLOBAL_NAME;
}
} else {
if (!this->isGlobalSymbolExportEnabled) {
driverHandle->setErrorDescription("Global Pointers Not Supported Without Compiler flag %s\n", BuildOptions::enableGlobalVariableSymbols.str().c_str());
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Global Pointers Not Supported Without Compiler flag %s\n", BuildOptions::enableGlobalVariableSymbols.str().c_str());
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_INVALID_GLOBAL_NAME;
}
address = deviceSymbolIt->second.gpuAddress;
@ -1168,6 +1199,7 @@ ze_result_t ModuleImp::performDynamicLink(uint32_t numModules,
ze_module_build_log_handle_t *phLinkLog) {
std::map<void *, std::map<void *, void *>> dependencies;
ModuleBuildLog *moduleLinkLog = nullptr;
const auto driverHandle = static_cast<DriverHandleImp *>((this->getDevice())->getDriverHandle());
if (phLinkLog) {
moduleLinkLog = ModuleBuildLog::create();
*phLinkLog = moduleLinkLog->toHandle();
@ -1246,9 +1278,11 @@ ze_result_t ModuleImp::performDynamicLink(uint32_t numModules,
}
if (numPatchedSymbols != moduleId->unresolvedExternalsInfo.size()) {
if (functionSymbolExportEnabledCounter == 0) {
driverHandle->setErrorDescription("Dynamic Link Not Supported Without Compiler flag %s\n", BuildOptions::enableLibraryCompile.str().c_str());
PRINT_DEBUG_STRING(NEO::DebugManager.flags.PrintDebugMessages.get(), stderr, "Dynamic Link Not Supported Without Compiler flag %s\n", BuildOptions::enableLibraryCompile.str().c_str());
return ZE_RESULT_ERROR_UNSUPPORTED_FEATURE;
}
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_LINK_FAILURE;
}
moduleId->copyPatchedSegments(isaSegmentsForPatching);
@ -1284,6 +1318,7 @@ ze_result_t ModuleImp::performDynamicLink(uint32_t numModules,
}
auto error = NEO::resolveExternalDependencies(externalFunctionInfos, kernelDependencies, extFuncDependencies, nameToKernelDescriptor);
if (error != NEO::RESOLVE_SUCCESS) {
driverHandle->clearErrorDescription();
return ZE_RESULT_ERROR_MODULE_LINK_FAILURE;
}
}

View File

@ -997,6 +997,23 @@ TEST_F(DriverHandleTest, givenValidDriverHandleWhenGetErrorDescriptionIsCalledTh
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
}
TEST_F(DriverHandleTest, givenValidDriverHandleWhenClearErrorDescriptionIsCalledThenEmptyStringIsReturned) {
std::string errorString = "error string";
std::string emptyString = "";
const char *pStr = nullptr;
ze_result_t result = ZE_RESULT_SUCCESS;
driverHandle->setErrorDescription(errorString.c_str());
result = zeDriverGetLastErrorDescription(driverHandle->toHandle(), &pStr);
EXPECT_EQ(0, strcmp(errorString.c_str(), pStr));
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
result = driverHandle->clearErrorDescription();
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
result = zeDriverGetLastErrorDescription(driverHandle->toHandle(), &pStr);
EXPECT_EQ(ZE_RESULT_SUCCESS, result);
EXPECT_EQ(0, strcmp(emptyString.c_str(), pStr));
}
TEST(zeDriverHandleGetProperties, whenZeDriverGetPropertiesIsCalledThenGetPropertiesIsCalled) {
ze_result_t result = ZE_RESULT_SUCCESS;
Mock<DriverHandle> driverHandle;

View File

@ -1967,6 +1967,10 @@ TEST_F(ModuleDynamicLinkTests, givenModuleWithUnresolvedSymbolsNotPresentInAnoth
std::vector<ze_module_handle_t> hModules = {module0->toHandle(), module1->toHandle()};
ze_result_t res = module0->performDynamicLink(2, hModules.data(), &dynLinkLog);
const char *pStr = nullptr;
std::string emptyString = "";
zeDriverGetLastErrorDescription(device->getDriverHandle(), &pStr);
EXPECT_NE(0, strcmp(pStr, emptyString.c_str()));
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, res);
size_t buildLogSize;
zeModuleBuildLogGetString(dynLinkLog, &buildLogSize, nullptr);
@ -2114,6 +2118,10 @@ TEST_F(ModuleFunctionPointerTests, givenModuleWithExportedSymbolButNoExportFlags
void *functionPointer = nullptr;
ze_result_t res = module0->getFunctionPointer("Invalid", &functionPointer);
const char *pStr = nullptr;
std::string emptyString = "";
zeDriverGetLastErrorDescription(device->getDriverHandle(), &pStr);
EXPECT_NE(0, strcmp(pStr, emptyString.c_str()));
EXPECT_EQ(ZE_RESULT_ERROR_UNSUPPORTED_FEATURE, res);
}
@ -2610,11 +2618,17 @@ HWTEST_F(ModuleTranslationUnitTest, WhenCreatingFromNativeBinaryThenSetsUpRequir
L0::ModuleTranslationUnit moduleTuValid(this->device);
ze_result_t result = ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
result = moduleTuValid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size());
const char *pStr = nullptr;
std::string emptyString = "";
zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr);
EXPECT_EQ(0, strcmp(pStr, emptyString.c_str()));
EXPECT_EQ(result, ZE_RESULT_SUCCESS);
++emptyProgram.elfHeader->machine;
L0::ModuleTranslationUnit moduleTuInvalid(this->device);
result = moduleTuInvalid.createFromNativeBinary(reinterpret_cast<const char *>(emptyProgram.storage.data()), emptyProgram.storage.size());
zeDriverGetLastErrorDescription(this->device->getDriverHandle(), &pStr);
EXPECT_NE(0, strcmp(pStr, emptyString.c_str()));
EXPECT_EQ(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, result);
}