Commit: 910d7d4be0c43e76cfe110617462a540a48bb6ed
Author: Jacques Lucke
Date:   Sat Mar 2 12:14:06 2019 +0100
Branches: functions
https://developer.blender.org/rB910d7d4be0c43e76cfe110617462a540a48bb6ed

compile llvm to tuple call

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

M       source/blender/functions/CMakeLists.txt
M       source/blender/functions/FN_llvm.hpp
A       source/blender/functions/backends/llvm/llvm_gen.cpp
A       source/blender/functions/backends/llvm/llvm_gen.hpp
A       source/blender/functions/backends/llvm/to_tuple_call.cpp
A       source/blender/functions/backends/llvm/to_tuple_call.hpp
M       source/blender/functions/backends/tuple_call/tuple.hpp
M       source/blender/functions/c_wrapper.cpp
M       source/blender/functions/functions/scalar_math.cpp

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

diff --git a/source/blender/functions/CMakeLists.txt 
b/source/blender/functions/CMakeLists.txt
index 184ced13bb8..a2ede8f049a 100644
--- a/source/blender/functions/CMakeLists.txt
+++ b/source/blender/functions/CMakeLists.txt
@@ -52,6 +52,10 @@ set(SRC
 
        backends/llvm/llvm_types.hpp
        backends/llvm/llvm_types.cpp
+       backends/llvm/llvm_gen.hpp
+       backends/llvm/llvm_gen.cpp
+       backends/llvm/to_tuple_call.hpp
+       backends/llvm/to_tuple_call.cpp
 
        types/numeric.cpp
        types/numeric.hpp
diff --git a/source/blender/functions/FN_llvm.hpp 
b/source/blender/functions/FN_llvm.hpp
index c1cf8027cb7..95b4749a260 100644
--- a/source/blender/functions/FN_llvm.hpp
+++ b/source/blender/functions/FN_llvm.hpp
@@ -1,3 +1,5 @@
 #pragma once
 
-#include "backends/llvm/llvm_types.hpp"
\ No newline at end of file
+#include "backends/llvm/llvm_types.hpp"
+#include "backends/llvm/llvm_gen.hpp"
+#include "backends/llvm/to_tuple_call.hpp"
\ No newline at end of file
diff --git a/source/blender/functions/backends/llvm/llvm_gen.cpp 
b/source/blender/functions/backends/llvm/llvm_gen.cpp
new file mode 100644
index 00000000000..73abd39dbd3
--- /dev/null
+++ b/source/blender/functions/backends/llvm/llvm_gen.cpp
@@ -0,0 +1,16 @@
+#include "llvm_gen.hpp"
+
+namespace FN {
+
+       const char *LLVMGenBody::identifier_in_composition()
+       {
+               return "LLVM Gen Body";
+       }
+
+       void LLVMGenBody::free_self(void *value)
+       {
+               LLVMGenBody *v = (LLVMGenBody *)value;
+               delete v;
+       }
+
+} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/backends/llvm/llvm_gen.hpp 
b/source/blender/functions/backends/llvm/llvm_gen.hpp
new file mode 100644
index 00000000000..20f13698adb
--- /dev/null
+++ b/source/blender/functions/backends/llvm/llvm_gen.hpp
@@ -0,0 +1,23 @@
+#pragma once
+
+#include "FN_core.hpp"
+#include <llvm/IR/IRBuilder.h>
+
+namespace FN {
+
+       using LLVMValues = SmallVector<llvm::Value *>;
+
+       class LLVMGenBody {
+       public:
+               static const char *identifier_in_composition();
+               static void free_self(void *value);
+
+               virtual ~LLVMGenBody() {};
+
+               virtual void build_ir(
+                       llvm::IRBuilder<> &builder,
+                       const LLVMValues &inputs,
+                       LLVMValues &r_outputs) const = 0;
+       };
+
+}
\ No newline at end of file
diff --git a/source/blender/functions/backends/llvm/to_tuple_call.cpp 
b/source/blender/functions/backends/llvm/to_tuple_call.cpp
new file mode 100644
index 00000000000..1ef1fea343c
--- /dev/null
+++ b/source/blender/functions/backends/llvm/to_tuple_call.cpp
@@ -0,0 +1,158 @@
+#include "to_tuple_call.hpp"
+#include "llvm_types.hpp"
+#include "llvm_gen.hpp"
+
+#include "FN_tuple_call.hpp"
+
+#include <llvm/IR/Verifier.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+
+namespace FN {
+
+       using LLVMTypes = BLI::SmallVector<llvm::Type *>;
+
+       static LLVMTypeInfo *type_info(const SharedType &type)
+       {
+               auto ext = type->extension<LLVMTypeInfo>();
+               BLI_assert(ext);
+               return ext;
+       }
+
+       template<typename T>
+       static llvm::ArrayRef<T> array_ref(SmallVector<T> &vector)
+       {
+               return llvm::ArrayRef<T>(vector.begin(), vector.end());
+       }
+
+       static llvm::Value *lookup_tuple_address(
+               llvm::IRBuilder<> &builder,
+               llvm::Value *data_addr,
+               llvm::Value *offsets_addr,
+               uint index)
+       {
+               llvm::Value *offset_addr = 
builder.CreateConstGEP1_32(offsets_addr, index);
+               llvm::Value *offset = builder.CreateLoad(offset_addr);
+               llvm::Value *value_byte_addr = builder.CreateGEP(data_addr, 
offset);
+               return value_byte_addr;
+       }
+
+       static llvm::Function *insert_tuple_call_function(
+               SharedFunction fn,
+               llvm::Module *module)
+       {
+               llvm::LLVMContext &context = module->getContext();
+
+               llvm::Type *void_ty = llvm::Type::getVoidTy(context);
+               llvm::Type *byte_ptr_ty = llvm::Type::getInt8PtrTy(context);
+               llvm::Type *int_ptr_ty = llvm::Type::getInt32PtrTy(context);
+
+               LLVMTypes input_types = {
+                       byte_ptr_ty,
+                       int_ptr_ty,
+                       byte_ptr_ty,
+                       int_ptr_ty,
+               };
+
+               llvm::FunctionType *function_type = llvm::FunctionType::get(
+                       void_ty, array_ref(input_types), false);
+
+               llvm::Function *function = llvm::Function::Create(
+                       function_type,
+                       llvm::GlobalValue::LinkageTypes::ExternalLinkage,
+                       fn->name(),
+                       module);
+
+
+               llvm::BasicBlock *bb = llvm::BasicBlock::Create(context, 
"entry", function);
+               llvm::IRBuilder<> builder(bb);
+
+               llvm::Value *fn_in_data = function->arg_begin() + 0;
+               llvm::Value *fn_in_offsets = function->arg_begin() + 1;
+               llvm::Value *fn_out_data = function->arg_begin() + 2;
+               llvm::Value *fn_out_offsets = function->arg_begin() + 3;
+
+               LLVMValues input_values;
+               for (uint i = 0; i < fn->signature().inputs().size(); i++) {
+                       llvm::Type *value_type = 
type_info(fn->signature().inputs()[i].type())->get_type(context);
+
+                       llvm::Value *value_byte_addr = lookup_tuple_address(
+                               builder, fn_in_data, fn_in_offsets, i);
+                       llvm::Value *value_addr = builder.CreatePointerCast(
+                               value_byte_addr, value_type->getPointerTo());
+                       llvm::Value *value = builder.CreateLoad(value_addr);
+                       input_values.append(value);
+               }
+
+               LLVMValues output_values;
+               auto body = fn->body<LLVMGenBody>();
+               BLI_assert(body);
+               body->build_ir(builder, input_values, output_values);
+
+               for (uint i = 0; i < output_values.size(); i++) {
+                       llvm::Type *value_type = output_values[i]->getType();
+
+                       llvm::Value *value_byte_addr = lookup_tuple_address(
+                               builder, fn_out_data, fn_out_offsets, i);
+                       llvm::Value *value_addr = builder.CreatePointerCast(
+                               value_byte_addr, value_type->getPointerTo());
+                       builder.CreateStore(output_values[i], value_addr);
+               }
+
+               builder.CreateRetVoid();
+
+               return function;
+       }
+
+       typedef void (*LLVMCallFN)(
+               void *data_in,
+               const uint *offsets_in,
+               void *data_out,
+               const uint *offsets_out);
+
+       class LLVMTupleCall : public TupleCallBody {
+       private:
+               LLVMCallFN m_call;
+
+       public:
+               LLVMTupleCall(LLVMCallFN call)
+                       : m_call(call) {}
+
+               void call(const Tuple &fn_in, Tuple &fn_out) const override
+               {
+                       m_call(
+                               fn_in.data_ptr(),
+                               fn_in.offsets_ptr(),
+                               fn_out.data_ptr(),
+                               fn_out.offsets_ptr());
+               }
+       };
+
+       TupleCallBody *compile_llvm_to_tuple_call(
+               SharedFunction &fn,
+               llvm::LLVMContext &context)
+       {
+               llvm::Module *module = new llvm::Module(fn->name(), context);
+               llvm::Function *function = insert_tuple_call_function(fn, 
module);
+
+               // module->print(llvm::outs(), nullptr);
+
+               llvm::verifyFunction(*function, &llvm::outs());
+               llvm::verifyModule(*module, &llvm::outs());
+
+               llvm::InitializeNativeTarget();
+               llvm::InitializeNativeTargetAsmPrinter();
+               llvm::InitializeNativeTargetAsmParser();
+
+               llvm::ExecutionEngine *ee = llvm::EngineBuilder(
+                       std::unique_ptr<llvm::Module>(module)).create();
+               ee->finalizeObject();
+               ee->generateCodeForModule(module);
+
+               uint64_t fn_ptr = ee->getFunctionAddress(
+                       function->getName().str());
+
+               return new LLVMTupleCall((LLVMCallFN)fn_ptr);
+       }
+
+} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/backends/llvm/to_tuple_call.hpp 
b/source/blender/functions/backends/llvm/to_tuple_call.hpp
new file mode 100644
index 00000000000..8adb6b393d7
--- /dev/null
+++ b/source/blender/functions/backends/llvm/to_tuple_call.hpp
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "FN_core.hpp"
+#include <llvm/IR/IRBuilder.h>
+
+namespace FN {
+
+       class TupleCallBody;
+
+       TupleCallBody *compile_llvm_to_tuple_call(
+               SharedFunction &fn,
+               llvm::LLVMContext &context);
+
+} /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/backends/tuple_call/tuple.hpp 
b/source/blender/functions/backends/tuple_call/tuple.hpp
index 48aaf084f36..f17c3e478f5 100644
--- a/source/blender/functions/backends/tuple_call/tuple.hpp
+++ b/source/blender/functions/backends/tuple_call/tuple.hpp
@@ -93,6 +93,16 @@ namespace FN {
                        }
                }
 
