[Bf-blender-cvs] [ff6673d] object_nodes: Type generation for LLVM based on node socket types.

Lukas Tönne noreply at git.blender.org
Tue Apr 5 11:06:01 CEST 2016


Commit: ff6673d8b80d969cbdd98402a347fe7e2175fb97
Author: Lukas Tönne
Date:   Tue Apr 5 10:16:57 2016 +0200
Branches: object_nodes
https://developer.blender.org/rBff6673d8b80d969cbdd98402a347fe7e2175fb97

Type generation for LLVM based on node socket types.

Currently every socket stores a complete and unique type definition.
This should be changed to module-level type declarations and referencing by name.

===================================================================

M	source/blender/blenvm/llvm/llvm_codegen.cc
M	source/blender/blenvm/llvm/llvm_codegen.h

===================================================================

diff --git a/source/blender/blenvm/llvm/llvm_codegen.cc b/source/blender/blenvm/llvm/llvm_codegen.cc
index 560c19b..dde5e11 100644
--- a/source/blender/blenvm/llvm/llvm_codegen.cc
+++ b/source/blender/blenvm/llvm/llvm_codegen.cc
@@ -30,6 +30,7 @@
  */
 
 #include <set>
+#include <sstream>
 
 #include "nodegraph.h"
 
@@ -38,8 +39,86 @@
 #include "llvm_function.h"
 #include "llvm_headers.h"
 
