P4 to Git Change 1607675 by gandryey@gera-w8 on 2018/09/18 18:42:34
SWDEV-79445 - OCL generic changes and code clean-up
Program compilation clean-up. Step#1:
- Move device::Program implementation into a separate file
- Combine the common fields accros all 3 layers into the abstract device::Program
Affected files ...
... //depot/stg/opencl/drivers/opencl/runtime/device/device.cpp#230 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/device.hpp#318 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.cpp#1 add
... //depot/stg/opencl/drivers/opencl/runtime/device/devprogram.hpp#1 add
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpucompiler.cpp#159 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.cpp#241 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/gpu/gpuprogram.hpp#73 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.cpp#72 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palprogram.hpp#29 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/pal/palvirtual.cpp#125 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#86 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.hpp#35 edit
[ROCm/clr commit: 0253c1afb3]
Этот коммит содержится в:
@@ -0,0 +1,674 @@
|
||||
//
|
||||
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
||||
//
|
||||
#include "platform/runtime.hpp"
|
||||
#include "platform/program.hpp"
|
||||
#include "platform/ndrange.hpp"
|
||||
#include "devprogram.hpp"
|
||||
#include "devkernel.hpp"
|
||||
#include "utils/macros.hpp"
|
||||
#include "utils/options.hpp"
|
||||
#include "utils/bif_section_labels.hpp"
|
||||
#include "utils/libUtils.h"
|
||||
|
||||
#include "spirv/spirvUtils.h"
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include "acl.h"
|
||||
|
||||
#if defined(WITH_LIGHTNING_COMPILER)
|
||||
#include "llvm/Support/AMDGPUMetadata.h"
|
||||
|
||||
typedef llvm::AMDGPU::HSAMD::Kernel::Arg::Metadata KernelArgMD;
|
||||
#endif // defined(WITH_LIGHTNING_COMPILER)
|
||||
|
||||
namespace device {
|
||||
|
||||
// ================================================================================================
|
||||
Program::Program(amd::Device& device)
|
||||
: device_(device),
|
||||
type_(TYPE_NONE),
|
||||
flags_(0),
|
||||
clBinary_(nullptr),
|
||||
llvmBinary_(),
|
||||
elfSectionType_(amd::OclElf::LLVMIR),
|
||||
compileOptions_(),
|
||||
linkOptions_(),
|
||||
binaryElf_(nullptr),
|
||||
lastBuildOptionsArg_(),
|
||||
buildStatus_(CL_BUILD_NONE),
|
||||
buildError_(CL_SUCCESS),
|
||||
globalVariableTotalSize_(0),
|
||||
programOptions_(nullptr)
|
||||
{
|
||||
memset(&binOpts_, 0, sizeof(binOpts_));
|
||||
binOpts_.struct_size = sizeof(binOpts_);
|
||||
binOpts_.elfclass = LP64_SWITCH(ELFCLASS32, ELFCLASS64);
|
||||
binOpts_.bitness = ELFDATA2LSB;
|
||||
binOpts_.alloc = &::malloc;
|
||||
binOpts_.dealloc = &::free;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
Program::~Program() { clear(); }
|
||||
|
||||
// ================================================================================================
|
||||
void Program::clear() {
|
||||
// Destroy all device kernels
|
||||
for (const auto& it : kernels_) {
|
||||
delete it.second;
|
||||
}
|
||||
kernels_.clear();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::initClBinary() {
|
||||
if (clBinary_ == nullptr) {
|
||||
clBinary_ = new ClBinary(device());
|
||||
if (clBinary_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Program::releaseClBinary() {
|
||||
if (clBinary_ != nullptr) {
|
||||
delete clBinary_;
|
||||
clBinary_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::initBuild(amd::option::Options* options) {
|
||||
programOptions_ = options;
|
||||
|
||||
if (options->oVariables->DumpFlags > 0) {
|
||||
static amd::Atomic<unsigned> build_num = 0;
|
||||
options->setBuildNo(build_num++);
|
||||
}
|
||||
buildLog_.clear();
|
||||
if (!initClBinary()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::finiBuild(bool isBuildGood) { return true; }
|
||||
|
||||
// ================================================================================================
|
||||
cl_int Program::compile(const std::string& sourceCode,
|
||||
const std::vector<const std::string*>& headers,
|
||||
const char** headerIncludeNames, const char* origOptions,
|
||||
amd::option::Options* options) {
|
||||
uint64_t start_time = 0;
|
||||
if (options->oVariables->EnableBuildTiming) {
|
||||
buildLog_ = "\nStart timing major build components.....\n\n";
|
||||
start_time = amd::Os::timeNanos();
|
||||
}
|
||||
|
||||
lastBuildOptionsArg_ = origOptions ? origOptions : "";
|
||||
if (options) {
|
||||
compileOptions_ = options->origOptionStr;
|
||||
}
|
||||
|
||||
buildStatus_ = CL_BUILD_IN_PROGRESS;
|
||||
if (!initBuild(options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation init failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if (options->oVariables->FP32RoundDivideSqrt &&
|
||||
!(device().info().singleFPConfig_ & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
buildLog_ +=
|
||||
"Error: -cl-fp32-correctly-rounded-divide-sqrt "
|
||||
"specified without device support";
|
||||
}
|
||||
|
||||
// Compile the source code if any
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !sourceCode.empty() &&
|
||||
!compileImpl(sourceCode, headers, headerIncludeNames, options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation failed.";
|
||||
}
|
||||
}
|
||||
|
||||
setType(TYPE_COMPILED);
|
||||
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !createBinary(options)) {
|
||||
buildLog_ += "Internal Error: creating OpenCL binary failed!\n";
|
||||
}
|
||||
|
||||
if (!finiBuild(buildStatus_ == CL_BUILD_IN_PROGRESS)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation fini failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if (buildStatus_ == CL_BUILD_IN_PROGRESS) {
|
||||
buildStatus_ = CL_BUILD_SUCCESS;
|
||||
} else {
|
||||
buildError_ = CL_COMPILE_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
if (options->oVariables->EnableBuildTiming) {
|
||||
std::stringstream tmp_ss;
|
||||
tmp_ss << "\nTotal Compile Time: " << (amd::Os::timeNanos() - start_time) / 1000ULL << " us\n";
|
||||
buildLog_ += tmp_ss.str();
|
||||
}
|
||||
|
||||
if (options->oVariables->BuildLog && !buildLog_.empty()) {
|
||||
if (strcmp(options->oVariables->BuildLog, "stderr") == 0) {
|
||||
fprintf(stderr, "%s\n", options->optionsLog().c_str());
|
||||
fprintf(stderr, "%s\n", buildLog_.c_str());
|
||||
} else if (strcmp(options->oVariables->BuildLog, "stdout") == 0) {
|
||||
printf("%s\n", options->optionsLog().c_str());
|
||||
printf("%s\n", buildLog_.c_str());
|
||||
} else {
|
||||
std::fstream f;
|
||||
std::stringstream tmp_ss;
|
||||
std::string logs = options->optionsLog() + buildLog_;
|
||||
tmp_ss << options->oVariables->BuildLog << "." << options->getBuildNo();
|
||||
f.open(tmp_ss.str().c_str(), (std::fstream::out | std::fstream::binary));
|
||||
f.write(logs.data(), logs.size());
|
||||
f.close();
|
||||
}
|
||||
LogError(buildLog_.c_str());
|
||||
}
|
||||
|
||||
return buildError();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
cl_int Program::link(const std::vector<Program*>& inputPrograms, const char* origLinkOptions,
|
||||
amd::option::Options* linkOptions) {
|
||||
lastBuildOptionsArg_ = origLinkOptions ? origLinkOptions : "";
|
||||
if (linkOptions) {
|
||||
linkOptions_ = linkOptions->origOptionStr;
|
||||
}
|
||||
|
||||
buildStatus_ = CL_BUILD_IN_PROGRESS;
|
||||
|
||||
amd::option::Options options;
|
||||
if (!getCompileOptionsAtLinking(inputPrograms, linkOptions)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ += "Internal error: Get compile options failed.";
|
||||
}
|
||||
} else {
|
||||
if (!amd::option::parseAllOptions(compileOptions_, options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
buildLog_ += options.optionsLog();
|
||||
LogError("Parsing compile options failed.");
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t start_time = 0;
|
||||
if (options.oVariables->EnableBuildTiming) {
|
||||
buildLog_ = "\nStart timing major build components.....\n\n";
|
||||
start_time = amd::Os::timeNanos();
|
||||
}
|
||||
|
||||
// initBuild() will clear buildLog_, so store it in a temporary variable
|
||||
std::string tmpBuildLog = buildLog_;
|
||||
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !initBuild(&options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ += "Internal error: Compilation init failed.";
|
||||
}
|
||||
}
|
||||
|
||||
buildLog_ += tmpBuildLog;
|
||||
|
||||
if (options.oVariables->FP32RoundDivideSqrt &&
|
||||
!(device().info().singleFPConfig_ & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
buildLog_ +=
|
||||
"Error: -cl-fp32-correctly-rounded-divide-sqrt "
|
||||
"specified without device support";
|
||||
}
|
||||
|
||||
bool createLibrary = linkOptions ? linkOptions->oVariables->clCreateLibrary : false;
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !linkImpl(inputPrograms, &options, createLibrary)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ += "Internal error: Link failed.\n";
|
||||
buildLog_ += "Make sure the system setup is correct.";
|
||||
}
|
||||
}
|
||||
|
||||
if (!finiBuild(buildStatus_ == CL_BUILD_IN_PROGRESS)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation fini failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if (buildStatus_ == CL_BUILD_IN_PROGRESS) {
|
||||
buildStatus_ = CL_BUILD_SUCCESS;
|
||||
} else {
|
||||
buildError_ = CL_LINK_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
if (options.oVariables->EnableBuildTiming) {
|
||||
std::stringstream tmp_ss;
|
||||
tmp_ss << "\nTotal Link Time: " << (amd::Os::timeNanos() - start_time) / 1000ULL << " us\n";
|
||||
buildLog_ += tmp_ss.str();
|
||||
}
|
||||
|
||||
if (options.oVariables->BuildLog && !buildLog_.empty()) {
|
||||
if (strcmp(options.oVariables->BuildLog, "stderr") == 0) {
|
||||
fprintf(stderr, "%s\n", options.optionsLog().c_str());
|
||||
fprintf(stderr, "%s\n", buildLog_.c_str());
|
||||
} else if (strcmp(options.oVariables->BuildLog, "stdout") == 0) {
|
||||
printf("%s\n", options.optionsLog().c_str());
|
||||
printf("%s\n", buildLog_.c_str());
|
||||
} else {
|
||||
std::fstream f;
|
||||
std::stringstream tmp_ss;
|
||||
std::string logs = options.optionsLog() + buildLog_;
|
||||
tmp_ss << options.oVariables->BuildLog << "." << options.getBuildNo();
|
||||
f.open(tmp_ss.str().c_str(), (std::fstream::out | std::fstream::binary));
|
||||
f.write(logs.data(), logs.size());
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (!buildLog_.empty()) {
|
||||
LogError(buildLog_.c_str());
|
||||
}
|
||||
|
||||
return buildError();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
cl_int Program::build(const std::string& sourceCode, const char* origOptions,
|
||||
amd::option::Options* options) {
|
||||
uint64_t start_time = 0;
|
||||
if (options->oVariables->EnableBuildTiming) {
|
||||
buildLog_ = "\nStart timing major build components.....\n\n";
|
||||
start_time = amd::Os::timeNanos();
|
||||
}
|
||||
|
||||
lastBuildOptionsArg_ = origOptions ? origOptions : "";
|
||||
if (options) {
|
||||
compileOptions_ = options->origOptionStr;
|
||||
}
|
||||
|
||||
buildStatus_ = CL_BUILD_IN_PROGRESS;
|
||||
if (!initBuild(options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation init failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if (options->oVariables->FP32RoundDivideSqrt &&
|
||||
!(device().info().singleFPConfig_ & CL_FP_CORRECTLY_ROUNDED_DIVIDE_SQRT)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
buildLog_ +=
|
||||
"Error: -cl-fp32-correctly-rounded-divide-sqrt "
|
||||
"specified without device support";
|
||||
}
|
||||
|
||||
// Compile the source code if any
|
||||
std::vector<const std::string*> headers;
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !sourceCode.empty() &&
|
||||
!compileImpl(sourceCode, headers, nullptr, options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if ((buildStatus_ == CL_BUILD_IN_PROGRESS) && !linkImpl(options)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ += "Internal error: Link failed.\n";
|
||||
buildLog_ += "Make sure the system setup is correct.";
|
||||
}
|
||||
}
|
||||
|
||||
if (!finiBuild(buildStatus_ == CL_BUILD_IN_PROGRESS)) {
|
||||
buildStatus_ = CL_BUILD_ERROR;
|
||||
if (buildLog_.empty()) {
|
||||
buildLog_ = "Internal error: Compilation fini failed.";
|
||||
}
|
||||
}
|
||||
|
||||
if (buildStatus_ == CL_BUILD_IN_PROGRESS) {
|
||||
buildStatus_ = CL_BUILD_SUCCESS;
|
||||
} else {
|
||||
buildError_ = CL_BUILD_PROGRAM_FAILURE;
|
||||
}
|
||||
|
||||
if (options->oVariables->EnableBuildTiming) {
|
||||
std::stringstream tmp_ss;
|
||||
tmp_ss << "\nTotal Build Time: " << (amd::Os::timeNanos() - start_time) / 1000ULL << " us\n";
|
||||
buildLog_ += tmp_ss.str();
|
||||
}
|
||||
|
||||
if (options->oVariables->BuildLog && !buildLog_.empty()) {
|
||||
if (strcmp(options->oVariables->BuildLog, "stderr") == 0) {
|
||||
fprintf(stderr, "%s\n", options->optionsLog().c_str());
|
||||
fprintf(stderr, "%s\n", buildLog_.c_str());
|
||||
} else if (strcmp(options->oVariables->BuildLog, "stdout") == 0) {
|
||||
printf("%s\n", options->optionsLog().c_str());
|
||||
printf("%s\n", buildLog_.c_str());
|
||||
} else {
|
||||
std::fstream f;
|
||||
std::stringstream tmp_ss;
|
||||
std::string logs = options->optionsLog() + buildLog_;
|
||||
tmp_ss << options->oVariables->BuildLog << "." << options->getBuildNo();
|
||||
f.open(tmp_ss.str().c_str(), (std::fstream::out | std::fstream::binary));
|
||||
f.write(logs.data(), logs.size());
|
||||
f.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (!buildLog_.empty()) {
|
||||
LogError(buildLog_.c_str());
|
||||
}
|
||||
|
||||
return buildError();
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
std::string Program::ProcessOptions(amd::option::Options* options) {
|
||||
std::string optionsStr;
|
||||
|
||||
#ifndef WITH_LIGHTNING_COMPILER
|
||||
optionsStr.append(" -D__AMD__=1");
|
||||
|
||||
optionsStr.append(" -D__").append(device().info().name_).append("__=1");
|
||||
optionsStr.append(" -D__").append(device().info().name_).append("=1");
|
||||
#endif
|
||||
|
||||
#ifdef WITH_LIGHTNING_COMPILER
|
||||
int major, minor;
|
||||
::sscanf(device().info().version_, "OpenCL %d.%d ", &major, &minor);
|
||||
|
||||
std::stringstream ss;
|
||||
ss << " -D__OPENCL_VERSION__=" << (major * 100 + minor * 10);
|
||||
optionsStr.append(ss.str());
|
||||
#endif
|
||||
|
||||
if (device().info().imageSupport_ && options->oVariables->ImageSupport) {
|
||||
optionsStr.append(" -D__IMAGE_SUPPORT__=1");
|
||||
}
|
||||
|
||||
#ifndef WITH_LIGHTNING_COMPILER
|
||||
// Set options for the standard device specific options
|
||||
// All our devices support these options now
|
||||
if (device().settings().reportFMAF_) {
|
||||
optionsStr.append(" -DFP_FAST_FMAF=1");
|
||||
}
|
||||
if (device().settings().reportFMA_) {
|
||||
optionsStr.append(" -DFP_FAST_FMA=1");
|
||||
}
|
||||
#endif
|
||||
|
||||
uint clcStd =
|
||||
(options->oVariables->CLStd[2] - '0') * 100 + (options->oVariables->CLStd[4] - '0') * 10;
|
||||
|
||||
if (clcStd >= 200) {
|
||||
std::stringstream opts;
|
||||
// Add only for CL2.0 and later
|
||||
opts << " -D"
|
||||
<< "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE=" << device().info().maxGlobalVariableSize_;
|
||||
optionsStr.append(opts.str());
|
||||
}
|
||||
|
||||
#if !defined(WITH_LIGHTNING_COMPILER)
|
||||
if (!device().settings().singleFpDenorm_) {
|
||||
optionsStr.append(" -cl-denorms-are-zero");
|
||||
}
|
||||
|
||||
// Check if the host is 64 bit or 32 bit
|
||||
LP64_ONLY(optionsStr.append(" -m64"));
|
||||
#endif // !defined(WITH_LIGHTNING_COMPILER)
|
||||
|
||||
// Tokenize the extensions string into a vector of strings
|
||||
std::istringstream istrstr(device().info().extensions_);
|
||||
std::istream_iterator<std::string> sit(istrstr), end;
|
||||
std::vector<std::string> extensions(sit, end);
|
||||
|
||||
if (IS_LIGHTNING && !options->oVariables->Legacy) {
|
||||
// FIXME_lmoriche: opencl-c.h defines 'cl_khr_depth_images', so
|
||||
// remove it from the command line. Should we fix opencl-c.h?
|
||||
auto found = std::find(extensions.begin(), extensions.end(), "cl_khr_depth_images");
|
||||
if (found != extensions.end()) {
|
||||
extensions.erase(found);
|
||||
}
|
||||
|
||||
if (!extensions.empty()) {
|
||||
std::ostringstream clext;
|
||||
|
||||
clext << " -Xclang -cl-ext=+";
|
||||
std::copy(extensions.begin(), extensions.end() - 1,
|
||||
std::ostream_iterator<std::string>(clext, ",+"));
|
||||
clext << extensions.back();
|
||||
|
||||
optionsStr.append(clext.str());
|
||||
}
|
||||
} else {
|
||||
for (auto e : extensions) {
|
||||
optionsStr.append(" -D").append(e).append("=1");
|
||||
}
|
||||
}
|
||||
|
||||
return optionsStr;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::getCompileOptionsAtLinking(const std::vector<Program*>& inputPrograms,
|
||||
const amd::option::Options* linkOptions) {
|
||||
amd::option::Options compileOptions;
|
||||
auto it = inputPrograms.cbegin();
|
||||
const auto itEnd = inputPrograms.cend();
|
||||
for (size_t i = 0; it != itEnd; ++it, ++i) {
|
||||
Program* program = *it;
|
||||
|
||||
amd::option::Options compileOptions2;
|
||||
amd::option::Options* thisCompileOptions = i == 0 ? &compileOptions : &compileOptions2;
|
||||
if (!amd::option::parseAllOptions(program->compileOptions_, *thisCompileOptions)) {
|
||||
buildLog_ += thisCompileOptions->optionsLog();
|
||||
LogError("Parsing compile options failed.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (i == 0) compileOptions_ = program->compileOptions_;
|
||||
|
||||
// if we are linking a program executable, and if "program" is a
|
||||
// compiled module or a library created with "-enable-link-options",
|
||||
// we can overwrite "program"'s compile options with linking options
|
||||
if (!linkOptions_.empty() && !linkOptions->oVariables->clCreateLibrary) {
|
||||
bool linkOptsCanOverwrite = false;
|
||||
if (program->type() != TYPE_LIBRARY) {
|
||||
linkOptsCanOverwrite = true;
|
||||
} else {
|
||||
amd::option::Options thisLinkOptions;
|
||||
if (!amd::option::parseLinkOptions(program->linkOptions_, thisLinkOptions)) {
|
||||
buildLog_ += thisLinkOptions.optionsLog();
|
||||
LogError("Parsing link options failed.");
|
||||
return false;
|
||||
}
|
||||
if (thisLinkOptions.oVariables->clEnableLinkOptions) linkOptsCanOverwrite = true;
|
||||
}
|
||||
if (linkOptsCanOverwrite) {
|
||||
if (!thisCompileOptions->setOptionVariablesAs(*linkOptions)) {
|
||||
buildLog_ += thisCompileOptions->optionsLog();
|
||||
LogError("Setting link options failed.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (i == 0) compileOptions_ += " " + linkOptions_;
|
||||
}
|
||||
// warn if input modules have inconsistent compile options
|
||||
if (i > 0) {
|
||||
if (!compileOptions.equals(*thisCompileOptions, true /*ignore clc options*/)) {
|
||||
buildLog_ +=
|
||||
"Warning: Input OpenCL binaries has inconsistent"
|
||||
" compile options. Using compile options from"
|
||||
" the first input binary!\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::initClBinary(const char* binaryIn, size_t size) {
|
||||
if (!initClBinary()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Save the original binary that isn't owned by ClBinary
|
||||
clBinary()->saveOrigBinary(binaryIn, size);
|
||||
|
||||
const char* bin = binaryIn;
|
||||
size_t sz = size;
|
||||
|
||||
// unencrypted
|
||||
int encryptCode = 0;
|
||||
char* decryptedBin = nullptr;
|
||||
|
||||
#if !defined(WITH_LIGHTNING_COMPILER)
|
||||
bool isSPIRV = isSPIRVMagic(binaryIn, size);
|
||||
if (isSPIRV || isBcMagic(binaryIn)) {
|
||||
acl_error err = ACL_SUCCESS;
|
||||
aclBinaryOptions binOpts = {0};
|
||||
binOpts.struct_size = sizeof(binOpts);
|
||||
binOpts.elfclass =
|
||||
(info().arch_id == aclX64 || info().arch_id == aclAMDIL64 || info().arch_id == aclHSAIL64)
|
||||
? ELFCLASS64
|
||||
: ELFCLASS32;
|
||||
binOpts.bitness = ELFDATA2LSB;
|
||||
binOpts.alloc = &::malloc;
|
||||
binOpts.dealloc = &::free;
|
||||
aclBinary* aclbin_v30 = aclBinaryInit(sizeof(aclBinary), &info(), &binOpts, &err);
|
||||
if (err != ACL_SUCCESS) {
|
||||
LogWarning("aclBinaryInit failed");
|
||||
aclBinaryFini(aclbin_v30);
|
||||
return false;
|
||||
}
|
||||
err = aclInsertSection(device().compiler(), aclbin_v30, binaryIn, size,
|
||||
isSPIRV ? aclSPIRV : aclSPIR);
|
||||
if (ACL_SUCCESS != err) {
|
||||
LogWarning("aclInsertSection failed");
|
||||
aclBinaryFini(aclbin_v30);
|
||||
return false;
|
||||
}
|
||||
if (info().arch_id == aclHSAIL || info().arch_id == aclHSAIL64) {
|
||||
err = aclWriteToMem(aclbin_v30, (void**)const_cast<char**>(&bin), &sz);
|
||||
if (err != ACL_SUCCESS) {
|
||||
LogWarning("aclWriteToMem failed");
|
||||
aclBinaryFini(aclbin_v30);
|
||||
return false;
|
||||
}
|
||||
aclBinaryFini(aclbin_v30);
|
||||
} else {
|
||||
aclBinary* aclbin_v21 = aclCreateFromBinary(aclbin_v30, aclBIFVersion21);
|
||||
err = aclWriteToMem(aclbin_v21, (void**)const_cast<char**>(&bin), &sz);
|
||||
if (err != ACL_SUCCESS) {
|
||||
LogWarning("aclWriteToMem failed");
|
||||
aclBinaryFini(aclbin_v30);
|
||||
aclBinaryFini(aclbin_v21);
|
||||
return false;
|
||||
}
|
||||
aclBinaryFini(aclbin_v30);
|
||||
aclBinaryFini(aclbin_v21);
|
||||
}
|
||||
} else
|
||||
#endif // !defined(WITH_LIGHTNING_COMPILER)
|
||||
{
|
||||
size_t decryptedSize;
|
||||
if (!clBinary()->decryptElf(binaryIn, size, &decryptedBin, &decryptedSize, &encryptCode)) {
|
||||
return false;
|
||||
}
|
||||
if (decryptedBin != nullptr) {
|
||||
// It is decrypted binary.
|
||||
bin = decryptedBin;
|
||||
sz = decryptedSize;
|
||||
}
|
||||
|
||||
if (!isElf(bin)) {
|
||||
// Invalid binary.
|
||||
if (decryptedBin != nullptr) {
|
||||
delete[] decryptedBin;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
clBinary()->setFlags(encryptCode);
|
||||
|
||||
return clBinary()->setBinary(bin, sz, (decryptedBin != nullptr));
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
bool Program::setBinary(const char* binaryIn, size_t size) {
|
||||
if (!initClBinary(binaryIn, size)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!clBinary()->setElfIn()) {
|
||||
LogError("Setting input OCL binary failed");
|
||||
return false;
|
||||
}
|
||||
uint16_t type;
|
||||
if (!clBinary()->elfIn()->getType(type)) {
|
||||
LogError("Bad OCL Binary: error loading ELF type!");
|
||||
return false;
|
||||
}
|
||||
switch (type) {
|
||||
case ET_NONE: {
|
||||
setType(TYPE_NONE);
|
||||
break;
|
||||
}
|
||||
case ET_REL: {
|
||||
if (clBinary()->isSPIR() || clBinary()->isSPIRV()) {
|
||||
setType(TYPE_INTERMEDIATE);
|
||||
} else {
|
||||
setType(TYPE_COMPILED);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ET_DYN: {
|
||||
char* sect = nullptr;
|
||||
size_t sz = 0;
|
||||
// FIXME: we should look for the e_machine to detect an HSACO.
|
||||
if (clBinary()->elfIn()->getSection(amd::OclElf::TEXT, §, &sz) && sect && sz > 0) {
|
||||
setType(TYPE_EXECUTABLE);
|
||||
} else {
|
||||
setType(TYPE_LIBRARY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ET_EXEC: {
|
||||
setType(TYPE_EXECUTABLE);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LogError("Bad OCL Binary: bad ELF type!");
|
||||
return false;
|
||||
}
|
||||
|
||||
clBinary()->loadCompileOptions(compileOptions_);
|
||||
clBinary()->loadLinkOptions(linkOptions_);
|
||||
|
||||
clBinary()->resetElfIn();
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
Ссылка в новой задаче
Block a user