mirror of
https://github.com/intel/compute-runtime.git
synced 2025-12-24 20:39:56 +08:00
Add support for a new relocation name for implicit args
Related-To: NEO-5081 Signed-off-by: Mateusz Jablonski <mateusz.jablonski@intel.com>
This commit is contained in:
committed by
Compute-Runtime-Automation
parent
c14dc6d9ed
commit
c7e76ce109
@@ -342,11 +342,17 @@ void Linker::patchInstructionsSegments(const std::vector<PatchableSegment> &inst
|
||||
}
|
||||
UNRECOVERABLE_IF(nullptr == instSeg.hostPointer);
|
||||
auto relocAddress = ptrOffset(instSeg.hostPointer, static_cast<uintptr_t>(relocation.offset));
|
||||
if (relocation.symbolName == implicitArgsRelocationSymbolName) {
|
||||
if (pImplicitArgsRelocationAddresses.find(segId) == pImplicitArgsRelocationAddresses.end()) {
|
||||
pImplicitArgsRelocationAddresses.insert({segId, {}});
|
||||
bool isImplicitArgsRelocation = false;
|
||||
for (const auto &implicitArgsRelocationSymbolName : implicitArgsRelocationSymbolNames) {
|
||||
if (relocation.symbolName == implicitArgsRelocationSymbolName) {
|
||||
if (pImplicitArgsRelocationAddresses.find(segId) == pImplicitArgsRelocationAddresses.end()) {
|
||||
pImplicitArgsRelocationAddresses.insert({segId, {}});
|
||||
}
|
||||
pImplicitArgsRelocationAddresses[segId].push_back(reinterpret_cast<uint32_t *>(relocAddress));
|
||||
isImplicitArgsRelocation = true;
|
||||
}
|
||||
pImplicitArgsRelocationAddresses[segId].push_back(reinterpret_cast<uint32_t *>(relocAddress));
|
||||
}
|
||||
if (isImplicitArgsRelocation) {
|
||||
continue;
|
||||
}
|
||||
auto symbolIt = relocatedSymbols.find(relocation.symbolName);
|
||||
|
||||
@@ -41,7 +41,7 @@ struct ImplicitArgs {
|
||||
static_assert((sizeof(ImplicitArgs) & 31) == 0, "Implicit args size need to be aligned to 32");
|
||||
static_assert(std::is_pod<ImplicitArgs>::value);
|
||||
|
||||
constexpr const char *implicitArgsRelocationSymbolName = "INTEL_PATCH_CROSS_THREAD_OFFSET_OFF_R0";
|
||||
constexpr const char *implicitArgsRelocationSymbolNames[] = {"INTEL_PATCH_CROSS_THREAD_OFFSET_OFF_R0", "__INTEL_PATCH_CROSS_THREAD_OFFSET_OFF_R0"};
|
||||
|
||||
namespace ImplicitArgsHelper {
|
||||
std::array<uint8_t, 3> getDimensionOrderForLocalIds(const uint8_t *workgroupDimensionsOrder, std::optional<std::pair<bool /* localIdsGeneratedByRuntime */, uint32_t /* walkOrderForHwGenerationOfLocalIds */>> hwGenerationOfLocalIdsParams);
|
||||
|
||||
@@ -2009,177 +2009,183 @@ TEST(LinkerTests, GivenDebugDataWhenApplyingDebugDataRelocationsThenRelocationsA
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenImplicitArgRelocationAndStackCallsThenPatchRelocationWithSizeOfImplicitArgStructAndUpdateKernelDescriptor) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
for (const auto &implicitArgsRelocationSymbolName : implicitArgsRelocationSymbolNames) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
|
||||
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenImplicitArgRelocationAndEnabledDebuggerThenPatchRelocationWithSizeOfImplicitArgStructAndUpdateKernelDescriptor) {
|
||||
if (!defaultHwInfo->capabilityTable.debuggerSupported) {
|
||||
GTEST_SKIP();
|
||||
}
|
||||
NEO::LinkerInput linkerInput;
|
||||
for (const auto &implicitArgsRelocationSymbolName : implicitArgsRelocationSymbolNames) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
|
||||
|
||||
DebugManagerStateRestore restorer;
|
||||
DebugManager.flags.EnableMockSourceLevelDebugger.set(1);
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
EXPECT_NE(nullptr, device->getDebugger());
|
||||
DebugManagerStateRestore restorer;
|
||||
DebugManager.flags.EnableMockSourceLevelDebugger.set(1);
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
EXPECT_NE(nullptr, device->getDebugger());
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
device, nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
device, nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenImplicitArgRelocationWithoutStackCallsAndDisabledDebuggerThenPatchRelocationWithZeroAndUpdateKernelDescriptor) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
for (const auto &implicitArgsRelocationSymbolName : implicitArgsRelocationSymbolNames) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
vISA::GenRelocEntry reloc = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc.r_offset = 8;
|
||||
reloc.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
vISA::GenRelocEntry relocs[] = {reloc};
|
||||
constexpr uint32_t numRelocations = 1;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = false;
|
||||
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
EXPECT_EQ(nullptr, device->getDebugger());
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
auto device = deviceFactory.rootDevices[0];
|
||||
EXPECT_EQ(nullptr, device->getDebugger());
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
std::vector<char> instructionSegment;
|
||||
uint32_t initData = 0x77777777;
|
||||
instructionSegment.resize(32, static_cast<char>(initData));
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
device, nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
device, nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(0u, *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(0u, *addressToPatch);
|
||||
EXPECT_EQ(initData, *(addressToPatch - 1));
|
||||
EXPECT_EQ(initData, *(addressToPatch + 1));
|
||||
EXPECT_FALSE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenNoImplicitArgRelocationAndStackCallsThenImplicitArgsAreNotRequired) {
|
||||
@@ -2276,60 +2282,62 @@ TEST(LinkerTests, givenNoImplicitArgRelocationAndEnabledDebuggerThenImplicitArgs
|
||||
}
|
||||
|
||||
TEST(LinkerTests, givenMultipleImplicitArgsRelocationsWithinSingleKernelWhenLinkingThenPatchAllOfThem) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
for (const auto &implicitArgsRelocationSymbolName : implicitArgsRelocationSymbolNames) {
|
||||
NEO::LinkerInput linkerInput;
|
||||
|
||||
vISA::GenRelocEntry reloc0 = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc0.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc0.r_offset = 8;
|
||||
reloc0.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
vISA::GenRelocEntry reloc0 = {};
|
||||
std::string relocationName = implicitArgsRelocationSymbolName;
|
||||
memcpy_s(reloc0.r_symbol, 1024, relocationName.c_str(), relocationName.size());
|
||||
reloc0.r_offset = 8;
|
||||
reloc0.r_type = vISA::GenRelocType::R_SYM_ADDR_32;
|
||||
|
||||
vISA::GenRelocEntry reloc1 = reloc0;
|
||||
reloc1.r_offset = 24;
|
||||
vISA::GenRelocEntry reloc1 = reloc0;
|
||||
reloc1.r_offset = 24;
|
||||
|
||||
vISA::GenRelocEntry relocs[] = {reloc0, reloc1};
|
||||
constexpr uint32_t numRelocations = 2;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
vISA::GenRelocEntry relocs[] = {reloc0, reloc1};
|
||||
constexpr uint32_t numRelocations = 2;
|
||||
bool decodeRelocSuccess = linkerInput.decodeRelocationTable(&relocs, numRelocations, 0);
|
||||
EXPECT_TRUE(decodeRelocSuccess);
|
||||
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
|
||||
NEO::Linker linker(linkerInput);
|
||||
NEO::Linker::SegmentInfo globalVarSegment, globalConstSegment, exportedFuncSegment;
|
||||
globalVarSegment.gpuAddress = 8;
|
||||
globalVarSegment.segmentSize = 64;
|
||||
globalConstSegment.gpuAddress = 128;
|
||||
globalConstSegment.segmentSize = 256;
|
||||
exportedFuncSegment.gpuAddress = 4096;
|
||||
exportedFuncSegment.segmentSize = 1024;
|
||||
NEO::Linker::UnresolvedExternals unresolvedExternals;
|
||||
NEO::Linker::ExternalFunctionsT externalFunctions;
|
||||
NEO::Linker::KernelDescriptorsT kernelDescriptors;
|
||||
KernelDescriptor kernelDescriptor;
|
||||
kernelDescriptors.push_back(&kernelDescriptor);
|
||||
kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs = false;
|
||||
kernelDescriptor.kernelAttributes.flags.useStackCalls = true;
|
||||
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
UltDeviceFactory deviceFactory{1, 0};
|
||||
|
||||
std::vector<char> instructionSegment;
|
||||
char initData = 0x77;
|
||||
instructionSegment.resize(32, initData);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
std::vector<char> instructionSegment;
|
||||
char initData = 0x77;
|
||||
instructionSegment.resize(32, initData);
|
||||
NEO::Linker::PatchableSegment seg0;
|
||||
seg0.hostPointer = instructionSegment.data();
|
||||
seg0.segmentSize = instructionSegment.size();
|
||||
NEO::Linker::PatchableSegments patchableInstructionSegments{seg0};
|
||||
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
auto linkResult = linker.link(globalVarSegment, globalConstSegment, exportedFuncSegment, {},
|
||||
nullptr, nullptr, patchableInstructionSegments, unresolvedExternals,
|
||||
deviceFactory.rootDevices[0], nullptr, nullptr, kernelDescriptors, externalFunctions);
|
||||
EXPECT_EQ(NEO::LinkingStatus::LinkedFully, linkResult);
|
||||
auto relocatedSymbols = linker.extractRelocatedSymbols();
|
||||
EXPECT_EQ(0U, unresolvedExternals.size());
|
||||
EXPECT_EQ(0U, relocatedSymbols.size());
|
||||
|
||||
for (const auto &reloc : relocs) {
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
for (const auto &reloc : relocs) {
|
||||
auto addressToPatch = reinterpret_cast<const uint32_t *>(instructionSegment.data() + reloc.r_offset);
|
||||
EXPECT_EQ(sizeof(ImplicitArgs), *addressToPatch);
|
||||
EXPECT_TRUE(kernelDescriptor.kernelAttributes.flags.requiresImplicitArgs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user