From 19c717fe2bc7e429eab5ec0ef678fe521002e5a4 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Thu, 3 Aug 2017 15:50:58 -0700 Subject: [PATCH] implemented more instructions --- src/llvm_wrapper/llvm_wrapper.h | 26 ++++- src/spirv_to_llvm/spirv_to_llvm.cpp | 172 ++++++++++++++++++++++++---- src/spirv_to_llvm/spirv_to_llvm.h | 50 ++++++++ test-files/tri.frag | 8 ++ test-files/tri.frag.spv | Bin 0 -> 420 bytes test-files/tri.vert | 6 + test-files/tri.vert.spv | Bin 0 -> 1000 bytes 7 files changed, 240 insertions(+), 22 deletions(-) create mode 100644 test-files/tri.frag create mode 100644 test-files/tri.frag.spv create mode 100644 test-files/tri.vert create mode 100644 test-files/tri.vert.spv diff --git a/src/llvm_wrapper/llvm_wrapper.h b/src/llvm_wrapper/llvm_wrapper.h index f1fcb6c..91ccb0e 100644 --- a/src/llvm_wrapper/llvm_wrapper.h +++ b/src/llvm_wrapper/llvm_wrapper.h @@ -349,6 +349,29 @@ struct Builder : public Wrapper<::LLVMBuilderRef, Builder_deleter> { return Builder(::LLVMCreateBuilderInContext(context)); } + static ::LLVMValueRef build_smod(::LLVMBuilderRef builder, + ::LLVMValueRef lhs, + ::LLVMValueRef rhs, + const char *result_name) + { + auto srem_result = ::LLVMBuildSRem(builder, lhs, rhs, ""); + auto zero_constant = ::LLVMConstInt(::LLVMTypeOf(lhs), 0, false); + auto different_signs = ::LLVMBuildICmp( + builder, ::LLVMIntSLT, ::LLVMBuildXor(builder, lhs, rhs, ""), zero_constant, ""); + auto imperfectly_divides = + ::LLVMBuildICmp(builder, ::LLVMIntNE, srem_result, zero_constant, ""); + auto adjustment = + ::LLVMBuildSelect(builder, + ::LLVMBuildAnd(builder, different_signs, imperfectly_divides, ""), + rhs, + zero_constant, + ""); + return ::LLVMBuildAdd(builder, srem_result, adjustment, result_name); + } + ::LLVMValueRef build_smod(::LLVMValueRef lhs, ::LLVMValueRef rhs, const char *result_name) const + { + return build_smod(get(), lhs, rhs, result_name); + } }; inline ::LLVMTypeRef get_scalar_or_vector_element_type(::LLVMTypeRef type) @@ -441,7 +464,8 @@ struct Orc_jit_stack : public Wrapper<::LLVMOrcJITStackRef, Orc_jit_stack_delete return add_eagerly_compiled_ir( get(), std::move(module), symbol_resolver_callback, symbol_resolver_user_data); } - static std::uintptr_t get_symbol_address(::LLVMOrcJITStackRef orc_jit_stack, const char *symbol_name) + static std::uintptr_t get_symbol_address(::LLVMOrcJITStackRef orc_jit_stack, + const char *symbol_name) { return ::LLVMOrcGetSymbolAddress(orc_jit_stack, symbol_name); } diff --git a/src/spirv_to_llvm/spirv_to_llvm.cpp b/src/spirv_to_llvm/spirv_to_llvm.cpp index 09f567d..1f901fa 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.cpp +++ b/src/spirv_to_llvm/spirv_to_llvm.cpp @@ -654,6 +654,48 @@ private: throw Parser_error(instruction_start_index, instruction_start_index, "type mismatch"); return retval; } + unsigned long long get_unsigned_integer_constant(Id id, std::size_t instruction_start_index) + { + auto &constant = get_id_state(id).constant; + if(!constant) + throw Parser_error( + instruction_start_index, instruction_start_index, "id is not a constant integer"); + if(auto *type = dynamic_cast(constant->type.get())) + { + auto llvm_type = type->get_or_make_type(); + if(::LLVMGetTypeKind(llvm_type) != ::LLVMIntegerTypeKind) + throw Parser_error(instruction_start_index, + instruction_start_index, + "id is not a constant integer"); + } + else + { + throw Parser_error( + instruction_start_index, instruction_start_index, "id is not a constant integer"); + } + return ::LLVMConstIntGetZExtValue(constant->get_or_make_value()); + } + long long get_signed_integer_constant(Id id, std::size_t instruction_start_index) + { + auto &constant = get_id_state(id).constant; + if(!constant) + throw Parser_error( + instruction_start_index, instruction_start_index, "id is not a constant integer"); + if(auto *type = dynamic_cast(constant->type.get())) + { + auto llvm_type = type->get_or_make_type(); + if(::LLVMGetTypeKind(llvm_type) != ::LLVMIntegerTypeKind) + throw Parser_error(instruction_start_index, + instruction_start_index, + "id is not a constant integer"); + } + else + { + throw Parser_error( + instruction_start_index, instruction_start_index, "id is not a constant integer"); + } + return ::LLVMConstIntGetSExtValue(constant->get_or_make_value()); + } std::string get_name(Id id) { auto &name = get_id_state(id).name; @@ -2289,11 +2331,26 @@ void Spirv_to_llvm::handle_instruction_op_type_sampled_image(Op_type_sampled_ima void Spirv_to_llvm::handle_instruction_op_type_array(Op_type_array instruction, std::size_t instruction_start_index) { -#warning finish - throw Parser_error(instruction_start_index, - instruction_start_index, - "instruction not implemented: " - + std::string(get_enumerant_name(instruction.get_operation()))); + switch(stage) + { + case Stage::calculate_types: + { + auto &state = get_id_state(instruction.result); + auto length = get_unsigned_integer_constant(instruction.length, instruction_start_index); + if(length <= 0) + throw Parser_error(instruction_start_index, + instruction_start_index, + "OpTypeArray length must be a positive constant integer"); + state.type = std::make_shared( + state.decorations, + get_type(instruction.element_type, instruction_start_index), + length, + instruction_start_index); + break; + } + case Stage::generate_code: + break; + } } void Spirv_to_llvm::handle_instruction_op_type_runtime_array(Op_type_runtime_array instruction, @@ -2739,7 +2796,10 @@ void Spirv_to_llvm::handle_instruction_op_function(Op_function instruction, + std::string(get_enumerant_name(instruction.get_operation()))); auto function_type = get_type(instruction.function_type, instruction_start_index); - auto function_name = get_or_make_prefixed_name(get_name(current_function_id)); + auto function_name = get_name(current_function_id); + if(function_name.empty() && state.op_entry_points.size() == 1) + function_name = std::string(state.op_entry_points[0].entry_point.name); + function_name = get_or_make_prefixed_name(std::move(function_name)); auto function = ::LLVMAddFunction( module.get(), function_name.c_str(), function_type->get_or_make_type()); llvm_wrapper::Module::set_function_target_machine(function, target_machine); @@ -3296,6 +3356,13 @@ void Spirv_to_llvm::handle_instruction_op_access_chain(Op_access_chain instructi } void operator()(Matrix_type_descriptor &) { +#warning finish + throw Parser_error(instruction_start_index, + instruction_start_index, + "unimplemented composite type for OpAccessChain"); + } + void operator()(Array_type_descriptor &) + { #warning finish throw Parser_error(instruction_start_index, instruction_start_index, @@ -3546,6 +3613,13 @@ void Spirv_to_llvm::handle_instruction_op_composite_construct(Op_composite_const } void operator()(Matrix_type_descriptor &) { +#warning finish + throw Parser_error(instruction_start_index, + instruction_start_index, + "unimplemented result type for OpCompositeConstruct"); + } + void operator()(Array_type_descriptor &) + { #warning finish throw Parser_error(instruction_start_index, instruction_start_index, @@ -3632,6 +3706,13 @@ void Spirv_to_llvm::handle_instruction_op_composite_extract(Op_composite_extract } void operator()(Matrix_type_descriptor &) { +#warning finish + throw Parser_error(instruction_start_index, + instruction_start_index, + "unimplemented composite type for OpCompositeExtract"); + } + void operator()(Array_type_descriptor &) + { #warning finish throw Parser_error(instruction_start_index, instruction_start_index, @@ -3957,11 +4038,28 @@ void Spirv_to_llvm::handle_instruction_op_convert_f_to_s(Op_convert_f_to_s instr void Spirv_to_llvm::handle_instruction_op_convert_s_to_f(Op_convert_s_to_f instruction, std::size_t instruction_start_index) { -#warning finish - throw Parser_error(instruction_start_index, - instruction_start_index, - "instruction not implemented: " - + std::string(get_enumerant_name(instruction.get_operation()))); + switch(stage) + { + case Stage::calculate_types: + break; + case Stage::generate_code: + { + auto &state = get_id_state(instruction.result); + if(!state.decorations.empty()) + throw Parser_error(instruction_start_index, + instruction_start_index, + "decorations on instruction not implemented: " + + std::string(get_enumerant_name(instruction.get_operation()))); + auto result_type = get_type(instruction.result_type, instruction_start_index); + state.value = + Value(::LLVMBuildSIToFP(builder.get(), + get_id_state(instruction.signed_value).value.value().value, + result_type->get_or_make_type(), + get_name(instruction.result).c_str()), + result_type); + break; + } + } } void Spirv_to_llvm::handle_instruction_op_convert_u_to_f(Op_convert_u_to_f instruction, @@ -4223,11 +4321,27 @@ void Spirv_to_llvm::handle_instruction_op_i_mul(Op_i_mul instruction, void Spirv_to_llvm::handle_instruction_op_f_mul(Op_f_mul instruction, std::size_t instruction_start_index) { -#warning finish - throw Parser_error(instruction_start_index, - instruction_start_index, - "instruction not implemented: " - + std::string(get_enumerant_name(instruction.get_operation()))); + switch(stage) + { + case Stage::calculate_types: + break; + case Stage::generate_code: + { + auto &state = get_id_state(instruction.result); + if(!state.decorations.empty()) + throw Parser_error(instruction_start_index, + instruction_start_index, + "decorations on instruction not implemented: " + + std::string(get_enumerant_name(instruction.get_operation()))); + auto result_type = get_type(instruction.result_type, instruction_start_index); + state.value = Value(::LLVMBuildFMul(builder.get(), + get_id_state(instruction.operand_1).value.value().value, + get_id_state(instruction.operand_2).value.value().value, + get_name(instruction.result).c_str()), + result_type); + break; + } + } } void Spirv_to_llvm::handle_instruction_op_u_div(Op_u_div instruction, @@ -4283,11 +4397,27 @@ void Spirv_to_llvm::handle_instruction_op_s_rem(Op_s_rem instruction, void Spirv_to_llvm::handle_instruction_op_s_mod(Op_s_mod instruction, std::size_t instruction_start_index) { -#warning finish - throw Parser_error(instruction_start_index, - instruction_start_index, - "instruction not implemented: " - + std::string(get_enumerant_name(instruction.get_operation()))); + switch(stage) + { + case Stage::calculate_types: + break; + case Stage::generate_code: + { + auto &state = get_id_state(instruction.result); + if(!state.decorations.empty()) + throw Parser_error(instruction_start_index, + instruction_start_index, + "decorations on instruction not implemented: " + + std::string(get_enumerant_name(instruction.get_operation()))); + auto result_type = get_type(instruction.result_type, instruction_start_index); + state.value = + Value(builder.build_smod(get_id_state(instruction.operand_1).value.value().value, + get_id_state(instruction.operand_2).value.value().value, + get_name(instruction.result).c_str()), + result_type); + break; + } + } } void Spirv_to_llvm::handle_instruction_op_f_rem(Op_f_rem instruction, diff --git a/src/spirv_to_llvm/spirv_to_llvm.h b/src/spirv_to_llvm/spirv_to_llvm.h index eda3fe2..475d521 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.h +++ b/src/spirv_to_llvm/spirv_to_llvm.h @@ -40,6 +40,7 @@ namespace spirv_to_llvm class Simple_type_descriptor; class Vector_type_descriptor; class Matrix_type_descriptor; +class Array_type_descriptor; class Pointer_type_descriptor; class Function_type_descriptor; class Struct_type_descriptor; @@ -55,6 +56,7 @@ public: virtual void visit(Simple_type_descriptor &type) = 0; virtual void visit(Vector_type_descriptor &type) = 0; virtual void visit(Matrix_type_descriptor &type) = 0; + virtual void visit(Array_type_descriptor &type) = 0; virtual void visit(Pointer_type_descriptor &type) = 0; virtual void visit(Function_type_descriptor &type) = 0; virtual void visit(Struct_type_descriptor &type) = 0; @@ -94,6 +96,10 @@ public: { std::forward(fn)(type); } + virtual void visit(Array_type_descriptor &type) override + { + std::forward(fn)(type); + } virtual void visit(Pointer_type_descriptor &type) override { std::forward(fn)(type); @@ -247,6 +253,50 @@ public: } }; +class Array_type_descriptor final : public Type_descriptor +{ +private: + ::LLVMTypeRef type; + std::shared_ptr element_type; + std::size_t element_count; + std::size_t instruction_start_index; + Recursion_checker_state recursion_checker_state; + +public: + explicit Array_type_descriptor(std::vector decorations, + std::shared_ptr element_type, + std::size_t element_count, + std::size_t instruction_start_index) noexcept + : Type_descriptor(std::move(decorations)), + type(::LLVMVectorType(element_type->get_or_make_type(), element_count)), + element_type(std::move(element_type)), + element_count(element_count), + instruction_start_index(instruction_start_index) + { + } + virtual ::LLVMTypeRef get_or_make_type() override + { + if(!type) + { + Recursion_checker recursion_checker(recursion_checker_state, instruction_start_index); + type = ::LLVMArrayType(element_type->get_or_make_type(), element_count); + } + return type; + } + virtual void visit(Type_visitor &type_visitor) override + { + type_visitor.visit(*this); + } + const std::shared_ptr &get_element_type() const noexcept + { + return element_type; + } + std::size_t get_element_count() const noexcept + { + return element_count; + } +}; + class Pointer_type_descriptor final : public Type_descriptor { private: diff --git a/test-files/tri.frag b/test-files/tri.frag new file mode 100644 index 0000000..efe2ee8 --- /dev/null +++ b/test-files/tri.frag @@ -0,0 +1,8 @@ +#version 450 + +layout(location = 0) out vec4 color; + +void main() +{ + color = vec4(1, 0, 1, 1); +} diff --git a/test-files/tri.frag.spv b/test-files/tri.frag.spv new file mode 100644 index 0000000000000000000000000000000000000000..e5e5fe0d6bef0478a5b1d18ddd6e43daaa4e33c7 GIT binary patch literal 420 zcmYjN&1%9x7#xk!R9mYE?X4&t73rZ$q0pYnUIHHa082@7ScoyiRPfek>r?eo=*-qa zHcY;6CiDGdgZ8`!wD?50!rvLAO%4pu_0hy{@#;{gtB3Wy976=&D9<%L9Y$gI?h1Xl zAV%~^V{>K!I|5%U=%5c1TeIDo_|+z5X%F=&&us3B%%-l&lG+_J`J#r;6-oY)HVq*i z&6(nwo9y#_#c0m_j=9c+8)%1_-v&OvVcw-SC2r~0uHx!DbJ33;R|3LAuezUJtt-#3+z@tI6BRQJQ%e&;9USh%m^Rsj2&ZIp zU1wDG{AeTMDOp*T)h{FeE#jz|FkapFZg0K%mEUN${cijg27YLxz;D`4(1`6z0Ix8_ zvr!}LHHQf~F@|U5q_LPj=>@huy_V#oRZ!Ed`lee5HBjq%U5Mf;`7zW>9wH$f_zoR+3n}!iqW*L zd_o>RSVa-DTn}nkRlG@gr}Lzr^EP12nNE0VU*?dPWE}3#$TJh1`{e8f1|JRcGGji@ z-2EkG?C9#Nl#Qvmd_Bzv^^GL|s4;I-G1}PWNZ*J)ya@;VM@UZoR4AHeW$0-sN6TCv z`%Jz(JEj;K-JM0n-1!oR9?LQ?bh|z)ecbg~Qx3*1cT$JGij4l$*oi&P)sr2nGTxcD OJd<*A_`iC&W7!`ecv8s# literal 0 HcmV?d00001 -- 2.30.2