I would move some common code outside from function programNewFromSource, so please pend for the V3 update.
Luo Xionghu Best Regards -----Original Message----- From: Song, Ruiling Sent: Friday, June 06, 2014 4:28 PM To: Luo, Xionghu; beignet@lists.freedesktop.org Cc: Luo, Xionghu Subject: RE: [Beignet] [PATCH V2] remove the code of saving the llvm bitcode to file, replace it with llvm::Module The patch looks good to me. Thanks! -----Original Message----- From: Beignet [mailto:beignet-boun...@lists.freedesktop.org] On Behalf Of xionghu....@intel.com Sent: Thursday, June 05, 2014 8:01 AM To: beignet@lists.freedesktop.org Cc: Luo, Xionghu Subject: [Beignet] [PATCH V2] remove the code of saving the llvm bitcode to file, replace it with llvm::Module From: Luo <xionghu....@intel.com> Save the global LLVMContext and module pointer to GenProgram, delete the module pointer in the destructor. Signed-off-by: Luo <xionghu....@intel.com> --- backend/src/backend/gen_program.cpp | 33 +++++++++++++++++++-- backend/src/backend/gen_program.hpp | 4 ++- backend/src/backend/program.cpp | 59 ++++++++++++++++--------------------- backend/src/backend/program.h | 3 +- backend/src/backend/program.hpp | 2 +- backend/src/llvm/llvm_to_gen.cpp | 16 ++++++---- backend/src/llvm/llvm_to_gen.hpp | 2 +- src/cl_program.c | 2 +- 8 files changed, 73 insertions(+), 48 deletions(-) diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp index d2e95d4..33f2ed6 100644 --- a/backend/src/backend/gen_program.cpp +++ b/backend/src/backend/gen_program.cpp @@ -22,6 +22,17 @@ * \author Benjamin Segovia <benjamin.sego...@intel.com> */ +#include "llvm/Config/config.h" +#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR <= 2 #include +"llvm/LLVMContext.h" +#include "llvm/Module.h" +#include "llvm/DataLayout.h" +#else +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/DataLayout.h" +#endif /* LLVM_VERSION_MINOR <= 2 */ + #include "backend/program.h" #include "backend/gen_program.h" #include "backend/gen_program.hpp" @@ -33,6 +44,8 @@ #include "ir/unit.hpp" #include "llvm/llvm_to_gen.hpp" +#include <clang/CodeGen/CodeGenAction.h> + #include <cstring> #include <sstream> #include <memory> @@ -74,7 +87,19 @@ namespace gbe { #endif } - GenProgram::~GenProgram(void) {} + GenProgram::~GenProgram(void){ +#ifdef GBE_COMPILER_AVAILABLE + if(module){ + delete (llvm::Module*)module; + module = NULL; + } + + if(llvm_ctx){ + delete (llvm::LLVMContext*)llvm_ctx; + llvm_ctx = NULL; + } +#endif + } /*! We must avoid spilling at all cost with Gen */ static const struct CodeGenStrategy { @@ -182,17 +207,19 @@ namespace gbe { static gbe_program genProgramNewFromLLVM(uint32_t deviceID, const char *fileName, + const void* module, + const void* llvm_ctx, size_t stringSize, char *err, size_t *errSize, int optLevel) { using namespace gbe; - GenProgram *program = GBE_NEW(GenProgram, deviceID); + GenProgram *program = GBE_NEW(GenProgram, deviceID, module, + llvm_ctx); #ifdef GBE_COMPILER_AVAILABLE std::string error; // Try to compile the program - if (program->buildFromLLVMFile(fileName, error, optLevel) == false) { + if (program->buildFromLLVMFile(fileName, 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); diff --git a/backend/src/backend/gen_program.hpp b/backend/src/backend/gen_program.hpp index ea54b49..70794c9 100644 --- a/backend/src/backend/gen_program.hpp +++ b/backend/src/backend/gen_program.hpp @@ -58,7 +58,7 @@ namespace gbe { public: /*! Create an empty program */ - GenProgram(uint32_t deviceID) : deviceID(deviceID) {} + GenProgram(uint32_t deviceID, const void* mod = NULL, const void* + ctx = NULL) : deviceID(deviceID),module((void*)mod), + llvm_ctx((void*)ctx) {} /*! Current device ID*/ uint32_t deviceID; /*! Destroy the program */ @@ -69,6 +69,8 @@ namespace gbe virtual Kernel *allocateKernel(const std::string &name) { return GBE_NEW(GenKernel, name); } + void* module; + void* llvm_ctx; /*! Use custom allocators */ GBE_CLASS(GenProgram); }; diff --git a/backend/src/backend/program.cpp b/backend/src/backend/program.cpp index 949aeb4..26d9454 100644 --- a/backend/src/backend/program.cpp +++ b/backend/src/backend/program.cpp @@ -34,6 +34,8 @@ #include "llvm/Config/config.h" #include "llvm/Support/Threading.h" #include "llvm/Support/ManagedStatic.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/IR/LLVMContext.h" #include <cstring> #include <algorithm> #include <fstream> @@ -103,9 +105,13 @@ namespace gbe { #ifdef GBE_COMPILER_AVAILABLE BVAR(OCL_OUTPUT_GEN_IR, false); - bool Program::buildFromLLVMFile(const char *fileName, std::string &error, int optLevel) { + bool Program::buildFromLLVMFile(const char *fileName, const void* + module, std::string &error, int optLevel) { ir::Unit *unit = new ir::Unit(); - if (llvmToGen(*unit, fileName, optLevel) == false) { + llvm::Module * cloned_module = NULL; + if(module){ + cloned_module = llvm::CloneModule((llvm::Module*)module); + } + if (llvmToGen(*unit, fileName, module, optLevel) == false) { error = std::string(fileName) + " not found"; return false; } @@ -114,11 +120,18 @@ namespace gbe { if(!unit->getValid()) { delete unit; //clear unit unit = new ir::Unit(); - llvmToGen(*unit, fileName, 0); //suppose file exists and llvmToGen will not return false. + if(cloned_module){ + llvmToGen(*unit, fileName, cloned_module, 0); //suppose file exists and llvmToGen will not return false. + }else{ + llvmToGen(*unit, fileName, module, 0); //suppose file exists and llvmToGen will not return false. + } } assert(unit->getValid()); this->buildFromUnit(*unit, error); delete unit; + if(cloned_module){ + delete (llvm::Module*) cloned_module; + } return true; } @@ -518,7 +531,7 @@ namespace gbe { SVAR(OCL_PCH_PATH, PCH_OBJECT_DIR); SVAR(OCL_PCM_PATH, PCM_OBJECT_DIR); - static bool buildModuleFromSource(const char* input, const char* output, std::string options, + static bool buildModuleFromSource(const char* input, llvm::Module** + out_module, llvm::LLVMContext* llvm_ctx, std::string options, size_t stringSize, char *err, size_t *errSize) { // Arguments to pass to the clang frontend vector<const char *> args; @@ -634,7 +647,7 @@ namespace gbe { } // Create an action and make the compiler instance carry it out - llvm::OwningPtr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction()); + llvm::OwningPtr<clang::CodeGenAction> Act(new + clang::EmitLLVMOnlyAction(llvm_ctx)); std::string dirs = OCL_PCM_PATH; std::string pcmFileName; @@ -669,28 +682,7 @@ namespace gbe { llvm::Module *module = Act->takeModule(); -#if (LLVM_VERSION_MAJOR == 3) && (LLVM_VERSION_MINOR > 3) - auto mode = llvm::sys::fs::F_Binary; -#else - auto mode = llvm::raw_fd_ostream::F_Binary; -#endif - llvm::raw_fd_ostream OS(output, ErrorString, mode); - //still write to temp file for code simply, otherwise need add another function. - //because gbe_program_new_from_llvm also be used by cl_program_create_from_llvm, can't be removed - //TODO: Pass module to llvmToGen, if use module, should return Act and use OwningPtr out of this funciton - llvm::WriteBitcodeToFile(module, OS); - if (err != NULL && *errSize < stringSize - 1 && ErrorString.size() > 0) { - size_t errLen; - errLen = ErrorString.copy(err + *errSize, stringSize - *errSize - 1, 0); - *errSize += errLen; - } - - if (err == NULL || OCL_OUTPUT_BUILD_LOG) { - // flush the error messages to the errs() if there is no - // error string buffer. - llvm::errs() << ErrorString; - } - OS.close(); + *out_module = module; return true; } @@ -705,12 +697,8 @@ namespace gbe { size_t *errSize) { char clStr[] = "/tmp/XXXXXX.cl"; - char llStr[] = "/tmp/XXXXXX.ll"; int clFd = mkstemps(clStr, 3); - int llFd = mkstemps(llStr, 3); - close(llFd); const std::string clName = std::string(clStr); - const std::string llName = std::string(llStr); std::string clOpt; int optLevel = 1; @@ -825,7 +813,10 @@ namespace gbe { fclose(clFile); gbe_program p; - if (buildModuleFromSource(clName.c_str(), llName.c_str(), clOpt.c_str(), + // will delete the module and act in the destructor of GenProgram. + llvm::Module * out_module; + llvm::LLVMContext* llvm_ctx = new llvm::LLVMContext; + if (buildModuleFromSource(clName.c_str(), &out_module, llvm_ctx, + clOpt.c_str(), stringSize, err, errSize)) { // Now build the program from llvm static std::mutex gbe_mutex; @@ -837,14 +828,14 @@ namespace gbe { err += *errSize; clangErrSize = *errSize; } - p = gbe_program_new_from_llvm(deviceID, llName.c_str(), stringSize, + + p = gbe_program_new_from_llvm(deviceID, NULL, out_module, + llvm_ctx, stringSize, err, errSize, optLevel); if (err != NULL) *errSize += clangErrSize; gbe_mutex.unlock(); if (OCL_OUTPUT_BUILD_LOG && options) llvm::errs() << options; - remove(llName.c_str()); } else p = NULL; remove(clName.c_str()); diff --git a/backend/src/backend/program.h b/backend/src/backend/program.h index 8727966..5c72964 100644 --- a/backend/src/backend/program.h +++ b/backend/src/backend/program.h @@ -120,7 +120,6 @@ typedef gbe_program (gbe_program_new_from_source_cb)(uint32_t deviceID, char *err, size_t *err_size); extern gbe_program_new_from_source_cb *gbe_program_new_from_source; - /*! Create a new program from the given blob */ typedef gbe_program (gbe_program_new_from_binary_cb)(uint32_t deviceID, const char *binary, size_t size); extern gbe_program_new_from_binary_cb *gbe_program_new_from_binary; @@ -132,6 +131,8 @@ extern gbe_program_serialize_to_binary_cb *gbe_program_serialize_to_binary; /*! Create a new program from the given LLVM file */ typedef gbe_program (gbe_program_new_from_llvm_cb)(uint32_t deviceID, const char *fileName, + const void *module, + const void + *llvm_ctx, size_t string_size, char *err, size_t *err_size, diff --git a/backend/src/backend/program.hpp b/backend/src/backend/program.hpp index 6bb1529..1235d51 100644 --- a/backend/src/backend/program.hpp +++ b/backend/src/backend/program.hpp @@ -234,7 +234,7 @@ namespace gbe { /*! Build a program from a ir::Unit */ bool buildFromUnit(const ir::Unit &unit, std::string &error); /*! Buils a program from a LLVM source code */ - bool buildFromLLVMFile(const char *fileName, std::string &error, int optLevel); + bool buildFromLLVMFile(const char *fileName, const void* module, + std::string &error, int optLevel); /*! Buils a program from a OCL string */ bool buildFromSource(const char *source, std::string &error); /*! Get size of the global constant arrays */ diff --git a/backend/src/llvm/llvm_to_gen.cpp b/backend/src/llvm/llvm_to_gen.cpp index 9282b3f..2bb9da1 100644 --- a/backend/src/llvm/llvm_to_gen.cpp +++ b/backend/src/llvm/llvm_to_gen.cpp @@ -61,6 +61,8 @@ #include "sys/cvar.hpp" #include "sys/platform.hpp" +#include <clang/CodeGen/CodeGenAction.h> + #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> @@ -163,10 +165,8 @@ namespace gbe MPM.run(mod); } - bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel) + bool llvmToGen(ir::Unit &unit, const char *fileName,const void* + module, int optLevel) { - // Get the global LLVM context - llvm::LLVMContext& c = llvm::getGlobalContext(); std::string errInfo; std::unique_ptr<llvm::raw_fd_ostream> o = NULL; if (OCL_OUTPUT_LLVM_BEFORE_EXTRA_PASS || OCL_OUTPUT_LLVM) @@ -175,9 +175,13 @@ namespace gbe // Get the module from its file llvm::SMDiagnostic Err; std::auto_ptr<Module> M; - M.reset(ParseIRFile(fileName, Err, c)); - if (M.get() == 0) return false; - Module &mod = *M.get(); + if(fileName){ + // only when module is null, Get the global LLVM context + llvm::LLVMContext& c = llvm::getGlobalContext(); + M.reset(ParseIRFile(fileName, Err, c)); + if (M.get() == 0) return false; + } + Module &mod = (module!=NULL)?*(llvm::Module*)module:*M.get(); Triple TargetTriple(mod.getTargetTriple()); TargetLibraryInfo *libraryInfo = new TargetLibraryInfo(TargetTriple); diff --git a/backend/src/llvm/llvm_to_gen.hpp b/backend/src/llvm/llvm_to_gen.hpp index 50ea267..41e3477 100644 --- a/backend/src/llvm/llvm_to_gen.hpp +++ b/backend/src/llvm/llvm_to_gen.hpp @@ -32,7 +32,7 @@ namespace gbe { /*! Convert the LLVM IR code to a GEN IR code, optLevel 0 equal to clang -O1 and 1 equal to clang -O2*/ - bool llvmToGen(ir::Unit &unit, const char *fileName, int optLevel); + bool llvmToGen(ir::Unit &unit, const char *fileName, const void* + module, int optLevel); } /* namespace gbe */ diff --git a/src/cl_program.c b/src/cl_program.c index af9d21e..42058e8 100644 --- a/src/cl_program.c +++ b/src/cl_program.c @@ -226,7 +226,7 @@ cl_program_create_from_llvm(cl_context ctx, INVALID_VALUE_IF (file_name == NULL); program = cl_program_new(ctx); - program->opaque = compiler_program_new_from_llvm(ctx->device->vendor_id, file_name, program->build_log_max_sz, program->build_log, &program->build_log_sz, 1); + program->opaque = + compiler_program_new_from_llvm(ctx->device->vendor_id, file_name, + NULL, NULL, program->build_log_max_sz, program->build_log, + &program->build_log_sz, 1); if (UNLIKELY(program->opaque == NULL)) { err = CL_INVALID_PROGRAM; goto error; -- 1.8.1.2 _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/beignet _______________________________________________ Beignet mailing list Beignet@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/beignet