From e6e2d5ccb42f54cc48236daf0ac30cd23ab24a38 Mon Sep 17 00:00:00 2001 From: Jacob Lifshay Date: Fri, 11 Aug 2017 15:12:53 -0700 Subject: [PATCH] add alignment to generated llvm ir --- src/llvm_wrapper/llvm_wrapper.cpp | 6 ++ src/llvm_wrapper/llvm_wrapper.h | 5 ++ src/spirv_to_llvm/spirv_to_llvm.cpp | 124 ++++++++++++++++------------ src/spirv_to_llvm/spirv_to_llvm.h | 109 ++++++++++++++++-------- 4 files changed, 155 insertions(+), 89 deletions(-) diff --git a/src/llvm_wrapper/llvm_wrapper.cpp b/src/llvm_wrapper/llvm_wrapper.cpp index d30fb51..6829317 100644 --- a/src/llvm_wrapper/llvm_wrapper.cpp +++ b/src/llvm_wrapper/llvm_wrapper.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,11 @@ LLVM_string Target::get_host_cpu_features() return LLVM_string::from(retval); } +std::size_t Target_data::get_pointer_alignment(::LLVMTargetDataRef td) noexcept +{ + return llvm::unwrap(td)->getPointerABIAlignment(0); +} + Target_machine Target_machine::create_native_target_machine() { auto target = Target::get_native_target(); diff --git a/src/llvm_wrapper/llvm_wrapper.h b/src/llvm_wrapper/llvm_wrapper.h index 91ccb0e..ce81b9e 100644 --- a/src/llvm_wrapper/llvm_wrapper.h +++ b/src/llvm_wrapper/llvm_wrapper.h @@ -241,6 +241,11 @@ struct Target_data : public Wrapper<::LLVMTargetDataRef, Target_data_deleter> { return Target_data(::LLVMCreateTargetData(str)); } + static std::size_t get_pointer_alignment(::LLVMTargetDataRef td) noexcept; + std::size_t get_pointer_alignment() const noexcept + { + return get_pointer_alignment(get()); + } }; struct Target_machine_deleter diff --git a/src/spirv_to_llvm/spirv_to_llvm.cpp b/src/spirv_to_llvm/spirv_to_llvm.cpp index 1f901fa..4d3b409 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.cpp +++ b/src/spirv_to_llvm/spirv_to_llvm.cpp @@ -389,8 +389,8 @@ void Struct_type_descriptor::complete_type() + std::string(get_enumerant_name(decoration.value))); } auto member_type = member.type->get_or_make_type(); - if(::LLVMGetTypeKind(member_type) == ::LLVMStructTypeKind - && ::LLVMIsOpaqueStruct(member_type)) + if(::LLVMGetTypeKind(member_type.type) == ::LLVMStructTypeKind + && ::LLVMIsOpaqueStruct(member_type.type)) { if(dynamic_cast(member.type.get())) throw Parser_error(instruction_start_index, @@ -400,12 +400,12 @@ void Struct_type_descriptor::complete_type() instruction_start_index, "struct can't have opaque struct members"); } - std::size_t alignment = ::LLVMPreferredAlignmentOfType(target_data, member_type); - assert(is_power_of_2(alignment)); - std::size_t size = ::LLVMABISizeOfType(target_data, member_type); - if(alignment > total_alignment) - total_alignment = alignment; - member_descriptors.push_back(Member_descriptor(alignment, size, member_type)); + assert(is_power_of_2(member_type.alignment)); + std::size_t size = ::LLVMABISizeOfType(target_data, member_type.type); + if(member_type.alignment > total_alignment) + total_alignment = member_type.alignment; + member_descriptors.push_back( + Member_descriptor(member_type.alignment, size, member_type.type)); } assert(member_descriptors.size() == members.size()); assert(is_power_of_2(total_alignment)); @@ -436,8 +436,9 @@ void Struct_type_descriptor::complete_type() { member_types.push_back(::LLVMInt8TypeInContext(context)); // so it isn't empty } - constexpr bool is_packed = false; - ::LLVMStructSetBody(type, member_types.data(), member_types.size(), is_packed); + constexpr bool is_packed = true; + ::LLVMStructSetBody(type.type, member_types.data(), member_types.size(), is_packed); + type.alignment = total_alignment; is_complete = true; } @@ -619,6 +620,7 @@ private: util::Enum_set enabled_capabilities; ::LLVMContextRef context; ::LLVMTargetMachineRef target_machine; + ::LLVMTargetDataRef target_data; [[gnu::unused]] const std::uint64_t shader_id; std::string name_prefix_string; llvm_wrapper::Module module; @@ -663,7 +665,7 @@ private: if(auto *type = dynamic_cast(constant->type.get())) { auto llvm_type = type->get_or_make_type(); - if(::LLVMGetTypeKind(llvm_type) != ::LLVMIntegerTypeKind) + if(::LLVMGetTypeKind(llvm_type.type) != ::LLVMIntegerTypeKind) throw Parser_error(instruction_start_index, instruction_start_index, "id is not a constant integer"); @@ -684,7 +686,7 @@ private: if(auto *type = dynamic_cast(constant->type.get())) { auto llvm_type = type->get_or_make_type(); - if(::LLVMGetTypeKind(llvm_type) != ::LLVMIntegerTypeKind) + if(::LLVMGetTypeKind(llvm_type.type) != ::LLVMIntegerTypeKind) throw Parser_error(instruction_start_index, instruction_start_index, "id is not a constant integer"); @@ -753,8 +755,8 @@ public: } module = llvm_wrapper::Module::create_with_target_machine( get_prefixed_name("module").c_str(), context, target_machine); + target_data = ::LLVMGetModuleDataLayout(module.get()); builder = llvm_wrapper::Builder::create(context); - auto target_data = ::LLVMGetModuleDataLayout(module.get()); constexpr std::size_t no_instruction_index = 0; io_struct = std::make_shared(std::vector{}, @@ -765,8 +767,10 @@ public: assert(implicit_function_arguments.size() == 1); static_assert(io_struct_argument_index == 0, ""); implicit_function_arguments[io_struct_argument_index] = - std::make_shared( - std::vector{}, io_struct, no_instruction_index); + std::make_shared(std::vector{}, + io_struct, + no_instruction_index, + target_data); inputs_struct = std::make_shared(std::vector{}, context, @@ -2180,8 +2184,8 @@ void Spirv_to_llvm::handle_instruction_op_type_void( case Stage::calculate_types: { auto &state = get_id_state(instruction.result); - state.type = std::make_shared(state.decorations, - ::LLVMVoidTypeInContext(context)); + state.type = std::make_shared( + state.decorations, LLVM_type_and_alignment(::LLVMVoidTypeInContext(context), 1)); break; } case Stage::generate_code: @@ -2213,9 +2217,13 @@ void Spirv_to_llvm::handle_instruction_op_type_int(Op_type_int instruction, case 16: case 32: case 64: + { + auto type = ::LLVMIntTypeInContext(context, instruction.width); state.type = std::make_shared( - state.decorations, ::LLVMIntTypeInContext(context, instruction.width)); + state.decorations, + LLVM_type_and_alignment(type, ::LLVMPreferredAlignmentOfType(target_data, type))); break; + } default: throw Parser_error( instruction_start_index, instruction_start_index, "invalid int width"); @@ -2235,24 +2243,25 @@ void Spirv_to_llvm::handle_instruction_op_type_float(Op_type_float instruction, case Stage::calculate_types: { auto &state = get_id_state(instruction.result); + ::LLVMTypeRef type = nullptr; switch(instruction.width) { case 16: - state.type = std::make_shared(state.decorations, - ::LLVMHalfTypeInContext(context)); + type = ::LLVMHalfTypeInContext(context); break; case 32: - state.type = std::make_shared( - state.decorations, ::LLVMFloatTypeInContext(context)); + type = ::LLVMFloatTypeInContext(context); break; case 64: - state.type = std::make_shared( - state.decorations, ::LLVMDoubleTypeInContext(context)); + type = ::LLVMDoubleTypeInContext(context); break; default: throw Parser_error( instruction_start_index, instruction_start_index, "invalid float width"); } + state.type = std::make_shared( + state.decorations, + LLVM_type_and_alignment(type, ::LLVMPreferredAlignmentOfType(target_data, type))); break; } case Stage::generate_code: @@ -2271,7 +2280,8 @@ void Spirv_to_llvm::handle_instruction_op_type_vector(Op_type_vector instruction state.type = std::make_shared( state.decorations, get_type(instruction.component_type, instruction_start_index), - instruction.component_count); + instruction.component_count, + target_data); break; } case Stage::generate_code: @@ -2290,7 +2300,8 @@ void Spirv_to_llvm::handle_instruction_op_type_matrix(Op_type_matrix instruction state.type = std::make_shared( state.decorations, get_type(instruction.column_type, instruction_start_index), - instruction.column_count); + instruction.column_count, + target_data); break; } case Stage::generate_code: @@ -2422,7 +2433,8 @@ void Spirv_to_llvm::handle_instruction_op_type_pointer(Op_type_pointer instructi state.type = std::make_shared( state.decorations, get_type(instruction.type, instruction_start_index), - instruction_start_index); + instruction_start_index, + target_data); } else if(auto *pointer_type = dynamic_cast(state.type.get())) { @@ -2464,7 +2476,8 @@ void Spirv_to_llvm::handle_instruction_op_type_function(Op_type_function instruc state.decorations, get_type(instruction.return_type, instruction_start_index), std::move(args), - instruction_start_index); + instruction_start_index, + target_data); break; } case Stage::generate_code: @@ -2569,7 +2582,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, if(auto *simple_type = dynamic_cast(type.get())) { auto llvm_type = simple_type->get_or_make_type(); - switch(::LLVMGetTypeKind(llvm_type)) + switch(::LLVMGetTypeKind(llvm_type.type)) { case LLVMFloatTypeKind: { @@ -2582,12 +2595,12 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, ::LLVMConstBitCast( ::LLVMConstInt( ::LLVMInt32TypeInContext(context), instruction.value[0], false), - llvm_type)); + llvm_type.type)); break; } case LLVMIntegerTypeKind: { - switch(::LLVMGetIntTypeWidth(llvm_type)) + switch(::LLVMGetIntTypeWidth(llvm_type.type)) { case 16: { @@ -2597,7 +2610,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, instruction_start_index, "OpConstant immediate value is wrong size for type int16"); state.constant = std::make_shared( - type, ::LLVMConstInt(llvm_type, instruction.value[0], false)); + type, ::LLVMConstInt(llvm_type.type, instruction.value[0], false)); break; } case 32: @@ -2608,7 +2621,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, instruction_start_index, "OpConstant immediate value is wrong size for type int32"); state.constant = std::make_shared( - type, ::LLVMConstInt(llvm_type, instruction.value[0], false)); + type, ::LLVMConstInt(llvm_type.type, instruction.value[0], false)); break; } case 64: @@ -2620,7 +2633,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, "OpConstant immediate value is wrong size for type int64"); state.constant = std::make_shared( type, - ::LLVMConstInt(llvm_type, + ::LLVMConstInt(llvm_type.type, (static_cast(instruction.value[1]) << 32) | instruction.value[0], false)); @@ -2632,7 +2645,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, instruction_start_index, instruction_start_index, "unimplemented simple type for OpConstant: " - + std::string(llvm_wrapper::print_type_to_string(llvm_type))); + + std::string(llvm_wrapper::print_type_to_string(llvm_type.type))); } break; } @@ -2649,7 +2662,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, (static_cast(instruction.value[1]) << 32) | instruction.value[0], false), - llvm_type)); + llvm_type.type)); break; } case LLVMHalfTypeKind: @@ -2663,7 +2676,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, ::LLVMConstBitCast( ::LLVMConstInt( ::LLVMInt16TypeInContext(context), instruction.value[0], false), - llvm_type)); + llvm_type.type)); break; } default: @@ -2672,7 +2685,7 @@ void Spirv_to_llvm::handle_instruction_op_constant(Op_constant instruction, instruction_start_index, instruction_start_index, "unimplemented simple type for OpConstant: " - + std::string(llvm_wrapper::print_type_to_string(llvm_type))); + + std::string(llvm_wrapper::print_type_to_string(llvm_type.type))); } } } @@ -2801,7 +2814,7 @@ void Spirv_to_llvm::handle_instruction_op_function(Op_function instruction, 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()); + module.get(), function_name.c_str(), function_type->get_or_make_type().type); llvm_wrapper::Module::set_function_target_machine(function, target_machine); state.function = Function_state(function_type, function, std::move(function_name)); break; @@ -3181,9 +3194,10 @@ void Spirv_to_llvm::handle_instruction_op_variable(Op_variable instruction, auto type = get_type(instruction.result_type, instruction_start_index); state.value = Value(::LLVMBuildAlloca(builder.get(), - type->get_base_type()->get_or_make_type(), + type->get_base_type()->get_or_make_type().type, get_name(instruction.result).c_str()), type); + ::LLVMSetAlignment(state.value->value, type->get_base_type()->get_or_make_type().alignment); return; } case Storage_class::generic: @@ -3250,6 +3264,7 @@ void Spirv_to_llvm::handle_instruction_op_load(Op_load instruction, get_id_state(instruction.pointer).value.value().value, get_name(instruction.result).c_str()), get_type(instruction.result_type, instruction_start_index)); + ::LLVMSetAlignment(state.value->value, state.value->type->get_or_make_type().alignment); break; } } @@ -3278,9 +3293,11 @@ void Spirv_to_llvm::handle_instruction_op_store(Op_store instruction, throw Parser_error(instruction_start_index, instruction_start_index, "OpStore nontemporal not implemented"); - ::LLVMBuildStore(builder.get(), - get_id_state(instruction.object).value.value().value, - get_id_state(instruction.pointer).value.value().value); + auto &object_value = get_id_state(instruction.object).value.value(); + auto &pointer_value = get_id_state(instruction.pointer).value.value(); + ::LLVMSetAlignment(::LLVMBuildStore(builder.get(), + object_value.value, + pointer_value.value), object_value.type->get_or_make_type().alignment); break; } } @@ -3568,7 +3585,7 @@ void Spirv_to_llvm::handle_instruction_op_composite_construct(Op_composite_const throw Parser_error(instruction_start_index, instruction_start_index, "too few inputs to construct a vector"); - result_value = ::LLVMGetUndef(type.get_or_make_type()); + result_value = ::LLVMGetUndef(type.get_or_make_type().type); std::uint32_t insert_index = 0; auto insert_element = [&](::LLVMValueRef element) { @@ -4017,7 +4034,7 @@ void Spirv_to_llvm::handle_instruction_op_convert_f_to_u(Op_convert_f_to_u instr state.value = Value(::LLVMBuildFPToUI(builder.get(), get_id_state(instruction.float_value).value.value().value, - result_type->get_or_make_type(), + result_type->get_or_make_type().type, get_name(instruction.result).c_str()), result_type); break; @@ -4054,7 +4071,7 @@ void Spirv_to_llvm::handle_instruction_op_convert_s_to_f(Op_convert_s_to_f instr state.value = Value(::LLVMBuildSIToFP(builder.get(), get_id_state(instruction.signed_value).value.value().value, - result_type->get_or_make_type(), + result_type->get_or_make_type().type, get_name(instruction.result).c_str()), result_type); break; @@ -4089,17 +4106,17 @@ void Spirv_to_llvm::handle_instruction_op_u_convert(Op_u_convert instruction, + std::string(get_enumerant_name(instruction.get_operation()))); auto result_type = get_type(instruction.result_type, instruction_start_index); auto result_type_int_width = ::LLVMGetIntTypeWidth( - llvm_wrapper::get_scalar_or_vector_element_type(result_type->get_or_make_type())); + llvm_wrapper::get_scalar_or_vector_element_type(result_type->get_or_make_type().type)); auto &arg = get_id_state(instruction.unsigned_value).value.value(); auto arg_int_width = ::LLVMGetIntTypeWidth( - llvm_wrapper::get_scalar_or_vector_element_type(arg.type->get_or_make_type())); + llvm_wrapper::get_scalar_or_vector_element_type(arg.type->get_or_make_type().type)); auto opcode = ::LLVMTrunc; if(result_type_int_width > arg_int_width) opcode = ::LLVMZExt; state.value = Value(::LLVMBuildCast(builder.get(), opcode, arg.value, - result_type->get_or_make_type(), + result_type->get_or_make_type().type, get_name(instruction.result).c_str()), result_type); break; @@ -4240,7 +4257,7 @@ void Spirv_to_llvm::handle_instruction_op_bitcast(Op_bitcast instruction, } state.value = Value(::LLVMBuildBitCast(builder.get(), arg.value, - result_type->get_or_make_type(), + result_type->get_or_make_type().type, get_name(instruction.result).c_str()), result_type); break; @@ -5485,9 +5502,10 @@ void Spirv_to_llvm::handle_instruction_op_switch( get_or_make_label(instruction.default_), instruction.target.size()); for(auto &target : instruction.target) - ::LLVMAddCase(switch_instruction, - ::LLVMConstInt(selector.type->get_or_make_type(), target.part_1, false), - get_or_make_label(target.part_2)); + ::LLVMAddCase( + switch_instruction, + ::LLVMConstInt(selector.type->get_or_make_type().type, target.part_1, false), + get_or_make_label(target.part_2)); break; } } diff --git a/src/spirv_to_llvm/spirv_to_llvm.h b/src/spirv_to_llvm/spirv_to_llvm.h index 475d521..cd01c09 100644 --- a/src/spirv_to_llvm/spirv_to_llvm.h +++ b/src/spirv_to_llvm/spirv_to_llvm.h @@ -31,12 +31,27 @@ #include #include #include +#include #include "llvm_wrapper/llvm_wrapper.h" namespace vulkan_cpu { namespace spirv_to_llvm { +struct LLVM_type_and_alignment +{ + ::LLVMTypeRef type; + std::size_t alignment; + constexpr LLVM_type_and_alignment() noexcept : type(nullptr), alignment(0) + { + } + constexpr LLVM_type_and_alignment(::LLVMTypeRef type, std::size_t alignment) noexcept + : type(type), + alignment(alignment) + { + } +}; + class Simple_type_descriptor; class Vector_type_descriptor; class Matrix_type_descriptor; @@ -71,7 +86,7 @@ public: { } virtual ~Type_descriptor() = default; - virtual ::LLVMTypeRef get_or_make_type() = 0; + virtual LLVM_type_and_alignment get_or_make_type() = 0; virtual void visit(Type_visitor &type_visitor) = 0; void visit(Type_visitor &&type_visitor) { @@ -163,16 +178,16 @@ public: class Simple_type_descriptor final : public Type_descriptor { private: - ::LLVMTypeRef type; + LLVM_type_and_alignment type; public: explicit Simple_type_descriptor(std::vector decorations, - ::LLVMTypeRef type) noexcept + LLVM_type_and_alignment type) noexcept : Type_descriptor(std::move(decorations)), type(type) { } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { return type; } @@ -185,21 +200,35 @@ public: class Vector_type_descriptor final : public Type_descriptor { private: - ::LLVMTypeRef type; + LLVM_type_and_alignment type; std::shared_ptr element_type; std::size_t element_count; public: explicit Vector_type_descriptor(std::vector decorations, std::shared_ptr element_type, - std::size_t element_count) noexcept + std::size_t element_count, + ::LLVMTargetDataRef target_data) noexcept : Type_descriptor(std::move(decorations)), - type(::LLVMVectorType(element_type->get_or_make_type(), element_count)), + type(make_vector_type(element_type, element_count, target_data)), element_type(std::move(element_type)), element_count(element_count) { } - virtual ::LLVMTypeRef get_or_make_type() override + static LLVM_type_and_alignment make_vector_type( + const std::shared_ptr &element_type, + std::size_t element_count, + ::LLVMTargetDataRef target_data) + { + auto llvm_element_type = element_type->get_or_make_type(); + auto type = ::LLVMVectorType(llvm_element_type.type, element_count); + std::size_t alignment = ::LLVMPreferredAlignmentOfType(target_data, type); + constexpr std::size_t max_abi_alignment = alignof(std::max_align_t); + if(alignment > max_abi_alignment) + alignment = max_abi_alignment; + return {type, alignment}; + } + virtual LLVM_type_and_alignment get_or_make_type() override { return type; } @@ -220,22 +249,25 @@ public: class Matrix_type_descriptor final : public Type_descriptor { private: - ::LLVMTypeRef type; + LLVM_type_and_alignment type; std::shared_ptr column_type; std::size_t column_count; public: explicit Matrix_type_descriptor(std::vector decorations, std::shared_ptr column_type, - std::size_t column_count) noexcept + std::size_t column_count, + ::LLVMTargetDataRef target_data) noexcept : Type_descriptor(std::move(decorations)), - type(::LLVMVectorType(column_type->get_element_type()->get_or_make_type(), - column_type->get_element_count() * column_count)), + type(Vector_type_descriptor::make_vector_type(column_type->get_element_type(), + column_type->get_element_count() + * column_count, + target_data)), column_type(std::move(column_type)), column_count(column_count) { } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { return type; } @@ -256,7 +288,7 @@ public: class Array_type_descriptor final : public Type_descriptor { private: - ::LLVMTypeRef type; + LLVM_type_and_alignment type; std::shared_ptr element_type; std::size_t element_count; std::size_t instruction_start_index; @@ -268,18 +300,20 @@ public: 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)), + type(), element_type(std::move(element_type)), element_count(element_count), instruction_start_index(instruction_start_index) { } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { - if(!type) + if(!type.type) { Recursion_checker recursion_checker(recursion_checker_state, instruction_start_index); - type = ::LLVMArrayType(element_type->get_or_make_type(), element_count); + auto llvm_element_type = element_type->get_or_make_type(); + type = LLVM_type_and_alignment(::LLVMArrayType(llvm_element_type.type, element_count), + llvm_element_type.alignment); } return type; } @@ -302,17 +336,18 @@ class Pointer_type_descriptor final : public Type_descriptor private: std::shared_ptr base; std::size_t instruction_start_index; - ::LLVMTypeRef type; + LLVM_type_and_alignment type; Recursion_checker_state recursion_checker_state; public: Pointer_type_descriptor(std::vector decorations, std::shared_ptr base, - std::size_t instruction_start_index) noexcept + std::size_t instruction_start_index, + ::LLVMTargetDataRef target_data) noexcept : Type_descriptor(std::move(decorations)), base(std::move(base)), instruction_start_index(instruction_start_index), - type(nullptr) + type(nullptr, llvm_wrapper::Target_data::get_pointer_alignment(target_data)) { } const std::shared_ptr &get_base_type() const noexcept @@ -326,16 +361,17 @@ public: base = std::move(new_base); } explicit Pointer_type_descriptor(std::vector decorations, - std::size_t instruction_start_index) noexcept + std::size_t instruction_start_index, + ::LLVMTargetDataRef target_data) noexcept : Type_descriptor(std::move(decorations)), base(nullptr), instruction_start_index(instruction_start_index), - type(nullptr) + type(nullptr, llvm_wrapper::Target_data::get_pointer_alignment(target_data)) { } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { - if(!type) + if(!type.type) { Recursion_checker recursion_checker(recursion_checker_state, instruction_start_index); if(!base) @@ -345,7 +381,7 @@ public: "attempting to create type from pointer forward declaration"); auto base_type = base->get_or_make_type(); constexpr unsigned default_address_space = 0; - type = ::LLVMPointerType(base_type, default_address_space); + type.type = ::LLVMPointerType(base_type.type, default_address_space); } return type; } @@ -360,7 +396,7 @@ class Function_type_descriptor final : public Type_descriptor private: std::shared_ptr return_type; std::vector> args; - ::LLVMTypeRef type; + LLVM_type_and_alignment type; Recursion_checker_state recursion_checker_state; std::size_t instruction_start_index; bool is_var_arg; @@ -370,27 +406,28 @@ public: std::shared_ptr return_type, std::vector> args, std::size_t instruction_start_index, + ::LLVMTargetDataRef target_data, bool is_var_arg = false) noexcept : Type_descriptor(std::move(decorations)), return_type(std::move(return_type)), args(std::move(args)), - type(nullptr), + type(nullptr, llvm_wrapper::Target_data::get_pointer_alignment(target_data)), instruction_start_index(instruction_start_index), is_var_arg(is_var_arg) { } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { - if(!type) + if(!type.type) { Recursion_checker recursion_checker(recursion_checker_state, instruction_start_index); std::vector<::LLVMTypeRef> llvm_args; llvm_args.reserve(args.size()); auto llvm_return_type = return_type->get_or_make_type(); for(auto &arg : args) - llvm_args.push_back(arg->get_or_make_type()); - type = ::LLVMFunctionType( - llvm_return_type, llvm_args.data(), llvm_args.size(), is_var_arg); + llvm_args.push_back(arg->get_or_make_type().type); + type.type = ::LLVMFunctionType( + llvm_return_type.type, llvm_args.data(), llvm_args.size(), is_var_arg); } return type; } @@ -419,7 +456,7 @@ public: private: std::vector members; util::Enum_map builtin_members; - ::LLVMTypeRef type; + LLVM_type_and_alignment type; bool is_complete; Recursion_checker_state recursion_checker_state; std::size_t instruction_start_index; @@ -460,7 +497,7 @@ public: : Type_descriptor(std::move(decorations)), members(std::move(members)), builtin_members{}, - type(::LLVMStructCreateNamed(context, name)), + type(::LLVMStructCreateNamed(context, name), 0), is_complete(false), instruction_start_index(instruction_start_index), context(context), @@ -469,7 +506,7 @@ public: for(std::size_t member_index = 0; member_index < members.size(); member_index++) on_add_member(member_index); } - virtual ::LLVMTypeRef get_or_make_type() override + virtual LLVM_type_and_alignment get_or_make_type() override { if(!is_complete) { -- 2.30.2