From 697848f3d15cfd8eb1cf41c4c67307cd5bb5f367 Mon Sep 17 00:00:00 2001 From: chmielew Date: Fri, 7 Feb 2020 14:06:50 +0100 Subject: [PATCH] ocloc as shared library, ocloc API Change-Id: Ie866b9ad5ee6de8c8b10f83551e2a3cab9d64a02 --- CMakeLists.txt | 2 +- offline_compiler/CMakeLists.txt | 111 ++++++--- offline_compiler/api.cpp | 128 ++++++++++ offline_compiler/decoder/binary_decoder.cpp | 218 +++++++++--------- offline_compiler/decoder/binary_decoder.h | 12 +- offline_compiler/decoder/binary_encoder.cpp | 132 +++++------ offline_compiler/decoder/binary_encoder.h | 13 +- offline_compiler/main.cpp | 125 +--------- offline_compiler/ocloc_api.cpp | 129 +++++++++++ offline_compiler/ocloc_api.h | 28 +++ offline_compiler/ocloc_arg_helper.cpp | 150 ++++++++++++ offline_compiler/ocloc_arg_helper.h | 77 +++++++ offline_compiler/ocloc_wrapper.cpp | 94 ++++++++ offline_compiler/ocloc_wrapper.h | 33 +++ offline_compiler/offline_compiler.cpp | 54 +++-- offline_compiler/offline_compiler.h | 9 +- offline_compiler/utilities/CMakeLists.txt | 11 +- offline_compiler/utilities/get_path.h | 10 + offline_compiler/utilities/linux/get_path.cpp | 24 ++ .../utilities/windows/get_path.cpp | 12 + .../source/built_ins/kernels/CMakeLists.txt | 5 +- .../source/scheduler/scheduler_binary.cmake | 4 +- opencl/test/unit_test/CMakeLists.txt | 4 +- .../unit_test/offline_compiler/CMakeLists.txt | 47 ++-- .../decoder/decoder_tests.cpp | 12 +- .../decoder/encoder_tests.cpp | 14 +- .../decoder/mock/mock_decoder.h | 1 + .../decoder/mock/mock_encoder.h | 16 +- .../mock/mock_argument_helper.h | 29 +++ .../mock/mock_offline_compiler.h | 2 + .../offline_compiler_tests.cpp | 3 +- .../source/built_ins/kernels/CMakeLists.txt | 4 +- 32 files changed, 1087 insertions(+), 426 deletions(-) create mode 100644 offline_compiler/api.cpp create mode 100644 offline_compiler/ocloc_api.cpp create mode 100644 offline_compiler/ocloc_api.h create mode 100644 offline_compiler/ocloc_arg_helper.cpp create mode 100644 offline_compiler/ocloc_arg_helper.h create mode 100644 offline_compiler/ocloc_wrapper.cpp create mode 100644 offline_compiler/ocloc_wrapper.h create mode 100644 offline_compiler/utilities/get_path.h create mode 100644 offline_compiler/utilities/linux/get_path.cpp create mode 100644 offline_compiler/utilities/windows/get_path.cpp create mode 100644 opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 54587358eb..0548f13435 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -821,7 +821,7 @@ if(MSVC) endif() add_subdirectory_unique(offline_compiler ${NEO_BUILD_DIR}/offline_compiler) -target_compile_definitions(ocloc PRIVATE MOCKABLE_VIRTUAL=) +target_compile_definitions(ocloc_lib PRIVATE MOCKABLE_VIRTUAL=) if(DONT_CARE_OF_VIRTUALS) set(NEO_CORE_RELEASE_LIB_NAME "neo_core") diff --git a/offline_compiler/CMakeLists.txt b/offline_compiler/CMakeLists.txt index 67dc770a7c..b15d44cad7 100644 --- a/offline_compiler/CMakeLists.txt +++ b/offline_compiler/CMakeLists.txt @@ -4,9 +4,9 @@ # SPDX-License-Identifier: MIT # -project(ocloc) +project(ocloc_lib) -set(CLOC_SRCS_LIB +set(CLOC_LIB_SRCS_LIB ${NEO_CORE_DIRECTORY}/device_binary_format/ar/ar.h ${NEO_CORE_DIRECTORY}/device_binary_format/ar/ar_decoder.h ${NEO_CORE_DIRECTORY}/device_binary_format/ar/ar_decoder.cpp @@ -30,6 +30,10 @@ set(CLOC_SRCS_LIB ${NEO_SOURCE_DIR}/offline_compiler/decoder/helper.h ${NEO_SOURCE_DIR}/offline_compiler/decoder/iga_wrapper.h ${NEO_SOURCE_DIR}/offline_compiler/decoder/translate_platform_base.h + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_api.cpp + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_api.h + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_arg_helper.h + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_arg_helper.cpp ${NEO_SOURCE_DIR}/offline_compiler/ocloc_fatbinary.cpp ${NEO_SOURCE_DIR}/offline_compiler/ocloc_fatbinary.h ${NEO_SOURCE_DIR}/offline_compiler/offline_compiler_helper.cpp @@ -47,24 +51,24 @@ set(CLOC_SRCS_LIB ) if(${IGA_HEADERS_AVAILABLE}) - set(CLOC_SRCS_LIB ${CLOC_SRCS_LIB} + set(CLOC_LIB_SRCS_LIB ${CLOC_LIB_SRCS_LIB} ${NEO_SOURCE_DIR}/offline_compiler/decoder/iga_wrapper.cpp ${NEO_SOURCE_DIR}/offline_compiler/decoder${BRANCH_DIR_SUFFIX}/translate_platform.cpp ) else() - set(CLOC_SRCS_LIB ${CLOC_SRCS_LIB} + set(CLOC_LIB_SRCS_LIB ${CLOC_LIB_SRCS_LIB} ${NEO_SOURCE_DIR}/offline_compiler/decoder/iga_stubs.cpp ) endif() if(WIN32) - list(APPEND CLOC_SRCS_LIB + list(APPEND CLOC_LIB_SRCS_LIB ${NEO_CORE_DIRECTORY}/os_interface/windows/os_library_win.cpp ${NEO_CORE_DIRECTORY}/os_interface/windows/os_library_win.h ${NEO_SOURCE_DIR}/opencl/source/dll/windows/options_windows.cpp ) else() - list(APPEND CLOC_SRCS_LIB + list(APPEND CLOC_LIB_SRCS_LIB ${NEO_CORE_DIRECTORY}/os_interface/linux/os_library_linux.cpp ${NEO_CORE_DIRECTORY}/os_interface/linux/os_library_linux.h ${NEO_SOURCE_DIR}/opencl/source/dll/linux/options_linux.cpp @@ -73,7 +77,7 @@ endif() string(REPLACE ";" "," ALL_SUPPORTED_PRODUCT_FAMILIES "${ALL_SUPPORTED_PRODUCT_FAMILY}") -set(CLOC_LIB_FLAGS_DEFINITIONS +set(CLOC_LIB_LIB_FLAGS_DEFINITIONS -DCIF_HEADERS_ONLY_BUILD -DALL_SUPPORTED_PRODUCT_FAMILIES=${ALL_SUPPORTED_PRODUCT_FAMILIES} ) @@ -83,43 +87,34 @@ set(RUNTIME_GENX_CPP_FILES ) macro(macro_for_each_platform) - list(APPEND CLOC_SRCS_LIB ${NEO_SOURCE_DIR}/opencl/source/${GEN_TYPE_LOWER}/hw_info_${PLATFORM_IT_LOWER}.inl) + list(APPEND CLOC_LIB_SRCS_LIB ${NEO_SOURCE_DIR}/opencl/source/${GEN_TYPE_LOWER}/hw_info_${PLATFORM_IT_LOWER}.inl) endmacro() macro(macro_for_each_gen) foreach(SRC_IT ${RUNTIME_GENX_CPP_FILES}) set(SRC_FILE ${NEO_SOURCE_DIR}/opencl/source/${GEN_TYPE_LOWER}/${SRC_IT}) if(EXISTS ${SRC_FILE}_${GEN_TYPE_LOWER}.cpp) - list(APPEND CLOC_SRCS_LIB ${SRC_FILE}_${GEN_TYPE_LOWER}.cpp) + list(APPEND CLOC_LIB_SRCS_LIB ${SRC_FILE}_${GEN_TYPE_LOWER}.cpp) endif() endforeach() apply_macro_for_each_platform() - list(APPEND CLOC_SRCS_LIB ${NEO_CORE_DIRECTORY}/${GEN_TYPE_LOWER}/enable_${GEN_TYPE_LOWER}.cpp) + list(APPEND CLOC_LIB_SRCS_LIB ${NEO_CORE_DIRECTORY}/${GEN_TYPE_LOWER}/enable_${GEN_TYPE_LOWER}.cpp) endmacro() apply_macro_for_each_gen("SUPPORTED") -set(CLOC_SRCS - ${CLOC_SRCS_LIB} - ${CMAKE_CURRENT_SOURCE_DIR}/main.cpp +set(CLOC_LIB_SRCS + ${CLOC_LIB_SRCS_LIB} ${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt ) -add_executable(ocloc ${CLOC_SRCS}) - -if(UNIX) - install(FILES $ - DESTINATION ${CMAKE_INSTALL_BINDIR} - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE - COMPONENT ocloc) - set_property(GLOBAL APPEND PROPERTY NEO_COMPONENTS_LIST "ocloc") -endif() +add_library(ocloc_lib SHARED ${CLOC_LIB_SRCS}) add_subdirectories() -create_project_source_tree(ocloc) +create_project_source_tree(ocloc_lib) -set(CLOC_INCLUDES +set(CLOC_LIB_INCLUDES ${ENGINE_NODE_DIR} ${IGC_OCL_ADAPTOR_DIR} ${CIF_BASE_DIR} @@ -128,22 +123,75 @@ set(CLOC_INCLUDES ${NEO__IGC_INCLUDE_DIR} ) -target_include_directories(ocloc BEFORE PRIVATE ${CLOC_INCLUDES}) -target_include_directories(ocloc BEFORE PRIVATE ${IGA_INCLUDE_DIR}) +target_include_directories(ocloc_lib BEFORE PRIVATE ${CLOC_LIB_INCLUDES}) +target_include_directories(ocloc_lib BEFORE PRIVATE ${IGA_INCLUDE_DIR}) -target_compile_definitions(ocloc PUBLIC ${CLOC_LIB_FLAGS_DEFINITIONS} ${SUPPORTED_GEN_FLAGS_DEFINITONS} DEFAULT_PLATFORM=${DEFAULT_SUPPORTED_PLATFORM} +target_compile_definitions(ocloc_lib PUBLIC ${CLOC_LIB_LIB_FLAGS_DEFINITIONS} ${SUPPORTED_GEN_FLAGS_DEFINITONS} DEFAULT_PLATFORM=${DEFAULT_SUPPORTED_PLATFORM} IGA_LIBRARY_NAME=${CMAKE_SHARED_LIBRARY_PREFIX}${IGA_LIBRARY_NAME}${CMAKE_SHARED_LIBRARY_SUFFIX}) -target_compile_definitions(ocloc PRIVATE ${NEO__IGC_COMPILE_DEFINITIONS}) +target_compile_definitions(ocloc_lib PRIVATE ${NEO__IGC_COMPILE_DEFINITIONS}) if(MSVC) - target_link_libraries(ocloc dbghelp) + target_link_libraries(ocloc_lib dbghelp) endif() if(UNIX) - target_link_libraries(ocloc dl pthread) + target_link_libraries(ocloc_lib dl pthread) endif() +set(CLOC_LIB_SRCS_LIB ${CLOC_LIB_SRCS_LIB} PARENT_SCOPE) + +set(CLOC_SRCS + ${NEO_CORE_DIRECTORY}/os_interface/os_library.h + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_wrapper.h + ${NEO_SOURCE_DIR}/offline_compiler/ocloc_wrapper.cpp + ${NEO_SOURCE_DIR}/offline_compiler/utilities/get_path.h +) +if(WIN32) + list(APPEND CLOC_SRCS + ${NEO_CORE_DIRECTORY}/os_interface/windows/os_library_win.cpp + ${NEO_CORE_DIRECTORY}/os_interface/windows/os_library_win.h + ${NEO_SOURCE_DIR}/offline_compiler/utilities/windows/get_path.cpp + + ) +else() + list(APPEND CLOC_SRCS + ${NEO_CORE_DIRECTORY}/os_interface/linux/os_library_linux.cpp + ${NEO_CORE_DIRECTORY}/os_interface/linux/os_library_linux.h + ${NEO_SOURCE_DIR}/offline_compiler/utilities/linux/get_path.cpp + ) +endif() + +add_executable(ocloc ${CLOC_SRCS} ${NEO_SOURCE_DIR}/offline_compiler/main.cpp) +add_dependencies(ocloc ocloc_lib) +target_link_libraries(ocloc ocloc_lib) + +set(OCLOC_LIB_NAME "ocloc") +if(CMAKE_SIZEOF_VOID_P EQUAL 4) + set(OCLOC_BITNESS_SUFFIX 32) +elseif(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(OCLOC_BITNESS_SUFFIX 64) +endif() + +if(UNIX) + install(FILES $ + DESTINATION ${CMAKE_INSTALL_LIBDIR}/intel-opencl + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) + install(FILES $ + DESTINATION ${CMAKE_INSTALL_BINDIR} + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ + COMPONENT ocloc) + set_property(GLOBAL APPEND PROPERTY NEO_COMPONENTS_LIST "ocloc") + set_target_properties(ocloc_lib PROPERTIES OUTPUT_NAME ${OCLOC_LIB_NAME}) + add_definitions(-DOCLOC_LIB_NAME="lib${OCLOC_LIB_NAME}.so") +else() + set_target_properties(ocloc_lib PROPERTIES OUTPUT_NAME "${OCLOC_LIB_NAME}${OCLOC_BITNESS_SUFFIX}") + add_definitions(-DOCLOC_LIB_NAME="${OCLOC_LIB_NAME}${OCLOC_BITNESS_SUFFIX}.dll") +endif() + +create_project_source_tree(ocloc) set_target_properties(ocloc PROPERTIES FOLDER "offline_compiler") +set_target_properties(ocloc_lib PROPERTIES FOLDER "offline_compiler") + add_custom_target(copy_compiler_files DEPENDS ${NEO__IGC_TARGETS}) set_target_properties(copy_compiler_files PROPERTIES FOLDER "opencl runtime") @@ -153,10 +201,11 @@ if(WIN32) add_custom_command( TARGET copy_compiler_files PRE_BUILD + COMMAND ${CMAKE_COMMAND} -E make_directory $ + COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ COMMAND ${CMAKE_COMMAND} -E make_directory $ COMMAND ${CMAKE_COMMAND} -E copy_if_different $ $ ) endforeach() endif() -set(CLOC_SRCS_LIB ${CLOC_SRCS_LIB} PARENT_SCOPE) diff --git a/offline_compiler/api.cpp b/offline_compiler/api.cpp new file mode 100644 index 0000000000..1d3b1b7a2b --- /dev/null +++ b/offline_compiler/api.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ocloc_api.h" + +#include + +void printHelp() { + printf(R"===(ocloc is a tool for managing Intel OpenCL GPU device binary format. +It can be used for generation (as part of 'compile' command) as well as +manipulation (decoding/modifying - as part of 'disasm'/'asm' commands) of such +binary files. +Intel OpenCL GPU device binary is a format used by Intel OpenCL GPU runtime +(aka NEO). Intel OpenCL GPU runtime will return this binary format when queried +using clGetProgramInfo(..., CL_PROGRAM_BINARIES, ...). It will also honor +this format as input to clCreateProgramWithBinary function call. +ocloc does not require Intel GPU device to be present in the system nor does it +depend on Intel OpenCL GPU runtime driver to be installed. It does however rely +on the same set of compilers (IGC, common_clang) as the runtime driver. + +Usage: ocloc [--help] [] +Available commands are listed below. +Use 'ocloc --help' to get help about specific command. + +Commands: + compile Compiles input to Intel OpenCL GPU device binary. + disasm Disassembles Intel OpenCL GPU device binary. + asm Assembles Intel OpenCL GPU device binary. + multi Compiles multiple files using a config file. + +Default command (when none provided) is 'compile'. + +Examples: + Compile file to Intel OpenCL GPU device binary (out = source_file_Gen9core.bin) + ocloc -file source_file.cl -device skl + + Disassemble Intel OpenCL GPU device binary + ocloc disasm -file source_file_Gen9core.bin + + Assemble to Intel OpenCL GPU device binary (after above disasm) + ocloc asm -out reassembled.bin +)==="); +} + +extern "C" { +int oclocInvoke(unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + auto helper = std::make_unique( + numSources, dataSources, lenSources, nameSources, + numInputHeaders, dataInputHeaders, lenInputHeaders, nameInputHeaders, + numOutputs, dataOutputs, lenOutputs, nameOutputs); + std::vector allArgs; + if (numArgs > 1) { + allArgs.assign(argv, argv + numArgs); + } + + try { + if (numArgs == 1 || (numArgs > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))) { + printHelp(); + } else if (numArgs > 1 && !strcmp(argv[1], "disasm")) { + BinaryDecoder disasm(std::move(helper)); + int retVal = disasm.validateInput(allArgs); + if (retVal == 0) { + return disasm.decode(); + } else { + return retVal; + } + } else if (numArgs > 1 && !strcmp(argv[1], "asm")) { + BinaryEncoder assembler(std::move(helper)); + int retVal = assembler.validateInput(allArgs); + if (retVal == 0) { + return assembler.encode(); + } else { + return retVal; + } + } else if (numArgs > 1 && (!strcmp(argv[1], "multi") || !strcmp(argv[1], "-multi"))) { + int retValue = CL_SUCCESS; + auto pMulti = std::unique_ptr(MultiCommand::create(allArgs, retValue)); + return retValue; + } else { + int retVal = CL_SUCCESS; + std::vector allArgs; + if (numArgs > 1) { + allArgs.assign(argv, argv + numArgs); + } + + OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, allArgs, true, retVal, std::move(helper)); + + if (retVal == CL_SUCCESS) { + retVal = buildWithSafetyGuard(pCompiler); + + std::string buildLog = pCompiler->getBuildLog(); + if (buildLog.empty() == false) { + printf("%s\n", buildLog.c_str()); + } + + if (retVal == CL_SUCCESS) { + if (!pCompiler->isQuiet()) + printf("Build succeeded.\n"); + } else { + printf("Build failed with error code: %d\n", retVal); + } + } + delete pCompiler; + return retVal; + } + } catch (const std::exception &e) { + printf("%s\n", e.what()); + return -1; + } + return -1; +} +void oclocFreeOutput(uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + for (uint32_t i = 0; i < *numOutputs; i++) { + delete[](*dataOutputs)[i]; + delete[](*nameOutputs)[i]; + } + delete[](*dataOutputs); + delete[](*lenOutputs); + delete[](*nameOutputs); +} +} diff --git a/offline_compiler/decoder/binary_decoder.cpp b/offline_compiler/decoder/binary_decoder.cpp index 15965db79d..b055d17136 100644 --- a/offline_compiler/decoder/binary_decoder.cpp +++ b/offline_compiler/decoder/binary_decoder.cpp @@ -45,7 +45,7 @@ T readUnaligned(const void *ptr) { int BinaryDecoder::decode() { parseTokens(); - std::ofstream ptmFile(pathToDump + "PTM.txt"); + std::stringstream ptmFile; auto devBinPtr = getDevBinary(); if (devBinPtr == nullptr) { messagePrinter.printf("Error! Device Binary section was not found.\n"); @@ -85,7 +85,7 @@ void BinaryDecoder::dumpField(const void *&binaryPtr, const PTField &field, std: } const void *BinaryDecoder::getDevBinary() { - binary = readBinaryFile(binaryFile); + binary = argHelper->readBinaryFile(binaryFile); const void *data = nullptr; std::string decoderErrors; std::string decoderWarnings; @@ -95,18 +95,15 @@ const void *BinaryDecoder::getDevBinary() { auto sectionData = ArrayRef(reinterpret_cast(sectionHeader.data.begin()), sectionHeader.data.size()); switch (sectionHeader.header->type) { case NEO::Elf::SHT_OPENCL_LLVM_BINARY: { - std::ofstream ofs(pathToDump + "llvm.bin", std::ios::binary); - ofs.write(sectionData.begin(), sectionData.size()); + argHelper->saveOutput(pathToDump + "llvm.bin", sectionData.begin(), sectionData.size()); break; } case NEO::Elf::SHT_OPENCL_SPIRV: { - std::ofstream ofs(pathToDump + "spirv.bin", std::ios::binary); - ofs.write(sectionData.begin(), sectionData.size()); + argHelper->saveOutput(pathToDump + "spirv.bin", sectionData.begin(), sectionData.size()); break; } case NEO::Elf::SHT_OPENCL_OPTIONS: { - std::ofstream ofs(pathToDump + "build.bin", std::ios::binary); - ofs.write(sectionData.begin(), sectionData.size()); + argHelper->saveOutput(pathToDump + "build.bin", sectionData.begin(), sectionData.size()); break; } case NEO::Elf::SHT_OPENCL_DEV_BINARY: { @@ -135,70 +132,78 @@ uint8_t BinaryDecoder::getSize(const std::string &typeStr) { } } +std::vector BinaryDecoder::loadPatchList() { + if (argHelper->hasHeaders()) { + return argHelper->headersToVectorOfStrings(); + } else { + std::vector patchList; + if (pathToPatch.empty()) { + messagePrinter.printf("Path to patch list not provided - using defaults, skipping patchokens as undefined.\n"); + patchList = { + "struct SProgramBinaryHeader", + "{", + " uint32_t Magic;", + " uint32_t Version;", + " uint32_t Device;", + " uint32_t GPUPointerSizeInBytes;", + " uint32_t NumberOfKernels;", + " uint32_t SteppingId;", + " uint32_t PatchListSize;", + "};", + "", + "struct SKernelBinaryHeader", + "{", + " uint32_t CheckSum;", + " uint64_t ShaderHashCode;", + " uint32_t KernelNameSize;", + " uint32_t PatchListSize;", + "};", + "", + "struct SKernelBinaryHeaderCommon :", + " SKernelBinaryHeader", + "{", + " uint32_t KernelHeapSize;", + " uint32_t GeneralStateHeapSize;", + " uint32_t DynamicStateHeapSize;", + " uint32_t SurfaceStateHeapSize;", + " uint32_t KernelUnpaddedSize;", + "};", + "", + "enum PATCH_TOKEN", + "{", + " PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO, // 41 @SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo@", + " PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO, // 42 @SPatchAllocateConstantMemorySurfaceProgramBinaryInfo@", + "};", + "struct SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo :", + " SPatchItemHeader", + "{", + " uint32_t Type;", + " uint32_t GlobalBufferIndex;", + " uint32_t InlineDataSize;", + "};", + "struct SPatchAllocateConstantMemorySurfaceProgramBinaryInfo :", + " SPatchItemHeader", + "{", + " uint32_t ConstantBufferIndex;", + " uint32_t InlineDataSize;", + "};", + + }; + } else { + readFileToVectorOfStrings(patchList, pathToPatch + "patch_list.h", true); + readFileToVectorOfStrings(patchList, pathToPatch + "patch_shared.h", true); + readFileToVectorOfStrings(patchList, pathToPatch + "patch_g7.h", true); + readFileToVectorOfStrings(patchList, pathToPatch + "patch_g8.h", true); + readFileToVectorOfStrings(patchList, pathToPatch + "patch_g9.h", true); + readFileToVectorOfStrings(patchList, pathToPatch + "patch_g10.h", true); + } + return patchList; + } +} + void BinaryDecoder::parseTokens() { //Creating patchlist definitions - std::vector patchList; - - if (pathToPatch.empty()) { - messagePrinter.printf("Path to patch list not provided - using defaults, skipping patchokens as undefined.\n"); - patchList = { - "struct SProgramBinaryHeader", - "{", - " uint32_t Magic;", - " uint32_t Version;", - " uint32_t Device;", - " uint32_t GPUPointerSizeInBytes;", - " uint32_t NumberOfKernels;", - " uint32_t SteppingId;", - " uint32_t PatchListSize;", - "};", - "", - "struct SKernelBinaryHeader", - "{", - " uint32_t CheckSum;", - " uint64_t ShaderHashCode;", - " uint32_t KernelNameSize;", - " uint32_t PatchListSize;", - "};", - "", - "struct SKernelBinaryHeaderCommon :", - " SKernelBinaryHeader", - "{", - " uint32_t KernelHeapSize;", - " uint32_t GeneralStateHeapSize;", - " uint32_t DynamicStateHeapSize;", - " uint32_t SurfaceStateHeapSize;", - " uint32_t KernelUnpaddedSize;", - "};", - "", - "enum PATCH_TOKEN", - "{", - " PATCH_TOKEN_ALLOCATE_GLOBAL_MEMORY_SURFACE_PROGRAM_BINARY_INFO, // 41 @SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo@", - " PATCH_TOKEN_ALLOCATE_CONSTANT_MEMORY_SURFACE_PROGRAM_BINARY_INFO, // 42 @SPatchAllocateConstantMemorySurfaceProgramBinaryInfo@", - "};", - "struct SPatchAllocateGlobalMemorySurfaceProgramBinaryInfo :", - " SPatchItemHeader", - "{", - " uint32_t Type;", - " uint32_t GlobalBufferIndex;", - " uint32_t InlineDataSize;", - "};", - "struct SPatchAllocateConstantMemorySurfaceProgramBinaryInfo :", - " SPatchItemHeader", - "{", - " uint32_t ConstantBufferIndex;", - " uint32_t InlineDataSize;", - "};", - - }; - } else { - readFileToVectorOfStrings(patchList, pathToPatch + "patch_list.h", true); - readFileToVectorOfStrings(patchList, pathToPatch + "patch_shared.h", true); - readFileToVectorOfStrings(patchList, pathToPatch + "patch_g7.h", true); - readFileToVectorOfStrings(patchList, pathToPatch + "patch_g8.h", true); - readFileToVectorOfStrings(patchList, pathToPatch + "patch_g9.h", true); - readFileToVectorOfStrings(patchList, pathToPatch + "patch_g10.h", true); - } + auto patchList = loadPatchList(); size_t pos = findPos(patchList, "struct SProgramBinaryHeader"); if (pos == patchList.size()) { @@ -354,6 +359,8 @@ int BinaryDecoder::processBinary(const void *&ptr, std::ostream &ptmFile) { ptmFile << "Kernel #" << i << '\n'; processKernel(ptr, ptmFile); } + + argHelper->saveOutput(pathToDump + "PTM.txt", ptmFile); return 0; } @@ -394,12 +401,12 @@ void BinaryDecoder::processKernel(const void *&ptr, std::ostream &ptmFile) { messagePrinter.printf("Trying to disassemble %s.krn\n", kernelName.c_str()); std::string disassembledKernel; if (iga->tryDisassembleGenISA(ptr, KernelHeapUnpaddedSize, disassembledKernel)) { - writeDataToFile((fileName + ".asm").c_str(), disassembledKernel.data(), disassembledKernel.size()); + argHelper->saveOutput(fileName + ".asm", disassembledKernel.data(), disassembledKernel.size()); } else { if (ignoreIsaPadding) { - writeDataToFile((fileName + ".dat").c_str(), ptr, KernelHeapUnpaddedSize); + argHelper->saveOutput(fileName + ".dat", ptr, KernelHeapUnpaddedSize); } else { - writeDataToFile((fileName + ".dat").c_str(), ptr, KernelHeapSize); + argHelper->saveOutput(fileName + ".dat", ptr, KernelHeapSize); } } ptr = ptrOffset(ptr, KernelHeapSize); @@ -407,16 +414,16 @@ void BinaryDecoder::processKernel(const void *&ptr, std::ostream &ptmFile) { if (GeneralStateHeapSize != 0) { messagePrinter.printf("Warning! GeneralStateHeapSize wasn't 0.\n"); fileName = pathToDump + kernelName + "_GeneralStateHeap.bin"; - writeDataToFile(fileName.c_str(), ptr, DynamicStateHeapSize); + argHelper->saveOutput(fileName, ptr, DynamicStateHeapSize); ptr = ptrOffset(ptr, GeneralStateHeapSize); } fileName = pathToDump + kernelName + "_DynamicStateHeap.bin"; - writeDataToFile(fileName.c_str(), ptr, DynamicStateHeapSize); + argHelper->saveOutput(fileName, ptr, DynamicStateHeapSize); ptr = ptrOffset(ptr, DynamicStateHeapSize); fileName = pathToDump + kernelName + "_SurfaceStateHeap.bin"; - writeDataToFile(fileName.c_str(), ptr, SurfaceStateHeapSize); + argHelper->saveOutput(fileName, ptr, SurfaceStateHeapSize); ptr = ptrOffset(ptr, SurfaceStateHeapSize); if (KernelPatchListSize == 0) { @@ -501,33 +508,34 @@ uint32_t BinaryDecoder::readStructFields(const std::vector &patchLi return fullSize; } -int BinaryDecoder::validateInput(uint32_t argc, const char **argv) { - if (!strcmp(argv[argc - 1], "--help")) { +int BinaryDecoder::validateInput(const std::vector &args) { + if (args[args.size() - 1] == "-help") { printHelp(); return -1; } - for (uint32_t i = 2; i < argc; ++i) { - if (i < argc - 1) { - if (!strcmp(argv[i], "-file")) { - binaryFile = std::string(argv[++i]); - } else if (!strcmp(argv[i], "-device")) { - iga->setProductFamily(getProductFamilyFromDeviceName(argv[++i])); - } else if (!strcmp(argv[i], "-patch")) { - pathToPatch = std::string(argv[++i]); - addSlash(pathToPatch); - } else if (!strcmp(argv[i], "-dump")) { - pathToDump = std::string(argv[++i]); - addSlash(pathToDump); - } + for (size_t argIndex = 2; argIndex < args.size(); ++argIndex) { + const auto &currArg = args[argIndex]; + const bool hasMoreArgs = (argIndex + 1 < args.size()); + if ("-file" == currArg && hasMoreArgs) { + binaryFile = args[++argIndex]; + } else if ("-device" == currArg && hasMoreArgs) { + iga->setProductFamily(getProductFamilyFromDeviceName(args[++argIndex])); + } else if ("-patch" == currArg && hasMoreArgs) { + pathToPatch = args[++argIndex]; + addSlash(pathToPatch); + } else if ("-dump" == currArg && hasMoreArgs) { + pathToDump = args[++argIndex]; + addSlash(pathToDump); + } else if ("-ignore_isa_padding" == currArg) { + ignoreIsaPadding = true; + } else if ("-q" == currArg) { + this->messagePrinter = MessagePrinter{true}; + iga->setMessagePrinter(this->messagePrinter); } else { - if (!strcmp(argv[i], "-ignore_isa_padding")) { - ignoreIsaPadding = true; - } else { - messagePrinter.printf("Unknown argument %s\n", argv[i]); - printHelp(); - return -1; - } + messagePrinter.printf("Unknown argument %s\n", currArg.c_str()); + printHelp(); + return -1; } } if (binaryFile.find(".bin") == std::string::npos) { @@ -535,15 +543,15 @@ int BinaryDecoder::validateInput(uint32_t argc, const char **argv) { printHelp(); return -1; } - if (pathToDump.empty()) { - messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n"); - pathToDump = std::string("dump/"); - } - if (false == iga->isKnownPlatform()) { messagePrinter.printf("Warning : missing or invalid -device parameter - results may be inacurate\n"); } - - MakeDirectory(pathToDump.c_str()); + if (!argHelper->outputEnabled()) { + if (pathToDump.empty()) { + messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n"); + pathToDump = std::string("dump/"); + } + MakeDirectory(pathToDump.c_str()); + } return 0; } diff --git a/offline_compiler/decoder/binary_decoder.h b/offline_compiler/decoder/binary_decoder.h index 6866cb0085..ad4b2116cd 100644 --- a/offline_compiler/decoder/binary_decoder.h +++ b/offline_compiler/decoder/binary_decoder.h @@ -8,6 +8,7 @@ #pragma once #include "offline_compiler/decoder/helper.h" #include "offline_compiler/decoder/iga_wrapper.h" +#include "offline_compiler/ocloc_arg_helper.h" #include #include @@ -33,15 +34,21 @@ class BinaryDecoder { public: BinaryDecoder() : iga(new IgaWrapper) { iga->setMessagePrinter(messagePrinter); + if (nullptr == argHelper) { + argHelper = std::make_unique(); + } } BinaryDecoder(const std::string &file, const std::string &patch, const std::string &dump) : binaryFile(file), pathToPatch(patch), pathToDump(dump){}; + BinaryDecoder(std::unique_ptr helper) : argHelper(std::move(helper)), iga(new IgaWrapper) { + iga->setMessagePrinter(messagePrinter); + }; int decode(); - int validateInput(uint32_t argc, const char **argv); - + int validateInput(const std::vector &args); void setMessagePrinter(const MessagePrinter &messagePrinter); protected: + std::unique_ptr argHelper = nullptr; bool ignoreIsaPadding = false; BinaryHeader programHeader, kernelHeader; std::vector binary; @@ -53,6 +60,7 @@ class BinaryDecoder { void dumpField(const void *&binaryPtr, const PTField &field, std::ostream &ptmFile); uint8_t getSize(const std::string &typeStr); const void *getDevBinary(); + std::vector loadPatchList(); void parseTokens(); void printHelp(); int processBinary(const void *&ptr, std::ostream &ptmFile); diff --git a/offline_compiler/decoder/binary_encoder.cpp b/offline_compiler/decoder/binary_encoder.cpp index 1044cbec68..eaf32713d8 100644 --- a/offline_compiler/decoder/binary_encoder.cpp +++ b/offline_compiler/decoder/binary_encoder.cpp @@ -56,16 +56,8 @@ void BinaryEncoder::calculatePatchListSizes(std::vector &ptmFile) { } bool BinaryEncoder::copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary, uint32_t *binaryLength) { - std::ifstream ifs(srcFileName, std::ios::binary); - if (!ifs.good()) { - messagePrinter.printf("Cannot open %s.\n", srcFileName.c_str()); - return false; - } - ifs.seekg(0, ifs.end); - auto length = static_cast(ifs.tellg()); - ifs.seekg(0, ifs.beg); - std::vector binary(length); - ifs.read(binary.data(), length); + auto binary = argHelper->readBinaryFile(srcFileName); + auto length = binary.size(); outBinary.write(binary.data(), length); if (binaryLength) { @@ -75,27 +67,24 @@ bool BinaryEncoder::copyBinaryToBinary(const std::string &srcFileName, std::ostr return true; } -int BinaryEncoder::createElf() { +int BinaryEncoder::createElf(std::stringstream &deviceBinary) { NEO::Elf::ElfEncoder ElfEncoder; ElfEncoder.getElfFileHeader().type = NEO::Elf::ET_OPENCL_EXECUTABLE; - //Build Options - if (fileExists(pathToDump + "build.bin")) { - auto binary = readBinaryFile(pathToDump + "build.bin"); + if (argHelper->fileExists(pathToDump + "build.bin")) { + auto binary = argHelper->readBinaryFile(pathToDump + "build.bin"); ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_OPTIONS, "BuildOptions", ArrayRef(reinterpret_cast(binary.data()), binary.size())); } else { messagePrinter.printf("Warning! Missing build section.\n"); } - //LLVM or SPIRV - if (fileExists(pathToDump + "llvm.bin")) { - auto binary = readBinaryFile(pathToDump + "llvm.bin"); + if (argHelper->fileExists(pathToDump + "llvm.bin")) { + auto binary = argHelper->readBinaryFile(pathToDump + "llvm.bin"); ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_LLVM_BINARY, "Intel(R) OpenCL LLVM Object", ArrayRef(reinterpret_cast(binary.data()), binary.size())); - } else if (fileExists(pathToDump + "spirv.bin")) { - auto binary = readBinaryFile(pathToDump + "spirv.bin"); - std::string data(binary.begin(), binary.end()); + } else if (argHelper->fileExists(pathToDump + "spirv.bin")) { + auto binary = argHelper->readBinaryFile(pathToDump + "spirv.bin"); ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_SPIRV, "SPIRV Object", ArrayRef(reinterpret_cast(binary.data()), binary.size())); } else { @@ -103,25 +92,15 @@ int BinaryEncoder::createElf() { } //Device Binary - if (fileExists(pathToDump + "device_binary.bin")) { - auto binary = readBinaryFile(pathToDump + "device_binary.bin"); - ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, "Intel(R) OpenCL Device Binary", - ArrayRef(reinterpret_cast(binary.data()), binary.size())); - } else { - messagePrinter.printf("Missing device_binary.bin\n"); - return -1; - } + auto deviceBinaryStr = deviceBinary.str(); + std::vector binary(deviceBinaryStr.begin(), deviceBinaryStr.end()); + ElfEncoder.appendSection(NEO::Elf::SHT_OPENCL_DEV_BINARY, "Intel(R) OpenCL Device Binary", + ArrayRef(reinterpret_cast(binary.data()), binary.size())); //Resolve Elf Binary auto elfBinary = ElfEncoder.encode(); + argHelper->saveOutput(elfName, elfBinary.data(), elfBinary.size()); - std::ofstream elfFile(elfName, std::ios::binary); - if (!elfFile.good()) { - messagePrinter.printf("Couldn't create %s.\n", elfName.c_str()); - return -1; - } - - elfFile.write(reinterpret_cast(elfBinary.data()), elfBinary.size()); return 0; } @@ -160,21 +139,23 @@ Examples: int BinaryEncoder::encode() { std::vector ptmFile; - readFileToVectorOfStrings(ptmFile, pathToDump + "PTM.txt"); - calculatePatchListSizes(ptmFile); - - std::ofstream deviceBinary(pathToDump + "device_binary.bin", std::ios::binary); - if (!deviceBinary.good()) { - messagePrinter.printf("Error! Couldn't create device_binary.bin.\n"); + if (!argHelper->fileExists(pathToDump + "PTM.txt")) { + messagePrinter.printf("Error! Couldn't find PTM.txt"); return -1; } + argHelper->readFileToVectorOfStrings(pathToDump + "PTM.txt", ptmFile); + + calculatePatchListSizes(ptmFile); + + std::stringstream deviceBinary; //(pathToDump + "device_binary.bin", std::ios::binary); int retVal = processBinary(ptmFile, deviceBinary); - deviceBinary.close(); + argHelper->saveOutput(pathToDump + "device_binary.bin", deviceBinary.str().c_str(), deviceBinary.str().length()); if (retVal != CL_SUCCESS) { return retVal; } - return createElf(); + retVal = createElf(deviceBinary); + return retVal; } int BinaryEncoder::processBinary(const std::vector &ptmFileLines, std::ostream &deviceBinary) { @@ -252,8 +233,8 @@ int BinaryEncoder::processKernel(size_t &line, const std::vector &p bool heapsCopiedSuccesfully = true; // Use .asm if available, fallback to .dat - if (fileExists(pathToDump + kernelName + "_KernelHeap.asm")) { - auto kernelAsAsm = readBinaryFile(pathToDump + kernelName + "_KernelHeap.asm"); + if (argHelper->fileExists(pathToDump + kernelName + "_KernelHeap.asm")) { + auto kernelAsAsm = argHelper->readBinaryFile(pathToDump + kernelName + "_KernelHeap.asm"); std::string kernelAsBinary; messagePrinter.printf("Trying to assemble %s.asm\n", kernelName.c_str()); if (false == iga->tryAssembleGenISA(std::string(kernelAsAsm.begin(), kernelAsAsm.end()), kernelAsBinary)) { @@ -278,7 +259,7 @@ int BinaryEncoder::processKernel(size_t &line, const std::vector &p } // Write GeneralStateHeap, DynamicStateHeap, SurfaceStateHeap - if (fileExists(pathToDump + kernelName + "_GeneralStateHeap.bin")) { + if (argHelper->fileExists(pathToDump + kernelName + "_GeneralStateHeap.bin")) { heapsCopiedSuccesfully = heapsCopiedSuccesfully && copyBinaryToBinary(pathToDump + kernelName + "_GeneralStateHeap.bin", kernelBlob); } heapsCopiedSuccesfully = heapsCopiedSuccesfully && copyBinaryToBinary(pathToDump + kernelName + "_DynamicStateHeap.bin", kernelBlob); @@ -324,40 +305,39 @@ int BinaryEncoder::processKernel(size_t &line, const std::vector &p return 0; } -int BinaryEncoder::validateInput(uint32_t argc, const char **argv) { - if (!strcmp(argv[argc - 1], "--help")) { +int BinaryEncoder::validateInput(const std::vector &args) { + if ("-help" == args[args.size() - 1]) { printHelp(); return -1; } - for (uint32_t i = 2; i < argc; ++i) { - if (i < argc - 1) { - if (!strcmp(argv[i], "-dump")) { - pathToDump = std::string(argv[++i]); - addSlash(pathToDump); - } else if (!strcmp(argv[i], "-device")) { - iga->setProductFamily(getProductFamilyFromDeviceName(argv[++i])); - } else if (!strcmp(argv[i], "-out")) { - elfName = std::string(argv[++i]); - } else { - messagePrinter.printf("Unknown argument %s\n", argv[i]); - printHelp(); - return -1; - } + for (size_t argIndex = 2; argIndex < args.size(); ++argIndex) { + const auto &currArg = args[argIndex]; + const bool hasMoreArgs = (argIndex + 1 < args.size()); + if ("-dump" == currArg && hasMoreArgs) { + pathToDump = args[++argIndex]; + addSlash(pathToDump); + } else if ("-device" == currArg && hasMoreArgs) { + iga->setProductFamily(getProductFamilyFromDeviceName(args[++argIndex])); + } else if ("-out" == currArg && hasMoreArgs) { + elfName = args[++argIndex]; + } else if ("-ignore_isa_padding" == currArg) { + ignoreIsaPadding = true; + } else if ("-q" == currArg) { + this->messagePrinter = MessagePrinter{true}; + iga->setMessagePrinter(this->messagePrinter); } else { - if (!strcmp(argv[i], "-ignore_isa_padding")) { - ignoreIsaPadding = true; - } else { - messagePrinter.printf("Unknown argument %s\n", argv[i]); - printHelp(); - return -1; - } + messagePrinter.printf("Unknown argument %s\n", currArg.c_str()); + printHelp(); + return -1; } } if (pathToDump.empty()) { - messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n"); - pathToDump = "dump"; - addSlash(pathToDump); + if (!argHelper->outputEnabled()) { + messagePrinter.printf("Warning : Path to dump folder not specificed - using ./dump as default.\n"); + pathToDump = "dump"; + addSlash(pathToDump); + } } if (elfName.find(".bin") == std::string::npos) { messagePrinter.printf(".bin extension is expected for binary file.\n"); @@ -428,11 +408,3 @@ int BinaryEncoder::writeDeviceBinary(const std::string &line, std::ostream &devi } return 0; } - -bool BinaryEncoder::fileExists(const std::string &path) const { - return ::fileExists(path); -} - -std::vector BinaryEncoder::readBinaryFile(const std::string &path) const { - return ::readBinaryFile(path); -} diff --git a/offline_compiler/decoder/binary_encoder.h b/offline_compiler/decoder/binary_encoder.h index 809eb71178..9c4d7c2c06 100644 --- a/offline_compiler/decoder/binary_encoder.h +++ b/offline_compiler/decoder/binary_encoder.h @@ -6,6 +6,8 @@ */ #pragma once +#include "offline_compiler/ocloc_arg_helper.h" + #include "helper.h" #include "iga_wrapper.h" @@ -17,15 +19,20 @@ class BinaryEncoder { public: BinaryEncoder() : iga(new IgaWrapper) { iga->setMessagePrinter(messagePrinter); + argHelper = std::make_unique(); } BinaryEncoder(const std::string &dump, const std::string &elf) : pathToDump(dump), elfName(elf){}; + BinaryEncoder(std::unique_ptr helper) : argHelper(std::move(helper)), iga(new IgaWrapper) { + iga->setMessagePrinter(messagePrinter); + } int encode(); - int validateInput(uint32_t argc, const char **argv); + int validateInput(const std::vector &args); void setMessagePrinter(const MessagePrinter &messagePrinter); protected: + std::unique_ptr argHelper = nullptr; bool ignoreIsaPadding = false; std::string pathToDump, elfName; MessagePrinter messagePrinter; @@ -35,7 +42,7 @@ class BinaryEncoder { bool copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary) { return copyBinaryToBinary(srcFileName, outBinary, nullptr); } - int createElf(); + int createElf(std::stringstream &deviceBinary); void printHelp(); int processBinary(const std::vector &ptmFile, std::ostream &deviceBinary); int processKernel(size_t &i, const std::vector &ptmFileLines, std::ostream &deviceBinary); @@ -43,6 +50,4 @@ class BinaryEncoder { void write(std::stringstream &in, std::ostream &deviceBinary); int writeDeviceBinary(const std::string &line, std::ostream &deviceBinary); void addPadding(std::ostream &out, size_t numBytes); - MOCKABLE_VIRTUAL bool fileExists(const std::string &path) const; - MOCKABLE_VIRTUAL std::vector readBinaryFile(const std::string &path) const; }; diff --git a/offline_compiler/main.cpp b/offline_compiler/main.cpp index 465c06f973..f39a28d586 100644 --- a/offline_compiler/main.cpp +++ b/offline_compiler/main.cpp @@ -1,128 +1,13 @@ /* - * Copyright (C) 2017-2020 Intel Corporation + * Copyright (C) 2020 Intel Corporation * * SPDX-License-Identifier: MIT * */ -#include "shared/source/os_interface/os_library.h" +#include "ocloc_wrapper.h" -#include "offline_compiler/multi_command.h" -#include "offline_compiler/ocloc_fatbinary.h" -#include "offline_compiler/offline_compiler.h" - -#include "decoder/binary_decoder.h" -#include "decoder/binary_encoder.h" -#include - -#include -#include - -using namespace NEO; - -void printHelp() { - printf(R"===(ocloc is a tool for managing Intel OpenCL GPU device binary format. -It can be used for generation (as part of 'compile' command) as well as -manipulation (decoding/modifying - as part of 'disasm'/'asm' commands) of such -binary files. -Intel OpenCL GPU device binary is a format used by Intel OpenCL GPU runtime -(aka NEO). Intel OpenCL GPU runtime will return this binary format when queried -using clGetProgramInfo(..., CL_PROGRAM_BINARIES, ...). It will also honor -this format as input to clCreateProgramWithBinary function call. -ocloc does not require Intel GPU device to be present in the system nor does it -depend on Intel OpenCL GPU runtime driver to be installed. It does however rely -on the same set of compilers (IGC, common_clang) as the runtime driver. - -Usage: ocloc [--help] [] -Available commands are listed below. -Use 'ocloc --help' to get help about specific command. - -Commands: - compile Compiles input to Intel OpenCL GPU device binary. - disasm Disassembles Intel OpenCL GPU device binary. - asm Assembles Intel OpenCL GPU device binary. - multi Compiles multiple files using a config file. - -Default command (when none provided) is 'compile'. - -Examples: - Compile file to Intel OpenCL GPU device binary (out = source_file_Gen9core.bin) - ocloc -file source_file.cl -device skl - - Disassemble Intel OpenCL GPU device binary - ocloc disasm -file source_file_Gen9core.bin - - Assemble to Intel OpenCL GPU device binary (after above disasm) - ocloc asm -out reassembled.bin -)==="); -} - -int main(int numArgs, const char *argv[]) { - try { - if (numArgs == 1 || (numArgs > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))) { - printHelp(); - } else if (numArgs > 1 && !strcmp(argv[1], "disasm")) { - BinaryDecoder disasm; - int retVal = disasm.validateInput(numArgs, argv); - if (retVal == 0) { - return disasm.decode(); - } else { - return retVal; - } - } else if (numArgs > 1 && !strcmp(argv[1], "asm")) { - BinaryEncoder assembler; - int retVal = assembler.validateInput(numArgs, argv); - if (retVal == 0) { - return assembler.encode(); - } else { - return retVal; - } - } else if (numArgs > 1 && (!strcmp(argv[1], "multi") || !strcmp(argv[1], "-multi"))) { - int retValue = CL_SUCCESS; - std::vector allArgs; - if (numArgs > 1) { - allArgs.assign(argv, argv + numArgs); - } - auto pMulti = std::unique_ptr(MultiCommand::create(allArgs, retValue)); - return retValue; - } else { - if (requestedFatBinary(numArgs, argv)) { - return buildFatbinary(numArgs, argv); - } - - int retVal = CL_SUCCESS; - std::vector allArgs; - if (numArgs > 1) { - allArgs.assign(argv, argv + numArgs); - } - - OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, allArgs, true, retVal); - - if (retVal == CL_SUCCESS) { - retVal = buildWithSafetyGuard(pCompiler); - - std::string buildLog = pCompiler->getBuildLog(); - if (buildLog.empty() == false) { - printf("%s\n", buildLog.c_str()); - } - - if (retVal == CL_SUCCESS) { - if (!pCompiler->isQuiet()) - printf("Build succeeded.\n"); - } else { - printf("Build failed with error code: %d\n", retVal); - printf("Command was:"); - for (auto i = 0; i < numArgs; ++i) - printf(" %s", argv[i]); - printf("\n"); - } - } - delete pCompiler; - return retVal; - } - } catch (const std::exception &e) { - printf("%s\n", e.what()); - return -1; - } - return -1; +int main(int argc, const char *argv[]) { + OclocWrapper oclocWrapper; + return oclocWrapper.invokeOcloc(argc, argv); } diff --git a/offline_compiler/ocloc_api.cpp b/offline_compiler/ocloc_api.cpp new file mode 100644 index 0000000000..53f578b0d5 --- /dev/null +++ b/offline_compiler/ocloc_api.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ocloc_api.h" + +#include + +void printHelp() { + printf(R"===(ocloc is a tool for managing Intel OpenCL GPU device binary format. +It can be used for generation (as part of 'compile' command) as well as +manipulation (decoding/modifying - as part of 'disasm'/'asm' commands) of such +binary files. +Intel OpenCL GPU device binary is a format used by Intel OpenCL GPU runtime +(aka NEO). Intel OpenCL GPU runtime will return this binary format when queried +using clGetProgramInfo(..., CL_PROGRAM_BINARIES, ...). It will also honor +this format as input to clCreateProgramWithBinary function call. +ocloc does not require Intel GPU device to be present in the system nor does it +depend on Intel OpenCL GPU runtime driver to be installed. It does however rely +on the same set of compilers (IGC, common_clang) as the runtime driver. + +Usage: ocloc [--help] [] +Available commands are listed below. +Use 'ocloc --help' to get help about specific command. + +Commands: + compile Compiles input to Intel OpenCL GPU device binary. + disasm Disassembles Intel OpenCL GPU device binary. + asm Assembles Intel OpenCL GPU device binary. + multi Compiles multiple files using a config file. + +Default command (when none provided) is 'compile'. + +Examples: + Compile file to Intel OpenCL GPU device binary (out = source_file_Gen9core.bin) + ocloc -file source_file.cl -device skl + + Disassemble Intel OpenCL GPU device binary + ocloc disasm -file source_file_Gen9core.bin + + Assemble to Intel OpenCL GPU device binary (after above disasm) + ocloc asm -out reassembled.bin +)==="); +} + +extern "C" { +int oclocInvoke(unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + auto helper = std::make_unique( + numSources, dataSources, lenSources, nameSources, + numInputHeaders, dataInputHeaders, lenInputHeaders, nameInputHeaders, + numOutputs, dataOutputs, lenOutputs, nameOutputs); + std::vector allArgs; + if (numArgs > 1) { + allArgs.assign(argv, argv + numArgs); + } + + try { + if (numArgs == 1 || (numArgs > 1 && (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")))) { + printHelp(); + } else if (numArgs > 1 && !strcmp(argv[1], "disasm")) { + BinaryDecoder disasm(std::move(helper)); + int retVal = disasm.validateInput(allArgs); + if (retVal == 0) { + return disasm.decode(); + } else { + return retVal; + } + } else if (numArgs > 1 && !strcmp(argv[1], "asm")) { + BinaryEncoder assembler(std::move(helper)); + int retVal = assembler.validateInput(allArgs); + if (retVal == 0) { + return assembler.encode(); + } else { + return retVal; + } + } else if (numArgs > 1 && (!strcmp(argv[1], "multi") || !strcmp(argv[1], "-multi"))) { + int retValue = CL_SUCCESS; + auto pMulti = std::unique_ptr(MultiCommand::create(allArgs, retValue)); + return retValue; + } else { + int retVal = CL_SUCCESS; + std::vector allArgs; + if (numArgs > 1) { + allArgs.assign(argv, argv + numArgs); + } + + OfflineCompiler *pCompiler = OfflineCompiler::create(numArgs, allArgs, true, retVal, std::move(helper)); + + if (retVal == CL_SUCCESS) { + retVal = buildWithSafetyGuard(pCompiler); + + std::string buildLog = pCompiler->getBuildLog(); + if (buildLog.empty() == false) { + printf("%s\n", buildLog.c_str()); + } + + if (retVal == CL_SUCCESS) { + if (!pCompiler->isQuiet()) + printf("Build succeeded.\n"); + } else { + printf("Build failed with error code: %d\n", retVal); + } + } + delete pCompiler; + return retVal; + } + } catch (const std::exception &e) { + printf("%s\n", e.what()); + return -1; + } + return -1; +} +int oclocFreeOutput(uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + for (uint32_t i = 0; i < *numOutputs; i++) { + delete[](*dataOutputs)[i]; + delete[](*nameOutputs)[i]; + } + delete[](*dataOutputs); + delete[](*lenOutputs); + delete[](*nameOutputs); + return 0; +} +} diff --git a/offline_compiler/ocloc_api.h b/offline_compiler/ocloc_api.h new file mode 100644 index 0000000000..4ec64850d9 --- /dev/null +++ b/offline_compiler/ocloc_api.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "offline_compiler/multi_command.h" +#include "offline_compiler/offline_compiler.h" + +#include "decoder/binary_decoder.h" +#include "decoder/binary_encoder.h" + +using namespace NEO; + +#ifdef _WIN32 +#define SIGNATURE __declspec(dllexport) int __cdecl +#else +#define SIGNATURE int +#endif + +extern "C" { +SIGNATURE oclocInvoke(unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); +SIGNATURE oclocFreeOutput(uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); +} diff --git a/offline_compiler/ocloc_arg_helper.cpp b/offline_compiler/ocloc_arg_helper.cpp new file mode 100644 index 0000000000..ef94decdbf --- /dev/null +++ b/offline_compiler/ocloc_arg_helper.cpp @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ocloc_arg_helper.h" + +#include "shared/source/helpers/file_io.h" +#include "shared/source/helpers/string.h" + +#include "decoder/helper.h" + +#include +#include +void Source::toVectorOfStrings(std::vector &lines, bool replaceTabs) { + std::string line; + const char *file = reinterpret_cast(data); + + while (*file != '\0') { + if (replaceTabs && *file == '\t') { + line += ' '; + } else if (*file == '\n') { + lines.push_back(line); + line = ""; + } else { + line += *file; + } + file++; + } +} + +Output::Output(const std::string &name, const void *data, const size_t &size) + : name(name), size(size) { + this->data = new uint8_t[size]; + memcpy_s(reinterpret_cast(this->data), this->size, data, size); +}; + +OclocArgHelper::OclocArgHelper(const uint32_t numSources, const uint8_t **dataSources, + const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, + const uint8_t **dataInputHeaders, + const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, + uint64_t **lenOutputs, char ***nameOutputs) + : numOutputs(numOutputs), nameOutputs(nameOutputs), + dataOutputs(dataOutputs), lenOutputs(lenOutputs), hasOutput(numOutputs != nullptr) { + for (uint32_t i = 0; i < numSources; ++i) { + inputs.push_back(Source(dataSources[i], lenSources[i], nameSources[i])); + } + for (uint32_t i = 0; i < numInputHeaders; ++i) { + headers.push_back(Source(dataInputHeaders[i], lenInputHeaders[i], nameInputHeaders[i])); + } +} + +OclocArgHelper::~OclocArgHelper() { + if (outputEnabled()) { + moveOutputs(); + } +} + +bool OclocArgHelper::fileExists(const std::string &filename) const { + return sourceFileExists(filename) || ::fileExists(filename); +} + +void OclocArgHelper::moveOutputs() { + *numOutputs = static_cast(outputs.size()); + *nameOutputs = new char *[outputs.size()]; + *dataOutputs = new uint8_t *[outputs.size()]; + *lenOutputs = new uint64_t[outputs.size()]; + for (size_t i = 0; i < outputs.size(); ++i) { + (*nameOutputs)[i] = new char[outputs[i]->name.length() + 1]; + strncpy((*nameOutputs)[i], outputs[i]->name.c_str(), outputs[i]->name.length() + 1); + (*dataOutputs)[i] = outputs[i]->data; + (*lenOutputs)[i] = outputs[i]->size; + } +} + +Source *OclocArgHelper::findSourceFile(const std::string &filename) { + for (auto &source : inputs) { + if (filename == source.name) { + return &source; + } + } + return nullptr; +} + +bool OclocArgHelper::sourceFileExists(const std::string &filename) const { + for (auto &input : inputs) { + if (filename == input.name) { + return true; + } + } + return false; +} + +std::vector OclocArgHelper::headersToVectorOfStrings() { + std::vector lines; + for (auto &header : headers) { + header.toVectorOfStrings(lines, true); + } + return lines; +} + +void OclocArgHelper::readFileToVectorOfStrings(const std::string &filename, std::vector &lines) { + if (Source *s = findSourceFile(filename)) { + s->toVectorOfStrings(lines); + } else { + ::readFileToVectorOfStrings(lines, filename); + } +} + +std::vector OclocArgHelper::readBinaryFile(const std::string &filename) { + if (Source *s = findSourceFile(filename)) { + return s->toBinaryVector(); + } else { + return ::readBinaryFile(filename); + } +} + +std::unique_ptr OclocArgHelper::loadDataFromFile(const std::string &filename, size_t &retSize) { + if (Source *s = findSourceFile(filename)) { + std::unique_ptr ret(new char[static_cast(s->length)]()); + memcpy(ret.get(), s->data, static_cast(s->length)); + retSize = static_cast(s->length); + return ret; + } else { + return ::loadDataFromFile(filename.c_str(), retSize); + } +} + +void OclocArgHelper::saveOutput(const std::string &filename, const void *pData, const size_t &dataSize) { + if (outputEnabled()) { + addOutput(filename, pData, dataSize); + } else { + writeDataToFile(filename.c_str(), pData, dataSize); + } +} + +void OclocArgHelper::saveOutput(const std::string &filename, std::ostream &stream) { + std::stringstream ss; + ss << stream.rdbuf(); + if (outputEnabled()) { + addOutput(filename, ss.str().c_str(), ss.str().length()); + } else { + std::ofstream file(filename); + file << ss.str(); + } +} diff --git a/offline_compiler/ocloc_arg_helper.h b/offline_compiler/ocloc_arg_helper.h new file mode 100644 index 0000000000..a4715a8480 --- /dev/null +++ b/offline_compiler/ocloc_arg_helper.h @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include +#include +#include +#include +#include + +#pragma once + +struct Source { + const uint8_t *data; + const uint64_t length; + const char *name; + Source(const uint8_t *data, const uint64_t length, const char *name) + : data(data), length(length), name(name){}; + void toVectorOfStrings(std::vector &lines, bool replaceTabs = false); + inline std::vector toBinaryVector() { + return std::vector(data, data + length); + }; +}; + +struct Output { + std::string name; + uint8_t *data; + const size_t size; + Output(const std::string &name, const void *data, const size_t &size); +}; + +class OclocArgHelper { + protected: + std::vector inputs, headers; + std::vector outputs; + uint32_t *numOutputs = nullptr; + char ***nameOutputs = nullptr; + uint8_t ***dataOutputs = nullptr; + uint64_t **lenOutputs = nullptr; + bool hasOutput = false; + void moveOutputs(); + + Source *findSourceFile(const std::string &filename); + bool sourceFileExists(const std::string &filename) const; + + inline void addOutput(const std::string &filename, const void *data, const size_t &size) { + outputs.push_back(new Output(filename, data, size)); + } + + public: + OclocArgHelper() = default; + OclocArgHelper(const uint32_t numSources, const uint8_t **dataSources, + const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, + const uint8_t **dataInputHeaders, + const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, + uint64_t **lenOutputs, char ***nameOutputs); + virtual ~OclocArgHelper(); + + MOCKABLE_VIRTUAL bool fileExists(const std::string &filename) const; + + std::vector headersToVectorOfStrings(); + void readFileToVectorOfStrings(const std::string &filename, std::vector &lines); + MOCKABLE_VIRTUAL std::vector readBinaryFile(const std::string &filename); + std::unique_ptr loadDataFromFile(const std::string &filename, size_t &retSize); + + inline bool outputEnabled() { return hasOutput; } + inline bool hasHeaders() { return headers.size() > 0; } + void saveOutput(const std::string &filename, const void *pData, const size_t &dataSize); + void saveOutput(const std::string &filename, std::ostream &stream); + + void addInput(const std::string &filename, std::stringstream &stream); +}; diff --git a/offline_compiler/ocloc_wrapper.cpp b/offline_compiler/ocloc_wrapper.cpp new file mode 100644 index 0000000000..0701fa0ec3 --- /dev/null +++ b/offline_compiler/ocloc_wrapper.cpp @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "ocloc_wrapper.h" + +#include "shared/source/os_interface/os_library.h" + +#include "utilities/get_path.h" + +#include +#include + +typedef int (*pOclocInvoke)( + unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); + +typedef int (*pOclocFreeOutput)( + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); + +struct OclocLibrary { + pOclocInvoke invoke = nullptr; + pOclocFreeOutput freeOutput = nullptr; + + std::unique_ptr library; + bool isLoaded() { + return library != nullptr; + } +}; + +OclocWrapper::OclocWrapper() : pImpl(std::make_unique()){}; +OclocWrapper::~OclocWrapper() = default; + +struct OclocWrapper::Impl { + OclocLibrary oclocLib; + + void loadOcloc() { + OclocLibrary ocloc; + std::string oclocLibName = getPath() + OCLOC_LIB_NAME; + ocloc.library.reset(NEO::OsLibrary::load(oclocLibName)); + if (nullptr == ocloc.library) { + std::cout << "Error! Couldn't find " << OCLOC_LIB_NAME << ".\n"; + return; + } + if (nullptr == (ocloc.invoke = reinterpret_cast(ocloc.library->getProcAddress("oclocInvoke")))) { + std::cout << "Error! Couldn't find OclocInvoke function.\n"; + return; + } + if (nullptr == (ocloc.freeOutput = reinterpret_cast(ocloc.library->getProcAddress("oclocFreeOutput")))) { + std::cout << "Error! Couldn't find OclocFreeOutput function.\n"; + return; + } + this->oclocLib = std::move(ocloc); + } +}; + +int OclocWrapper::invokeOcloc(unsigned int numArgs, const char *argv[]) { + return invokeOcloc(numArgs, argv, 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr); +} + +int OclocWrapper::invokeOcloc(unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + if (false == tryLoadOcloc()) { + std::cout << "Error! Ocloc Library couldn't be loaded.\n"; + return -1; + } + return pImpl->oclocLib.invoke(numArgs, argv, + numSources, dataSources, lenSources, nameSources, + numInputHeaders, dataInputHeaders, lenInputHeaders, nameInputHeaders, + numOutputs, dataOutputs, lenOutputs, nameOutputs); +} + +int OclocWrapper::freeOutput(uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs) { + if (false == tryLoadOcloc()) { + std::cout << "Error! Ocloc Library couldn't be loaded.\n"; + return -1; + } + return pImpl->oclocLib.freeOutput(numOutputs, dataOutputs, lenOutputs, nameOutputs); +} + +bool OclocWrapper::tryLoadOcloc() { + if (false == pImpl->oclocLib.isLoaded()) { + pImpl->loadOcloc(); + } + return pImpl->oclocLib.isLoaded(); +} diff --git a/offline_compiler/ocloc_wrapper.h b/offline_compiler/ocloc_wrapper.h new file mode 100644 index 0000000000..8db09d6be6 --- /dev/null +++ b/offline_compiler/ocloc_wrapper.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include +#include +#include + +struct OclocWrapper { + public: + OclocWrapper(); + ~OclocWrapper(); + + OclocWrapper(OclocWrapper &) = delete; + OclocWrapper(const OclocWrapper &&) = delete; + OclocWrapper &operator=(const OclocWrapper &) = delete; + OclocWrapper &operator=(OclocWrapper &&) = delete; + + int invokeOcloc(unsigned int numArgs, const char *argv[]); + int invokeOcloc(unsigned int numArgs, const char *argv[], + const uint32_t numSources, const uint8_t **dataSources, const uint64_t *lenSources, const char **nameSources, + const uint32_t numInputHeaders, const uint8_t **dataInputHeaders, const uint64_t *lenInputHeaders, const char **nameInputHeaders, + uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); + int freeOutput(uint32_t *numOutputs, uint8_t ***dataOutputs, uint64_t **lenOutputs, char ***nameOutputs); + + protected: + bool tryLoadOcloc(); + struct Impl; + std::unique_ptr pImpl; +}; diff --git a/offline_compiler/offline_compiler.cpp b/offline_compiler/offline_compiler.cpp index 1dbcdd068f..0a0dd1b81a 100644 --- a/offline_compiler/offline_compiler.cpp +++ b/offline_compiler/offline_compiler.cpp @@ -78,6 +78,24 @@ OfflineCompiler *OfflineCompiler::create(size_t numArgs, const std::vectorargHelper = std::make_unique(); + retVal = pOffCompiler->initialize(numArgs, allArgs, dumpFiles); + } + + if (retVal != CL_SUCCESS) { + delete pOffCompiler; + pOffCompiler = nullptr; + } + + return pOffCompiler; +} + +OfflineCompiler *OfflineCompiler::create(size_t numArgs, const std::vector &allArgs, bool dumpFiles, int &retVal, std::unique_ptr helper) { + retVal = CL_SUCCESS; + auto pOffCompiler = new OfflineCompiler(); + + if (pOffCompiler) { + pOffCompiler->argHelper = std::move(helper); retVal = pOffCompiler->initialize(numArgs, allArgs, dumpFiles); } @@ -256,7 +274,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & oclocOptionsFileName.append("_ocloc_options.txt"); std::string oclocOptionsFromFile; - bool oclocOptionsRead = readOptionsFromFile(oclocOptionsFromFile, oclocOptionsFileName); + bool oclocOptionsRead = readOptionsFromFile(oclocOptionsFromFile, oclocOptionsFileName, argHelper); if (oclocOptionsRead && !isQuiet()) { printf("Building with ocloc options:\n%s\n", oclocOptionsFromFile.c_str()); } @@ -275,7 +293,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & std::string optionsFileName = inputFile.substr(0, ext_start); optionsFileName.append("_options.txt"); - bool optionsRead = readOptionsFromFile(options, optionsFileName); + bool optionsRead = readOptionsFromFile(options, optionsFileName, argHelper); if (optionsRead && !isQuiet()) { printf("Building with options:\n%s\n", options.c_str()); } @@ -284,7 +302,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & internalOptionsFileName.append("_internal_options.txt"); std::string internalOptionsFromFile; - bool internalOptionsRead = readOptionsFromFile(internalOptionsFromFile, internalOptionsFileName); + bool internalOptionsRead = readOptionsFromFile(internalOptionsFromFile, internalOptionsFileName, argHelper); if (internalOptionsRead && !isQuiet()) { printf("Building with internal options:\n%s\n", internalOptionsFromFile.c_str()); } @@ -295,7 +313,7 @@ int OfflineCompiler::initialize(size_t numArgs, const std::vector & parseDebugSettings(); // set up the device inside the program - sourceFromFile = loadDataFromFile(inputFile.c_str(), sourceFromFileSize); + sourceFromFile = argHelper->loadDataFromFile(inputFile, sourceFromFileSize); if (sourceFromFileSize == 0) { retVal = INVALID_FILE; return retVal; @@ -507,7 +525,7 @@ int OfflineCompiler::parseCommandLine(size_t numArgs, const std::vectorfileExists(inputFile)) { printf("Error: Input file %s missing.\n", inputFile.c_str()); retVal = INVALID_FILE; } else { @@ -828,24 +846,18 @@ void OfflineCompiler::writeOutAllFiles() { if (irBinary) { std::string irOutputFileName = generateFilePathForIr(fileBase) + generateOptsSuffix(); - writeDataToFile( - irOutputFileName.c_str(), - irBinary, - irBinarySize); + argHelper->saveOutput(irOutputFileName, irBinary, irBinarySize); } if (genBinary) { std::string genOutputFile = generateFilePath(outputDirectory, fileBase, ".gen") + generateOptsSuffix(); - writeDataToFile( - genOutputFile.c_str(), - genBinary, - genBinarySize); + argHelper->saveOutput(genOutputFile, genBinary, genBinarySize); if (useCppFile) { std::string cppOutputFile = generateFilePath(outputDirectory, fileBase, ".cpp"); std::string cpp = parseBinAsCharArray((uint8_t *)genBinary, genBinarySize, fileTrunk); - writeDataToFile(cppOutputFile.c_str(), cpp.c_str(), cpp.size()); + argHelper->saveOutput(cppOutputFile, cpp.c_str(), cpp.size()); } } @@ -856,8 +868,8 @@ void OfflineCompiler::writeOutAllFiles() { } else { elfOutputFile = generateFilePath(outputDirectory, fileBase, ".bin") + generateOptsSuffix(); } - writeDataToFile( - elfOutputFile.c_str(), + argHelper->saveOutput( + elfOutputFile, elfBinary.data(), elfBinary.size()); } @@ -865,19 +877,19 @@ void OfflineCompiler::writeOutAllFiles() { if (debugDataBinary) { std::string debugOutputFile = generateFilePath(outputDirectory, fileBase, ".dbg") + generateOptsSuffix(); - writeDataToFile( - debugOutputFile.c_str(), + argHelper->saveOutput( + debugOutputFile, debugDataBinary, debugDataBinarySize); } } -bool OfflineCompiler::readOptionsFromFile(std::string &options, const std::string &file) { - if (!fileExists(file)) { +bool OfflineCompiler::readOptionsFromFile(std::string &options, const std::string &file, std::unique_ptr &helper) { + if (!helper->fileExists(file)) { return false; } size_t optionsSize = 0U; - auto optionsFromFile = loadDataFromFile(file.c_str(), optionsSize); + auto optionsFromFile = helper->loadDataFromFile(file, optionsSize); if (optionsSize > 0) { // Remove comment containing copyright header options = optionsFromFile.get(); diff --git a/offline_compiler/offline_compiler.h b/offline_compiler/offline_compiler.h index eee82503b2..774ab373b6 100644 --- a/offline_compiler/offline_compiler.h +++ b/offline_compiler/offline_compiler.h @@ -11,6 +11,8 @@ #include "shared/source/utilities/arrayref.h" #include "shared/source/utilities/const_stringref.h" +#include "offline_compiler/ocloc_arg_helper.h" + #include "cif/common/cif_main.h" #include "ocl_igc_interface/fcl_ocl_device_ctx.h" #include "ocl_igc_interface/igc_ocl_device_ctx.h" @@ -38,6 +40,7 @@ std::string getDevicesTypes(); class OfflineCompiler { public: static OfflineCompiler *create(size_t numArgs, const std::vector &allArgs, bool dumpFiles, int &retVal); + static OfflineCompiler *create(size_t numArgs, const std::vector &allArgs, bool dumpFiles, int &retVal, std::unique_ptr helper); int build(); std::string &getBuildLog(); void printUsage(); @@ -51,7 +54,9 @@ class OfflineCompiler { } std::string parseBinAsCharArray(uint8_t *binary, size_t size, std::string &fileName); - static bool readOptionsFromFile(std::string &optionsOut, const std::string &file); + + static bool readOptionsFromFile(std::string &optionsOut, const std::string &file, std::unique_ptr &helper); + ArrayRef getPackedDeviceBinaryOutput() { return this->elfBinary; } @@ -126,5 +131,7 @@ class OfflineCompiler { CIF::RAII::UPtr_t fclMain = nullptr; CIF::RAII::UPtr_t fclDeviceCtx = nullptr; IGC::CodeType::CodeType_t preferredIntermediateRepresentation; + + std::unique_ptr argHelper = nullptr; }; } // namespace NEO diff --git a/offline_compiler/utilities/CMakeLists.txt b/offline_compiler/utilities/CMakeLists.txt index f4fb37d29d..f930c4142a 100644 --- a/offline_compiler/utilities/CMakeLists.txt +++ b/offline_compiler/utilities/CMakeLists.txt @@ -4,24 +4,27 @@ # SPDX-License-Identifier: MIT # -set(CLOC_SRCS_UTILITIES +set(CLOC_LIB_SRCS_UTILITIES ${CMAKE_CURRENT_SOURCE_DIR}/safety_caller.h ${CMAKE_CURRENT_SOURCE_DIR}/get_current_dir.h + ${CMAKE_CURRENT_SOURCE_DIR}/get_path.h ) if(WIN32) - list(APPEND CLOC_SRCS_UTILITIES + list(APPEND CLOC_LIB_SRCS_UTILITIES ${CMAKE_CURRENT_SOURCE_DIR}/windows/safety_caller_windows.cpp ${CMAKE_CURRENT_SOURCE_DIR}/windows/safety_guard_windows.h ${CMAKE_CURRENT_SOURCE_DIR}/windows/seh_exception.cpp ${CMAKE_CURRENT_SOURCE_DIR}/windows/seh_exception.h ${CMAKE_CURRENT_SOURCE_DIR}/windows/get_current_dir_windows.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/windows/get_path.cpp ) else() - list(APPEND CLOC_SRCS_UTILITIES + list(APPEND CLOC_LIB_SRCS_UTILITIES ${CMAKE_CURRENT_SOURCE_DIR}/linux/safety_caller_linux.cpp ${CMAKE_CURRENT_SOURCE_DIR}/linux/get_current_dir_linux.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/linux/get_path.cpp ) endif() -target_sources(ocloc PRIVATE ${CLOC_SRCS_UTILITIES}) +target_sources(ocloc_lib PRIVATE ${CLOC_LIB_SRCS_UTILITIES}) diff --git a/offline_compiler/utilities/get_path.h b/offline_compiler/utilities/get_path.h new file mode 100644 index 0000000000..053de86d20 --- /dev/null +++ b/offline_compiler/utilities/get_path.h @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#pragma once + +extern std::string getPath(); diff --git a/offline_compiler/utilities/linux/get_path.cpp b/offline_compiler/utilities/linux/get_path.cpp new file mode 100644 index 0000000000..3cced1a593 --- /dev/null +++ b/offline_compiler/utilities/linux/get_path.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include +#include +#include +#include + +std::string getPath() { + char exepath[128] = {0}; + std::stringstream ss; + ss << "/proc/" << getpid() << "/exe"; + if (readlink(ss.str().c_str(), exepath, 128) != -1) { + std::string path = std::string(exepath); + path = path.substr(0, path.find_last_of('/') + 1); + return path; + } else { + return std::string(""); + } +} diff --git a/offline_compiler/utilities/windows/get_path.cpp b/offline_compiler/utilities/windows/get_path.cpp new file mode 100644 index 0000000000..5e0b9eef4a --- /dev/null +++ b/offline_compiler/utilities/windows/get_path.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include + +std::string getPath() { + return std::string(""); +} diff --git a/opencl/source/built_ins/kernels/CMakeLists.txt b/opencl/source/built_ins/kernels/CMakeLists.txt index bb9dcf5d34..2d944783ca 100644 --- a/opencl/source/built_ins/kernels/CMakeLists.txt +++ b/opencl/source/built_ins/kernels/CMakeLists.txt @@ -64,11 +64,12 @@ function(compile_builtin gen_type platform_type builtin bits builtin_options) set(cloc_cmd_prefix ocloc) else() if(DEFINED NEO__IGC_LIBRARY_PATH) - set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH} $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH}:$ $) else() - set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) endif() endif() + list(APPEND __cloc__options__ "-cl-kernel-arg-info") add_custom_command( OUTPUT ${OUTPUT_FILES} diff --git a/opencl/source/scheduler/scheduler_binary.cmake b/opencl/source/scheduler/scheduler_binary.cmake index 1a0e30d1a3..740ff7d63e 100644 --- a/opencl/source/scheduler/scheduler_binary.cmake +++ b/opencl/source/scheduler/scheduler_binary.cmake @@ -35,9 +35,9 @@ function(compile_kernel target gen_type platform_type kernel) set(cloc_cmd_prefix ocloc) else() if(DEFINED NEO__IGC_LIBRARY_PATH) - set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH} $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH}:$ $) else() - set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) endif() endif() list(APPEND __cloc__options__ "-cl-kernel-arg-info") diff --git a/opencl/test/unit_test/CMakeLists.txt b/opencl/test/unit_test/CMakeLists.txt index b90e6fee28..e01d3e9996 100644 --- a/opencl/test/unit_test/CMakeLists.txt +++ b/opencl/test/unit_test/CMakeLists.txt @@ -205,9 +205,9 @@ if(WIN32) set(cloc_cmd_prefix ocloc) else() if(DEFINED NEO__IGC_LIBRARY_PATH) - set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH} $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH}:$ $) else() - set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) endif() endif() diff --git a/opencl/test/unit_test/offline_compiler/CMakeLists.txt b/opencl/test/unit_test/offline_compiler/CMakeLists.txt index 92f49a03fc..ae026383b2 100644 --- a/opencl/test/unit_test/offline_compiler/CMakeLists.txt +++ b/opencl/test/unit_test/offline_compiler/CMakeLists.txt @@ -20,15 +20,16 @@ ${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_encoder.h ${CMAKE_CURRENT_SOURCE_DIR}/decoder/mock/mock_iga_wrapper.h ${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_offline_compiler.h ${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_sip_ocloc_tests.cpp +${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_argument_helper.h ) -set(CLOC_SRCS_UTILITIES +set(CLOC_LIB_SRCS_UTILITIES ${NEO_SOURCE_DIR}/offline_compiler/utilities/safety_caller.h ${NEO_SOURCE_DIR}/offline_compiler/utilities//get_current_dir.h ) if(WIN32) - list(APPEND CLOC_SRCS_UTILITIES + list(APPEND CLOC_LIB_SRCS_UTILITIES ${NEO_SOURCE_DIR}/offline_compiler/utilities/windows/safety_caller_windows.cpp ${NEO_SOURCE_DIR}/offline_compiler/utilities/windows/safety_guard_windows.h ${NEO_SOURCE_DIR}/offline_compiler/utilities/windows/seh_exception.cpp @@ -36,7 +37,7 @@ if(WIN32) ${NEO_SOURCE_DIR}/offline_compiler/utilities/windows/get_current_dir_windows.cpp ) else() - list(APPEND CLOC_SRCS_UTILITIES + list(APPEND CLOC_LIB_SRCS_UTILITIES ${NEO_SOURCE_DIR}/offline_compiler/utilities/linux/safety_caller_linux.cpp ${NEO_SOURCE_DIR}/offline_compiler/utilities/linux/safety_guard_linux.h ${NEO_SOURCE_DIR}/offline_compiler/utilities/linux/get_current_dir_linux.cpp @@ -62,8 +63,8 @@ set(IGDRCL_SRCS_offline_compiler_tests ${IGDRCL_SRCS_cloc} ${IGDRCL_SRCS_offline_compiler_mock} ${IGDRCL_SRCS_tests_compiler_mocks} - ${CLOC_SRCS_LIB} - ${CLOC_SRCS_UTILITIES} + ${CLOC_LIB_SRCS_LIB} + ${CLOC_LIB_SRCS_UTILITIES} ) if(WIN32) @@ -81,9 +82,9 @@ link_directories(${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) add_executable(ocloc_tests ${IGDRCL_SRCS_offline_compiler_tests}) target_include_directories(ocloc_tests PRIVATE - $ + $ ) -target_compile_definitions(ocloc_tests PUBLIC MOCKABLE_VIRTUAL=virtual $) +target_compile_definitions(ocloc_tests PUBLIC MOCKABLE_VIRTUAL=virtual $) target_link_libraries(ocloc_tests gmock-gtest) @@ -95,25 +96,25 @@ if(UNIX) target_link_libraries(ocloc_tests dl pthread) endif() -get_property(CLOC_FOLDER TARGET ocloc PROPERTY FOLDER) -get_property(CLOC_COMPILE_FLAGS TARGET ocloc PROPERTY COMPILE_FLAGS) -set_property(TARGET ocloc_tests PROPERTY FOLDER ${CLOC_FOLDER}) -set_property(TARGET ocloc_tests APPEND_STRING PROPERTY COMPILE_FLAGS ${CLOC_COMPILE_FLAGS}) +get_property(CLOC_LIB_FOLDER TARGET ocloc_lib PROPERTY FOLDER) +get_property(CLOC_LIB_COMPILE_FLAGS TARGET ocloc_lib PROPERTY COMPILE_FLAGS) +set_property(TARGET ocloc_tests PROPERTY FOLDER ${CLOC_LIB_FOLDER}) +set_property(TARGET ocloc_tests APPEND_STRING PROPERTY COMPILE_FLAGS ${CLOC_LIB_COMPILE_FLAGS}) -string(TOLOWER ${DEFAULT_TESTED_PLATFORM} CLOC_DEFAULT_DEVICE) +string(TOLOWER ${DEFAULT_TESTED_PLATFORM} CLOC_LIB_DEFAULT_DEVICE) add_custom_target(run_ocloc_tests ALL DEPENDS ocloc_tests ) macro(macro_for_each_platform) - if("${PLATFORM_IT_LOWER}" STREQUAL "${CLOC_DEFAULT_DEVICE}") + if("${PLATFORM_IT_LOWER}" STREQUAL "${CLOC_LIB_DEFAULT_DEVICE}") foreach(PLATFORM_TYPE ${PLATFORM_TYPES}) if(${PLATFORM_IT}_IS_${PLATFORM_TYPE}) get_family_name_with_type(${GEN_TYPE} ${PLATFORM_TYPE}) add_dependencies(run_ocloc_tests prepare_test_kernels_${family_name_with_type}) neo_copy_test_files(copy_test_files_${family_name_with_type} ${family_name_with_type}) add_dependencies(run_ocloc_tests copy_test_files_${family_name_with_type}) - set(run_tests_cmd ocloc_tests --device ${CLOC_DEFAULT_DEVICE} --family_type ${family_name_with_type}) + set(run_tests_cmd ocloc_tests --device ${CLOC_LIB_DEFAULT_DEVICE} --family_type ${family_name_with_type}) endif() endforeach() endif() @@ -123,17 +124,17 @@ macro(macro_for_each_gen) endmacro() apply_macro_for_each_gen("TESTED") -set_property(TARGET run_ocloc_tests PROPERTY FOLDER ${CLOC_FOLDER}) +set_property(TARGET run_ocloc_tests PROPERTY FOLDER ${CLOC_LIB_FOLDER}) if(WIN32) add_custom_command( TARGET run_ocloc_tests POST_BUILD COMMAND echo deleting offline compiler files and directories... - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/copybuffer_${CLOC_DEFAULT_DEVICE}.bc - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/copybuffer_${CLOC_DEFAULT_DEVICE}.gen - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/copybuffer_${CLOC_DEFAULT_DEVICE}.bin - COMMAND ${CMAKE_COMMAND} -E remove_directory ${TargetDir}/${CLOC_DEFAULT_DEVICE}/offline_compiler_test + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/copybuffer_${CLOC_LIB_DEFAULT_DEVICE}.bc + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/copybuffer_${CLOC_LIB_DEFAULT_DEVICE}.gen + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/copybuffer_${CLOC_LIB_DEFAULT_DEVICE}.bin + COMMAND ${CMAKE_COMMAND} -E remove_directory ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/offline_compiler_test COMMAND ${run_tests_cmd} WORKING_DIRECTORY ${TargetDir} ) @@ -142,10 +143,10 @@ else() TARGET run_ocloc_tests POST_BUILD COMMAND echo deleting offline compiler files and directories... - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/*.bc - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/*.gen - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/*.ll - COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_DEFAULT_DEVICE}/*.bin + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/*.bc + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/*.gen + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/*.ll + COMMAND ${CMAKE_COMMAND} -E remove ${TargetDir}/${CLOC_LIB_DEFAULT_DEVICE}/*.bin COMMAND ${CMAKE_COMMAND} -E remove_directory "${TargetDir}/offline_compiler_test" COMMAND ${run_tests_cmd} WORKING_DIRECTORY ${TargetDir} diff --git a/opencl/test/unit_test/offline_compiler/decoder/decoder_tests.cpp b/opencl/test/unit_test/offline_compiler/decoder/decoder_tests.cpp index f75ca48297..b4b30a7ea0 100644 --- a/opencl/test/unit_test/offline_compiler/decoder/decoder_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/decoder/decoder_tests.cpp @@ -29,7 +29,7 @@ SKernelBinaryHeaderCommon createKernelBinaryHeaderCommon(const uint32_t kernelNa namespace NEO { TEST(DecoderTests, WhenParsingValidListOfParametersThenReturnValueIsZero) { - const char *argv[] = { + std::vector args = { "ocloc", "decoder", "-file", @@ -40,22 +40,22 @@ TEST(DecoderTests, WhenParsingValidListOfParametersThenReturnValueIsZero) { "test_files/created"}; MockDecoder decoder; - EXPECT_EQ(0, decoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_EQ(0, decoder.validateInput(args)); } TEST(DecoderTests, WhenMissingParametersThenValidateInputReturnsErrorCode) { - const char *argv[] = { + std::vector args = { "ocloc", "decoder", "-patch", "test_files"}; MockDecoder decoder; - EXPECT_NE(0, decoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_NE(0, decoder.validateInput(args)); } TEST(DecoderTests, GivenWrongParametersWhenParsingParametersThenValidateInputReturnsErrorCode) { - const char *argv[] = { + std::vector args = { "cloc", "decoder", "-file", @@ -66,7 +66,7 @@ TEST(DecoderTests, GivenWrongParametersWhenParsingParametersThenValidateInputRet "test_files/created"}; MockDecoder decoder; - EXPECT_NE(0, decoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_NE(0, decoder.validateInput(args)); } TEST(DecoderTests, GivenValidSizeStringWhenGettingSizeThenProperOutcomeIsExpectedAndExceptionIsNotThrown) { diff --git a/opencl/test/unit_test/offline_compiler/decoder/encoder_tests.cpp b/opencl/test/unit_test/offline_compiler/decoder/encoder_tests.cpp index 6358ed728d..86c596a7bc 100644 --- a/opencl/test/unit_test/offline_compiler/decoder/encoder_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/decoder/encoder_tests.cpp @@ -17,7 +17,7 @@ namespace NEO { TEST(EncoderTests, WhenParsingValidListOfParametersThenReturnValueIsZero) { - const char *argv[] = { + std::vector args = { "ocloc", "asm", "-dump", @@ -26,11 +26,11 @@ TEST(EncoderTests, WhenParsingValidListOfParametersThenReturnValueIsZero) { "test_files/binary_gen.bin"}; MockEncoder encoder; - EXPECT_EQ(0, encoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_EQ(0, encoder.validateInput(args)); } TEST(EncoderTests, WhenMissingParametersThenErrorCodeIsReturned) { - const char *argv[] = { + std::vector args = { "ocloc", "asm", "-dump", @@ -38,11 +38,11 @@ TEST(EncoderTests, WhenMissingParametersThenErrorCodeIsReturned) { "-out"}; MockEncoder encoder; - EXPECT_NE(0, encoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_NE(0, encoder.validateInput(args)); } -TEST(EncoderTests, GivenWrongParametersWhenParsingParametersThenErrorCodeIsReturne) { - const char *argv[] = { +TEST(EncoderTests, GivenWrongParametersWhenParsingParametersThenErrorCodeIsReturned) { + std::vector args = { "ocloc", "asm", "-dump", @@ -51,7 +51,7 @@ TEST(EncoderTests, GivenWrongParametersWhenParsingParametersThenErrorCodeIsRetur "rasputin"}; MockEncoder encoder; - EXPECT_NE(0, encoder.validateInput(static_cast(arrayCount(argv)), argv)); + EXPECT_NE(0, encoder.validateInput(args)); } TEST(EncoderTests, WhenTryingToCopyNonExistingFileThenErrorCodeIsReturned) { diff --git a/opencl/test/unit_test/offline_compiler/decoder/mock/mock_decoder.h b/opencl/test/unit_test/offline_compiler/decoder/mock/mock_decoder.h index c948d15e57..249d187036 100644 --- a/opencl/test/unit_test/offline_compiler/decoder/mock/mock_decoder.h +++ b/opencl/test/unit_test/offline_compiler/decoder/mock/mock_decoder.h @@ -17,6 +17,7 @@ struct MockDecoder : public BinaryDecoder { : BinaryDecoder(file, patch, dump) { this->iga.reset(new MockIgaWrapper); setMessagePrinter(MessagePrinter{true}); + argHelper = std::make_unique(); }; using BinaryDecoder::binaryFile; using BinaryDecoder::decode; diff --git a/opencl/test/unit_test/offline_compiler/decoder/mock/mock_encoder.h b/opencl/test/unit_test/offline_compiler/decoder/mock/mock_encoder.h index f36beec2d2..161ce17fb4 100644 --- a/opencl/test/unit_test/offline_compiler/decoder/mock/mock_encoder.h +++ b/opencl/test/unit_test/offline_compiler/decoder/mock/mock_encoder.h @@ -9,6 +9,7 @@ #include "shared/source/helpers/hash.h" #include "offline_compiler/decoder/binary_encoder.h" +#include "opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h" #include "mock_iga_wrapper.h" @@ -21,8 +22,11 @@ struct MockEncoder : public BinaryEncoder { : BinaryEncoder(dump, elf) { this->iga.reset(new MockIgaWrapper); setMessagePrinter(MessagePrinter{true}); + this->argHelper.reset(new MockOclocArgHelper(filesMap)); }; + std::map filesMap; + bool copyBinaryToBinary(const std::string &srcFileName, std::ostream &outBinary, uint32_t *binaryLength) override { auto it = filesMap.find(srcFileName); if (it == filesMap.end()) { @@ -34,16 +38,6 @@ struct MockEncoder : public BinaryEncoder { } return true; } - - bool fileExists(const std::string &path) const override { - return filesMap.count(path) || BinaryEncoder::fileExists(path); - } - - std::vector readBinaryFile(const std::string &path) const override { - return filesMap.count(path) ? std::vector(filesMap.at(path).c_str(), filesMap.at(path).c_str() + filesMap.at(path).size()) - : BinaryEncoder::readBinaryFile(path); - } - using BinaryEncoder::addPadding; using BinaryEncoder::calculatePatchListSizes; using BinaryEncoder::copyBinaryToBinary; @@ -60,6 +54,4 @@ struct MockEncoder : public BinaryEncoder { MockIgaWrapper *getMockIga() const { return static_cast(iga.get()); } - - std::map filesMap; }; diff --git a/opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h b/opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h new file mode 100644 index 0000000000..c61e80f173 --- /dev/null +++ b/opencl/test/unit_test/offline_compiler/mock/mock_argument_helper.h @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2020 Intel Corporation + * + * SPDX-License-Identifier: MIT + * + */ + +#include "offline_compiler/ocloc_arg_helper.h" + +#include +#include + +class MockOclocArgHelper : public OclocArgHelper { + public: + std::map &filesMap; + MockOclocArgHelper(std::map &filesMap) : OclocArgHelper( + 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr), + filesMap(filesMap){}; + + protected: + bool fileExists(const std::string &filename) const override { + return filesMap.find(filename) != filesMap.end(); + } + + std::vector readBinaryFile(const std::string &filename) override { + auto file = filesMap[filename]; + return std::vector(file.begin(), file.end()); + } +}; diff --git a/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h b/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h index 6d2695a482..796fecc0bf 100644 --- a/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h +++ b/opencl/test/unit_test/offline_compiler/mock/mock_offline_compiler.h @@ -31,6 +31,8 @@ class MockOfflineCompiler : public OfflineCompiler { using OfflineCompiler::useOptionsSuffix; MockOfflineCompiler() : OfflineCompiler() { + argHelper.reset(new OclocArgHelper( + 0, nullptr, nullptr, nullptr, 0, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr)); } int initialize(size_t numArgs, const std::vector &argv) { diff --git a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp index 7daf2accc7..317687fa53 100644 --- a/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp +++ b/opencl/test/unit_test/offline_compiler/offline_compiler_tests.cpp @@ -1051,7 +1051,8 @@ TEST(OfflineCompilerTest, givenNonExistingFilenameWhenUsedToReadOptionsThenReadO std::string file("non_existing_file"); ASSERT_FALSE(fileExists(file.c_str())); - bool result = OfflineCompiler::readOptionsFromFile(options, file); + auto helper = std::make_unique(); + bool result = OfflineCompiler::readOptionsFromFile(options, file, helper); EXPECT_FALSE(result); } diff --git a/shared/source/built_ins/kernels/CMakeLists.txt b/shared/source/built_ins/kernels/CMakeLists.txt index 41ac296e5f..dd5df2061f 100644 --- a/shared/source/built_ins/kernels/CMakeLists.txt +++ b/shared/source/built_ins/kernels/CMakeLists.txt @@ -64,9 +64,9 @@ function(compile_builtin gen_type platform_type builtin bits builtin_options) set(cloc_cmd_prefix ocloc) else() if(DEFINED NEO__IGC_LIBRARY_PATH) - set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH} $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=${NEO__IGC_LIBRARY_PATH}:$ $) else() - set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) + set(cloc_cmd_prefix LD_LIBRARY_PATH=$ $) endif() endif() list(APPEND __cloc__options__ "-cl-kernel-arg-info")