summaryrefslogtreecommitdiff
path: root/backend/src
diff options
context:
space:
mode:
authorLuo <xionghu.luo@intel.com>2014-06-13 11:17:38 +0800
committerZhigang Gong <zhigang.gong@intel.com>2014-06-13 17:20:25 +0800
commit5ff5d6ce93ee28a677f6cc782716d463d1c9c049 (patch)
treece507b2a37921cee37c5e32dd706085528d2163d /backend/src
parent8d25175926bd4e8437e69a3991b5bd1994f3dc35 (diff)
add [opencl-1.2] API clLinkProgram.
this API links a set of compiled program objects and libraries for all the devices or a specific device(s) in the OpenCL context and creates an executable. the llvm bitcode in the compiled program objects are linked together and built to Gen binary. Signed-off-by: Luo <xionghu.luo@intel.com> Reviewed-by: "Song, Ruiling" <ruiling.song@intel.com> Conflicts: src/cl_gbe_loader.h
Diffstat (limited to 'backend/src')
-rw-r--r--backend/src/backend/gen_program.cpp84
-rw-r--r--backend/src/backend/program.cpp26
-rw-r--r--backend/src/backend/program.h28
3 files changed, 134 insertions, 4 deletions
diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp
index 1700bfeb..300741ee 100644
--- a/backend/src/backend/gen_program.cpp
+++ b/backend/src/backend/gen_program.cpp
@@ -33,6 +33,9 @@
#include "llvm/IR/DataLayout.h"
#endif /* LLVM_VERSION_MINOR <= 2 */
+#include "llvm/Linker.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+
#include "backend/program.h"
#include "backend/gen_program.h"
#include "backend/gen_program.hpp"
@@ -51,6 +54,7 @@
#include <memory>
#include <iostream>
#include <fstream>
+#include <mutex>
namespace gbe {
@@ -250,6 +254,84 @@ namespace gbe {
// Everything run fine
return (gbe_program) program;
}
+
+ static void genProgramLinkFromLLVM(gbe_program dst_program,
+ gbe_program src_program,
+ size_t stringSize,
+ char * err,
+ size_t * errSize)
+ {
+#ifdef GBE_COMPILER_AVAILABLE
+ using namespace gbe;
+ std::string errMsg;
+ if(((GenProgram*)dst_program)->module == NULL){
+ ((GenProgram*)dst_program)->module = llvm::CloneModule((llvm::Module*)((GenProgram*)src_program)->module);
+ errSize = 0;
+ }else{
+ //set the global variables and functions to link once to fix redefine.
+ llvm::Module* src = (llvm::Module*)((GenProgram*)src_program)->module;
+ for (llvm::Module::global_iterator I = src->global_begin(), E = src->global_end(); I != E; ++I) {
+ I->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
+ }
+
+ for (llvm::Module::iterator I = src->begin(), E = src->end(); I != E; ++I) {
+ I->setLinkage(llvm::GlobalValue::LinkOnceAnyLinkage);
+ }
+
+ llvm::Module* dst = (llvm::Module*)((GenProgram*)dst_program)->module;
+ llvm::Linker::LinkModules( dst,
+ src,
+ llvm::Linker::PreserveSource,
+ &errMsg);
+ if (errMsg.c_str() != NULL) {
+ if (err != NULL && errSize != NULL && stringSize > 0u) {
+ if(errMsg.length() < stringSize )
+ stringSize = errMsg.length();
+ strcpy(err, errMsg.c_str());
+ err[stringSize+1] = '\0';
+ }
+ }
+ }
+ // Everything run fine
+#endif
+ }
+
+ static void genProgramBuildFromLLVM(gbe_program program,
+ size_t stringSize,
+ char *err,
+ size_t *errSize,
+ const char * options)
+ {
+#ifdef GBE_COMPILER_AVAILABLE
+ using namespace gbe;
+ std::string error;
+
+ int optLevel = 1;
+
+ if(options) {
+ char *p;
+ p = strstr(const_cast<char *>(options), "-cl-opt-disable");
+ if (p)
+ optLevel = 0;
+ }
+
+ GenProgram* p = (GenProgram*) program;
+ // Try to compile the program
+ acquireLLVMContextLock();
+ llvm::Module* module = (llvm::Module*)p->module;
+
+ if (p->buildFromLLVMFile(NULL, module, error, optLevel) == false) {
+ if (err != NULL && errSize != NULL && stringSize > 0u) {
+ const size_t msgSize = std::min(error.size(), stringSize-1u);
+ std::memcpy(err, error.c_str(), msgSize);
+ *errSize = error.size();
+ }
+ GBE_DELETE(p);
+ }
+ releaseLLVMContextLock();
+#endif
+ }
+
} /* namespace gbe */
void genSetupCallBacks(void)
@@ -258,4 +340,6 @@ void genSetupCallBacks(void)
gbe_program_serialize_to_binary = gbe::genProgramSerializeToBinary;
gbe_program_new_from_llvm = gbe::genProgramNewFromLLVM;
gbe_program_new_gen_program = gbe::genProgramNewGenProgram;
+ gbe_program_link_from_llvm = gbe::genProgramLinkFromLLVM;
+ gbe_program_build_from_llvm = gbe::genProgramBuildFromLLVM;
}
diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp
index e225bb27..7432cc35 100644
--- a/backend/src/backend/program.cpp
+++ b/backend/src/backend/program.cpp
@@ -888,18 +888,14 @@ namespace gbe {
if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, clOpt.c_str(),
stringSize, err, errSize)) {
// Now build the program from llvm
- size_t clangErrSize = 0;
if (err != NULL) {
GBE_ASSERT(errSize != NULL);
stringSize -= *errSize;
err += *errSize;
- clangErrSize = *errSize;
}
p = gbe_program_new_gen_program(deviceID, out_module, NULL);
- if (err != NULL)
- *errSize += clangErrSize;
if (OCL_OUTPUT_BUILD_LOG && options)
llvm::errs() << options;
} else
@@ -910,6 +906,24 @@ namespace gbe {
}
#endif
+#ifdef GBE_COMPILER_AVAILABLE
+ static void programLinkProgram(gbe_program dst_program,
+ gbe_program src_program,
+ size_t stringSize,
+ char * err,
+ size_t * errSize)
+ {
+ acquireLLVMContextLock();
+
+ gbe_program_link_from_llvm(dst_program, src_program, stringSize, err, errSize);
+
+ releaseLLVMContextLock();
+
+ if (OCL_OUTPUT_BUILD_LOG && err)
+ llvm::errs() << err;
+ }
+#endif
+
static size_t programGetGlobalConstantSize(gbe_program gbeProgram) {
if (gbeProgram == NULL) return 0;
const gbe::Program *program = (const gbe::Program*) gbeProgram;
@@ -1120,10 +1134,13 @@ void releaseLLVMContextLock()
GBE_EXPORT_SYMBOL gbe_program_new_from_source_cb *gbe_program_new_from_source = NULL;
GBE_EXPORT_SYMBOL gbe_program_compile_from_source_cb *gbe_program_compile_from_source = NULL;
+GBE_EXPORT_SYMBOL gbe_program_link_program_cb *gbe_program_link_program = NULL;
GBE_EXPORT_SYMBOL gbe_program_new_from_binary_cb *gbe_program_new_from_binary = NULL;
GBE_EXPORT_SYMBOL gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary = NULL;
GBE_EXPORT_SYMBOL gbe_program_new_from_llvm_cb *gbe_program_new_from_llvm = NULL;
GBE_EXPORT_SYMBOL gbe_program_new_gen_program_cb *gbe_program_new_gen_program = NULL;
+GBE_EXPORT_SYMBOL gbe_program_link_from_llvm_cb *gbe_program_link_from_llvm = NULL;
+GBE_EXPORT_SYMBOL gbe_program_build_from_llvm_cb *gbe_program_build_from_llvm = NULL;
GBE_EXPORT_SYMBOL gbe_program_get_global_constant_size_cb *gbe_program_get_global_constant_size = NULL;
GBE_EXPORT_SYMBOL gbe_program_get_global_constant_data_cb *gbe_program_get_global_constant_data = NULL;
GBE_EXPORT_SYMBOL gbe_program_delete_cb *gbe_program_delete = NULL;
@@ -1168,6 +1185,7 @@ namespace gbe
CallBackInitializer(void) {
gbe_program_new_from_source = gbe::programNewFromSource;
gbe_program_compile_from_source = gbe::programCompileFromSource;
+ gbe_program_link_program = gbe::programLinkProgram;
gbe_program_get_global_constant_size = gbe::programGetGlobalConstantSize;
gbe_program_get_global_constant_data = gbe::programGetGlobalConstantData;
gbe_program_delete = gbe::programDelete;
diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h
index 7ddbd22b..e410221e 100644
--- a/backend/src/backend/program.h
+++ b/backend/src/backend/program.h
@@ -151,6 +151,13 @@ typedef gbe_program (gbe_program_compile_from_source_cb)(uint32_t deviceID,
char *err,
size_t *err_size);
extern gbe_program_compile_from_source_cb *gbe_program_compile_from_source;
+/*! link the programs. */
+typedef void (gbe_program_link_program_cb)(gbe_program dst_program,
+ gbe_program src_program,
+ size_t stringSize,
+ char * err,
+ size_t * errSize);
+extern gbe_program_link_program_cb *gbe_program_link_program;
/*! create s new genprogram for link. */
typedef gbe_program (gbe_program_new_gen_program_cb)(uint32_t deviceID,
@@ -177,6 +184,27 @@ typedef gbe_program (gbe_program_new_from_llvm_cb)(uint32_t deviceID,
int optLevel);
extern gbe_program_new_from_llvm_cb *gbe_program_new_from_llvm;
+/*! create s new genprogram for link. */
+typedef gbe_program (gbe_program_new_gen_program_cb)(uint32_t deviceID,
+ const void *module,
+ const void *act);
+extern gbe_program_new_gen_program_cb *gbe_program_new_gen_program;
+
+/*! link the programs from llvm level. */
+typedef void (gbe_program_link_from_llvm_cb)(gbe_program dst_program,
+ gbe_program src_program,
+ size_t stringSize,
+ char * err,
+ size_t * errSize);
+extern gbe_program_link_from_llvm_cb *gbe_program_link_from_llvm;
+/* build the program to gen binary */
+typedef void gbe_program_build_from_llvm_cb(gbe_program program,
+ size_t stringSize,
+ char *err,
+ size_t *errSize,
+ const char * options);
+extern gbe_program_build_from_llvm_cb *gbe_program_build_from_llvm;
+
/*! Get the size of global constants */
typedef size_t (gbe_program_get_global_constant_size_cb)(gbe_program gbeProgram);
extern gbe_program_get_global_constant_size_cb *gbe_program_get_global_constant_size;