Commit: 37477ffa1ce112353887a030753f4788f8f576c5 Author: Lukas Tönne Date: Tue Apr 5 17:57:29 2016 +0200 Branches: object_nodes https://developer.blender.org/rB37477ffa1ce112353887a030753f4788f8f576c5
Ported over code from previous llvm branch for loading IR modules and linking runtime code. =================================================================== M source/blender/blenvm/llvm/llvm_codegen.cc M source/blender/blenvm/llvm/llvm_engine.cc M source/blender/blenvm/llvm/llvm_engine.h M source/blender/blenvm/llvm/llvm_headers.h =================================================================== diff --git a/source/blender/blenvm/llvm/llvm_codegen.cc b/source/blender/blenvm/llvm/llvm_codegen.cc index 2de7fdf..d751464 100644 --- a/source/blender/blenvm/llvm/llvm_codegen.cc +++ b/source/blender/blenvm/llvm/llvm_codegen.cc @@ -291,6 +291,8 @@ FunctionLLVM *LLVMCompiler::compile_function(const string &name, const NodeGraph fpm.run(*func); + llvm_link_module_full(module); + llvm_execution_engine()->finalizeObject(); uint64_t address = llvm_execution_engine()->getFunctionAddress(name); diff --git a/source/blender/blenvm/llvm/llvm_engine.cc b/source/blender/blenvm/llvm/llvm_engine.cc index 4d4fd74..c607a5e 100644 --- a/source/blender/blenvm/llvm/llvm_engine.cc +++ b/source/blender/blenvm/llvm/llvm_engine.cc @@ -29,8 +29,15 @@ * \ingroup llvm */ +#include <map> + extern "C" { +#include "BLI_fileops.h" +#include "BLI_fileops_types.h" +#include "BLI_path_util.h" #include "BLI_utildefines.h" + +#include "BKE_appdir.h" } #include "llvm_engine.h" @@ -38,8 +45,11 @@ extern "C" { namespace blenvm { +typedef std::map<string, llvm::Module*> ModuleMap; + static llvm::ExecutionEngine *theEngine = NULL; static llvm::Module *theModule = NULL; +static ModuleMap theModules; //static ModuleMap theModules; @@ -77,14 +87,12 @@ void llvm_init() theEngine = create_execution_engine(); /* load modules */ -// BJIT_load_all_modules(NULL, false); -// bjit::build_effector_module(); + llvm_load_all_modules("", false); } void llvm_free() { -// bjit::free_effector_module(); -// BJIT_unload_all_modules(); + llvm_unload_all_modules(); if (theEngine) { delete theEngine; @@ -97,4 +105,156 @@ llvm::ExecutionEngine *llvm_execution_engine() return theEngine; } +bool llvm_function_is_external(const llvm::Function *func) +{ + return func->hasFnAttribute("name"); +} + +llvm::Function *llvm_find_external_function(llvm::Module *mod, const string &name) +{ + using namespace llvm; + + for (Module::FunctionListType::iterator it = mod->getFunctionList().begin(); it != mod->getFunctionList().end(); ++it) { + Function *func = &(*it); + if (func->hasFnAttribute("name")) { + std::string value = func->getFnAttribute("name").getValueAsString(); + if (value == name) + return func; + } + } + return NULL; +} + +string llvm_get_external_function_name(llvm::Function *func) +{ + if (func->hasFnAttribute("name")) + return func->getFnAttribute("name").getValueAsString().str(); + else + return func->getName().str(); +} + +#if 0 +/* Based on + * http://homes.cs.washington.edu/~bholt/posts/llvm-quick-tricks.html + */ +static void llvm_parse_function_annotations(llvm::Module *mod) +{ + using namespace llvm; + + GlobalVariable *global_annos = mod->getNamedGlobal("llvm.global.annotations"); + if (global_annos) { + ConstantArray *a = static_cast<ConstantArray*>(global_annos->getOperand(0)); + for (int i = 0; i < a->getNumOperands(); i++) { + ConstantStruct *e = static_cast<ConstantStruct*>(a->getOperand(i)); + StringRef anno = static_cast<ConstantDataArray*>(static_cast<GlobalVariable*>(e->getOperand(1)->getOperand(0))->getOperand(0))->getAsCString(); + + Function *fn = dynamic_cast<Function*>(e->getOperand(0)->getOperand(0)); + if (fn) { + fn->addFnAttr("name", anno); /* add function annotation */ + } + } + } +} +#endif + +void llvm_load_module(const string &modfile, const string &modname) +{ + using namespace llvm; + + printf("Loading module '%s'\n", modfile.c_str()); + LLVMContext &llvmctx = getGlobalContext(); + SMDiagnostic err; + + Module *mod = getLazyIRFileModule(modfile, err, llvmctx); +// Module *mod = ParseIRFile(modfile, err, llvmctx); + if (!mod) { + err.print(modfile.c_str(), errs()); + return; + } + + printf("Module Functions for '%s'\n", mod->getModuleIdentifier().c_str()); + for (Module::FunctionListType::const_iterator it = mod->getFunctionList().begin(); it != mod->getFunctionList().end(); ++it) { + const Function &func = *it; + printf(" %s\n", func.getName().str().c_str()); + +// func.dump(); +// printf("++++++++++++++++++++++++++++++++++\n"); + } + + /* XXX this code was used to identify special node functions, + * similar to the "shader" keyword in OSL. + * Not sure if needed eventually. + */ +// bjit_parse_function_annotations(mod); + mod->setModuleIdentifier(modname); + + verifyModule(*mod, &outs()); + + theEngine->addModule(mod); + theModules[mod->getModuleIdentifier()] = mod; +} + +void llvm_load_all_modules(const string &modpath, bool reload) +{ + using namespace llvm; + + string path = modpath; + if (path.empty()) + path = string(BKE_appdir_folder_id(BLENDER_SYSTEM_SCRIPTS, "llvm/modules/")); + if (path.empty()) + return; + + if (reload) { + llvm_unload_all_modules(); + } + + struct direntry *dir; + int totfile = BLI_filelist_dir_contents(path.c_str(), &dir); + for (int i = 0; i < totfile; ++i) { + if ((dir[i].type & S_IFREG)) { + const char *filename = dir[i].relname; + const char *filepath = dir[i].path; + + if (BLI_testextensie(filename, ".ll")) { + /* found a potential llvm IR module, try parsing it */ + llvm_load_module(filepath, filename); + } + } + } + BLI_filelist_free(dir, totfile); +} + +void llvm_unload_all_modules() +{ + using namespace llvm; + + // TODO + theModules.clear(); +} + +/* links the module to all other modules in the module map */ +void llvm_link_module_full(llvm::Module *mod) +{ + using namespace llvm; + + for (ModuleMap::const_iterator it = theModules.begin(); it != theModules.end(); ++it) { + Module *lmod = it->second; + std::string error; + Linker::LinkModules(mod, lmod, Linker::LinkerMode::PreserveSource, &error); + } + +// printf("Linked Module Functions for '%s'\n", mod->getModuleIdentifier().c_str()); +// for (Module::FunctionListType::const_iterator it = mod->getFunctionList().begin(); it != mod->getFunctionList().end(); ++it) { +// printf(" %s\n", it->getName().str().c_str()); +// } + + verifyModule(*mod, &outs()); + +// PassManager *pm = create_pass_manager(); +// pm->run(*mod); +// delete pm; + + theEngine->finalizeObject(); +} + } /* namespace llvm */ diff --git a/source/blender/blenvm/llvm/llvm_engine.h b/source/blender/blenvm/llvm/llvm_engine.h index 4b2d17a..2bd34c2 100644 --- a/source/blender/blenvm/llvm/llvm_engine.h +++ b/source/blender/blenvm/llvm/llvm_engine.h @@ -32,8 +32,12 @@ * \ingroup llvm */ +#include "util_string.h" + namespace llvm { class ExecutionEngine; +class Function; +class Module; } namespace blenvm { @@ -43,6 +47,16 @@ void llvm_free(); llvm::ExecutionEngine *llvm_execution_engine(); +bool llvm_function_is_external(const llvm::Function *func); +llvm::Function *llvm_find_external_function(llvm::Module *mod, const string &name); +string llvm_get_external_function_name(llvm::Function *func); + +void llvm_load_module(const string &modfile, const string &modname); +void llvm_load_all_modules(const string &modpath, bool reload); +void llvm_unload_all_modules(); + +void llvm_link_module_full(llvm::Module *mod); + } /* namespace blenvm */ #endif /* __LLVM_ENGINE_H__ */ diff --git a/source/blender/blenvm/llvm/llvm_headers.h b/source/blender/blenvm/llvm/llvm_headers.h index 25ade33..2137f89 100644 --- a/source/blender/blenvm/llvm/llvm_headers.h +++ b/source/blender/blenvm/llvm/llvm_headers.h @@ -42,6 +42,7 @@ #include "llvm/IR/IRPrintingPasses.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/TypeBuilder.h" +#include "llvm/IR/Verifier.h" #include "llvm/Linker/Linker.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/raw_ostream.h" _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs