Commit: 662b5ade05dfbc7555355cf85948baab652a0cf6
Author: Jacques Lucke
Date:   Sun Mar 3 15:03:56 2019 +0100
Branches: functions
https://developer.blender.org/rB662b5ade05dfbc7555355cf85948baab652a0cf6

generate separate wrapper functions

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

M       source/blender/functions/backends/llvm/from_tuple_call.cpp
M       source/blender/functions/backends/llvm/ir_utils.cpp
M       source/blender/functions/backends/llvm/ir_utils.hpp
M       source/blender/functions/backends/llvm/llvm_gen.hpp
M       source/blender/functions/backends/llvm/llvm_types.hpp
M       source/blender/functions/backends/llvm/to_tuple_call.cpp
M       source/blender/functions/core/signature.hpp

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

diff --git a/source/blender/functions/backends/llvm/from_tuple_call.cpp 
b/source/blender/functions/backends/llvm/from_tuple_call.cpp
index ed7c8075e62..89d4bfa54e0 100644
--- a/source/blender/functions/backends/llvm/from_tuple_call.cpp
+++ b/source/blender/functions/backends/llvm/from_tuple_call.cpp
@@ -44,25 +44,69 @@ namespace FN {
                        LLVMValues &r_outputs) const override
                {
                        Function *fn = m_tuple_call->owner();
+                       llvm::LLVMContext &context = builder.getContext();
 
-                       llvm::Type *void_ty = builder.getVoidTy();
+                       /* Find relevant type information. */
+                       auto input_type_infos = 
fn->signature().input_extensions<LLVMTypeInfo>();
+                       auto output_type_infos = 
fn->signature().output_extensions<LLVMTypeInfo>();
+
+                       LLVMTypes input_types = types_of_values(inputs);
+                       LLVMTypes output_types;
+                       for (auto type_info : output_type_infos) {
+                               
output_types.append(type_info->get_type(context));
+                       }
+
+                       /* Build wrapper function. */
+                       llvm::Type *wrapper_output_type = 
llvm::StructType::get(context, to_array_ref(output_types));
+
+                       llvm::FunctionType *wrapper_function_type = 
llvm::FunctionType::get(
+                               wrapper_output_type, to_array_ref(input_types), 
false);
+
+                       llvm::Function *wrapper_function = 
llvm::Function::Create(
+                               wrapper_function_type,
+                               
llvm::GlobalValue::LinkageTypes::InternalLinkage,
+                               fn->name() + " Wrapper",
+                               builder.GetInsertBlock()->getModule());
+
+                       this->build_wrapper_function(
+                               wrapper_function,
+                               input_type_infos,
+                               output_type_infos,
+                               wrapper_output_type);
+
+                       /* Call wrapper function. */
+                       llvm::Value *output_struct = builder.CreateCall(
+                               wrapper_function, 
to_array_ref(const_cast<LLVMValues&>(inputs)));
+
+                       /* Extract output values. */
+                       for (uint i = 0; i < output_type_infos.size(); i++) {
+                               llvm::Value *out = 
builder.CreateExtractValue(output_struct, i);
+                               r_outputs.append(out);
+                       }
+               }
+
+       private:
+               void build_wrapper_function(
+                       llvm::Function *function,
+                       SmallVector<LLVMTypeInfo *> &input_type_infos,
+                       SmallVector<LLVMTypeInfo *> &output_type_infos,
+                       llvm::Type *output_type) const
+               {
+                       llvm::LLVMContext &context = function->getContext();
+
+                       llvm::BasicBlock *bb = 
llvm::BasicBlock::Create(context, "entry", function);
+                       llvm::IRBuilder<> builder(bb);
+
+                       /* Type declarations. */
+                       llvm::Type *void_ty = llvm::Type::getVoidTy(context);
                        llvm::Type *void_ptr_ty = void_ty->getPointerTo();
-                       llvm::Type *byte_ptr_ty = builder.getInt8PtrTy();
+                       llvm::Type *byte_ptr_ty = 
llvm::Type::getInt8PtrTy(context);
 
                        llvm::FunctionType *construct_ftype = 
llvm::FunctionType::get(
                                void_ty, {byte_ptr_ty, void_ptr_ty}, false);
                        llvm::FunctionType *call_ftype = 
llvm::FunctionType::get(
                                void_ty, {void_ptr_ty, byte_ptr_ty, 
byte_ptr_ty}, false);
 
-                       /* Load static pointers into IR. */
-                       llvm::Value *meta_in_ptr = void_ptr_to_ir(builder, 
(void *)&m_in_meta);
-                       llvm::Value *meta_out_ptr = void_ptr_to_ir(builder, 
(void *)&m_out_meta);
-
-                       llvm::Value *offsets_in_ptr = int_ptr_to_ir(
-                               builder, (int *)m_in_meta->offsets().begin());
-                       llvm::Value *offsets_out_ptr = int_ptr_to_ir(
-                               builder, (int *)m_out_meta->offsets().begin());
-
                        /* Construct input and output tuple on stack. */
                        llvm::Value *tuple_in_ptr = alloca_bytes(builder, 
get_total_tuple_size(m_in_meta));
                        tuple_in_ptr->setName("tuple_in");
@@ -70,33 +114,37 @@ namespace FN {
                        tuple_out_ptr->setName("tuple_out");
 
                        llvm::Value *tuple_in_data_ptr = 
builder.CreateConstGEP1_32(tuple_in_ptr, sizeof(Tuple));
+                       tuple_in_data_ptr->setName("tuple_in_data");
                        llvm::Value *tuple_out_data_ptr = 
builder.CreateConstGEP1_32(tuple_out_ptr, sizeof(Tuple));
+                       tuple_out_data_ptr->setName("tuple_out_data");
+
+                       llvm::Value *meta_in_ptr = void_ptr_to_ir(builder, 
(void *)&m_in_meta);
+                       llvm::Value *meta_out_ptr = void_ptr_to_ir(builder, 
(void *)&m_out_meta);
 
                        call_pointer(builder, (void *)construct_tuple,
                                construct_ftype, {tuple_in_ptr, meta_in_ptr});
                        call_pointer(builder, (void *)construct_tuple,
                                construct_ftype, {tuple_out_ptr, meta_out_ptr});
 
-
                        /* Write input values into tuple. */
-                       for (uint i = 0; i < fn->signature().inputs().size(); 
i++) {
-                               LLVMTypeInfo *type_info = 
fn->signature().inputs()[i].type()->extension<LLVMTypeInfo>();
-                               llvm::Value *store_at_addr = 
lookup_tuple_address(builder, tuple_in_data_ptr, offsets_in_ptr, i);
-                               type_info->build_store_ir__relocate(builder, 
inputs[i], store_at_addr);
+                       for (uint i = 0; i < input_type_infos.size(); i++) {
+                               llvm::Value *arg = function->arg_begin() + i;
+                               llvm::Value *store_at_addr = 
builder.CreateConstGEP1_32(tuple_in_data_ptr, m_in_meta->offsets()[i]);
+                               
input_type_infos[i]->build_store_ir__relocate(builder, arg, store_at_addr);
                        }
 
                        /* Execute tuple call body. */
                        call_pointer(builder, (void *)call,
                                call_ftype, {void_ptr_to_ir(builder, 
m_tuple_call), tuple_in_ptr, tuple_out_ptr});
 
-                       /* Read output values back into virtual registers. */
-                       for (uint i = 0; i < fn->signature().outputs().size(); 
i++) {
-                               LLVMTypeInfo *type_info = 
fn->signature().outputs()[i].type()->extension<LLVMTypeInfo>();
-                               llvm::Value *load_from_addr = 
lookup_tuple_address(builder, tuple_out_data_ptr, offsets_out_ptr, i);
-                               llvm::Value *out = 
type_info->build_load_ir__relocate(builder, load_from_addr);
-                               out->setName("output");
-                               r_outputs.append(out);
+                       /* Read output values into struct and return. */
+                       llvm::Value *output = 
llvm::UndefValue::get(output_type);
+                       for (uint i = 0; i < output_type_infos.size(); i++) {
+                               llvm::Value *load_from_addr = 
builder.CreateConstGEP1_32(tuple_out_data_ptr, m_out_meta->offsets()[i]);
+                               llvm::Value *out = 
output_type_infos[i]->build_load_ir__relocate(builder, load_from_addr);
+                               output = builder.CreateInsertValue(output, out, 
i);
                        }
+                       builder.CreateRet(output);
                }
        };
 
diff --git a/source/blender/functions/backends/llvm/ir_utils.cpp 
b/source/blender/functions/backends/llvm/ir_utils.cpp
index 647b759446e..a232af3416b 100644
--- a/source/blender/functions/backends/llvm/ir_utils.cpp
+++ b/source/blender/functions/backends/llvm/ir_utils.cpp
@@ -54,4 +54,13 @@ namespace FN {
                return builder.CreatePointerCast(tuple_in_ptr, 
builder.getInt8PtrTy());
        }
 
+       LLVMTypes types_of_values(const LLVMValues &values)
+       {
+               LLVMTypes types;
+               for (llvm::Value *value : values) {
+                       types.append(value->getType());
+               }
+               return types;
+       }
+
 } /* namespace FN */
\ No newline at end of file
diff --git a/source/blender/functions/backends/llvm/ir_utils.hpp 
b/source/blender/functions/backends/llvm/ir_utils.hpp
index 73a8faa116e..843b746b9ad 100644
--- a/source/blender/functions/backends/llvm/ir_utils.hpp
+++ b/source/blender/functions/backends/llvm/ir_utils.hpp
@@ -28,5 +28,7 @@ namespace FN {
        llvm::Value *byte_ptr_to_ir(llvm::IRBuilder<> &builder, void *ptr);
        llvm::Value *ptr_to_ir(llvm::IRBuilder<> &builder, void *ptr, 
llvm::Type *type);
 
+       LLVMTypes types_of_values(const LLVMValues &values);
+
        llvm::Value *alloca_bytes(llvm::IRBuilder<> &builder, uint size);
  } /* 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
index f6d8ba6a3aa..5a473c48c47 100644
--- a/source/blender/functions/backends/llvm/llvm_gen.hpp
+++ b/source/blender/functions/backends/llvm/llvm_gen.hpp
@@ -6,6 +6,7 @@
 namespace FN {
 
        using LLVMValues = SmallVector<llvm::Value *>;
+       using LLVMTypes = BLI::SmallVector<llvm::Type *>;
 
        class LLVMGenBody : public FunctionBody {
        public:
diff --git a/source/blender/functions/backends/llvm/llvm_types.hpp 
b/source/blender/functions/backends/llvm/llvm_types.hpp
index b346a65085b..3ce825d005c 100644
--- a/source/blender/functions/backends/llvm/llvm_types.hpp
+++ b/source/blender/functions/backends/llvm/llvm_types.hpp
@@ -64,4 +64,11 @@ namespace FN {
                        : m_create_func(create_func) {}
        };
 
+       inline LLVMTypeInfo *get_type_info(const SharedType &type)
+       {
+               auto ext = type->extension<LLVMTypeInfo>();
+               BLI_assert(ext);
+               return ext;
+       }
+
 } /* namespace FN */
\ 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
index 86b4b525899..34a672e758d 100644
--- a/source/blender/functions/backends/llvm/to_tuple_call.cpp
+++ b/source/blender/functions/backends/llvm/to_tuple_call.cpp
@@ -11,15 +11,6 @@
 
 namespace FN {
 
-       using LLVMTypes = BLI::SmallVector<llvm::Type *>;
-
-       static LLVMTypeInfo *get_type_info(const SharedType &type)
-       {
-               auto ext = type->extension<LLVMTypeInfo>();
-               BLI_assert(ext);
-               return ext;
-       }
-
        static llvm::Function *insert_tuple_call_function(
                Function *fn,
                LLVMGenBody *llvm_body,
diff --git a/source/blender/functions/core/signature.hpp 
b/source/blender/functions/core/signature.hpp
index 2128aa99896..da58e528f8d 100644
--- a/source/blender/functions/core/signature.hpp
+++ b/source/blender/functions/core/signature.hpp
@@ -25,6 +25,30 @@ namespace FN {
                SmallTypeVector input_types() const;
                SmallTypeVector output_types() const;
 
+               template<typename T>
+               SmallVector<T *> input_extensions() const
+               {
+                       SmallVector<T *> extensions;
+                       for (InputParameter &param : m_inputs) {
+                               T *ext = param.type()->extension<T>();
+                               BLI_assert(ext);
+                               extensions.append(ext);
+                       }
+                       return extensions;
+               }
+
+               template<typename T>
+               SmallVector<T *> output_extensions() const
+               {
+                       SmallVector<T *> extensions;
+                       for (OutputParameter &param : m_outputs) {
+                               T *ext = param.type()->extension<T>();
+                               BLI_assert(ext);
+                               extensions.append(ext);
+                       }
+                       return extensions;
+               }
+
                bool has_interface(
                        const SmallTypeVector &inputs,
                        const SmallTypeVector &outputs) const;

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

Reply via email to