[Bf-blender-cvs] [35c7b749ddb] nodes_playground: generate some code

Jacques Lucke noreply at git.blender.org
Sun Jan 6 17:25:18 CET 2019


Commit: 35c7b749ddb015dca2a16ceb4eb6e3ce498dc731
Author: Jacques Lucke
Date:   Thu Jan 3 17:42:10 2019 +0100
Branches: nodes_playground
https://developer.blender.org/rB35c7b749ddb015dca2a16ceb4eb6e3ce498dc731

generate some code

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

M	source/blender/modifiers/CMakeLists.txt
A	source/blender/modifiers/intern/HashMap.hpp
M	source/blender/modifiers/intern/HashSet.hpp
M	source/blender/modifiers/intern/node_compiler.cpp
M	source/blender/modifiers/intern/node_compiler.hpp
M	source/blender/modifiers/intern/node_compiler_testing.cpp

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

diff --git a/source/blender/modifiers/CMakeLists.txt b/source/blender/modifiers/CMakeLists.txt
index f2909be8cab..a6ba8a9f93b 100644
--- a/source/blender/modifiers/CMakeLists.txt
+++ b/source/blender/modifiers/CMakeLists.txt
@@ -119,6 +119,8 @@ set(SRC
 	intern/node_compiler_testing.cpp
 	intern/node_compiler.cpp
 	intern/node_compiler.hpp
+	intern/HashSet.hpp
+	intern/HashMap.hpp
 )
 
 if(WITH_ALEMBIC)
diff --git a/source/blender/modifiers/intern/HashMap.hpp b/source/blender/modifiers/intern/HashMap.hpp
new file mode 100644
index 00000000000..1e0fb215f9a
--- /dev/null
+++ b/source/blender/modifiers/intern/HashMap.hpp
@@ -0,0 +1,43 @@
+#include <cstdint>
+#include <vector>
+
+template<typename TKey, typename TValue>
+class HashMap {
+private:
+	struct Entry {
+		TKey key;
+		TValue value;
+
+		Entry(TKey key, TValue value)
+			: key(key), value(value) {}
+	};
+
+	std::vector<Entry> entries;
+
+public:
+	HashMap() {};
+
+	void add(TKey key, TValue value)
+	{
+		if (!this->contains(key)) {
+			this->entries.push_back(Entry(key, value));
+		}
+	}
+
+	bool contains(TKey key)
+	{
+		for (Entry entry : this->entries) {
+			if (entry.key == key) return true;
+		}
+		return false;
+	}
+
+	TValue lookup(TKey key)
+	{
+		for (Entry entry : this->entries) {
+			if (entry.key == key) return entry.value;
+		}
+
+		assert(!"key not found");
+	}
+};
\ No newline at end of file
diff --git a/source/blender/modifiers/intern/HashSet.hpp b/source/blender/modifiers/intern/HashSet.hpp
index 45d5930b350..8a1575f0358 100644
--- a/source/blender/modifiers/intern/HashSet.hpp
+++ b/source/blender/modifiers/intern/HashSet.hpp
@@ -3,6 +3,9 @@
 
 template<typename T>
 class HashSet {
+private:
+    std::vector<T> entries;
+
 public:
     HashSet() {};
     HashSet(std::vector<T> values)
@@ -38,7 +41,4 @@ public:
     {
         return this->entries;
     }
-
-private:
-    std::vector<T> entries;
 };
\ No newline at end of file
diff --git a/source/blender/modifiers/intern/node_compiler.cpp b/source/blender/modifiers/intern/node_compiler.cpp
index 1ad44dec5d2..d5e3b5aa31b 100644
--- a/source/blender/modifiers/intern/node_compiler.cpp
+++ b/source/blender/modifiers/intern/node_compiler.cpp
@@ -50,11 +50,70 @@ std::string SimpleNode::debug_id() const
 }
 
 void Graph::generateCode(
-	llvm::IRBuilder<> &builder,
+	llvm::IRBuilder<> *builder,
 	std::vector<AnySocket> &inputs, std::vector<AnySocket> &outputs, std::vector<llvm::Value *> &input_values,
-	llvm::IRBuilder<> *r_builder, std::vector<llvm::Value *> *r_output_values)
+	llvm::IRBuilder<> **r_builder, std::vector<llvm::Value *> &r_output_values)
 {
+	assert(inputs.size() == input_values.size());
 
+	SocketValueMap values;
+	for (uint i = 0; i < inputs.size(); i++) {
+		values.add(inputs[i], input_values[i]);
+	}
+
+	for (AnySocket socket : outputs) {
+		llvm::IRBuilder<> *next_builder;
+
+		llvm::Value *value = this->generateCodeForSocket(socket, builder, values, &next_builder);
+		r_output_values.push_back(value);
+
+		builder = next_builder;
+	}
+
+	*r_builder = builder;
+}
+
+llvm::Value *Graph::generateCodeForSocket(
+	AnySocket socket,
+	llvm::IRBuilder<> *builder,
+	SocketValueMap &values,
+	llvm::IRBuilder<> **r_builder)
+{
+	if (values.contains(socket)) {
+		*r_builder = builder;
+		return values.lookup(socket);
+	}
+
+	if (socket.is_input()) {
+		AnySocket origin = this->getOriginSocket(socket);
+		llvm::Value *value = this->generateCodeForSocket(origin, builder, values, r_builder);
+		values.add(socket, value);
+		return value;
+	}
+
+	if (socket.is_output()) {
+		SimpleNode *node = socket.node();
+		std::vector<llvm::Value *> input_values;
+		for (uint i = 0; i < node->inputs.size(); i++) {
+			llvm::IRBuilder<> *next_builder;
+
+			llvm::Value *value = this->generateCodeForSocket(node->Input(i), builder, values, &next_builder);
+			input_values.push_back(value);
+
+			builder = next_builder;
+		}
+
+		std::vector<llvm::Value *> output_values;
+		node->generateCode(input_values, builder, output_values, r_builder);
+
+		for (uint i = 0; i < node->outputs.size(); i++) {
+			values.add(node->Output(i), output_values[i]);
+		}
+
+		return values.lookup(socket);
+	}
+
+	assert(!"should never happen");
 }
 
 SocketSet Graph::findRequiredSockets(SocketSet &inputs, SocketSet &outputs)
