[Bf-blender-cvs] [37477ff] object_nodes: Ported over code from previous llvm branch for loading IR modules and linking runtime code.
Lukas Tönne
noreply at git.blender.org
Tue Apr 5 17:58:28 CEST 2016
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"
More information about the Bf-blender-cvs
mailing list