+/* TypeBuilder specializations for own structs */
+
+namespace llvm {
+
+template <bool xcompile>
+class TypeBuilder<blenvm::float3, xcompile> {
+public:
+	static StructType *get(LLVMContext &context) {
+		return StructType::get(
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            NULL);
+	}
+	
+	enum Fields {
+		FIELD_X = 0,
+		FIELD_Y = 1,
+		FIELD_Z = 2,
+	};
+};
+
+template <bool xcompile>
+class TypeBuilder<blenvm::float4, xcompile> {
+public:
+	static StructType *get(LLVMContext &context) {
+		return StructType::get(
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            TypeBuilder<types::ieee_float, xcompile>::get(context),
+		            NULL);
+	}
+	
+	enum Fields {
+		FIELD_X = 0,
+		FIELD_Y = 1,
+		FIELD_Z = 2,
+		FIELD_W = 3,
+	};
+};
+
+template <bool xcompile>
+class TypeBuilder<blenvm::matrix44, xcompile> {
+public:
+	static StructType *get(LLVMContext &context) {
+		return StructType::get(
+		            ArrayType::get(
+		                ArrayType::get(
+		                    TypeBuilder<types::ieee_float, xcompile>::get(context),
+		                    4),
+		                4),
+		            NULL);
+	}
+};
+
+} /* namespace llvm */
+
+
 namespace blenvm {
 
+/* XXX Should eventually declare and reference types by name,
+ * rather than storing full TypeDesc in each socket!
+ * These functions just provides per-socket type names in the meantime.
+ */
+static string dummy_type_name(const InputKey &input)
+{
+	size_t hash = std::hash<const NodeInstance *>()(input.node) ^ std::hash<const NodeInput *>()(input.socket);
+	std::stringstream ss;
+	ss << "InputType" << (unsigned short)hash;
+	return ss.str();
+}
+static string dummy_type_name(const OutputKey &output)
+{
+	size_t hash = std::hash<const NodeInstance *>()(output.node) ^ std::hash<const NodeOutput *>()(output.socket);
+	std::stringstream ss;
+	ss << "OutputType" << (unsigned short)hash;
+	return ss.str();
+}
+
 LLVMCompiler::LLVMCompiler()
 {
 }
@@ -48,11 +127,47 @@ LLVMCompiler::~LLVMCompiler()
 {
 }
 
-llvm::Type *LLVMCompiler::codegen_typedesc(TypeDesc *td)
+llvm::LLVMContext &LLVMCompiler::context() const
+{
+	return llvm::getGlobalContext();
+}
+
+llvm::Type *LLVMCompiler::codegen_typedesc(const string &name, const TypeDesc *td)
 {
 	using namespace llvm;
 	
-	// TODO
+	if (td->is_structure()) {
+		const StructSpec *s = td->structure();
+		std::vector<Type*> elemtypes;
+		for (int i = 0; i < s->num_fields(); ++s) {
+			Type *ftype = codegen_typedesc(s->field(i).name, &s->field(i).typedesc);
+			elemtypes.push_back(ftype);
+		}
+		
+		StructType *stype = StructType::create(context(), ArrayRef<Type*>(elemtypes), name);
+		return stype;
+	}
+	else {
+		switch (td->base_type()) {
+			case BVM_FLOAT:
+				return TypeBuilder<types::ieee_float, true>::get(context());
+			case BVM_FLOAT3:
+				return TypeBuilder<float3, true>::get(context());
+			case BVM_FLOAT4:
+				return TypeBuilder<float4, true>::get(context());
+			case BVM_INT:
+				return TypeBuilder<types::i<32>, true>::get(context());
+			case BVM_MATRIX44:
+				return TypeBuilder<matrix44, true>::get(context());
+				
+			case BVM_STRING:
+			case BVM_RNAPOINTER:
+			case BVM_MESH:
+			case BVM_DUPLIS:
+				/* TODO */
+				return NULL;
+		}
+	}
 	return NULL;
 }
 
@@ -60,47 +175,36 @@ llvm::FunctionType *LLVMCompiler::codegen_node_function_type(const NodeGraph &gr
 {
 	using namespace llvm;
 	
-	LLVMContext &context = getGlobalContext();
-	
 	std::vector<Type *> input_types, output_types;
 	
-#if 0
 	for (int i = 0; i < graph.outputs.size(); ++i) {
-#if 0 // TODO
 		const NodeGraph::Output &output = graph.outputs[i];
-		Type *type = bjit_get_socket_llvm_type(output.type, context, module);
+		Type *type = codegen_typedesc(dummy_type_name(output.key), &output.typedesc);
 		output_types.push_back(type);
-#endif
 	}
-	StructType *return_type = StructType::get(context, output_types);
+	StructType *return_type = StructType::get(context(), output_types);
 	
 	input_types.push_back(PointerType::get(return_type, 0));
 	for (int i = 0; i < graph.inputs.size(); ++i) {
-#if 0 // TODO
 		const NodeGraph::Input &input = graph.inputs[i];
-		Type *type = bjit_get_socket_llvm_type(input.type, context, module);
-		type = PointerType::get(type, 0);
+		Type *type = codegen_typedesc(dummy_type_name(input.key), &input.typedesc);
+//		type = PointerType::get(type, 0);
 		input_types.push_back(type);
-#endif
 	}
-#endif
 	
-	return FunctionType::get(TypeBuilder<void, true>::get(context), input_types, false);
+	return FunctionType::get(TypeBuilder<void, true>::get(context()), input_types, false);
 }
 
 llvm::Function *LLVMCompiler::codegen_node_function(const string &name, const NodeGraph &graph, llvm::Module *module)
 {
 	using namespace llvm;
 	
-	LLVMContext &context = getGlobalContext();
-	IRBuilder<> builder(context);
+	IRBuilder<> builder(context());
 	
 	FunctionType *functype = codegen_node_function_type(graph);
-//	Function *func = Function::Create(functype, Function::ExternalLinkage, name, module);
 	Function *func = llvm::cast<Function>(module->getOrInsertFunction(name, functype));
-#if 0
 	Argument *retarg = func->getArgumentList().begin();
-	retarg->addAttr(AttributeSet::get(context, AttributeSet::ReturnIndex, Attribute::StructRet));
+	retarg->addAttr(AttributeSet::get(context(), AttributeSet::ReturnIndex, Attribute::StructRet));
 	
 	int num_inputs = graph.inputs.size();
 	int num_outputs = graph.outputs.size();
@@ -111,16 +215,15 @@ llvm::Function *LLVMCompiler::codegen_node_function(const string &name, const No
 	}
 	
 	Function::ArgumentListType::iterator it = func->getArgumentList().begin();
-//	++it; /* skip return arg */
+	++it; /* skip return arg */
 	for (int i = 0; i < num_inputs; ++i) {
 //		Argument *arg = &(*it++);
 //		const NodeGraph::Input &input = graph.inputs[i];
 		
 //		graph.set_input_argument(input.name, arg);
 	}
-#endif
 	
-	BasicBlock *entry = BasicBlock::Create(context, "entry", func);
+	BasicBlock *entry = BasicBlock::Create(context(), "entry", func);
 	builder.SetInsertPoint(entry);
 	
 #if 0 // TODO
@@ -134,9 +237,8 @@ llvm::Function *LLVMCompiler::codegen_node_function(const string &name, const No
 	}
 #endif
 	
-#if 0
 	for (int i = 0; i < num_outputs; ++i) {
-		Value *retptr = builder.CreateStructGEP(retarg, i);
+//		Value *retptr = builder.CreateStructGEP(retarg, i);
 		
 #if 0 // TODO
 		const NodeGraph::Output &output = graph.outputs[i];
@@ -153,7 +255,6 @@ llvm::Function *LLVMCompiler::codegen_node_function(const string &name, const No
 		builder.CreateStore(retval, retptr);
 #endif
 	}
-#endif
 	
 	builder.CreateRetVoid();
 	
@@ -164,12 +265,16 @@ FunctionLLVM *LLVMCompiler::compile_function(const string &name, const NodeGraph
 {
 	using namespace llvm;
 	
-	Module *module = new Module(name, getGlobalContext());
+	Module *module = new Module(name, context());
 	llvm_execution_engine()->addModule(module);
 	
 	Function *func = codegen_node_function(name, graph, module);
 	assert(func != NULL && "codegen_node_function returned NULL!");
 	
+	printf("=== NODE FUNCTION ===\n");
+	func->dump();
+	printf("=====================\n");
+	
 	FunctionPassManager fpm(module);
 	PassManagerBuilder builder;
 	builder.OptLevel = 0;
diff --git a/source/blender/blenvm/llvm/llvm_codegen.h b/source/blender/blenvm/llvm/llvm_codegen.h
index d764c17..f23ed37 100644
--- a/source/blender/blenvm/llvm/llvm_codegen.h
+++ b/source/blender/blenvm/llvm/llvm_codegen.h
@@ -43,6 +43,7 @@
 #include "util_string.h"
 
 namespace llvm {
+class LLVMContext;
 class Function;
 class FunctionType;
 class Module;
@@ -63,9 +64,11 @@ struct LLVMCompiler {
 	FunctionLLVM *compile_function(const string &name, const NodeGraph &graph);
 	
 protected:
+	llvm::LLVMContext &context() const;
+	
 	llvm::FunctionType *codegen_node_function_type(const NodeGraph &graph);
 	llvm::Function *codegen_node_function(const string &name, const NodeGraph &graph, llvm::Module *module);
-	llvm::Type *codegen_typedesc(TypeDesc *td);
+	llvm::Type *codegen_typedesc(const string &name, const TypeDesc *td);
 };
 
 } /* namespace blenvm */




More information about the Bf-blender-cvs mailing list