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

Reply via email to