[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