diff --git a/runtime/device/device.cpp b/runtime/device/device.cpp index 48fe3ce4ce398..a3c65320aa5a7 100644 --- a/runtime/device/device.cpp +++ b/runtime/device/device.cpp @@ -108,6 +108,10 @@ Device::~Device() { commandStreamReceiver = nullptr; } + if (deviceInfo.sourceLevelDebuggerActive && sourceLevelDebugger) { + sourceLevelDebugger->notifyDeviceDestruction(); + } + if (memoryManager) { if (preemptionAllocation) { memoryManager->freeGraphicsMemory(preemptionAllocation); diff --git a/runtime/device/device.h b/runtime/device/device.h index 3511b82efe47e..ea3959f7ba402 100644 --- a/runtime/device/device.h +++ b/runtime/device/device.h @@ -136,6 +136,7 @@ class Device : public BaseObject<_cl_device_id> { std::string deviceExtensions; bool getEnabled64kbPages(); bool isSourceLevelDebuggerActive() const; + SourceLevelDebugger *getSourceLevelDebugger() { return sourceLevelDebugger.get(); } protected: Device() = delete; diff --git a/runtime/platform/extensions.cpp b/runtime/platform/extensions.cpp index 8ca2aa6e97b11..c3f51818d3ec4 100644 --- a/runtime/platform/extensions.cpp +++ b/runtime/platform/extensions.cpp @@ -83,7 +83,7 @@ std::string convertEnabledExtensionsToCompilerInternalOptions(const char *enable while ((pos = extensionsList.find(" ", pos)) != std::string::npos) { extensionsList.replace(pos, 1, ",+"); } - extensionsList = "-cl-ext=-all,+" + extensionsList; + extensionsList = " -cl-ext=-all,+" + extensionsList; return extensionsList; } diff --git a/runtime/program/build.cpp b/runtime/program/build.cpp index ebd97a482dc64..2a49d3d222252 100644 --- a/runtime/program/build.cpp +++ b/runtime/program/build.cpp @@ -24,6 +24,7 @@ #include "runtime/compiler_interface/compiler_options.h" #include "runtime/os_interface/debug_settings_manager.h" #include "runtime/platform/platform.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include "runtime/helpers/validators.h" #include "program.h" #include @@ -91,13 +92,24 @@ cl_int Program::build( break; } - internalOptions.append(platform()->peekCompilerExtensions()); - if (isKernelDebugEnabled()) { internalOptions.append(CompilerOptions::debugKernelEnable); options.append(" -g "); + if (pDevice->getSourceLevelDebugger()) { + if (pDevice->getSourceLevelDebugger()->isOptimizationDisabled()) { + options.append("-cl-opt-disable "); + } + std::string filename; + pDevice->getSourceLevelDebugger()->notifySourceCode(sourceCode.c_str(), sourceCode.size(), filename); + if (!filename.empty()) { + // Add "-s" flag first so it will be ignored by clang in case the options already have this flag set. + options = std::string("-s ") + filename + " " + options; + } + } } + internalOptions.append(platform()->peekCompilerExtensions()); + inputArgs.pInput = (char *)(sourceCode.c_str()); inputArgs.InputSize = (uint32_t)sourceCode.size(); inputArgs.pOptions = options.c_str(); @@ -122,6 +134,15 @@ cl_int Program::build( break; } + if (isKernelDebugEnabled()) { + processDebugData(); + if (pDevice->getSourceLevelDebugger()) { + for (size_t i = 0; i < kernelInfoArray.size(); i++) { + pDevice->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfoArray[i]); + } + } + } + separateBlockKernels(); } while (false); diff --git a/runtime/program/compile.cpp b/runtime/program/compile.cpp index c3544f341804a..9b186b7f8910f 100644 --- a/runtime/program/compile.cpp +++ b/runtime/program/compile.cpp @@ -24,6 +24,7 @@ #include "runtime/compiler_interface/compiler_interface.h" #include "runtime/compiler_interface/compiler_options.h" #include "runtime/platform/platform.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include "runtime/helpers/validators.h" #include "program.h" #include @@ -155,6 +156,16 @@ cl_int Program::compile( if (isKernelDebugEnabled()) { internalOptions.append(CompilerOptions::debugKernelEnable); options.append(" -g "); + if (pDevice->getSourceLevelDebugger()) { + if (pDevice->getSourceLevelDebugger()->isOptimizationDisabled()) { + options.append("-cl-opt-disable "); + } + std::string filename; + pDevice->getSourceLevelDebugger()->notifySourceCode(sourceCode.c_str(), sourceCode.size(), filename); + if (!filename.empty()) { + options = std::string("-s ") + filename + " " + options; + } + } } inputArgs.pInput = pCompileData; diff --git a/runtime/program/link.cpp b/runtime/program/link.cpp index 271dcbcd4c7cd..4907fa9869c2d 100644 --- a/runtime/program/link.cpp +++ b/runtime/program/link.cpp @@ -23,6 +23,7 @@ #include "runtime/compiler_interface/compiler_interface.h" #include "runtime/platform/platform.h" #include "runtime/helpers/validators.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include "program.h" #include "elf/writer.h" #include @@ -147,6 +148,13 @@ cl_int Program::link( break; } programBinaryType = CL_PROGRAM_BINARY_TYPE_EXECUTABLE; + + if (isKernelDebugEnabled()) { + processDebugData(); + for (size_t i = 0; i < kernelInfoArray.size(); i++) { + pDevice->getSourceLevelDebugger()->notifyKernelDebugData(kernelInfoArray[i]); + } + } } else { retVal = pCompilerInterface->createLibrary(*this, inputArgs); if (retVal != CL_SUCCESS) { diff --git a/runtime/program/process_gen_binary.cpp b/runtime/program/process_gen_binary.cpp index b99f1682225e9..dfaf7ac7a398d 100644 --- a/runtime/program/process_gen_binary.cpp +++ b/runtime/program/process_gen_binary.cpp @@ -28,6 +28,7 @@ #include "runtime/memory_manager/memory_manager.h" #include "patch_list.h" #include "patch_shared.h" +#include "program_debug_data.h" #include "program.h" #include "runtime/kernel/kernel.h" @@ -992,4 +993,34 @@ bool Program::validateGenBinaryHeader(const iOpenCL::SProgramBinaryHeader *pGenB pGenBinaryHeader->Version == CURRENT_ICBE_VERSION && validateGenBinaryDevice(static_cast(pGenBinaryHeader->Device)); } + +void Program::processDebugData() { + if (debugData != nullptr) { + SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast(debugData); + + DEBUG_BREAK_IF(programDebugHeader->NumberOfKernels != kernelInfoArray.size()); + + const SKernelDebugDataHeaderIGC *kernelDebugHeader = reinterpret_cast(ptrOffset(programDebugHeader, sizeof(SProgramDebugDataHeaderIGC))); + const char *kernelName = nullptr; + const char *kernelDebugData = nullptr; + + for (uint32_t i = 0; i < programDebugHeader->NumberOfKernels; i++) { + kernelName = reinterpret_cast(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC))); + + auto kernelInfo = kernelInfoArray[i]; + UNRECOVERABLE_IF(kernelInfo->name.compare(0, kernelInfo->name.size(), kernelName) != 0); + + kernelDebugData = ptrOffset(kernelName, kernelDebugHeader->KernelNameSize); + + kernelInfo->debugData.vIsa = kernelDebugData; + kernelInfo->debugData.genIsa = ptrOffset(kernelDebugData, kernelDebugHeader->SizeVisaDbgInBytes); + kernelInfo->debugData.vIsaSize = kernelDebugHeader->SizeVisaDbgInBytes; + kernelInfo->debugData.genIsaSize = kernelDebugHeader->SizeGenIsaDbgInBytes; + + kernelDebugData = ptrOffset(kernelDebugData, kernelDebugHeader->SizeVisaDbgInBytes + kernelDebugHeader->SizeGenIsaDbgInBytes); + kernelDebugHeader = reinterpret_cast(kernelDebugData); + } + } +} + } // namespace OCLRT diff --git a/runtime/program/program.cpp b/runtime/program/program.cpp index 5f3eafb4279dc..a08e24a59e686 100644 --- a/runtime/program/program.cpp +++ b/runtime/program/program.cpp @@ -87,6 +87,7 @@ Program::Program(Context *context, bool isBuiltIn) : context(context), isBuiltIn if (DebugManager.flags.DisableStatelessToStatefulOptimization.get()) { internalOptions += "-cl-intel-greater-than-4GB-buffer-required "; } + kernelDebugEnabled = pDevice->isSourceLevelDebuggerActive(); } if (DebugManager.flags.EnableStatelessToStatefulBufferOffsetOpt.get()) { diff --git a/runtime/program/program.h b/runtime/program/program.h index b37ce1c8ae04e..3901771a47a6b 100644 --- a/runtime/program/program.h +++ b/runtime/program/program.h @@ -188,6 +188,7 @@ class Program : public BaseObject<_cl_program> { void storeLlvmBinary(const void *pSrc, const size_t srcSize); void storeDebugData(const void *pSrc, const size_t srcSize); + void processDebugData(); void updateBuildLog(const Device *pDevice, const char *pErrorString, const size_t errorStringSize); diff --git a/runtime/source_level_debugger/source_level_debugger.cpp b/runtime/source_level_debugger/source_level_debugger.cpp index 454834ffa8572..511e912f21598 100644 --- a/runtime/source_level_debugger/source_level_debugger.cpp +++ b/runtime/source_level_debugger/source_level_debugger.cpp @@ -34,6 +34,7 @@ const char *SourceLevelDebugger::getDebuggerOptionSymbol = "getDebuggerOption"; const char *SourceLevelDebugger::notifyKernelDebugDataSymbol = "notifyKernelDebugData"; const char *SourceLevelDebugger::initSymbol = "init"; const char *SourceLevelDebugger::isDebuggerActiveSymbol = "isDebuggerActive"; +const char *SourceLevelDebugger::notifyDeviceDestructionSymbol = "notifyDeviceDestruction"; class SourceLevelDebugger::SourceLevelDebuggerInterface { public: @@ -46,6 +47,7 @@ class SourceLevelDebugger::SourceLevelDebuggerInterface { typedef int (*NotifyKernelDebugDataFunction)(GfxDbgKernelDebugData *data); typedef int (*InitFunction)(GfxDbgTargetCaps *data); typedef int (*IsDebuggerActiveFunction)(void); + typedef int (*NotifyDeviceDestructionFunction)(GfxDbgDeviceDestructionData *data); NotifyNewDeviceFunction notifyNewDeviceFunc = nullptr; NotifySourceCodeFunction notifySourceCodeFunc = nullptr; @@ -53,6 +55,7 @@ class SourceLevelDebugger::SourceLevelDebuggerInterface { NotifyKernelDebugDataFunction notifyKernelDebugDataFunc = nullptr; InitFunction initFunc = nullptr; IsDebuggerActiveFunction isDebuggerActive = nullptr; + NotifyDeviceDestructionFunction notifyDeviceDestructionFunc = nullptr; }; SourceLevelDebugger *SourceLevelDebugger::create() { @@ -88,6 +91,7 @@ SourceLevelDebugger::SourceLevelDebugger(OsLibrary *library) { UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyKernelDebugDataFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyNewDeviceFunc == nullptr); UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifySourceCodeFunc == nullptr); + UNRECOVERABLE_IF(sourceLevelDebuggerInterface->notifyDeviceDestructionFunc == nullptr); isActive = true; } } @@ -111,31 +115,55 @@ void SourceLevelDebugger::getFunctions() { sourceLevelDebuggerInterface->notifyKernelDebugDataFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyKernelDebugDataSymbol)); sourceLevelDebuggerInterface->initFunc = reinterpret_cast(debuggerLibrary->getProcAddress(initSymbol)); sourceLevelDebuggerInterface->isDebuggerActive = reinterpret_cast(debuggerLibrary->getProcAddress(isDebuggerActiveSymbol)); + sourceLevelDebuggerInterface->notifyDeviceDestructionFunc = reinterpret_cast(debuggerLibrary->getProcAddress(notifyDeviceDestructionSymbol)); } -void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { +bool SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) { if (isActive) { GfxDbgNewDeviceData newDevice; newDevice.version = IGFXDBG_CURRENT_VERSION; newDevice.dh = reinterpret_cast(static_cast(deviceHandle)); newDevice.udh = GfxDeviceHandle(0); - sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice); + int result = sourceLevelDebuggerInterface->notifyNewDeviceFunc(&newDevice); + DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); + static_cast(result); + this->deviceHandle = deviceHandle; } + return false; +} + +bool SourceLevelDebugger::notifyDeviceDestruction() { + if (isActive) { + GfxDbgDeviceDestructionData deviceDestruction; + deviceDestruction.version = IGFXDBG_CURRENT_VERSION; + deviceDestruction.dh = reinterpret_cast(static_cast(this->deviceHandle)); + int result = sourceLevelDebuggerInterface->notifyDeviceDestructionFunc(&deviceDestruction); + DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); + static_cast(result); + this->deviceHandle = 0; + return true; + } + return false; } -void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *source, size_t sourceSize) const { + +bool SourceLevelDebugger::notifySourceCode(const char *source, size_t sourceSize, std::string &file) const { if (isActive) { GfxDbgSourceCode sourceCode; char fileName[FILENAME_MAX] = ""; sourceCode.version = IGFXDBG_CURRENT_VERSION; - sourceCode.hDevice = reinterpret_cast(static_cast(deviceHandle)); + sourceCode.hDevice = reinterpret_cast(static_cast(this->deviceHandle)); sourceCode.sourceCode = source; sourceCode.sourceCodeSize = static_cast(sourceSize); sourceCode.sourceName = &fileName[0]; sourceCode.sourceNameMaxLen = sizeof(fileName); - sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode); + int result = sourceLevelDebuggerInterface->notifySourceCodeFunc(&sourceCode); + DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); + static_cast(result); + file = fileName; } + return false; } bool SourceLevelDebugger::isOptimizationDisabled() const { @@ -157,10 +185,10 @@ bool SourceLevelDebugger::isOptimizationDisabled() const { return false; } -void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const { +bool SourceLevelDebugger::notifyKernelDebugData(const KernelInfo *kernelInfo) const { if (isActive) { GfxDbgKernelDebugData kernelDebugData; - kernelDebugData.hDevice = reinterpret_cast(static_cast(deviceHandle)); + kernelDebugData.hDevice = reinterpret_cast(static_cast(this->deviceHandle)); kernelDebugData.version = IGFXDBG_CURRENT_VERSION; kernelDebugData.hProgram = reinterpret_cast(0); @@ -173,11 +201,14 @@ void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const Ker kernelDebugData.dbgGenIsaBuffer = kernelInfo->debugData.genIsa; kernelDebugData.dbgGenIsaSize = kernelInfo->debugData.genIsaSize; - sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData); + int result = sourceLevelDebuggerInterface->notifyKernelDebugDataFunc(&kernelDebugData); + DEBUG_BREAK_IF(static_cast(result) != IgfxdbgRetVal::IGFXDBG_SUCCESS); + static_cast(result); } + return false; } -void SourceLevelDebugger::initialize(bool useLocalMemory) { +bool SourceLevelDebugger::initialize(bool useLocalMemory) { if (isActive) { GfxDbgTargetCaps caps = {IGFXDBG_CURRENT_VERSION, useLocalMemory}; int result = sourceLevelDebuggerInterface->initFunc(&caps); @@ -185,5 +216,6 @@ void SourceLevelDebugger::initialize(bool useLocalMemory) { isActive = false; } } + return false; } } // namespace OCLRT diff --git a/runtime/source_level_debugger/source_level_debugger.h b/runtime/source_level_debugger/source_level_debugger.h index f8adc753cb486..e3eddd979a742 100644 --- a/runtime/source_level_debugger/source_level_debugger.h +++ b/runtime/source_level_debugger/source_level_debugger.h @@ -23,6 +23,7 @@ #pragma once #include "runtime/os_interface/os_library.h" #include +#include namespace OCLRT { struct KernelInfo; @@ -30,17 +31,18 @@ struct KernelInfo; class SourceLevelDebugger { public: SourceLevelDebugger(OsLibrary *library); - ~SourceLevelDebugger(); + virtual ~SourceLevelDebugger(); SourceLevelDebugger(const SourceLevelDebugger &ref) = delete; SourceLevelDebugger &operator=(const SourceLevelDebugger &) = delete; static SourceLevelDebugger *create(); - bool isDebuggerActive(); - void notifyNewDevice(uint32_t deviceHandle) const; - void notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const; - bool isOptimizationDisabled() const; - void notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const; - void initialize(bool useLocalMemory); + MOCKABLE_VIRTUAL bool isDebuggerActive(); + MOCKABLE_VIRTUAL bool notifyNewDevice(uint32_t deviceHandle); + MOCKABLE_VIRTUAL bool notifyDeviceDestruction(); + MOCKABLE_VIRTUAL bool notifySourceCode(const char *sourceCode, size_t size, std::string &filename) const; + MOCKABLE_VIRTUAL bool isOptimizationDisabled() const; + MOCKABLE_VIRTUAL bool notifyKernelDebugData(const KernelInfo *kernelInfo) const; + MOCKABLE_VIRTUAL bool initialize(bool useLocalMemory); protected: class SourceLevelDebuggerInterface; @@ -51,6 +53,7 @@ class SourceLevelDebugger { std::unique_ptr debuggerLibrary; bool isActive = false; + uint32_t deviceHandle = 0; static const char *notifyNewDeviceSymbol; static const char *notifySourceCodeSymbol; @@ -58,6 +61,7 @@ class SourceLevelDebugger { static const char *notifyKernelDebugDataSymbol; static const char *initSymbol; static const char *isDebuggerActiveSymbol; + static const char *notifyDeviceDestructionSymbol; // OS specific library name static const char *dllName; }; diff --git a/runtime/source_level_debugger/source_level_debugger_stubs.cpp b/runtime/source_level_debugger/source_level_debugger_stubs.cpp index db2b82de89633..a19f01a484a70 100644 --- a/runtime/source_level_debugger/source_level_debugger_stubs.cpp +++ b/runtime/source_level_debugger/source_level_debugger_stubs.cpp @@ -39,16 +39,28 @@ bool SourceLevelDebugger::isDebuggerActive() { return false; } -void SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) const { +bool SourceLevelDebugger::notifyNewDevice(uint32_t deviceHandle) { + return false; +} + +bool SourceLevelDebugger::notifyDeviceDestruction() { + return false; } -void SourceLevelDebugger::notifySourceCode(uint32_t deviceHandle, const char *sourceCode, size_t size) const { + +bool SourceLevelDebugger::notifySourceCode(const char *sourceCode, size_t size, std::string &filename) const { + return false; } + bool SourceLevelDebugger::isOptimizationDisabled() const { return false; } -void SourceLevelDebugger::notifyKernelDebugData(uint32_t deviceHandle, const KernelInfo *kernelInfo) const { + +bool SourceLevelDebugger::notifyKernelDebugData(const KernelInfo *kernelInfo) const { + return false; } -void SourceLevelDebugger::initialize(bool useLocalMemory) { + +bool SourceLevelDebugger::initialize(bool useLocalMemory) { + return false; } } // namespace OCLRT diff --git a/unit_tests/command_queue/enqueue_debug_kernel_tests.cpp b/unit_tests/command_queue/enqueue_debug_kernel_tests.cpp index 814e74c4c2adb..8796e734f6f2d 100644 --- a/unit_tests/command_queue/enqueue_debug_kernel_tests.cpp +++ b/unit_tests/command_queue/enqueue_debug_kernel_tests.cpp @@ -23,6 +23,7 @@ #include "runtime/compiler_interface/compiler_options.h" #include "runtime/command_queue/command_queue.h" #include "runtime/program/program.h" +#include "runtime/source_level_debugger/source_level_debugger.h" #include "unit_tests/fixtures/enqueue_handler_fixture.h" #include "unit_tests/helpers/kernel_binary_helper.h" #include "unit_tests/helpers/kernel_filename_helper.h" @@ -44,6 +45,8 @@ class EnqueueDebugKernelTest : public ProgramSimpleFixture, void SetUp() override { ProgramSimpleFixture::SetUp(); device = pDevice; + pDevice->sourceLevelDebugger.reset(new SourceLevelDebugger(nullptr)); + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { std::string filename; std::string kernelOption(CompilerOptions::debugKernelEnable); diff --git a/unit_tests/libult/source_level_debugger_library.cpp b/unit_tests/libult/source_level_debugger_library.cpp index 009b23ac4350a..49c708599bbce 100644 --- a/unit_tests/libult/source_level_debugger_library.cpp +++ b/unit_tests/libult/source_level_debugger_library.cpp @@ -42,6 +42,8 @@ void *DebuggerLibrary::getProcAddress(const std::string &procName) { return reinterpret_cast(init); } else if (procName == "isDebuggerActive") { return reinterpret_cast(isDebuggerActive); + } else if (procName == "notifyDeviceDestruction") { + return reinterpret_cast(notifyDeviceDestruction); } return nullptr; } @@ -66,6 +68,9 @@ int DebuggerLibrary::notifySourceCode(GfxDbgSourceCode *sourceCode) { if (interceptor) { interceptor->sourceCodeArgIn = *sourceCode; interceptor->sourceCodeCalled = true; + if (interceptor->sourceCodeArgOut && sourceCode->sourceNameMaxLen > 0) { + memcpy_s(sourceCode->sourceName, sourceCode->sourceNameMaxLen, interceptor->sourceCodeArgOut->sourceName, interceptor->sourceCodeArgOut->sourceNameMaxLen); + } return interceptor->sourceCodeRetVal; } return IgfxdbgRetVal::IGFXDBG_SUCCESS; @@ -105,3 +110,12 @@ int DebuggerLibrary::init(GfxDbgTargetCaps *targetCaps) { int DebuggerLibrary::isDebuggerActive(void) { return debuggerActive ? 1 : 0; } + +int DebuggerLibrary::notifyDeviceDestruction(GfxDbgDeviceDestructionData *deviceDestruction) { + if (interceptor) { + interceptor->deviceDestructionArgIn = *deviceDestruction; + interceptor->deviceDestructionCalled = true; + return interceptor->deviceDestructionRetVal; + } + return IgfxdbgRetVal::IGFXDBG_SUCCESS; +} \ No newline at end of file diff --git a/unit_tests/libult/source_level_debugger_library.h b/unit_tests/libult/source_level_debugger_library.h index 1ffe73442365d..bca729e145a6f 100644 --- a/unit_tests/libult/source_level_debugger_library.h +++ b/unit_tests/libult/source_level_debugger_library.h @@ -32,24 +32,28 @@ struct DebuggerLibraryInterceptor { GfxDbgOption optionArgIn; GfxDbgKernelDebugData kernelDebugDataArgIn; GfxDbgTargetCaps targetCapsArgIn; + GfxDbgDeviceDestructionData deviceDestructionArgIn; GfxDbgNewDeviceData *newDeviceArgOut = nullptr; GfxDbgSourceCode *sourceCodeArgOut = nullptr; GfxDbgOption *optionArgOut = nullptr; GfxDbgKernelDebugData *kernelDebugDataArgOut = nullptr; GfxDbgTargetCaps *targetCapsArgOut = nullptr; + GfxDbgDeviceDestructionData *deviceDestructionArgOut = nullptr; bool newDeviceCalled = false; bool sourceCodeCalled = false; bool optionCalled = false; bool kernelDebugDataCalled = false; bool initCalled = false; + bool deviceDestructionCalled = false; int newDeviceRetVal = 0; int sourceCodeRetVal = 0; int optionRetVal = 0; int kernelDebugDataRetVal = 0; int initRetVal = 0; + int deviceDestructionRetVal = 0; }; class DebuggerLibrary : public OCLRT::OsLibrary { @@ -96,6 +100,7 @@ class DebuggerLibrary : public OCLRT::OsLibrary { static int notifyKernelDebugData(GfxDbgKernelDebugData *); static int init(GfxDbgTargetCaps *); static int isDebuggerActive(void); + static int notifyDeviceDestruction(GfxDbgDeviceDestructionData *); static bool isLibraryAvailable; static bool debuggerActive; diff --git a/unit_tests/mocks/CMakeLists.txt b/unit_tests/mocks/CMakeLists.txt index 6e2690a8afbfc..c5a67670f89eb 100644 --- a/unit_tests/mocks/CMakeLists.txt +++ b/unit_tests/mocks/CMakeLists.txt @@ -58,6 +58,7 @@ set(IGDRCL_SRCS_tests_mocks ${CMAKE_CURRENT_SOURCE_DIR}/mock_sampler.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_sip.cpp ${CMAKE_CURRENT_SOURCE_DIR}/mock_sip.h + ${CMAKE_CURRENT_SOURCE_DIR}/mock_source_level_debugger.h ${CMAKE_CURRENT_SOURCE_DIR}/mock_submissions_aggregator.h ) diff --git a/unit_tests/mocks/mock_source_level_debugger.h b/unit_tests/mocks/mock_source_level_debugger.h new file mode 100644 index 0000000000000..f7cf4906bd5c8 --- /dev/null +++ b/unit_tests/mocks/mock_source_level_debugger.h @@ -0,0 +1,120 @@ +/* +* Copyright (c) 2018, Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +#pragma once + +#include "runtime/source_level_debugger/source_level_debugger.h" +#include "gmock/gmock.h" + +#include + +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Winconsistent-missing-override" +#endif + +using namespace OCLRT; + +class MockSourceLevelDebugger : public SourceLevelDebugger { + public: + using SourceLevelDebugger::debuggerLibrary; + using SourceLevelDebugger::deviceHandle; + + MockSourceLevelDebugger() : SourceLevelDebugger(SourceLevelDebugger::loadDebugger()) { + this->deviceHandle = mockDeviceHandle; + } + + MockSourceLevelDebugger(OsLibrary *library) : SourceLevelDebugger(library) { + this->deviceHandle = mockDeviceHandle; + } + + void setActive(bool active) { + isActive = active; + } + static const uint32_t mockDeviceHandle = 23; +}; + +class MockActiveSourceLevelDebugger : public SourceLevelDebugger { + public: + using SourceLevelDebugger::debuggerLibrary; + using SourceLevelDebugger::deviceHandle; + + MockActiveSourceLevelDebugger() : SourceLevelDebugger(nullptr) { + this->deviceHandle = mockDeviceHandle; + isActive = true; + } + + MockActiveSourceLevelDebugger(OsLibrary *library) : SourceLevelDebugger(nullptr) { + this->deviceHandle = mockDeviceHandle; + isActive = true; + } + + void setActive(bool active) { + isActive = active; + } + bool isOptimizationDisabled() const override { + return isOptDisabled; + } + bool isDebuggerActive() override { + return isActive; + } + bool notifyNewDevice(uint32_t deviceHandle) override { + return false; + } + bool notifyDeviceDestruction() override { + return true; + } + bool notifySourceCode(const char *sourceCode, size_t size, std::string &filename) const override { + filename = sourceCodeFilename; + return true; + } + bool notifyKernelDebugData(const KernelInfo *kernelInfo) const override { + return false; + } + bool initialize(bool useLocalMemory) override { + return false; + } + + static const uint32_t mockDeviceHandle = 23; + bool isOptDisabled = false; + std::string sourceCodeFilename; +}; + +class GMockSourceLevelDebugger : public SourceLevelDebugger { + public: + GMockSourceLevelDebugger(OsLibrary *library) : SourceLevelDebugger(library) { + } + void setActive(bool active) { + isActive = active; + } + + bool isDebuggerActive() override { + return isActive; + } + + MOCK_METHOD0(notifyDeviceDestruction, bool(void)); + MOCK_CONST_METHOD1(notifyKernelDebugData, bool(const KernelInfo *)); + MOCK_CONST_METHOD0(isOptimizationDisabled, bool()); + MOCK_METHOD1(notifyNewDevice, bool(uint32_t)); + MOCK_CONST_METHOD3(notifySourceCode, bool(const char *, size_t, std::string &)); + MOCK_METHOD1(initialize, bool(bool)); +}; diff --git a/unit_tests/platform/platform_tests.cpp b/unit_tests/platform/platform_tests.cpp index d0fd4cff0aeeb..43ecd08b2110d 100644 --- a/unit_tests/platform/platform_tests.cpp +++ b/unit_tests/platform/platform_tests.cpp @@ -83,7 +83,7 @@ TEST_F(PlatformTest, PlatformgetAsCompilerEnabledExtensionsString) { pPlatform->initialize(numPlatformDevices, platformDevices); compilerExtensions = pPlatform->peekCompilerExtensions(); - EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("-cl-ext=-all,+cl"))); + EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string(" -cl-ext=-all,+cl"))); if (std::string(pPlatform->getDevice(0)->getDeviceInfo().clVersion).find("OpenCL 2.1") != std::string::npos) { EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("cl_khr_subgroups"))); } @@ -160,7 +160,7 @@ TEST_F(PlatformTest, getAsCompilerEnabledExtensionsString) { EXPECT_THAT(extensionsList, ::testing::HasSubstr(std::string("cl_khr_3d_image_writes"))); std::string compilerExtensions = convertEnabledExtensionsToCompilerInternalOptions(extensionsList.c_str()); - EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("-cl-ext=-all,+cl"))); + EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string(" -cl-ext=-all,+cl"))); if (hwInfo->capabilityTable.clVersionSupport > 20) { EXPECT_THAT(compilerExtensions, ::testing::HasSubstr(std::string("cl_khr_subgroups"))); diff --git a/unit_tests/program/CMakeLists.txt b/unit_tests/program/CMakeLists.txt index 13fc1feef863e..451e9d69a381c 100644 --- a/unit_tests/program/CMakeLists.txt +++ b/unit_tests/program/CMakeLists.txt @@ -27,6 +27,7 @@ set(IGDRCL_SRCS_tests_program ${CMAKE_CURRENT_SOURCE_DIR}/kernel_info_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/printf_handler_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/printf_helper_tests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/process_debug_data_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/process_elf_binary_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/process_spir_binary_tests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/program_data_tests.cpp diff --git a/unit_tests/program/process_debug_data_tests.cpp b/unit_tests/program/process_debug_data_tests.cpp new file mode 100644 index 0000000000000..378eb959379f2 --- /dev/null +++ b/unit_tests/program/process_debug_data_tests.cpp @@ -0,0 +1,95 @@ +/* +* Copyright (c) 2018, Intel Corporation +* +* Permission is hereby granted, free of charge, to any person obtaining a +* copy of this software and associated documentation files (the "Software"), +* to deal in the Software without restriction, including without limitation +* the rights to use, copy, modify, merge, publish, distribute, sublicense, +* and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included +* in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +* OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "unit_tests/program/program_tests.h" +#include "unit_tests/mocks/mock_program.h" +#include "program_debug_data.h" +#include "test.h" + +#include +using namespace iOpenCL; +using namespace OCLRT; + +TEST_F(ProgramTests, GivenProgramWithDebugDataForTwoKernelsWhenPorcessedThenDebugDataIsSetInKernelInfos) { + const char kernelName1[] = "kernel1"; + const char kernelName2[] = "kernel2"; + uint32_t kernelNameSize = static_cast(sizeof(kernelName1)); + uint32_t genIsaSize = 8; + uint32_t visaSize = 8; + size_t debugDataSize = sizeof(SProgramDebugDataHeaderIGC) + 2 * (sizeof(SKernelDebugDataHeaderIGC) + kernelNameSize + genIsaSize + visaSize); + std::unique_ptr debugData(new char[debugDataSize]); + + KernelInfo *kernelInfo1 = new KernelInfo(); + kernelInfo1->name = kernelName1; + KernelInfo *kernelInfo2 = new KernelInfo(); + kernelInfo2->name = kernelName2; + std::unique_ptr program(new MockProgram()); + + SProgramDebugDataHeaderIGC *programDebugHeader = reinterpret_cast(debugData.get()); + programDebugHeader->NumberOfKernels = 2; + + SKernelDebugDataHeaderIGC *kernelDebugHeader = reinterpret_cast(ptrOffset(programDebugHeader, sizeof(SProgramDebugDataHeaderIGC))); + kernelDebugHeader->KernelNameSize = kernelNameSize; + kernelDebugHeader->SizeGenIsaDbgInBytes = genIsaSize; + kernelDebugHeader->SizeVisaDbgInBytes = visaSize; + + char *kernelName = reinterpret_cast(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC))); + memcpy_s(kernelName, kernelNameSize, kernelName1, kernelNameSize); + + char *vIsa1 = (ptrOffset(kernelName, kernelNameSize)); + memset(vIsa1, 10, visaSize); + + char *genIsa1 = (ptrOffset(vIsa1, visaSize)); + memset(genIsa1, 20, genIsaSize); + + kernelDebugHeader = reinterpret_cast(ptrOffset(vIsa1, genIsaSize + visaSize)); + kernelDebugHeader->KernelNameSize = kernelNameSize; + kernelDebugHeader->SizeGenIsaDbgInBytes = genIsaSize; + kernelDebugHeader->SizeVisaDbgInBytes = visaSize; + kernelName = reinterpret_cast(ptrOffset(kernelDebugHeader, sizeof(SKernelDebugDataHeaderIGC))); + + memcpy_s(kernelName, kernelNameSize, kernelName2, kernelNameSize); + + char *vIsa2 = (ptrOffset(kernelName, kernelNameSize)); + memset(vIsa2, 10, visaSize); + + char *genIsa2 = (ptrOffset(vIsa2, visaSize)); + memset(genIsa2, 20, genIsaSize); + + program->storeDebugData(debugData.get(), debugDataSize); + + program->addKernelInfo(kernelInfo1); + program->addKernelInfo(kernelInfo2); + + program->processDebugData(); + + size_t programDebugDataSize = 0; + EXPECT_EQ(genIsaSize, kernelInfo1->debugData.genIsaSize); + EXPECT_EQ(visaSize, kernelInfo1->debugData.vIsaSize); + EXPECT_EQ(ptrDiff(vIsa1, debugData.get()), ptrDiff(kernelInfo1->debugData.vIsa, program->getDebugDataBinary(programDebugDataSize))); + EXPECT_EQ(ptrDiff(genIsa1, debugData.get()), ptrDiff(kernelInfo1->debugData.genIsa, program->getDebugDataBinary(programDebugDataSize))); + + EXPECT_EQ(genIsaSize, kernelInfo2->debugData.genIsaSize); + EXPECT_EQ(visaSize, kernelInfo2->debugData.vIsaSize); + EXPECT_EQ(ptrDiff(vIsa2, debugData.get()), ptrDiff(kernelInfo2->debugData.vIsa, program->getDebugDataBinary(programDebugDataSize))); + EXPECT_EQ(ptrDiff(genIsa2, debugData.get()), ptrDiff(kernelInfo2->debugData.genIsa, program->getDebugDataBinary(programDebugDataSize))); +} \ No newline at end of file diff --git a/unit_tests/program/program_with_kernel_debug_tests.cpp b/unit_tests/program/program_with_kernel_debug_tests.cpp index a66b1a8348fda..71f3daa3be406 100644 --- a/unit_tests/program/program_with_kernel_debug_tests.cpp +++ b/unit_tests/program/program_with_kernel_debug_tests.cpp @@ -26,6 +26,7 @@ #include "unit_tests/helpers/kernel_binary_helper.h" #include "unit_tests/helpers/kernel_filename_helper.h" #include "unit_tests/mocks/mock_program.h" +#include "unit_tests/mocks/mock_source_level_debugger.h" #include "unit_tests/program/program_tests.h" #include "unit_tests/program/program_from_binary.h" #include "test.h" @@ -107,6 +108,37 @@ TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsCompi } } +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugAndOptDisabledWhenProgramIsCompiledThenOptionsIncludeClOptDisableFlag) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + + MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger; + sourceLevelDebugger->isOptDisabled = true; + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->compile(1, &device, nullptr, + 0, nullptr, nullptr, + nullptr, + nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr("-cl-opt-disable")); + } +} + +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsCompiledThenOptionsStartsWithDashSFilename) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger; + sourceLevelDebugger->sourceCodeFilename = "debugFileName"; + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->compile(1, &device, nullptr, + 0, nullptr, nullptr, + nullptr, + nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pProgram->getOptions(), ::testing::StartsWith("-s debugFileName")); + } +} + TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenInternalOptionsIncludeDebugFlag) { if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { std::string receivedInternalOptions; @@ -131,6 +163,78 @@ TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuilt } } +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugAndOptDisabledWhenProgramIsBuiltThenOptionsIncludeClOptDisableFlag) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + + MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger; + sourceLevelDebugger->isOptDisabled = true; + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pProgram->getOptions(), ::testing::HasSubstr("-cl-opt-disable")); + } +} + +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenOptionsStartsWithDashSFilename) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + + MockActiveSourceLevelDebugger *sourceLevelDebugger = new MockActiveSourceLevelDebugger; + sourceLevelDebugger->sourceCodeFilename = "debugFileName"; + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); + EXPECT_THAT(pProgram->getOptions(), ::testing::StartsWith("-s debugFileName")); + } +} + +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsBuiltThenDebuggerIsNotifiedWithKernelDebugData) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + + GMockSourceLevelDebugger *sourceLevelDebugger = new GMockSourceLevelDebugger(nullptr); + ON_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).WillByDefault(::testing::Return(false)); + ON_CALL(*sourceLevelDebugger, isOptimizationDisabled()).WillByDefault(::testing::Return(false)); + + EXPECT_CALL(*sourceLevelDebugger, isOptimizationDisabled()).Times(1); + EXPECT_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).Times(1); + EXPECT_CALL(*sourceLevelDebugger, notifyKernelDebugData(::testing::_)).Times(1); + + sourceLevelDebugger->setActive(true); + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); + } +} + +TEST_F(ProgramWithKernelDebuggingTest, givenEnabledKernelDebugWhenProgramIsLinkedThenDebuggerIsNotifiedWithKernelDebugData) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + + GMockSourceLevelDebugger *sourceLevelDebugger = new GMockSourceLevelDebugger(nullptr); + ON_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).WillByDefault(::testing::Return(false)); + ON_CALL(*sourceLevelDebugger, isOptimizationDisabled()).WillByDefault(::testing::Return(false)); + + EXPECT_CALL(*sourceLevelDebugger, isOptimizationDisabled()).Times(1); + EXPECT_CALL(*sourceLevelDebugger, notifySourceCode(::testing::_, ::testing::_, ::testing::_)).Times(1); + EXPECT_CALL(*sourceLevelDebugger, notifyKernelDebugData(::testing::_)).Times(1); + + sourceLevelDebugger->setActive(true); + pDevice->sourceLevelDebugger.reset(sourceLevelDebugger); + + cl_int retVal = pProgram->compile(1, &device, nullptr, + 0, nullptr, nullptr, + nullptr, + nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + + cl_program program = pProgram; + retVal = pProgram->link(1, &device, nullptr, + 1, &program, nullptr, nullptr); + EXPECT_EQ(CL_SUCCESS, retVal); + } +} + TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithKernelDebugEnabledWhenBuiltThenPatchTokenAllocateSipSurfaceHasSizeGreaterThanZero) { if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { retVal = pProgram->build(1, &device, CompilerOptions::debugKernelEnable, nullptr, nullptr, false); @@ -151,3 +255,20 @@ TEST_F(ProgramWithKernelDebuggingTest, givenKernelDebugEnabledWhenProgramIsBuilt EXPECT_NE(0u, debugDataSize); } } + +TEST_F(ProgramWithKernelDebuggingTest, givenProgramWithKernelDebugEnabledWhenProcessDebugDataIsCalledThenKernelInfosAreFilledWithDebugData) { + if (pDevice->getHardwareInfo().pPlatform->eRenderCoreFamily >= IGFX_GEN9_CORE) { + retVal = pProgram->build(1, &device, nullptr, nullptr, nullptr, false); + EXPECT_EQ(CL_SUCCESS, retVal); + + pProgram->processDebugData(); + + auto kernelInfo = pProgram->getKernelInfo("CopyBuffer"); + + EXPECT_NE(0u, kernelInfo->debugData.genIsaSize); + EXPECT_NE(0u, kernelInfo->debugData.vIsaSize); + + EXPECT_NE(nullptr, kernelInfo->debugData.genIsa); + EXPECT_NE(nullptr, kernelInfo->debugData.vIsa); + } +} diff --git a/unit_tests/source_level_debugger/device_tests.cpp b/unit_tests/source_level_debugger/device_tests.cpp index 57e03dae436ad..c2f687137f3e4 100644 --- a/unit_tests/source_level_debugger/device_tests.cpp +++ b/unit_tests/source_level_debugger/device_tests.cpp @@ -25,12 +25,14 @@ #include "unit_tests/helpers/debug_manager_state_restore.h" #include "unit_tests/mocks/mock_builtins.h" #include "unit_tests/mocks/mock_device.h" +#include "unit_tests/mocks/mock_source_level_debugger.h" #include "test.h" using PreambleTest = ::testing::Test; using namespace OCLRT; +template class MockDeviceWithActiveDebugger : public MockDevice { public: class MockOsLibrary : public OsLibrary { @@ -43,13 +45,18 @@ class MockDeviceWithActiveDebugger : public MockDevice { } }; MockDeviceWithActiveDebugger(const HardwareInfo &hwInfo, bool isRootDevice = true) : MockDevice(hwInfo, isRootDevice) { - sourceLevelDebugger.reset(new SourceLevelDebugger(new MockOsLibrary)); + sourceLevelDebuggerCreated = new T(new MockOsLibrary); + sourceLevelDebugger.reset(sourceLevelDebuggerCreated); } void initializeCaps() override { MockDevice::initializeCaps(); this->setSourceLevelDebuggerActive(true); } + T *getSourceLevelDebugger() { + return sourceLevelDebuggerCreated; + } + T *sourceLevelDebuggerCreated = nullptr; }; TEST(DeviceCreation, givenDeviceWithMidThreadPreemptionAndDebuggingActiveWhenDeviceIsCreatedThenCorrectSipKernelIsCreated) { @@ -65,7 +72,7 @@ TEST(DeviceCreation, givenDeviceWithMidThreadPreemptionAndDebuggingActiveWhenDev EXPECT_FALSE(mockBuiltins->getSipKernelCalled); DebugManager.flags.ForcePreemptionMode.set((int32_t)PreemptionMode::MidThread); - auto device = std::unique_ptr(Device::create(nullptr)); + auto device = std::unique_ptr>(Device::create>(nullptr)); EXPECT_TRUE(mockBuiltins->getSipKernelCalled); EXPECT_LE(SipKernelType::DbgCsr, mockBuiltins->getSipKernelType); @@ -88,7 +95,7 @@ TEST(DeviceCreation, givenDeviceWithDisabledPreemptionAndDebuggingActiveWhenDevi EXPECT_FALSE(mockBuiltins->getSipKernelCalled); DebugManager.flags.ForcePreemptionMode.set((int32_t)PreemptionMode::Disabled); - auto device = std::unique_ptr(Device::create(nullptr)); + auto device = std::unique_ptr>(Device::create>(nullptr)); EXPECT_TRUE(mockBuiltins->getSipKernelCalled); EXPECT_LE(SipKernelType::DbgCsr, mockBuiltins->getSipKernelType); @@ -97,3 +104,9 @@ TEST(DeviceCreation, givenDeviceWithDisabledPreemptionAndDebuggingActiveWhenDevi mockBuiltins.reset(); } } + +TEST(DeviceWithSourceLevelDebugger, givenDeviceWithSourceLevelDebuggerActiveWhenDeviceIsDestructedThenSourceLevelDebuggerIsNotified) { + auto device = std::unique_ptr>(Device::create>(nullptr)); + GMockSourceLevelDebugger *gmock = device->getSourceLevelDebugger(); + EXPECT_CALL(*gmock, notifyDeviceDestruction()).Times(1); +} diff --git a/unit_tests/source_level_debugger/source_level_debugger_tests.cpp b/unit_tests/source_level_debugger/source_level_debugger_tests.cpp index b5b414938fcf4..e204885872ed8 100644 --- a/unit_tests/source_level_debugger/source_level_debugger_tests.cpp +++ b/unit_tests/source_level_debugger/source_level_debugger_tests.cpp @@ -27,11 +27,14 @@ #include "unit_tests/fixtures/device_fixture.h" #include "unit_tests/libult/source_level_debugger_library.h" #include "unit_tests/libult/create_command_stream.h" +#include "unit_tests/mocks/mock_source_level_debugger.h" #include #include +#include using namespace OCLRT; +using std::string; using std::unique_ptr; class DebuggerLibraryRestorer { @@ -49,15 +52,6 @@ class DebuggerLibraryRestorer { bool restoreAvailableState = false; }; -class MockSourceLevelDebugger : public SourceLevelDebugger { - public: - using SourceLevelDebugger::debuggerLibrary; - MockSourceLevelDebugger() : SourceLevelDebugger(SourceLevelDebugger::loadDebugger()) {} - void setActive(bool active) { - isActive = active; - } -}; - TEST(SourceLevelDebugger, givenNoKernelDebuggerLibraryWhenSourceLevelDebuggerIsCreatedThenLibraryIsNotLoaded) { DebuggerLibraryRestorer restorer; DebuggerLibrary::setLibraryAvailable(false); @@ -112,15 +106,24 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifySourceCodeIs MockSourceLevelDebugger debugger; + GfxDbgSourceCode argOut; + char fileName[] = "filename"; + argOut.sourceName = fileName; + argOut.sourceNameMaxLen = sizeof(fileName); + interceptor.sourceCodeArgOut = &argOut; + const char source[] = "sourceCode"; - debugger.notifySourceCode(4, source, sizeof(source)); + string file; + debugger.notifySourceCode(source, sizeof(source), file); EXPECT_TRUE(interceptor.sourceCodeCalled); - EXPECT_EQ(reinterpret_cast(static_cast(4u)), interceptor.sourceCodeArgIn.hDevice); + EXPECT_EQ(reinterpret_cast(static_cast(MockSourceLevelDebugger::mockDeviceHandle)), interceptor.sourceCodeArgIn.hDevice); EXPECT_EQ(source, interceptor.sourceCodeArgIn.sourceCode); EXPECT_EQ(sizeof(source), interceptor.sourceCodeArgIn.sourceCodeSize); EXPECT_NE(nullptr, interceptor.sourceCodeArgIn.sourceName); EXPECT_NE(0u, interceptor.sourceCodeArgIn.sourceNameMaxLen); + + EXPECT_STREQ(fileName, file.c_str()); } TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifySourceCodeIsCalledThenDebuggerLibraryFunctionIsNotCalled) { @@ -136,7 +139,8 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifySourceCod debugger.setActive(false); const char source[] = "sourceCode"; - debugger.notifySourceCode(4, source, sizeof(source)); + string file; + debugger.notifySourceCode(source, sizeof(source), file); EXPECT_FALSE(interceptor.sourceCodeCalled); } @@ -153,6 +157,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifyNewDeviceIsC EXPECT_TRUE(interceptor.newDeviceCalled); EXPECT_EQ(reinterpret_cast(static_cast(4u)), interceptor.newDeviceArgIn.dh); + EXPECT_EQ(4u, debugger.deviceHandle); } TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifyNewDeviceIsCalledThenDebuggerLibraryFunctionIsNotCalled) { @@ -289,12 +294,12 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryActiveWhenNotifyKernelDebugD info.heapInfo.pKernelHeader = &kernelHeader; info.heapInfo.pKernelHeap = isa; - debugger.notifyKernelDebugData(6, &info); + debugger.notifyKernelDebugData(&info); EXPECT_TRUE(interceptor.kernelDebugDataCalled); EXPECT_EQ(static_cast(IGFXDBG_CURRENT_VERSION), interceptor.kernelDebugDataArgIn.version); - EXPECT_EQ(reinterpret_cast(6), interceptor.kernelDebugDataArgIn.hDevice); + EXPECT_EQ(reinterpret_cast(static_cast(MockSourceLevelDebugger::mockDeviceHandle)), interceptor.kernelDebugDataArgIn.hDevice); EXPECT_EQ(reinterpret_cast(0), interceptor.kernelDebugDataArgIn.hProgram); EXPECT_EQ(dbgIsa, interceptor.kernelDebugDataArgIn.dbgGenIsaBuffer); @@ -319,7 +324,7 @@ TEST(SourceLevelDebugger, givenKernelDebuggerLibraryNotActiveWhenNotifyKernelDeb debugger.setActive(false); KernelInfo info; - debugger.notifyKernelDebugData(6, &info); + debugger.notifyKernelDebugData(&info); EXPECT_FALSE(interceptor.kernelDebugDataCalled); }