Files
rocm-systems/rocclr/compiler/lib/backends/common/frontend_clang.cpp
T
foreman fd39fdc694 P4 to Git Change 1221604 by yaxunl@yaxunl_stg_win50 on 2015/12/16 17:19:59
SWDEV-84089 - [SPIRV] github pull request #32 Changes for Clang integration.

Affected files ...

... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/frontend_clang.cpp#27 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/linker.cpp#136 edit
... //depot/stg/opencl/drivers/opencl/compiler/lib/backends/common/v0_8/if_acl.cpp#89 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/include/llvm/Support/SPIRV.h#10 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/CMakeLists.txt#16 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/SPIRVWriter.cpp#16 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/SPIRVWriterPass.cpp#1 branch
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/SPIRVWriterPass.h#1 branch
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/build/Makefile.SPIRV#3 edit
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVBasicBlock.cpp#2 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVBasicBlock.h#2 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVDebug.h#3 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVDecorate.cpp#2 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVDecorate.h#6 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVEntry.cpp#5 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVEntry.h#7 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVFunction.cpp#3 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVFunction.h#3 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVInstruction.h#8 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVModule.cpp#13 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVModule.h#7 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVStream.cpp#5 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVStream.h#4 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVUtil.h#4 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/lib/SPIRV/libSPIRV/SPIRVValue.h#4 integrate
... //depot/stg/opencl/drivers/opencl/compiler/llvm/tools/llvm-spirv/llvm-spirv.cpp#10 integrate
2015-12-16 17:27:20 -05:00

227 lines
6.5 KiB
C++

