{
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)
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);
}
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<Simple_type_descriptor *>(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<Simple_type_descriptor *>(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;
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<Array_type_descriptor>(
+ 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,
+ std::string(get_enumerant_name(instruction.get_operation())));
auto function_type =
get_type<Function_type_descriptor>(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);
}
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,
}
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,
}
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,
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,
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,
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,
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;
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;
{
std::forward<Fn>(fn)(type);
}
+ virtual void visit(Array_type_descriptor &type) override
+ {
+ std::forward<Fn>(fn)(type);
+ }
virtual void visit(Pointer_type_descriptor &type) override
{
std::forward<Fn>(fn)(type);
}
};
+class Array_type_descriptor final : public Type_descriptor
+{
+private:
+ ::LLVMTypeRef type;
+ std::shared_ptr<Type_descriptor> 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<spirv::Decoration_with_parameters> decorations,
+ std::shared_ptr<Type_descriptor> 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<Type_descriptor> &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: