diff --git a/doc/langref.html.in b/doc/langref.html.in index 9ea502828211..23d63f2db23f 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2112,8 +2112,8 @@ test "linked list" {
  • A {#link|packed enum#} field uses exactly the bit width of its integer tag type.
  • A {#link|packed union#} field uses exactly the bit width of the union field with the largest bit width.
  • -
  • Non-byte-aligned fields are packed into the smallest possible - byte-aligned integers in accordance with the target endianness. +
  • Non-ABI-aligned fields are packed into the smallest possible + ABI-aligned integers in accordance with the target endianness.
  • @@ -2213,10 +2213,10 @@ fn bar(x: *const u3) u3 { {#code_end#}

    In this case, the function {#syntax#}bar{#endsyntax#} cannot be called becuse the pointer - to the non-byte-aligned field mentions the bit offset, but the function expects a byte-aligned pointer. + to the non-ABI-aligned field mentions the bit offset, but the function expects an ABI-aligned pointer.

    - Pointers to non-byte-aligned fields share the same address as the other fields within their host integer: + Pointers to non-ABI-aligned fields share the same address as the other fields within their host integer:

    {#code_begin|test#} const std = @import("std"); diff --git a/src/all_types.hpp b/src/all_types.hpp index f6e0b2828ce0..d5d708fd09e5 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1067,8 +1067,10 @@ struct TypeStructField { ZigType *type_entry; size_t src_index; size_t gen_index; - uint32_t bit_offset_in_host; // offset from the memory at gen_index + size_t offset; // byte offset from beginning of struct AstNode *decl_node; + uint32_t bit_offset_in_host; // offset from the memory at gen_index + uint32_t host_int_bytes; // size of host integer }; enum ResolveStatus { @@ -1077,6 +1079,8 @@ enum ResolveStatus { ResolveStatusZeroBitsKnown, ResolveStatusAlignmentKnown, ResolveStatusSizeKnown, + ResolveStatusLLVMFwdDecl, + ResolveStatusLLVMFull, }; struct ZigPackage { @@ -1101,14 +1105,13 @@ struct ZigTypeStruct { AstNode *decl_node; TypeStructField *fields; ScopeDecls *decls_scope; - uint64_t size_bytes; HashMap fields_by_name; RootStruct *root_struct; + uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index uint32_t src_field_count; uint32_t gen_field_count; - uint32_t abi_alignment; // known after ResolveStatusAlignmentKnown ContainerLayout layout; ResolveStatus resolve_status; @@ -1164,39 +1167,28 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b); struct ZigTypeUnion { AstNode *decl_node; - ContainerLayout layout; - uint32_t src_field_count; - uint32_t gen_field_count; TypeUnionField *fields; - bool is_invalid; // true if any fields are invalid + ScopeDecls *decls_scope; + HashMap fields_by_name; ZigType *tag_type; // always an enum or null - LLVMTypeRef union_type_ref; + LLVMTypeRef union_llvm_type; + ZigType *most_aligned_union_member; + size_t gen_union_index; + size_t gen_tag_index; + size_t union_abi_size; - ScopeDecls *decls_scope; + uint32_t src_field_count; + uint32_t gen_field_count; - // set this flag temporarily to detect infinite loops - bool embedded_in_current; - bool reported_infinite_err; - // whether we've finished resolving it - bool complete; + ContainerLayout layout; + ResolveStatus resolve_status; + bool have_explicit_tag_type; + bool resolve_loop_flag; // set this flag temporarily to detect infinite loops + bool reported_infinite_err; // whether any of the fields require comptime // the value is not valid until zero_bits_known == true bool requires_comptime; - - bool zero_bits_loop_flag; - bool zero_bits_known; - uint32_t abi_alignment; // also figured out with zero_bits pass - - size_t gen_union_index; - size_t gen_tag_index; - - bool have_explicit_tag_type; - - uint32_t union_size_bytes; - ZigType *most_aligned_union_member; - - HashMap fields_by_name; }; struct FnGenParamInfo { @@ -1277,8 +1269,11 @@ struct ZigType { ZigTypeId id; Buf name; - LLVMTypeRef type_ref; - ZigLLVMDIType *di_type; + // These are not supposed to be accessed directly. They're + // null during semantic analysis, memoized with get_llvm_type + // and get_llvm_di_type + LLVMTypeRef llvm_type; + ZigLLVMDIType *llvm_di_type; union { ZigTypePointer pointer; @@ -1308,8 +1303,14 @@ struct ZigType { ConstExprValue *cached_const_name_val; OnePossibleValue one_possible_value; + // Known after ResolveStatusAlignmentKnown. + uint32_t abi_align; + // The offset in bytes between consecutive array elements of this type. Known + // after ResolveStatusSizeKnown. + size_t abi_size; + // Number of bits of information in this type. Known after ResolveStatusSizeKnown. + size_t size_in_bits; - bool zero_bits; // this is denormalized data bool gen_h_loop_flag; }; @@ -1700,11 +1701,9 @@ struct CodeGen { ZigList use_queue; size_t use_queue_index; ZigList timing_events; - ZigList error_di_types; ZigList tld_ref_source_node_stack; ZigList inline_fns; ZigList test_fns; - ZigList err_enumerators; ZigList errors_by_index; ZigList caches_to_release; size_t largest_err_name_len; @@ -1896,7 +1895,6 @@ struct ZigVar { AstNode *decl_node; ZigLLVMDILocalVariable *di_loc_var; size_t src_arg_index; - size_t gen_arg_index; Scope *parent_scope; Scope *child_scope; LLVMValueRef param_value_ref; diff --git a/src/analyze.cpp b/src/analyze.cpp index 1e0ddd845123..394364c68fc7 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -19,14 +19,15 @@ static const size_t default_backward_branch_quota = 1000; -static Error resolve_enum_type(CodeGen *g, ZigType *enum_type); static Error resolve_struct_type(CodeGen *g, ZigType *struct_type); static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type); static Error ATTRIBUTE_MUST_USE resolve_struct_alignment(CodeGen *g, ZigType *struct_type); static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type); static Error ATTRIBUTE_MUST_USE resolve_union_zero_bits(CodeGen *g, ZigType *union_type); +static Error ATTRIBUTE_MUST_USE resolve_union_alignment(CodeGen *g, ZigType *union_type); static void analyze_fn_body(CodeGen *g, ZigFn *fn_table_entry); +static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status); static bool is_top_level_struct(ZigType *import) { return import->id == ZigTypeIdStruct && import->data.structure.root_struct != nullptr; @@ -264,6 +265,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { zig_unreachable(); case ZigTypeIdStruct: return type_entry->data.structure.resolve_status >= status; + case ZigTypeIdUnion: + return type_entry->data.unionation.resolve_status >= status; case ZigTypeIdEnum: switch (status) { case ResolveStatusUnstarted: @@ -276,20 +279,9 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { return type_entry->data.enumeration.zero_bits_known; case ResolveStatusSizeKnown: return type_entry->data.enumeration.complete; - } - zig_unreachable(); - case ZigTypeIdUnion: - switch (status) { - case ResolveStatusUnstarted: - return true; - case ResolveStatusInvalid: - zig_unreachable(); - case ResolveStatusZeroBitsKnown: - return type_entry->data.unionation.zero_bits_known; - case ResolveStatusAlignmentKnown: - return type_entry->data.unionation.zero_bits_known; - case ResolveStatusSizeKnown: - return type_entry->data.unionation.complete; + case ResolveStatusLLVMFwdDecl: + case ResolveStatusLLVMFull: + return type_entry->llvm_di_type != nullptr; } zig_unreachable(); case ZigTypeIdOpaque: @@ -325,49 +317,18 @@ bool type_is_complete(ZigType *type_entry) { } uint64_t type_size(CodeGen *g, ZigType *type_entry) { - assert(type_is_complete(type_entry)); - - if (!type_has_bits(type_entry)) - return 0; - - if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) { - uint64_t size_in_bits = type_size_bits(g, type_entry); - return (size_in_bits + 7) / 8; - } else if (type_entry->id == ZigTypeIdArray) { - ZigType *child_type = type_entry->data.array.child_type; - if (child_type->id == ZigTypeIdStruct && - child_type->data.structure.layout == ContainerLayoutPacked) - { - uint64_t size_in_bits = type_size_bits(g, type_entry); - return (size_in_bits + 7) / 8; - } - } - - return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref); + assert(type_is_resolved(type_entry, ResolveStatusSizeKnown)); + return type_entry->abi_size; } uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) { - assert(type_is_complete(type_entry)); - - if (!type_has_bits(type_entry)) - return 0; - - if (type_entry->id == ZigTypeIdStruct) { - if (type_entry->data.structure.layout == ContainerLayoutPacked) { - uint64_t result = 0; - for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry); - } - return result; - } else if (type_entry->data.structure.layout == ContainerLayoutExtern) { - return type_size(g, type_entry) * 8; - } - } else if (type_entry->id == ZigTypeIdArray) { - ZigType *child_type = type_entry->data.array.child_type; - return type_entry->data.array.len * type_size_bits(g, child_type); - } + assert(type_is_resolved(type_entry, ResolveStatusSizeKnown)); + return type_entry->size_in_bits; +} - return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref); +uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) { + assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown)); + return type_entry->abi_align; } static bool is_slice(ZigType *type) { @@ -385,16 +346,15 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { return g->builtin_types.entry_promise; } - ZigType *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); ZigType *entry = new_type_table_entry(ZigTypeIdPromise); - entry->type_ref = u8_ptr_type->type_ref; - entry->zero_bits = false; + entry->abi_size = g->builtin_types.entry_usize->abi_size; + entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; + entry->abi_align = g->builtin_types.entry_usize->abi_align; entry->data.promise.result_type = result_type; buf_init_from_str(&entry->name, "promise"); if (result_type != nullptr) { buf_appendf(&entry->name, "->%s", buf_ptr(&result_type->name)); } - entry->di_type = u8_ptr_type->di_type; if (result_type != nullptr) { result_type->promise_parent = entry; @@ -496,36 +456,15 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons assert(child_type->id != ZigTypeIdInvalid); - entry->zero_bits = !type_has_bits(child_type); - - if (!entry->zero_bits) { - if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || - bit_offset_in_host != 0 || allow_zero) - { - ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false, - PtrLenSingle, 0, 0, host_int_bytes, false); - entry->type_ref = peer_type->type_ref; - entry->di_type = peer_type->di_type; - } else { - if (host_int_bytes == 0) { - entry->type_ref = LLVMPointerType(child_type->type_ref, 0); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); - assert(child_type->di_type); - entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, child_type->di_type, - debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); - } else { - ZigType *host_int_type = get_int_type(g, false, host_int_bytes * 8); - entry->type_ref = LLVMPointerType(host_int_type->type_ref, 0); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, host_int_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, host_int_type->type_ref); - entry->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, host_int_type->di_type, - debug_size_in_bits, debug_align_in_bits, buf_ptr(&entry->name)); - } - } + if (type_has_bits(child_type)) { + entry->abi_size = g->builtin_types.entry_usize->abi_size; + entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; + entry->abi_align = g->builtin_types.entry_usize->abi_align; } else { assert(byte_alignment == 0); - entry->di_type = g->builtin_types.entry_void->di_type; + entry->abi_size = 0; + entry->size_in_bits = 0; + entry->abi_align = 0; } entry->data.pointer.ptr_len = ptr_len; @@ -586,89 +525,60 @@ ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type) { } ZigType *get_optional_type(CodeGen *g, ZigType *child_type) { - if (child_type->optional_parent) { - ZigType *entry = child_type->optional_parent; - return entry; - } else { - assertNoError(ensure_complete_type(g, child_type)); - - ZigType *entry = new_type_table_entry(ZigTypeIdOptional); - assert(child_type->type_ref || child_type->zero_bits); - - buf_resize(&entry->name, 0); - buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); - - if (child_type->zero_bits) { - entry->type_ref = LLVMInt1Type(); - entry->di_type = g->builtin_types.entry_bool->di_type; - } else if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) { - assert(child_type->di_type); - // this is an optimization but also is necessary for calling C - // functions where all pointers are maybe pointers - // function types are technically pointers - entry->type_ref = child_type->type_ref; - entry->di_type = child_type->di_type; - if (entry->di_type == g->builtin_types.entry_global_error_set->di_type) { - g->error_di_types.append(&entry->di_type); - } - } else { - assert(child_type->di_type); - // create a struct with a boolean whether this is the null value - LLVMTypeRef elem_types[] = { - child_type->type_ref, - LLVMInt1Type(), - }; - entry->type_ref = LLVMStructType(elem_types, 2, false); - - - ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); - ZigLLVMDIFile *di_file = nullptr; - unsigned line = 0; - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), - compile_unit_scope, di_file, line); - - uint64_t val_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref); - uint64_t val_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_type->type_ref); - uint64_t val_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); - - ZigType *bool_type = g->builtin_types.entry_bool; - uint64_t maybe_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, bool_type->type_ref); - uint64_t maybe_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, bool_type->type_ref); - uint64_t maybe_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1); - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); - - ZigLLVMDIType *di_element_types[] = { - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "val", di_file, line, - val_debug_size_in_bits, - val_debug_align_in_bits, - val_offset_in_bits, - 0, child_type->di_type), - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "maybe", di_file, line, - maybe_debug_size_in_bits, - maybe_debug_align_in_bits, - maybe_offset_in_bits, - 0, bool_type->di_type), - }; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - compile_unit_scope, - buf_ptr(&entry->name), - di_file, line, debug_size_in_bits, debug_align_in_bits, 0, - nullptr, di_element_types, 2, 0, nullptr, ""); + if (child_type->optional_parent != nullptr) { + return child_type->optional_parent; + } - ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); - entry->di_type = replacement_di_type; - } + assert(type_is_resolved(child_type, ResolveStatusSizeKnown)); - entry->data.maybe.child_type = child_type; + ZigType *entry = new_type_table_entry(ZigTypeIdOptional); - child_type->optional_parent = entry; - return entry; + buf_resize(&entry->name, 0); + buf_appendf(&entry->name, "?%s", buf_ptr(&child_type->name)); + + if (!type_has_bits(child_type)) { + entry->size_in_bits = g->builtin_types.entry_bool->size_in_bits; + entry->abi_size = g->builtin_types.entry_bool->abi_size; + entry->abi_align = g->builtin_types.entry_bool->abi_align; + } else if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) { + // This is an optimization but also is necessary for calling C + // functions where all pointers are optional pointers. + // Function types are technically pointers. + entry->size_in_bits = child_type->size_in_bits; + entry->abi_size = child_type->abi_size; + entry->abi_align = child_type->abi_align; + } else { + // This value only matters if the type is legal in a packed struct, which is not + // true for optional types which did not fit the above 2 categories (zero bit child type, + // or nonnull ptr child type, or error set child type). + entry->size_in_bits = child_type->size_in_bits + 1; + + // We're going to make a struct with the child type as the first field, + // and a bool as the second. Since the child type's abi alignment is guaranteed + // to be >= the bool's abi size (1 byte), the added size is exactly equal to the + // child type's ABI alignment. + assert(child_type->abi_align >= g->builtin_types.entry_bool->abi_size); + entry->abi_align = child_type->abi_align; + entry->abi_size = child_type->abi_size + child_type->abi_align; } + + entry->data.maybe.child_type = child_type; + + child_type->optional_parent = entry; + return entry; +} + +static size_t align_forward(size_t addr, size_t alignment) { + return (addr + alignment - 1) & ~(alignment - 1); +} + +static size_t next_field_offset(size_t offset, size_t align_from_zero, size_t field_size, size_t next_field_align) { + // Convert offset to a pretend address which has the specified alignment. + size_t addr = offset + align_from_zero; + // March the address forward to respect the field alignment. + size_t aligned_addr = align_forward(addr + field_size, next_field_align); + // Convert back from pretend address to offset. + return aligned_addr - align_from_zero; } ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type) { @@ -686,8 +596,7 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa } ZigType *entry = new_type_table_entry(ZigTypeIdErrorUnion); - assert(payload_type->di_type); - assert(type_is_complete(payload_type)); + assert(type_is_resolved(payload_type, ResolveStatusSizeKnown)); buf_resize(&entry->name, 0); buf_appendf(&entry->name, "%s!%s", buf_ptr(&err_set_type->name), buf_ptr(&payload_type->name)); @@ -697,68 +606,29 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa if (!type_has_bits(payload_type)) { if (type_has_bits(err_set_type)) { - entry->type_ref = err_set_type->type_ref; - entry->di_type = err_set_type->di_type; - g->error_di_types.append(&entry->di_type); + entry->size_in_bits = err_set_type->size_in_bits; + entry->abi_size = err_set_type->abi_size; + entry->abi_align = err_set_type->abi_align; } else { - entry->zero_bits = true; - entry->di_type = g->builtin_types.entry_void->di_type; + entry->size_in_bits = 0; + entry->abi_size = 0; + entry->abi_align = 0; } } else if (!type_has_bits(err_set_type)) { - entry->type_ref = payload_type->type_ref; - entry->di_type = payload_type->di_type; + entry->size_in_bits = payload_type->size_in_bits; + entry->abi_size = payload_type->abi_size; + entry->abi_align = payload_type->abi_align; } else { - LLVMTypeRef elem_types[] = { - err_set_type->type_ref, - payload_type->type_ref, - }; - entry->type_ref = LLVMStructType(elem_types, 2, false); - - ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); - ZigLLVMDIFile *di_file = nullptr; - unsigned line = 0; - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), - compile_unit_scope, di_file, line); - - uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, err_set_type->type_ref); - uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, err_set_type->type_ref); - uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, err_union_err_index); - - uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, payload_type->type_ref); - uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, payload_type->type_ref); - uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, - err_union_payload_index); - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); - - ZigLLVMDIType *di_element_types[] = { - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "tag", di_file, line, - tag_debug_size_in_bits, - tag_debug_align_in_bits, - tag_offset_in_bits, - 0, err_set_type->di_type), - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "value", di_file, line, - value_debug_size_in_bits, - value_debug_align_in_bits, - value_offset_in_bits, - 0, payload_type->di_type), - }; - - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - compile_unit_scope, - buf_ptr(&entry->name), - di_file, line, - debug_size_in_bits, - debug_align_in_bits, - 0, - nullptr, di_element_types, 2, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); - entry->di_type = replacement_di_type; + entry->abi_align = max(err_set_type->abi_align, payload_type->abi_align); + size_t field_sizes[2]; + size_t field_aligns[2]; + field_sizes[err_union_err_index] = err_set_type->abi_size; + field_aligns[err_union_err_index] = err_set_type->abi_align; + field_sizes[err_union_payload_index] = payload_type->abi_size; + field_aligns[err_union_payload_index] = payload_type->abi_align; + size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[1]); + entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], entry->abi_align); + entry->size_in_bits = entry->abi_size * 8; } g->type_table.put(type_id, entry); @@ -772,31 +642,20 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { type_id.data.array.size = array_size; auto existing_entry = g->type_table.maybe_get(type_id); if (existing_entry) { - ZigType *entry = existing_entry->value; - return entry; + return existing_entry->value; } - assertNoError(ensure_complete_type(g, child_type)); + assert(type_is_resolved(child_type, ResolveStatusSizeKnown)); ZigType *entry = new_type_table_entry(ZigTypeIdArray); - entry->zero_bits = (array_size == 0) || child_type->zero_bits; buf_resize(&entry->name, 0); buf_appendf(&entry->name, "[%" ZIG_PRI_u64 "]%s", array_size, buf_ptr(&child_type->name)); - if (entry->zero_bits) { - entry->di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, 0, - 0, child_type->di_type, 0); - } else { - entry->type_ref = child_type->type_ref ? LLVMArrayType(child_type->type_ref, - (unsigned int)array_size) : nullptr; - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, entry->type_ref); + entry->size_in_bits = child_type->size_in_bits * array_size; + entry->abi_align = child_type->abi_align; + entry->abi_size = child_type->abi_size * array_size; - entry->di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits, - debug_align_in_bits, child_type->di_type, (int)array_size); - } entry->data.array.child_type = child_type; entry->data.array.len = array_size; @@ -804,11 +663,27 @@ ZigType *get_array_type(CodeGen *g, ZigType *child_type, uint64_t array_size) { return entry; } -static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *entry) { +ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { + assert(ptr_type->id == ZigTypeIdPointer); + assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown); + + ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent; + if (*parent_pointer) { + return *parent_pointer; + } + + ZigType *entry = new_type_table_entry(ZigTypeIdStruct); + + // replace the & with [] to go from a ptr type name to a slice type name + buf_resize(&entry->name, 0); + size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3; + buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset); + unsigned element_count = 2; Buf *ptr_field_name = buf_create_from_str("ptr"); Buf *len_field_name = buf_create_from_str("len"); + entry->data.structure.resolve_status = ResolveStatusSizeKnown; entry->data.structure.layout = ContainerLayoutAuto; entry->data.structure.is_slice = true; entry->data.structure.src_field_count = element_count; @@ -816,7 +691,7 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e entry->data.structure.fields = allocate(element_count); entry->data.structure.fields_by_name.init(element_count); entry->data.structure.fields[slice_ptr_index].name = ptr_field_name; - entry->data.structure.fields[slice_ptr_index].type_entry = pointer_type; + entry->data.structure.fields[slice_ptr_index].type_entry = ptr_type; entry->data.structure.fields[slice_ptr_index].src_index = slice_ptr_index; entry->data.structure.fields[slice_ptr_index].gen_index = 0; entry->data.structure.fields[slice_len_index].name = len_field_name; @@ -827,28 +702,20 @@ static void slice_type_common_init(CodeGen *g, ZigType *pointer_type, ZigType *e entry->data.structure.fields_by_name.put(ptr_field_name, &entry->data.structure.fields[slice_ptr_index]); entry->data.structure.fields_by_name.put(len_field_name, &entry->data.structure.fields[slice_len_index]); - if (!type_has_bits(pointer_type->data.pointer.child_type)) { + switch (type_requires_comptime(g, ptr_type)) { + case ReqCompTimeInvalid: + zig_unreachable(); + case ReqCompTimeNo: + break; + case ReqCompTimeYes: + entry->data.structure.requires_comptime = true; + } + + if (!type_has_bits(ptr_type)) { entry->data.structure.gen_field_count = 1; entry->data.structure.fields[slice_ptr_index].gen_index = SIZE_MAX; entry->data.structure.fields[slice_len_index].gen_index = 0; } -} - -ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { - assert(ptr_type->id == ZigTypeIdPointer); - assert(ptr_type->data.pointer.ptr_len == PtrLenUnknown); - - ZigType **parent_pointer = &ptr_type->data.pointer.slice_parent; - if (*parent_pointer) { - return *parent_pointer; - } - - ZigType *entry = new_type_table_entry(ZigTypeIdStruct); - - // replace the & with [] to go from a ptr type name to a slice type name - buf_resize(&entry->name, 0); - size_t name_offset = (ptr_type->data.pointer.ptr_len == PtrLenSingle) ? 1 : 3; - buf_appendf(&entry->name, "[]%s", buf_ptr(&ptr_type->name) + name_offset); ZigType *child_type = ptr_type->data.pointer.child_type; if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || @@ -858,134 +725,24 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { PtrLenUnknown, 0, 0, 0, false); ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); - slice_type_common_init(g, ptr_type, entry); - - entry->type_ref = peer_slice_type->type_ref; - entry->di_type = peer_slice_type->di_type; - entry->data.structure.resolve_status = ResolveStatusSizeKnown; - entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; + entry->size_in_bits = peer_slice_type->size_in_bits; + entry->abi_size = peer_slice_type->abi_size; + entry->abi_align = peer_slice_type->abi_align; *parent_pointer = entry; return entry; } - // If the child type is []const T then we need to make sure the type ref - // and debug info is the same as if the child type were []T. - if (is_slice(child_type)) { - ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; - assert(child_ptr_type->id == ZigTypeIdPointer); - if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || - child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) - { - ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; - ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, - PtrLenUnknown, 0, 0, 0, false); - ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type); - ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false, - PtrLenUnknown, 0, 0, 0, false); - ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); - - entry->type_ref = peer_slice_type->type_ref; - entry->di_type = peer_slice_type->di_type; - entry->data.structure.abi_alignment = peer_slice_type->data.structure.abi_alignment; - } - } - - slice_type_common_init(g, ptr_type, entry); - - if (!entry->type_ref) { - entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&entry->name)); - - ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); - ZigLLVMDIFile *di_file = nullptr; - unsigned line = 0; - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - ZigLLVMTag_DW_structure_type(), buf_ptr(&entry->name), - compile_unit_scope, di_file, line); - - if (child_type->zero_bits) { - LLVMTypeRef element_types[] = { - g->builtin_types.entry_usize->type_ref, - }; - LLVMStructSetBody(entry->type_ref, element_types, 1, false); - - ZigType *usize_type = g->builtin_types.entry_usize; - uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); - uint64_t len_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); - uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); - - ZigLLVMDIType *di_element_types[] = { - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "len", di_file, line, - len_debug_size_in_bits, - len_debug_align_in_bits, - len_offset_in_bits, - 0, usize_type->di_type), - }; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - compile_unit_scope, - buf_ptr(&entry->name), - di_file, line, debug_size_in_bits, debug_align_in_bits, 0, - nullptr, di_element_types, 1, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); - entry->di_type = replacement_di_type; - - entry->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); - } else { - unsigned element_count = 2; - LLVMTypeRef element_types[] = { - ptr_type->type_ref, - g->builtin_types.entry_usize->type_ref, - }; - LLVMStructSetBody(entry->type_ref, element_types, element_count, false); - - - uint64_t ptr_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, ptr_type->type_ref); - uint64_t ptr_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->type_ref); - uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 0); - - ZigType *usize_type = g->builtin_types.entry_usize; - uint64_t len_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, usize_type->type_ref); - uint64_t len_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, usize_type->type_ref); - uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, entry->type_ref, 1); - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); - - ZigLLVMDIType *di_element_types[] = { - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "ptr", di_file, line, - ptr_debug_size_in_bits, - ptr_debug_align_in_bits, - ptr_offset_in_bits, - 0, ptr_type->di_type), - ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(entry->di_type), - "len", di_file, line, - len_debug_size_in_bits, - len_debug_align_in_bits, - len_offset_in_bits, - 0, usize_type->di_type), - }; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - compile_unit_scope, - buf_ptr(&entry->name), - di_file, line, debug_size_in_bits, debug_align_in_bits, 0, - nullptr, di_element_types, 2, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); - entry->di_type = replacement_di_type; - - entry->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref); - } + if (type_has_bits(ptr_type)) { + entry->size_in_bits = ptr_type->size_in_bits + g->builtin_types.entry_usize->size_in_bits; + entry->abi_size = ptr_type->abi_size + g->builtin_types.entry_usize->abi_size; + entry->abi_align = ptr_type->abi_align; + } else { + entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; + entry->abi_size = g->builtin_types.entry_usize->abi_size; + entry->abi_align = g->builtin_types.entry_usize->abi_align; } - - entry->data.structure.resolve_status = ResolveStatusSizeKnown; - *parent_pointer = entry; return entry; } @@ -998,15 +755,20 @@ ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const c ZigType *import = scope ? get_scope_import(scope) : nullptr; unsigned line = source_node ? (unsigned)(source_node->line + 1) : 0; - entry->type_ref = LLVMInt8Type(); - entry->di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, + entry->llvm_type = LLVMInt8Type(); + entry->llvm_di_type = ZigLLVMCreateDebugForwardDeclType(g->dbuilder, ZigLLVMTag_DW_structure_type(), full_name, import ? ZigLLVMFileToScope(import->data.structure.root_struct->di_file) : nullptr, import ? import->data.structure.root_struct->di_file : nullptr, line); - entry->zero_bits = false; entry->data.opaque.bare_name = bare_name; + // The actual size is unknown, but the value must not be 0 because that + // is how type_has_bits is determined. + entry->abi_size = SIZE_MAX; + entry->size_in_bits = SIZE_MAX; + entry->abi_align = 1; + return entry; } @@ -1018,7 +780,6 @@ ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry) { ZigType *bound_fn_type = new_type_table_entry(ZigTypeIdBoundFn); bound_fn_type->data.bound_fn.fn_type = fn_type; - bound_fn_type->zero_bits = true; buf_resize(&bound_fn_type->name, 0); buf_appendf(&bound_fn_type->name, "(bound %s)", buf_ptr(&fn_type->name)); @@ -1114,8 +875,6 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { ZigType *fn_type = new_type_table_entry(ZigTypeIdFn); fn_type->data.fn.fn_type_id = *fn_type_id; - bool skip_debug_info = false; - // populate the name of the type buf_resize(&fn_type->name, 0); if (fn_type->data.fn.fn_type_id.cc == CallingConventionAsync) { @@ -1133,8 +892,6 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { const char *comma = (i == 0) ? "" : ", "; const char *noalias_str = param_info->is_noalias ? "noalias " : ""; buf_appendf(&fn_type->name, "%s%s%s", comma, noalias_str, buf_ptr(¶m_type->name)); - - skip_debug_info = skip_debug_info || !param_type->di_type; } if (fn_type_id->is_var_args) { @@ -1146,116 +903,11 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { buf_appendf(&fn_type->name, " align(%" PRIu32 ")", fn_type_id->alignment); } buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name)); - skip_debug_info = skip_debug_info || !fn_type_id->return_type->di_type; - - // next, loop over the parameters again and compute debug information - // and codegen information - if (!skip_debug_info) { - bool first_arg_return = want_first_arg_sret(g, fn_type_id); - bool is_async = fn_type_id->cc == CallingConventionAsync; - bool is_c_abi = fn_type_id->cc == CallingConventionC; - bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); - // +1 for maybe making the first argument the return value - // +1 for maybe first argument the error return trace - // +2 for maybe arguments async allocator and error code pointer - ZigList gen_param_types = {}; - // +1 because 0 is the return type and - // +1 for maybe making first arg ret val and - // +1 for maybe first argument the error return trace - // +2 for maybe arguments async allocator and error code pointer - ZigList param_di_types = {}; - param_di_types.append(fn_type_id->return_type->di_type); - ZigType *gen_return_type; - if (is_async) { - gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); - } else if (!type_has_bits(fn_type_id->return_type)) { - gen_return_type = g->builtin_types.entry_void; - } else if (first_arg_return) { - ZigType *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false); - gen_param_types.append(gen_type->type_ref); - param_di_types.append(gen_type->di_type); - gen_return_type = g->builtin_types.entry_void; - } else { - gen_return_type = fn_type_id->return_type; - } - fn_type->data.fn.gen_return_type = gen_return_type; - - if (prefix_arg_error_return_trace) { - ZigType *gen_type = get_ptr_to_stack_trace_type(g); - gen_param_types.append(gen_type->type_ref); - param_di_types.append(gen_type->di_type); - } - if (is_async) { - { - // async allocator param - ZigType *gen_type = fn_type_id->async_allocator_type; - gen_param_types.append(gen_type->type_ref); - param_di_types.append(gen_type->di_type); - } - - { - // error code pointer - ZigType *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); - gen_param_types.append(gen_type->type_ref); - param_di_types.append(gen_type->di_type); - } - } - - fn_type->data.fn.gen_param_info = allocate(fn_type_id->param_count); - for (size_t i = 0; i < fn_type_id->param_count; i += 1) { - FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; - ZigType *type_entry = src_param_info->type; - FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i]; - - gen_param_info->src_index = i; - gen_param_info->gen_index = SIZE_MAX; - - if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown))) - return g->builtin_types.entry_invalid; - - if (is_c_abi) { - if ((err = type_resolve(g, type_entry, ResolveStatusSizeKnown))) - return g->builtin_types.entry_invalid; - continue; - } - if (type_has_bits(type_entry)) { - ZigType *gen_type; - if (handle_is_ptr(type_entry)) { - gen_type = get_pointer_to_type(g, type_entry, true); - gen_param_info->is_byval = true; - } else { - gen_type = type_entry; - } - gen_param_info->gen_index = gen_param_types.length; - gen_param_info->type = gen_type; - gen_param_types.append(gen_type->type_ref); - - param_di_types.append(gen_type->di_type); - } - } - - if (is_c_abi) { - FnWalk fn_walk = {}; - fn_walk.id = FnWalkIdTypes; - fn_walk.data.types.param_di_types = ¶m_di_types; - fn_walk.data.types.gen_param_types = &gen_param_types; - walk_function_params(g, fn_type, &fn_walk); - } - - fn_type->data.fn.gen_param_count = gen_param_types.length; - - for (size_t i = 0; i < gen_param_types.length; i += 1) { - assert(gen_param_types.items[i] != nullptr); - } - fn_type->data.fn.raw_type_ref = LLVMFunctionType(gen_return_type->type_ref, - gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); - fn_type->type_ref = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); - fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); - fn_type->di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type, - LLVMStoreSizeOfType(g->target_data_ref, fn_type->type_ref), - LLVMABIAlignmentOfType(g->target_data_ref, fn_type->type_ref), ""); - } + // The fn_type is a pointer; not to be confused with the raw function type. + fn_type->size_in_bits = g->builtin_types.entry_usize->size_in_bits; + fn_type->abi_size = g->builtin_types.entry_usize->abi_size; + fn_type->abi_align = g->builtin_types.entry_usize->abi_align; g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); @@ -1282,14 +934,6 @@ static ZigType *get_root_container_type(CodeGen *g, const char *full_name, Buf * entry->data.structure.decls_scope = create_decls_scope(g, nullptr, nullptr, entry, entry, bare_name); entry->data.structure.root_struct = root_struct; entry->data.structure.layout = ContainerLayoutAuto; - entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), full_name); - - size_t line = 0; // root therefore first line - unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); - - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - dwarf_kind, full_name, - ZigLLVMFileToScope(root_struct->di_file), root_struct->di_file, (unsigned)(line + 1)); buf_init_from_str(&entry->name, full_name); return entry; @@ -1316,16 +960,6 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind break; } - size_t line = decl_node ? decl_node->line : 0; - unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); - - ZigType *import = get_scope_import(scope); - entry->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), full_name); - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - dwarf_kind, full_name, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - import->data.structure.root_struct->di_file, (unsigned)(line + 1)); - buf_init_from_str(&entry->name, full_name); return entry; @@ -1375,7 +1009,9 @@ ZigType *get_generic_fn_type(CodeGen *g, FnTypeId *fn_type_id) { fn_type->data.fn.fn_type_id = *fn_type_id; fn_type->data.fn.is_generic = true; - fn_type->zero_bits = true; + fn_type->abi_size = 0; + fn_type->size_in_bits = 0; + fn_type->abi_align = 0; return fn_type; } @@ -1488,6 +1124,7 @@ static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType ZigType *elem_type = type_entry->data.array.child_type; if ((err = emit_error_unless_type_allowed_in_packed_struct(g, elem_type, source_node))) return err; + // TODO revisit this when doing https://github.com/ziglang/zig/issues/1512 if (type_size(g, type_entry) * 8 == type_size_bits(g, type_entry)) return ErrorNone; add_node_error(g, source_node, @@ -1611,13 +1248,12 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) { ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); buf_resize(&err_set_type->name, 0); buf_appendf(&err_set_type->name, "@typeOf(%s).ReturnType.ErrorSet", buf_ptr(&fn_entry->symbol_name)); - err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; - err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; err_set_type->data.error_set.err_count = 0; err_set_type->data.error_set.errors = nullptr; err_set_type->data.error_set.infer_fn = fn_entry; - - g->error_di_types.append(&err_set_type->di_type); + err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size; return err_set_type; } @@ -1858,10 +1494,10 @@ bool type_is_invalid(ZigType *type_entry) { return true; case ZigTypeIdStruct: return type_entry->data.structure.resolve_status == ResolveStatusInvalid; + case ZigTypeIdUnion: + return type_entry->data.unionation.resolve_status == ResolveStatusInvalid; case ZigTypeIdEnum: return type_entry->data.enumeration.is_invalid; - case ZigTypeIdUnion: - return type_entry->data.unionation.is_invalid; default: return false; } @@ -1869,178 +1505,80 @@ bool type_is_invalid(ZigType *type_entry) { } -static Error resolve_enum_type(CodeGen *g, ZigType *enum_type) { - assert(enum_type->id == ZigTypeIdEnum); - - if (enum_type->data.enumeration.is_invalid) - return ErrorSemanticAnalyzeFail; +ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], + ZigType *field_types[], size_t field_count) +{ + ZigType *struct_type = new_type_table_entry(ZigTypeIdStruct); - if (enum_type->data.enumeration.complete) - return ErrorNone; + buf_init_from_str(&struct_type->name, type_name); - Error err; - if ((err = resolve_enum_zero_bits(g, enum_type))) - return err; + struct_type->data.structure.src_field_count = field_count; + struct_type->data.structure.gen_field_count = 0; + struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; + struct_type->data.structure.fields = allocate(field_count); + struct_type->data.structure.fields_by_name.init(field_count); - AstNode *decl_node = enum_type->data.enumeration.decl_node; + size_t abi_align = 0; + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + field->name = buf_create_from_str(field_names[i]); + field->type_entry = field_types[i]; + field->src_index = i; - if (enum_type->data.enumeration.embedded_in_current) { - if (!enum_type->data.enumeration.reported_infinite_err) { - enum_type->data.enumeration.is_invalid = true; - enum_type->data.enumeration.reported_infinite_err = true; - ErrorMsg *msg = add_node_error(g, decl_node, - buf_sprintf("enum '%s' contains itself", buf_ptr(&enum_type->name))); - emit_error_notes_for_ref_stack(g, msg); + if (type_has_bits(field->type_entry)) { + assert(type_is_resolved(field->type_entry, ResolveStatusSizeKnown)); + if (field->type_entry->abi_align > abi_align) { + abi_align = field->type_entry->abi_align; + } + field->gen_index = struct_type->data.structure.gen_field_count; + struct_type->data.structure.gen_field_count += 1; + } else { + field->gen_index = SIZE_MAX; } - return ErrorSemanticAnalyzeFail; + + auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); + assert(prev_entry == nullptr); } - assert(!enum_type->data.enumeration.zero_bits_loop_flag); - assert(decl_node->type == NodeTypeContainerDecl); - assert(enum_type->di_type); + size_t next_offset = 0; + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + if (field->gen_index == SIZE_MAX) + continue; + field->offset = next_offset; + size_t next_src_field_index = i + 1; + for (; next_src_field_index < field_count; next_src_field_index += 1) { + if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) { + break; + } + } + size_t next_abi_align = (next_src_field_index == field_count) ? + abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align); + } - uint32_t field_count = enum_type->data.enumeration.src_field_count; + struct_type->abi_align = abi_align; + struct_type->abi_size = next_offset; + struct_type->size_in_bits = next_offset * 8; - assert(enum_type->data.enumeration.fields); - ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); - - Scope *scope = &enum_type->data.enumeration.decls_scope->base; - ZigType *import = get_scope_import(scope); - - // set temporary flag - enum_type->data.enumeration.embedded_in_current = true; - - for (uint32_t i = 0; i < field_count; i += 1) { - TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; - - // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t - // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html - di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name), - bigint_as_signed(&enum_field->value)); - } - - // unset temporary flag - enum_type->data.enumeration.embedded_in_current = false; - enum_type->data.enumeration.complete = true; - - if (enum_type->data.enumeration.is_invalid) - return ErrorSemanticAnalyzeFail; - - if (enum_type->zero_bits) { - enum_type->type_ref = LLVMVoidType(); - - uint64_t debug_size_in_bits = 0; - uint64_t debug_align_in_bits = 0; - ZigLLVMDIType **di_root_members = nullptr; - size_t debug_member_count = 0; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - buf_ptr(&enum_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - 0, nullptr, di_root_members, (int)debug_member_count, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, replacement_di_type); - enum_type->di_type = replacement_di_type; - return ErrorNone; - } - - ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type; - - // create debug type for tag - uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_int_type->type_ref); - uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); - ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - tag_debug_size_in_bits, - tag_debug_align_in_bits, - di_enumerators, field_count, - tag_int_type->di_type, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, enum_type->di_type, tag_di_type); - enum_type->di_type = tag_di_type; - return ErrorNone; + return struct_type; } +static size_t get_store_size_bytes(size_t size_in_bits) { + return (size_in_bits + 7) / 8; +} -ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], - ZigType *field_types[], size_t field_count) -{ - ZigType *struct_type = new_type_table_entry(ZigTypeIdStruct); - - buf_init_from_str(&struct_type->name, type_name); - - struct_type->data.structure.src_field_count = field_count; - struct_type->data.structure.gen_field_count = 0; - struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; - struct_type->data.structure.fields = allocate(field_count); - struct_type->data.structure.fields_by_name.init(field_count); - - ZigLLVMDIType **di_element_types = allocate(field_count); - LLVMTypeRef *element_types = allocate(field_count); - for (size_t i = 0; i < field_count; i += 1) { - element_types[struct_type->data.structure.gen_field_count] = field_types[i]->type_ref; - - TypeStructField *field = &struct_type->data.structure.fields[i]; - field->name = buf_create_from_str(field_names[i]); - field->type_entry = field_types[i]; - field->src_index = i; - - if (type_has_bits(field->type_entry)) { - field->gen_index = struct_type->data.structure.gen_field_count; - struct_type->data.structure.gen_field_count += 1; - } else { - field->gen_index = SIZE_MAX; - } - - auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field); - assert(prev_entry == nullptr); - } - - struct_type->type_ref = LLVMStructCreateNamed(LLVMGetGlobalContext(), type_name); - LLVMStructSetBody(struct_type->type_ref, element_types, struct_type->data.structure.gen_field_count, false); - - struct_type->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - ZigLLVMTag_DW_structure_type(), type_name, - ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); - - for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - if (type_struct_field->gen_index == SIZE_MAX) { - continue; - } - ZigType *field_type = type_struct_field->type_entry; - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); - uint64_t debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, type_struct_field->gen_index); - di_element_types[type_struct_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, - ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), - nullptr, 0, - debug_size_in_bits, - debug_align_in_bits, - debug_offset_in_bits, - 0, field_type->di_type); - - assert(di_element_types[type_struct_field->gen_index]); - } - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref); - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMCompileUnitToScope(g->compile_unit), - type_name, nullptr, 0, - debug_size_in_bits, - debug_align_in_bits, - 0, - nullptr, di_element_types, struct_type->data.structure.gen_field_count, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); - struct_type->di_type = replacement_di_type; - struct_type->data.structure.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, struct_type->type_ref); +static size_t get_abi_align_bytes(size_t size_in_bits, size_t pointer_size_bytes) { + size_t store_size_bytes = get_store_size_bytes(size_in_bits); + if (store_size_bytes >= pointer_size_bytes) + return pointer_size_bytes; + return round_to_next_power_of_2(store_size_bytes); +} - return struct_type; +static size_t get_abi_size_bytes(size_t size_in_bits, size_t pointer_size_bytes) { + size_t store_size_bytes = get_store_size_bytes(size_in_bits); + size_t abi_align = get_abi_align_bytes(size_in_bits, pointer_size_bytes); + return align_forward(store_size_bytes, abi_align); } static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { @@ -2068,454 +1606,313 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - struct_type->data.structure.resolve_loop_flag = true; - assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); assert(decl_node->type == NodeTypeContainerDecl); size_t field_count = struct_type->data.structure.src_field_count; - size_t gen_field_count = struct_type->data.structure.gen_field_count; - LLVMTypeRef *element_types = allocate(gen_field_count); - - Scope *scope = &struct_type->data.structure.decls_scope->base; - - size_t gen_field_index = 0; bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); - size_t packed_bits_offset = 0; - size_t first_packed_bits_offset_misalign = SIZE_MAX; - size_t debug_field_count = 0; + struct_type->data.structure.resolve_loop_flag = true; - for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - ZigType *field_type = type_struct_field->type_entry; + uint32_t *host_int_bytes = packed ? allocate(struct_type->data.structure.gen_field_count) : nullptr; - if ((err = ensure_complete_type(g, field_type))) { + // Resolve sizes of all the field types. Done before the offset loop because the offset + // loop has to look ahead. + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + if ((err = type_resolve(g, field->type_entry, ResolveStatusSizeKnown))) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; + return ErrorSemanticAnalyzeFail; } + } - if (struct_type->data.structure.layout == ContainerLayoutExtern) { - if (!type_allowed_in_extern(g, field_type)) { - AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); - add_node_error(g, field_source_node, - buf_sprintf("extern structs cannot contain fields of type '%s'", - buf_ptr(&field_type->name))); - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; - } - } + size_t packed_bits_offset = 0; + size_t next_offset = 0; + size_t first_packed_bits_offset_misalign = SIZE_MAX; + size_t gen_field_index = 0; + size_t size_in_bits = 0; + size_t abi_align = struct_type->abi_align; - if (!type_has_bits(field_type)) + // Calculate offsets + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *field = &struct_type->data.structure.fields[i]; + if (field->gen_index == SIZE_MAX) continue; + ZigType *field_type = field->type_entry; + assert(field_type != nullptr); - type_struct_field->gen_index = gen_field_index; + field->gen_index = gen_field_index; + field->offset = next_offset; if (packed) { - AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); - if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; - } - size_t field_size_in_bits = type_size_bits(g, field_type); size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; + size_in_bits += field_size_in_bits; + if (first_packed_bits_offset_misalign != SIZE_MAX) { // this field is not byte-aligned; it is part of the previous field with a bit offset - type_struct_field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign; + field->bit_offset_in_host = packed_bits_offset - first_packed_bits_offset_misalign; size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; - LLVMTypeRef int_type_ref = LLVMIntType((unsigned)(full_bit_count)); - if (8 * LLVMStoreSizeOfType(g->target_data_ref, int_type_ref) == full_bit_count) { - // next field recovers store alignment - element_types[gen_field_index] = int_type_ref; + size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes); + if (full_abi_size * 8 == full_bit_count) { + // next field recovers ABI alignment + host_int_bytes[gen_field_index] = full_abi_size; gen_field_index += 1; + // TODO: https://github.com/ziglang/zig/issues/1512 + next_offset = next_field_offset(next_offset, abi_align, full_abi_size, 1); + size_in_bits = next_offset * 8; first_packed_bits_offset_misalign = SIZE_MAX; } - } else if (8 * LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref) != field_size_in_bits) { + } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) { first_packed_bits_offset_misalign = packed_bits_offset; - type_struct_field->bit_offset_in_host = 0; + field->bit_offset_in_host = 0; } else { // This is a byte-aligned field (both start and end) in a packed struct. - element_types[gen_field_index] = field_type->type_ref; - type_struct_field->bit_offset_in_host = 0; + host_int_bytes[gen_field_index] = field_type->size_in_bits / 8; + field->bit_offset_in_host = 0; gen_field_index += 1; + // TODO: https://github.com/ziglang/zig/issues/1512 + next_offset = next_field_offset(next_offset, abi_align, field_type->size_in_bits / 8, 1); + size_in_bits = next_offset * 8; } packed_bits_offset = next_packed_bits_offset; } else { - element_types[gen_field_index] = field_type->type_ref; - assert(element_types[gen_field_index]); - gen_field_index += 1; + size_t next_src_field_index = i + 1; + for (; next_src_field_index < field_count; next_src_field_index += 1) { + if (struct_type->data.structure.fields[next_src_field_index].gen_index != SIZE_MAX) { + break; + } + } + size_t next_abi_align = (next_src_field_index == field_count) ? + abi_align : struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align; + next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, next_abi_align); + size_in_bits = next_offset * 8; } - debug_field_count += 1; } if (first_packed_bits_offset_misalign != SIZE_MAX) { size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; - LLVMTypeRef int_type_ref = LLVMIntType((unsigned)full_bit_count); - size_t store_bit_count = 8 * LLVMStoreSizeOfType(g->target_data_ref, int_type_ref); - element_types[gen_field_index] = LLVMIntType((unsigned)store_bit_count); + size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes); + next_offset = next_field_offset(next_offset, abi_align, full_abi_size, abi_align); + host_int_bytes[gen_field_index] = full_abi_size; gen_field_index += 1; } + struct_type->abi_size = next_offset; + struct_type->size_in_bits = size_in_bits; + struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; + struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; struct_type->data.structure.resolve_loop_flag = false; + struct_type->data.structure.host_int_bytes = host_int_bytes; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) - return ErrorSemanticAnalyzeFail; + return ErrorNone; +} - struct_type->data.structure.resolve_status = ResolveStatusSizeKnown; +static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { + assert(union_type->id == ZigTypeIdUnion); - if (struct_type->zero_bits) { - struct_type->type_ref = LLVMVoidType(); + Error err; - ZigType *import = get_scope_import(scope); - uint64_t debug_size_in_bits = 0; - uint64_t debug_align_in_bits = 0; - ZigLLVMDIType **di_element_types = nullptr; - size_t debug_field_count = 0; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - buf_ptr(&struct_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); - ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); - struct_type->di_type = replacement_di_type; + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown) + return ErrorNone; + if ((err = resolve_union_zero_bits(g, union_type))) + return err; + if (union_type->data.unionation.resolve_status >= ResolveStatusAlignmentKnown) return ErrorNone; + + if (union_type->data.unionation.resolve_loop_flag) { + if (!union_type->data.unionation.reported_infinite_err) { + AstNode *decl_node = union_type->data.unionation.decl_node; + union_type->data.unionation.reported_infinite_err = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + ErrorMsg *msg = add_node_error(g, decl_node, + buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); + emit_error_notes_for_ref_stack(g, msg); + } + return ErrorSemanticAnalyzeFail; } - assert(struct_type->di_type); + // set temporary flag + union_type->data.unionation.resolve_loop_flag = true; - // the count may have been adjusting from packing bit fields - gen_field_count = gen_field_index; - struct_type->data.structure.gen_field_count = (uint32_t)gen_field_count; + ZigType *most_aligned_union_member = nullptr; + uint32_t field_count = union_type->data.unionation.src_field_count; + bool packed = union_type->data.unionation.layout == ContainerLayoutPacked; - LLVMStructSetBody(struct_type->type_ref, element_types, (unsigned)gen_field_count, packed); + for (uint32_t i = 0; i < field_count; i += 1) { + TypeUnionField *field = &union_type->data.unionation.fields[i]; + if (field->gen_index == UINT32_MAX) + continue; - // if you hit this assert then probably this type or a related type didn't - // get ensure_complete_type called on it before using it with something that - // requires a complete type - assert(LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref) > 0); + size_t this_field_align; + if (packed) { + // TODO: https://github.com/ziglang/zig/issues/1512 + this_field_align = 1; + // This is the same hack as resolve_struct_alignment. See the comment there. + } else if (field->type_entry == nullptr) { + this_field_align = g->builtin_types.entry_usize->abi_align; + } else { + if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } - ZigLLVMDIType **di_element_types = allocate(debug_field_count); + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; - ZigType *import = get_scope_import(scope); - size_t debug_field_index = 0; - for (size_t i = 0; i < field_count; i += 1) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); - TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; - size_t gen_field_index = type_struct_field->gen_index; - if (gen_field_index == SIZE_MAX) { - continue; + this_field_align = field->type_entry->abi_align; } - ZigType *field_type = type_struct_field->type_entry; - - // if the field is a function, actually the debug info should be a pointer. - ZigLLVMDIType *field_di_type; - if (field_type->id == ZigTypeIdFn) { - ZigType *field_ptr_type = get_pointer_to_type(g, field_type, true); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_ptr_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_ptr_type->type_ref); - field_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, field_type->di_type, - debug_size_in_bits, debug_align_in_bits, buf_ptr(&field_ptr_type->name)); - } else { - field_di_type = field_type->di_type; + if (most_aligned_union_member == nullptr || + this_field_align > most_aligned_union_member->abi_align) + { + most_aligned_union_member = field->type_entry; } + } - assert(field_type->type_ref); - assert(struct_type->type_ref); - assert(struct_type->data.structure.resolve_status == ResolveStatusSizeKnown); - uint64_t debug_size_in_bits; - uint64_t debug_align_in_bits; - uint64_t debug_offset_in_bits; - if (packed) { - debug_size_in_bits = type_size_bits(g, type_struct_field->type_entry); - debug_align_in_bits = 1; - debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, - (unsigned)gen_field_index) + type_struct_field->bit_offset_in_host; + // unset temporary flag + union_type->data.unionation.resolve_loop_flag = false; + union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown; + union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; + + ZigType *tag_type = union_type->data.unionation.tag_type; + if (tag_type != nullptr && type_has_bits(tag_type)) { + if ((err = type_resolve(g, tag_type, ResolveStatusAlignmentKnown))) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (most_aligned_union_member == nullptr) { + union_type->abi_align = tag_type->abi_align; + union_type->data.unionation.gen_tag_index = SIZE_MAX; + union_type->data.unionation.gen_union_index = SIZE_MAX; + } else if (tag_type->abi_align > most_aligned_union_member->abi_align) { + union_type->abi_align = tag_type->abi_align; + union_type->data.unionation.gen_tag_index = 0; + union_type->data.unionation.gen_union_index = 1; } else { - debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); - debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, field_type->type_ref); - debug_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, struct_type->type_ref, - (unsigned)gen_field_index); + union_type->abi_align = most_aligned_union_member->abi_align; + union_type->data.unionation.gen_union_index = 0; + union_type->data.unionation.gen_tag_index = 1; } - di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, - ZigLLVMTypeToScope(struct_type->di_type), buf_ptr(type_struct_field->name), - import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - debug_offset_in_bits, - 0, field_di_type); - assert(di_element_types[debug_field_index]); - debug_field_index += 1; + } else { + assert(most_aligned_union_member != nullptr); + union_type->abi_align = most_aligned_union_member->abi_align; + union_type->data.unionation.gen_union_index = SIZE_MAX; + union_type->data.unionation.gen_tag_index = SIZE_MAX; } - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, struct_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, struct_type->type_ref); - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - buf_ptr(&struct_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, struct_type->di_type, replacement_di_type); - struct_type->di_type = replacement_di_type; - return ErrorNone; } static Error resolve_union_type(CodeGen *g, ZigType *union_type) { assert(union_type->id == ZigTypeIdUnion); - if (union_type->data.unionation.complete) + Error err; + + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + if (union_type->data.unionation.resolve_status >= ResolveStatusSizeKnown) return ErrorNone; - Error err; - if ((err = resolve_union_zero_bits(g, union_type))) + if ((err = resolve_union_alignment(g, union_type))) return err; AstNode *decl_node = union_type->data.unionation.decl_node; - if (union_type->data.unionation.embedded_in_current) { + + assert(decl_node->type == NodeTypeContainerDecl); + + uint32_t field_count = union_type->data.unionation.src_field_count; + ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; + + assert(union_type->data.unionation.fields); + + size_t union_abi_size = 0; + size_t union_size_in_bits = 0; + + if (union_type->data.unionation.resolve_loop_flag) { if (!union_type->data.unionation.reported_infinite_err) { union_type->data.unionation.reported_infinite_err = true; - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; ErrorMsg *msg = add_node_error(g, decl_node, - buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); + buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name))); emit_error_notes_for_ref_stack(g, msg); } return ErrorSemanticAnalyzeFail; } - assert(!union_type->data.unionation.zero_bits_loop_flag); - assert(decl_node->type == NodeTypeContainerDecl); - assert(union_type->di_type); - - uint32_t field_count = union_type->data.unionation.src_field_count; + // set temporary flag + union_type->data.unionation.resolve_loop_flag = true; - assert(union_type->data.unionation.fields); + for (uint32_t i = 0; i < field_count; i += 1) { + TypeUnionField *union_field = &union_type->data.unionation.fields[i]; + ZigType *field_type = union_field->type_entry; - uint32_t gen_field_count = union_type->data.unionation.gen_field_count; - ZigLLVMDIType **union_inner_di_types = allocate(gen_field_count); - - ZigType *most_aligned_union_member = nullptr; - uint64_t size_of_most_aligned_member_in_bits = 0; - uint64_t biggest_align_in_bits = 0; - uint64_t biggest_size_in_bits = 0; - - Scope *scope = &union_type->data.unionation.decls_scope->base; - ZigType *import = get_scope_import(scope); - - // set temporary flag - union_type->data.unionation.embedded_in_current = true; - - - for (uint32_t i = 0; i < field_count; i += 1) { - AstNode *field_node = decl_node->data.container_decl.fields.at(i); - TypeUnionField *union_field = &union_type->data.unionation.fields[i]; - ZigType *field_type = union_field->type_entry; - - if ((err = ensure_complete_type(g, field_type))) { - union_type->data.unionation.is_invalid = true; - continue; + if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } + if (type_is_invalid(union_type)) + return ErrorSemanticAnalyzeFail; + if (!type_has_bits(field_type)) continue; - uint64_t store_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, field_type->type_ref); - uint64_t abi_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, field_type->type_ref); - - assert(store_size_in_bits > 0); - assert(abi_align_in_bits > 0); - - union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, - ZigLLVMTypeToScope(union_type->di_type), buf_ptr(union_field->enum_field->name), - import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), - store_size_in_bits, - abi_align_in_bits, - 0, - 0, field_type->di_type); - - biggest_size_in_bits = max(biggest_size_in_bits, store_size_in_bits); - - if (!most_aligned_union_member || abi_align_in_bits > biggest_align_in_bits) { - most_aligned_union_member = field_type; - biggest_align_in_bits = abi_align_in_bits; - size_of_most_aligned_member_in_bits = store_size_in_bits; - } + union_abi_size = max(union_abi_size, field_type->abi_size); + union_size_in_bits = max(union_size_in_bits, field_type->size_in_bits); } - - // unset temporary flag - union_type->data.unionation.embedded_in_current = false; - union_type->data.unionation.complete = true; - union_type->data.unionation.union_size_bytes = biggest_size_in_bits / 8; - union_type->data.unionation.most_aligned_union_member = most_aligned_union_member; - - if (union_type->data.unionation.is_invalid) - return ErrorSemanticAnalyzeFail; - - if (union_type->zero_bits) { - union_type->type_ref = LLVMVoidType(); - - uint64_t debug_size_in_bits = 0; - uint64_t debug_align_in_bits = 0; - ZigLLVMDIType **di_root_members = nullptr; - size_t debug_member_count = 0; - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - buf_ptr(&union_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - 0, di_root_members, (int)debug_member_count, 0, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); - union_type->di_type = replacement_di_type; - return ErrorNone; + // The union itself for now has to be treated as being independently aligned. + // See https://github.com/ziglang/zig/issues/2166. + if (most_aligned_union_member != nullptr) { + union_abi_size = align_forward(union_abi_size, most_aligned_union_member->abi_align); } - uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; + // unset temporary flag + union_type->data.unionation.resolve_loop_flag = false; + union_type->data.unionation.resolve_status = ResolveStatusSizeKnown; + union_type->data.unionation.union_abi_size = union_abi_size; ZigType *tag_type = union_type->data.unionation.tag_type; - if (tag_type == nullptr || tag_type->zero_bits) { - assert(most_aligned_union_member != nullptr); - - if (padding_in_bits > 0) { - ZigType *u8_type = get_int_type(g, false, 8); - ZigType *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); - LLVMTypeRef union_element_types[] = { - most_aligned_union_member->type_ref, - padding_array->type_ref, - }; - LLVMStructSetBody(union_type->type_ref, union_element_types, 2, false); + if (tag_type != nullptr && type_has_bits(tag_type)) { + if ((err = type_resolve(g, tag_type, ResolveStatusSizeKnown))) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (most_aligned_union_member == nullptr) { + union_type->abi_size = tag_type->abi_size; + union_type->size_in_bits = tag_type->size_in_bits; } else { - LLVMStructSetBody(union_type->type_ref, &most_aligned_union_member->type_ref, 1, false); + size_t field_sizes[2]; + size_t field_aligns[2]; + field_sizes[union_type->data.unionation.gen_tag_index] = tag_type->abi_size; + field_aligns[union_type->data.unionation.gen_tag_index] = tag_type->abi_align; + field_sizes[union_type->data.unionation.gen_union_index] = union_abi_size; + field_aligns[union_type->data.unionation.gen_union_index] = most_aligned_union_member->abi_align; + size_t field2_offset = next_field_offset(0, union_type->abi_align, field_sizes[0], field_aligns[1]); + union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], union_type->abi_align); + union_type->size_in_bits = union_type->abi_size * 8; } - union_type->data.unionation.union_type_ref = union_type->type_ref; - union_type->data.unionation.gen_tag_index = SIZE_MAX; - union_type->data.unionation.gen_union_index = SIZE_MAX; - - assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type->type_ref) >= biggest_align_in_bits); - assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref) >= biggest_size_in_bits); - - // create debug type for union - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, - gen_field_count, 0, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); - union_type->di_type = replacement_di_type; - return ErrorNone; - } - - LLVMTypeRef union_type_ref; - if (padding_in_bits > 0) { - ZigType *u8_type = get_int_type(g, false, 8); - ZigType *padding_array = get_array_type(g, u8_type, padding_in_bits / 8); - LLVMTypeRef union_element_types[] = { - most_aligned_union_member->type_ref, - padding_array->type_ref, - }; - union_type_ref = LLVMStructType(union_element_types, 2, false); - } else if (most_aligned_union_member == nullptr) { - union_type->data.unionation.gen_tag_index = SIZE_MAX; - union_type->data.unionation.gen_union_index = SIZE_MAX; - union_type->type_ref = tag_type->type_ref; - - ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, tag_type->di_type); - union_type->di_type = tag_type->di_type; - return ErrorNone; - } else { - union_type_ref = most_aligned_union_member->type_ref; - } - union_type->data.unionation.union_type_ref = union_type_ref; - - assert(8*LLVMABIAlignmentOfType(g->target_data_ref, union_type_ref) >= biggest_align_in_bits); - assert(8*LLVMStoreSizeOfType(g->target_data_ref, union_type_ref) >= biggest_size_in_bits); - - // create llvm type for root struct - ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; - uint64_t align_of_tag_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_int_type->type_ref); - - if (align_of_tag_in_bits >= biggest_align_in_bits) { - union_type->data.unionation.gen_tag_index = 0; - union_type->data.unionation.gen_union_index = 1; } else { - union_type->data.unionation.gen_union_index = 0; - union_type->data.unionation.gen_tag_index = 1; + union_type->abi_size = union_abi_size; + union_type->size_in_bits = union_size_in_bits; } - LLVMTypeRef root_struct_element_types[2]; - root_struct_element_types[union_type->data.unionation.gen_tag_index] = tag_type->type_ref; - root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; - LLVMStructSetBody(union_type->type_ref, root_struct_element_types, 2, false); - - - // create debug type for union - ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, - ZigLLVMTypeToScope(union_type->di_type), "AnonUnion", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - biggest_size_in_bits, biggest_align_in_bits, 0, union_inner_di_types, - gen_field_count, 0, ""); - - uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->type_ref, - union_type->data.unionation.gen_union_index); - uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->type_ref, - union_type->data.unionation.gen_tag_index); - - ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, - ZigLLVMTypeToScope(union_type->di_type), "payload", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - biggest_size_in_bits, - biggest_align_in_bits, - union_offset_in_bits, - 0, union_di_type); - - uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); - uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); - - ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, - ZigLLVMTypeToScope(union_type->di_type), "tag", - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - tag_debug_size_in_bits, - tag_debug_align_in_bits, - tag_offset_in_bits, - 0, tag_type->di_type); - - ZigLLVMDIType *di_root_members[2]; - di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type; - di_root_members[union_type->data.unionation.gen_union_index] = union_member_di_type; - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, union_type->type_ref); - uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, union_type->type_ref); - ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - buf_ptr(&union_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - debug_size_in_bits, - debug_align_in_bits, - 0, nullptr, di_root_members, 2, 0, nullptr, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, union_type->di_type, replacement_di_type); - union_type->di_type = replacement_di_type; - return ErrorNone; } static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { assert(enum_type->id == ZigTypeIdEnum); + if (enum_type->data.enumeration.is_invalid) + return ErrorSemanticAnalyzeFail; + if (enum_type->data.enumeration.zero_bits_known) return ErrorNone; @@ -2531,7 +1928,6 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { AstNode *decl_node = enum_type->data.enumeration.decl_node; assert(decl_node->type == NodeTypeContainerDecl); - assert(enum_type->di_type); assert(!enum_type->data.enumeration.fields); uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; @@ -2564,6 +1960,10 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); } + enum_type->size_in_bits = tag_int_type->size_in_bits; + enum_type->abi_size = tag_int_type->abi_size; + enum_type->abi_align = tag_int_type->abi_align; + // TODO: Are extern enums allowed to have an init_arg_expr? if (decl_node->data.container_decl.init_arg_expr != nullptr) { ZigType *wanted_tag_int_type = analyze_type_expr(g, scope, decl_node->data.container_decl.init_arg_expr); @@ -2587,7 +1987,9 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { } } enum_type->data.enumeration.tag_int_type = tag_int_type; - enum_type->type_ref = tag_int_type->type_ref; + enum_type->size_in_bits = tag_int_type->size_in_bits; + enum_type->abi_size = tag_int_type->abi_size; + enum_type->abi_align = tag_int_type->abi_align; for (uint32_t field_i = 0; field_i < field_count; field_i += 1) { AstNode *field_node = decl_node->data.container_decl.fields.at(field_i); @@ -2671,8 +2073,8 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { } enum_type->data.enumeration.zero_bits_loop_flag = false; - enum_type->zero_bits = !type_has_bits(tag_int_type); enum_type->data.enumeration.zero_bits_known = true; + enum_type->data.enumeration.complete = true; if (enum_type->data.enumeration.is_invalid) return ErrorSemanticAnalyzeFail; @@ -2683,12 +2085,20 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { assert(struct_type->id == ZigTypeIdStruct); + Error err; + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; if (struct_type->data.structure.resolve_status >= ResolveStatusZeroBitsKnown) return ErrorNone; + AstNode *decl_node = struct_type->data.structure.decl_node; + assert(decl_node->type == NodeTypeContainerDecl); + if (struct_type->data.structure.resolve_loop_flag) { + // TODO This is a problem. I believe it can be solved with lazy values. + struct_type->size_in_bits = SIZE_MAX; + struct_type->abi_size = SIZE_MAX; struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown; struct_type->data.structure.resolve_loop_flag = false; return ErrorNone; @@ -2696,10 +2106,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { struct_type->data.structure.resolve_loop_flag = true; - AstNode *decl_node = struct_type->data.structure.decl_node; - assert(decl_node->type == NodeTypeContainerDecl); - assert(struct_type->di_type); - assert(!struct_type->data.structure.fields); size_t field_count = decl_node->data.container_decl.fields.length; struct_type->data.structure.src_field_count = (uint32_t)field_count; @@ -2718,7 +2124,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { if (field_node->data.struct_field.type == nullptr) { add_node_error(g, field_node, buf_sprintf("struct field missing type")); struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; + return ErrorSemanticAnalyzeFail; } auto field_entry = struct_type->data.structure.fields_by_name.put_unique(type_struct_field->name, type_struct_field); @@ -2727,11 +2133,33 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { buf_sprintf("duplicate struct field: '%s'", buf_ptr(type_struct_field->name))); add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; + return ErrorSemanticAnalyzeFail; } ZigType *field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); type_struct_field->type_entry = field_type; + if (type_is_invalid(field_type)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + + if (struct_type->data.structure.layout == ContainerLayoutExtern && + !type_allowed_in_extern(g, field_type)) + { + add_node_error(g, field_node, + buf_sprintf("extern structs cannot contain fields of type '%s'", + buf_ptr(&field_type->name))); + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } else if (struct_type->data.structure.layout == ContainerLayoutPacked) { + if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_node))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + } + type_struct_field->src_index = i; type_struct_field->gen_index = SIZE_MAX; @@ -2739,21 +2167,19 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { add_node_error(g, field_node->data.struct_field.value, buf_sprintf("enums, not structs, support field assignment")); } - if (field_type->id == ZigTypeIdOpaque) { add_node_error(g, field_node->data.struct_field.type, buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs")); struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; + return ErrorSemanticAnalyzeFail; } - switch (type_requires_comptime(g, field_type)) { case ReqCompTimeYes: struct_type->data.structure.requires_comptime = true; break; case ReqCompTimeInvalid: struct_type->data.structure.resolve_status = ResolveStatusInvalid; - continue; + return ErrorSemanticAnalyzeFail; case ReqCompTimeNo: break; } @@ -2767,7 +2193,10 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { struct_type->data.structure.resolve_loop_flag = false; struct_type->data.structure.gen_field_count = (uint32_t)gen_field_index; - struct_type->zero_bits = (gen_field_index == 0); + if (gen_field_index != 0) { + struct_type->abi_size = SIZE_MAX; + struct_type->size_in_bits = SIZE_MAX; + } if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; @@ -2785,9 +2214,10 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown) return ErrorNone; - if ((err = resolve_struct_zero_bits(g, struct_type))) return err; + if (struct_type->data.structure.resolve_status >= ResolveStatusAlignmentKnown) + return ErrorNone; AstNode *decl_node = struct_type->data.structure.decl_node; @@ -2803,22 +2233,19 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { struct_type->data.structure.resolve_loop_flag = true; assert(decl_node->type == NodeTypeContainerDecl); - assert(struct_type->di_type); size_t field_count = struct_type->data.structure.src_field_count; - if (struct_type->data.structure.layout == ContainerLayoutPacked) { - struct_type->data.structure.abi_alignment = 1; - for (size_t i = 0; i < field_count; i += 1) { - TypeStructField *field = &struct_type->data.structure.fields[i]; - if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; - } - } - } else for (size_t i = 0; i < field_count; i += 1) { + bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; + + for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = &struct_type->data.structure.fields[i]; - uint32_t this_field_align; + if (field->gen_index == SIZE_MAX) + continue; + size_t this_field_align; + if (packed) { + // TODO: https://github.com/ziglang/zig/issues/1512 + this_field_align = 1; // TODO If we have no type_entry for the field, we've already failed to // compile the program correctly. This stage1 compiler needs a deeper // reworking to make this correct, or we can ignore the problem @@ -2827,28 +2254,19 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { // on itself. When this false positive happens we assume a pointer-aligned // field, which is usually fine but could be incorrectly over-aligned or // even under-aligned. See https://github.com/ziglang/zig/issues/1512 - if (field->type_entry == nullptr) { - this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); + } else if (field->type_entry == nullptr) { + this_field_align = g->builtin_types.entry_usize->abi_align; } else { - if (type_is_invalid(field->type_entry)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; - } - - if (!type_has_bits(field->type_entry)) - continue; - if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; + return ErrorSemanticAnalyzeFail; } - - this_field_align = get_abi_alignment(g, field->type_entry); - assert(this_field_align != 0); + this_field_align = field->type_entry->abi_align; } - // alignment of structs is the alignment of the most-aligned field - if (this_field_align > struct_type->data.structure.abi_alignment) { - struct_type->data.structure.abi_alignment = this_field_align; + + // TODO: https://github.com/ziglang/zig/issues/1512 + if (this_field_align > struct_type->abi_align) { + struct_type->abi_align = this_field_align; } } @@ -2867,57 +2285,41 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { Error err; - if (union_type->data.unionation.is_invalid) + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; - if (union_type->data.unionation.zero_bits_known) + if (union_type->data.unionation.resolve_status >= ResolveStatusZeroBitsKnown) return ErrorNone; - if (type_is_invalid(union_type)) - return ErrorSemanticAnalyzeFail; - - if (union_type->data.unionation.zero_bits_loop_flag) { + if (union_type->data.unionation.resolve_loop_flag) { // If we get here it's due to recursion. From this we conclude that the struct is - // not zero bits, and if abi_alignment == 0 we further conclude that the first field - // is a pointer to this very struct, or a function pointer with parameters that - // reference such a type. - union_type->data.unionation.zero_bits_known = true; - union_type->data.unionation.zero_bits_loop_flag = false; - if (union_type->data.unionation.abi_alignment == 0) { - if (union_type->data.unionation.layout == ContainerLayoutPacked) { - union_type->data.unionation.abi_alignment = 1; - } else { - union_type->data.unionation.abi_alignment = LLVMABIAlignmentOfType(g->target_data_ref, - LLVMPointerType(LLVMInt8Type(), 0)); - } - } + // not zero bits. + // TODO actually it could still be zero bits. Here we should continue analyzing + // the union from the next field index. + union_type->data.unionation.resolve_status = ResolveStatusZeroBitsKnown; + union_type->data.unionation.resolve_loop_flag = false; + union_type->abi_size = SIZE_MAX; + union_type->size_in_bits = SIZE_MAX; return ErrorNone; } - union_type->data.unionation.zero_bits_loop_flag = true; + union_type->data.unionation.resolve_loop_flag = true; AstNode *decl_node = union_type->data.unionation.decl_node; assert(decl_node->type == NodeTypeContainerDecl); - assert(union_type->di_type); - assert(!union_type->data.unionation.fields); + assert(union_type->data.unionation.fields == nullptr); uint32_t field_count = (uint32_t)decl_node->data.container_decl.fields.length; if (field_count == 0) { add_node_error(g, decl_node, buf_sprintf("unions must have 1 or more fields")); - union_type->data.unionation.src_field_count = field_count; - union_type->data.unionation.fields = nullptr; - union_type->data.unionation.is_invalid = true; - union_type->data.unionation.zero_bits_loop_flag = false; - union_type->data.unionation.zero_bits_known = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } union_type->data.unionation.src_field_count = field_count; union_type->data.unionation.fields = allocate(field_count); union_type->data.unionation.fields_by_name.init(field_count); - uint32_t biggest_align_bytes = 0; - Scope *scope = &union_type->data.unionation.decls_scope->base; HashMap occupied_tag_values = {}; @@ -2931,7 +2333,6 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety); bool *covered_enum_fields; ZigLLVMDIEnumerator **di_enumerators; - uint32_t abi_alignment_so_far; if (create_enum_type) { occupied_tag_values.init(field_count); @@ -2941,13 +2342,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { if (enum_type_node != nullptr) { tag_int_type = analyze_type_expr(g, scope, enum_type_node); if (type_is_invalid(tag_int_type)) { - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } if (tag_int_type->id != ZigTypeIdInt) { add_node_error(g, enum_type_node, buf_sprintf("expected integer tag type, found '%s'", buf_ptr(&tag_int_type->name))); - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } } else if (auto_layout && field_count == 1) { @@ -2955,13 +2356,15 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } else { tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1); } - abi_alignment_so_far = get_abi_alignment(g, tag_int_type); tag_type = new_type_table_entry(ZigTypeIdEnum); buf_resize(&tag_type->name, 0); buf_appendf(&tag_type->name, "@TagType(%s)", buf_ptr(&union_type->name)); - tag_type->type_ref = tag_int_type->type_ref; - tag_type->zero_bits = tag_int_type->zero_bits; + tag_type->llvm_type = tag_int_type->llvm_type; + tag_type->llvm_di_type = tag_int_type->llvm_di_type; + tag_type->abi_size = tag_int_type->abi_size; + tag_type->abi_align = tag_int_type->abi_align; + tag_type->size_in_bits = tag_int_type->size_in_bits; tag_type->data.enumeration.tag_int_type = tag_int_type; tag_type->data.enumeration.zero_bits_known = true; @@ -2975,11 +2378,11 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { } else if (enum_type_node != nullptr) { ZigType *enum_type = analyze_type_expr(g, scope, enum_type_node); if (type_is_invalid(enum_type)) { - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } if (enum_type->id != ZigTypeIdEnum) { - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; add_node_error(g, enum_type_node, buf_sprintf("expected enum tag type, found '%s'", buf_ptr(&enum_type->name))); return ErrorSemanticAnalyzeFail; @@ -2989,11 +2392,9 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { return err; } tag_type = enum_type; - abi_alignment_so_far = get_abi_alignment(g, enum_type); // this populates src_field_count covered_enum_fields = allocate(enum_type->data.enumeration.src_field_count); } else { tag_type = nullptr; - abi_alignment_so_far = 0; } union_type->data.unionation.tag_type = tag_type; @@ -3004,14 +2405,15 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { TypeUnionField *union_field = &union_type->data.unionation.fields[i]; union_field->name = field_node->data.struct_field.name; union_field->decl_node = field_node; + union_field->gen_index = UINT32_MAX; auto field_entry = union_type->data.unionation.fields_by_name.put_unique(union_field->name, union_field); if (field_entry != nullptr) { ErrorMsg *msg = add_node_error(g, field_node, buf_sprintf("duplicate union field: '%s'", buf_ptr(union_field->name))); add_error_note(g, msg, field_entry->value->decl_node, buf_sprintf("other field here")); - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } ZigType *field_type; @@ -3020,29 +2422,31 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { field_type = g->builtin_types.entry_void; } else { add_node_error(g, field_node, buf_sprintf("union field missing type")); - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } } else { field_type = analyze_type_expr(g, scope, field_node->data.struct_field.type); if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; } union_field->type_entry = field_type; if (field_type->id == ZigTypeIdOpaque) { add_node_error(g, field_node->data.struct_field.type, buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions")); - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } switch (type_requires_comptime(g, field_type)) { case ReqCompTimeInvalid: - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; case ReqCompTimeYes: union_type->data.unionation.requires_comptime = true; break; @@ -3074,8 +2478,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { ZigType *tag_int_type = tag_type->data.enumeration.tag_int_type; ConstExprValue *result = analyze_const_value(g, scope, tag_value, tag_int_type, nullptr); if (type_is_invalid(result->type)) { - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } assert(result->special != ConstValSpecialRuntime); assert(result->type->id == ZigTypeIdInt); @@ -3090,8 +2494,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { buf_sprintf("enum tag value %s already taken", buf_ptr(val_buf))); add_error_note(g, msg, entry->value, buf_sprintf("other occurrence here")); - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } } } else if (enum_type_node != nullptr) { @@ -3101,8 +2505,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { buf_sprintf("enum field not found: '%s'", buf_ptr(field_name))); add_error_note(g, msg, tag_type->data.enumeration.decl_node, buf_sprintf("enum declared here")); - union_type->data.unionation.is_invalid = true; - continue; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } covered_enum_fields[union_field->enum_field->decl_index] = true; } else { @@ -3118,21 +2522,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { union_field->gen_index = gen_field_index; gen_field_index += 1; - - uint32_t field_align_bytes = get_abi_alignment(g, field_type); - if (field_align_bytes > biggest_align_bytes) { - biggest_align_bytes = field_align_bytes; - if (biggest_align_bytes > abi_alignment_so_far) { - abi_alignment_so_far = biggest_align_bytes; - } - } } - union_type->data.unionation.abi_alignment = abi_alignment_so_far; - - if (union_type->data.unionation.is_invalid) - return ErrorSemanticAnalyzeFail; - bool src_have_tag = decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr; @@ -3152,7 +2543,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { decl_node->data.container_decl.init_arg_expr : decl_node; add_node_error(g, source_node, buf_sprintf("%s union does not support enum tag type", qual_str)); - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } @@ -3194,33 +2585,24 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { buf_sprintf("enum field missing: '%s'", buf_ptr(enum_field->name))); add_error_note(g, msg, field_node, buf_sprintf("declared here")); - union_type->data.unionation.is_invalid = true; + union_type->data.unionation.resolve_status = ResolveStatusInvalid; } } } - if (create_enum_type) { - ZigType *import = get_scope_import(scope); - uint64_t tag_debug_size_in_bits = tag_type->zero_bits ? 0 : - 8*LLVMStoreSizeOfType(g->target_data_ref, tag_type->type_ref); - uint64_t tag_debug_align_in_bits = tag_type->zero_bits ? 0 : - 8*LLVMABIAlignmentOfType(g->target_data_ref, tag_type->type_ref); - // TODO get a more accurate debug scope - ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&tag_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), - tag_debug_size_in_bits, tag_debug_align_in_bits, di_enumerators, field_count, - tag_type->di_type, ""); - tag_type->di_type = tag_di_type; + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) { + return ErrorSemanticAnalyzeFail; } - union_type->data.unionation.zero_bits_loop_flag = false; - union_type->data.unionation.gen_field_count = gen_field_index; - union_type->zero_bits = (gen_field_index == 0 && (field_count < 2 || !src_have_tag)); - union_type->data.unionation.zero_bits_known = true; + union_type->data.unionation.resolve_loop_flag = false; - if (union_type->data.unionation.is_invalid) - return ErrorSemanticAnalyzeFail; + union_type->data.unionation.gen_field_count = gen_field_index; + bool zero_bits = gen_field_index == 0 && (field_count < 2 || !src_have_tag); + if (!zero_bits) { + union_type->abi_size = SIZE_MAX; + union_type->size_in_bits = SIZE_MAX; + } + union_type->data.unionation.resolve_status = zero_bits ? ResolveStatusSizeKnown : ResolveStatusZeroBitsKnown; return ErrorNone; } @@ -3630,20 +3012,17 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) { } } -static void resolve_decl_container(CodeGen *g, TldContainer *tld_container) { +static Error resolve_decl_container(CodeGen *g, TldContainer *tld_container) { ZigType *type_entry = tld_container->type_entry; assert(type_entry); switch (type_entry->id) { case ZigTypeIdStruct: - resolve_struct_type(g, tld_container->type_entry); - return; + return resolve_struct_type(g, tld_container->type_entry); case ZigTypeIdEnum: - resolve_enum_type(g, tld_container->type_entry); - return; + return resolve_enum_zero_bits(g, tld_container->type_entry); case ZigTypeIdUnion: - resolve_union_type(g, tld_container->type_entry); - return; + return resolve_union_type(g, tld_container->type_entry); default: zig_unreachable(); } @@ -4007,7 +3386,7 @@ TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name) { TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name) { assert(type_entry->id == ZigTypeIdUnion); - assert(type_entry->data.unionation.zero_bits_known); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); if (type_entry->data.unionation.src_field_count == 0) return nullptr; auto entry = type_entry->data.unionation.fields_by_name.maybe_get(name); @@ -4018,7 +3397,7 @@ TypeUnionField *find_union_type_field(ZigType *type_entry, Buf *name) { TypeUnionField *find_union_field_by_tag(ZigType *type_entry, const BigInt *tag) { assert(type_entry->id == ZigTypeIdUnion); - assert(type_entry->data.unionation.zero_bits_known); + assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); for (uint32_t i = 0; i < type_entry->data.unionation.src_field_count; i += 1) { TypeUnionField *field = &type_entry->data.unionation.fields[i]; if (bigint_cmp(&field->enum_field->value, tag) == CmpEQ) { @@ -4096,17 +3475,14 @@ ZigType *container_ref_type(ZigType *type_entry) { type_entry->data.pointer.child_type : type_entry; } -void resolve_container_type(CodeGen *g, ZigType *type_entry) { +Error resolve_container_type(CodeGen *g, ZigType *type_entry) { switch (type_entry->id) { case ZigTypeIdStruct: - resolve_struct_type(g, type_entry); - break; + return resolve_struct_type(g, type_entry); case ZigTypeIdEnum: - resolve_enum_type(g, type_entry); - break; + return resolve_enum_zero_bits(g, type_entry); case ZigTypeIdUnion: - resolve_union_type(g, type_entry); - break; + return resolve_union_type(g, type_entry); case ZigTypeIdPointer: case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -4132,6 +3508,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { case ZigTypeIdVector: zig_unreachable(); } + zig_unreachable(); } ZigType *get_src_ptr_type(ZigType *type) { @@ -4233,10 +3610,6 @@ static void define_local_param_variables(CodeGen *g, ZigFn *fn_table_entry) { if (type_has_bits(param_type)) { fn_table_entry->variable_list.append(var); } - - if (fn_type->data.fn.gen_param_info) { - var->gen_arg_index = fn_type->data.fn.gen_param_info[i].gen_index; - } } } @@ -4626,18 +3999,26 @@ ZigType *get_vector_type(CodeGen *g, uint32_t len, ZigType *elem_type) { } ZigType *entry = new_type_table_entry(ZigTypeIdVector); - entry->zero_bits = (len == 0) || !type_has_bits(elem_type); - entry->type_ref = entry->zero_bits ? LLVMVoidType() : LLVMVectorType(elem_type->type_ref, len); + if ((len != 0) && type_has_bits(elem_type)) { + // Vectors can only be ints, floats, or pointers. ints and floats have trivially resolvable + // llvm type refs. pointers we will use usize instead. + LLVMTypeRef example_vector_llvm_type; + if (elem_type->id == ZigTypeIdPointer) { + example_vector_llvm_type = LLVMVectorType(g->builtin_types.entry_usize->llvm_type, len); + } else { + example_vector_llvm_type = LLVMVectorType(elem_type->llvm_type, len); + } + assert(example_vector_llvm_type != nullptr); + entry->size_in_bits = elem_type->size_in_bits * len; + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, example_vector_llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, example_vector_llvm_type); + } entry->data.vector.len = len; entry->data.vector.elem_type = elem_type; buf_resize(&entry->name, 0); buf_appendf(&entry->name, "@Vector(%u, %s)", len, buf_ptr(&elem_type->name)); - entry->di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, - len * type_size_bits(g, elem_type), - LLVMABIAlignmentOfType(g->target_data_ref, entry->type_ref), elem_type->di_type, len); - g->type_table.put(type_id, entry); return entry; } @@ -4685,12 +4066,7 @@ bool handle_is_ptr(ZigType *type_entry) { !type_is_nonnull_ptr(type_entry->data.maybe.child_type) && type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; case ZigTypeIdUnion: - assert(type_entry->data.unionation.zero_bits_known); - if (type_entry->data.unionation.gen_field_count == 0) - return false; - if (!type_has_bits(type_entry)) - return false; - return true; + return type_has_bits(type_entry) && type_entry->data.unionation.gen_field_count != 0; } zig_unreachable(); @@ -5165,10 +4541,10 @@ bool fn_eval_eql(Scope *a, Scope *b) { // Whether the type has bits at runtime. bool type_has_bits(ZigType *type_entry) { - assert(type_entry); + assert(type_entry != nullptr); assert(!type_is_invalid(type_entry)); assert(type_is_resolved(type_entry, ResolveStatusZeroBitsKnown)); - return !type_entry->zero_bits; + return type_entry->abi_size != 0; } // Whether you can infer the value based solely on the type. @@ -5629,18 +5005,22 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { } else if (ty->id == ZigTypeIdEnum) { return resolve_enum_zero_bits(g, ty); } else if (ty->id == ZigTypeIdUnion) { - return resolve_union_zero_bits(g, ty); + return resolve_union_alignment(g, ty); } return ErrorNone; case ResolveStatusSizeKnown: if (ty->id == ZigTypeIdStruct) { return resolve_struct_type(g, ty); } else if (ty->id == ZigTypeIdEnum) { - return resolve_enum_type(g, ty); + return resolve_enum_zero_bits(g, ty); } else if (ty->id == ZigTypeIdUnion) { return resolve_union_type(g, ty); } return ErrorNone; + case ResolveStatusLLVMFwdDecl: + case ResolveStatusLLVMFull: + resolve_llvm_types(g, ty, status); + return ErrorNone; } zig_unreachable(); } @@ -6192,31 +5572,18 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) { assert(size_in_bits <= 65535); ZigType *entry = new_type_table_entry(ZigTypeIdInt); - entry->type_ref = (size_in_bits == 0) ? LLVMVoidType() : LLVMIntType(size_in_bits); - entry->zero_bits = (size_in_bits == 0); + + entry->size_in_bits = size_in_bits; + if (size_in_bits != 0) { + entry->llvm_type = LLVMIntType(size_in_bits); + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); + } const char u_or_i = is_signed ? 'i' : 'u'; buf_resize(&entry->name, 0); buf_appendf(&entry->name, "%c%" PRIu32, u_or_i, size_in_bits); - unsigned dwarf_tag; - if (is_signed) { - if (size_in_bits == 8) { - dwarf_tag = ZigLLVMEncoding_DW_ATE_signed_char(); - } else { - dwarf_tag = ZigLLVMEncoding_DW_ATE_signed(); - } - } else { - if (size_in_bits == 8) { - dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned_char(); - } else { - dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned(); - } - } - - uint64_t debug_size_in_bits = (size_in_bits == 0) ? - 0 : (8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref)); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), debug_size_in_bits, dwarf_tag); entry->data.integral.is_signed = is_signed; entry->data.integral.bit_count = size_in_bits; return entry; @@ -6620,33 +5987,13 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) { return link_lib; } -uint32_t get_abi_alignment(CodeGen *g, ZigType *type_entry) { - assert(type_is_resolved(type_entry, ResolveStatusAlignmentKnown)); - if (type_entry->zero_bits) return 0; - - // We need to make this function work without requiring ensure_complete_type - // so that we can have structs with fields that are pointers to their own type. - if (type_entry->id == ZigTypeIdStruct) { - assert(type_entry->data.structure.abi_alignment != 0); - return type_entry->data.structure.abi_alignment; - } else if (type_entry->id == ZigTypeIdUnion) { - assert(type_entry->data.unionation.abi_alignment != 0); - return type_entry->data.unionation.abi_alignment; - } else if (type_entry->id == ZigTypeIdOpaque) { - return 1; - } else { - uint32_t llvm_alignment = LLVMABIAlignmentOfType(g->target_data_ref, type_entry->type_ref); - return llvm_alignment; - } -} - -ZigType *get_align_amt_type(CodeGen *g) { - if (g->align_amt_type == nullptr) { - // according to LLVM the maximum alignment is 1 << 29. - g->align_amt_type = get_int_type(g, false, 29); - } - return g->align_amt_type; -} +ZigType *get_align_amt_type(CodeGen *g) { + if (g->align_amt_type == nullptr) { + // according to LLVM the maximum alignment is 1 << 29. + g->align_amt_type = get_int_type(g, false, 29); + } + return g->align_amt_type; +} uint32_t type_ptr_hash(const ZigType *ptr) { return hash_ptr((void*)ptr); @@ -6841,11 +6188,10 @@ bool type_is_c_abi_int(CodeGen *g, ZigType *ty) { uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field) { assert(struct_type->id == ZigTypeIdStruct); - if (struct_type->data.structure.layout != ContainerLayoutPacked) { + assert(type_is_resolved(struct_type, ResolveStatusSizeKnown)); + if (struct_type->data.structure.host_int_bytes == nullptr) return 0; - } - LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); - return LLVMStoreSizeOfType(g->target_data_ref, field_type); + return struct_type->data.structure.host_int_bytes[field->gen_index]; } Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node, @@ -6911,3 +6257,968 @@ Buf *type_bare_name(ZigType *type_entry) { Buf *type_h_name(ZigType *t) { return type_bare_name(t); } + +static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { + if (type->data.structure.resolve_status >= wanted_resolve_status) return; + + ZigType *ptr_type = type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *child_type = ptr_type->data.pointer.child_type; + ZigType *usize_type = g->builtin_types.entry_usize; + + bool done = false; + if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile || + ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero) + { + ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, + PtrLenUnknown, 0, 0, 0, false); + ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); + + assertNoError(type_resolve(g, peer_slice_type, wanted_resolve_status)); + type->llvm_type = peer_slice_type->llvm_type; + type->llvm_di_type = peer_slice_type->llvm_di_type; + type->data.structure.resolve_status = peer_slice_type->data.structure.resolve_status; + done = true; + } + + // If the child type is []const T then we need to make sure the type ref + // and debug info is the same as if the child type were []T. + if (is_slice(child_type)) { + ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry; + assert(child_ptr_type->id == ZigTypeIdPointer); + if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile || + child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero) + { + ZigType *grand_child_type = child_ptr_type->data.pointer.child_type; + ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false, + PtrLenUnknown, 0, 0, 0, false); + ZigType *bland_child_slice = get_slice_type(g, bland_child_ptr_type); + ZigType *peer_ptr_type = get_pointer_to_type_extra(g, bland_child_slice, false, false, + PtrLenUnknown, 0, 0, 0, false); + ZigType *peer_slice_type = get_slice_type(g, peer_ptr_type); + + assertNoError(type_resolve(g, peer_slice_type, wanted_resolve_status)); + type->llvm_type = peer_slice_type->llvm_type; + type->llvm_di_type = peer_slice_type->llvm_di_type; + type->data.structure.resolve_status = peer_slice_type->data.structure.resolve_status; + done = true; + } + } + + if (done) return; + + LLVMTypeRef usize_llvm_type = get_llvm_type(g, usize_type); + ZigLLVMDIType *usize_llvm_di_type = get_llvm_di_type(g, usize_type); + ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); + ZigLLVMDIFile *di_file = nullptr; + unsigned line = 0; + + if (type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) { + type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name)); + + type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name), + compile_unit_scope, di_file, line); + + type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl; + if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; + } + + if (!type_has_bits(child_type)) { + LLVMTypeRef element_types[] = { + usize_llvm_type, + }; + LLVMStructSetBody(type->llvm_type, element_types, 1, false); + + uint64_t len_debug_size_in_bits = usize_type->size_in_bits; + uint64_t len_debug_align_in_bits = 8*usize_type->abi_align; + uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 0); + + uint64_t debug_size_in_bits = type->size_in_bits; + uint64_t debug_align_in_bits = 8*type->abi_align; + + ZigLLVMDIType *di_element_types[] = { + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "len", di_file, line, + len_debug_size_in_bits, + len_debug_align_in_bits, + len_offset_in_bits, + 0, usize_llvm_di_type), + }; + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + compile_unit_scope, + buf_ptr(&type->name), + di_file, line, debug_size_in_bits, debug_align_in_bits, 0, + nullptr, di_element_types, 1, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type); + type->llvm_di_type = replacement_di_type; + type->data.structure.resolve_status = ResolveStatusLLVMFull; + return; + } + + LLVMTypeRef element_types[2]; + element_types[slice_ptr_index] = get_llvm_type(g, ptr_type); + element_types[slice_len_index] = get_llvm_type(g, g->builtin_types.entry_usize); + if (type->data.structure.resolve_status >= wanted_resolve_status) return; + LLVMStructSetBody(type->llvm_type, element_types, 2, false); + + uint64_t ptr_debug_size_in_bits = ptr_type->size_in_bits; + uint64_t ptr_debug_align_in_bits = 8*ptr_type->abi_align; + uint64_t ptr_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 0); + + uint64_t len_debug_size_in_bits = usize_type->size_in_bits; + uint64_t len_debug_align_in_bits = 8*usize_type->abi_align; + uint64_t len_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 1); + + uint64_t debug_size_in_bits = type->size_in_bits; + uint64_t debug_align_in_bits = 8*type->abi_align; + + ZigLLVMDIType *di_element_types[] = { + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "ptr", di_file, line, + ptr_debug_size_in_bits, + ptr_debug_align_in_bits, + ptr_offset_in_bits, + 0, get_llvm_di_type(g, ptr_type)), + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "len", di_file, line, + len_debug_size_in_bits, + len_debug_align_in_bits, + len_offset_in_bits, + 0, usize_llvm_di_type), + }; + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + compile_unit_scope, + buf_ptr(&type->name), + di_file, line, debug_size_in_bits, debug_align_in_bits, 0, + nullptr, di_element_types, 2, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type); + type->llvm_di_type = replacement_di_type; + type->data.structure.resolve_status = ResolveStatusLLVMFull; +} + +static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status) { + assert(struct_type->id == ZigTypeIdStruct); + assert(struct_type->data.structure.resolve_status != ResolveStatusInvalid); + assert(struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown); + assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); + if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return; + + AstNode *decl_node = struct_type->data.structure.decl_node; + ZigLLVMDIFile *di_file; + ZigLLVMDIScope *di_scope; + unsigned line; + if (decl_node != nullptr) { + assert(decl_node->type == NodeTypeContainerDecl); + Scope *scope = &struct_type->data.structure.decls_scope->base; + ZigType *import = get_scope_import(scope); + di_file = import->data.structure.root_struct->di_file; + di_scope = ZigLLVMFileToScope(di_file); + line = decl_node->line + 1; + } else { + di_file = nullptr; + di_scope = ZigLLVMCompileUnitToScope(g->compile_unit); + line = 0; + } + + if (struct_type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) { + struct_type->llvm_type = type_has_bits(struct_type) ? + LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType(); + unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); + struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + dwarf_kind, buf_ptr(&struct_type->name), + di_scope, di_file, line); + + struct_type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl; + if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; + } + + size_t field_count = struct_type->data.structure.src_field_count; + size_t gen_field_count = struct_type->data.structure.gen_field_count; + LLVMTypeRef *element_types = allocate(gen_field_count); + + size_t gen_field_index = 0; + bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); + size_t packed_bits_offset = 0; + size_t first_packed_bits_offset_misalign = SIZE_MAX; + size_t debug_field_count = 0; + + // trigger all the recursive get_llvm_type calls + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; + ZigType *field_type = type_struct_field->type_entry; + if (!type_has_bits(field_type)) + continue; + (void)get_llvm_type(g, field_type); + if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return; + } + + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; + ZigType *field_type = type_struct_field->type_entry; + + if (!type_has_bits(field_type)) + continue; + + if (packed) { + size_t field_size_in_bits = type_size_bits(g, field_type); + size_t next_packed_bits_offset = packed_bits_offset + field_size_in_bits; + + if (first_packed_bits_offset_misalign != SIZE_MAX) { + // this field is not byte-aligned; it is part of the previous field with a bit offset + + size_t full_bit_count = next_packed_bits_offset - first_packed_bits_offset_misalign; + size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes); + if (full_abi_size * 8 == full_bit_count) { + // next field recovers ABI alignment + element_types[gen_field_index] = LLVMIntType((unsigned)(full_bit_count)); + gen_field_index += 1; + + first_packed_bits_offset_misalign = SIZE_MAX; + } + } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) { + first_packed_bits_offset_misalign = packed_bits_offset; + } else { + // This is a byte-aligned field (both start and end) in a packed struct. + element_types[gen_field_index] = get_llvm_type(g, field_type); + gen_field_index += 1; + } + packed_bits_offset = next_packed_bits_offset; + } else { + element_types[gen_field_index] = get_llvm_type(g, field_type); + + gen_field_index += 1; + } + debug_field_count += 1; + } + if (first_packed_bits_offset_misalign != SIZE_MAX) { + size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; + size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes); + element_types[gen_field_index] = LLVMIntType((unsigned)full_abi_size * 8); + gen_field_index += 1; + } + + if (type_has_bits(struct_type)) { + LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed); + } + + ZigLLVMDIType **di_element_types = allocate(debug_field_count); + size_t debug_field_index = 0; + for (size_t i = 0; i < field_count; i += 1) { + TypeStructField *type_struct_field = &struct_type->data.structure.fields[i]; + size_t gen_field_index = type_struct_field->gen_index; + if (gen_field_index == SIZE_MAX) { + continue; + } + + ZigType *field_type = type_struct_field->type_entry; + + // if the field is a function, actually the debug info should be a pointer. + ZigLLVMDIType *field_di_type; + if (field_type->id == ZigTypeIdFn) { + ZigType *field_ptr_type = get_pointer_to_type(g, field_type, true); + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, field_ptr_type)); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, get_llvm_type(g, field_ptr_type)); + field_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, field_type), + debug_size_in_bits, debug_align_in_bits, buf_ptr(&field_ptr_type->name)); + } else { + field_di_type = get_llvm_di_type(g, field_type); + } + + uint64_t debug_size_in_bits; + uint64_t debug_align_in_bits; + uint64_t debug_offset_in_bits; + if (packed) { + debug_size_in_bits = type_struct_field->type_entry->size_in_bits; + debug_align_in_bits = 8 * type_struct_field->type_entry->abi_align; + debug_offset_in_bits = 8 * type_struct_field->offset + type_struct_field->bit_offset_in_host; + } else { + debug_size_in_bits = 8 * get_store_size_bytes(field_type->size_in_bits); + debug_align_in_bits = 8 * field_type->abi_align; + debug_offset_in_bits = 8 * type_struct_field->offset; + } + unsigned line; + if (decl_node != nullptr) { + AstNode *field_node = decl_node->data.container_decl.fields.at(i); + line = field_node->line + 1; + } else { + line = 0; + } + di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(struct_type->llvm_di_type), buf_ptr(type_struct_field->name), + di_file, line, + debug_size_in_bits, + debug_align_in_bits, + debug_offset_in_bits, + 0, field_di_type); + assert(di_element_types[debug_field_index]); + debug_field_index += 1; + } + + uint64_t debug_size_in_bits = 8*get_store_size_bytes(struct_type->size_in_bits); + uint64_t debug_align_in_bits = 8*struct_type->abi_align; + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + di_scope, + buf_ptr(&struct_type->name), + di_file, line, + debug_size_in_bits, + debug_align_in_bits, + 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type); + struct_type->llvm_di_type = replacement_di_type; + struct_type->data.structure.resolve_status = ResolveStatusLLVMFull; +} + +static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { + assert(!enum_type->data.enumeration.is_invalid); + assert(enum_type->data.enumeration.complete); + if (enum_type->llvm_di_type != nullptr) return; + + Scope *scope = &enum_type->data.enumeration.decls_scope->base; + ZigType *import = get_scope_import(scope); + AstNode *decl_node = enum_type->data.enumeration.decl_node; + + if (!type_has_bits(enum_type)) { + enum_type->llvm_type = g->builtin_types.entry_void->llvm_type; + + uint64_t debug_size_in_bits = 0; + uint64_t debug_align_in_bits = 0; + ZigLLVMDIType **di_element_types = nullptr; + size_t debug_field_count = 0; + enum_type->llvm_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + buf_ptr(&enum_type->name), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + debug_size_in_bits, + debug_align_in_bits, + 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); + return; + } + + uint32_t field_count = enum_type->data.enumeration.src_field_count; + + assert(enum_type->data.enumeration.fields); + ZigLLVMDIEnumerator **di_enumerators = allocate(field_count); + + for (uint32_t i = 0; i < field_count; i += 1) { + TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; + + // TODO send patch to LLVM to support APInt in createEnumerator instead of int64_t + // http://lists.llvm.org/pipermail/llvm-dev/2017-December/119456.html + di_enumerators[i] = ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(enum_field->name), + bigint_as_signed(&enum_field->value)); + } + + ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type; + enum_type->llvm_type = get_llvm_type(g, tag_int_type); + + // create debug type for tag + uint64_t tag_debug_size_in_bits = tag_int_type->size_in_bits; + uint64_t tag_debug_align_in_bits = 8*tag_int_type->abi_align; + ZigLLVMDIType *tag_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&enum_type->name), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + tag_debug_size_in_bits, + tag_debug_align_in_bits, + di_enumerators, field_count, + get_llvm_di_type(g, tag_int_type), ""); + + enum_type->llvm_di_type = tag_di_type; +} + +static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) { + if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return; + + ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; + ZigType *tag_type = union_type->data.unionation.tag_type; + if (most_aligned_union_member == nullptr) { + union_type->llvm_type = get_llvm_type(g, tag_type); + union_type->llvm_di_type = get_llvm_di_type(g, tag_type); + union_type->data.unionation.resolve_status = ResolveStatusLLVMFull; + return; + } + + Scope *scope = &union_type->data.unionation.decls_scope->base; + ZigType *import = get_scope_import(scope); + AstNode *decl_node = union_type->data.unionation.decl_node; + + if (union_type->data.unionation.resolve_status < ResolveStatusLLVMFwdDecl) { + union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); + size_t line = decl_node ? decl_node->line : 0; + unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); + union_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + dwarf_kind, buf_ptr(&union_type->name), + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + import->data.structure.root_struct->di_file, (unsigned)(line + 1)); + + union_type->data.unionation.resolve_status = ResolveStatusLLVMFwdDecl; + if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; + } + + uint32_t gen_field_count = union_type->data.unionation.gen_field_count; + ZigLLVMDIType **union_inner_di_types = allocate(gen_field_count); + uint32_t field_count = union_type->data.unionation.src_field_count; + for (uint32_t i = 0; i < field_count; i += 1) { + TypeUnionField *union_field = &union_type->data.unionation.fields[i]; + if (!type_has_bits(union_field->type_entry)) + continue; + + ZigLLVMDIType *field_di_type = get_llvm_di_type(g, union_field->type_entry); + if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return; + + uint64_t store_size_in_bits = union_field->type_entry->size_in_bits; + uint64_t abi_align_in_bits = 8*union_field->type_entry->abi_align; + AstNode *field_node = decl_node->data.container_decl.fields.at(i); + union_inner_di_types[union_field->gen_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(union_type->llvm_di_type), buf_ptr(union_field->enum_field->name), + import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), + store_size_in_bits, + abi_align_in_bits, + 0, + 0, field_di_type); + + } + + if (tag_type == nullptr || !type_has_bits(tag_type)) { + assert(most_aligned_union_member != nullptr); + + size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size; + if (padding_bytes > 0) { + ZigType *u8_type = get_int_type(g, false, 8); + ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); + LLVMTypeRef union_element_types[] = { + most_aligned_union_member->llvm_type, + get_llvm_type(g, padding_array), + }; + LLVMStructSetBody(union_type->llvm_type, union_element_types, 2, false); + } else { + LLVMStructSetBody(union_type->llvm_type, &most_aligned_union_member->llvm_type, 1, false); + } + union_type->data.unionation.union_llvm_type = union_type->llvm_type; + union_type->data.unionation.gen_tag_index = SIZE_MAX; + union_type->data.unionation.gen_union_index = SIZE_MAX; + + // create debug type for union + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), buf_ptr(&union_type->name), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + union_type->data.unionation.union_abi_size * 8, + most_aligned_union_member->abi_align * 8, + 0, union_inner_di_types, + gen_field_count, 0, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type); + union_type->llvm_di_type = replacement_di_type; + union_type->data.unionation.resolve_status = ResolveStatusLLVMFull; + return; + } + + LLVMTypeRef union_type_ref; + size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size; + if (padding_bytes == 0) { + union_type_ref = get_llvm_type(g, most_aligned_union_member); + } else { + ZigType *u8_type = get_int_type(g, false, 8); + ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); + LLVMTypeRef union_element_types[] = { + get_llvm_type(g, most_aligned_union_member), + get_llvm_type(g, padding_array), + }; + union_type_ref = LLVMStructType(union_element_types, 2, false); + } + union_type->data.unionation.union_llvm_type = union_type_ref; + + LLVMTypeRef root_struct_element_types[2]; + root_struct_element_types[union_type->data.unionation.gen_tag_index] = get_llvm_type(g, tag_type); + root_struct_element_types[union_type->data.unionation.gen_union_index] = union_type_ref; + LLVMStructSetBody(union_type->llvm_type, root_struct_element_types, 2, false); + + // create debug type for union + ZigLLVMDIType *union_di_type = ZigLLVMCreateDebugUnionType(g->dbuilder, + ZigLLVMTypeToScope(union_type->llvm_di_type), "AnonUnion", + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + most_aligned_union_member->size_in_bits, 8*most_aligned_union_member->abi_align, + 0, union_inner_di_types, gen_field_count, 0, ""); + + uint64_t union_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type, + union_type->data.unionation.gen_union_index); + uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, union_type->llvm_type, + union_type->data.unionation.gen_tag_index); + + ZigLLVMDIType *union_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(union_type->llvm_di_type), "payload", + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + most_aligned_union_member->size_in_bits, + 8*most_aligned_union_member->abi_align, + union_offset_in_bits, + 0, union_di_type); + + uint64_t tag_debug_size_in_bits = tag_type->size_in_bits; + uint64_t tag_debug_align_in_bits = 8*tag_type->abi_align; + + ZigLLVMDIType *tag_member_di_type = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(union_type->llvm_di_type), "tag", + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + tag_debug_size_in_bits, + tag_debug_align_in_bits, + tag_offset_in_bits, + 0, get_llvm_di_type(g, tag_type)); + + ZigLLVMDIType *di_root_members[2]; + di_root_members[union_type->data.unionation.gen_tag_index] = tag_member_di_type; + di_root_members[union_type->data.unionation.gen_union_index] = union_member_di_type; + + uint64_t debug_size_in_bits = union_type->size_in_bits; + uint64_t debug_align_in_bits = 8*union_type->abi_align; + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + buf_ptr(&union_type->name), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + debug_size_in_bits, + debug_align_in_bits, + 0, nullptr, di_root_members, 2, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, union_type->llvm_di_type, replacement_di_type); + union_type->llvm_di_type = replacement_di_type; + union_type->data.unionation.resolve_status = ResolveStatusLLVMFull; +} + +static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + + if (!type_has_bits(type)) { + type->llvm_type = g->builtin_types.entry_void->llvm_type; + type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; + return; + } + + ZigType *elem_type = type->data.pointer.child_type; + + if (type->data.pointer.is_const || type->data.pointer.is_volatile || + type->data.pointer.explicit_alignment != 0 || type->data.pointer.ptr_len != PtrLenSingle || + type->data.pointer.bit_offset_in_host != 0 || type->data.pointer.allow_zero) + { + ZigType *peer_type = get_pointer_to_type_extra(g, elem_type, false, false, + PtrLenSingle, 0, 0, type->data.pointer.host_int_bytes, false); + type->llvm_type = get_llvm_type(g, peer_type); + type->llvm_di_type = get_llvm_di_type(g, peer_type); + return; + } + + if (type->data.pointer.host_int_bytes == 0) { + assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFwdDecl)); + type->llvm_type = LLVMPointerType(elem_type->llvm_type, 0); + uint64_t debug_size_in_bits = 8*get_store_size_bytes(type->size_in_bits); + uint64_t debug_align_in_bits = 8*type->abi_align; + type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, elem_type->llvm_di_type, + debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name)); + assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFull)); + } else { + ZigType *host_int_type = get_int_type(g, false, type->data.pointer.host_int_bytes * 8); + LLVMTypeRef host_int_llvm_type = get_llvm_type(g, host_int_type); + type->llvm_type = LLVMPointerType(host_int_llvm_type, 0); + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, host_int_llvm_type); + uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, host_int_llvm_type); + type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, host_int_type), + debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name)); + } +} + +static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + + if (!type_has_bits(type)) { + type->llvm_type = g->builtin_types.entry_void->llvm_type; + type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; + return; + } + + unsigned dwarf_tag; + if (type->data.integral.is_signed) { + if (type->size_in_bits == 8) { + dwarf_tag = ZigLLVMEncoding_DW_ATE_signed_char(); + } else { + dwarf_tag = ZigLLVMEncoding_DW_ATE_signed(); + } + } else { + if (type->size_in_bits == 8) { + dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned_char(); + } else { + dwarf_tag = ZigLLVMEncoding_DW_ATE_unsigned(); + } + } + + type->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&type->name), type->size_in_bits, dwarf_tag); + type->llvm_type = LLVMIntType(type->size_in_bits); +} + +static void resolve_llvm_types_optional(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + + LLVMTypeRef bool_llvm_type = get_llvm_type(g, g->builtin_types.entry_bool); + ZigLLVMDIType *bool_llvm_di_type = get_llvm_di_type(g, g->builtin_types.entry_bool); + + ZigType *child_type = type->data.maybe.child_type; + if (!type_has_bits(child_type)) { + type->llvm_type = bool_llvm_type; + type->llvm_di_type = bool_llvm_di_type; + return; + } + + LLVMTypeRef child_llvm_type = get_llvm_type(g, child_type); + ZigLLVMDIType *child_llvm_di_type = get_llvm_di_type(g, child_type); + + if (type_is_nonnull_ptr(child_type) || child_type->id == ZigTypeIdErrorSet) { + type->llvm_type = child_llvm_type; + type->llvm_di_type = child_llvm_di_type; + return; + } + + LLVMTypeRef elem_types[] = { + get_llvm_type(g, child_type), + LLVMInt1Type(), + }; + type->llvm_type = LLVMStructType(elem_types, 2, false); + + ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); + ZigLLVMDIFile *di_file = nullptr; + unsigned line = 0; + type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name), + compile_unit_scope, di_file, line); + + uint64_t val_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, child_llvm_type); + uint64_t val_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, child_llvm_type); + uint64_t val_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 0); + + uint64_t maybe_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, bool_llvm_type); + uint64_t maybe_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, bool_llvm_type); + uint64_t maybe_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, 1); + + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type); + + ZigLLVMDIType *di_element_types[] = { + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "val", di_file, line, + val_debug_size_in_bits, + val_debug_align_in_bits, + val_offset_in_bits, + 0, child_llvm_di_type), + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "maybe", di_file, line, + maybe_debug_size_in_bits, + maybe_debug_align_in_bits, + maybe_offset_in_bits, + 0, bool_llvm_di_type), + }; + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + compile_unit_scope, + buf_ptr(&type->name), + di_file, line, debug_size_in_bits, debug_align_in_bits, 0, + nullptr, di_element_types, 2, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type); + type->llvm_di_type = replacement_di_type; +} + +static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + + ZigType *payload_type = type->data.error_union.payload_type; + ZigType *err_set_type = type->data.error_union.err_set_type; + + if (!type_has_bits(payload_type)) { + assert(type_has_bits(err_set_type)); + type->llvm_type = get_llvm_type(g, err_set_type); + type->llvm_di_type = get_llvm_di_type(g, err_set_type); + } else if (!type_has_bits(err_set_type)) { + type->llvm_type = get_llvm_type(g, payload_type); + type->llvm_di_type = get_llvm_di_type(g, payload_type); + } else { + LLVMTypeRef err_set_llvm_type = get_llvm_type(g, err_set_type); + LLVMTypeRef payload_llvm_type = get_llvm_type(g, payload_type); + LLVMTypeRef elem_types[2]; + elem_types[err_union_err_index] = err_set_llvm_type; + elem_types[err_union_payload_index] = payload_llvm_type; + type->llvm_type = LLVMStructType(elem_types, 2, false); + + ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit); + ZigLLVMDIFile *di_file = nullptr; + unsigned line = 0; + type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + ZigLLVMTag_DW_structure_type(), buf_ptr(&type->name), + compile_unit_scope, di_file, line); + + uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, err_set_llvm_type); + uint64_t tag_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, err_set_llvm_type); + uint64_t tag_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, err_union_err_index); + + uint64_t value_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, payload_llvm_type); + uint64_t value_debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, payload_llvm_type); + uint64_t value_offset_in_bits = 8*LLVMOffsetOfElement(g->target_data_ref, type->llvm_type, + err_union_payload_index); + + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type); + + ZigLLVMDIType *di_element_types[] = { + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "tag", di_file, line, + tag_debug_size_in_bits, + tag_debug_align_in_bits, + tag_offset_in_bits, + 0, get_llvm_di_type(g, err_set_type)), + ZigLLVMCreateDebugMemberType(g->dbuilder, ZigLLVMTypeToScope(type->llvm_di_type), + "value", di_file, line, + value_debug_size_in_bits, + value_debug_align_in_bits, + value_offset_in_bits, + 0, get_llvm_di_type(g, payload_type)), + }; + + ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, + compile_unit_scope, + buf_ptr(&type->name), + di_file, line, + debug_size_in_bits, + debug_align_in_bits, + 0, + nullptr, di_element_types, 2, 0, nullptr, ""); + + ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type); + type->llvm_di_type = replacement_di_type; + } +} + +static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + + if (!type_has_bits(type)) { + type->llvm_type = g->builtin_types.entry_void->llvm_type; + type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; + return; + } + + ZigType *elem_type = type->data.array.child_type; + + // TODO https://github.com/ziglang/zig/issues/1424 + type->llvm_type = LLVMArrayType(get_llvm_type(g, elem_type), (unsigned)type->data.array.len); + + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type); + uint64_t debug_align_in_bits = 8*LLVMABISizeOfType(g->target_data_ref, type->llvm_type); + + type->llvm_di_type = ZigLLVMCreateDebugArrayType(g->dbuilder, debug_size_in_bits, + debug_align_in_bits, get_llvm_di_type(g, elem_type), (int)type->data.array.len); +} + +static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) { + if (fn_type->llvm_di_type != nullptr) return; + + FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; + bool first_arg_return = want_first_arg_sret(g, fn_type_id); + bool is_async = fn_type_id->cc == CallingConventionAsync; + bool is_c_abi = fn_type_id->cc == CallingConventionC; + bool prefix_arg_error_return_trace = g->have_err_ret_tracing && fn_type_can_fail(fn_type_id); + // +1 for maybe making the first argument the return value + // +1 for maybe first argument the error return trace + // +2 for maybe arguments async allocator and error code pointer + ZigList gen_param_types = {}; + // +1 because 0 is the return type and + // +1 for maybe making first arg ret val and + // +1 for maybe first argument the error return trace + // +2 for maybe arguments async allocator and error code pointer + ZigList param_di_types = {}; + param_di_types.append(get_llvm_di_type(g, fn_type_id->return_type)); + ZigType *gen_return_type; + if (is_async) { + gen_return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); + } else if (!type_has_bits(fn_type_id->return_type)) { + gen_return_type = g->builtin_types.entry_void; + } else if (first_arg_return) { + ZigType *gen_type = get_pointer_to_type(g, fn_type_id->return_type, false); + gen_param_types.append(get_llvm_type(g, gen_type)); + param_di_types.append(get_llvm_di_type(g, gen_type)); + gen_return_type = g->builtin_types.entry_void; + } else { + gen_return_type = fn_type_id->return_type; + } + fn_type->data.fn.gen_return_type = gen_return_type; + + if (prefix_arg_error_return_trace) { + ZigType *gen_type = get_ptr_to_stack_trace_type(g); + gen_param_types.append(get_llvm_type(g, gen_type)); + param_di_types.append(get_llvm_di_type(g, gen_type)); + } + if (is_async) { + { + // async allocator param + ZigType *gen_type = fn_type_id->async_allocator_type; + gen_param_types.append(get_llvm_type(g, gen_type)); + param_di_types.append(get_llvm_di_type(g, gen_type)); + } + + { + // error code pointer + ZigType *gen_type = get_pointer_to_type(g, g->builtin_types.entry_global_error_set, false); + gen_param_types.append(get_llvm_type(g, gen_type)); + param_di_types.append(get_llvm_di_type(g, gen_type)); + } + } + + fn_type->data.fn.gen_param_info = allocate(fn_type_id->param_count); + for (size_t i = 0; i < fn_type_id->param_count; i += 1) { + FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; + ZigType *type_entry = src_param_info->type; + FnGenParamInfo *gen_param_info = &fn_type->data.fn.gen_param_info[i]; + + gen_param_info->src_index = i; + gen_param_info->gen_index = SIZE_MAX; + + if (is_c_abi || !type_has_bits(type_entry)) + continue; + + ZigType *gen_type; + if (handle_is_ptr(type_entry)) { + gen_type = get_pointer_to_type(g, type_entry, true); + gen_param_info->is_byval = true; + } else { + gen_type = type_entry; + } + gen_param_info->gen_index = gen_param_types.length; + gen_param_info->type = gen_type; + gen_param_types.append(get_llvm_type(g, gen_type)); + + param_di_types.append(get_llvm_di_type(g, gen_type)); + } + + if (is_c_abi) { + FnWalk fn_walk = {}; + fn_walk.id = FnWalkIdTypes; + fn_walk.data.types.param_di_types = ¶m_di_types; + fn_walk.data.types.gen_param_types = &gen_param_types; + walk_function_params(g, fn_type, &fn_walk); + } + + fn_type->data.fn.gen_param_count = gen_param_types.length; + + for (size_t i = 0; i < gen_param_types.length; i += 1) { + assert(gen_param_types.items[i] != nullptr); + } + fn_type->data.fn.raw_type_ref = LLVMFunctionType(get_llvm_type(g, gen_return_type), + gen_param_types.items, (unsigned int)gen_param_types.length, fn_type_id->is_var_args); + fn_type->llvm_type = LLVMPointerType(fn_type->data.fn.raw_type_ref, 0); + fn_type->data.fn.raw_di_type = ZigLLVMCreateSubroutineType(g->dbuilder, param_di_types.items, (int)param_di_types.length, 0); + fn_type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, fn_type->data.fn.raw_di_type, + LLVMStoreSizeOfType(g->target_data_ref, fn_type->llvm_type), + LLVMABIAlignmentOfType(g->target_data_ref, fn_type->llvm_type), ""); +} + +static void resolve_llvm_types_anyerror(CodeGen *g) { + ZigType *entry = g->builtin_types.entry_global_error_set; + entry->llvm_type = get_llvm_type(g, g->err_tag_type); + ZigList err_enumerators = {}; + // reserve index 0 to indicate no error + err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0)); + for (size_t i = 1; i < g->errors_by_index.length; i += 1) { + ErrorTableEntry *error_entry = g->errors_by_index.at(i); + err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, buf_ptr(&error_entry->name), i)); + } + + // create debug type for error sets + uint64_t tag_debug_size_in_bits = g->err_tag_type->size_in_bits; + uint64_t tag_debug_align_in_bits = 8*g->err_tag_type->abi_align; + ZigLLVMDIFile *err_set_di_file = nullptr; + entry->llvm_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, + ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&entry->name), + err_set_di_file, 0, + tag_debug_size_in_bits, + tag_debug_align_in_bits, + err_enumerators.items, err_enumerators.length, + get_llvm_di_type(g, g->err_tag_type), ""); +} + +static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) { + assert(type->id == ZigTypeIdOpaque || type_is_resolved(type, ResolveStatusSizeKnown)); + assert(wanted_resolve_status > ResolveStatusSizeKnown); + switch (type->id) { + case ZigTypeIdInvalid: + case ZigTypeIdMetaType: + case ZigTypeIdComptimeFloat: + case ZigTypeIdComptimeInt: + case ZigTypeIdEnumLiteral: + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + zig_unreachable(); + case ZigTypeIdFloat: + case ZigTypeIdOpaque: + case ZigTypeIdVoid: + case ZigTypeIdBool: + case ZigTypeIdUnreachable: + assert(type->llvm_di_type != nullptr); + return; + case ZigTypeIdStruct: + if (type->data.structure.is_slice) + return resolve_llvm_types_slice(g, type, wanted_resolve_status); + else + return resolve_llvm_types_struct(g, type, wanted_resolve_status); + case ZigTypeIdEnum: + return resolve_llvm_types_enum(g, type); + case ZigTypeIdUnion: + return resolve_llvm_types_union(g, type, wanted_resolve_status); + case ZigTypeIdPointer: + return resolve_llvm_types_pointer(g, type); + case ZigTypeIdPromise: { + if (type->llvm_di_type != nullptr) return; + ZigType *u8_ptr_type = get_pointer_to_type(g, g->builtin_types.entry_u8, false); + type->llvm_type = get_llvm_type(g, u8_ptr_type); + type->llvm_di_type = get_llvm_di_type(g, u8_ptr_type); + return; + } + case ZigTypeIdInt: + return resolve_llvm_types_integer(g, type); + case ZigTypeIdOptional: + return resolve_llvm_types_optional(g, type); + case ZigTypeIdErrorUnion: + return resolve_llvm_types_error_union(g, type); + case ZigTypeIdArray: + return resolve_llvm_types_array(g, type); + case ZigTypeIdFn: + return resolve_llvm_types_fn(g, type); + case ZigTypeIdErrorSet: { + if (type->llvm_di_type != nullptr) return; + + if (g->builtin_types.entry_global_error_set->llvm_type == nullptr) { + resolve_llvm_types_anyerror(g); + } + type->llvm_type = g->builtin_types.entry_global_error_set->llvm_type; + type->llvm_di_type = g->builtin_types.entry_global_error_set->llvm_di_type; + return; + } + case ZigTypeIdVector: { + if (type->llvm_di_type != nullptr) return; + + type->llvm_type = LLVMVectorType(get_llvm_type(g, type->data.vector.elem_type), type->data.vector.len); + type->llvm_di_type = ZigLLVMDIBuilderCreateVectorType(g->dbuilder, type->size_in_bits, + type->abi_align, get_llvm_di_type(g, type->data.vector.elem_type), type->data.vector.len); + return; + } + } + zig_unreachable(); +} + +LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) { + assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); + assert(type->abi_size == 0 || type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); + assert(type->abi_align == 0 || type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); + return type->llvm_type; +} + +ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) { + assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); + return type->llvm_di_type; +} diff --git a/src/analyze.hpp b/src/analyze.hpp index 85d698358fd0..a3246fdf4d5b 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -73,7 +73,7 @@ bool type_is_complete(ZigType *type_entry); bool type_is_resolved(ZigType *type_entry, ResolveStatus status); bool type_is_invalid(ZigType *type_entry); bool type_is_global_error_set(ZigType *err_set_type); -void resolve_container_type(CodeGen *g, ZigType *type_entry); +Error resolve_container_type(CodeGen *g, ZigType *type_entry); ScopeDecls *get_container_scope(ZigType *type_entry); TypeStructField *find_struct_type_field(ZigType *type_entry, Buf *name); TypeEnumField *find_enum_type_field(ZigType *enum_type, Buf *name); @@ -244,4 +244,7 @@ Buf *type_bare_name(ZigType *t); Buf *type_h_name(ZigType *t); Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose); +LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type); +ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type); + #endif diff --git a/src/codegen.cpp b/src/codegen.cpp index 8de3e81194a1..55733464521d 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -483,6 +483,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { ZigType *fn_type = fn_table_entry->type_entry; + // Make the raw_type_ref populated + (void)get_llvm_type(g, fn_type); LLVMTypeRef fn_llvm_type = fn_type->data.fn.raw_type_ref; if (fn_table_entry->body_node == nullptr) { LLVMValueRef existing_llvm_fn = LLVMGetNamedFunction(g->module, buf_ptr(symbol_name)); @@ -496,6 +498,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) { } else { assert(entry->value->id == TldIdFn); TldFn *tld_fn = reinterpret_cast(entry->value); + // Make the raw_type_ref populated + (void)get_llvm_type(g, tld_fn->fn_entry->type_entry); tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), tld_fn->fn_entry->type_entry->data.fn.raw_type_ref); fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value, @@ -668,7 +672,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) { if (scope->parent) { ScopeDecls *decls_scope = (ScopeDecls *)scope; assert(decls_scope->container_type); - scope->di_scope = ZigLLVMTypeToScope(decls_scope->container_type->di_type); + scope->di_scope = ZigLLVMTypeToScope(get_llvm_di_type(g, decls_scope->container_type)); } else { scope->di_scope = ZigLLVMFileToScope(import->data.structure.root_struct->di_file); } @@ -711,8 +715,8 @@ static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type const char *signed_str = int_type->data.integral.is_signed ? signed_name : unsigned_name; LLVMTypeRef param_types[] = { - operand_type->type_ref, - operand_type->type_ref, + get_llvm_type(g, operand_type), + get_llvm_type(g, operand_type), }; if (operand_type->id == ZigTypeIdVector) { @@ -720,7 +724,7 @@ static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type operand_type->data.vector.len, int_type->data.integral.bit_count); LLVMTypeRef return_elem_types[] = { - operand_type->type_ref, + get_llvm_type(g, operand_type), LLVMVectorType(LLVMInt1Type(), operand_type->data.vector.len), }; LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false); @@ -732,7 +736,7 @@ static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, ZigType *operand_type sprintf(fn_name, "llvm.%s.with.overflow.i%" PRIu32, signed_str, int_type->data.integral.bit_count); LLVMTypeRef return_elem_types[] = { - operand_type->type_ref, + get_llvm_type(g, operand_type), LLVMInt1Type(), }; LLVMTypeRef return_struct_type = LLVMStructType(return_elem_types, 2, false); @@ -800,7 +804,8 @@ static LLVMValueRef get_float_fn(CodeGen *g, ZigType *type_entry, ZigLLVMFnId fn char fn_name[64]; sprintf(fn_name, "llvm.%s.f%" ZIG_PRI_usize "", name, type_entry->data.floating.bit_count); - LLVMTypeRef fn_type = LLVMFunctionType(type_entry->type_ref, &type_entry->type_ref, 1, false); + LLVMTypeRef float_type_ref = get_llvm_type(g, type_entry); + LLVMTypeRef fn_type = LLVMFunctionType(float_type_ref, &float_type_ref, 1, false); LLVMValueRef fn_val = LLVMAddFunction(g->module, fn_name, fn_type); assert(LLVMGetIntrinsicID(fn_val)); @@ -958,7 +963,7 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); ZigType *str_type = get_slice_type(g, u8_ptr_type); - return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0)); + return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(get_llvm_type(g, str_type), 0)); } static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) { @@ -967,7 +972,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc); if (stack_trace_arg == nullptr) { ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); - stack_trace_arg = LLVMConstNull(ptr_to_stack_trace_type->type_ref); + stack_trace_arg = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type)); } LLVMValueRef args[] = { msg_arg, @@ -1081,7 +1086,7 @@ static LLVMValueRef get_coro_size_fn_val(CodeGen *g) { if (g->coro_size_fn_val) return g->coro_size_fn_val; - LLVMTypeRef fn_type = LLVMFunctionType(g->builtin_types.entry_usize->type_ref, nullptr, 0, false); + LLVMTypeRef fn_type = LLVMFunctionType(g->builtin_types.entry_usize->llvm_type, nullptr, 0, false); Buf *name = buf_sprintf("llvm.coro.size.i%d", g->pointer_size_bytes * 8); g->coro_size_fn_val = LLVMAddFunction(g->module, buf_ptr(name), fn_type); assert(LLVMGetIntrinsicID(g->coro_size_fn_val)); @@ -1206,8 +1211,8 @@ static LLVMValueRef get_return_address_fn_val(CodeGen *g) { ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); - LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref, - &g->builtin_types.entry_i32->type_ref, 1, false); + LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, return_type), + &g->builtin_types.entry_i32->llvm_type, 1, false); g->return_address_fn_val = LLVMAddFunction(g->module, "llvm.returnaddress", fn_type); assert(LLVMGetIntrinsicID(g->return_address_fn_val)); @@ -1219,8 +1224,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { return g->add_error_return_trace_addr_fn_val; LLVMTypeRef arg_types[] = { - get_ptr_to_stack_trace_type(g)->type_ref, - g->builtin_types.entry_usize->type_ref, + get_llvm_type(g, get_ptr_to_stack_trace_type(g)), + g->builtin_types.entry_usize->llvm_type, }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); @@ -1245,7 +1250,7 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, entry_block); ZigLLVMClearCurrentDebugLocation(g->builder); - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; // stack_trace.instruction_addresses[stack_trace.index & (stack_trace.instruction_addresses.len - 1)] = return_address; @@ -1297,8 +1302,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { assert(g->stack_trace_type != nullptr); LLVMTypeRef param_types[] = { - get_ptr_to_stack_trace_type(g)->type_ref, - get_ptr_to_stack_trace_type(g)->type_ref, + get_llvm_type(g, get_ptr_to_stack_trace_type(g)), + get_llvm_type(g, get_ptr_to_stack_trace_type(g)), }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), param_types, 2, false); @@ -1350,8 +1355,8 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { // } LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); - LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->type_ref, "frame_index"); - LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->type_ref, "frames_left"); + LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index"); + LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frames_left"); LLVMValueRef dest_stack_trace_ptr = LLVMGetParam(fn_val, 0); LLVMValueRef src_stack_trace_ptr = LLVMGetParam(fn_val, 1); @@ -1377,14 +1382,14 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildCondBr(g->builder, no_wrap_bit, no_wrap_block, yes_wrap_block); LLVMPositionBuilderAtEnd(g->builder, no_wrap_block); - LLVMValueRef usize_zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); + LLVMValueRef usize_zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); LLVMBuildStore(g->builder, usize_zero, frame_index_ptr); LLVMBuildStore(g->builder, src_index_val, frames_left_ptr); LLVMValueRef frames_left_eq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_index_val, usize_zero, ""); LLVMBuildCondBr(g->builder, frames_left_eq_zero_bit, return_block, loop_block); LLVMPositionBuilderAtEnd(g->builder, yes_wrap_block); - LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->type_ref, 1, false); + LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false); LLVMValueRef plus_one = LLVMBuildNUWAdd(g->builder, src_index_val, usize_one, ""); LLVMValueRef mod_len = LLVMBuildURem(g->builder, plus_one, src_len_val, ""); LLVMBuildStore(g->builder, mod_len, frame_index_ptr); @@ -1430,7 +1435,7 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMTypeRef arg_types[] = { // error return trace pointer - get_ptr_to_stack_trace_type(g)->type_ref, + get_llvm_type(g, get_ptr_to_stack_trace_type(g)), }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 1, false); @@ -1461,8 +1466,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0); - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32)); LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); @@ -1508,8 +1513,8 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { ZigType *usize = g->builtin_types.entry_usize; LLVMValueRef full_buf_ptr_indices[] = { - LLVMConstNull(usize->type_ref), - LLVMConstNull(usize->type_ref), + LLVMConstNull(usize->llvm_type), + LLVMConstNull(usize->llvm_type), }; LLVMValueRef full_buf_ptr = LLVMConstInBoundsGEP(global_array, full_buf_ptr_indices, 2); @@ -1519,9 +1524,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { ZigType *str_type = get_slice_type(g, u8_ptr_type); LLVMValueRef global_slice_fields[] = { full_buf_ptr, - LLVMConstNull(usize->type_ref), + LLVMConstNull(usize->llvm_type), }; - LLVMValueRef slice_init_value = LLVMConstNamedStruct(str_type->type_ref, global_slice_fields, 2); + LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, str_type), global_slice_fields, 2); LLVMValueRef global_slice = LLVMAddGlobal(g->module, LLVMTypeOf(slice_init_value), ""); LLVMSetInitializer(global_slice, slice_init_value); LLVMSetLinkage(global_slice, LLVMInternalLinkage); @@ -1530,15 +1535,15 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMSetAlignment(global_slice, get_abi_alignment(g, str_type)); LLVMValueRef offset_ptr_indices[] = { - LLVMConstNull(usize->type_ref), - LLVMConstInt(usize->type_ref, unwrap_err_msg_text_len, false), + LLVMConstNull(usize->llvm_type), + LLVMConstInt(usize->llvm_type, unwrap_err_msg_text_len, false), }; LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2); Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); LLVMTypeRef arg_types[] = { - g->ptr_to_stack_trace_type->type_ref, - g->err_tag_type->type_ref, + get_llvm_type(g, g->ptr_to_stack_trace_type), + get_llvm_type(g, g->err_tag_type), }; LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); @@ -1565,7 +1570,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMValueRef err_val = LLVMGetParam(fn_val, 1); LLVMValueRef err_table_indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; LLVMValueRef err_name_val = LLVMBuildInBoundsGEP(g->builder, g->err_name_table, err_table_indices, 2, ""); @@ -1623,7 +1628,7 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc LLVMValueRef err_ret_trace_val = get_cur_err_ret_trace_val(g, scope); if (err_ret_trace_val == nullptr) { ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); - err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref); + err_ret_trace_val = LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type)); } LLVMValueRef args[] = { err_ret_trace_val, @@ -1669,7 +1674,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, } static LLVMValueRef gen_assert_zero(CodeGen *g, LLVMValueRef expr_val, ZigType *int_type) { - LLVMValueRef zero = LLVMConstNull(int_type->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, int_type)); LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, ""); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail"); @@ -1704,7 +1709,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z !wanted_type->data.integral.is_signed && actual_type->data.integral.is_signed && want_runtime_safety) { - LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, actual_type)); LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntSGE, expr_val, zero, ""); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SignCastOk"); @@ -1721,19 +1726,19 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z return expr_val; } else if (actual_bits < wanted_bits) { if (actual_type->id == ZigTypeIdFloat) { - return LLVMBuildFPExt(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildFPExt(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } else if (actual_type->id == ZigTypeIdInt) { if (actual_type->data.integral.is_signed) { - return LLVMBuildSExt(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildSExt(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } else { - return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildZExt(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } } else { zig_unreachable(); } } else if (actual_bits > wanted_bits) { if (actual_type->id == ZigTypeIdFloat) { - return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildFPTrunc(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } else if (actual_type->id == ZigTypeIdInt) { if (wanted_bits == 0) { if (!want_runtime_safety) @@ -1741,15 +1746,15 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z return gen_assert_zero(g, expr_val, actual_type); } - LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); + LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); if (!want_runtime_safety) { return trunc_val; } LLVMValueRef orig_val; if (wanted_type->data.integral.is_signed) { - orig_val = LLVMBuildSExt(g->builder, trunc_val, actual_type->type_ref, ""); + orig_val = LLVMBuildSExt(g->builder, trunc_val, get_llvm_type(g, actual_type), ""); } else { - orig_val = LLVMBuildZExt(g->builder, trunc_val, actual_type->type_ref, ""); + orig_val = LLVMBuildZExt(g->builder, trunc_val, get_llvm_type(g, actual_type), ""); } LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, orig_val, ""); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); @@ -1793,7 +1798,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul LLVMValueRef extended1 = buildExtFn(g->builder, val1, one_more_bit_int_vector, ""); LLVMValueRef extended2 = buildExtFn(g->builder, val2, one_more_bit_int_vector, ""); LLVMValueRef extended_result = wrap_op[op](g->builder, extended1, extended2, ""); - result = LLVMBuildTrunc(g->builder, extended_result, operand_type->type_ref, ""); + result = LLVMBuildTrunc(g->builder, extended_result, get_llvm_type(g, operand_type), ""); LLVMValueRef re_extended_result = buildExtFn(g->builder, result, one_more_bit_int_vector, ""); LLVMValueRef overflow_vector = LLVMBuildICmp(g->builder, LLVMIntNE, extended_result, re_extended_result, ""); @@ -1880,12 +1885,13 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); ZigType *usize = g->builtin_types.entry_usize; - uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, child_type->type_ref); + uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, child_type)); uint64_t align_bytes = get_ptr_align(g, ptr_type); assert(size_bytes > 0); assert(align_bytes > 0); - ZigLLVMBuildMemCpy(g->builder, dest_ptr, align_bytes, src_ptr, align_bytes, LLVMConstInt(usize->type_ref, size_bytes, false), + ZigLLVMBuildMemCpy(g->builder, dest_ptr, align_bytes, src_ptr, align_bytes, + LLVMConstInt(usize->llvm_type, size_bytes, false), ptr_type->data.pointer.is_volatile); return nullptr; } @@ -1907,7 +1913,7 @@ static LLVMValueRef gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_ty uint32_t shift_amt = big_endian ? host_bit_count - bit_offset - size_in_bits : bit_offset; LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false); - LLVMValueRef mask_val = LLVMConstAllOnes(child_type->type_ref); + LLVMValueRef mask_val = LLVMConstAllOnes(get_llvm_type(g, child_type)); mask_val = LLVMConstZExt(mask_val, LLVMTypeOf(containing_int)); mask_val = LLVMConstShl(mask_val, shift_amt_val); mask_val = LLVMConstNot(mask_val); @@ -1942,9 +1948,10 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { if (handle_is_ptr(instruction->value.type)) { render_const_val_global(g, &instruction->value, ""); ZigType *ptr_type = get_pointer_to_type(g, instruction->value.type, true); - instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, ptr_type->type_ref, ""); + instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_global, get_llvm_type(g, ptr_type), ""); } else if (instruction->value.type->id == ZigTypeIdPointer) { - instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value, instruction->value.type->type_ref, ""); + instruction->llvm_value = LLVMBuildBitCast(g->builder, instruction->value.global_refs->llvm_value, + get_llvm_type(g, instruction->value.type), ""); } else { instruction->llvm_value = instruction->value.global_refs->llvm_value; } @@ -1979,7 +1986,7 @@ static void give_up_with_c_abi_error(CodeGen *g, AstNode *source_node) { } static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment) { - LLVMValueRef result = LLVMBuildAlloca(g->builder, type_entry->type_ref, name); + LLVMValueRef result = LLVMBuildAlloca(g->builder, get_llvm_type(g, type_entry), name); LLVMSetAlignment(result, (alignment == 0) ? get_abi_alignment(g, type_entry) : alignment); return result; } @@ -2062,8 +2069,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ fn_walk->data.call.gen_param_values->append(val); break; case FnWalkIdTypes: - fn_walk->data.types.gen_param_types->append(ty->type_ref); - fn_walk->data.types.param_di_types->append(ty->di_type); + fn_walk->data.types.gen_param_types->append(get_llvm_type(g, ty)); + fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, ty)); break; case FnWalkIdVars: { var->value_ref = build_alloca(g, ty, buf_ptr(&var->name), var->align_bytes); @@ -2099,8 +2106,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ break; case FnWalkIdTypes: { ZigType *gen_type = get_pointer_to_type(g, ty, true); - fn_walk->data.types.gen_param_types->append(gen_type->type_ref); - fn_walk->data.types.param_di_types->append(gen_type->di_type); + fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type)); + fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type)); break; } case FnWalkIdVars: { @@ -2138,8 +2145,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ break; case FnWalkIdTypes: { ZigType *gen_type = get_pointer_to_type(g, ty, true); - fn_walk->data.types.gen_param_types->append(gen_type->type_ref); - fn_walk->data.types.param_di_types->append(gen_type->di_type); + fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type)); + fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type)); break; } case FnWalkIdVars: { @@ -2171,8 +2178,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ } case FnWalkIdTypes: { ZigType *gen_type = get_int_type(g, false, ty_size * 8); - fn_walk->data.types.gen_param_types->append(gen_type->type_ref); - fn_walk->data.types.param_di_types->append(gen_type->di_type); + fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type)); + fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type)); break; } case FnWalkIdVars: { @@ -2210,7 +2217,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), fn_walk->data.vars.import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), - dest_ty->di_type, !g->strip_debug_symbols, 0, di_arg_index + 1); + get_llvm_di_type(g, dest_ty), !g->strip_debug_symbols, 0, di_arg_index + 1); } return true; } @@ -2282,7 +2289,9 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) { if (!handle_is_ptr(variable->var_type)) { clear_debug_source_node(g); - gen_store_untyped(g, LLVMGetParam(llvm_fn, (unsigned)variable->gen_arg_index), + ZigType *fn_type = fn_table_entry->type_entry; + unsigned gen_arg_index = fn_type->data.fn.gen_param_info[variable->src_arg_index].gen_index; + gen_store_untyped(g, LLVMGetParam(llvm_fn, gen_arg_index), variable->value_ref, variable->align_bytes, false); } @@ -2436,7 +2445,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast { ZigLLVMSetFastMath(g->builder, want_fast_math); - LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, type_entry)); if (want_runtime_safety && (want_fast_math || type_entry->id != ZigTypeIdFloat)) { LLVMValueRef is_zero_bit; if (type_entry->id == ZigTypeIdInt) { @@ -2456,10 +2465,10 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block); if (type_entry->id == ZigTypeIdInt && type_entry->data.integral.is_signed) { - LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true); + LLVMValueRef neg_1_value = LLVMConstInt(get_llvm_type(g, type_entry), -1, true); BigInt int_min_bi = {0}; eval_min_max_value_int(g, type_entry, &int_min_bi, false); - LLVMValueRef int_min_value = bigint_to_llvm_const(type_entry->type_ref, &int_min_bi); + LLVMValueRef int_min_value = bigint_to_llvm_const(get_llvm_type(g, type_entry), &int_min_bi); LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk"); LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail"); LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, ""); @@ -2513,7 +2522,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast LLVMBuildBr(g->builder, end_block); LLVMPositionBuilderAtEnd(g->builder, end_block); - LLVMValueRef phi = LLVMBuildPhi(g->builder, type_entry->type_ref, ""); + LLVMValueRef phi = LLVMBuildPhi(g->builder, get_llvm_type(g, type_entry), ""); LLVMValueRef incoming_values[] = { ceiled, floored }; LLVMBasicBlockRef incoming_blocks[] = { ceiled_end_block, floored_end_block }; LLVMAddIncoming(phi, incoming_values, incoming_blocks, 2); @@ -2576,7 +2585,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_runtime_safety, bool want_fast LLVMValueRef orig_num = LLVMBuildNSWMul(g->builder, result, val2, ""); LLVMValueRef orig_ok = LLVMBuildICmp(g->builder, LLVMIntEQ, orig_num, val1, ""); LLVMValueRef ok_bit = LLVMBuildOr(g->builder, orig_ok, is_pos, ""); - LLVMValueRef one = LLVMConstInt(type_entry->type_ref, 1, true); + LLVMValueRef one = LLVMConstInt(get_llvm_type(g, type_entry), 1, true); LLVMValueRef result_minus_1 = LLVMBuildNSWSub(g->builder, result, one, ""); return LLVMBuildSelect(g->builder, ok_bit, result, result_minus_1, ""); } @@ -2595,7 +2604,7 @@ static LLVMValueRef gen_rem(CodeGen *g, bool want_runtime_safety, bool want_fast { ZigLLVMSetFastMath(g->builder, want_fast_math); - LLVMValueRef zero = LLVMConstNull(type_entry->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, type_entry)); if (want_runtime_safety) { LLVMValueRef is_zero_bit; if (type_entry->id == ZigTypeIdInt) { @@ -2820,7 +2829,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in assert(err_set_type->id == ZigTypeIdErrorSet); if (type_is_global_error_set(err_set_type)) { - LLVMValueRef zero = LLVMConstNull(int_type->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, int_type)); LLVMValueRef neq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntNE, target_val, zero, ""); LLVMValueRef ok_bit; @@ -2832,7 +2841,7 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in { ok_bit = neq_zero_bit; } else { - LLVMValueRef error_value_count = LLVMConstInt(int_type->type_ref, g->errors_by_index.length, false); + LLVMValueRef error_value_count = LLVMConstInt(get_llvm_type(g, int_type), g->errors_by_index.length, false); LLVMValueRef in_bounds_bit = LLVMBuildICmp(g->builder, LLVMIntULT, target_val, error_value_count, ""); ok_bit = LLVMBuildAnd(g->builder, neq_zero_bit, in_bounds_bit, ""); } @@ -2853,7 +2862,8 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in uint32_t err_count = err_set_type->data.error_set.err_count; LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, target_val, fail_block, err_count); for (uint32_t i = 0; i < err_count; i += 1) { - LLVMValueRef case_value = LLVMConstInt(g->err_tag_type->type_ref, err_set_type->data.error_set.errors[i]->value, false); + LLVMValueRef case_value = LLVMConstInt(get_llvm_type(g, g->err_tag_type), + err_set_type->data.error_set.errors[i]->value, false); LLVMAddCase(switch_instr, case_value, ok_block); } @@ -2892,7 +2902,7 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, - wanted_type->data.structure.fields[0].type_entry->type_ref, ""); + get_llvm_type(g, wanted_type->data.structure.fields[0].type_entry), ""); LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)wanted_ptr_index, ""); gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); @@ -2904,13 +2914,13 @@ static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable, LLVMValueRef new_len; if (dest_size == 1) { - LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false); + LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, src_size, false); new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); } else if (src_size == 1) { - LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false); + LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, dest_size, false); if (ir_want_runtime_safety(g, &instruction->base)) { LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref); + LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); @@ -2951,9 +2961,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, case CastOpIntToFloat: assert(actual_type->id == ZigTypeIdInt); if (actual_type->data.integral.is_signed) { - return LLVMBuildSIToFP(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildSIToFP(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } else { - return LLVMBuildUIToFP(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildUIToFP(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } case CastOpFloatToInt: { assert(wanted_type->id == ZigTypeIdInt); @@ -2963,9 +2973,9 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, LLVMValueRef result; if (wanted_type->data.integral.is_signed) { - result = LLVMBuildFPToSI(g->builder, expr_val, wanted_type->type_ref, ""); + result = LLVMBuildFPToSI(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } else { - result = LLVMBuildFPToUI(g->builder, expr_val, wanted_type->type_ref, ""); + result = LLVMBuildFPToUI(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); } if (want_safety) { @@ -2993,14 +3003,14 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, case CastOpBoolToInt: assert(wanted_type->id == ZigTypeIdInt); assert(actual_type->id == ZigTypeIdBool); - return LLVMBuildZExt(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildZExt(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); case CastOpErrSet: if (ir_want_runtime_safety(g, &cast_instruction->base)) { add_error_range_check(g, wanted_type, g->err_tag_type, expr_val); } return expr_val; case CastOpBitCast: - return LLVMBuildBitCast(g->builder, expr_val, wanted_type->type_ref, ""); + return LLVMBuildBitCast(g->builder, expr_val, get_llvm_type(g, wanted_type), ""); case CastOpPtrOfArrayToSlice: { assert(cast_instruction->tmp_ptr); assert(actual_type->id == ZigTypeIdPointer); @@ -3010,15 +3020,15 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable, LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), - LLVMConstInt(g->builtin_types.entry_usize->type_ref, 0, false), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), + LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false), }; LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr, slice_len_index, ""); - LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->type_ref, + LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); gen_store_untyped(g, len_value, len_field_ptr, 0, false); @@ -3036,7 +3046,7 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable, return nullptr; } LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); - LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, ""); + LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, get_llvm_type(g, wanted_type), ""); bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base); if (!want_safety_check || ptr_allows_addr_zero(wanted_type)) return result_ptr; @@ -3066,16 +3076,16 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable, if (wanted_is_ptr == actual_is_ptr) { // We either bitcast the value directly or bitcast the pointer which does a pointer cast LLVMTypeRef wanted_type_ref = wanted_is_ptr ? - LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref; + LLVMPointerType(get_llvm_type(g, wanted_type), 0) : get_llvm_type(g, wanted_type); return LLVMBuildBitCast(g->builder, value, wanted_type_ref, ""); } else if (actual_is_ptr) { - LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(wanted_type->type_ref, 0); + LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0); LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, ""); uint32_t alignment = get_abi_alignment(g, actual_type); return gen_load_untyped(g, bitcasted_ptr, alignment, false, ""); } else { assert(instruction->tmp_ptr != nullptr); - LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(actual_type->type_ref, 0); + LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, actual_type), 0); LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, ""); uint32_t alignment = get_abi_alignment(g, wanted_type); gen_store_untyped(g, value, bitcasted_ptr, alignment, false); @@ -3115,13 +3125,13 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutable *executable, I LLVMPositionBuilderAtEnd(g->builder, ok_block); } - return LLVMBuildIntToPtr(g->builder, target_val, wanted_type->type_ref, ""); + return LLVMBuildIntToPtr(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } static LLVMValueRef ir_render_ptr_to_int(CodeGen *g, IrExecutable *executable, IrInstructionPtrToInt *instruction) { ZigType *wanted_type = instruction->base.value.type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); - return LLVMBuildPtrToInt(g->builder, target_val, wanted_type->type_ref, ""); + return LLVMBuildPtrToInt(g->builder, target_val, get_llvm_type(g, wanted_type), ""); } static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, IrInstructionIntToEnum *instruction) { @@ -3139,7 +3149,7 @@ static LLVMValueRef ir_render_int_to_enum(CodeGen *g, IrExecutable *executable, size_t field_count = wanted_type->data.enumeration.src_field_count; LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, tag_int_value, bad_value_block, field_count); for (size_t field_i = 0; field_i < field_count; field_i += 1) { - LLVMValueRef this_tag_int_value = bigint_to_llvm_const(tag_int_type->type_ref, + LLVMValueRef this_tag_int_value = bigint_to_llvm_const(get_llvm_type(g, tag_int_type), &wanted_type->data.enumeration.fields[field_i].value); LLVMAddCase(switch_instr, this_tag_int_value, ok_value_block); } @@ -3321,7 +3331,7 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, ""); if (!handle_is_ptr(child_type)) - return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, ""); + return LLVMBuildTrunc(g->builder, shifted_value, get_llvm_type(g, child_type), ""); assert(instruction->tmp_ptr != nullptr); LLVMTypeRef same_size_int = LLVMIntType(size_in_bits); @@ -3378,7 +3388,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default if (!target_has_valgrind_support(g->zig_target)) { return default_value; } - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; bool asm_has_side_effects = true; bool asm_is_alignstack = false; if (g->zig_target->arch == ZigLLVM_x86_64) { @@ -3445,7 +3455,7 @@ static bool want_valgrind_support(CodeGen *g) { static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) { assert(type_has_bits(value_type)); - uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref); + uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, value_type)); assert(size_bytes > 0); assert(ptr_align_bytes > 0); // memset uninitialized memory to 0xaa @@ -3453,14 +3463,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_ LLVMValueRef fill_char = LLVMConstInt(LLVMInt8Type(), 0xaa, false); LLVMValueRef dest_ptr = LLVMBuildBitCast(g->builder, ptr, ptr_u8, ""); ZigType *usize = g->builtin_types.entry_usize; - LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false); + LLVMValueRef byte_count = LLVMConstInt(usize->llvm_type, size_bytes, false); ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false); // then tell valgrind that the memory is undefined even though we just memset it if (want_valgrind_support(g)) { static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; - LLVMValueRef zero = LLVMConstInt(usize->type_ref, 0, false); - LLVMValueRef req = LLVMConstInt(usize->type_ref, VG_USERREQ__MAKE_MEM_UNDEFINED, false); - LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->type_ref, ""); + LLVMValueRef zero = LLVMConstInt(usize->llvm_type, 0, false); + LLVMValueRef req = LLVMConstInt(usize->llvm_type, VG_USERREQ__MAKE_MEM_UNDEFINED, false); + LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->llvm_type, ""); gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero); } } @@ -3515,7 +3525,7 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI array_type = array_type->data.pointer.child_type; } if (safety_check_on) { - LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, + LLVMValueRef end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, end); } @@ -3533,18 +3543,18 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI LLVMTypeRef ptr_u8_type_ref = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef u8_array_ptr = LLVMBuildBitCast(g->builder, array_ptr, ptr_u8_type_ref, ""); assert(size_in_bits % 8 == 0); - LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->type_ref, + LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, size_in_bits / 8, false); LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); LLVMValueRef indices[] = { byte_offset }; LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, ""); - return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(child_type->type_ref, 0), ""); + return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(get_llvm_type(g, child_type), 0), ""); } } LLVMValueRef indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), subscript_value }; return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); @@ -3556,7 +3566,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, IrExecutable *executable, IrI return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, ""); } else if (array_type->id == ZigTypeIdStruct) { assert(array_type->data.structure.is_slice); - if (!type_has_bits(instruction->base.value.type)) { + + ZigType *ptr_type = instruction->base.value.type; + if (!type_has_bits(ptr_type)) { if (safety_check_on) { assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMIntegerTypeKind); add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, LLVMIntULT, array_ptr); @@ -3773,7 +3785,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab return nullptr; LLVMValueRef union_ptr = ir_llvm_value(g, instruction->union_ptr); - LLVMTypeRef field_type_ref = LLVMPointerType(field->type_entry->type_ref, 0); + LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0); if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, ""); @@ -3786,7 +3798,7 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, IrExecutable *executab LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); - LLVMValueRef expected_tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, + LLVMValueRef expected_tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), &field->enum_field->value); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckOk"); LLVMBasicBlockRef bad_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnionCheckFail"); @@ -3916,7 +3928,7 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru } ZigType *const type = ir_input->value.type; - LLVMTypeRef type_ref = type->type_ref; + LLVMTypeRef type_ref = get_llvm_type(g, type); LLVMValueRef value_ref = ir_llvm_value(g, ir_input); // Handle integers of non pot bitsize by widening them. if (type->id == ZigTypeIdInt) { @@ -3925,7 +3937,7 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru const bool is_signed = type->data.integral.is_signed; const size_t wider_bitsize = bitsize < 8 ? 8 : round_to_next_power_of_2(bitsize); ZigType *const wider_type = get_int_type(g, is_signed, wider_bitsize); - type_ref = wider_type->type_ref; + type_ref = get_llvm_type(g, wider_type); value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref); } } @@ -3945,7 +3957,7 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru if (instruction->return_count == 0) { ret_type = LLVMVoidType(); } else { - ret_type = instruction->base.value.type->type_ref; + ret_type = get_llvm_type(g, instruction->base.value.type); } LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, (unsigned)input_and_output_count, false); @@ -3964,7 +3976,7 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR } else { bool is_scalar = !handle_is_ptr(maybe_type); if (is_scalar) { - return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(maybe_type->type_ref), ""); + return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); } else { LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); @@ -3999,7 +4011,7 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, IrExecutable *exec LLVMPositionBuilderAtEnd(g->builder, ok_block); } - if (child_type->zero_bits) { + if (!type_has_bits(child_type)) { return nullptr; } else { bool is_scalar = !handle_is_ptr(maybe_type); @@ -4052,10 +4064,10 @@ static LLVMValueRef get_int_builtin_fn(CodeGen *g, ZigType *int_type, BuiltinFnI char llvm_name[64]; sprintf(llvm_name, "llvm.%s.i%" PRIu32, fn_name, int_type->data.integral.bit_count); LLVMTypeRef param_types[] = { - int_type->type_ref, + get_llvm_type(g, int_type), LLVMInt1Type(), }; - LLVMTypeRef fn_type = LLVMFunctionType(int_type->type_ref, param_types, n_args, false); + LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, int_type), param_types, n_args, false); LLVMValueRef fn_val = LLVMAddFunction(g->module, llvm_name, fn_type); assert(LLVMGetIntrinsicID(fn_val)); @@ -4114,9 +4126,9 @@ static LLVMValueRef ir_render_phi(CodeGen *g, IrExecutable *executable, IrInstru LLVMTypeRef phi_type; if (handle_is_ptr(instruction->base.value.type)) { - phi_type = LLVMPointerType(instruction->base.value.type->type_ref, 0); + phi_type = LLVMPointerType(get_llvm_type(g,instruction->base.value.type), 0); } else { - phi_type = instruction->base.value.type->type_ref; + phi_type = get_llvm_type(g, instruction->base.value.type); } LLVMValueRef phi = LLVMBuildPhi(g->builder, phi_type, ""); @@ -4160,7 +4172,7 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, IrExecutable *executable, IrI } LLVMValueRef indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); @@ -4176,8 +4188,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { ZigType *u8_slice_type = get_slice_type(g, u8_ptr_type); ZigType *tag_int_type = enum_type->data.enumeration.tag_int_type; - LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(u8_slice_type->type_ref, 0), - &tag_int_type->type_ref, 1, false); + LLVMTypeRef tag_int_llvm_type = get_llvm_type(g, tag_int_type); + LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(get_llvm_type(g, u8_slice_type), 0), + &tag_int_llvm_type, 1, false); Buf *fn_name = get_mangled_name(g, buf_sprintf("__zig_tag_name_%s", buf_ptr(&enum_type->name)), false); LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); @@ -4209,8 +4222,8 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { ZigType *usize = g->builtin_types.entry_usize; LLVMValueRef array_ptr_indices[] = { - LLVMConstNull(usize->type_ref), - LLVMConstNull(usize->type_ref), + LLVMConstNull(usize->llvm_type), + LLVMConstNull(usize->llvm_type), }; for (size_t field_i = 0; field_i < field_count; field_i += 1) { @@ -4225,9 +4238,9 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMValueRef fields[] = { LLVMConstGEP(str_global, array_ptr_indices, 2), - LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(name), false), + LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false), }; - LLVMValueRef slice_init_value = LLVMConstNamedStruct(u8_slice_type->type_ref, fields, 2); + LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, u8_slice_type), fields, 2); LLVMValueRef slice_global = LLVMAddGlobal(g->module, LLVMTypeOf(slice_init_value), ""); LLVMSetInitializer(slice_global, slice_init_value); @@ -4237,7 +4250,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMSetAlignment(slice_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(slice_init_value))); LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "Name"); - LLVMValueRef this_tag_int_value = bigint_to_llvm_const(tag_int_type->type_ref, + LLVMValueRef this_tag_int_value = bigint_to_llvm_const(get_llvm_type(g, tag_int_type), &enum_type->data.enumeration.fields[field_i].value); LLVMAddCase(switch_instr, this_tag_int_value, return_block); @@ -4283,22 +4296,21 @@ static LLVMValueRef ir_render_field_parent_ptr(CodeGen *g, IrExecutable *executa ZigType *container_type = container_ptr_type->data.pointer.child_type; size_t byte_offset = LLVMOffsetOfElement(g->target_data_ref, - container_type->type_ref, instruction->field->gen_index); + get_llvm_type(g, container_type), instruction->field->gen_index); LLVMValueRef field_ptr_val = ir_llvm_value(g, instruction->field_ptr); if (byte_offset == 0) { - return LLVMBuildBitCast(g->builder, field_ptr_val, container_ptr_type->type_ref, ""); + return LLVMBuildBitCast(g->builder, field_ptr_val, get_llvm_type(g, container_ptr_type), ""); } else { ZigType *usize = g->builtin_types.entry_usize; - LLVMValueRef field_ptr_int = LLVMBuildPtrToInt(g->builder, field_ptr_val, - usize->type_ref, ""); + LLVMValueRef field_ptr_int = LLVMBuildPtrToInt(g->builder, field_ptr_val, usize->llvm_type, ""); LLVMValueRef base_ptr_int = LLVMBuildNUWSub(g->builder, field_ptr_int, - LLVMConstInt(usize->type_ref, byte_offset, false), ""); + LLVMConstInt(usize->llvm_type, byte_offset, false), ""); - return LLVMBuildIntToPtr(g->builder, base_ptr_int, container_ptr_type->type_ref, ""); + return LLVMBuildIntToPtr(g->builder, base_ptr_int, get_llvm_type(g, container_ptr_type), ""); } } @@ -4349,10 +4361,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I assert(align_bytes != 1); ZigType *usize = g->builtin_types.entry_usize; - LLVMValueRef ptr_as_int_val = LLVMBuildPtrToInt(g->builder, ptr_val, usize->type_ref, ""); - LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->type_ref, align_bytes - 1, false); + LLVMValueRef ptr_as_int_val = LLVMBuildPtrToInt(g->builder, ptr_val, usize->llvm_type, ""); + LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->llvm_type, align_bytes - 1, false); LLVMValueRef anded_val = LLVMBuildAnd(g->builder, ptr_as_int_val, alignment_minus_1, ""); - LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, LLVMConstNull(usize->type_ref), ""); + LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, LLVMConstNull(usize->llvm_type), ""); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "AlignCastOk"); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "AlignCastFail"); @@ -4373,7 +4385,7 @@ static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *execu LLVMValueRef cur_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope); if (cur_err_ret_trace_val == nullptr) { ZigType *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); - return LLVMConstNull(ptr_to_stack_trace_type->type_ref); + return LLVMConstNull(get_llvm_type(g, ptr_to_stack_trace_type)); } return cur_err_ret_trace_val; } @@ -4439,7 +4451,7 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, IrExecutable *executable, IrIn if (!handle_is_ptr(maybe_type)) { LLVMValueRef payload_val = LLVMBuildExtractValue(g->builder, result_val, 0, ""); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); - return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(child_type->type_ref), payload_val, ""); + return LLVMBuildSelect(g->builder, success_bit, LLVMConstNull(get_llvm_type(g, child_type)), payload_val, ""); } assert(instruction->tmp_ptr != nullptr); @@ -4470,10 +4482,10 @@ static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrI // no-op return target_val; } if (src_type->data.integral.bit_count == dest_type->data.integral.bit_count) { - return LLVMBuildBitCast(g->builder, target_val, dest_type->type_ref, ""); + return LLVMBuildBitCast(g->builder, target_val, get_llvm_type(g, dest_type), ""); } else { LLVMValueRef target_val = ir_llvm_value(g, instruction->target); - return LLVMBuildTrunc(g->builder, target_val, dest_type->type_ref, ""); + return LLVMBuildTrunc(g->builder, target_val, get_llvm_type(g, dest_type), ""); } } @@ -4539,12 +4551,12 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst if (instruction->end) { end_val = ir_llvm_value(g, instruction->end); } else { - end_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, array_type->data.array.len, false); + end_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); } if (want_runtime_safety) { add_bounds_check(g, start_val, LLVMIntEQ, nullptr, LLVMIntULE, end_val); if (instruction->end) { - LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->type_ref, + LLVMValueRef array_end = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); add_bounds_check(g, end_val, LLVMIntEQ, nullptr, LLVMIntULE, array_end); } @@ -4561,7 +4573,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInst LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), start_val, }; LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); @@ -4663,9 +4675,9 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutable *executable, I static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutable *executable, IrInstructionReturnAddress *instruction) { - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); + LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); - return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->type_ref, ""); + return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { @@ -4674,8 +4686,8 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { ZigType *return_type = get_pointer_to_type(g, g->builtin_types.entry_u8, true); - LLVMTypeRef fn_type = LLVMFunctionType(return_type->type_ref, - &g->builtin_types.entry_i32->type_ref, 1, false); + LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, return_type), + &g->builtin_types.entry_i32->llvm_type, 1, false); g->frame_address_fn_val = LLVMAddFunction(g->module, "llvm.frameaddress", fn_type); assert(LLVMGetIntrinsicID(g->frame_address_fn_val)); @@ -4685,9 +4697,9 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { static LLVMValueRef ir_render_frame_address(CodeGen *g, IrExecutable *executable, IrInstructionFrameAddress *instruction) { - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->type_ref); + LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, ""); - return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->type_ref, ""); + return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } static LLVMValueRef get_handle_fn_val(CodeGen *g) { @@ -4706,7 +4718,7 @@ static LLVMValueRef get_handle_fn_val(CodeGen *g) { static LLVMValueRef ir_render_handle(CodeGen *g, IrExecutable *executable, IrInstructionHandle *instruction) { - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_promise->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_promise)); return LLVMBuildCall(g->builder, get_handle_fn_val(g), &zero, 0, ""); } @@ -4786,7 +4798,7 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, IrExecutable *executable, IrI err_val = err_union_handle; } - LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); return LLVMBuildICmp(g->builder, LLVMIntNE, err_val, zero, ""); } @@ -4834,7 +4846,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu } else { err_val = err_union_handle; } - LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref); + LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, ""); LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrError"); LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "UnwrapErrOk"); @@ -4860,7 +4872,7 @@ static LLVMValueRef ir_render_maybe_wrap(CodeGen *g, IrExecutable *executable, I ZigType *child_type = wanted_type->data.maybe.child_type; - if (child_type->zero_bits) { + if (!type_has_bits(child_type)) { return LLVMConstInt(LLVMInt1Type(), 1, false); } @@ -4913,7 +4925,7 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, IrExecutable *executa return ir_llvm_value(g, instruction->value); } - LLVMValueRef ok_err_val = LLVMConstNull(g->err_tag_type->type_ref); + LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); if (!type_has_bits(payload_type)) return ok_err_val; @@ -4991,7 +5003,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = bigint_to_llvm_const(union_type->data.unionation.tag_type->type_ref, + LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), &type_union_field->enum_field->value); gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); @@ -5001,7 +5013,7 @@ static LLVMValueRef ir_render_union_init(CodeGen *g, IrExecutable *executable, I uncasted_union_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr, (unsigned)0, ""); } - LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, ptr_type->type_ref, ""); + LLVMValueRef field_ptr = LLVMBuildBitCast(g->builder, uncasted_union_ptr, get_llvm_type(g, ptr_type), ""); LLVMValueRef value = ir_llvm_value(g, instruction->init_value); gen_assign_raw(g, field_ptr, ptr_type, value); @@ -5023,8 +5035,8 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec for (size_t i = 0; i < field_count; i += 1) { LLVMValueRef elem_val = ir_llvm_value(g, instruction->items[i]); LLVMValueRef indices[] = { - LLVMConstNull(g->builtin_types.entry_usize->type_ref), - LLVMConstInt(g->builtin_types.entry_usize->type_ref, i, false), + LLVMConstNull(g->builtin_types.entry_usize->llvm_type), + LLVMConstInt(g->builtin_types.entry_usize->llvm_type, i, false), }; LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, tmp_array_ptr, indices, 2, ""); gen_assign_raw(g, elem_ptr, get_pointer_to_type(g, child_type, false), elem_val); @@ -5041,7 +5053,7 @@ static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInst static LLVMValueRef ir_render_coro_id(CodeGen *g, IrExecutable *executable, IrInstructionCoroId *instruction) { LLVMValueRef promise_ptr = ir_llvm_value(g, instruction->promise_ptr); LLVMValueRef align_val = LLVMConstInt(LLVMInt32Type(), get_coro_frame_align_bytes(g), false); - LLVMValueRef null = LLVMConstIntToPtr(LLVMConstNull(g->builtin_types.entry_usize->type_ref), + LLVMValueRef null = LLVMConstIntToPtr(LLVMConstNull(g->builtin_types.entry_usize->llvm_type), LLVMPointerType(LLVMInt8Type(), 0)); LLVMValueRef params[] = { align_val, @@ -5140,7 +5152,7 @@ static LLVMValueRef ir_render_coro_promise(CodeGen *g, IrExecutable *executable, LLVMConstNull(LLVMInt1Type()), }; LLVMValueRef uncasted_result = LLVMBuildCall(g->builder, get_coro_promise_fn_val(g), params, 3, ""); - return LLVMBuildBitCast(g->builder, uncasted_result, instruction->base.value.type->type_ref, ""); + return LLVMBuildBitCast(g->builder, uncasted_result, get_llvm_type(g, instruction->base.value.type), ""); } static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_fn_type_ref, ZigType *fn_type) { @@ -5161,8 +5173,8 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f arg_types.append(alloc_fn_arg_types[1]); } arg_types.append(alloc_fn_arg_types[g->have_err_ret_tracing ? 2 : 1]); - arg_types.append(ptr_to_err_code_type->type_ref); - arg_types.append(g->builtin_types.entry_usize->type_ref); + arg_types.append(get_llvm_type(g, ptr_to_err_code_type)); + arg_types.append(g->builtin_types.entry_usize->llvm_type); LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMPointerType(LLVMInt8Type(), 0), arg_types.items, arg_types.length, false); @@ -5204,7 +5216,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f next_arg += 1; LLVMValueRef coro_size = LLVMGetParam(fn_val, next_arg); next_arg += 1; - LLVMValueRef alignment_val = LLVMConstInt(g->builtin_types.entry_u29->type_ref, + LLVMValueRef alignment_val = LLVMConstInt(g->builtin_types.entry_u29->llvm_type, get_coro_frame_align_bytes(g), false); ConstExprValue *zero_array = create_const_str_lit(g, buf_create_from_str("")); @@ -5219,7 +5231,7 @@ static LLVMValueRef get_coro_alloc_helper_fn_val(CodeGen *g, LLVMTypeRef alloc_f } args.append(allocator_val); args.append(undef_slice_zero->global_refs->llvm_global); - args.append(LLVMGetUndef(g->builtin_types.entry_u29->type_ref)); + args.append(LLVMGetUndef(g->builtin_types.entry_u29->llvm_type)); args.append(coro_size); args.append(alignment_val); LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, realloc_fn_val, args.items, args.length, @@ -5299,10 +5311,10 @@ static LLVMValueRef ir_render_atomic_rmw(CodeGen *g, IrExecutable *executable, // it's a pointer but we need to treat it as an int LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, ptr, - LLVMPointerType(g->builtin_types.entry_usize->type_ref, 0), ""); - LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->type_ref, ""); + LLVMPointerType(g->builtin_types.entry_usize->llvm_type, 0), ""); + LLVMValueRef casted_operand = LLVMBuildPtrToInt(g->builder, operand, g->builtin_types.entry_usize->llvm_type, ""); LLVMValueRef uncasted_result = LLVMBuildAtomicRMW(g->builder, op, casted_ptr, casted_operand, ordering, false); - return LLVMBuildIntToPtr(g->builder, uncasted_result, operand_type->type_ref, ""); + return LLVMBuildIntToPtr(g->builder, uncasted_result, get_llvm_type(g, operand_type), ""); } static LLVMValueRef ir_render_atomic_load(CodeGen *g, IrExecutable *executable, @@ -5355,15 +5367,15 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, IrExecutable *executable, IrInst ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, int_type->data.integral.bit_count + 8); // aabbcc - LLVMValueRef extended = LLVMBuildZExt(g->builder, op, extended_type->type_ref, ""); + LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); // ccbbaa00 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, - LLVMConstInt(extended_type->type_ref, 8, false), ""); + LLVMConstInt(get_llvm_type(g, extended_type), 8, false), ""); // 00ccbbaa - return LLVMBuildTrunc(g->builder, shifted, int_type->type_ref, ""); + return LLVMBuildTrunc(g->builder, shifted, get_llvm_type(g, int_type), ""); } static LLVMValueRef ir_render_bit_reverse(CodeGen *g, IrExecutable *executable, IrInstructionBitReverse *instruction) { @@ -5383,7 +5395,7 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, IrExecutable *executab assert(instruction->tmp_ptr); LLVMValueRef vector = ir_llvm_value(g, instruction->vector); LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, - LLVMPointerType(instruction->vector->value.type->type_ref, 0), ""); + LLVMPointerType(get_llvm_type(g, instruction->vector->value.type), 0), ""); gen_store_untyped(g, vector, casted_ptr, 0, false); return instruction->tmp_ptr; } @@ -5396,7 +5408,7 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, IrExecutable *executab assert(!handle_is_ptr(vector_type)); LLVMValueRef array_ptr = ir_llvm_value(g, instruction->array); LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, - LLVMPointerType(vector_type->type_ref, 0), ""); + LLVMPointerType(get_llvm_type(g, vector_type), 0), ""); return gen_load_untyped(g, casted_ptr, 0, false, ""); } @@ -5685,6 +5697,7 @@ static void ir_render(CodeGen *g, ZigFn *fn_entry) { IrInstruction *instruction = current_block->instruction_list.at(instr_i); if (instruction->ref_count == 0 && !ir_has_side_effects(instruction)) continue; + instruction->llvm_value = ir_render_instruction(g, executable, instruction); } current_block->llvm_exit_block = LLVMGetInsertBlock(g->builder); @@ -5735,15 +5748,15 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ConstExprValue *ar if (el_type == LLVMArrayTypeKind) { ZigType *usize = g->builtin_types.entry_usize; LLVMValueRef indices[] = { - LLVMConstNull(usize->type_ref), - LLVMConstInt(usize->type_ref, index, false), + LLVMConstNull(usize->llvm_type), + LLVMConstInt(usize->llvm_type, index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } else if (el_type == LLVMStructTypeKind) { ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, index, false), + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } else { @@ -5758,8 +5771,8 @@ static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ConstExprValue *s ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, field_index, false), + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), field_index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } @@ -5770,8 +5783,8 @@ static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ConstExpr ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, err_union_err_index, false), + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), err_union_err_index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } @@ -5782,8 +5795,8 @@ static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ConstE ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, err_union_payload_index, false), + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), err_union_payload_index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } @@ -5794,8 +5807,8 @@ static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ConstEx ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, maybe_child_index, false), + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), maybe_child_index, false), }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } @@ -5806,8 +5819,8 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(u32->type_ref), - LLVMConstInt(u32->type_ref, 0, false), // TODO test const union with more aligned tag type than payload + LLVMConstNull(get_llvm_type(g, u32)), + LLVMConstInt(get_llvm_type(g, u32), 0, false), // TODO test const union with more aligned tag type than payload }; return LLVMConstInBoundsGEP(base_ptr, indices, 2); } @@ -5823,7 +5836,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con } ZigType *type_entry = const_val->type; - assert(!type_entry->zero_bits); + assert(type_has_bits(type_entry)); switch (type_entry->id) { case ZigTypeIdInvalid: case ZigTypeIdMetaType: @@ -5866,7 +5879,7 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con case ZigTypeIdPromise: { LLVMValueRef ptr_val = gen_const_val(g, const_val, ""); - LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref); + LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->llvm_type); return LLVMConstZExt(ptr_size_int_val, big_int_type_ref); } case ZigTypeIdArray: { @@ -5933,8 +5946,8 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con // We have this because union constants can't be represented by the official union type, // and this property bubbles up in whatever aggregate type contains a union constant -static bool is_llvm_value_unnamed_type(ZigType *type_entry, LLVMValueRef val) { - return LLVMTypeOf(val) != type_entry->type_ref; +static bool is_llvm_value_unnamed_type(CodeGen *g, ZigType *type_entry, LLVMValueRef val) { + return LLVMTypeOf(val) != get_llvm_type(g, type_entry); } static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, const char *name) { @@ -5948,7 +5961,8 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con ConstExprValue *pointee = const_val->data.x_ptr.data.ref.pointee; render_const_val(g, pointee, ""); render_const_val_global(g, pointee, ""); - const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstBitCast(pointee->global_refs->llvm_global, + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } case ConstPtrSpecialBaseArray: @@ -5959,13 +5973,13 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con if (!type_has_bits(array_const_val->type)) { // make this a null pointer ZigType *usize = g->builtin_types.entry_usize; - const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), - const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } size_t elem_index = const_val->data.x_ptr.data.base_array.elem_index; LLVMValueRef uncasted_ptr_val = gen_const_ptr_array_recursive(g, array_const_val, elem_index); - LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); const_val->global_refs->llvm_value = ptr_val; return ptr_val; } @@ -5977,15 +5991,15 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con if (!type_has_bits(struct_const_val->type)) { // make this a null pointer ZigType *usize = g->builtin_types.entry_usize; - const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), - const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } size_t src_field_index = const_val->data.x_ptr.data.base_struct.field_index; size_t gen_field_index = struct_const_val->type->data.structure.fields[src_field_index].gen_index; LLVMValueRef uncasted_ptr_val = gen_const_ptr_struct_recursive(g, struct_const_val, gen_field_index); - LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); const_val->global_refs->llvm_value = ptr_val; return ptr_val; } @@ -5997,12 +6011,12 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con if (!type_has_bits(err_union_const_val->type)) { // make this a null pointer ZigType *usize = g->builtin_types.entry_usize; - const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), - const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_code_recursive(g, err_union_const_val); - LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); const_val->global_refs->llvm_value = ptr_val; return ptr_val; } @@ -6011,15 +6025,15 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con assert(const_val->global_refs != nullptr); ConstExprValue *err_union_const_val = const_val->data.x_ptr.data.base_err_union_payload.err_union_val; assert(err_union_const_val->type->id == ZigTypeIdErrorUnion); - if (err_union_const_val->type->zero_bits) { + if (!type_has_bits(err_union_const_val->type)) { // make this a null pointer ZigType *usize = g->builtin_types.entry_usize; - const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), - const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } LLVMValueRef uncasted_ptr_val = gen_const_ptr_err_union_payload_recursive(g, err_union_const_val); - LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); const_val->global_refs->llvm_value = ptr_val; return ptr_val; } @@ -6028,15 +6042,15 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con assert(const_val->global_refs != nullptr); ConstExprValue *optional_const_val = const_val->data.x_ptr.data.base_optional_payload.optional_val; assert(optional_const_val->type->id == ZigTypeIdOptional); - if (optional_const_val->type->zero_bits) { + if (!type_has_bits(optional_const_val->type)) { // make this a null pointer ZigType *usize = g->builtin_types.entry_usize; - const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->type_ref), - const_val->type->type_ref); + const_val->global_refs->llvm_value = LLVMConstIntToPtr(LLVMConstNull(usize->llvm_type), + get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } LLVMValueRef uncasted_ptr_val = gen_const_ptr_optional_payload_recursive(g, optional_const_val); - LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, const_val->type->type_ref); + LLVMValueRef ptr_val = LLVMConstBitCast(uncasted_ptr_val, get_llvm_type(g, const_val->type)); const_val->global_refs->llvm_value = ptr_val; return ptr_val; } @@ -6046,50 +6060,51 @@ static LLVMValueRef gen_const_val_ptr(CodeGen *g, ConstExprValue *const_val, con uint64_t addr_value = const_val->data.x_ptr.data.hard_coded_addr.addr; ZigType *usize = g->builtin_types.entry_usize; const_val->global_refs->llvm_value = LLVMConstIntToPtr( - LLVMConstInt(usize->type_ref, addr_value, false), const_val->type->type_ref); + LLVMConstInt(usize->llvm_type, addr_value, false), get_llvm_type(g, const_val->type)); return const_val->global_refs->llvm_value; } case ConstPtrSpecialFunction: - return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), const_val->type->type_ref); + return LLVMConstBitCast(fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry), + get_llvm_type(g, const_val->type)); case ConstPtrSpecialNull: - return LLVMConstNull(const_val->type->type_ref); + return LLVMConstNull(get_llvm_type(g, const_val->type)); } zig_unreachable(); } static LLVMValueRef gen_const_val_err_set(CodeGen *g, ConstExprValue *const_val, const char *name) { uint64_t value = (const_val->data.x_err_set == nullptr) ? 0 : const_val->data.x_err_set->value; - return LLVMConstInt(g->builtin_types.entry_global_error_set->type_ref, value, false); + return LLVMConstInt(get_llvm_type(g, g->builtin_types.entry_global_error_set), value, false); } static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const char *name) { Error err; ZigType *type_entry = const_val->type; - assert(!type_entry->zero_bits); + assert(type_has_bits(type_entry)); switch (const_val->special) { case ConstValSpecialRuntime: zig_unreachable(); case ConstValSpecialUndef: - return LLVMGetUndef(type_entry->type_ref); + return LLVMGetUndef(get_llvm_type(g, type_entry)); case ConstValSpecialStatic: break; } switch (type_entry->id) { case ZigTypeIdInt: - return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_bigint); + return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_bigint); case ZigTypeIdErrorSet: return gen_const_val_err_set(g, const_val, name); case ZigTypeIdFloat: switch (type_entry->data.floating.bit_count) { case 16: - return LLVMConstReal(type_entry->type_ref, zig_f16_to_double(const_val->data.x_f16)); + return LLVMConstReal(get_llvm_type(g, type_entry), zig_f16_to_double(const_val->data.x_f16)); case 32: - return LLVMConstReal(type_entry->type_ref, const_val->data.x_f32); + return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f32); case 64: - return LLVMConstReal(type_entry->type_ref, const_val->data.x_f64); + return LLVMConstReal(get_llvm_type(g, type_entry), const_val->data.x_f64); case 128: { // TODO make sure this is correct on big endian targets too @@ -6097,7 +6112,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c memcpy(buf, &const_val->data.x_f128, 16); LLVMValueRef as_int = LLVMConstIntOfArbitraryPrecision(LLVMInt128Type(), 2, (uint64_t*)buf); - return LLVMConstBitCast(as_int, type_entry->type_ref); + return LLVMConstBitCast(as_int, get_llvm_type(g, type_entry)); } default: zig_unreachable(); @@ -6125,9 +6140,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c child_val = gen_const_val(g, const_val->data.x_optional, ""); maybe_val = LLVMConstAllOnes(LLVMInt1Type()); - make_unnamed_struct = is_llvm_value_unnamed_type(const_val->type, child_val); + make_unnamed_struct = is_llvm_value_unnamed_type(g, const_val->type, child_val); } else { - child_val = LLVMGetUndef(child_type->type_ref); + child_val = LLVMGetUndef(get_llvm_type(g, child_type)); maybe_val = LLVMConstNull(LLVMInt1Type()); make_unnamed_struct = false; @@ -6139,7 +6154,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c if (make_unnamed_struct) { return LLVMConstStruct(fields, 2, false); } else { - return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2); } } } @@ -6168,10 +6183,10 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c ConstExprValue *field_val = &const_val->data.x_struct.fields[src_field_index]; LLVMValueRef val = gen_const_val(g, field_val, ""); fields[type_struct_field->gen_index] = val; - make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); } else { bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type - LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(type_entry->type_ref, + LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(get_llvm_type(g, type_entry), (unsigned)type_struct_field->gen_index); LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false); size_t used_bits = 0; @@ -6216,14 +6231,14 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c LLVMValueRef val = gen_const_val(g, field_val, ""); fields[type_struct_field->gen_index] = val; - make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(field_val->type, val); + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val); } } if (make_unnamed_struct) { return LLVMConstStruct(fields, type_entry->data.structure.gen_field_count, type_entry->data.structure.layout == ContainerLayoutPacked); } else { - return LLVMConstNamedStruct(type_entry->type_ref, fields, type_entry->data.structure.gen_field_count); + return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, type_entry->data.structure.gen_field_count); } } case ZigTypeIdArray: @@ -6231,16 +6246,16 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c uint64_t len = type_entry->data.array.len; switch (const_val->data.x_array.special) { case ConstArraySpecialUndef: - return LLVMGetUndef(type_entry->type_ref); + return LLVMGetUndef(get_llvm_type(g, type_entry)); case ConstArraySpecialNone: { LLVMValueRef *values = allocate(len); - LLVMTypeRef element_type_ref = type_entry->data.array.child_type->type_ref; + LLVMTypeRef element_type_ref = get_llvm_type(g, type_entry->data.array.child_type); bool make_unnamed_struct = false; for (uint64_t i = 0; i < len; i += 1) { ConstExprValue *elem_value = &const_val->data.x_array.data.s_none.elements[i]; LLVMValueRef val = gen_const_val(g, elem_value, ""); values[i] = val; - make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(elem_value->type, val); + make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, elem_value->type, val); } if (make_unnamed_struct) { return LLVMConstStruct(values, len, true); @@ -6259,7 +6274,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c uint32_t len = type_entry->data.vector.len; switch (const_val->data.x_array.special) { case ConstArraySpecialUndef: - return LLVMGetUndef(type_entry->type_ref); + return LLVMGetUndef(get_llvm_type(g, type_entry)); case ConstArraySpecialNone: { LLVMValueRef *values = allocate(len); for (uint64_t i = 0; i < len; i += 1) { @@ -6273,7 +6288,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c assert(buf_len(buf) == len); LLVMValueRef *values = allocate(len); for (uint64_t i = 0; i < len; i += 1) { - values[i] = LLVMConstInt(g->builtin_types.entry_u8->type_ref, buf_ptr(buf)[i], false); + values[i] = LLVMConstInt(g->builtin_types.entry_u8->llvm_type, buf_ptr(buf)[i], false); } return LLVMConstVector(values, len); } @@ -6282,31 +6297,36 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c } case ZigTypeIdUnion: { - LLVMTypeRef union_type_ref = type_entry->data.unionation.union_type_ref; + // Force type_entry->data.unionation.union_llvm_type to get resolved + (void)get_llvm_type(g, type_entry); if (type_entry->data.unionation.gen_field_count == 0) { if (type_entry->data.unionation.tag_type == nullptr) { return nullptr; } else { - return bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, + return bigint_to_llvm_const(get_llvm_type(g, type_entry->data.unionation.tag_type), &const_val->data.x_union.tag); } } + LLVMTypeRef union_type_ref = type_entry->data.unionation.union_llvm_type; + assert(union_type_ref != nullptr); + LLVMValueRef union_value_ref; bool make_unnamed_struct; ConstExprValue *payload_value = const_val->data.x_union.payload; if (payload_value == nullptr || !type_has_bits(payload_value->type)) { if (type_entry->data.unionation.gen_tag_index == SIZE_MAX) - return LLVMGetUndef(type_entry->type_ref); + return LLVMGetUndef(get_llvm_type(g, type_entry)); union_value_ref = LLVMGetUndef(union_type_ref); make_unnamed_struct = false; } else { - uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, payload_value->type->type_ref); - uint64_t pad_bytes = type_entry->data.unionation.union_size_bytes - field_type_bytes; + uint64_t field_type_bytes = LLVMStoreSizeOfType(g->target_data_ref, + get_llvm_type(g, payload_value->type)); + uint64_t pad_bytes = type_entry->data.unionation.union_abi_size - field_type_bytes; LLVMValueRef correctly_typed_value = gen_const_val(g, payload_value, ""); - make_unnamed_struct = is_llvm_value_unnamed_type(payload_value->type, correctly_typed_value) || + make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_value->type, correctly_typed_value) || payload_value->type != type_entry->data.unionation.most_aligned_union_member; { @@ -6329,7 +6349,8 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c } } - LLVMValueRef tag_value = bigint_to_llvm_const(type_entry->data.unionation.tag_type->type_ref, + LLVMValueRef tag_value = bigint_to_llvm_const( + get_llvm_type(g, type_entry->data.unionation.tag_type), &const_val->data.x_union.tag); LLVMValueRef fields[3]; @@ -6341,7 +6362,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1); uint64_t end_offset = last_field_offset + LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1])); - uint64_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref); + uint64_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, get_llvm_type(g, type_entry)); unsigned pad_sz = expected_sz - end_offset; if (pad_sz != 0) { fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz)); @@ -6351,21 +6372,21 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c assert(actual_sz == expected_sz); return result; } else { - return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2); } } case ZigTypeIdEnum: - return bigint_to_llvm_const(type_entry->type_ref, &const_val->data.x_enum_tag); + return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_enum_tag); case ZigTypeIdFn: if (const_val->data.x_ptr.special == ConstPtrSpecialFunction) { assert(const_val->data.x_ptr.mut == ConstPtrMutComptimeConst); return fn_llvm_value(g, const_val->data.x_ptr.data.fn.fn_entry); } else if (const_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) { - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; uint64_t addr = const_val->data.x_ptr.data.hard_coded_addr.addr; - return LLVMConstIntToPtr(LLVMConstInt(usize_type_ref, addr, false), type_entry->type_ref); + return LLVMConstIntToPtr(LLVMConstInt(usize_type_ref, addr, false), get_llvm_type(g, type_entry)); } else { zig_unreachable(); } @@ -6379,7 +6400,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c assert(type_has_bits(err_set_type)); ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; uint64_t value = (err_set == nullptr) ? 0 : err_set->value; - return LLVMConstInt(g->err_tag_type->type_ref, value, false); + return LLVMConstInt(get_llvm_type(g, g->err_tag_type), value, false); } else if (!type_has_bits(err_set_type)) { assert(type_has_bits(payload_type)); return gen_const_val(g, const_val->data.x_err_union.payload, ""); @@ -6389,17 +6410,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c bool make_unnamed_struct; ErrorTableEntry *err_set = const_val->data.x_err_union.error_set->data.x_err_set; if (err_set != nullptr) { - err_tag_value = LLVMConstInt(g->err_tag_type->type_ref, err_set->value, false); - err_payload_value = LLVMConstNull(payload_type->type_ref); + err_tag_value = LLVMConstInt(get_llvm_type(g, g->err_tag_type), err_set->value, false); + err_payload_value = LLVMConstNull(get_llvm_type(g, payload_type)); make_unnamed_struct = false; } else { - err_tag_value = LLVMConstNull(g->err_tag_type->type_ref); + err_tag_value = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); ConstExprValue *payload_val = const_val->data.x_err_union.payload; err_payload_value = gen_const_val(g, payload_val, ""); - make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value); + make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_val->type, err_payload_value); } if (make_unnamed_struct) { - uint64_t payload_off = LLVMOffsetOfElement(g->target_data_ref, type_entry->type_ref, 1); + uint64_t payload_off = LLVMOffsetOfElement(g->target_data_ref, get_llvm_type(g, type_entry), 1); uint64_t err_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(err_tag_value)); unsigned pad_sz = payload_off - err_sz; if (pad_sz == 0) { @@ -6421,7 +6442,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c err_tag_value, err_payload_value, }; - return LLVMConstNamedStruct(type_entry->type_ref, fields, 2); + return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2); } } } @@ -6460,7 +6481,8 @@ static void render_const_val_global(CodeGen *g, ConstExprValue *const_val, const const_val->global_refs = allocate(1); if (!const_val->global_refs->llvm_global) { - LLVMTypeRef type_ref = const_val->global_refs->llvm_value ? LLVMTypeOf(const_val->global_refs->llvm_value) : const_val->type->type_ref; + LLVMTypeRef type_ref = const_val->global_refs->llvm_value ? + LLVMTypeOf(const_val->global_refs->llvm_value) : get_llvm_type(g, const_val->type); LLVMValueRef global_value = LLVMAddGlobal(g->module, type_ref, name); LLVMSetLinkage(global_value, LLVMInternalLinkage); LLVMSetGlobalConstant(global_value, true); @@ -6486,7 +6508,7 @@ static void generate_error_name_table(CodeGen *g) { ZigType *str_type = get_slice_type(g, u8_ptr_type); LLVMValueRef *values = allocate(g->errors_by_index.length); - values[0] = LLVMGetUndef(str_type->type_ref); + values[0] = LLVMGetUndef(get_llvm_type(g, str_type)); for (size_t i = 1; i < g->errors_by_index.length; i += 1) { ErrorTableEntry *err_entry = g->errors_by_index.at(i); Buf *name = &err_entry->name; @@ -6502,13 +6524,13 @@ static void generate_error_name_table(CodeGen *g) { LLVMSetAlignment(str_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(str_init))); LLVMValueRef fields[] = { - LLVMConstBitCast(str_global, u8_ptr_type->type_ref), - LLVMConstInt(g->builtin_types.entry_usize->type_ref, buf_len(name), false), + LLVMConstBitCast(str_global, get_llvm_type(g, u8_ptr_type)), + LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false), }; - values[i] = LLVMConstNamedStruct(str_type->type_ref, fields, 2); + values[i] = LLVMConstNamedStruct(get_llvm_type(g, str_type), fields, 2); } - LLVMValueRef err_name_table_init = LLVMConstArray(str_type->type_ref, values, (unsigned)g->errors_by_index.length); + LLVMValueRef err_name_table_init = LLVMConstArray(get_llvm_type(g, str_type), values, (unsigned)g->errors_by_index.length); g->err_name_table = LLVMAddGlobal(g->module, LLVMTypeOf(err_name_table_init), buf_ptr(get_mangled_name(g, buf_create_from_str("__zig_err_name_table"), false))); @@ -6547,7 +6569,7 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, ZigLLVMCreateGlobalVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), - type_entry->di_type, is_local_to_unit); + get_llvm_di_type(g, type_entry), is_local_to_unit); // TODO ^^ make an actual global variable } @@ -6588,28 +6610,6 @@ static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) { static void do_code_gen(CodeGen *g) { assert(!g->errors.length); - { - // create debug type for error sets - assert(g->err_enumerators.length == g->errors_by_index.length); - uint64_t tag_debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, g->err_tag_type->type_ref); - uint64_t tag_debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, g->err_tag_type->type_ref); - ZigLLVMDIFile *err_set_di_file = nullptr; - ZigLLVMDIType *err_set_di_type = ZigLLVMCreateDebugEnumerationType(g->dbuilder, - ZigLLVMCompileUnitToScope(g->compile_unit), buf_ptr(&g->builtin_types.entry_global_error_set->name), - err_set_di_file, 0, - tag_debug_size_in_bits, - tag_debug_align_in_bits, - g->err_enumerators.items, g->err_enumerators.length, - g->err_tag_type->di_type, ""); - ZigLLVMReplaceTemporary(g->dbuilder, g->builtin_types.entry_global_error_set->di_type, err_set_di_type); - g->builtin_types.entry_global_error_set->di_type = err_set_di_type; - - for (size_t i = 0; i < g->error_di_types.length; i += 1) { - ZigLLVMDIType **di_type_ptr = g->error_di_types.at(i); - *di_type_ptr = err_set_di_type; - } - } - generate_error_name_table(g); // Generate module level variables @@ -6646,7 +6646,7 @@ static void do_code_gen(CodeGen *g) { bits_needed = 8; } ZigType *var_type = get_int_type(g, const_val->data.x_bigint.is_negative, bits_needed); - LLVMValueRef init_val = bigint_to_llvm_const(var_type->type_ref, &const_val->data.x_bigint); + LLVMValueRef init_val = bigint_to_llvm_const(get_llvm_type(g, var_type), &const_val->data.x_bigint); gen_global_var(g, var, init_val, var_type); continue; } @@ -6660,9 +6660,10 @@ static void do_code_gen(CodeGen *g) { if (var->linkage == VarLinkageExternal) { LLVMValueRef existing_llvm_var = LLVMGetNamedGlobal(g->module, buf_ptr(&var->name)); if (existing_llvm_var) { - global_value = LLVMConstBitCast(existing_llvm_var, LLVMPointerType(var->var_type->type_ref, 0)); + global_value = LLVMConstBitCast(existing_llvm_var, + LLVMPointerType(get_llvm_type(g, var->var_type), 0)); } else { - global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name)); + global_value = LLVMAddGlobal(g->module, get_llvm_type(g, var->var_type), buf_ptr(&var->name)); // TODO debug info for the extern variable LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage)); @@ -6736,6 +6737,9 @@ static void do_code_gen(CodeGen *g) { if (have_err_ret_trace_stack) { ZigType *array_type = get_array_type(g, g->builtin_types.entry_usize, stack_trace_ptr_count); err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", get_abi_alignment(g, array_type)); + + // populate g->stack_trace_type + (void)get_ptr_to_stack_trace_type(g); g->cur_err_ret_trace_val_stack = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type)); } else { g->cur_err_ret_trace_val_stack = nullptr; @@ -6834,15 +6838,15 @@ static void do_code_gen(CodeGen *g) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), buf_ptr(&var->name), import->data.structure.root_struct->di_file, (unsigned)(var->decl_node->line + 1), - var->var_type->di_type, !g->strip_debug_symbols, 0); + get_llvm_di_type(g, var->var_type), !g->strip_debug_symbols, 0); } else if (is_c_abi) { fn_walk_var.data.vars.var = var; iter_function_params_c_abi(g, fn_table_entry->type_entry, &fn_walk_var, var->src_arg_index); } else { - assert(var->gen_arg_index != SIZE_MAX); ZigType *gen_type; FnGenParamInfo *gen_info = &fn_table_entry->type_entry->data.fn.gen_param_info[var->src_arg_index]; + assert(gen_info->gen_index != SIZE_MAX); if (handle_is_ptr(var->var_type)) { if (gen_info->is_byval) { @@ -6850,16 +6854,16 @@ static void do_code_gen(CodeGen *g) { } else { gen_type = gen_info->type; } - var->value_ref = LLVMGetParam(fn, (unsigned)var->gen_arg_index); + var->value_ref = LLVMGetParam(fn, gen_info->gen_index); } else { gen_type = var->var_type; var->value_ref = build_alloca(g, var->var_type, buf_ptr(&var->name), var->align_bytes); } if (var->decl_node) { var->di_loc_var = ZigLLVMCreateParameterVariable(g->dbuilder, get_di_scope(g, var->parent_scope), - buf_ptr(&var->name), import->data.structure.root_struct->di_file, - (unsigned)(var->decl_node->line + 1), - gen_type->di_type, !g->strip_debug_symbols, 0, (unsigned)(var->gen_arg_index + 1)); + buf_ptr(&var->name), import->data.structure.root_struct->di_file, + (unsigned)(var->decl_node->line + 1), + get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index+1)); } } @@ -6870,7 +6874,7 @@ static void do_code_gen(CodeGen *g) { ZigType *usize = g->builtin_types.entry_usize; size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); - gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false); + gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false); size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); @@ -6878,7 +6882,7 @@ static void do_code_gen(CodeGen *g) { ZigType *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); - LLVMValueRef zero = LLVMConstNull(usize->type_ref); + LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP(g->builder, err_ret_array_val, indices, 2, ""); @@ -6887,7 +6891,7 @@ static void do_code_gen(CodeGen *g) { size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); - gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); + gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } // create debug variable declarations for parameters @@ -6997,50 +7001,60 @@ static const GlobalLinkageValue global_linkage_values[] = { {GlobalLinkageIdLinkOnce, "LinkOnce"}, }; +static void add_fp_entry(CodeGen *g, const char *name, uint32_t bit_count, LLVMTypeRef type_ref, + ZigType **field) +{ + ZigType *entry = new_type_table_entry(ZigTypeIdFloat); + entry->llvm_type = type_ref; + entry->size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); + buf_init_from_str(&entry->name, name); + entry->data.floating.bit_count = bit_count; + + entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + entry->size_in_bits, ZigLLVMEncoding_DW_ATE_float()); + *field = entry; + g->primitive_type_table.put(&entry->name, entry); +} + static void define_builtin_types(CodeGen *g) { { // if this type is anywhere in the AST, we should never hit codegen. ZigType *entry = new_type_table_entry(ZigTypeIdInvalid); buf_init_from_str(&entry->name, "(invalid)"); - entry->zero_bits = true; g->builtin_types.entry_invalid = entry; } { ZigType *entry = new_type_table_entry(ZigTypeIdComptimeFloat); buf_init_from_str(&entry->name, "comptime_float"); - entry->zero_bits = true; g->builtin_types.entry_num_lit_float = entry; g->primitive_type_table.put(&entry->name, entry); } { ZigType *entry = new_type_table_entry(ZigTypeIdComptimeInt); buf_init_from_str(&entry->name, "comptime_int"); - entry->zero_bits = true; g->builtin_types.entry_num_lit_int = entry; g->primitive_type_table.put(&entry->name, entry); } { ZigType *entry = new_type_table_entry(ZigTypeIdEnumLiteral); buf_init_from_str(&entry->name, "(enum literal)"); - entry->zero_bits = true; g->builtin_types.entry_enum_literal = entry; } { ZigType *entry = new_type_table_entry(ZigTypeIdUndefined); buf_init_from_str(&entry->name, "(undefined)"); - entry->zero_bits = true; g->builtin_types.entry_undef = entry; } { ZigType *entry = new_type_table_entry(ZigTypeIdNull); buf_init_from_str(&entry->name, "(null)"); - entry->zero_bits = true; g->builtin_types.entry_null = entry; } { ZigType *entry = new_type_table_entry(ZigTypeIdArgTuple); buf_init_from_str(&entry->name, "(args)"); - entry->zero_bits = true; g->builtin_types.entry_arg_tuple = entry; } @@ -7050,14 +7064,15 @@ static void define_builtin_types(CodeGen *g) { bool is_signed = info->is_signed; ZigType *entry = new_type_table_entry(ZigTypeIdInt); - entry->type_ref = LLVMIntType(size_in_bits); + entry->llvm_type = LLVMIntType(size_in_bits); + entry->size_in_bits = size_in_bits; + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); buf_init_from_str(&entry->name, info->name); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), - debug_size_in_bits, - is_signed ? ZigLLVMEncoding_DW_ATE_signed() : ZigLLVMEncoding_DW_ATE_unsigned()); + entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + size_in_bits, is_signed ? ZigLLVMEncoding_DW_ATE_signed() : ZigLLVMEncoding_DW_ATE_unsigned()); entry->data.integral.is_signed = is_signed; entry->data.integral.bit_count = size_in_bits; g->primitive_type_table.put(&entry->name, entry); @@ -7067,12 +7082,13 @@ static void define_builtin_types(CodeGen *g) { { ZigType *entry = new_type_table_entry(ZigTypeIdBool); - entry->type_ref = LLVMInt1Type(); + entry->llvm_type = LLVMInt1Type(); + entry->size_in_bits = 1; + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); buf_init_from_str(&entry->name, "bool"); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), - debug_size_in_bits, - ZigLLVMEncoding_DW_ATE_boolean()); + entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + entry->size_in_bits, ZigLLVMEncoding_DW_ATE_boolean()); g->builtin_types.entry_bool = entry; g->primitive_type_table.put(&entry->name, entry); } @@ -7081,7 +7097,10 @@ static void define_builtin_types(CodeGen *g) { bool is_signed = is_signed_list[sign_i]; ZigType *entry = new_type_table_entry(ZigTypeIdInt); - entry->type_ref = LLVMIntType(g->pointer_size_bytes * 8); + entry->llvm_type = LLVMIntType(g->pointer_size_bytes * 8); + entry->size_in_bits = g->pointer_size_bytes * 8; + entry->abi_size = LLVMABISizeOfType(g->target_data_ref, entry->llvm_type); + entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type); const char u_or_i = is_signed ? 'i' : 'u'; buf_resize(&entry->name, 0); @@ -7090,9 +7109,8 @@ static void define_builtin_types(CodeGen *g) { entry->data.integral.is_signed = is_signed; entry->data.integral.bit_count = g->pointer_size_bytes * 8; - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), - debug_size_in_bits, + entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + entry->size_in_bits, is_signed ? ZigLLVMEncoding_DW_ATE_signed() : ZigLLVMEncoding_DW_ATE_unsigned()); g->primitive_type_table.put(&entry->name, entry); @@ -7103,23 +7121,6 @@ static void define_builtin_types(CodeGen *g) { } } - auto add_fp_entry = [] (CodeGen *g, - const char *name, - uint32_t bit_count, - LLVMTypeRef type_ref, - ZigType **field) { - ZigType *entry = new_type_table_entry(ZigTypeIdFloat); - entry->type_ref = type_ref; - buf_init_from_str(&entry->name, name); - entry->data.floating.bit_count = bit_count; - - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, entry->type_ref); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), - debug_size_in_bits, - ZigLLVMEncoding_DW_ATE_float()); - *field = entry; - g->primitive_type_table.put(&entry->name, entry); - }; add_fp_entry(g, "f16", 16, LLVMHalfType(), &g->builtin_types.entry_f16); add_fp_entry(g, "f32", 32, LLVMFloatType(), &g->builtin_types.entry_f32); add_fp_entry(g, "f64", 64, LLVMDoubleType(), &g->builtin_types.entry_f64); @@ -7128,10 +7129,9 @@ static void define_builtin_types(CodeGen *g) { { ZigType *entry = new_type_table_entry(ZigTypeIdVoid); - entry->type_ref = LLVMVoidType(); - entry->zero_bits = true; + entry->llvm_type = LLVMVoidType(); buf_init_from_str(&entry->name, "void"); - entry->di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), + entry->llvm_di_type = ZigLLVMCreateDebugBasicType(g->dbuilder, buf_ptr(&entry->name), 0, ZigLLVMEncoding_DW_ATE_unsigned()); g->builtin_types.entry_void = entry; @@ -7139,17 +7139,15 @@ static void define_builtin_types(CodeGen *g) { } { ZigType *entry = new_type_table_entry(ZigTypeIdUnreachable); - entry->type_ref = LLVMVoidType(); - entry->zero_bits = true; + entry->llvm_type = LLVMVoidType(); buf_init_from_str(&entry->name, "noreturn"); - entry->di_type = g->builtin_types.entry_void->di_type; + entry->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; g->builtin_types.entry_unreachable = entry; g->primitive_type_table.put(&entry->name, entry); } { ZigType *entry = new_type_table_entry(ZigTypeIdMetaType); buf_init_from_str(&entry->name, "type"); - entry->zero_bits = true; g->builtin_types.entry_type = entry; g->primitive_type_table.put(&entry->name, entry); } @@ -7174,19 +7172,15 @@ static void define_builtin_types(CodeGen *g) { buf_init_from_str(&entry->name, "anyerror"); entry->data.error_set.err_count = UINT32_MAX; - // TODO allow overriding this type and keep track of max value and emit an - // error if there are too many errors declared + // TODO https://github.com/ziglang/zig/issues/786 g->err_tag_type = g->builtin_types.entry_u16; - g->builtin_types.entry_global_error_set = entry; - entry->type_ref = g->err_tag_type->type_ref; + entry->size_in_bits = g->err_tag_type->size_in_bits; + entry->abi_align = g->err_tag_type->abi_align; + entry->abi_size = g->err_tag_type->abi_size; - entry->di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - ZigLLVMTag_DW_enumeration_type(), "anyerror", - ZigLLVMCompileUnitToScope(g->compile_unit), nullptr, 0); + g->builtin_types.entry_global_error_set = entry; - // reserve index 0 to indicate no error - g->err_enumerators.append(ZigLLVMCreateDebugEnumerator(g->dbuilder, "(none)", 0)); g->errors_by_index.append(nullptr); g->primitive_type_table.put(&entry->name, entry); @@ -7194,6 +7188,9 @@ static void define_builtin_types(CodeGen *g) { { ZigType *entry = get_promise_type(g, nullptr); g->primitive_type_table.put(&entry->name, entry); + entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; + entry->abi_align = g->builtin_types.entry_usize->abi_align; + entry->abi_size = g->builtin_types.entry_usize->abi_size; } } @@ -7749,8 +7746,15 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g))); buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); - buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n"); - + if (g->is_test_build) { + buf_appendf(contents, + "const TestFn = struct {\n" + "name: []const u8,\n" + "func: fn()anyerror!void,\n" + "};\n" + "pub const test_functions = {}; // overwritten later\n" + ); + } return contents; } @@ -8157,6 +8161,8 @@ static ZigPackage *create_panic_pkg(CodeGen *g) { } static void create_test_compile_var_and_add_test_runner(CodeGen *g) { + Error err; + assert(g->is_test_build); if (g->test_fns.length == 0) { @@ -8164,14 +8170,13 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { exit(0); } - ZigType *u8_ptr_type = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false, - PtrLenUnknown, get_abi_alignment(g, g->builtin_types.entry_u8), 0, 0, false); - ZigType *str_type = get_slice_type(g, u8_ptr_type); ZigType *fn_type = get_test_fn_type(g); - const char *field_names[] = { "name", "func", }; - ZigType *field_types[] = { str_type, fn_type, }; - ZigType *struct_type = get_struct_type(g, "ZigTestFn", field_names, field_types, 2); + ConstExprValue *test_fn_type_val = get_builtin_value(g, "TestFn"); + assert(test_fn_type_val->type->id == ZigTypeIdMetaType); + ZigType *struct_type = test_fn_type_val->data.x_type; + if ((err = type_resolve(g, struct_type, ResolveStatusSizeKnown))) + zig_unreachable(); ConstExprValue *test_fn_array = create_const_vals(1); test_fn_array->type = get_array_type(g, struct_type, g->test_fns.length); @@ -8203,7 +8208,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) { ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true); - update_compile_var(g, buf_create_from_str("__zig_test_fn_slice"), test_fn_slice); + update_compile_var(g, buf_create_from_str("test_functions"), test_fn_slice); g->test_runner_package = create_test_runner_pkg(g); g->test_runner_import = add_special_code(g, g->test_runner_package, "test_runner.zig"); } diff --git a/src/ir.cpp b/src/ir.cpp index f0387e6ab3ac..ea7a27f31223 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -6842,6 +6842,9 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp assert(set2->id == ZigTypeIdErrorSet); ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); + err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size; buf_resize(&err_set_type->name, 0); buf_appendf(&err_set_type->name, "error{"); @@ -6857,8 +6860,6 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp } } - err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; - err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; err_set_type->data.error_set.err_count = count; err_set_type->data.error_set.errors = allocate(count); @@ -6883,8 +6884,6 @@ static ZigType *get_error_set_union(CodeGen *g, ErrorTableEntry **errors, ZigTyp buf_appendf(&err_set_type->name, "}"); - g->error_di_types.append(&err_set_type->di_type); - return err_set_type; } @@ -6895,13 +6894,12 @@ static ZigType *make_err_set_with_one_item(CodeGen *g, Scope *parent_scope, AstN ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); buf_resize(&err_set_type->name, 0); buf_appendf(&err_set_type->name, "error{%s}", buf_ptr(&err_entry->name)); - err_set_type->type_ref = g->builtin_types.entry_global_error_set->type_ref; - err_set_type->di_type = g->builtin_types.entry_global_error_set->di_type; + err_set_type->size_in_bits = g->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = g->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = g->builtin_types.entry_global_error_set->abi_size; err_set_type->data.error_set.err_count = 1; err_set_type->data.error_set.errors = allocate(1); - g->error_di_types.append(&err_set_type->di_type); - err_set_type->data.error_set.errors[0] = err_entry; return err_set_type; @@ -6917,9 +6915,9 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet); buf_init_from_buf(&err_set_type->name, type_name); err_set_type->data.error_set.err_count = err_count; - err_set_type->type_ref = irb->codegen->builtin_types.entry_global_error_set->type_ref; - err_set_type->di_type = irb->codegen->builtin_types.entry_global_error_set->di_type; - irb->codegen->error_di_types.append(&err_set_type->di_type); + err_set_type->size_in_bits = irb->codegen->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = irb->codegen->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = irb->codegen->builtin_types.entry_global_error_set->abi_size; err_set_type->data.error_set.errors = allocate(err_count); ErrorTableEntry **errors = allocate(irb->codegen->errors_by_index.length + err_count); @@ -6940,8 +6938,6 @@ static IrInstruction *ir_gen_err_set_decl(IrBuilder *irb, Scope *parent_scope, A assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)irb->codegen->err_tag_type->data.integral.bit_count)); err->value = error_value_count; irb->codegen->errors_by_index.append(err); - irb->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(irb->codegen->dbuilder, - buf_ptr(err_name), error_value_count)); } err_set_type->data.error_set.errors[i] = err; @@ -8947,16 +8943,14 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp } free(errors); - err_set_type->type_ref = ira->codegen->builtin_types.entry_global_error_set->type_ref; - err_set_type->di_type = ira->codegen->builtin_types.entry_global_error_set->di_type; err_set_type->data.error_set.err_count = intersection_list.length; err_set_type->data.error_set.errors = intersection_list.items; - err_set_type->zero_bits = intersection_list.length == 0; + err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits; + err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align; + err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size; buf_appendf(&err_set_type->name, "}"); - ira->codegen->error_di_types.append(&err_set_type->di_type); - return err_set_type; } @@ -13968,20 +13962,19 @@ static bool ir_analyze_fn_call_generic_arg(IrAnalyze *ira, AstNode *fn_proto_nod } static ZigVar *get_fn_var_by_index(ZigFn *fn_entry, size_t index) { + FnTypeParamInfo *src_param_info = &fn_entry->type_entry->data.fn.fn_type_id.param_info[index]; + if (!type_has_bits(src_param_info->type)) + return nullptr; + size_t next_var_i = 0; - FnGenParamInfo *gen_param_info = fn_entry->type_entry->data.fn.gen_param_info; - assert(gen_param_info != nullptr); for (size_t param_i = 0; param_i < index; param_i += 1) { - FnGenParamInfo *info = &gen_param_info[param_i]; - if (info->gen_index == SIZE_MAX) + FnTypeParamInfo *src_param_info = &fn_entry->type_entry->data.fn.fn_type_id.param_info[param_i]; + if (!type_has_bits(src_param_info->type)) { continue; + } next_var_i += 1; } - FnGenParamInfo *info = &gen_param_info[index]; - if (info->gen_index == SIZE_MAX) - return nullptr; - return fn_entry->variable_list.at(next_var_i); } @@ -14855,7 +14848,7 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_ ZigType *type_entry = ir_resolve_type(ira, value); if (type_is_invalid(type_entry)) return ira->codegen->invalid_instruction; - if ((err = ensure_complete_type(ira->codegen, type_entry))) + if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; switch (type_entry->id) { @@ -16051,8 +16044,6 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc assert((uint32_t)error_value_count < (((uint32_t)1) << (uint32_t)ira->codegen->err_tag_type->data.integral.bit_count)); err_entry->value = error_value_count; ira->codegen->errors_by_index.append(err_entry); - ira->codegen->err_enumerators.append(ZigLLVMCreateDebugEnumerator(ira->codegen->dbuilder, - buf_ptr(field_name), error_value_count)); ira->codegen->error_table.put(field_name, err_entry); } if (err_entry->set_with_only_this_in_it == nullptr) { @@ -17519,6 +17510,8 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, IrInstructionContainerInitList *instruction) { + Error err; + ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child); if (type_is_invalid(container_type)) return ira->codegen->invalid_instruction; @@ -17547,6 +17540,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira, child_type = pointer_type->data.pointer.child_type; } + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) { + return ira->codegen->invalid_instruction; + } + ZigType *fixed_size_array_type = get_array_type(ira->codegen, child_type, elem_count); ConstExprValue const_val = {}; @@ -17873,7 +17870,7 @@ static TypeStructField *validate_byte_offset(IrAnalyze *ira, return nullptr; } - *byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, container_type->type_ref, field->gen_index); + *byte_offset = field->offset; return field; } @@ -17929,10 +17926,11 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig Error err; ConstExprValue *type_info_var = get_builtin_value(ira->codegen, "TypeInfo"); assert(type_info_var->type->id == ZigTypeIdMetaType); - assertNoError(ensure_complete_type(ira->codegen, type_info_var->data.x_type)); - ZigType *type_info_type = type_info_var->data.x_type; assert(type_info_type->id == ZigTypeIdUnion); + if ((err = type_resolve(ira->codegen, type_info_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } if (type_name == nullptr && root == nullptr) return type_info_type; @@ -17966,7 +17964,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr, { Error err; ZigType *type_info_definition_type = ir_type_info_get_type(ira, "Definition", nullptr); - if ((err = ensure_complete_type(ira->codegen, type_info_definition_type))) + if ((err = type_resolve(ira->codegen, type_info_definition_type, ResolveStatusSizeKnown))) return err; ensure_field_index(type_info_definition_type, "name", 0); @@ -18486,6 +18484,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr ensure_field_index(result->type, "fields", 2); ZigType *type_info_enum_field_type = ir_type_info_get_type(ira, "EnumField", nullptr); + if ((err = type_resolve(ira->codegen, type_info_enum_field_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } uint32_t enum_field_count = type_entry->data.enumeration.src_field_count; ConstExprValue *enum_field_array = create_const_vals(1); @@ -18529,6 +18530,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr result->data.x_optional = nullptr; break; } + if ((err = type_resolve(ira->codegen, type_info_error_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } ConstExprValue *slice_val = create_const_vals(1); result->data.x_optional = slice_val; @@ -18625,6 +18629,8 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr ensure_field_index(result->type, "fields", 2); ZigType *type_info_union_field_type = ir_type_info_get_type(ira, "UnionField", nullptr); + if ((err = type_resolve(ira->codegen, type_info_union_field_type, ResolveStatusSizeKnown))) + zig_unreachable(); uint32_t union_field_count = type_entry->data.unionation.src_field_count; ConstExprValue *union_field_array = create_const_vals(1); @@ -18702,6 +18708,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr ensure_field_index(result->type, "fields", 1); ZigType *type_info_struct_field_type = ir_type_info_get_type(ira, "StructField", nullptr); + if ((err = type_resolve(ira->codegen, type_info_struct_field_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } uint32_t struct_field_count = type_entry->data.structure.src_field_count; ConstExprValue *struct_field_array = create_const_vals(1); @@ -18726,7 +18735,7 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr if (!type_has_bits(struct_field->type_entry)) { inner_fields[1].data.x_optional = nullptr; } else { - size_t byte_offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, type_entry->type_ref, struct_field->gen_index); + size_t byte_offset = struct_field->offset; inner_fields[1].data.x_optional = create_const_vals(1); inner_fields[1].data.x_optional->special = ConstValSpecialStatic; inner_fields[1].data.x_optional->type = ira->codegen->builtin_types.entry_num_lit_int; @@ -18809,6 +18818,9 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr } // args: []TypeInfo.FnArg ZigType *type_info_fn_arg_type = ir_type_info_get_type(ira, "FnArg", nullptr); + if ((err = type_resolve(ira->codegen, type_info_fn_arg_type, ResolveStatusSizeKnown))) { + zig_unreachable(); + } size_t fn_arg_count = type_entry->data.fn.fn_type_id.param_count - (is_varargs && type_entry->data.fn.fn_type_id.cc != CallingConventionC); @@ -21425,12 +21437,11 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue case ContainerLayoutExtern: { size_t src_field_count = val->type->data.structure.src_field_count; for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { - TypeStructField *type_field = &val->type->data.structure.fields[field_i]; - if (type_field->gen_index == SIZE_MAX) + TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + if (struct_field->gen_index == SIZE_MAX) continue; ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; - size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref, - type_field->gen_index); + size_t offset = struct_field->offset; buf_write_value_bytes(codegen, buf + offset, field_val); } return; @@ -21446,10 +21457,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue size_t child_buf_len = 16; uint8_t *child_buf = child_buf_prealloc; while (gen_i < gen_field_count) { - LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref, - (unsigned)gen_i); - size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type); - size_t big_int_byte_count = big_int_bit_count / 8; + size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i]; if (big_int_byte_count > child_buf_len) { child_buf = allocate_nonzero(big_int_byte_count); child_buf_len = big_int_byte_count; @@ -21485,7 +21493,7 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue } src_i += 1; } - bigint_write_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian); + bigint_write_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian); offset += big_int_byte_count; gen_i += 1; } @@ -21606,12 +21614,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; field_val->special = ConstValSpecialStatic; - TypeStructField *type_field = &val->type->data.structure.fields[field_i]; - field_val->type = type_field->type_entry; - if (type_field->gen_index == SIZE_MAX) + TypeStructField *struct_field = &val->type->data.structure.fields[field_i]; + field_val->type = struct_field->type_entry; + if (struct_field->gen_index == SIZE_MAX) continue; - size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref, - type_field->gen_index); + size_t offset = struct_field->offset; uint8_t *new_buf = buf + offset; if ((err = buf_read_value_bytes(ira, codegen, source_node, new_buf, field_val))) return err; @@ -21630,16 +21637,13 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou size_t child_buf_len = 16; uint8_t *child_buf = child_buf_prealloc; while (gen_i < gen_field_count) { - LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref, - (unsigned)gen_i); - size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type); - size_t big_int_byte_count = big_int_bit_count / 8; + size_t big_int_byte_count = val->type->data.structure.host_int_bytes[gen_i]; if (big_int_byte_count > child_buf_len) { child_buf = allocate_nonzero(big_int_byte_count); child_buf_len = big_int_byte_count; } BigInt big_int; - bigint_read_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian, false); + bigint_read_twos_complement(&big_int, buf + offset, big_int_byte_count * 8, is_big_endian, false); while (src_i < src_field_count) { TypeStructField *field = &val->type->data.structure.fields[src_i]; assert(field->gen_index != SIZE_MAX); @@ -21662,7 +21666,7 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou big_int = tmp; } - bigint_write_twos_complement(&child_val, child_buf, big_int_bit_count, is_big_endian); + bigint_write_twos_complement(&child_val, child_buf, big_int_byte_count * 8, is_big_endian); if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) { return err; } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 93c34f0385ba..7d45871b2aa0 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -548,6 +548,7 @@ ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilde ZigLLVMDIType *type, bool always_preserve, unsigned flags, unsigned arg_no) { assert(flags == 0); + assert(arg_no != 0); DILocalVariable *result = reinterpret_cast(dbuilder)->createParameterVariable( reinterpret_cast(scope), name, diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index 857739e82d29..36b098bd613d 100644 --- a/std/special/test_runner.zig +++ b/std/special/test_runner.zig @@ -1,7 +1,7 @@ const std = @import("std"); const io = std.io; const builtin = @import("builtin"); -const test_fn_list = builtin.__zig_test_fn_slice; +const test_fn_list = builtin.test_functions; const warn = std.debug.warn; pub fn main() !void { diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index aa7789260215..62fb41ca28c6 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -256,8 +256,8 @@ const Foo96Bits = packed struct { test "packed struct 24bits" { comptime { - expect(@sizeOf(Foo24Bits) == 3); - expect(@sizeOf(Foo96Bits) == 12); + expect(@sizeOf(Foo24Bits) == 4); + expect(@sizeOf(Foo96Bits) == 16); } var value = Foo96Bits{ @@ -291,16 +291,22 @@ test "packed struct 24bits" { expect(value.d == 1); } +const Foo32Bits = packed struct { + field: u24, + pad: u8, +}; + const FooArray24Bits = packed struct { a: u16, - b: [2]Foo24Bits, + b: [2]Foo32Bits, c: u16, }; +// TODO revisit this test when doing https://github.com/ziglang/zig/issues/1512 test "packed array 24bits" { comptime { - expect(@sizeOf([9]Foo24Bits) == 9 * 3); - expect(@sizeOf(FooArray24Bits) == 2 + 2 * 3 + 2); + expect(@sizeOf([9]Foo32Bits) == 9 * 4); + expect(@sizeOf(FooArray24Bits) == 2 + 2 * 4 + 2); } var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);