diff --git a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp index b2126894cb..a79a17d149 100644 --- a/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp +++ b/rocclr/compiler/lib/backends/common/v0_8/if_acl.cpp @@ -2256,22 +2256,72 @@ if_aclQueryInfo(aclCompiler *cl, void *ptr, size_t *size) { - if (!size) + if (!size) { return ACL_ERROR; + } const oclBIFSymbolStruct* sym = findBIF30SymStruct(symOpenclMeta); assert(sym && "symbol not found"); - std::string symbol = sym->str[PRE] + std::string(kernel) + sym->str[POST]; + aclSections secID = sym->sections[0]; + std::string pre = std::string(sym->str[PRE]); + std::string post = std::string(sym->str[POST]); + if (RT_KERNEL_NAMES == query) { + bifbase *elfBin = reinterpret_cast(binary->bin); + if (!elfBin) { + return ACL_ELF_ERROR; + } + bifbase::SymbolVector symbols, kernels; + elfBin->getSectionSymbols(secID, symbols); + size_t totSize = 0; + if (!symbols.empty()) { + std::size_t beg = 0, begKernel = 0, end = 0, endKernel = 0, endSize = 0; + const oclBIFSymbolStruct* symKernel = findBIF30SymStruct(symOpenclKernel); + assert(symKernel && "symbol not found"); + std::string preKernel = std::string(symKernel->str[PRE]); + std::string postKernel = std::string(symKernel->str[POST]); + for (bifbase::SymbolVector::iterator it = symbols.begin(); it != symbols.end(); ++it) { + beg = (*it).find(pre); + if (std::string::npos == beg) continue; + beg += pre.size(); + begKernel = (*it).find(preKernel, beg); + if (std::string::npos != begKernel) { + beg = begKernel + preKernel.size(); + end = (*it).rfind(postKernel); + endSize = postKernel.size(); + } else { + end = (*it).rfind(post); + } + if (std::string::npos == end) continue; + endSize += post.size(); + if (end <= beg || end != (*it).size() - endSize) continue; + std::string kernel((*it).substr(beg, (*it).size() - beg - endSize) + " "); + totSize += kernel.size(); + kernels.push_back(kernel); + } + } + if (!ptr) { + *size = totSize > 0 ? totSize + 1 : 0; + return ACL_SUCCESS; + } else if (*size >= totSize && totSize > 0) { + char* tmp = reinterpret_cast(ptr); + for (bifbase::SymbolVector::iterator it = kernels.begin(); it != kernels.end(); ++it) { + memcpy(tmp, (*it).c_str(), (*it).size()); + tmp += (*it).size(); + } + *(tmp++) = '\0'; + return ACL_SUCCESS; + } + return ACL_ERROR; + } size_t roSize; acl_error error_code; - const void* roSec = cl->clAPI.extSym(cl, binary, &roSize, - sym->sections[0], symbol.c_str(), &error_code); + std::string symbol = pre + std::string(kernel) + post; + const void* roSec = cl->clAPI.extSym(cl, binary, &roSize, secID, symbol.c_str(), &error_code); if (error_code != ACL_SUCCESS) return error_code; if (roSec == NULL || roSize == 0) { return ACL_ELF_ERROR; } const aclMetadata *md = reinterpret_cast(roSec); bool success = false; - switch (query) { default: break; case RT_CPU_BARRIER_NAMES: diff --git a/rocclr/compiler/lib/include/v0_8/aclEnums.h b/rocclr/compiler/lib/include/v0_8/aclEnums.h index 91058b871b..451ff72126 100644 --- a/rocclr/compiler/lib/include/v0_8/aclEnums.h +++ b/rocclr/compiler/lib/include/v0_8/aclEnums.h @@ -201,7 +201,8 @@ typedef enum _rt_query_types_enum_0_8 { RT_DEVICE_ENQUEUE = 11, RT_KERNEL_INDEX = 12, RT_KERNEL_NAME = 13, - RT_LAST_TYPE = 14 + RT_KERNEL_NAMES = 14, + RT_LAST_TYPE = 15 } aclQueryType_0_8; //! An enumeration for the various GPU capabilities diff --git a/rocclr/compiler/lib/utils/v0_8/libUtils.h b/rocclr/compiler/lib/utils/v0_8/libUtils.h index 1f85bb044f..60a6d9340d 100644 --- a/rocclr/compiler/lib/utils/v0_8/libUtils.h +++ b/rocclr/compiler/lib/utils/v0_8/libUtils.h @@ -5,6 +5,7 @@ #define _CL_LIB_UTILS_0_8_H_ #include "v0_8/aclTypes.h" #include +#include #include "library.hpp" // Utility function to set a flag in option structure // of the aclDevCaps. @@ -176,4 +177,13 @@ enum scId { SC_LAST, }; +inline std::vector splitSpaceSeparatedString(char *str) +{ + std::string s(str); + std::stringstream ss(s); + std::istream_iterator beg(ss), end; + std::vector vec(beg, end); + return vec; +} + #endif // _CL_LIB_UTILS_0_8_H_ diff --git a/rocclr/runtime/device/gpu/gpukernel.cpp b/rocclr/runtime/device/gpu/gpukernel.cpp index 61614d9045..4417275d52 100644 --- a/rocclr/runtime/device/gpu/gpukernel.cpp +++ b/rocclr/runtime/device/gpu/gpukernel.cpp @@ -9,6 +9,7 @@ #include "device/gpu/gpusched.hpp" #include "platform/commandqueue.hpp" #include "utils/options.hpp" +#include "utils/bif_section_labels.hpp" #include "acl.h" #include "SCShadersR678XXCommon.h" @@ -3513,8 +3514,10 @@ bool HSAILKernel::init(bool finalize) { acl_error error; + const oclBIFSymbolStruct* sym = findBIF30SymStruct(symOpenclKernel); + assert(sym && "symbol not found"); + std::string openClKernelName(std::string("&") + sym->str[PRE] + name() + sym->str[POST]); //compile kernel down to ISA - std::string openClKernelName("&__OpenCL_" + name() + "_kernel"); if (finalize) { std::string options(compileOptions_.c_str()); options.append(" -just-kernel="); diff --git a/rocclr/runtime/device/gpu/gpuprogram.cpp b/rocclr/runtime/device/gpu/gpuprogram.cpp index a938e04008..777e1a6ade 100644 --- a/rocclr/runtime/device/gpu/gpuprogram.cpp +++ b/rocclr/runtime/device/gpu/gpuprogram.cpp @@ -15,6 +15,7 @@ #include #include #include "utils/options.hpp" +#include "utils/libUtils.h" #include "newcore.h" extern "C" bool @@ -2159,76 +2160,50 @@ HSAILProgram::linkImpl(amd::option::Options* options) buildLog_ += "Error while BRIG Codegen phase: loading BRIG globals in the ELF \n"; return false; } - // We need to pull out kernels' names for finalizing kernels - //! @todo Rewrite the below code, if another way to obtain kernel names - //! appears in the compiler library - size_t hsailSize = 0; - const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symHSAILText); - assert(symbol && "symbol not found"); - std::string symName = symbol->str[PRE] + std::string("main") + symbol->str[POST]; - const void *hsailText = aclExtractSymbol(dev().hsaCompiler(), binaryElf_, - &hsailSize, aclCODEGEN, symName.c_str(), &errorCode); + size_t kernelNamesSize = 0; + errorCode = aclQueryInfo(dev().hsaCompiler(), binaryElf_, RT_KERNEL_NAMES, NULL, NULL, &kernelNamesSize); if (errorCode != ACL_SUCCESS) { - buildLog_ += "Error while reading out the HSAIL from the ELF \n" ; + buildLog_ += "Error while Finalization phase: kernel names query from the ELF failed\n"; return false; } - std::string hsailProgram((char *)hsailText, hsailSize); - HSAILProgram_ = hsailProgram; - if (!HSAILProgram_.empty()) { - bool dynamicParallelism = false; - // Find out the name of the kernel. Works for multiple kernels - int pos = 0; - while (true) { - std::string findString = "kernel &"; - size_t kernelNPos = HSAILProgram_.find(findString, pos); - if (kernelNPos == std::string::npos) { - break; - } - size_t kernelEndNPos = HSAILProgram_.find("l(", kernelNPos); - pos = kernelEndNPos + 1; - if (kernelEndNPos == std::string::npos) { - break; - } - // "kernel &" is 8 - // "__OpenCL_" is 9 - // "_kerne" is 6 - // We can drop all this with a compiler tweak later - std::string kernelName = HSAILProgram_.substr(kernelNPos + 8 + 9, - kernelEndNPos - - (kernelNPos + 8 + 9) - 6); - HSAILKernel *aKernel = new HSAILKernel(kernelName, this, - options->origOptionStr + hsailOptions()); + if (kernelNamesSize > 0) { + char* kernelNames = new char[kernelNamesSize]; + errorCode = aclQueryInfo(dev().hsaCompiler(), binaryElf_, RT_KERNEL_NAMES, NULL, kernelNames, &kernelNamesSize); + if (errorCode != ACL_SUCCESS) { + buildLog_ += "Error while Finalization phase: kernel's Metadata is corrupted in the ELF\n"; + delete kernelNames; + return false; + } + std::vector vKernels = splitSpaceSeparatedString(kernelNames); + delete kernelNames; + std::vector::iterator it = vKernels.begin(); + bool dynamicParallelism = false; + for (it; it != vKernels.end(); ++it) { + std::string kernelName = *it; + HSAILKernel *aKernel = new HSAILKernel(kernelName, this, options->origOptionStr + hsailOptions()); if (!aKernel->init(finalize)) { return false; } buildLog_ += aKernel->buildLog(); - aKernel->setUniformWorkGroupSize(options - ->oVariables->UniformWorkGroupSize); + aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize); kernels()[kernelName] = aKernel; dynamicParallelism |= aKernel->dynamicParallelism(); - // Find max scratch regs used in the program - // It's used for scratch buffer preallocation with - // dynamic parallelism, since runtime doesn't know - // which child kernel will be called - maxScratchRegs_ = std::max( - static_cast(aKernel->workGroupInfo()->scratchRegs_), - maxScratchRegs_); + // Find max scratch regs used in the program. It's used for scratch buffer preallocation + // with dynamic parallelism, since runtime doesn't know which child kernel will be called + maxScratchRegs_ = std::max(static_cast(aKernel->workGroupInfo()->scratchRegs_), maxScratchRegs_); } - // Allocate kernel table for device enqueuing if (dynamicParallelism && !allocKernelTable()) { return false; } - - // Save the binary in the interface class - size_t size = 0; - void *mem = NULL; - aclWriteToMem(binaryElf_, &mem, &size); - setBinary(static_cast(mem), size); - buildLog_ += aclGetCompilerLog(dev().hsaCompiler()); - return true; } - return false; + // Save the binary in the interface class + size_t size = 0; + void *mem = NULL; + aclWriteToMem(binaryElf_, &mem, &size); + setBinary(static_cast(mem), size); + buildLog_ += aclGetCompilerLog(dev().hsaCompiler()); + return true; } bool