//
// Copyright (c) 2008 Advanced Micro Devices, Inc. All rights reserved.
//
#include "OpenCLFE.h"
#include "bif/bifbase.hpp"
#include "frontend.hpp"
#include "os/os.hpp"
#include "top.hpp"
#include "utils/options.hpp"
#include "utils/target_mappings.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SPIRV.h"
#include "llvm/ADT/StringRef.h"
#include <string>
#include <sstream>
amdcl::ClangOCLFrontend::ClangOCLFrontend(aclCompiler* cl, aclBinary* elf,
aclLogFunction log)
: Frontend(cl, elf, log){}
/// @brief This function generates the required command-line options to
/// call the ClangOCLFE library.
int amdcl::ClangOCLFrontend::compileCommand(const std::string& src) {
std::vector<const char*> argsToClang;
std::string tempFileName = amd::Os::getTempFileName();
std::string logFileName = tempFileName + ".log";
std::string inpCLFileName = tempFileName + ".cl";
std::string logFromClang;
int ret = 0;
aclBinary *elf = Elf();
amd::option::Options* amdOpts = (amd::option::Options*)elf->options;
// Following are the options passed to the ClangOCLFE library
// and then to Clang itself.
// handle -O0
if (amdOpts && amdOpts->origOptionStr.find("-O0") != std::string::npos) {
amdOpts->clangOptions.push_back("-O0");
}
// Passing the compiler FE options to clang.
if (amdOpts) {
for (std::vector<std::string>::const_iterator it = amdOpts->clangOptions.begin();
it != amdOpts->clangOptions.end(); ++it) {
argsToClang.push_back((*it).c_str());
}
}
if (Options()->oVariables->ImageSupport) {
argsToClang.push_back ("-D__IMAGE_SUPPORT__=1 ");
}
if (Options()->oVariables->FastFMA) {
argsToClang.push_back ("-DFP_FAST_FMA=1 ");
}
if (Options()->oVariables->FastFMAF) {
argsToClang.push_back ("-DFP_FAST_FMAF=1 ");
}
argsToClang.push_back ("-D__AMD__=1 ");
if (Options()->oVariables->FEGenSPIRV) {
argsToClang.push_back("-D__AMD_SPIRV__ ");
}
// Other options are passed using OptionsInfo structure.
clc2::OptionsInfo ClangOptions;
ClangOptions.InFilename = inpCLFileName;
// Generate target triple.
// TODO: Refine the triple as necessary.
uint32_t chipName = elf->target.chip_id;
assert(chipName < familySet[elf->target.arch_id].children_size &&
"Cannot index past end of array!");
switch (elf->target.arch_id) {
default:
log_ += "\nerror: Unknown target device ID!\n";
ret |= 1;
return ret;
break;
case aclX86:
case aclAMDIL:
case aclHSAIL:
// See bug: http://ocltc.amd.com/bugs/show_bug.cgi?id=9631
if (sizeof(void*) != 4) {
log_ += "\nerror: 32-bit kernels not supported on a 64-bit executable\n";
ret |= 1;
return ret;
}
ClangOptions.TargetArch = llvm::Triple::spir;
break;
case aclX64:
case aclAMDIL64:
case aclHSAIL64:
// See bug: http://ocltc.amd.com/bugs/show_bug.cgi?id=9631
if (sizeof(void*) != 8) {
log_ += "\nerror: 64-bit kernels not supported on a 32-bit executable\n";
ret |= 1;
return ret;
}
ClangOptions.TargetArch = llvm::Triple::spir64;
break;
};
// Copy the source to a buffer. Note that the input
// file itself is not passed to the ClangOCLFE library. It is a passed
// as a string for compilation.
std::unique_ptr<llvm::MemoryBuffer> srcBufferPtr =
llvm::MemoryBuffer::getMemBuffer(src, inpCLFileName.c_str(),
true);
ClangOptions.Src.swap(srcBufferPtr);
assert(ClangOptions.Src.get() && "ClangOCLFE: Memory Buffer"
" initialization error\n");
// Set Pre-processor output if user asks for it.
if (amdOpts && amdOpts->isDumpFlagSet(amd::option::DUMP_I)) {
ClangOptions.PreProcOut = amdOpts->getDumpFileName(".i");
}
// Set the LLVMContext for the front-end compilation.
// Clang needs to use a separate LLVMContext since the generated bitcode
// needs to be loaded again. Using the same LLVMContext causes name collision
// for named struct types in bitcode loader.
llvm::LLVMContext ClangCtx;
ClangOptions.CompilerContext = &ClangCtx;
if (amdOpts && amdOpts->isDumpFlagSet(amd::option::DUMP_CL)) {
dumpSource(src, amdOpts);
}
//Start the compilation
uint64_t start_time = 0, stop_time = 0;
if (Options()->oVariables->EnableBuildTiming) {
start_time = amd::Os::timeNanos();
}
if (!checkFlag(aclutGetCaps(Elf()), capSaveSOURCE)) {
CL()->clAPI.remSec(CL(), Elf(), aclSOURCE);
}
// Pass OpenCL version option to Clang
llvm::StringRef OCLVer(amdOpts->oVariables->CLStd);
if (OCLVer.equals("CL1.2")) {
ClangOptions.OCLVer = clc2::OCL_12;
} else if (OCLVer.equals("CL2.0")) {
ClangOptions.OCLVer = clc2::OCL_20;
} else {
llvm_unreachable("Unknown OpenCL version");
}
// Call the Clang Front-end to generate serialized llvm::Module
// from the OpenCL source.
#ifdef ANDROID
// We will not exercise Clang for RenderScript.
log_ += "\nerror: Clang front-end compilation unsupported on Android!\n";
ret |= 1;
return ret;
#else
if (!parseOCLSource(ClangOptions, argsToClang, &Source(), &logFromClang)) {
log_ += logFromClang;
log_ += "\nerror: Clang front-end compilation failed!\n";
ret |= 1;
return ret;
}
#endif
if (Options()->oVariables->EnableBuildTiming) {
stop_time = amd::Os::timeNanos();
std::stringstream tmp_ss;
tmp_ss << " OpenCL FE time: "
<< (stop_time - start_time)/1000ULL
<< "us\n";
appendLogToCL(CL(), tmp_ss.str());
}
llvmbinary_ = loadBitcode(Source());
if (!llvmbinary_) {
ret |= 1;
}
if (!ret) {
CL()->clAPI.insSec(CL(), Elf(), Source().data(), Source().size(), aclLLVMIR);
}
if (Options()->oVariables->FEGenSPIRV) {
std::string s;
llvm::raw_string_ostream ss(s);
std::string err;
if (Options()->getLLVMArgc()) {
llvm::cl::ParseCommandLineOptions(Options()->getLLVMArgc(),
Options()->getLLVMArgv(), "LLVM/SPIRV converter");
}
if (WriteSPIRV(llvmbinary_, ss, err)) {
std::string img = ss.str();
CL()->clAPI.insSec(CL(), Elf(), img.data(), img.size(), aclSPIRV);
}
if (!log_.empty())
log_ += std::string(" ");
log_ += err;
}
log_ += logFromClang;
if (isCpuTarget(Elf()->target)
&& Options()->oVariables->EnableDebug) {
Options()->sourceFileName_ = inpCLFileName;
} else {
amd::Os::unlink(inpCLFileName.c_str());
}
return ret;
}