[Bf-blender-cvs] [d02c7ee] object_nodes: Generate function calls for every node, using code defined in precompiled modules.

Lukas Tönne noreply at git.blender.org
Wed Apr 6 17:58:47 CEST 2016


Commit: d02c7eeacb78eaa8c5984d2a67006a13d25daa8f
Author: Lukas Tönne
Date:   Wed Apr 6 17:52:34 2016 +0200
Branches: object_nodes
https://developer.blender.org/rBd02c7eeacb78eaa8c5984d2a67006a13d25daa8f

Generate function calls for every node, using code defined in precompiled modules.

Note that this is currently not quite working: The clang compiler call used
tentatively for generating the LLVM IR code for modules uses a lowering pass to
coerce struct data types (such as float3) according to the target ABI. This should
be avoided and is unnecessary for our purposes, since we stitch together and optimize
these code fragments ourselves. In principle we could avoid using a C compiler altogether
and write this stuff by hand, but the point of using the compiler is to avoid this tedious
work. More info:
http://stackoverflow.com/questions/22776391/why-does-clang-coerce-struct-parameters-to-ints

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

M	source/blender/blenvm/compile/node_graph.cc
M	source/blender/blenvm/llvm/CMakeLists.txt
M	source/blender/blenvm/llvm/llvm_codegen.cc
M	source/blender/blenvm/llvm/llvm_codegen.h
M	source/blender/blenvm/llvm/llvm_engine.cc
M	source/blender/blenvm/llvm/llvm_engine.h
A	source/blender/blenvm/modules/mod_math.h
A	source/blender/blenvm/modules/mod_value.cc
A	source/blender/blenvm/modules/mod_value.h
D	source/blender/blenvm/modules/test.cc
D	source/blender/blenvm/modules/test.h

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

diff --git a/source/blender/blenvm/compile/node_graph.cc b/source/blender/blenvm/compile/node_graph.cc
index 1077ee8..466ca3d 100644
--- a/source/blender/blenvm/compile/node_graph.cc
+++ b/source/blender/blenvm/compile/node_graph.cc
@@ -1260,10 +1260,10 @@ void NodeGraph::finalize()
 {
 	ensure_valid_expression_inputs();
 	skip_pass_nodes();
-	inline_function_calls();
+//	inline_function_calls();
 	remove_unused_nodes();
 	sort_nodes();
-	blockify_nodes();
+//	blockify_nodes();
 }
 
 /* ------------------------------------------------------------------------- */
diff --git a/source/blender/blenvm/llvm/CMakeLists.txt b/source/blender/blenvm/llvm/CMakeLists.txt
index 8737ff9..113d5a2 100644
--- a/source/blender/blenvm/llvm/CMakeLists.txt
+++ b/source/blender/blenvm/llvm/CMakeLists.txt
@@ -91,11 +91,12 @@ macro(BLENVM_LLVM_MODULE_ADD src)
 	add_custom_command(
 		OUTPUT ${llvm_ir}
 		COMMAND ${LLVM_IR_COMPILER}
+				-cc1
+				-S
+				${CMAKE_CURRENT_SOURCE_DIR}/${src}
 				-emit-llvm
-				-S ${CMAKE_CURRENT_SOURCE_DIR}/${src}
 				-o ${CMAKE_CURRENT_BINARY_DIR}/${llvm_ir}
-				-I${CMAKE_CURRENT_SOURCE_DIR}/util
-				-DBJIT_RUNTIME
+				-DBLENVM_RUNTIME
 				-D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
 				-std=c++0x
 		DEPENDS ${LLVM_SRC})
@@ -106,10 +107,10 @@ endmacro()
 
 
 set(LLVM_SRC
-	../modules/test.cc
+	../modules/mod_value.cc
 )
 set(LLVM_HEADERS
-	../modules/test.h
+	../modules/mod_value.h
 )
 
 foreach(src ${LLVM_SRC})
diff --git a/source/blender/blenvm/llvm/llvm_codegen.cc b/source/blender/blenvm/llvm/llvm_codegen.cc
index d751464..2143df5 100644
--- a/source/blender/blenvm/llvm/llvm_codegen.cc
+++ b/source/blender/blenvm/llvm/llvm_codegen.cc
@@ -119,7 +119,8 @@ static string dummy_type_name(const OutputKey &output)
 	return ss.str();
 }
 
-LLVMCompiler::LLVMCompiler()
+LLVMCompiler::LLVMCompiler() :
+    m_module(NULL)
 {
 }
 
@@ -132,20 +133,25 @@ llvm::LLVMContext &LLVMCompiler::context() const
 	return llvm::getGlobalContext();
 }
 
