Allow to create partially linked module

Don't allow to create kernel from partially linked module

Change-Id: Id70b484686e6d1ca79f242bf96ff92582172e378
Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
Mateusz Jablonski
2020-07-13 18:42:11 +02:00
committed by sys_ocldev
parent 2b30166415
commit 794296334b
8 changed files with 164 additions and 71 deletions

View File

@@ -370,6 +370,9 @@ void ModuleImp::updateBuildLog(NEO::Device *neoDevice) {
ze_result_t ModuleImp::createKernel(const ze_kernel_desc_t *desc,
ze_kernel_handle_t *phFunction) {
ze_result_t res;
if (!isFullyLinked) {
return ZE_RESULT_ERROR_MODULE_BUILD_FAILURE;
}
auto kernel = Kernel::create(productFamily, this, desc, &res);
if (res == ZE_RESULT_SUCCESS) {
@@ -404,6 +407,7 @@ ze_result_t ModuleImp::getDebugInfo(size_t *pDebugDataSize, uint8_t *pDebugData)
bool ModuleImp::linkBinary() {
using namespace NEO;
if (this->translationUnit->programInfo.linkerInput == nullptr) {
isFullyLinked = true;
return true;
}
Linker linker(*this->translationUnit->programInfo.linkerInput);
@@ -439,20 +443,22 @@ bool ModuleImp::linkBinary() {
}
Linker::UnresolvedExternals unresolvedExternalsInfo;
bool linkSuccess = linker.link(globals, constants, exportedFunctions,
globalsForPatching, constantsForPatching,
isaSegmentsForPatching, unresolvedExternalsInfo, this->device->getNEODevice(),
translationUnit->programInfo.globalConstants.initData,
translationUnit->programInfo.globalVariables.initData);
auto linkStatus = linker.link(globals, constants, exportedFunctions,
globalsForPatching, constantsForPatching,
isaSegmentsForPatching, unresolvedExternalsInfo, this->device->getNEODevice(),
translationUnit->programInfo.globalConstants.initData,
translationUnit->programInfo.globalVariables.initData);
this->symbols = linker.extractRelocatedSymbols();
if (false == linkSuccess) {
std::vector<std::string> kernelNames;
for (const auto &kernelInfo : this->translationUnit->programInfo.kernelInfos) {
kernelNames.push_back("kernel : " + kernelInfo->name);
if (LinkingStatus::LinkedFully != linkStatus) {
if (moduleBuildLog) {
std::vector<std::string> kernelNames;
for (const auto &kernelInfo : this->translationUnit->programInfo.kernelInfos) {
kernelNames.push_back("kernel : " + kernelInfo->name);
}
auto error = constructLinkerErrorMessage(unresolvedExternalsInfo, kernelNames);
moduleBuildLog->appendString(error.c_str(), error.size());
}
auto error = constructLinkerErrorMessage(unresolvedExternalsInfo, kernelNames);
moduleBuildLog->appendString(error.c_str(), error.size());
return false;
return LinkingStatus::LinkedPartially == linkStatus;
} else if (this->translationUnit->programInfo.linkerInput->getTraits().requiresPatchingOfInstructionSegments) {
for (const auto &kernelImmData : this->kernelImmDatas) {
if (nullptr == kernelImmData->getIsaGraphicsAllocation()) {
@@ -465,6 +471,7 @@ bool ModuleImp::linkBinary() {
}
}
DBG_LOG(PrintRelocations, NEO::constructRelocationsDebugMessage(this->symbols));
isFullyLinked = true;
return true;
}

View File

@@ -114,6 +114,7 @@ struct ModuleImp : public Module {
std::vector<std::unique_ptr<KernelImmutableData>> kernelImmDatas;
NEO::Linker::RelocatedSymbolsMap symbols;
bool debugEnabled = false;
bool isFullyLinked = false;
};
bool moveBuildOption(std::string &dstOptionsSet, std::string &srcOptionSet, ConstStringRef dstOptionName, ConstStringRef srcOptionName);

View File

@@ -22,6 +22,7 @@ struct WhiteBox<::L0::Module> : public ::L0::ModuleImp {
using BaseClass = ::L0::ModuleImp;
using BaseClass::BaseClass;
using BaseClass::device;
using BaseClass::isFullyLinked;
using BaseClass::translationUnit;
};
@@ -56,7 +57,16 @@ struct MockModuleTranslationUnit : public L0::ModuleTranslationUnit {
};
struct MockCompilerInterface : public NEO::CompilerInterface {
MockCompilerInterface(uint32_t moduleNumSpecConstants) : moduleNumSpecConstants(moduleNumSpecConstants) {
NEO::TranslationOutput::ErrorCode build(const NEO::Device &device,
const NEO::TranslationInput &input,
NEO::TranslationOutput &output) override {
return NEO::TranslationOutput::ErrorCode::Success;
}
};
struct MockCompilerInterfaceWithSpecConstants : public NEO::CompilerInterface {
MockCompilerInterfaceWithSpecConstants(uint32_t moduleNumSpecConstants) : moduleNumSpecConstants(moduleNumSpecConstants) {
}
NEO::TranslationOutput::ErrorCode build(const NEO::Device &device,
const NEO::TranslationInput &input,

View File

@@ -5,6 +5,8 @@
*
*/
#include "shared/test/unit_test/compiler_interface/linker_mock.h"
#include "test.h"
#include "level_zero/core/source/kernel/kernel_imp.h"
@@ -103,7 +105,7 @@ struct ModuleSpecConstantsTests : public DeviceFixture,
void SetUp() override {
DeviceFixture::SetUp();
mockCompiler = new MockCompilerInterface(moduleNumSpecConstants);
mockCompiler = new MockCompilerInterfaceWithSpecConstants(moduleNumSpecConstants);
auto rootDeviceEnvironment = neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get();
rootDeviceEnvironment->compilerInterface.reset(mockCompiler);
@@ -120,7 +122,7 @@ struct ModuleSpecConstantsTests : public DeviceFixture,
const std::string binaryFilename = "test_kernel";
const std::string kernelName = "test";
MockCompilerInterface *mockCompiler;
MockCompilerInterfaceWithSpecConstants *mockCompiler;
MockModuleTranslationUnit *mockTranslationUnit;
};
@@ -156,6 +158,70 @@ HWTEST_F(ModuleSpecConstantsTests, givenSpecializationConstantsSetInDescriptorTh
module->destroy();
}
using ModuleLinkingTest = Test<DeviceFixture>;
HWTEST_F(ModuleLinkingTest, givenFailureDuringLinkingWhenCreatingModuleThenModuleInitialiationFails) {
auto mockCompiler = new MockCompilerInterface();
auto rootDeviceEnvironment = neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get();
rootDeviceEnvironment->compilerInterface.reset(mockCompiler);
auto mockTranslationUnit = new MockModuleTranslationUnit(device);
auto linkerInput = std::make_unique<::WhiteBox<NEO::LinkerInput>>();
linkerInput->valid = false;
mockTranslationUnit->programInfo.linkerInput = std::move(linkerInput);
uint8_t spirvData{};
ze_module_desc_t moduleDesc = {ZE_MODULE_DESC_VERSION_CURRENT};
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
moduleDesc.pInputModule = &spirvData;
moduleDesc.inputSize = sizeof(spirvData);
Module module(device, nullptr);
module.translationUnit.reset(mockTranslationUnit);
bool success = module.initialize(&moduleDesc, neoDevice);
EXPECT_FALSE(success);
}
HWTEST_F(ModuleLinkingTest, givenRemainingUnresolvedSymbolsDuringLinkingWhenCreatingModuleThenModuleIsNotLinkedFully) {
auto mockCompiler = new MockCompilerInterface();
auto rootDeviceEnvironment = neoDevice->getExecutionEnvironment()->rootDeviceEnvironments[0].get();
rootDeviceEnvironment->compilerInterface.reset(mockCompiler);
auto mockTranslationUnit = new MockModuleTranslationUnit(device);
auto linkerInput = std::make_unique<::WhiteBox<NEO::LinkerInput>>();
NEO::LinkerInput::RelocationInfo relocation;
relocation.symbolName = "unresolved";
linkerInput->dataRelocations.push_back(relocation);
linkerInput->traits.requiresPatchingOfGlobalVariablesBuffer = true;
mockTranslationUnit->programInfo.linkerInput = std::move(linkerInput);
uint8_t spirvData{};
ze_module_desc_t moduleDesc = {ZE_MODULE_DESC_VERSION_CURRENT};
moduleDesc.format = ZE_MODULE_FORMAT_IL_SPIRV;
moduleDesc.pInputModule = &spirvData;
moduleDesc.inputSize = sizeof(spirvData);
Module module(device, nullptr);
module.translationUnit.reset(mockTranslationUnit);
bool success = module.initialize(&moduleDesc, neoDevice);
EXPECT_TRUE(success);
EXPECT_FALSE(module.isFullyLinked);
}
HWTEST_F(ModuleLinkingTest, givenNotFullyLinkedModuleWhenCreatingKernelThenErrorIsReturned) {
Module module(device, nullptr);
module.isFullyLinked = false;
auto retVal = module.createKernel(nullptr, nullptr);
EXPECT_EQ(ZE_RESULT_ERROR_MODULE_BUILD_FAILURE, retVal);
}
using ModuleDynamicLinkTests = Test<ModuleFixture>;
HWTEST_F(ModuleDynamicLinkTests, givenCallToDynamicLinkThenUnsupportedFeatureIsReturned) {