Support for symbol/relocation tables

Change-Id: I87890f6dc36a3454ffdcab1fb9d070fdaf91e689
This commit is contained in:
Chodor, Jaroslaw
2019-07-04 17:14:51 +02:00
committed by sys_ocldev
parent b6792ef049
commit ce061a48ef
20 changed files with 1531 additions and 52 deletions

View File

@@ -1,5 +1,5 @@
#
# Copyright (C) 2017-2018 Intel Corporation
# Copyright (C) 2017-2019 Intel Corporation
#
# SPDX-License-Identifier: MIT
#
@@ -9,4 +9,8 @@ set(IGDRCL_SRCS_tests_compiler_interface
${CMAKE_CURRENT_SOURCE_DIR}/binary_cache_tests.cpp
${CMAKE_CURRENT_SOURCE_DIR}/compiler_interface_tests.cpp
)
get_property(NEO_CORE_COMPILER_INTERFACE_TESTS GLOBAL PROPERTY NEO_CORE_COMPILER_INTERFACE_TESTS)
list(APPEND IGDRCL_SRCS_tests_compiler_interface ${NEO_CORE_COMPILER_INTERFACE_TESTS})
target_sources(igdrcl_tests PRIVATE ${IGDRCL_SRCS_tests_compiler_interface})

View File

