From: Jacob Lifshay Date: Thu, 3 Aug 2017 22:50:58 +0000 (-0700) Subject: implemented more instructions X-Git-Tag: gsoc-2017~54 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=19c717fe2bc7e429eab5ec0ef678fe521002e5a4;p=kazan.git implemented more instructions --- 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 0000000..e5e5fe0 Binary files /dev/null and b/test-files/tri.frag.spv differ diff --git a/test-files/tri.vert b/test-files/tri.vert new file mode 100644 index 0000000..eea2ca9 --- /dev/null +++ b/test-files/tri.vert @@ -0,0 +1,6 @@ +#version 450 + +void main() +{ + gl_Position = vec4(gl_VertexIndex * 0.25, gl_VertexIndex % 2 * 0.5, 0.0, 1.0); +} diff --git a/test-files/tri.vert.spv b/test-files/tri.vert.spv new file mode 100644 index 0000000..f786d09 Binary files /dev/null and b/test-files/tri.vert.spv differ