diff --git a/projects/clr/rocclr/runtime/device/rocm/roccompiler.cpp b/projects/clr/rocclr/runtime/device/rocm/roccompiler.cpp index c9457e78d9..d2b9a8876e 100644 --- a/projects/clr/rocclr/runtime/device/rocm/roccompiler.cpp +++ b/projects/clr/rocclr/runtime/device/rocm/roccompiler.cpp @@ -35,19 +35,21 @@ extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeIn namespace roc { /* Temporary log function for the compiler library */ -static void logFunction(const char* msg, size_t size) +static void +logFunction(const char* msg, size_t size) { - std::cout<< "Compiler Log: " << msg << std::endl; + std::cout<< "Compiler Log: " << msg << std::endl; } static int programsCount = 0; #if defined(WITH_LIGHTNING_COMPILER) bool -HSAILProgram::compileImpl_LC(const std::string& sourceCode, - const std::vector& headers, - const char** headerIncludeNames, - amd::option::Options* options) +HSAILProgram::compileImpl_LC( + const std::string& sourceCode, + const std::vector& headers, + const char** headerIncludeNames, + amd::option::Options* options) { using namespace amd::opencl_driver; std::auto_ptr C(newCompilerInstance()); @@ -57,7 +59,7 @@ HSAILProgram::compileImpl_LC(const std::string& sourceCode, std::ofstream f(options->getDumpFileName(".cl").c_str(), std::ios::trunc); if(f.is_open()) { f << "/* Compiler options:\n" << options->origOptionStr - << "\n*/\n\n" << sourceCode; + << "\n*/\n\n" << sourceCode; } else { buildLog_ += "Warning: opening the file to dump the OpenCL source failed.\n"; @@ -93,7 +95,7 @@ HSAILProgram::compileImpl_LC(const std::string& sourceCode, for (std::string::iterator it = headerIncludeName.begin(), end = headerIncludeName.end(); it != end; - ++it) { + ++it) { if (*it == '/') *it = amd::Os::fileSeparator(); } } @@ -109,7 +111,7 @@ HSAILProgram::compileImpl_LC(const std::string& sourceCode, newDirs.push_back(headerPath); } std::string headerFullName - = headerPath + amd::Os::fileSeparator() + headerIncludeName; + = headerPath + amd::Os::fileSeparator() + headerIncludeName; headerFileNames[i] = headerFullName; f.open(headerFullName.c_str(), std::fstream::out); //Should we allow asserts @@ -236,10 +238,11 @@ HSAILProgram::compileImpl_LC(const std::string& sourceCode, #endif // defined(WITH_LIGHTNING_COMPILER) bool -HSAILProgram::compileImpl(const std::string& sourceCode, - const std::vector& headers, - const char** headerIncludeNames, - amd::option::Options* options) +HSAILProgram::compileImpl( + const std::string& sourceCode, + const std::vector& headers, + const char** headerIncludeNames, + amd::option::Options* options) { #if defined(WITH_LIGHTNING_COMPILER) return compileImpl_LC(sourceCode, headers, headerIncludeNames, options); @@ -279,7 +282,7 @@ HSAILProgram::compileImpl(const std::string& sourceCode, for (std::string::iterator it = headerIncludeName.begin(), end = headerIncludeName.end(); it != end; - ++it) { + ++it) { if (*it == '/') *it = amd::Os::fileSeparator(); } } @@ -295,7 +298,7 @@ HSAILProgram::compileImpl(const std::string& sourceCode, newDirs.push_back(headerPath); } std::string headerFullName - = headerPath + amd::Os::fileSeparator() + headerIncludeName; + = headerPath + amd::Os::fileSeparator() + headerIncludeName; headerFileNames[i] = headerFullName; f.open(headerFullName.c_str(), std::fstream::out); //Should we allow asserts diff --git a/projects/clr/rocclr/runtime/device/rocm/rocprogram.cpp b/projects/clr/rocclr/runtime/device/rocm/rocprogram.cpp index 70680de913..2ca5ff9ce5 100644 --- a/projects/clr/rocclr/runtime/device/rocm/rocprogram.cpp +++ b/projects/clr/rocclr/runtime/device/rocm/rocprogram.cpp @@ -44,1017 +44,1337 @@ #include #include -#endif // WITHOUT_HSA_BACKEND - namespace roc { -#ifndef WITHOUT_HSA_BACKEND #if defined(WITH_LIGHTNING_COMPILER) - static hsa_status_t GetKernelNamesCallback( - hsa_executable_t exec, - hsa_executable_symbol_t symbol, - void *data ) { - std::vector* symNameList = (reinterpret_cast *>(data)); +static hsa_status_t +GetKernelNamesCallback( + hsa_executable_t exec, + hsa_executable_symbol_t symbol, + void *data) +{ + std::vector* symNameList = reinterpret_cast*>(data); - hsa_symbol_kind_t sym_type; - hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_TYPE, &sym_type); + hsa_symbol_kind_t sym_type; + hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_TYPE, &sym_type); - if (sym_type == HSA_SYMBOL_KIND_KERNEL) { - uint32_t len; - hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_NAME_LENGTH, &len); + if (sym_type == HSA_SYMBOL_KIND_KERNEL) { + uint32_t len; + hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_NAME_LENGTH, &len); - char* symName = (char*) alloca(len); - hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_NAME, symName); + char* symName = (char*) alloca(len); + hsa_executable_symbol_get_info(symbol, HSA_EXECUTABLE_SYMBOL_INFO_NAME, symName); - std::string kernelName(symName); - symNameList->push_back(kernelName); - } - - return HSA_STATUS_SUCCESS; + std::string kernelName(symName); + symNameList->push_back(kernelName); } + + return HSA_STATUS_SUCCESS; +} #endif // defined(WITH_LIGHTNING_COMPILER) - /* Temporary log function for the compiler library */ - static void logFunction(const char *msg, size_t size) { - std::cout << "Compiler Library log :" << msg << std::endl; - } +/* Temporary log function for the compiler library */ +static void +logFunction(const char *msg, size_t size) +{ + std::cout << "Compiler Library log :" << msg << std::endl; +} - HSAILProgram::~HSAILProgram() { +HSAILProgram::~HSAILProgram() +{ #if !defined(WITH_LIGHTNING_COMPILER) - acl_error error; - // Free the elf binary - if (binaryElf_ != NULL) { - error = g_complibApi._aclBinaryFini(binaryElf_); - if (error != ACL_SUCCESS) { - LogWarning( "Error while destroying the acl binary \n" ); - } + acl_error error; + // Free the elf binary + if (binaryElf_ != NULL) { + error = g_complibApi._aclBinaryFini(binaryElf_); + if (error != ACL_SUCCESS) { + LogWarning( "Error while destroying the acl binary \n" ); } + } #endif // !defined(WITH_LIGHTNING_COMPILER) - // Destroy the executable. - if (hsaExecutable_.handle != 0) { - hsa_executable_destroy(hsaExecutable_); - } - // Destroy the code object. - if (hsaProgramCodeObject_.handle != 0) { - hsa_code_object_destroy(hsaProgramCodeObject_); - } - // Destroy the program handle. - if (hsaProgramHandle_.handle != 0) { - hsa_ext_program_destroy(hsaProgramHandle_); - } - destroyBrigModule(); - destroyBrigContainer(); - releaseClBinary(); + // Destroy the executable. + if (hsaExecutable_.handle != 0) { + hsa_executable_destroy(hsaExecutable_); + } + // Destroy the code object. + if (hsaProgramCodeObject_.handle != 0) { + hsa_code_object_destroy(hsaProgramCodeObject_); + } + // Destroy the program handle. + if (hsaProgramHandle_.handle != 0) { + hsa_ext_program_destroy(hsaProgramHandle_); + } + destroyBrigModule(); + destroyBrigContainer(); + releaseClBinary(); #if defined(WITH_LIGHTNING_COMPILER) - delete metadata_; + delete metadata_; #endif // defined(WITH_LIGHTNING_COMPILER) - } +} - HSAILProgram::HSAILProgram(roc::NullDevice& device) - : Program(device), - binaryElf_(NULL), - brigModule_(NULL), - hsaBrigContainer_(NULL) - { - memset(&binOpts_, 0, sizeof(binOpts_)); - binOpts_.struct_size = sizeof(binOpts_); - //binOpts_.elfclass = LP64_SWITCH( ELFCLASS32, ELFCLASS64 ); - //Setting as 32 bit because hsail64 returns an invalid aclTargetInfo - //when aclGetTargetInfo is called - EPR# 377910 - binOpts_.elfclass = ELFCLASS32; - binOpts_.bitness = ELFDATA2LSB; - binOpts_.alloc = &::malloc; - binOpts_.dealloc = &::free; +HSAILProgram::HSAILProgram(roc::NullDevice& device) + : Program(device), + binaryElf_(NULL), + brigModule_(NULL), + hsaBrigContainer_(NULL) +{ + memset(&binOpts_, 0, sizeof(binOpts_)); + binOpts_.struct_size = sizeof(binOpts_); + //binOpts_.elfclass = LP64_SWITCH( ELFCLASS32, ELFCLASS64 ); + //Setting as 32 bit because hsail64 returns an invalid aclTargetInfo + //when aclGetTargetInfo is called - EPR# 377910 + binOpts_.elfclass = ELFCLASS32; + binOpts_.bitness = ELFDATA2LSB; + binOpts_.alloc = &::malloc; + binOpts_.dealloc = &::free; - hsaProgramHandle_.handle = 0; - hsaProgramCodeObject_.handle = 0; - hsaExecutable_.handle = 0; + hsaProgramHandle_.handle = 0; + hsaProgramCodeObject_.handle = 0; + hsaExecutable_.handle = 0; #if defined(WITH_LIGHTNING_COMPILER) - metadata_ = NULL; + metadata_ = NULL; #endif // defined(WITH_LIGHTNING_COMPILER) +} + +bool +HSAILProgram::initClBinary(char *binaryIn, size_t size) +{ + // Save the original binary that isn't owned by ClBinary + clBinary()->saveOrigBinary(binaryIn, size); + + char *bin = binaryIn; + size_t sz = size; + + int encryptCode; + + char *decryptedBin; + size_t decryptedSize; + if (!clBinary()->decryptElf(binaryIn, size, + &decryptedBin, &decryptedSize, &encryptCode)) { + return false; + } + if (decryptedBin != NULL) { + // It is decrypted binary. + bin = decryptedBin; + sz = decryptedSize; } - bool HSAILProgram::initClBinary(char *binaryIn, size_t size) { // Save the - // original - // binary that - // isn't owned - // by ClBinary - clBinary()->saveOrigBinary(binaryIn, size); - - char *bin = binaryIn; - size_t sz = size; - - int encryptCode; - - char *decryptedBin; - size_t decryptedSize; - if (!clBinary()->decryptElf(binaryIn, size, - &decryptedBin, &decryptedSize, &encryptCode)) { - return false; - } + // Both 32-bit and 64-bit are allowed! + if (!amd::isElfMagic(bin)) { + // Invalid binary. if (decryptedBin != NULL) { - // It is decrypted binary. - bin = decryptedBin; - sz = decryptedSize; + delete[]decryptedBin; } - - // Both 32-bit and 64-bit are allowed! - if (!amd::isElfMagic(bin)) { - // Invalid binary. - if (decryptedBin != NULL) { - delete[]decryptedBin; - } - return false; - } - - clBinary()->setFlags(encryptCode); - - return clBinary()->setBinary(bin, sz, (decryptedBin != NULL)); + return false; } + clBinary()->setFlags(encryptCode); - bool HSAILProgram::initBuild(amd::option::Options *options) { - compileOptions_ = options->origOptionStr; + return clBinary()->setBinary(bin, sz, (decryptedBin != NULL)); +} - if (!device::Program::initBuild(options)) { - return false; - } - const char* devName = dev().deviceInfo().machineTarget_; - options->setPerBuildInfo( - (devName && (devName[0] != '\0')) ? devName : "gpu", +bool +HSAILProgram::initBuild(amd::option::Options *options) +{ + compileOptions_ = options->origOptionStr; + + if (!device::Program::initBuild(options)) { + return false; + } + + const char* devName = dev().deviceInfo().machineTarget_; + options->setPerBuildInfo( + (devName && (devName[0] != '\0')) ? devName : "gpu", clBinary()->getEncryptCode(), true); - // Elf Binary setup - std::string outFileName; + // Elf Binary setup + std::string outFileName; - // true means hsail required - clBinary()->init(options, true); - if (options->isDumpFlagSet(amd::option::DUMP_BIF)) { - outFileName = options->getDumpFileName(".bin"); - } - -#if defined(WITH_LIGHTNING_COMPILER) - bool useELF64 = true; -#else // !defined(WITH_LIGHTNING_COMPILER) - bool useELF64 = getCompilerOptions()->oVariables->EnableGpuElf64; -#endif // !defined(WITH_LIGHTNING_COMPILER) - if (!clBinary()->setElfOut(useELF64 ? ELFCLASS64 : ELFCLASS32, - (outFileName.size() > - 0) ? outFileName.c_str() : NULL)) { - LogError("Setup elf out for gpu failed"); - return false; - } - return true; + // true means hsail required + clBinary()->init(options, true); + if (options->isDumpFlagSet(amd::option::DUMP_BIF)) { + outFileName = options->getDumpFileName(".bin"); } - // ! post-compile setup for GPU - bool HSAILProgram::finiBuild(bool isBuildGood) { - clBinary()->resetElfOut(); - clBinary()->resetElfIn(); +#if defined(WITH_LIGHTNING_COMPILER) + bool useELF64 = true; +#else // !defined(WITH_LIGHTNING_COMPILER) + bool useELF64 = getCompilerOptions()->oVariables->EnableGpuElf64; +#endif // !defined(WITH_LIGHTNING_COMPILER) + if (!clBinary()->setElfOut(useELF64 ? ELFCLASS64 : ELFCLASS32, + (outFileName.size() > + 0) ? outFileName.c_str() : NULL)) { + LogError("Setup elf out for gpu failed"); + return false; + } + return true; +} - if (!isBuildGood) { - // Prevent the encrypted binary form leaking out - clBinary()->setBinary(NULL, 0); - - } +// ! post-compile setup for GPU +bool +HSAILProgram::finiBuild(bool isBuildGood) +{ + clBinary()->resetElfOut(); + clBinary()->resetElfIn(); + + if (!isBuildGood) { + // Prevent the encrypted binary form leaking out + clBinary()->setBinary(NULL, 0); - return device::Program::finiBuild(isBuildGood); } - aclType HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStages, bool& needOptionsCheck) - { - acl_error errorCode; - size_t secSize = 0; - completeStages.clear(); - aclType from = ACL_TYPE_DEFAULT; - needOptionsCheck = true; - size_t boolSize = sizeof(bool); - //! @todo Should we also check for ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT? - // Checking llvmir in .llvmir section - bool containsLlvmirText = true; + return device::Program::finiBuild(isBuildGood); +} + +aclType +HSAILProgram::getCompilationStagesFromBinary(std::vector& completeStages, bool& needOptionsCheck) +{ + acl_error errorCode; + size_t secSize = 0; + completeStages.clear(); + aclType from = ACL_TYPE_DEFAULT; + needOptionsCheck = true; + size_t boolSize = sizeof(bool); + //! @todo Should we also check for ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT? + // Checking llvmir in .llvmir section + bool containsLlvmirText = true; #if defined(WITH_LIGHTNING_COMPILER) - // TODO:FIXME_Wilkin - Query - bool containsOpts = false; - bool containsHsailText = false; - bool containsBrig = false; + // TODO:FIXME_Wilkin - Query + bool containsOpts = false; + bool containsHsailText = false; + bool containsBrig = false; #else // !defined(WITH_LIGHTNING_COMPILER) - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_LLVMIR, NULL, &containsLlvmirText, &boolSize); - if (errorCode != ACL_SUCCESS) { - containsLlvmirText = false; - } - // Checking compile & link options in .comment section - bool containsOpts = true; - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_OPTIONS, NULL, &containsOpts, &boolSize); - if (errorCode != ACL_SUCCESS) { - containsOpts = false; - } - if (containsLlvmirText && containsOpts) { - completeStages.push_back(from); - from = ACL_TYPE_LLVMIR_BINARY; - } - // Checking HSAIL in .cg section - bool containsHsailText = true; - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_HSAIL, NULL, &containsHsailText, &boolSize); - if (errorCode != ACL_SUCCESS) { - containsHsailText = false; - } - // Checking BRIG sections - bool containsBrig = true; - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_BRIG, NULL, &containsBrig, &boolSize); - if (errorCode != ACL_SUCCESS) { - containsBrig = false; - } + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_LLVMIR, NULL, &containsLlvmirText, &boolSize); + if (errorCode != ACL_SUCCESS) { + containsLlvmirText = false; + } + // Checking compile & link options in .comment section + bool containsOpts = true; + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_OPTIONS, NULL, &containsOpts, &boolSize); + if (errorCode != ACL_SUCCESS) { + containsOpts = false; + } + if (containsLlvmirText && containsOpts) { + completeStages.push_back(from); + from = ACL_TYPE_LLVMIR_BINARY; + } + // Checking HSAIL in .cg section + bool containsHsailText = true; + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_HSAIL, NULL, &containsHsailText, &boolSize); + if (errorCode != ACL_SUCCESS) { + containsHsailText = false; + } + // Checking BRIG sections + bool containsBrig = true; + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_BRIG, NULL, &containsBrig, &boolSize); + if (errorCode != ACL_SUCCESS) { + containsBrig = false; + } #endif // !defined(WITH_LIGHTNING_COMPILER) - if (containsBrig) { + if (containsBrig) { + completeStages.push_back(from); + from = ACL_TYPE_HSAIL_BINARY; + // Here we should check that CG stage was done. + // Right now there are 2 criterions to check it (besides BRIG itself): + // 1. matadata symbols symOpenclKernel for every kernel. + // 2. HSAIL text in aclCODEGEN section. + // Unfortunately there is no appropriate way in Compiler Lib to check 1. + // because kernel names are unknown here, therefore only 2. + if (containsHsailText) { completeStages.push_back(from); - from = ACL_TYPE_HSAIL_BINARY; - // Here we should check that CG stage was done. - // Right now there are 2 criterions to check it (besides BRIG itself): - // 1. matadata symbols symOpenclKernel for every kernel. - // 2. HSAIL text in aclCODEGEN section. - // Unfortunately there is no appropriate way in Compiler Lib to check 1. - // because kernel names are unknown here, therefore only 2. - if (containsHsailText) { - completeStages.push_back(from); - from = ACL_TYPE_CG; - } + from = ACL_TYPE_CG; } - else if (containsHsailText) { - completeStages.push_back(from); - from = ACL_TYPE_HSAIL_TEXT; - } - // Checking ISA in .text section - bool containsShaderIsa = true; + } + else if (containsHsailText) { + completeStages.push_back(from); + from = ACL_TYPE_HSAIL_TEXT; + } + // Checking ISA in .text section + bool containsShaderIsa = true; #if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_Wilkin"); - errorCode = ACL_ERROR; + assert(!"FIXME_Wilkin"); + errorCode = ACL_ERROR; #else // !defined(WITH_LIGHTNING_COMPILER) - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_ISA, NULL, &containsShaderIsa, &boolSize); + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_CONTAINS_ISA, NULL, &containsShaderIsa, &boolSize); #endif // !defined(WITH_LIGHTNING_COMPILER) - if (errorCode != ACL_SUCCESS) { - containsShaderIsa = false; - } - if (containsShaderIsa) { - completeStages.push_back(from); - from = ACL_TYPE_ISA; - } - std::string sCurOptions = compileOptions_ + linkOptions_; - amd::option::Options curOptions; - if (!amd::option::parseAllOptions(sCurOptions, curOptions)) { - buildLog_ += curOptions.optionsLog(); - LogError("Parsing compile options failed."); - return ACL_TYPE_DEFAULT; - } - switch (from) { - // compile from HSAIL text, no matter prev. stages and options - case ACL_TYPE_HSAIL_TEXT: + if (errorCode != ACL_SUCCESS) { + containsShaderIsa = false; + } + if (containsShaderIsa) { + completeStages.push_back(from); + from = ACL_TYPE_ISA; + } + std::string sCurOptions = compileOptions_ + linkOptions_; + amd::option::Options curOptions; + if (!amd::option::parseAllOptions(sCurOptions, curOptions)) { + buildLog_ += curOptions.optionsLog(); + LogError("Parsing compile options failed."); + return ACL_TYPE_DEFAULT; + } + switch (from) { + // compile from HSAIL text, no matter prev. stages and options + case ACL_TYPE_HSAIL_TEXT: + needOptionsCheck = false; + break; + case ACL_TYPE_HSAIL_BINARY: + case ACL_TYPE_CG: + // do not check options, if LLVMIR is absent or might be absent or options are absent + if (curOptions.oVariables->BinLLVMIR || !containsLlvmirText || !containsOpts) { needOptionsCheck = false; - break; + } + break; + case ACL_TYPE_ISA: + // do not check options, if LLVMIR is absent or might be absent or options are absent + if (curOptions.oVariables->BinLLVMIR || !containsLlvmirText || !containsOpts) { + needOptionsCheck = false; + } + if (containsBrig && containsHsailText && curOptions.oVariables->BinHSAIL) { + needOptionsCheck = false; + // recompile from prev. stage, if BRIG || HSAIL are absent + } else { + from = completeStages.back(); + completeStages.pop_back(); + needOptionsCheck = true; + } + break; + // recompilation might be needed + case ACL_TYPE_LLVMIR_BINARY: + case ACL_TYPE_DEFAULT: + default: + break; + } + return from; +} + +aclType +HSAILProgram::getNextCompilationStageFromBinary(amd::option::Options* options) +{ + aclType continueCompileFrom = ACL_TYPE_DEFAULT; + binary_t binary = this->binary(); + // If the binary already exists + if ((binary.first != NULL) && (binary.second > 0)) { + void *mem = const_cast(binary.first); + acl_error errorCode; +#if defined(WITH_LIGHTNING_COMPILER) + assert(!"FIXME_lmoriche: deserialize the code object, extract the metadata"); +#else // !defined(WITH_LIGHTNING_COMPILER) + binaryElf_ = g_complibApi._aclReadFromMem(mem, binary.second, &errorCode); + if (errorCode != ACL_SUCCESS) { + buildLog_ += "Error while BRIG Codegen phase: aclReadFromMem failure \n" ; + return continueCompileFrom; + } +#endif // !defined(WITH_LIGHTNING_COMPILER) + // Calculate the next stage to compile from, based on sections in binaryElf_; + // No any validity checks here + std::vector completeStages; + bool needOptionsCheck = true; + continueCompileFrom = getCompilationStagesFromBinary(completeStages, needOptionsCheck); + // Saving binary in the interface class, + // which also load compile & link options from binary + setBinary(static_cast(mem), binary.second); + if (!options || !needOptionsCheck) { + return continueCompileFrom; + } + bool recompile = false; + //! @todo Should we also check for ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT? + switch (continueCompileFrom) { case ACL_TYPE_HSAIL_BINARY: case ACL_TYPE_CG: - // do not check options, if LLVMIR is absent or might be absent or options are absent - if (curOptions.oVariables->BinLLVMIR || !containsLlvmirText || !containsOpts) { - needOptionsCheck = false; + case ACL_TYPE_ISA: { + // Compare options loaded from binary with current ones, recompile if differ; + // If compile options are absent in binary, do not compare and recompile + if (compileOptions_.empty()) + break; + const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symOpenclCompilerOptions); + assert(symbol && "symbol not found"); + std::string symName = std::string(symbol->str[bif::PRE]) + std::string(symbol->str[bif::POST]); + size_t symSize = 0; +#if defined(WITH_LIGHTNING_COMPILER) + assert(!"FIXME_Wilkin"); + const void *opts = NULL; +#else // !defined(WITH_LIGHTNING_COMPILER) + const void *opts = g_complibApi._aclExtractSymbol(device().compiler(), + binaryElf_, &symSize, aclCOMMENT, symName.c_str(), &errorCode); + if (errorCode != ACL_SUCCESS) { + recompile = true; + break; + } +#endif // !defined(WITH_LIGHTNING_COMPILER) + std::string sBinOptions = std::string((char*)opts, symSize); + std::string sCurOptions = compileOptions_ + linkOptions_; + amd::option::Options curOptions, binOptions; + if (!amd::option::parseAllOptions(sBinOptions, binOptions)) { + buildLog_ += binOptions.optionsLog(); + LogError("Parsing compile options from binary failed."); + return ACL_TYPE_DEFAULT; + } + if (!amd::option::parseAllOptions(sCurOptions, curOptions)) { + buildLog_ += curOptions.optionsLog(); + LogError("Parsing compile options failed."); + return ACL_TYPE_DEFAULT; + } + if (!curOptions.equals(binOptions)) { + recompile = true; } break; - case ACL_TYPE_ISA: - // do not check options, if LLVMIR is absent or might be absent or options are absent - if (curOptions.oVariables->BinLLVMIR || !containsLlvmirText || !containsOpts) { - needOptionsCheck = false; - } - if (containsBrig && containsHsailText && curOptions.oVariables->BinHSAIL) { - needOptionsCheck = false; - // recompile from prev. stage, if BRIG || HSAIL are absent - } else { - from = completeStages.back(); - completeStages.pop_back(); - needOptionsCheck = true; - } - break; - // recompilation might be needed - case ACL_TYPE_LLVMIR_BINARY: - case ACL_TYPE_DEFAULT: + } default: break; } - return from; + if (recompile) { + while (!completeStages.empty()) { + continueCompileFrom = completeStages.back(); + if (continueCompileFrom == ACL_TYPE_LLVMIR_BINARY || + continueCompileFrom == ACL_TYPE_DEFAULT) { + break; + } + completeStages.pop_back(); + } + } + } + return continueCompileFrom; +} + +static hsa_status_t +allocFunc(size_t size, hsa_callback_data_t data, void **address) +{ + if (!address || 0 == size) { + return HSA_STATUS_ERROR_INVALID_ARGUMENT; } - aclType HSAILProgram::getNextCompilationStageFromBinary(amd::option::Options* options) { - aclType continueCompileFrom = ACL_TYPE_DEFAULT; - binary_t binary = this->binary(); - // If the binary already exists - if ((binary.first != NULL) && (binary.second > 0)) { - void *mem = const_cast(binary.first); - acl_error errorCode; -#if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_lmoriche: deserialize the code object, extract the metadata"); -#else // !defined(WITH_LIGHTNING_COMPILER) - binaryElf_ = g_complibApi._aclReadFromMem(mem, binary.second, &errorCode); - if (errorCode != ACL_SUCCESS) { - buildLog_ += "Error while BRIG Codegen phase: aclReadFromMem failure \n" ; - return continueCompileFrom; - } -#endif // !defined(WITH_LIGHTNING_COMPILER) - // Calculate the next stage to compile from, based on sections in binaryElf_; - // No any validity checks here - std::vector completeStages; - bool needOptionsCheck = true; - continueCompileFrom = getCompilationStagesFromBinary(completeStages, needOptionsCheck); - // Saving binary in the interface class, - // which also load compile & link options from binary - setBinary(static_cast(mem), binary.second); - if (!options || !needOptionsCheck) { - return continueCompileFrom; - } - bool recompile = false; - //! @todo Should we also check for ACL_TYPE_OPENCL & ACL_TYPE_LLVMIR_TEXT? - switch (continueCompileFrom) { - case ACL_TYPE_HSAIL_BINARY: - case ACL_TYPE_CG: - case ACL_TYPE_ISA: { - // Compare options loaded from binary with current ones, recompile if differ; - // If compile options are absent in binary, do not compare and recompile - if (compileOptions_.empty()) - break; - const oclBIFSymbolStruct* symbol = findBIF30SymStruct(symOpenclCompilerOptions); - assert(symbol && "symbol not found"); - std::string symName = std::string(symbol->str[bif::PRE]) + std::string(symbol->str[bif::POST]); - size_t symSize = 0; -#if defined(WITH_LIGHTNING_COMPILER) - assert(!"FIXME_Wilkin"); - const void *opts = NULL; -#else // !defined(WITH_LIGHTNING_COMPILER) - const void *opts = g_complibApi._aclExtractSymbol(device().compiler(), - binaryElf_, &symSize, aclCOMMENT, symName.c_str(), &errorCode); - if (errorCode != ACL_SUCCESS) { - recompile = true; - break; - } -#endif // !defined(WITH_LIGHTNING_COMPILER) - std::string sBinOptions = std::string((char*)opts, symSize); - std::string sCurOptions = compileOptions_ + linkOptions_; - amd::option::Options curOptions, binOptions; - if (!amd::option::parseAllOptions(sBinOptions, binOptions)) { - buildLog_ += binOptions.optionsLog(); - LogError("Parsing compile options from binary failed."); - return ACL_TYPE_DEFAULT; - } - if (!amd::option::parseAllOptions(sCurOptions, curOptions)) { - buildLog_ += curOptions.optionsLog(); - LogError("Parsing compile options failed."); - return ACL_TYPE_DEFAULT; - } - if (!curOptions.equals(binOptions)) { - recompile = true; - } - break; - } - default: - break; - } - if (recompile) { - while (!completeStages.empty()) { - continueCompileFrom = completeStages.back(); - if (continueCompileFrom == ACL_TYPE_LLVMIR_BINARY || - continueCompileFrom == ACL_TYPE_DEFAULT) { - break; - } - completeStages.pop_back(); - } - } - } - return continueCompileFrom; + *address = (char*) malloc(size); + if (!*address) { + return HSA_STATUS_ERROR_OUT_OF_RESOURCES; } - static hsa_status_t - allocFunc(size_t size, hsa_callback_data_t data, void **address) { - if (!address || 0 == size) { - return HSA_STATUS_ERROR_INVALID_ARGUMENT; - } + return HSA_STATUS_SUCCESS; +} - *address = (char*) malloc(size); - if (!*address) { - return HSA_STATUS_ERROR_OUT_OF_RESOURCES; - } - - return HSA_STATUS_SUCCESS; - } - - bool HSAILProgram::saveBinaryAndSetType(type_t type) { - //Write binary to memory - void *rawBinary = NULL; - size_t size = 0; +bool +HSAILProgram::saveBinaryAndSetType(type_t type) +{ + //Write binary to memory + void *rawBinary = NULL; + size_t size = 0; #if defined(WITH_LIGHTNING_COMPILER) - hsa_callback_data_t allocData = {0}; - if (hsa_code_object_serialize(hsaProgramCodeObject_, - allocFunc, allocData, - NULL, &rawBinary, &size) != HSA_STATUS_SUCCESS) { - buildLog_ += "Failed to write binary to memory \n"; - return false; - } + hsa_callback_data_t allocData = {0}; + if (hsa_code_object_serialize(hsaProgramCodeObject_, + allocFunc, allocData, + NULL, &rawBinary, &size) != HSA_STATUS_SUCCESS) { + buildLog_ += "Failed to write binary to memory \n"; + return false; + } #else // !defined(WITH_LIGHTNING_COMPILER) - if (g_complibApi._aclWriteToMem(binaryElf_, &rawBinary, &size) - != ACL_SUCCESS) { - buildLog_ += "Failed to write binary to memory \n"; - return false; - } + if (g_complibApi._aclWriteToMem(binaryElf_, &rawBinary, &size) + != ACL_SUCCESS) { + buildLog_ += "Failed to write binary to memory \n"; + return false; + } #endif // !defined(WITH_LIGHTNING_COMPILER) - clBinary()->saveBIFBinary((char*)rawBinary, size); - //Set the type of binary - setType(type); - //Free memory containing rawBinary + clBinary()->saveBIFBinary((char*)rawBinary, size); + //Set the type of binary + setType(type); + //Free memory containing rawBinary #if !defined(WITH_LIGHTNING_COMPILER) - binaryElf_->binOpts.dealloc(rawBinary); + binaryElf_->binOpts.dealloc(rawBinary); #else // defined(WITH_LIGHTNING_COMPILER) - free(rawBinary); + free(rawBinary); #endif // defined(WITH_LIGHTNING_COMPILER) + return true; +} + +#if defined(WITH_LIGHTNING_COMPILER) +bool +HSAILProgram::linkImpl_LC( + const std::vector &inputPrograms, + amd::option::Options *options, + bool createLibrary) +{ + using namespace amd::opencl_driver; + std::auto_ptr C(newCompilerInstance()); + + std::vector inputs; + for (auto program : (const std::vector&)inputPrograms) { + if (program->llvmBinary_.empty()) { + if (program->clBinary() == NULL) { + buildLog_ += "Internal error: Input program not compiled!\n"; + return false; + } + + // We are using CL binary directly. + // Setup elfIn() and try to load llvmIR from binary + // This elfIn() will be released at the end of build by finiBuild(). + if (!program->clBinary()->setElfIn(ELFCLASS64)) { + buildLog_ += "Internal error: Setting input OCL binary failed!\n"; + return false; + } + if (!program->clBinary()->loadLlvmBinary(program->llvmBinary_, + program->elfSectionType_)) { + buildLog_ += "Internal error: Failed loading compiled binary!\n"; + return false; + } + } + + if (program->elfSectionType_ != amd::OclElf::LLVMIR) { + buildLog_ += "Error: Input binary format is not supported\n."; + return false; + } + + Data* input = C->NewBufferReference(DT_LLVM_BC, + (const char*) program->llvmBinary_.data(), + program->llvmBinary_.size()); + + if (!input) { + buildLog_ += "Internal error: Failed to open the compiled programs.\n"; + return false; + } + + inputs.push_back(input); + } + + // open the linked output + Buffer* output = C->NewBuffer(DT_LLVM_BC); + + if (!output) { + buildLog_ += "Error: Failed to open the linked program.\n"; + return false; + } + + std::vector linkOptions; + bool ret = C->LinkLLVMBitcode(inputs, output, linkOptions); + buildLog_ += C->Output(); + if (!ret) { + buildLog_ += "Error: Linking bitcode failed: linking source & IR libraries.\n"; + return false; + } + + llvmBinary_.assign(output->Buf().data(), output->Size()); + elfSectionType_ = amd::OclElf::LLVMIR; + + if (clBinary()->saveLLVMIR()) { + clBinary()->elfOut()->addSection( + amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false); + // store the original link options + clBinary()->storeLinkOptions(linkOptions_); + // store the original compile options + clBinary()->storeCompileOptions(compileOptions_); + } + + // skip the rest if we are building an opencl library + if (createLibrary) { + setType(TYPE_LIBRARY); + if (!createBinary(options)) { + buildLog_ += "Internal error: creating OpenCL binary failed\n"; + return false; + } return true; } -#if defined(WITH_LIGHTNING_COMPILER) - bool HSAILProgram::linkImpl_LC( - const std::vector &inputPrograms, - amd::option::Options *options, - bool createLibrary) - { - using namespace amd::opencl_driver; - std::auto_ptr C(newCompilerInstance()); - - std::vector inputs; - for (auto program : (const std::vector&)inputPrograms) { - if (program->llvmBinary_.empty()) { - if (program->clBinary() == NULL) { - buildLog_ += "Internal error: Input program not compiled!\n"; - return false; - } - - // We are using CL binary directly. - // Setup elfIn() and try to load llvmIR from binary - // This elfIn() will be released at the end of build by finiBuild(). - if (!program->clBinary()->setElfIn(ELFCLASS64)) { - buildLog_ += "Internal error: Setting input OCL binary failed!\n"; - return false; - } - if (!program->clBinary()->loadLlvmBinary(program->llvmBinary_, - program->elfSectionType_)) { - buildLog_ += "Internal error: Failed loading compiled binary!\n"; - return false; - } - } - - if (program->elfSectionType_ != amd::OclElf::LLVMIR) { - buildLog_ += "Error: Input binary format is not supported\n."; - return false; - } - - Data* input = C->NewBufferReference(DT_LLVM_BC, - (const char*) program->llvmBinary_.data(), - program->llvmBinary_.size()); - - if (!input) { - buildLog_ += "Internal error: Failed to open the compiled programs.\n"; - return false; - } - - inputs.push_back(input); - } - - // open the linked output - Buffer* output = C->NewBuffer(DT_LLVM_BC); - - if (!output) { - buildLog_ += "Error: Failed to open the linked program.\n"; - return false; - } - - std::vector linkOptions; - bool ret = C->LinkLLVMBitcode(inputs, output, linkOptions); - buildLog_ += C->Output(); - if (!ret) { - buildLog_ += "Error: Linking bitcode failed: linking source & IR libraries.\n"; - return false; - } - - llvmBinary_.assign(output->Buf().data(), output->Size()); - elfSectionType_ = amd::OclElf::LLVMIR; - - if (clBinary()->saveLLVMIR()) { - clBinary()->elfOut()->addSection( - amd::OclElf::LLVMIR, llvmBinary_.data(), llvmBinary_.size(), false); - // store the original link options - clBinary()->storeLinkOptions(linkOptions_); - // store the original compile options - clBinary()->storeCompileOptions(compileOptions_); - } - - // skip the rest if we are building an opencl library - if (createLibrary) { - setType(TYPE_LIBRARY); - if (!createBinary(options)) { - buildLog_ += "Internal error: creating OpenCL binary failed\n"; - return false; - } - return true; - } - - return linkImpl_LC(options); - } + return linkImpl_LC(options); +} #endif // defined(WITH_LIGHTNING_COMPILER) - bool HSAILProgram::linkImpl(const std::vector &inputPrograms, - amd::option::Options *options, - bool createLibrary) { +bool +HSAILProgram::linkImpl( + const std::vector &inputPrograms, + amd::option::Options *options, + bool createLibrary) +{ #if defined(WITH_LIGHTNING_COMPILER) - return linkImpl_LC(inputPrograms, options, createLibrary); + return linkImpl_LC(inputPrograms, options, createLibrary); #else // !defined(WITH_LIGHTNING_COMPILER) - std::vector::const_iterator it - = inputPrograms.begin(); - std::vector::const_iterator itEnd - = inputPrograms.end(); - acl_error errorCode; + std::vector::const_iterator it + = inputPrograms.begin(); + std::vector::const_iterator itEnd + = inputPrograms.end(); + acl_error errorCode; - // For each program we need to extract the LLVMIR and create - // aclBinary for each - std::vector binaries_to_link; + // For each program we need to extract the LLVMIR and create + // aclBinary for each + std::vector binaries_to_link; - for (size_t i = 0; it != itEnd; ++it, ++i) { - HSAILProgram *program = (HSAILProgram *)*it; - // Check if the program was created with clCreateProgramWIthBinary - binary_t binary = program->binary(); - if ((binary.first != NULL) && (binary.second > 0)) { - // Binary already exists -- we can also check if there is no - // opencl source code - // Need to check if LLVMIR exists in the binary - // If LLVMIR does not exist then is it valid - // We need to pull out all the compiled kernels - // We cannot do this at present because we need at least - // Hsail text to pull the kernels oout - void *mem = const_cast(binary.first); - binaryElf_ = g_complibApi._aclReadFromMem(mem, - binary.second, - &errorCode); + for (size_t i = 0; it != itEnd; ++it, ++i) { + HSAILProgram *program = (HSAILProgram *)*it; + // Check if the program was created with clCreateProgramWIthBinary + binary_t binary = program->binary(); + if ((binary.first != NULL) && (binary.second > 0)) { + // Binary already exists -- we can also check if there is no + // opencl source code + // Need to check if LLVMIR exists in the binary + // If LLVMIR does not exist then is it valid + // We need to pull out all the compiled kernels + // We cannot do this at present because we need at least + // Hsail text to pull the kernels oout + void *mem = const_cast(binary.first); + binaryElf_ = g_complibApi._aclReadFromMem(mem, + binary.second, + &errorCode); - if (errorCode != ACL_SUCCESS) { - LogWarning("Error while linking : Could not read from raw binary"); - return false; - } - } - // At this stage each HSAILProgram contains a valid binary_elf - // Check if LLVMIR is in the binary - size_t boolSize = sizeof(bool); - bool containsLLLVMIR = false; - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, - RT_CONTAINS_LLVMIR, NULL, &containsLLLVMIR, &boolSize); - if (errorCode != ACL_SUCCESS || !containsLLLVMIR) { - buildLog_ +="Error while linking : Invalid binary (Missing LLVMIR section)"; - return false; - } - // Create a new aclBinary for each LLVMIR and save it in a list - aclBIFVersion ver = g_complibApi._aclBinaryVersion(binaryElf_); - aclBinary *bin = g_complibApi._aclCreateFromBinary(binaryElf_, ver); - binaries_to_link.push_back(bin); - } - - // At this stage each HSAILProgram in the list has an aclBinary initialized - // and contains LLVMIR - // We can now go ahead and link them. - if (binaries_to_link.size() > 1) { - errorCode = g_complibApi._aclLink(device().compiler(), - binaries_to_link[0], - binaries_to_link.size() - 1, - &binaries_to_link[1], - ACL_TYPE_LLVMIR_BINARY, - "-create-library", - NULL); - } - else { - errorCode = g_complibApi._aclLink(device().compiler(), - binaries_to_link[0], - 0, - NULL, - ACL_TYPE_LLVMIR_BINARY, - "-create-library", - NULL); - } if (errorCode != ACL_SUCCESS) { - buildLog_ += "Failed to link programs"; + LogWarning("Error while linking : Could not read from raw binary"); return false; } - // Store the newly linked aclBinary for this program. - binaryElf_ = binaries_to_link[0]; - // Free all the other aclBinaries - for (size_t i = 1; i < binaries_to_link.size(); i++) { - g_complibApi._aclBinaryFini(binaries_to_link[i]); - } - if (createLibrary) { - saveBinaryAndSetType(TYPE_LIBRARY); - return true; - } - - // Now call linkImpl with the new options - return linkImpl(options); -#endif // !defined(WITH_LIGHTNING_COMPILER) + } + // At this stage each HSAILProgram contains a valid binary_elf + // Check if LLVMIR is in the binary + size_t boolSize = sizeof(bool); + bool containsLLLVMIR = false; + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, + RT_CONTAINS_LLVMIR, NULL, &containsLLLVMIR, &boolSize); + if (errorCode != ACL_SUCCESS || !containsLLLVMIR) { + buildLog_ +="Error while linking : Invalid binary (Missing LLVMIR section)"; + return false; + } + // Create a new aclBinary for each LLVMIR and save it in a list + aclBIFVersion ver = g_complibApi._aclBinaryVersion(binaryElf_); + aclBinary *bin = g_complibApi._aclCreateFromBinary(binaryElf_, ver); + binaries_to_link.push_back(bin); } - bool HSAILProgram::initBrigModule() { -#if defined(WITH_LIGHTNING_COMPILER) - brigModule_ = NULL; -#else // !defined(WITH_LIGHTNING_COMPILER) - const char *symbol_name = "__BRIG__"; - BrigModuleHeader* brig; - acl_error error_code; - size_t size; - const void* symbol_data = g_complibApi._aclExtractSymbol( - device().compiler(), - binaryElf_, - &size, - aclBRIG, - symbol_name, - &error_code); - if (error_code != ACL_SUCCESS) { - std::string error = "Could not find Brig in BIF: "; - error += symbol_name; - LogError(error.c_str()); - buildLog_ += error; - return false; - } - brig = (BrigModuleHeader*)malloc(size); - memcpy(brig, symbol_data, size); - brigModule_ = brig; -#endif // !defined(WITH_LIGHTNING_COMPILER) + // At this stage each HSAILProgram in the list has an aclBinary initialized + // and contains LLVMIR + // We can now go ahead and link them. + if (binaries_to_link.size() > 1) { + errorCode = g_complibApi._aclLink(device().compiler(), + binaries_to_link[0], + binaries_to_link.size() - 1, + &binaries_to_link[1], + ACL_TYPE_LLVMIR_BINARY, + "-create-library", + NULL); + } + else { + errorCode = g_complibApi._aclLink(device().compiler(), + binaries_to_link[0], + 0, + NULL, + ACL_TYPE_LLVMIR_BINARY, + "-create-library", + NULL); + } + if (errorCode != ACL_SUCCESS) { + buildLog_ += "Failed to link programs"; + return false; + } + // Store the newly linked aclBinary for this program. + binaryElf_ = binaries_to_link[0]; + // Free all the other aclBinaries + for (size_t i = 1; i < binaries_to_link.size(); i++) { + g_complibApi._aclBinaryFini(binaries_to_link[i]); + } + if (createLibrary) { + saveBinaryAndSetType(TYPE_LIBRARY); return true; } - void HSAILProgram::destroyBrigModule() { + + // Now call linkImpl with the new options + return linkImpl(options); +#endif // !defined(WITH_LIGHTNING_COMPILER) +} + +bool +HSAILProgram::initBrigModule() +{ +#if defined(WITH_LIGHTNING_COMPILER) + brigModule_ = NULL; +#else // !defined(WITH_LIGHTNING_COMPILER) + const char *symbol_name = "__BRIG__"; + BrigModuleHeader* brig; + acl_error error_code; + size_t size; + const void* symbol_data = g_complibApi._aclExtractSymbol( + device().compiler(), + binaryElf_, + &size, + aclBRIG, + symbol_name, + &error_code); + if (error_code != ACL_SUCCESS) { + std::string error = "Could not find Brig in BIF: "; + error += symbol_name; + LogError(error.c_str()); + buildLog_ += error; + return false; + } + brig = (BrigModuleHeader*)malloc(size); + memcpy(brig, symbol_data, size); + brigModule_ = brig; +#endif // !defined(WITH_LIGHTNING_COMPILER) + return true; +} +void HSAILProgram::destroyBrigModule() { if (brigModule_ != NULL) { free(brigModule_); } - } - bool HSAILProgram::initBrigContainer() { -#if defined(WITH_LIGHTNING_COMPILER) - hsaBrigContainer_ = NULL; -#else // !defined(WITH_LIGHTNING_COMPILER) - assert(brigModule_ != NULL); +} - //Create a BRIG container - hsaBrigContainer_ = new BrigContainer(brigModule_); - if (!hsaBrigContainer_) { +bool +HSAILProgram::initBrigContainer() +{ +#if defined(WITH_LIGHTNING_COMPILER) + hsaBrigContainer_ = NULL; +#else // !defined(WITH_LIGHTNING_COMPILER) + assert(brigModule_ != NULL); + + //Create a BRIG container + hsaBrigContainer_ = new BrigContainer(brigModule_); + if (!hsaBrigContainer_) { + return false; + } +#endif // !defined(WITH_LIGHTNING_COMPILER) + return true; +} + +void +HSAILProgram::destroyBrigContainer() +{ + delete (hsaBrigContainer_); +} + +static inline const char* +hsa_strerror(hsa_status_t status) +{ + const char* str = NULL; + if (hsa_status_string(status, &str) == HSA_STATUS_SUCCESS) { + return str; + } + return "Unknown error"; +} + +#if defined(WITH_LIGHTNING_COMPILER) +bool +HSAILProgram::linkImpl_LC(amd::option::Options *options) +{ + using namespace amd::opencl_driver; + std::auto_ptr C(newCompilerInstance()); + + // call LinkLLVMBitcode + std::vector inputs; + + // open the input IR source + Data* input = C->NewBufferReference( + DT_LLVM_BC, llvmBinary_.data(), llvmBinary_.size()); + + if (!input) { + buildLog_ += "Error: Failed to open the compiled program.\n"; + return false; + } + + inputs.push_back(input); //< must be the first input + + // open the bitcode libraries + Data* opencl_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) builtins_opencl_amdgcn, builtins_opencl_amdgcn_size); + Data* ocml_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) builtins_ocml_amdgcn, builtins_ocml_amdgcn_size); + Data* ockl_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) builtins_ockl_amdgcn, builtins_ockl_amdgcn_size); + Data* irif_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) builtins_irif_amdgcn, builtins_irif_amdgcn_size); + + if (!opencl_bc || !ocml_bc || !ockl_bc || !irif_bc) { + buildLog_ += "Error: Failed to open the bitcode library.\n"; + return false; + } + + inputs.push_back(opencl_bc); // depends on oclm & ockl + inputs.push_back(ockl_bc); // depends on irif + inputs.push_back(ocml_bc); // depends on irif + inputs.push_back(irif_bc); + + // open the control functions + std::pair isa_version; + switch (dev().deviceInfo().gfxipVersion_) { + case 701: + isa_version = std::make_pair( + control_isa_version_701_amdgcn, + control_isa_version_701_amdgcn_size); + break; + case 800: + isa_version = std::make_pair( + control_isa_version_800_amdgcn, + control_isa_version_800_amdgcn_size); + break; + case 801: + isa_version = std::make_pair( + control_isa_version_801_amdgcn, + control_isa_version_801_amdgcn_size); + break; + case 802: + isa_version = std::make_pair( + control_isa_version_802_amdgcn, + control_isa_version_802_amdgcn_size); + break; + case 803: + isa_version = std::make_pair( + control_isa_version_803_amdgcn, + control_isa_version_803_amdgcn_size); + break; + case 810: + isa_version = std::make_pair( + control_isa_version_810_amdgcn, + control_isa_version_810_amdgcn_size); + break; + default: + buildLog_ += "Error: Linking for this device is not supported\n"; + return false; + } + + Data* isa_version_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) isa_version.first, isa_version.second); + + if (!isa_version_bc) { + buildLog_ += "Error: Failed to open the control functions.\n"; + return false; + } + + inputs.push_back(isa_version_bc); + + auto correctly_rounded_sqrt = (options->oVariables->FP32RoundDivideSqrt) + ? std::make_pair( + control_correctly_rounded_sqrt_on_amdgcn, + control_correctly_rounded_sqrt_on_amdgcn_size) + : std::make_pair( + control_correctly_rounded_sqrt_off_amdgcn, + control_correctly_rounded_sqrt_off_amdgcn_size); + + auto daz_opt = (dev().deviceInfo().gfxipVersion_ < 900 + || options->oVariables->DenormsAreZero) + ? std::make_pair( + control_daz_opt_on_amdgcn, + control_daz_opt_on_amdgcn_size) + : std::make_pair( + control_daz_opt_off_amdgcn, + control_daz_opt_off_amdgcn_size); + + auto finite_only = (options->oVariables->FiniteMathOnly + || options->oVariables->FastRelaxedMath) + ? std::make_pair( + control_finite_only_on_amdgcn, + control_finite_only_on_amdgcn_size) + : std::make_pair( + control_finite_only_off_amdgcn, + control_finite_only_off_amdgcn_size); + + auto unsafe_math = (options->oVariables->UnsafeMathOpt + || options->oVariables->FastRelaxedMath) + ? std::make_pair( + control_unsafe_math_on_amdgcn, + control_unsafe_math_on_amdgcn_size) + : std::make_pair( + control_unsafe_math_off_amdgcn, + control_unsafe_math_off_amdgcn_size); + + Data* correctly_rounded_sqrt_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) correctly_rounded_sqrt.first, correctly_rounded_sqrt.second); + Data* daz_opt_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) daz_opt.first, daz_opt.second); + Data* finite_only_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) finite_only.first, finite_only.second); + Data* unsafe_math_bc = C->NewBufferReference(DT_LLVM_BC, + (const char*) unsafe_math.first, unsafe_math.second); + + if (!correctly_rounded_sqrt_bc || !daz_opt_bc || !finite_only_bc || !unsafe_math_bc) { + buildLog_ += "Error: Failed to open the control functions.\n"; + return false; + } + + inputs.push_back(correctly_rounded_sqrt_bc); + inputs.push_back(daz_opt_bc); + inputs.push_back(finite_only_bc); + inputs.push_back(unsafe_math_bc); + + // open the linked output + std::vector linkOptions; + Buffer* linked_bc = C->NewBuffer(DT_LLVM_BC); + + if (!linked_bc) { + buildLog_ += "Error: Failed to open the linked program.\n"; + return false; + } + + bool ret = C->LinkLLVMBitcode(inputs, linked_bc, linkOptions); + buildLog_ += C->Output(); + if (!ret) { + buildLog_ += "Error: Linking bitcode failed: linking source & IR libraries.\n"; + return false; + } + + if (options->isDumpFlagSet(amd::option::DUMP_BC_LINKED)) { + std::ofstream f(options->getDumpFileName("_linked.bc").c_str(), std::ios::trunc); + if(f.is_open()) { + f.write(linked_bc->Buf().data(), linked_bc->Size()); + } else { + buildLog_ += + "Warning: opening the file to dump the linked IR failed.\n"; + } + } + + // open the optimized output + Buffer* opt_bc = C->NewBuffer(DT_LLVM_BC); + + if (!opt_bc) { + buildLog_ += "Error: Failed to open the optimized program.\n"; + return false; + } + + std::ostringstream optLevel; + optLevel << "-O" << options->oVariables->OptLevel; + + std::vector optOptions; + optOptions.push_back(optLevel.str()); + optOptions.push_back("-strip"); + optOptions.push_back("-instcombine"); + optOptions.push_back("-always-inline"); + + ret = C->OptimizeLLVMBitcode(linked_bc, opt_bc, optOptions); + buildLog_ += C->Output(); + if (!ret) { + buildLog_ += "Error: Optimizing bitcode failed: linking source & IR libraries.\n"; + return false; + } + + if (options->isDumpFlagSet(amd::option::DUMP_BC_OPTIMIZED)) { + std::ofstream f(options->getDumpFileName("_optimized.bc").c_str(), std::ios::trunc); + if(f.is_open()) { + f.write(opt_bc->Buf().data(), opt_bc->Size()); + } else { + buildLog_ += + "Warning: opening the file to dump the optimized IR failed.\n"; + } + } + + inputs.clear(); + inputs.push_back(opt_bc); + + Buffer* out_exec = C->NewBuffer(DT_EXECUTABLE); + if (!out_exec) { + buildLog_ += "Error: Failed to create the linked executable.\n"; + return false; + } + + std::string codegenOptions(options->llvmOptions); + + // Set the machine target + codegenOptions.append(" -mcpu="); + codegenOptions.append(dev().deviceInfo().machineTarget_); + + // Set the -O# + codegenOptions.append(" ").append(optLevel.str()); + + // Tokenize the options string into a vector of strings + std::istringstream strstr(codegenOptions); + std::istream_iterator sit(strstr), end; + std::vector params(sit, end); + + ret = C->CompileAndLinkExecutable(inputs, out_exec, params); + buildLog_ += C->Output(); + if (!ret) { + buildLog_ += "Error: Creating the executable failed: Compiling LLVM IRs to exe.\n"; + return false; + } + + if (options->isDumpFlagSet(amd::option::DUMP_O)) { + std::ofstream f(options->getDumpFileName(".co").c_str(), std::ios::trunc); + if(f.is_open()) { + f.write(out_exec->Buf().data(), out_exec->Size()); + } else { + buildLog_ += + "Warning: opening the file to dump the code object failed.\n"; + } + } + + hsa_status_t status; + status = hsa_code_object_deserialize( out_exec->Buf().data(), + out_exec->Size(), + NULL, &hsaProgramCodeObject_ ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to deserialize the AMD HSA Code Object: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + status = hsa_executable_create( HSA_PROFILE_FULL, + HSA_EXECUTABLE_STATE_UNFROZEN, + NULL, &hsaExecutable_ ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Executable for AMD HSA Code Object isn't created: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + // Load the code object. + hsa_agent_t hsaDevice = dev().getBackendDevice(); + status = hsa_executable_load_code_object( hsaExecutable_, hsaDevice, + hsaProgramCodeObject_, NULL ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: AMD HSA Code Object loading failed: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + // Freeze the executable. + status = hsa_executable_freeze( hsaExecutable_, NULL ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Freezing the executable failed: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + // load the runtime metadata + amd::OclElf elf(ELFCLASS64, out_exec->Buf().data(), out_exec->Size(), NULL, ELF_C_READ); + + char* data; + size_t size; + if (!elf.getSection(amd::OclElf::RUNTIME_METADATA, &data, &size)) { + buildLog_ += "Error while access runtime metadata.\n"; + return false; + } + + metadata_ = new roc::RuntimeMD::Program::Metadata(); + if (!metadata_->ReadFrom((void *) data, size)) { + buildLog_ += "Error while parsing runtime metadata.\n"; + return false; + } + + saveBinaryAndSetType(TYPE_EXECUTABLE); + + // Get the list of kernels + std::vector kernelNameList; + status = hsa_executable_iterate_symbols( hsaExecutable_, GetKernelNamesCallback, + (void *) &kernelNameList ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get kernel names: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + for ( auto &kernelName : kernelNameList ) + { + hsa_executable_symbol_t kernelSymbol; + hsa_executable_get_symbol ( hsaExecutable_, "", kernelName.c_str(), + hsaDevice, 0, &kernelSymbol ); + + uint64_t kernelCodeHandle; + status = hsa_executable_symbol_get_info( + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, + &kernelCodeHandle); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get the kernel code: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + uint32_t workgroupGroupSegmentByteSize; + status = hsa_executable_symbol_get_info( + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_GROUP_SEGMENT_SIZE, + &workgroupGroupSegmentByteSize); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get group segment size info: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + uint32_t workitemPrivateSegmentByteSize; + status = hsa_executable_symbol_get_info( + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, + &workitemPrivateSegmentByteSize); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get private segment size info: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + uint32_t kernargSegmentByteSize; + status = hsa_executable_symbol_get_info( + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE, + &kernargSegmentByteSize); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get kernarg segment size info: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + uint32_t kernargSegmentAlignment; + status = hsa_executable_symbol_get_info( + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_ALIGNMENT, + &kernargSegmentAlignment); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get kernarg segment alignment info: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + // for OpenCL default hidden kernel arguments assuming there is no printf + size_t numHiddenKernelArgs = 3; // FIXME_Wilkin + + Kernel *aKernel = new roc::Kernel( + kernelName, + this, + kernelCodeHandle, + workgroupGroupSegmentByteSize, + workitemPrivateSegmentByteSize, + // TODO: remove the workaround + // add 24 bytes for global offsets as workaround for LC reporting + // excluded the hidden arguments + amd::alignUp(kernargSegmentByteSize, sizeof(size_t)) + numHiddenKernelArgs * sizeof(size_t), + kernargSegmentAlignment, + numHiddenKernelArgs + ); + if (!aKernel->init()) { + return false; + } + aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize); + kernels()[kernelName] = aKernel; + } + + return true; +} +#endif // defined(WITH_LIGHTNING_COMPILER) + +bool +HSAILProgram::linkImpl(amd::option::Options *options) +{ + acl_error errorCode; + aclType continueCompileFrom = ACL_TYPE_LLVMIR_BINARY; + bool finalize = true; +#if !defined(WITH_LIGHTNING_COMPILER) + // If !binaryElf_ then program must have been created using clCreateProgramWithBinary + if (!binaryElf_) +#else // defined(WITH_LIGHTNING_COMPILER) + if (llvmBinary_.empty()) +#endif // defined(WITH_LIGHTNING_COMPILER) + { + continueCompileFrom = getNextCompilationStageFromBinary(options); + } + switch (continueCompileFrom) { + // Compilation from ACL_TYPE_LLVMIR_BINARY to ACL_TYPE_CG in cases: + // 1. if the program is not created with binary; + // 2. if the program is created with binary and contains only .llvmir & .comment + // 3. if the program is created with binary, contains .llvmir, .comment, brig sections, + // but the binary's compile & link options differ from current ones (recompilation); + case ACL_TYPE_LLVMIR_BINARY: + // Compilation from ACL_TYPE_HSAIL_BINARY to ACL_TYPE_CG in cases: + // 1. if the program is created with binary and contains only brig sections + case ACL_TYPE_HSAIL_BINARY: + // Compilation from ACL_TYPE_HSAIL_TEXT to ACL_TYPE_CG in cases: + // 1. if the program is created with binary and contains only hsail text + case ACL_TYPE_HSAIL_TEXT: { +#if defined(WITH_LIGHTNING_COMPILER) + if (!linkImpl_LC(options)) { + return false; + } +#else // !defined(WITH_LIGHTNING_COMPILER) + std::string curOptions = options->origOptionStr + hsailOptions(options); + errorCode = g_complibApi._aclCompile(device().compiler(), binaryElf_, + curOptions.c_str(), continueCompileFrom, ACL_TYPE_CG, logFunction); + buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler()); + if (errorCode != ACL_SUCCESS) { + buildLog_ += "Error while BRIG Codegen phase: compilation error \n" ; return false; } #endif // !defined(WITH_LIGHTNING_COMPILER) + break; + } + case ACL_TYPE_CG: + break; + case ACL_TYPE_ISA: + finalize = false; + break; + default: + buildLog_ += "Error while BRIG Codegen phase: the binary is incomplete \n" ; + return false; + } + //Stop compilation if it is an offline device - HSA runtime does not + //support ISA compiled offline + if (!dev().isOnline()) { return true; } - void HSAILProgram::destroyBrigContainer() { - delete (hsaBrigContainer_); +#if !defined(WITH_LIGHTNING_COMPILER) + hsa_agent_t hsaDevice = dev().getBackendDevice(); + if (!initBrigModule()) { + buildLog_ += "Failed to create Brig Module"; + return false; } - static inline const char* hsa_strerror(hsa_status_t status) { - const char* str = NULL; - if (hsa_status_string(status, &str) == HSA_STATUS_SUCCESS) { - return str; - } - return "Unknown error"; + // Create a BrigContainer. + if (!initBrigContainer()) { + buildLog_ += "Failed to create Brig Container"; + return false; + } + // Create a program. + hsa_status_t status = hsa_ext_program_create( + HSA_MACHINE_MODEL_LARGE, + HSA_PROFILE_FULL, + HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, + NULL, + &hsaProgramHandle_ + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Failed to create hsail program: "; + buildLog_ += hsa_strerror(status); + return false; } -#if defined(WITH_LIGHTNING_COMPILER) - bool HSAILProgram::linkImpl_LC(amd::option::Options *options) - { - using namespace amd::opencl_driver; - std::auto_ptr C(newCompilerInstance()); + // Add module to a program. + hsa_ext_module_t programModule = + reinterpret_cast(brigModule_); + status = hsa_ext_program_add_module( + hsaProgramHandle_, programModule + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to add a module to the program: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - // call LinkLLVMBitcode - std::vector inputs; + // Obtain agent's Isa. + hsa_isa_t hsaDeviceIsa; + status = hsa_agent_get_info( + hsaDevice, HSA_AGENT_INFO_ISA, &hsaDeviceIsa + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to create hsail program: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - // open the input IR source - Data* input = C->NewBufferReference( - DT_LLVM_BC, llvmBinary_.data(), llvmBinary_.size()); + // Finalize a program. + hsa_ext_control_directives_t hsaControlDirectives; + memset(&hsaControlDirectives, 0, sizeof(hsa_ext_control_directives_t)); + status = hsa_ext_program_finalize( + hsaProgramHandle_, + hsaDeviceIsa, + 0, + hsaControlDirectives, + NULL, + HSA_CODE_OBJECT_TYPE_PROGRAM, + &hsaProgramCodeObject_ + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to finalize hsail program: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - if (!input) { - buildLog_ += "Error: Failed to open the compiled program.\n"; - return false; - } + // HLC always generates full profile + hsa_profile_t profile = HSA_PROFILE_FULL; - inputs.push_back(input); //< must be the first input + // Create an executable. + status = hsa_executable_create( + profile, + HSA_EXECUTABLE_STATE_UNFROZEN, + "", + &hsaExecutable_ + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to create executable: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - // open the bitcode libraries - Data* opencl_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) builtins_opencl_amdgcn, builtins_opencl_amdgcn_size); - Data* ocml_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) builtins_ocml_amdgcn, builtins_ocml_amdgcn_size); - Data* ockl_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) builtins_ockl_amdgcn, builtins_ockl_amdgcn_size); - Data* irif_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) builtins_irif_amdgcn, builtins_irif_amdgcn_size); + // Load the code object. + status = hsa_executable_load_code_object( + hsaExecutable_, hsaDevice, hsaProgramCodeObject_, NULL + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to load code object: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - if (!opencl_bc || !ocml_bc || !ockl_bc || !irif_bc) { - buildLog_ += "Error: Failed to open the bitcode library.\n"; - return false; - } + // Freeze the executable. + status = hsa_executable_freeze(hsaExecutable_, NULL); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to freeze executable: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } - inputs.push_back(opencl_bc); // depends on oclm & ockl - inputs.push_back(ockl_bc); // depends on irif - inputs.push_back(ocml_bc); // depends on irif - inputs.push_back(irif_bc); - - // open the control functions - std::pair isa_version; - switch (dev().deviceInfo().gfxipVersion_) { - case 701: - isa_version = std::make_pair( - control_isa_version_701_amdgcn, - control_isa_version_701_amdgcn_size); - break; - case 800: - isa_version = std::make_pair( - control_isa_version_800_amdgcn, - control_isa_version_800_amdgcn_size); - break; - case 801: - isa_version = std::make_pair( - control_isa_version_801_amdgcn, - control_isa_version_801_amdgcn_size); - break; - case 802: - isa_version = std::make_pair( - control_isa_version_802_amdgcn, - control_isa_version_802_amdgcn_size); - break; - case 803: - isa_version = std::make_pair( - control_isa_version_803_amdgcn, - control_isa_version_803_amdgcn_size); - break; - case 810: - isa_version = std::make_pair( - control_isa_version_810_amdgcn, - control_isa_version_810_amdgcn_size); - break; - default: - buildLog_ += "Error: Linking for this device is not supported\n"; - return false; - } - - Data* isa_version_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) isa_version.first, isa_version.second); - - if (!isa_version_bc) { - buildLog_ += "Error: Failed to open the control functions.\n"; - return false; - } - - inputs.push_back(isa_version_bc); - - auto correctly_rounded_sqrt = (options->oVariables->FP32RoundDivideSqrt) - ? std::make_pair( - control_correctly_rounded_sqrt_on_amdgcn, - control_correctly_rounded_sqrt_on_amdgcn_size) - : std::make_pair( - control_correctly_rounded_sqrt_off_amdgcn, - control_correctly_rounded_sqrt_off_amdgcn_size); - - auto daz_opt = (dev().deviceInfo().gfxipVersion_ < 900 - || options->oVariables->DenormsAreZero) - ? std::make_pair( - control_daz_opt_on_amdgcn, - control_daz_opt_on_amdgcn_size) - : std::make_pair( - control_daz_opt_off_amdgcn, - control_daz_opt_off_amdgcn_size); - - auto finite_only = (options->oVariables->FiniteMathOnly - || options->oVariables->FastRelaxedMath) - ? std::make_pair( - control_finite_only_on_amdgcn, - control_finite_only_on_amdgcn_size) - : std::make_pair( - control_finite_only_off_amdgcn, - control_finite_only_off_amdgcn_size); - - auto unsafe_math = (options->oVariables->UnsafeMathOpt - || options->oVariables->FastRelaxedMath) - ? std::make_pair( - control_unsafe_math_on_amdgcn, - control_unsafe_math_on_amdgcn_size) - : std::make_pair( - control_unsafe_math_off_amdgcn, - control_unsafe_math_off_amdgcn_size); - - Data* correctly_rounded_sqrt_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) correctly_rounded_sqrt.first, correctly_rounded_sqrt.second); - Data* daz_opt_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) daz_opt.first, daz_opt.second); - Data* finite_only_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) finite_only.first, finite_only.second); - Data* unsafe_math_bc = C->NewBufferReference(DT_LLVM_BC, - (const char*) unsafe_math.first, unsafe_math.second); - - if (!correctly_rounded_sqrt_bc || !daz_opt_bc || !finite_only_bc || !unsafe_math_bc) { - buildLog_ += "Error: Failed to open the control functions.\n"; - return false; - } - - inputs.push_back(correctly_rounded_sqrt_bc); - inputs.push_back(daz_opt_bc); - inputs.push_back(finite_only_bc); - inputs.push_back(unsafe_math_bc); - - // open the linked output - std::vector linkOptions; - Buffer* linked_bc = C->NewBuffer(DT_LLVM_BC); - - if (!linked_bc) { - buildLog_ += "Error: Failed to open the linked program.\n"; - return false; - } - - bool ret = C->LinkLLVMBitcode(inputs, linked_bc, linkOptions); - buildLog_ += C->Output(); - if (!ret) { - buildLog_ += "Error: Linking bitcode failed: linking source & IR libraries.\n"; - return false; - } - - if (options->isDumpFlagSet(amd::option::DUMP_BC_LINKED)) { - std::ofstream f(options->getDumpFileName("_linked.bc").c_str(), std::ios::trunc); - if(f.is_open()) { - f.write(linked_bc->Buf().data(), linked_bc->Size()); - } else { - buildLog_ += - "Warning: opening the file to dump the linked IR failed.\n"; + Code first_d = hsaBrigContainer_->code().begin(); + Code last_d = hsaBrigContainer_->code().end(); + //Iterate through the symbols using brig assembler + for (;first_d != last_d;first_d = first_d.next()) { + if (DirectiveExecutable de = first_d) { + // Disable function compilation unconditionally. + // TODO: May remove this after the finalizer supports function compilation. + if (DirectiveFunction df = first_d) { + continue; } - } - // open the optimized output - Buffer* opt_bc = C->NewBuffer(DT_LLVM_BC); - - if (!opt_bc) { - buildLog_ += "Error: Failed to open the optimized program.\n"; - return false; - } - - std::ostringstream optLevel; - optLevel << "-O" << options->oVariables->OptLevel; - - std::vector optOptions; - optOptions.push_back(optLevel.str()); - optOptions.push_back("-strip"); - optOptions.push_back("-instcombine"); - optOptions.push_back("-always-inline"); - - ret = C->OptimizeLLVMBitcode(linked_bc, opt_bc, optOptions); - buildLog_ += C->Output(); - if (!ret) { - buildLog_ += "Error: Optimizing bitcode failed: linking source & IR libraries.\n"; - return false; - } - - if (options->isDumpFlagSet(amd::option::DUMP_BC_OPTIMIZED)) { - std::ofstream f(options->getDumpFileName("_optimized.bc").c_str(), std::ios::trunc); - if(f.is_open()) { - f.write(opt_bc->Buf().data(), opt_bc->Size()); - } else { - buildLog_ += - "Warning: opening the file to dump the optimized IR failed.\n"; + std::string kernelName = (SRef)de.name(); + if (de.linkage() != BRIG_LINKAGE_PROGRAM) { + kernelName.insert(0, "am::"); } - } - - inputs.clear(); - inputs.push_back(opt_bc); - - Buffer* out_exec = C->NewBuffer(DT_EXECUTABLE); - if (!out_exec) { - buildLog_ += "Error: Failed to create the linked executable.\n"; - return false; - } - - std::string codegenOptions(options->llvmOptions); - - // Set the machine target - codegenOptions.append(" -mcpu="); - codegenOptions.append(dev().deviceInfo().machineTarget_); - - // Set the -O# - codegenOptions.append(" ").append(optLevel.str()); - - // Tokenize the options string into a vector of strings - std::istringstream strstr(codegenOptions); - std::istream_iterator sit(strstr), end; - std::vector params(sit, end); - - ret = C->CompileAndLinkExecutable(inputs, out_exec, params); - buildLog_ += C->Output(); - if (!ret) { - buildLog_ += "Error: Creating the executable failed: Compiling LLVM IRs to exe.\n"; - return false; - } - - if (options->isDumpFlagSet(amd::option::DUMP_O)) { - std::ofstream f(options->getDumpFileName(".co").c_str(), std::ios::trunc); - if(f.is_open()) { - f.write(out_exec->Buf().data(), out_exec->Size()); - } else { - buildLog_ += - "Warning: opening the file to dump the code object failed.\n"; - } - } - - hsa_status_t status; - status = hsa_code_object_deserialize( out_exec->Buf().data(), - out_exec->Size(), - NULL, &hsaProgramCodeObject_ ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to deserialize the AMD HSA Code Object: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - status = hsa_executable_create( HSA_PROFILE_FULL, - HSA_EXECUTABLE_STATE_UNFROZEN, - NULL, &hsaExecutable_ ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Executable for AMD HSA Code Object isn't created: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Load the code object. - hsa_agent_t hsaDevice = dev().getBackendDevice(); - status = hsa_executable_load_code_object( hsaExecutable_, hsaDevice, - hsaProgramCodeObject_, NULL ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: AMD HSA Code Object loading failed: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Freeze the executable. - status = hsa_executable_freeze( hsaExecutable_, NULL ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Freezing the executable failed: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // load the runtime metadata - amd::OclElf elf(ELFCLASS64, out_exec->Buf().data(), out_exec->Size(), NULL, ELF_C_READ); - - char* data; - size_t size; - if (!elf.getSection(amd::OclElf::RUNTIME_METADATA, &data, &size)) { - buildLog_ += "Error while access runtime metadata.\n"; - return false; - } - - metadata_ = new roc::RuntimeMD::Program::Metadata(); - if (!metadata_->ReadFrom((void *) data, size)) { - buildLog_ += "Error while parsing runtime metadata.\n"; - return false; - } - - saveBinaryAndSetType(TYPE_EXECUTABLE); - - // Get the list of kernels - std::vector kernelNameList; - status = hsa_executable_iterate_symbols( hsaExecutable_, GetKernelNamesCallback, - (void *) &kernelNameList ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get kernel names: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - for ( auto &kernelName : kernelNameList ) - { + // Query symbol handle for this symbol. hsa_executable_symbol_t kernelSymbol; - hsa_executable_get_symbol ( hsaExecutable_, "", kernelName.c_str(), - hsaDevice, 0, &kernelSymbol ); - - uint64_t kernelCodeHandle; - status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, - &kernelCodeHandle); + status = hsa_executable_get_symbol( + hsaExecutable_, NULL, kernelName.c_str(), hsaDevice, 0, &kernelSymbol + ); if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get the kernel code: "; + buildLog_ += "Error: Failed to get executable symbol: "; buildLog_ += hsa_strerror(status); buildLog_ += "\n"; return false; } + // Query code handle for this symbol. + uint64_t kernelCodeHandle; + status = hsa_executable_symbol_get_info( + kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &kernelCodeHandle + ); + if (status != HSA_STATUS_SUCCESS) { + buildLog_ += "Error: Failed to get executable symbol info: "; + buildLog_ += hsa_strerror(status); + buildLog_ += "\n"; + return false; + } + + std::string openclKernelName = kernelName; + // Strip the opencl and kernel name + kernelName = kernelName.substr(strlen("&__OpenCL_"), kernelName.size()); + kernelName = kernelName.substr(0,kernelName.size() - strlen("_kernel")); + aclMetadata md; + md.numHiddenKernelArgs = 0; + + size_t sizeOfnumHiddenKernelArgs = sizeof(md.numHiddenKernelArgs); + errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_NUM_KERNEL_HIDDEN_ARGS, + openclKernelName.c_str(), &md.numHiddenKernelArgs, &sizeOfnumHiddenKernelArgs); + if (errorCode != ACL_SUCCESS) { + buildLog_ += "Error while Finalization phase: Kernel extra arguments count querying from the ELF failed\n"; + return false; + } + uint32_t workgroupGroupSegmentByteSize; status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_GROUP_SEGMENT_SIZE, - &workgroupGroupSegmentByteSize); + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_GROUP_SEGMENT_SIZE, + &workgroupGroupSegmentByteSize); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: Failed to get group segment size info: "; buildLog_ += hsa_strerror(status); @@ -1064,9 +1384,9 @@ namespace roc { uint32_t workitemPrivateSegmentByteSize; status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, - &workitemPrivateSegmentByteSize); + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, + &workitemPrivateSegmentByteSize); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: Failed to get private segment size info: "; buildLog_ += hsa_strerror(status); @@ -1076,43 +1396,37 @@ namespace roc { uint32_t kernargSegmentByteSize; status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE, - &kernargSegmentByteSize); + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE, + &kernargSegmentByteSize); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: Failed to get kernarg segment size info: "; buildLog_ += hsa_strerror(status); buildLog_ += "\n"; - return false; + return false; } uint32_t kernargSegmentAlignment; status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_ALIGNMENT, - &kernargSegmentAlignment); + kernelSymbol, + HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_ALIGNMENT, + &kernargSegmentAlignment); if (status != HSA_STATUS_SUCCESS) { buildLog_ += "Error: Failed to get kernarg segment alignment info: "; buildLog_ += hsa_strerror(status); buildLog_ += "\n"; - return false; + return false; } - // for OpenCL default hidden kernel arguments assuming there is no printf - size_t numHiddenKernelArgs = 3; // FIXME_Wilkin - Kernel *aKernel = new roc::Kernel( kernelName, this, kernelCodeHandle, workgroupGroupSegmentByteSize, workitemPrivateSegmentByteSize, - // TODO: remove the workaround - // add 24 bytes for global offsets as workaround for LC reporting - // excluded the hidden arguments - amd::alignUp(kernargSegmentByteSize, sizeof(size_t)) + numHiddenKernelArgs * sizeof(size_t), + kernargSegmentByteSize, kernargSegmentAlignment, - numHiddenKernelArgs + md.numHiddenKernelArgs ); if (!aKernel->init()) { return false; @@ -1120,363 +1434,85 @@ namespace roc { aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize); kernels()[kernelName] = aKernel; } - - return true; } -#endif // defined(WITH_LIGHTNING_COMPILER) - - bool HSAILProgram::linkImpl(amd::option::Options *options) { - acl_error errorCode; - aclType continueCompileFrom = ACL_TYPE_LLVMIR_BINARY; - bool finalize = true; -#if !defined(WITH_LIGHTNING_COMPILER) - // If !binaryElf_ then program must have been created using clCreateProgramWithBinary - if (!binaryElf_) -#else // defined(WITH_LIGHTNING_COMPILER) - if (llvmBinary_.empty()) -#endif // defined(WITH_LIGHTNING_COMPILER) - { - continueCompileFrom = getNextCompilationStageFromBinary(options); - } - switch (continueCompileFrom) { - // Compilation from ACL_TYPE_LLVMIR_BINARY to ACL_TYPE_CG in cases: - // 1. if the program is not created with binary; - // 2. if the program is created with binary and contains only .llvmir & .comment - // 3. if the program is created with binary, contains .llvmir, .comment, brig sections, - // but the binary's compile & link options differ from current ones (recompilation); - case ACL_TYPE_LLVMIR_BINARY: - // Compilation from ACL_TYPE_HSAIL_BINARY to ACL_TYPE_CG in cases: - // 1. if the program is created with binary and contains only brig sections - case ACL_TYPE_HSAIL_BINARY: - // Compilation from ACL_TYPE_HSAIL_TEXT to ACL_TYPE_CG in cases: - // 1. if the program is created with binary and contains only hsail text - case ACL_TYPE_HSAIL_TEXT: { -#if defined(WITH_LIGHTNING_COMPILER) - if (!linkImpl_LC(options)) { - return false; - } -#else // !defined(WITH_LIGHTNING_COMPILER) - std::string curOptions = options->origOptionStr + hsailOptions(options); - errorCode = g_complibApi._aclCompile(device().compiler(), binaryElf_, - curOptions.c_str(), continueCompileFrom, ACL_TYPE_CG, logFunction); - buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler()); - if (errorCode != ACL_SUCCESS) { - buildLog_ += "Error while BRIG Codegen phase: compilation error \n" ; - return false; - } + saveBinaryAndSetType(TYPE_EXECUTABLE); + buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler()); #endif // !defined(WITH_LIGHTNING_COMPILER) - break; - } - case ACL_TYPE_CG: - break; - case ACL_TYPE_ISA: - finalize = false; - break; - default: - buildLog_ += "Error while BRIG Codegen phase: the binary is incomplete \n" ; - return false; - } - //Stop compilation if it is an offline device - HSA runtime does not - //support ISA compiled offline - if (!dev().isOnline()) { - return true; - } + return true; +} -#if !defined(WITH_LIGHTNING_COMPILER) - hsa_agent_t hsaDevice = dev().getBackendDevice(); - if (!initBrigModule()) { - buildLog_ += "Failed to create Brig Module"; - return false; - } - - // Create a BrigContainer. - if (!initBrigContainer()) { - buildLog_ += "Failed to create Brig Container"; - return false; - } - // Create a program. - hsa_status_t status = hsa_ext_program_create( - HSA_MACHINE_MODEL_LARGE, - HSA_PROFILE_FULL, - HSA_DEFAULT_FLOAT_ROUNDING_MODE_ZERO, - NULL, - &hsaProgramHandle_ - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Failed to create hsail program: "; - buildLog_ += hsa_strerror(status); - return false; - } - - // Add module to a program. - hsa_ext_module_t programModule = - reinterpret_cast(brigModule_); - status = hsa_ext_program_add_module( - hsaProgramHandle_, programModule - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to add a module to the program: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Obtain agent's Isa. - hsa_isa_t hsaDeviceIsa; - status = hsa_agent_get_info( - hsaDevice, HSA_AGENT_INFO_ISA, &hsaDeviceIsa - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to create hsail program: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Finalize a program. - hsa_ext_control_directives_t hsaControlDirectives; - memset(&hsaControlDirectives, 0, sizeof(hsa_ext_control_directives_t)); - status = hsa_ext_program_finalize( - hsaProgramHandle_, - hsaDeviceIsa, - 0, - hsaControlDirectives, - NULL, - HSA_CODE_OBJECT_TYPE_PROGRAM, - &hsaProgramCodeObject_ - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to finalize hsail program: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // HLC always generates full profile - hsa_profile_t profile = HSA_PROFILE_FULL; - - // Create an executable. - status = hsa_executable_create( - profile, - HSA_EXECUTABLE_STATE_UNFROZEN, - "", - &hsaExecutable_ - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to create executable: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Load the code object. - status = hsa_executable_load_code_object( - hsaExecutable_, hsaDevice, hsaProgramCodeObject_, NULL - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to load code object: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Freeze the executable. - status = hsa_executable_freeze(hsaExecutable_, NULL); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to freeze executable: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - Code first_d = hsaBrigContainer_->code().begin(); - Code last_d = hsaBrigContainer_->code().end(); - //Iterate through the symbols using brig assembler - for (;first_d != last_d;first_d = first_d.next()) { - if (DirectiveExecutable de = first_d) { - // Disable function compilation unconditionally. - // TODO: May remove this after the finalizer supports function compilation. - if (DirectiveFunction df = first_d) { - continue; - } - - std::string kernelName = (SRef)de.name(); - if (de.linkage() != BRIG_LINKAGE_PROGRAM) { - kernelName.insert(0, "am::"); - } - // Query symbol handle for this symbol. - hsa_executable_symbol_t kernelSymbol; - status = hsa_executable_get_symbol( - hsaExecutable_, NULL, kernelName.c_str(), hsaDevice, 0, &kernelSymbol - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get executable symbol: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - // Query code handle for this symbol. - uint64_t kernelCodeHandle; - status = hsa_executable_symbol_get_info( - kernelSymbol, HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_OBJECT, &kernelCodeHandle - ); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get executable symbol info: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - std::string openclKernelName = kernelName; - // Strip the opencl and kernel name - kernelName = kernelName.substr(strlen("&__OpenCL_"), kernelName.size()); - kernelName = kernelName.substr(0,kernelName.size() - strlen("_kernel")); - aclMetadata md; - md.numHiddenKernelArgs = 0; - - size_t sizeOfnumHiddenKernelArgs = sizeof(md.numHiddenKernelArgs); - errorCode = g_complibApi._aclQueryInfo(device().compiler(), binaryElf_, RT_NUM_KERNEL_HIDDEN_ARGS, - openclKernelName.c_str(), &md.numHiddenKernelArgs, &sizeOfnumHiddenKernelArgs); - if (errorCode != ACL_SUCCESS) { - buildLog_ += "Error while Finalization phase: Kernel extra arguments count querying from the ELF failed\n"; - return false; - } - - uint32_t workgroupGroupSegmentByteSize; - status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_GROUP_SEGMENT_SIZE, - &workgroupGroupSegmentByteSize); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get group segment size info: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - uint32_t workitemPrivateSegmentByteSize; - status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_PRIVATE_SEGMENT_SIZE, - &workitemPrivateSegmentByteSize); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get private segment size info: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - uint32_t kernargSegmentByteSize; - status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_SIZE, - &kernargSegmentByteSize); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get kernarg segment size info: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - uint32_t kernargSegmentAlignment; - status = hsa_executable_symbol_get_info( - kernelSymbol, - HSA_EXECUTABLE_SYMBOL_INFO_KERNEL_KERNARG_SEGMENT_ALIGNMENT, - &kernargSegmentAlignment); - if (status != HSA_STATUS_SUCCESS) { - buildLog_ += "Error: Failed to get kernarg segment alignment info: "; - buildLog_ += hsa_strerror(status); - buildLog_ += "\n"; - return false; - } - - Kernel *aKernel = new roc::Kernel( - kernelName, - this, - kernelCodeHandle, - workgroupGroupSegmentByteSize, - workitemPrivateSegmentByteSize, - kernargSegmentByteSize, - kernargSegmentAlignment, - md.numHiddenKernelArgs - ); - if (!aKernel->init()) { - return false; - } - aKernel->setUniformWorkGroupSize(options->oVariables->UniformWorkGroupSize); - kernels()[kernelName] = aKernel; - } - } - saveBinaryAndSetType(TYPE_EXECUTABLE); - buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler()); -#endif // !defined(WITH_LIGHTNING_COMPILER) - return true; - } - - bool HSAILProgram::createBinary(amd::option::Options *options) { +bool +HSAILProgram::createBinary(amd::option::Options *options) +{ #if defined(WITH_LIGHTNING_COMPILER) - if (!clBinary()->createElfBinary(options->oVariables->BinEncrypt, type())) { - LogError("Failed to create ELF binary image!"); - return false; - } - return true; -#else // !defined(WITH_LIGHTNING_COMPILER) + if (!clBinary()->createElfBinary(options->oVariables->BinEncrypt, type())) { + LogError("Failed to create ELF binary image!"); return false; + } + return true; +#else // !defined(WITH_LIGHTNING_COMPILER) + return false; #endif // !defined(WITH_LIGHTNING_COMPILER) - } +} - bool HSAILProgram::initClBinary() { +bool +HSAILProgram::initClBinary() +{ + if (clBinary_ == NULL) { + clBinary_ = new ClBinary(static_cast(device())); if (clBinary_ == NULL) { - clBinary_ = new ClBinary(static_cast(device())); - if (clBinary_ == NULL) { - return false; - } - } - return true; - } - - void HSAILProgram::releaseClBinary() { - if (clBinary_ != NULL) { - delete clBinary_; - clBinary_ = NULL; + return false; } } + return true; +} - std::string HSAILProgram::hsailOptions(amd::option::Options* options) { - std::string hsailOptions; - //Set options for the standard device specific options - //This is just for legacy compiler code - // All our devices support these options now - hsailOptions.append(" -DFP_FAST_FMAF"); - hsailOptions.append(" -DFP_FAST_FMA"); +void +HSAILProgram::releaseClBinary() +{ + if (clBinary_ != NULL) { + delete clBinary_; + clBinary_ = NULL; + } +} - if (dev().deviceInfo().gfxipVersion_ < 900) { - hsailOptions.append(" -cl-denorms-are-zero"); - } +std::string +HSAILProgram::hsailOptions(amd::option::Options* options) +{ + std::string hsailOptions; + //Set options for the standard device specific options + //This is just for legacy compiler code + // All our devices support these options now + hsailOptions.append(" -DFP_FAST_FMAF"); + hsailOptions.append(" -DFP_FAST_FMA"); - //check if the host is 64 bit or 32 bit - LP64_ONLY(hsailOptions.append(" -m64")); + if (dev().deviceInfo().gfxipVersion_ < 900) { + hsailOptions.append(" -cl-denorms-are-zero"); + } - //Now append each extension supported by the device - // one by one - std::string token; - std::istringstream iss(""); - iss.str(device().info().extensions_); - while (getline(iss, token, ' ')) { - if (!token.empty()) { + //check if the host is 64 bit or 32 bit + LP64_ONLY(hsailOptions.append(" -m64")); + + //Now append each extension supported by the device + // one by one + std::string token; + std::istringstream iss(""); + iss.str(device().info().extensions_); + while (getline(iss, token, ' ')) { + if (!token.empty()) { #if defined(WITH_LIGHTNING_COMPILER) - // FIXME_lmoriche: opencl-c.h defines 'cl_khr_depth_images', so - // remove it from the command line. Should we fix opencl-c.h? - if (options->oVariables->CLStd[2] >= '2' - && token == "cl_khr_depth_images") continue; + // FIXME_lmoriche: opencl-c.h defines 'cl_khr_depth_images', so + // remove it from the command line. Should we fix opencl-c.h? + if (options->oVariables->CLStd[2] >= '2' + && token == "cl_khr_depth_images") continue; #endif // defined(WITH_LIGHTHNING_COMPILER) - hsailOptions.append(" -D"); - hsailOptions.append(token); - } + hsailOptions.append(" -D"); + hsailOptions.append(token); } - return hsailOptions; } -#endif // WITHOUT_HSA_BACKEND + return hsailOptions; +} + } // namespace roc +#endif // WITHOUT_HSA_BACKEND diff --git a/projects/clr/rocclr/runtime/device/rocm/rocprogram.hpp b/projects/clr/rocclr/runtime/device/rocm/rocprogram.hpp index 4e76ff855e..5f28fb85e3 100644 --- a/projects/clr/rocclr/runtime/device/rocm/rocprogram.hpp +++ b/projects/clr/rocclr/runtime/device/rocm/rocprogram.hpp @@ -26,159 +26,159 @@ using namespace HSAIL_ASM; //! \namespace roc HSA Device Implementation namespace roc { - //! \class empty program - class HSAILProgram : public device::Program - { - friend class ClBinary; - public: - //! Default constructor - HSAILProgram(roc::NullDevice& device); - //! Default destructor - ~HSAILProgram(); +//! \class empty program +class HSAILProgram : public device::Program +{ + friend class ClBinary; +public: + //! Default constructor + HSAILProgram(roc::NullDevice& device); + //! Default destructor + ~HSAILProgram(); - // Initialize Binary for GPU (used only for clCreateProgramWithBinary()). - virtual bool initClBinary(char *binaryIn, size_t size); + // Initialize Binary for GPU (used only for clCreateProgramWithBinary()). + virtual bool initClBinary(char *binaryIn, size_t size); - //! Returns the aclBinary associated with the program - const aclBinary* binaryElf() const { - return static_cast(binaryElf_); - } + //! Returns the aclBinary associated with the program + const aclBinary* binaryElf() const { + return static_cast(binaryElf_); + } #if defined(WITH_LIGHTNING_COMPILER) - //! Returns the program metadata. - const RuntimeMD::Program::Metadata* metadata() const { return metadata_; } + //! Returns the program metadata. + const RuntimeMD::Program::Metadata* metadata() const { return metadata_; } #endif // defined(WITH_LIGHTNING_COMPILER) - //! Return a typecasted GPU device - const NullDevice& dev() const - { return static_cast(device()); } + //! Return a typecasted GPU device + const NullDevice& dev() const + { return static_cast(device()); } - //! Returns the hsaBinary associated with the program - hsa_agent_t hsaDevice() const { - return dev().getBackendDevice(); - } + //! Returns the hsaBinary associated with the program + hsa_agent_t hsaDevice() const { + return dev().getBackendDevice(); + } - protected: - //! pre-compile setup for GPU - virtual bool initBuild(amd::option::Options* options); +protected: + //! pre-compile setup for GPU + virtual bool initBuild(amd::option::Options* options); - //! post-compile setup for GPU - virtual bool finiBuild(bool isBuildGood); + //! post-compile setup for GPU + virtual bool finiBuild(bool isBuildGood); - /*! \brief Compiles GPU CL program to LLVM binary (compiler frontend) - * - * \return True if we successfully compiled a GPU program - */ - virtual bool compileImpl( - const std::string& sourceCode, //!< the program's source code - const std::vector& headers, - const char** headerIncludeNames, - amd::option::Options* options //!< compile options's object - ); + /*! \brief Compiles GPU CL program to LLVM binary (compiler frontend) + * + * \return True if we successfully compiled a GPU program + */ + virtual bool compileImpl( + const std::string& sourceCode, //!< the program's source code + const std::vector& headers, + const char** headerIncludeNames, + amd::option::Options* options //!< compile options's object + ); #if defined(WITH_LIGHTNING_COMPILER) - virtual bool compileImpl_LC( - const std::string& sourceCode, //!< the program's source code - const std::vector& headers, - const char** headerIncludeNames, - amd::option::Options* options //!< compile options's object - ); + virtual bool compileImpl_LC( + const std::string& sourceCode, //!< the program's source code + const std::vector& headers, + const char** headerIncludeNames, + amd::option::Options* options //!< compile options's object + ); #endif // defined(WITH_LIGHTNING_COMPILER) - /*! \brief Compiles LLVM binary to HSAIL code (compiler backend: link+opt+codegen) - * - * \return The build error code - */ - int compileBinaryToHSAIL( - amd::option::Options* options //!< options for compilation - ); + /*! \brief Compiles LLVM binary to HSAIL code (compiler backend: link+opt+codegen) + * + * \return The build error code + */ + int compileBinaryToHSAIL( + amd::option::Options* options //!< options for compilation + ); - virtual bool linkImpl(amd::option::Options* options); + virtual bool linkImpl(amd::option::Options* options); #if defined(WITH_LIGHTNING_COMPILER) - virtual bool linkImpl_LC(amd::option::Options* options); + virtual bool linkImpl_LC(amd::option::Options* options); #endif // defined(WITH_LIGHTNING_COMPILER) - //! Link the device programs. - virtual bool linkImpl (const std::vector& inputPrograms, - amd::option::Options* options, - bool createLibrary); + //! Link the device programs. + virtual bool linkImpl (const std::vector& inputPrograms, + amd::option::Options* options, + bool createLibrary); #if defined(WITH_LIGHTNING_COMPILER) - virtual bool linkImpl_LC(const std::vector& inputPrograms, - amd::option::Options* options, - bool createLibrary); + virtual bool linkImpl_LC(const std::vector& inputPrograms, + amd::option::Options* options, + bool createLibrary); #endif // defined(WITH_LIGHTNING_COMPILER) - virtual bool createBinary(amd::option::Options* options); + virtual bool createBinary(amd::option::Options* options); - //! Initialize Binary - virtual bool initClBinary(); + //! Initialize Binary + virtual bool initClBinary(); - //! Release the Binary - virtual void releaseClBinary(); + //! Release the Binary + virtual void releaseClBinary(); - virtual const aclTargetInfo & info(const char * str = ""){ - return info_; - } + virtual const aclTargetInfo & info(const char * str = ""){ + return info_; + } - virtual bool isElf(const char* bin) const { - return amd::isElfMagic(bin); - //return false; - } + virtual bool isElf(const char* bin) const { + return amd::isElfMagic(bin); + //return false; + } - //! Returns the binary - // This should ensure that the binary is updated with all the kernels - // ClBinary& clBinary() { return binary_; } - ClBinary* clBinary() { - return static_cast(device::Program::clBinary()); - } - const ClBinary* clBinary() const { - return static_cast(device::Program::clBinary()); - } - private: - /* \brief Returns the next stage to compile from, based on sections in binary, - * also returns completeStages in a vector, which contains at least ACL_TYPE_DEFAULT, - * sets needOptionsCheck to true if options check is needed to decide whether or not to recompile - */ - aclType getCompilationStagesFromBinary(std::vector& completeStages, bool& needOptionsCheck); + //! Returns the binary + // This should ensure that the binary is updated with all the kernels + // ClBinary& clBinary() { return binary_; } + ClBinary* clBinary() { + return static_cast(device::Program::clBinary()); + } + const ClBinary* clBinary() const { + return static_cast(device::Program::clBinary()); + } +private: + /* \brief Returns the next stage to compile from, based on sections in binary, + * also returns completeStages in a vector, which contains at least ACL_TYPE_DEFAULT, + * sets needOptionsCheck to true if options check is needed to decide whether or not to recompile + */ + aclType getCompilationStagesFromBinary(std::vector& completeStages, bool& needOptionsCheck); - /* \brief Returns the next stage to compile from, based on sections and options in binary - */ - aclType getNextCompilationStageFromBinary(amd::option::Options* options); - bool saveBinaryAndSetType(type_t type); - bool initBrigContainer(); - void destroyBrigContainer(); - //Initializes BRIG module - bool initBrigModule(); - void destroyBrigModule(); - //! Disable default copy constructor - HSAILProgram(const HSAILProgram&); + /* \brief Returns the next stage to compile from, based on sections and options in binary + */ + aclType getNextCompilationStageFromBinary(amd::option::Options* options); + bool saveBinaryAndSetType(type_t type); + bool initBrigContainer(); + void destroyBrigContainer(); + //Initializes BRIG module + bool initBrigModule(); + void destroyBrigModule(); + //! Disable default copy constructor + HSAILProgram(const HSAILProgram&); - //! Disable operator= - HSAILProgram& operator=(const HSAILProgram&); + //! Disable operator= + HSAILProgram& operator=(const HSAILProgram&); - //! Returns all the options to be appended while passing to the - //compiler - std::string hsailOptions(amd::option::Options* options); + //! Returns all the options to be appended while passing to the + //compiler + std::string hsailOptions(amd::option::Options* options); - // aclBinary and aclCompiler - for the compiler library - aclBinary* binaryElf_; //!< Binary for the new compiler library - aclBinaryOptions binOpts_; //!< Binary options to create aclBinary + // aclBinary and aclCompiler - for the compiler library + aclBinary* binaryElf_; //!< Binary for the new compiler library + aclBinaryOptions binOpts_; //!< Binary options to create aclBinary - /* Brig and Brig modules */ - BrigModule_t brigModule_; //!< Brig that should be used in the HSA runtime - BrigContainer* hsaBrigContainer_; //!< Container for the BRIG; - hsa_ext_program_t hsaProgramHandle_; //!< Handle to HSA runtime program - hsa_code_object_t hsaProgramCodeObject_; //!< Handle to HSA code object - hsa_executable_t hsaExecutable_; //!< Handle to HSA executable + /* Brig and Brig modules */ + BrigModule_t brigModule_; //!< Brig that should be used in the HSA runtime + BrigContainer* hsaBrigContainer_; //!< Container for the BRIG; + hsa_ext_program_t hsaProgramHandle_; //!< Handle to HSA runtime program + hsa_code_object_t hsaProgramCodeObject_; //!< Handle to HSA code object + hsa_executable_t hsaExecutable_; //!< Handle to HSA executable #if defined(WITH_LIGHTNING_COMPILER) - RuntimeMD::Program::Metadata* metadata_; //!< Runtime metadata - //! Return a new transient compiler instance. - static std::auto_ptr newCompilerInstance(); + RuntimeMD::Program::Metadata* metadata_; //!< Runtime metadata + //! Return a new transient compiler instance. + static std::auto_ptr newCompilerInstance(); #endif // defined(WITH_LIGHTNING_COMPILER) - }; +}; - /*@}*/} // namespace roc +/*@}*/} // namespace roc #endif /*WITHOUT_HSA_BACKEND*/