[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 &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;



More information about the Bf-blender-cvs mailing list