From: Luo <[email protected]> Save the LLVMContext and module pointer to GenProgram, delete it in the destructor.
Signed-off-by: Luo <[email protected]> --- backend/src/backend/gen_program.cpp | 31 ++++++++++++++++++++--- backend/src/backend/gen_program.hpp | 4 ++- backend/src/backend/program.cpp | 50 ++++++++++++------------------------- 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, 62 insertions(+), 48 deletions(-) diff --git a/backend/src/backend/gen_program.cpp b/backend/src/backend/gen_program.cpp index 52db904..74b6fa1 100644 --- a/backend/src/backend/gen_program.cpp +++ b/backend/src/backend/gen_program.cpp @@ -22,6 +22,17 @@ * \author Benjamin Segovia <[email protected]> */ +#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> @@ -72,7 +85,17 @@ namespace gbe { fclose(f); } - GenProgram::~GenProgram(void) {} + GenProgram::~GenProgram(void){ + if(module){ + delete (llvm::Module*)module; + module = NULL; + } + + if(llvm_ctx){ + delete (llvm::LLVMContext*)llvm_ctx; + llvm_ctx = NULL; + } + } /*! We must avoid spilling at all cost with Gen */ static const struct CodeGenStrategy { @@ -177,16 +200,18 @@ 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); 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 bdc7d34..66a5ce0 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> @@ -102,9 +104,9 @@ namespace gbe { 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) { + if (llvmToGen(*unit, fileName, module, optLevel) == false) { error = std::string(fileName) + " not found"; return false; } @@ -113,7 +115,7 @@ 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. + llvmToGen(*unit, fileName, module, 0); //suppose file exists and llvmToGen will not return false. } assert(unit->getValid()); this->buildFromUnit(*unit, error); @@ -515,7 +517,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; @@ -631,7 +633,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; @@ -666,28 +668,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; } @@ -702,12 +683,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; @@ -822,7 +799,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; @@ -834,14 +814,16 @@ namespace gbe { err += *errSize; clangErrSize = *errSize; } - p = gbe_program_new_from_llvm(deviceID, llName.c_str(), stringSize, + + //llvm::Module * mod = (llvm::Module*)CloneModule(out_module); + + 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 d90ada3..a0575f8 100644 --- a/backend/src/backend/program.h +++ b/backend/src/backend/program.h @@ -119,7 +119,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; @@ -131,6 +130,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 fe945a6..2055d65 100644 --- a/backend/src/backend/program.hpp +++ b/backend/src/backend/program.hpp @@ -232,7 +232,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 184d6b5..7f302cb 100644 --- a/src/cl_program.c +++ b/src/cl_program.c @@ -225,7 +225,7 @@ cl_program_create_from_llvm(cl_context ctx, INVALID_VALUE_IF (file_name == NULL); program = cl_program_new(ctx); - program->opaque = gbe_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 = gbe_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 [email protected] http://lists.freedesktop.org/mailman/listinfo/beignet
