[Bf-blender-cvs] [662b5ade05d] functions: generate separate wrapper functions
Jacques Lucke
noreply at git.blender.org
Sun Mar 3 15:04:06 CET 2019
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 ¶m : 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 ¶m : 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;
More information about the Bf-blender-cvs
mailing list