[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