@@ -94,6 +94,11 @@ TEST_P(KernelArgInfoTest, Create_Simple) {
// included in the setup of fixture
}
TEST_P(KernelArgInfoTest, WhenQueryingWithNullptrKernelNameTheniReturnNullptr) {
auto kernelInfo = this->pProgram->getKernelInfo(nullptr);
EXPECT_EQ(nullptr, kernelInfo);
}
TEST_P(KernelArgInfoTest, getKernelArgAcessQualifier) {
cl_kernel_arg_access_qualifier param_value = 0;
queryArgInfo<cl_kernel_arg_access_qualifier>(CL_KERNEL_ARG_ACCESS_QUALIFIER, param_value);

View File

@@ -436,6 +436,8 @@ class CommandStreamReceiverMock : public CommandStreamReceiver {
typedef CommandStreamReceiver BaseClass;
public:
using CommandStreamReceiver::executionEnvironment;
using BaseClass::CommandStreamReceiver;
CommandStreamReceiverMock() : BaseClass(*(new ExecutionEnvironment)) {
this->mockExecutionEnvironment.reset(&this->executionEnvironment);
@@ -443,12 +445,16 @@ class CommandStreamReceiverMock : public CommandStreamReceiver {
void makeResident(GraphicsAllocation &graphicsAllocation) override {
residency[graphicsAllocation.getUnderlyingBuffer()] = graphicsAllocation.getUnderlyingBufferSize();
CommandStreamReceiver::makeResident(graphicsAllocation);
if (passResidencyCallToBaseClass) {
CommandStreamReceiver::makeResident(graphicsAllocation);
}
}
void makeNonResident(GraphicsAllocation &graphicsAllocation) override {
residency.erase(graphicsAllocation.getUnderlyingBuffer());
CommandStreamReceiver::makeNonResident(graphicsAllocation);
if (passResidencyCallToBaseClass) {
CommandStreamReceiver::makeNonResident(graphicsAllocation);
}
}
FlushStamp flush(BatchBuffer &batchBuffer, ResidencyContainer &allocationsForResidency) override {
@@ -479,6 +485,7 @@ class CommandStreamReceiverMock : public CommandStreamReceiver {
}
std::map<const void *, size_t> residency;
bool passResidencyCallToBaseClass = true;
std::unique_ptr<ExecutionEnvironment> mockExecutionEnvironment;
};
@@ -1616,6 +1623,76 @@ HWTEST_F(KernelResidencyTest, givenKernelWhenMakeResidentIsCalledThenKernelIsaIs
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
}
HWTEST_F(KernelResidencyTest, givenKernelWhenMakeResidentIsCalledThenExportedFunctionsIsaAllocationIsMadeResident) {
auto pKernelInfo = std::make_unique<KernelInfo>();
auto &commandStreamReceiver = pDevice->getUltCommandStreamReceiver<FamilyType>();
commandStreamReceiver.storeMakeResidentAllocations = true;
auto memoryManager = commandStreamReceiver.getMemoryManager();
pKernelInfo->kernelAllocation = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize});
MockProgram program(*pDevice->getExecutionEnvironment());
auto exportedFunctionsSurface = std::make_unique<MockGraphicsAllocation>();
program.exportedFunctionsSurface = exportedFunctionsSurface.get();
std::unique_ptr<MockKernel> pKernel(new MockKernel(&program, *pKernelInfo, *pDevice));
ASSERT_EQ(CL_SUCCESS, pKernel->initialize());
EXPECT_EQ(0u, commandStreamReceiver.makeResidentAllocations.size());
pKernel->makeResident(pDevice->getCommandStreamReceiver());
EXPECT_TRUE(commandStreamReceiver.isMadeResident(program.exportedFunctionsSurface));
// check getResidency as well
std::vector<NEO::Surface *> residencySurfaces;
pKernel->getResidency(residencySurfaces);
std::unique_ptr<NEO::ExecutionEnvironment> mockCsrExecEnv;
{
CommandStreamReceiverMock csrMock;
csrMock.passResidencyCallToBaseClass = false;
for (const auto &s : residencySurfaces) {
s->makeResident(csrMock);
delete s;
}
EXPECT_EQ(1U, csrMock.residency.count(exportedFunctionsSurface->getUnderlyingBuffer()));
mockCsrExecEnv = std::move(csrMock.mockExecutionEnvironment);
}
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
}
HWTEST_F(KernelResidencyTest, givenKernelWhenMakeResidentIsCalledThenGlobalBufferIsMadeResident) {
auto pKernelInfo = std::make_unique<KernelInfo>();
auto &commandStreamReceiver = pDevice->getUltCommandStreamReceiver<FamilyType>();
commandStreamReceiver.storeMakeResidentAllocations = true;
auto memoryManager = commandStreamReceiver.getMemoryManager();
pKernelInfo->kernelAllocation = memoryManager->allocateGraphicsMemoryWithProperties(MockAllocationProperties{MemoryConstants::pageSize});
MockProgram program(*pDevice->getExecutionEnvironment());
program.globalSurface = new MockGraphicsAllocation();
std::unique_ptr<MockKernel> pKernel(new MockKernel(&program, *pKernelInfo, *pDevice));
ASSERT_EQ(CL_SUCCESS, pKernel->initialize());
EXPECT_EQ(0u, commandStreamReceiver.makeResidentAllocations.size());
pKernel->makeResident(pDevice->getCommandStreamReceiver());
EXPECT_TRUE(commandStreamReceiver.isMadeResident(program.globalSurface));
std::vector<NEO::Surface *> residencySurfaces;
pKernel->getResidency(residencySurfaces);
std::unique_ptr<NEO::ExecutionEnvironment> mockCsrExecEnv;
{
CommandStreamReceiverMock csrMock;
csrMock.passResidencyCallToBaseClass = false;
for (const auto &s : residencySurfaces) {
s->makeResident(csrMock);
delete s;
}
EXPECT_EQ(1U, csrMock.residency.count(program.globalSurface->getUnderlyingBuffer()));
mockCsrExecEnv = std::move(csrMock.mockExecutionEnvironment);
}
memoryManager->freeGraphicsMemory(pKernelInfo->kernelAllocation);
}
HWTEST_F(KernelResidencyTest, givenKernelWhenItUsesIndirectUnifiedMemoryDeviceAllocationThenTheyAreMadeResident) {
MockKernelWithInternals mockKernel(*this->pDevice);
auto &commandStreamReceiver = this->pDevice->getUltCommandStreamReceiver<FamilyType>();

View File

@@ -25,25 +25,35 @@ class GraphicsAllocation;
class MockProgram : public Program {
public:
using Program::createProgramFromBinary;
using Program::getKernelNamesString;
using Program::getProgramCompilerVersion;
using Program::isKernelDebugEnabled;
using Program::linkBinary;
using Program::prepareLinkerInputStorage;
using Program::rebuildProgramFromIr;
using Program::resolveProgramBinary;
using Program::updateNonUniformFlag;
using Program::areSpecializationConstantsInitialized;
using Program::constantSurface;
using Program::context;
using Program::elfBinary;
using Program::elfBinarySize;
using Program::exportedFunctionsSurface;
using Program::genBinary;
using Program::genBinarySize;
using Program::globalSurface;
using Program::irBinary;
using Program::irBinarySize;
using Program::isProgramBinaryResolved;
using Program::isSpirV;
using Program::linkerInput;
using Program::pDevice;
using Program::programBinaryType;
using Program::specConstantsIds;
using Program::specConstantsSizes;
using Program::specConstantsValues;
using Program::symbols;
using Program::sourceCode;

View File

@@ -108,18 +108,24 @@ TEST_F(KernelDataTest, PrintfString) {
iOpenCL::SPatchString printfString;
printfString.Token = PATCH_TOKEN_STRING;
printfString.Size = static_cast<uint32_t>(sizeof(SPatchString) + strSize);
printfString.Index = 0;
printfString.StringSize = static_cast<uint32_t>(strSize);
cl_char *pPrintfString = new cl_char[printfString.Size];
iOpenCL::SPatchString emptyString;
emptyString.Token = PATCH_TOKEN_STRING;
emptyString.Size = static_cast<uint32_t>(sizeof(SPatchString));
emptyString.Index = 1;
emptyString.StringSize = 0;
cl_char *pPrintfString = new cl_char[printfString.Size + emptyString.Size];
memcpy_s(pPrintfString, sizeof(SPatchString), &printfString, sizeof(SPatchString));
memcpy_s((cl_char *)pPrintfString + sizeof(printfString), strSize, stringValue, strSize);
memcpy_s((cl_char *)pPrintfString + printfString.Size, emptyString.Size, &emptyString, emptyString.Size);
pPatchList = (void *)pPrintfString;
patchListSize = printfString.Size;
patchListSize = printfString.Size + emptyString.Size;
buildAndDecode();
@@ -1387,3 +1393,31 @@ TEST_F(KernelDataTest, PATCH_TOKEN_ALLOCATE_SIP_SURFACE) {
EXPECT_EQ(token.Token, pKernelInfo->patchInfo.pAllocateSystemThreadSurface->Token);
EXPECT_EQ(token.PerThreadSystemThreadSurfaceSize, pKernelInfo->patchInfo.pAllocateSystemThreadSurface->PerThreadSystemThreadSurfaceSize);
}
TEST_F(KernelDataTest, givenSymbolTablePatchTokenThenLinkerInputIsCreated) {
SPatchFunctionTableInfo token;
token.Token = PATCH_TOKEN_PROGRAM_SYMBOL_TABLE;
token.Size = static_cast<uint32_t>(sizeof(SPatchFunctionTableInfo));
token.NumEntries = 0;
pPatchList = &token;
patchListSize = token.Size;
buildAndDecode();
EXPECT_NE(nullptr, program->linkerInput);
}
TEST_F(KernelDataTest, givenRelocationTablePatchTokenThenLinkerInputIsCreated) {
SPatchFunctionTableInfo token;
token.Token = PATCH_TOKEN_PROGRAM_RELOCATION_TABLE;
token.Size = static_cast<uint32_t>(sizeof(SPatchFunctionTableInfo));
token.NumEntries = 0;
pPatchList = &token;
patchListSize = token.Size;
buildAndDecode();
EXPECT_NE(nullptr, program->linkerInput);
}

View File

@@ -5,9 +5,11 @@
*
*/
#include "core/unit_tests/compiler_interface/linker_mock.h"
#include "runtime/helpers/string.h"
#include "runtime/memory_manager/allocations_list.h"
#include "runtime/memory_manager/graphics_allocation.h"
#include "runtime/memory_manager/svm_memory_manager.h"
#include "runtime/platform/platform.h"
#include "runtime/program/program.h"
#include "test.h"
@@ -22,17 +24,17 @@ using namespace iOpenCL;
static const char constValue[] = "11223344";
static const char globalValue[] = "55667788";
class ProgramDataTest : public testing::Test,
public ContextFixture,
public PlatformFixture,
public ProgramFixture {
template <typename ProgramType>
class ProgramDataTestBase : public testing::Test,
public ContextFixture,
public PlatformFixture,
public ProgramFixture {
using ContextFixture::SetUp;
using PlatformFixture::SetUp;
public:
ProgramDataTest() {
ProgramDataTestBase() {
memset(&programBinaryHeader, 0x00, sizeof(SProgramBinaryHeader));
pCurPtr = nullptr;
pProgramPatchList = nullptr;
@@ -48,7 +50,7 @@ class ProgramDataTest : public testing::Test,
ContextFixture::SetUp(1, &device);
ProgramFixture::SetUp();
CreateProgramWithSource(
CreateProgramWithSource<ProgramType>(
pContext,
&device,
"CopyBuffer_simd8.cl");
@@ -120,7 +122,8 @@ class ProgramDataTest : public testing::Test,
uint32_t programPatchListSize;
};
void ProgramDataTest::buildAndDecodeProgramPatchList() {
template <typename ProgramType>
void ProgramDataTestBase<ProgramType>::buildAndDecodeProgramPatchList() {
size_t headerSize = sizeof(SProgramBinaryHeader);
cl_int error = CL_SUCCESS;
@@ -154,6 +157,9 @@ void ProgramDataTest::buildAndDecodeProgramPatchList() {
delete[] pProgramData;
}
using ProgramDataTest = ProgramDataTestBase<NEO::Program>;
using MockProgramDataTest = ProgramDataTestBase<MockProgram>;
TEST_F(ProgramDataTest, EmptyProgramBinaryHeader) {
buildAndDecodeProgramPatchList();
}
@@ -168,6 +174,113 @@ TEST_F(ProgramDataTest, AllocateConstantMemorySurfaceProgramBinaryInfo) {
EXPECT_EQ(0, memcmp(constValue, reinterpret_cast<char *>(pProgram->getConstantSurface()->getUnderlyingBuffer()), constSize));
}
TEST_F(MockProgramDataTest, whenGlobalConstantsAreExportedThenAllocateSurfacesAsSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupConstantAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalConstants = true;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
ASSERT_NE(nullptr, pProgram->getConstantSurface());
EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
}
TEST_F(MockProgramDataTest, whenGlobalConstantsAreNotExportedThenAllocateSurfacesAsNonSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupConstantAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalConstants = false;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
ASSERT_NE(nullptr, pProgram->getConstantSurface());
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
}
TEST_F(MockProgramDataTest, whenGlobalConstantsAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupConstantAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalConstants = true;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
ASSERT_NE(nullptr, pProgram->getConstantSurface());
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getConstantSurface()->getGpuAddress())));
}
TEST_F(MockProgramDataTest, whenGlobalVariablesAreExportedThenAllocateSurfacesAsSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupGlobalAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalVariables = true;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
buildAndDecodeProgramPatchList();
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
EXPECT_NE(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
}
TEST_F(MockProgramDataTest, whenGlobalVariablesAreExportedButContextUnavailableThenAllocateSurfacesAsNonSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupGlobalAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalVariables = true;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
}
TEST_F(MockProgramDataTest, whenGlobalVariablesAreNotExportedThenAllocateSurfacesAsNonSvm) {
if (this->pContext->getSVMAllocsManager() == nullptr) {
return;
}
setupGlobalAllocation();
std::unique_ptr<WhiteBox<NEO::LinkerInput>> mockLinkerInput = std::make_unique<WhiteBox<NEO::LinkerInput>>();
mockLinkerInput->traits.exportsGlobalVariables = false;
static_cast<MockProgram *>(pProgram)->linkerInput = std::move(mockLinkerInput);
static_cast<MockProgram *>(pProgram)->context = nullptr;
buildAndDecodeProgramPatchList();
static_cast<MockProgram *>(pProgram)->context = pContext;
ASSERT_NE(nullptr, pProgram->getGlobalSurface());
EXPECT_EQ(nullptr, this->pContext->getSVMAllocsManager()->getSVMAlloc(reinterpret_cast<const void *>(pProgram->getGlobalSurface()->getGpuAddress())));
}
TEST_F(ProgramDataTest, givenConstantAllocationThatIsInUseByGpuWhenProgramIsBeingDestroyedThenItIsAddedToTemporaryAllocationList) {
setupConstantAllocation();
@@ -676,3 +789,122 @@ TEST_F(ProgramDataTest, GivenProgramWith32bitPointerOptWhenProgramScopeGlobalPoi
globalSurface.mockGfxAllocation.set32BitAllocation(false);
prog->setGlobalSurface(nullptr);
}
TEST_F(ProgramDataTest, givenSymbolTablePatchTokenThenLinkerInputIsCreated) {
SPatchFunctionTableInfo token;
token.Token = PATCH_TOKEN_PROGRAM_SYMBOL_TABLE;
token.Size = static_cast<uint32_t>(sizeof(SPatchFunctionTableInfo));
token.NumEntries = 0;
pProgramPatchList = &token;
programPatchListSize = token.Size;
buildAndDecodeProgramPatchList();
EXPECT_NE(nullptr, pProgram->getLinkerInput());
}
TEST(ProgramLinkBinaryTest, whenLinkerInputEmptyThenLinkSuccessful) {
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
NEO::ExecutionEnvironment env;
MockProgram program{env};
program.linkerInput = std::move(linkerInput);
auto ret = program.linkBinary();
EXPECT_EQ(CL_SUCCESS, ret);
}
TEST(ProgramLinkBinaryTest, whenLinkerUnresolvedExternalThenLinkFailedAndBuildLogAvailable) {
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
NEO::LinkerInput::RelocationInfo relocation = {};
relocation.symbolName = "A";
relocation.offset = 0;
linkerInput->relocations.push_back(NEO::LinkerInput::Relocations{relocation});
linkerInput->traits.requiresPatchingOfInstructionSegments = true;
NEO::ExecutionEnvironment env;
MockProgram program{env};
KernelInfo kernelInfo = {};
kernelInfo.name = "onlyKernel";
std::vector<char> kernelHeap;
kernelHeap.resize(32, 7);
kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
iOpenCL::SKernelBinaryHeaderCommon kernelHeader = {};
kernelHeader.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
program.getKernelInfoArray().push_back(&kernelInfo);
program.linkerInput = std::move(linkerInput);
EXPECT_EQ(nullptr, program.getBuildLog(nullptr));
auto ret = program.linkBinary();
EXPECT_NE(CL_SUCCESS, ret);
program.getKernelInfoArray().clear();
auto buildLog = program.getBuildLog(nullptr);
ASSERT_NE(nullptr, buildLog);
Linker::UnresolvedExternals expectedUnresolvedExternals;
expectedUnresolvedExternals.push_back(Linker::UnresolvedExternal{relocation, 0, false});
auto expectedError = constructLinkerErrorMessage(expectedUnresolvedExternals, std::vector<std::string>{"kernel : " + kernelInfo.name});
EXPECT_THAT(buildLog, ::testing::HasSubstr(expectedError));
}
TEST(ProgramLinkBinaryTest, whenPrepareLinkerInputStorageGetsCalledTwiceThenLinkerInputStorageIsReused) {
ExecutionEnvironment execEnv;
MockProgram program{execEnv};
EXPECT_EQ(nullptr, program.linkerInput);
program.prepareLinkerInputStorage();
EXPECT_NE(nullptr, program.linkerInput);
auto prevLinkerInput = program.getLinkerInput();
program.prepareLinkerInputStorage();
EXPECT_EQ(prevLinkerInput, program.linkerInput.get());
}
TEST_F(ProgramDataTest, whenLinkerInputValidThenIsaIsProperlyPatched) {
auto linkerInput = std::make_unique<WhiteBox<LinkerInput>>();
linkerInput->symbols["A"] = NEO::SymbolInfo{4U, 4U, NEO::SymbolInfo::GlobalVariable};
linkerInput->symbols["B"] = NEO::SymbolInfo{8U, 4U, NEO::SymbolInfo::GlobalConstant};
linkerInput->symbols["C"] = NEO::SymbolInfo{16U, 4U, NEO::SymbolInfo::Function};
linkerInput->relocations.push_back({NEO::LinkerInput::RelocationInfo{"A", 8U}, NEO::LinkerInput::RelocationInfo{"B", 16U}, NEO::LinkerInput::RelocationInfo{"C", 24U}});
linkerInput->traits.requiresPatchingOfInstructionSegments = true;
linkerInput->exportedFunctionsSegmentId = 0;
NEO::ExecutionEnvironment env;
MockProgram program{env};
KernelInfo kernelInfo = {};
kernelInfo.name = "onlyKernel";
std::vector<char> kernelHeap;
kernelHeap.resize(32, 7);
kernelInfo.heapInfo.pKernelHeap = kernelHeap.data();
iOpenCL::SKernelBinaryHeaderCommon kernelHeader = {};
kernelHeader.KernelHeapSize = static_cast<uint32_t>(kernelHeap.size());
kernelInfo.heapInfo.pKernelHeader = &kernelHeader;
MockGraphicsAllocation kernelIsa(kernelHeap.data(), kernelHeap.size());
kernelInfo.kernelAllocation = &kernelIsa;
program.getKernelInfoArray().push_back(&kernelInfo);
program.linkerInput = std::move(linkerInput);
program.exportedFunctionsSurface = kernelInfo.kernelAllocation;
std::vector<char> globalVariablesBuffer;
globalVariablesBuffer.resize(32, 7);
std::vector<char> globalConstantsBuffer;
globalConstantsBuffer.resize(32, 7);
program.globalSurface = new MockGraphicsAllocation(globalVariablesBuffer.data(), globalVariablesBuffer.size());
program.constantSurface = new MockGraphicsAllocation(globalConstantsBuffer.data(), globalConstantsBuffer.size());
program.pDevice = this->pContext->getDevice(0);
auto ret = program.linkBinary();
EXPECT_EQ(CL_SUCCESS, ret);
linkerInput.reset(static_cast<WhiteBox<LinkerInput> *>(program.linkerInput.release()));
for (size_t i = 0; i < linkerInput->relocations.size(); ++i) {
auto expectedPatch = program.globalSurface->getGpuAddress() + linkerInput->symbols[linkerInput->relocations[0][0].symbolName].offset;
auto relocationAddress = kernelHeap.data() + linkerInput->relocations[0][0].offset;
EXPECT_EQ(static_cast<uintptr_t>(expectedPatch), *reinterpret_cast<uintptr_t *>(relocationAddress)) << i;
}
program.getKernelInfoArray().clear();
delete program.globalSurface;
program.globalSurface = nullptr;
delete program.constantSurface;
program.constantSurface = nullptr;
}

View File

@@ -2923,6 +2923,12 @@ TEST_F(ProgramTests, givenProgramWhenUnknownInternalOptionsArePassedThenTheyAreN
EXPECT_TRUE(buildOptions == internalOption);
}
TEST_F(ProgramTests, givenProgramWhenGetSymbolsIsCalledThenMapWithExportedSymbolsIsReturned) {
ExecutionEnvironment executionEnvironment;
MockProgram program(executionEnvironment);
EXPECT_EQ(&program.symbols, &program.getSymbols());
}
class AdditionalOptionsMockProgram : public MockProgram {
public:
AdditionalOptionsMockProgram() : MockProgram(executionEnvironment) {}
@@ -3011,6 +3017,19 @@ TEST(RebuildProgramFromIrTests, givenBinaryProgramWhenKernelRebulildIsNotForcedT
EXPECT_FALSE(pProgram->rebuildProgramFromIrCalled);
}
TEST(Program, whenGetKernelNamesStringIsCalledThenNamesAreProperlyConcatenated) {
ExecutionEnvironment execEnv;
MockProgram program{execEnv};
KernelInfo kernel1 = {};
kernel1.name = "kern1";
KernelInfo kernel2 = {};
kernel2.name = "kern2";
program.getKernelInfoArray().push_back(&kernel1);
program.getKernelInfoArray().push_back(&kernel2);
EXPECT_EQ("kern1;kern2", program.getKernelNamesString());
program.getKernelInfoArray().clear();
}
struct SpecializationConstantProgramMock : public MockProgram {
using MockProgram::MockProgram;
cl_int updateSpecializationConstant(cl_uint specId, size_t specSize, const void *specValue) override {