@@ -83,12 +142,16 @@ void Graph::findRequiredSockets(AnySocket socket, SocketSet &inputs, SocketSet &
 	if (socket.is_input()) {
 		AnySocket origin = this->getOriginSocket(socket);
 		this->findRequiredSockets(origin, inputs, required_sockets);
+		return;
 	}
-	else {
-		for (uint i = 0; i < socket.node()->inputs.size(); i++) {
+
+	if (socket.is_output()) {
+		SimpleNode *node = socket.node();
+		for (uint i = 0; i < node->inputs.size(); i++) {
 			AnySocket input = AnySocket::NewInput(socket.node(), i);
 			this->findRequiredSockets(input, inputs, required_sockets);
 		}
+		return;
 	}
 }
 
diff --git a/source/blender/modifiers/intern/node_compiler.hpp b/source/blender/modifiers/intern/node_compiler.hpp
index a4b4a3e9f83..c478854395a 100644
--- a/source/blender/modifiers/intern/node_compiler.hpp
+++ b/source/blender/modifiers/intern/node_compiler.hpp
@@ -9,6 +9,7 @@
 #include <unordered_set>
 
 #include "HashSet.hpp"
+#include "HashMap.hpp"
 
 namespace NodeCompiler {
 
@@ -55,6 +56,11 @@ private:
 
 using SocketSet = HashSet<AnySocket>;
 
+template<typename TValue>
+using SocketMap = HashMap<AnySocket, TValue>;
+
+using SocketValueMap = SocketMap<llvm::Value *>;
+
 struct SocketInfo {
 	const std::string debug_name;
 	const llvm::Type *type;
@@ -104,9 +110,9 @@ struct Graph {
 	LinkSet links;
 
 	void generateCode(
-		llvm::IRBuilder<> &builder,
+		llvm::IRBuilder<> *builder,
 		std::vector<AnySocket> &inputs, std::vector<AnySocket> &outputs, std::vector<llvm::Value *> &input_values,
-		llvm::IRBuilder<> *r_builder, std::vector<llvm::Value *> *r_output_values);
+		llvm::IRBuilder<> **r_builder, std::vector<llvm::Value *> &r_output_values);
 
 	AnySocket getOriginSocket(AnySocket socket) const;
 
@@ -115,6 +121,12 @@ struct Graph {
 	SocketSet findRequiredSockets(SocketSet &inputs, SocketSet &outputs);
 private:
 	void findRequiredSockets(AnySocket socket, SocketSet &inputs, SocketSet &required_sockets);
+
+	llvm::Value *generateCodeForSocket(
+		AnySocket socket,
+		llvm::IRBuilder<> *builder,
+		SocketValueMap &values,
+		llvm::IRBuilder<> **r_builder);
 };
 
 } /* namespace NodeCompiler */
diff --git a/source/blender/modifiers/intern/node_compiler_testing.cpp b/source/blender/modifiers/intern/node_compiler_testing.cpp
index 00eb070d368..63d0af38bf9 100644
--- a/source/blender/modifiers/intern/node_compiler_testing.cpp
+++ b/source/blender/modifiers/intern/node_compiler_testing.cpp
@@ -43,6 +43,22 @@ static NC::SimpleNode *new_int_node(llvm::LLVMContext &context, int value)
 	return node;
 }
 
+static NC::SimpleNode *new_int_ref_node(llvm::LLVMContext &context, int *value)
+{
+	auto node = new NC::SimpleNode();
+	node->debug_name = "Int Ref";
+	node->outputs.push_back(NC::SocketInfo("Value", llvm::Type::getInt32Ty(context)));
+	node->generateCode = [value](
+		std::vector<llvm::Value *> &UNUSED(inputs), llvm::IRBuilder<> *builder,
+		std::vector<llvm::Value *> &r_outputs, llvm::IRBuilder<> **r_builder) {
+			auto address_int = builder->getInt64((uint64_t)value);
+			auto address = builder->CreateIntToPtr(address_int, llvm::Type::getInt32PtrTy(builder->getContext()));
+			r_outputs.push_back(builder->CreateLoad(address));
+			*r_builder = builder;
+		};
+	return node;
+}
+
 extern "C" {
 	void run_tests(void);
 }
@@ -52,9 +68,11 @@ void run_tests()
 	llvm::LLVMContext *_context = new llvm::LLVMContext();
 	llvm::LLVMContext &context = *_context;
 
+	int test_value = 1000;
+
 	auto in1 = new_int_node(context, 1);
-	auto in2 = new_int_node(context, 10);
-	auto in3 = new_int_node(context, 100);
+	auto in2 = new_int_ref_node(context, &test_value);
+	auto in3 = new_int_node(context, 10);
 
 	auto add1 = new_add_node(context);
 	auto add2 = new_add_node(context);
@@ -75,19 +93,44 @@ void run_tests()
 	graph.links.links.push_back(NC::Link(add1->Output(0), add3->Input(0)));
 	graph.links.links.push_back(NC::Link(add2->Output(0), add3->Input(1)));
 
-	NC::SocketSet inputs = { add1->Input(0), add1->Input(1), add2->Input(1) };
-	NC::SocketSet outputs = { add3->Output(0) };
+	llvm::Module *module = new llvm::Module("test", context);
+	std::vector<llvm::Type *> arg_types = {};
+	llvm::FunctionType *ftype = llvm::FunctionType::get(
+		llvm::Type::getInt32Ty(context), arg_types, false);
+
+	llvm::Function *func = llvm::Function::Create(
+		ftype, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "my_func", module);
+
+	llvm::BasicBlock *bb = llvm::BasicBlock::Create(context, "entry", func);
+	llvm::IRBuilder<> builder(context);
+	builder.SetInsertPoint(bb);
+
+	std::vector<NC::AnySocket> inputs = {};
+	std::vector<llvm::Value *> input_values = {};
+	std::vector<NC::AnySocket> outputs = { add3->Output(0) };
+	llvm::IRBuilder<> *next_builder;
+	std::vector<llvm::Value *> output_values;
+	graph.generateCode(&builder, inputs, outputs, input_values, &next_builder, output_values);
+	next_builder->CreateRet(output_values[0]);
+
+	llvm::verifyFunction(*func, &llvm::outs());
+	llvm::verifyModule(*module, &llvm::outs());
+
+	module->print(llvm::outs(), nullptr);
+
+	// NC::SocketSet inputs = { add1->Input(0), add1->Input(1), add2->Input(1) };
+	// NC::SocketSet outputs = { add3->Output(0) };
 
-	auto required_sockets = graph.findRequiredSockets(inputs, outputs);
+	// auto required_sockets = graph.findRequiredSockets(inputs, outputs);
 
-	std::vector<NC::SimpleNode *> required_nodes;
-	for (NC::AnySocket socket : required_sockets.elements()) {
-		required_nodes.push_back(socket.node());
-	}
+	// std::vector<NC::SimpleNode *> required_nodes;
+	// for (NC::AnySocket socket : required_sockets.elements()) {
+	// 	required_nodes.push_back(socket.node());
+	// }
 
-	auto dot = graph.toDotFormat(required_nodes);
-	std::cout << dot << std::endl;
-	WM_clipboard_text_set(dot.c_str(), false);
+	// auto dot = graph.toDotFormat(required_nodes);
+	// std::cout << dot << std::endl;
+	// WM_clipboard_text_set(dot.c_str(), false);
 
 	std::cout << "Test Finished" << std::endl;
 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list