+               void *data_ptr() const
+               {
+                       return m_data;
+               }
+
+               const uint *offsets_ptr() const
+               {
+                       return m_offsets.begin();
+               }
+
        private:
                inline uint element_size(uint index) const
                {
diff --git a/source/blender/functions/c_wrapper.cpp 
b/source/blender/functions/c_wrapper.cpp
index ce934ce86ed..1d8a8a4d190 100644
--- a/source/blender/functions/c_wrapper.cpp
+++ b/source/blender/functions/c_wrapper.cpp
@@ -21,9 +21,27 @@ WRAPPERS(RefCounted<Type> *, FnType);
 WRAPPERS(Tuple *, FnTuple);
 WRAPPERS(const TupleCallBody *, FnTupleCallBody);
 
+static void playground()
+{
+       SharedFunction fn = Functions::add_floats();
+       llvm::LLVMContext *context = new llvm::LLVMContext();
+       auto body = compile_llvm_to_tuple_call(fn, *context);
+
+       Tuple fn_in(fn->signature().input_types());
+       Tuple fn_out(fn->signature().output_types());
+
+       fn_in.set<float>(0, 12);
+       fn_in.set<float>(1, 30);
+       body->call(fn_in, fn_out);
+       float result = fn_out.get<float>(0);
+       std::cout << "Result: " << result << std::endl;
+
+       delete context;
+}
 
 void FN_initialize()
 {
+       playground();
 }
 
 void FN_function_call(FnTupleCallBody fn_call, FnTuple fn_in, FnTuple fn_out)
diff --git a/source/blender/functions/functions/scalar_math.cpp 
b/source/blender/functions/functions/scalar_math.cpp
index dc3e94814f6..4ddeecb494e 100644
--- a/source/blender/functions/functions/scalar_math.cpp
+++ b/source/blender/functions/functions/scalar_math.cpp
@@ -1,6 +1,7 @@
 #include "scalar_math.hpp"
 #include "FN_types.hpp"
 #include "FN_tuple_call.hpp"
+#include "FN_llvm.hpp"
 
 #include "BLI_lazy_init.hpp"
 
@@ -29,10 +30,22 @@ namespace FN { namespace Functions {
                }
        };
 
+       class GenAddFloats : public LLVMGenBody {
+               void build_ir(
+                       llvm::IRBuilder<> &builder,
+                       const LLVMValues &inputs,
+                       LLVMValues &r_outputs) const override
+               {
+                       auto output = builder.CreateFAdd(inputs[0], inputs[1]);
+                       r_outputs.append(output);
+               }
+       };
+
        LAZY_INIT_REF__NO_ARG(SharedFunction, add_floats)
        {
                auto fn = get_simple_math_function("Add Floats");
                fn->add_body(new AddFloats());
+               fn->add_body(new GenAddFloats());
                return fn;
        }

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to