e195bb5eea
SWDEV-94640 - Set the O# level and cl-std from the command args or default settings.
Select the correct header (CL1.2/C2.0) from the given cl-std.
Reorder the linked libraries in reverse order of dependency (was failing linking).
Make the built-in library objects depend on the pre-compiled header.
Disable the timestamp on the pre-compiled header.
Disable image support reporting.
Affected files ...
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/headers/build/Makefile.headers#7 edit
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/irif/build/Makefile.irif#4 edit
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/ockl/build/Makefile.ockl#5 edit
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/oclc/build/Makefile.oclc#5 edit
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/ocml/build/Makefile.ocml#5 edit
... //depot/stg/opencl/drivers/opencl/make/amdgcn.git/opencl/build/Makefile.opencl#6 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/roccompiler.cpp#8 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocdevice.cpp#10 edit
... //depot/stg/opencl/drivers/opencl/runtime/device/rocm/rocprogram.cpp#11 edit
[ROCm/clr commit: 9674e8eb01]
321 lines
11 KiB
C++
321 lines
11 KiB
C++
//
|
|
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
|
|
//
|
|
#ifndef WITHOUT_HSA_BACKEND
|
|
|
|
#include <string>
|
|
#include <sstream>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
#include "os/os.hpp"
|
|
#include "rocdevice.hpp"
|
|
#include "rocprogram.hpp"
|
|
#if defined(WITH_LIGHTNING_COMPILER)
|
|
#include "opencl1.2-c.amdgcn.inc"
|
|
#include "opencl2.0-c.amdgcn.inc"
|
|
#else // !defined(WITH_LIGHTNING_COMPILER)
|
|
#include "roccompilerlib.hpp"
|
|
#endif // !defined(WITH_LIGHTNING_COMPILER)
|
|
#include "utils/options.hpp"
|
|
#include <cstdio>
|
|
|
|
//CLC_IN_PROCESS_CHANGE
|
|
extern int openclFrontEnd(const char* cmdline, std::string*, std::string* typeInfo = NULL);
|
|
|
|
namespace roc {
|
|
|
|
/* Temporary log function for the compiler library */
|
|
static void logFunction(const char* msg, size_t size)
|
|
{
|
|
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<const std::string*>& headers,
|
|
const char** headerIncludeNames,
|
|
amd::option::Options* options)
|
|
{
|
|
using namespace amd::opencl_driver;
|
|
std::vector<Data*> inputs;
|
|
|
|
Data* src = device().compiler()->NewBufferReference(DT_CL,
|
|
sourceCode.c_str(), sourceCode.length());
|
|
|
|
if (src == NULL) {
|
|
buildLog_ += "Error while creating data from source code";
|
|
return false;
|
|
}
|
|
|
|
inputs.push_back(src);
|
|
|
|
//Find the temp folder for the OS
|
|
std::string tempFolder = amd::Os::getEnvironment("TEMP");
|
|
if (tempFolder.empty()) {
|
|
tempFolder = amd::Os::getEnvironment("TMP");
|
|
if (tempFolder.empty()) {
|
|
tempFolder = WINDOWS_SWITCH(".","/tmp");;
|
|
}
|
|
}
|
|
//Iterate through each source code and dump it into tmp
|
|
std::fstream f;
|
|
std::vector<std::string> headerFileNames(headers.size());
|
|
std::vector<std::string> newDirs;
|
|
for (size_t i = 0; i < headers.size(); ++i) {
|
|
std::string headerPath = tempFolder;
|
|
std::string headerIncludeName(headerIncludeNames[i]);
|
|
// replace / in path with current os's file separator
|
|
if ( amd::Os::fileSeparator() != '/') {
|
|
for (std::string::iterator it = headerIncludeName.begin(),
|
|
end = headerIncludeName.end();
|
|
it != end;
|
|
++it) {
|
|
if (*it == '/') *it = amd::Os::fileSeparator();
|
|
}
|
|
}
|
|
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
|
|
if (pos != std::string::npos) {
|
|
headerPath += amd::Os::fileSeparator();
|
|
headerPath += headerIncludeName.substr(0, pos);
|
|
headerIncludeName = headerIncludeName.substr(pos+1);
|
|
}
|
|
if (!amd::Os::pathExists(headerPath)) {
|
|
bool ret = amd::Os::createPath(headerPath);
|
|
assert(ret && "failed creating path!");
|
|
newDirs.push_back(headerPath);
|
|
}
|
|
std::string headerFullName
|
|
= headerPath + amd::Os::fileSeparator() + headerIncludeName;
|
|
headerFileNames[i] = headerFullName;
|
|
f.open(headerFullName.c_str(), std::fstream::out);
|
|
//Should we allow asserts
|
|
assert(!f.fail() && "failed creating header file!");
|
|
f.write(headers[i]->c_str(), headers[i]->length());
|
|
f.close();
|
|
|
|
Data* inc = device().compiler()->NewFileReference(DT_CL_HEADER,
|
|
headerFileNames[i]);
|
|
inputs.push_back(inc);
|
|
}
|
|
|
|
|
|
//Set the options for the compiler
|
|
//Set the include path for the temp folder that contains the includes
|
|
if(!headers.empty()) {
|
|
compileOptions_.append(" -I");
|
|
compileOptions_.append(tempFolder);
|
|
}
|
|
|
|
const char* xLang = options->oVariables->XLang;
|
|
if (xLang != NULL && strcmp(xLang, "cl")) {
|
|
buildLog_ += "Unsupported OpenCL language.\n";
|
|
}
|
|
|
|
//FIXME_Nikolay: the program manager should be setting the language
|
|
//compileOptions_.append(" -x cl");
|
|
//FIXME_Nikolay: the program manager shouls be setting the cl-std. -Xclang
|
|
//is not necessary, we add it to overridde the flag set in the comp driver.
|
|
compileOptions_.append(" -Xclang -cl-std=").append(options->oVariables->CLStd);
|
|
|
|
std::ostringstream optLevel;
|
|
optLevel << " -O" << options->oVariables->OptLevel;
|
|
compileOptions_.append(optLevel.str());
|
|
|
|
//FIXME_lmoriche: has the CL option been validated?
|
|
uint clVer = (options->oVariables->CLStd[2] - '0') * 100
|
|
+ (options->oVariables->CLStd[4] - '0') * 10;
|
|
|
|
std::pair<const void*, size_t> hdr;
|
|
switch(clVer) {
|
|
case 120: hdr = std::make_pair(opencl1_2_c_amdgcn, opencl1_2_c_amdgcn_size); break;
|
|
case 200: hdr = std::make_pair(opencl2_0_c_amdgcn, opencl2_0_c_amdgcn_size); break;
|
|
default:
|
|
buildLog_ += "Unsupported requested OpenCL C version (-cl-std).\n";
|
|
return false;
|
|
}
|
|
|
|
File* pch = device().compiler()->NewTempFile(DT_CL_HEADER);
|
|
if (pch == NULL || !pch->WriteData((const char*) hdr.first, hdr.second)) {
|
|
buildLog_ += "Error while opening the opencl-c header ";
|
|
return false;
|
|
}
|
|
|
|
compileOptions_.append(" -Xclang -include-pch -Xclang " + pch->Name());
|
|
compileOptions_.append(" -Xclang -fno-validate-pch");
|
|
|
|
compileOptions_.append(hsailOptions());
|
|
if (clVer >= 200) {
|
|
std::stringstream opts;
|
|
//Add only for CL2.0 and later
|
|
opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
|
|
<< device().info().maxGlobalVariableSize_;
|
|
compileOptions_.append(opts.str());
|
|
}
|
|
|
|
Buffer* output = device().compiler()->NewBuffer(DT_LLVM_BC);
|
|
if (output == NULL) {
|
|
buildLog_ += "Error while creating buffer for the LLVM bitcode";
|
|
return false;
|
|
}
|
|
|
|
// Tokenize the options string into a vector of strings
|
|
std::istringstream strstr(compileOptions_);
|
|
std::istream_iterator<std::string> sit(strstr), end;
|
|
std::vector<std::string> optionsvec(sit, end);
|
|
|
|
// Compile source to IR
|
|
bool ret = device().compiler()->CompileToLLVMBitcode(inputs, output, optionsvec);
|
|
buildLog_ += device().compiler()->Output().c_str();
|
|
if (!ret) {
|
|
buildLog_ += "Error while compiling opencl source: Compiling CL to IR";
|
|
return false;
|
|
}
|
|
|
|
// save the source code
|
|
//Create Binary
|
|
codeObjBinary_ = new CodeObjBinary();
|
|
|
|
openCLSource_ = sourceCode;
|
|
codeObjBinary_->saveIR(std::string(output->Buf().begin(), output->Buf().end()));
|
|
return true;
|
|
}
|
|
#endif // defined(WITH_LIGHTNING_COMPILER)
|
|
|
|
bool
|
|
HSAILProgram::compileImpl(const std::string& sourceCode,
|
|
const std::vector<const std::string*>& headers,
|
|
const char** headerIncludeNames,
|
|
amd::option::Options* options)
|
|
{
|
|
#if defined(WITH_LIGHTNING_COMPILER)
|
|
return compileImpl_LC(sourceCode, headers, headerIncludeNames, options);
|
|
#else // !defined(WITH_LIGHTNING_COMPILER)
|
|
acl_error errorCode;
|
|
aclTargetInfo target;
|
|
|
|
//Defaulting to bonaire
|
|
//Todo (sramalin) : Query the device for asic type-
|
|
//Defaulting to Bonair for now.
|
|
target = g_complibApi._aclGetTargetInfo(LP64_SWITCH("hsail","hsail64"), "Bonaire",
|
|
&errorCode);
|
|
|
|
//end if asic info is ready
|
|
// We dump the source code for each program (param: headers)
|
|
// into their filenames (headerIncludeNames) into the TEMP
|
|
// folder specific to the OS and add the include path while
|
|
// compiling
|
|
|
|
//Find the temp folder for the OS
|
|
std::string tempFolder = amd::Os::getEnvironment("TEMP");
|
|
if (tempFolder.empty()) {
|
|
tempFolder = amd::Os::getEnvironment("TMP");
|
|
if (tempFolder.empty()) {
|
|
tempFolder = WINDOWS_SWITCH(".","/tmp");;
|
|
}
|
|
}
|
|
//Iterate through each source code and dump it into tmp
|
|
std::fstream f;
|
|
std::vector<std::string> headerFileNames(headers.size());
|
|
std::vector<std::string> newDirs;
|
|
for (size_t i = 0; i < headers.size(); ++i) {
|
|
std::string headerPath = tempFolder;
|
|
std::string headerIncludeName(headerIncludeNames[i]);
|
|
// replace / in path with current os's file separator
|
|
if ( amd::Os::fileSeparator() != '/') {
|
|
for (std::string::iterator it = headerIncludeName.begin(),
|
|
end = headerIncludeName.end();
|
|
it != end;
|
|
++it) {
|
|
if (*it == '/') *it = amd::Os::fileSeparator();
|
|
}
|
|
}
|
|
size_t pos = headerIncludeName.rfind(amd::Os::fileSeparator());
|
|
if (pos != std::string::npos) {
|
|
headerPath += amd::Os::fileSeparator();
|
|
headerPath += headerIncludeName.substr(0, pos);
|
|
headerIncludeName = headerIncludeName.substr(pos+1);
|
|
}
|
|
if (!amd::Os::pathExists(headerPath)) {
|
|
bool ret = amd::Os::createPath(headerPath);
|
|
assert(ret && "failed creating path!");
|
|
newDirs.push_back(headerPath);
|
|
}
|
|
std::string headerFullName
|
|
= headerPath + amd::Os::fileSeparator() + headerIncludeName;
|
|
headerFileNames[i] = headerFullName;
|
|
f.open(headerFullName.c_str(), std::fstream::out);
|
|
//Should we allow asserts
|
|
assert(!f.fail() && "failed creating header file!");
|
|
f.write(headers[i]->c_str(), headers[i]->length());
|
|
f.close();
|
|
}
|
|
|
|
//Create Binary
|
|
binaryElf_ = g_complibApi._aclBinaryInit(sizeof(aclBinary),
|
|
&target,
|
|
&binOpts_,
|
|
&errorCode);
|
|
|
|
if( errorCode!=ACL_SUCCESS ) {
|
|
buildLog_ += "Error while compiling opencl source:\
|
|
aclBinary init failure \n";
|
|
LogWarning("aclBinaryInit failed");
|
|
return false;
|
|
}
|
|
|
|
//Insert opencl into binary
|
|
errorCode = g_complibApi._aclInsertSection(device().compiler(),
|
|
binaryElf_,
|
|
sourceCode.c_str(),
|
|
strlen(sourceCode.c_str()),
|
|
aclSOURCE);
|
|
|
|
if ( errorCode != ACL_SUCCESS ) {
|
|
buildLog_ += "Error while converting to BRIG: \
|
|
Inserting openCl Source \n";
|
|
}
|
|
|
|
//Set the options for the compiler
|
|
//Set the include path for the temp folder that contains the includes
|
|
if(!headers.empty()) {
|
|
this->compileOptions_.append(" -I");
|
|
this->compileOptions_.append(tempFolder);
|
|
}
|
|
|
|
//Add only for CL2.0 and later
|
|
if (options->oVariables->CLStd[2] >= '2') {
|
|
std::stringstream opts;
|
|
opts << " -D" << "CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE="
|
|
<< device().info().maxGlobalVariableSize_;
|
|
compileOptions_.append(opts.str());
|
|
}
|
|
|
|
//Compile source to IR
|
|
this->compileOptions_.append(hsailOptions());
|
|
|
|
errorCode = g_complibApi._aclCompile(device().compiler(),
|
|
binaryElf_,
|
|
//"-Wf,--support_all_extensions",
|
|
this->compileOptions_.c_str(),
|
|
ACL_TYPE_OPENCL,
|
|
ACL_TYPE_LLVMIR_BINARY,
|
|
logFunction);
|
|
buildLog_ += g_complibApi._aclGetCompilerLog(device().compiler());
|
|
if( errorCode!=ACL_SUCCESS ) {
|
|
LogWarning("aclCompile failed");
|
|
buildLog_ += "Error while compiling \
|
|
opencl source: Compiling CL to IR";
|
|
return false;
|
|
}
|
|
// Save the binary in the interface class
|
|
saveBinaryAndSetType(TYPE_COMPILED);
|
|
return true;
|
|
#endif // !defined(WITH_LIGHTNING_COMPILER)
|
|
}
|
|
}
|
|
#endif // WITHOUT_GPU_BACKEND
|