-llvm::Type *LLVMCompiler::codegen_typedesc(const string &name, const TypeDesc *td)
+llvm::StructType *LLVMCompiler::codegen_struct_type(const string &name, const StructSpec *s)
+{
+	using namespace llvm;
+	
+	std::vector<Type*> elemtypes;
+	for (int i = 0; i < s->num_fields(); ++s) {
+		Type *ftype = codegen_type(s->field(i).name, &s->field(i).typedesc);
+		elemtypes.push_back(ftype);
+	}
+	
+	return StructType::create(context(), ArrayRef<Type*>(elemtypes), name);
+}
+
+llvm::Type *LLVMCompiler::codegen_type(const string &name, const TypeDesc *td)
 {
 	using namespace llvm;
 	
 	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;
+		return codegen_struct_type(name, td->structure());
 	}
 	else {
 		switch (td->base_type()) {
@@ -171,6 +177,82 @@ llvm::Type *LLVMCompiler::codegen_typedesc(const string &name, const TypeDesc *t
 	return NULL;
 }
 
+llvm::Constant *LLVMCompiler::codegen_constant(const NodeValue *node_value)
+{
+	using namespace llvm;
+	
+	const TypeDesc &td = node_value->typedesc();
+	if (td.is_structure()) {
+//		const StructSpec *s = td.structure();
+		/* TODO don't have value storage for this yet */
+		return NULL;
+	}
+	else {
+		switch (td.base_type()) {
+			case BVM_FLOAT: {
+				float f;
+				node_value->get(&f);
+				return ConstantFP::get(context(), APFloat(f));
+			}
+			case BVM_FLOAT3: {
+				StructType *stype = TypeBuilder<float3, true>::get(context());
+				
+				float3 f;
+				node_value->get(&f);
+				return ConstantStruct::get(stype,
+				                           ConstantFP::get(context(), APFloat(f.x)),
+				                           ConstantFP::get(context(), APFloat(f.y)),
+				                           ConstantFP::get(context(), APFloat(f.z)),
+				                           NULL);
+			}
+			case BVM_FLOAT4: {
+				StructType *stype = TypeBuilder<float4, true>::get(context());
+				
+				float4 f;
+				node_value->get(&f);
+				return ConstantStruct::get(stype,
+				                           ConstantFP::get(context(), APFloat(f.x)),
+				                           ConstantFP::get(context(), APFloat(f.y)),
+				                           ConstantFP::get(context(), APFloat(f.z)),
+				                           ConstantFP::get(context(), APFloat(f.w)),
+				                           NULL);
+			}
+			case BVM_INT: {
+				int i;
+				node_value->get(&i);
+				return ConstantInt::get(context(), APInt(32, i, true));
+			}
+			case BVM_MATRIX44: {
+				Type *elem_t = TypeBuilder<types::ieee_float, true>::get(context());
+				ArrayType *inner_t = ArrayType::get(elem_t, 4);
+				ArrayType *outer_t = ArrayType::get(inner_t, 4);
+				StructType *matrix_t = StructType::get(outer_t, NULL);
+				
+				matrix44 m;
+				node_value->get(&m);
+				Constant *constants[4][4];
+				for (int i = 0; i < 4; ++i)
+					for (int j = 0; j < 4; ++j)
+						constants[i][j] = ConstantFP::get(context(), APFloat(m.data[i][j]));
+				Constant *cols[4];
+				for (int i = 0; i < 4; ++i)
+					cols[i] = ConstantArray::get(inner_t, ArrayRef<Constant*>(constants[i], 4));
+				Constant *data = ConstantArray::get(outer_t, ArrayRef<Constant*>(cols, 4));
+				return ConstantStruct::get(matrix_t,
+				                           data, NULL);
+			}
+				
+			case BVM_STRING:
+			case BVM_RNAPOINTER:
+			case BVM_MESH:
+			case BVM_DUPLIS:
+				/* TODO */
+				return NULL;
+		}
+	}
+	return NULL;
+}
+
 llvm::FunctionType *LLVMCompiler::codegen_node_function_type(const NodeGraph &graph)
 {
 	using namespace llvm;
@@ -179,7 +261,7 @@ llvm::FunctionType *LLVMCompiler::codegen_node_function_type(const NodeGraph &gr
 	
 	for (int i = 0; i < graph.outputs.size(); ++i) {
 		const NodeGraph::Output &output = graph.outputs[i];
-		Type *type = codegen_typedesc(dummy_type_name(output.key), &output.typedesc);
+		Type *type = codegen_type(dummy_type_name(output.key), &output.typedesc);
 		output_types.push_back(type);
 	}
 	StructType *return_type = StructType::get(context(), output_types);
@@ -187,7 +269,7 @@ llvm::FunctionType *LLVMCompiler::codegen_node_function_type(const NodeGraph &gr
 	input_types.push_back(PointerType::get(return_type, 0));
 	for (int i = 0; i < graph.inputs.size(); ++i) {
 		const NodeGraph::Input &input = graph.inputs[i];
-		Type *type = codegen_typedesc(dummy_type_name(input.key), &input.typedesc);
+		Type *type = codegen_type(dummy_type_name(input.key), &input.typedesc);
 //		type = PointerType::get(type, 0);
 		input_types.push_back(type);
 	}
@@ -195,6 +277,73 @@ llvm::FunctionType *LLVMCompiler::codegen_node_function_type(const NodeGraph &gr
 	return FunctionType::get(TypeBuilder<void, true>::get(context()), input_types, false);
 }
 
+llvm::CallInst *LLVMCompiler::codegen_node_call(llvm::BasicBlock *block,
+                                                const NodeInstance *node,
+                                                OutputValueMap &output_values)
+{
+	using namespace llvm;
+	
+	const bool use_struct_return = (node->num_outputs() > 1);
+	
+	IRBuilder<> builder(context());
+	builder.SetInsertPoint(block);
+	
+	/* get evaluation function */
+	const std::string &evalname = node->type->name();
+	Function *evalfunc = module()->getFunction(evalname);
+	if (!evalfunc) {
+		printf("Could not find node function '%s'\n", evalname.c_str());
+		return NULL;
+	}
+	
+	/* function call arguments (including possible return struct if MRV is used) */
+	std::vector<Value *> args;
+	
+	Value *retval = NULL;
+	if (evalfunc->hasStructRetAttr()) {
+		Argument *retarg = &(*evalfunc->getArgumentList().begin());
+		retval = builder.CreateAlloca(retarg->getType()->getPointerElementType());
+		
+		args.push_back(retval);
+	}
+	
+	/* set input arguments */
+	for (int i = 0; i < node->num_inputs(); ++i) {
+		ConstInputKey input = node->input(i);
+		
+		switch (input.value_type()) {
+			case INPUT_CONSTANT:
+				args.push_back(codegen_constant(input.value()));
+				break;
+			case INPUT_EXPRESSION:
+				args.push_back(output_values.at(input.link()));
+				break;
+			case INPUT_VARIABLE:
+				/* TODO */
+				BLI_assert(false && "Variable inputs not supported yet!");
+				break;
+		}
+	}
+	
+	CallInst *call = builder.CreateCall(evalfunc, args);
+	if (!retval)
+		retval = call;
+	
+	for (int i = 0; i < node->num_outputs(); ++i) {
+		ConstOutputKey output = node->output(i);
+		Value *value = builder.CreateStructGEP(retval, i);
+		if (!value) {
+			printf("Error: no output value defined for '%s':'%s'\n", node->name.c_str(), output.socket->name.c_str());
+		}
+		
+		/* use as node output values */
+		bool ok = output_values.insert(OutputValuePair(output, value)).second;
+		BLI_assert(ok && "Value for node output already defined!");
+	}
+	
+	return call;
+}
+
 /* Compile nodes as a simple expression.
  * Every node can be treated as a single statement. Each node is translated
  * into a function call, with regular value arguments. The resulting value is
@@ -206,8 +355,8 @@ llvm::BasicBlock *LLVMCompiler::codegen_function_body_expression(const NodeGraph
 	
 	IRBuilder<> builder(context());
 	
-	BasicBlock *entry = BasicBlock::Create(context(), "entry", func);
-	builder.SetInsertPoint(entry);
+	BasicBlock *block = BasicBlock::Create(context(), "entry", func);
+	builder.SetInsertPoint(block);
 	
 	int num_inputs = graph.inputs.size();
 	int num_outputs = graph.outputs.size();
@@ -224,16 +373,21 @@ llvm::BasicBlock *LLVMCompiler::codegen_function_body_expression(const NodeGraph
 		output_values[input.key] = arg;
 	}
 	
-#if 0 // TODO
-	NodeRefList sorted_nodes = toposort_nodes(graph);
-	for (NodeRefList::iterator it = sorted_nodes.begin(); it != sorted_nodes.end(); ++it) {
-		NodeInstance *node = *it;
+	OrderedNodeSet nodes;
+	for (NodeGraph::NodeInstanceMap::const_iterator it = graph.nodes.begin(); it != graph.nodes.end(); ++it)
+		nodes.insert(it->second);
+	
+	printf("DOING THE NODES: ---\n");
+	module()->dump();
+	printf("--------------------\n");
+	
+	for (OrderedNodeSet::const_iterator it = nodes.b

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list