From ee5064c053526e9e6a0a94d835cd334eea2e5823 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 29 Mar 2019 18:32:16 -0400 Subject: decouple llvm types from zig types Not tested yet, but it builds. This closes #761, and lays the groundwork for fixing the remaining false positive "foo depends on itself" bugs, such as #624. It also lays the groundwork for implementing ability to specify alignment of fields (#1512). --- src/analyze.cpp | 2526 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 1307 insertions(+), 1219 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 1e0ddd8451..e17f9eaa66 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -26,6 +26,7 @@ static Error ATTRIBUTE_MUST_USE resolve_struct_zero_bits(CodeGen *g, ZigType *st 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 bool is_top_level_struct(ZigType *import) { @@ -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: @@ -278,20 +281,6 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) { 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; - } - zig_unreachable(); case ZigTypeIdOpaque: return status < ResolveStatusSizeKnown; case ZigTypeIdMetaType: @@ -325,49 +314,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 +343,14 @@ 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->pointer_size_bytes; + entry->size_in_bits = g->pointer_size_bytes * 8; 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 +452,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 +521,61 @@ 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; + if (child_type->optional_parent != nullptr) { + return child_type->optional_parent; + } + + assert(type_is_resolved(child_type, ResolveStatusSizeKnown)); + + ZigType *entry = new_type_table_entry(ZigTypeIdOptional); + + 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 { - 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, ""); - - ZigLLVMReplaceTemporary(g->dbuilder, entry->di_type, replacement_di_type); - entry->di_type = replacement_di_type; - } - - entry->data.maybe.child_type = child_type; - - child_type->optional_parent = entry; - return entry; + // 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 field_align) { + BREAKPOINT; // TODO test this + // 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, 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 +593,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 +603,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[0]); + entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], field_aligns[1]); + entry->size_in_bits = entry->abi_size * 8; } g->type_table.put(type_id, entry); @@ -772,31 +639,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 +660,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 +688,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 +699,11 @@ 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)) { + 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 +713,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 +743,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 +768,9 @@ 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; + bound_fn_type->abi_size = 0; + bound_fn_type->size_in_bits = 0; + bound_fn_type->abi_align = 0; buf_resize(&bound_fn_type->name, 0); buf_appendf(&bound_fn_type->name, "(bound %s)", buf_ptr(&fn_type->name)); @@ -1114,8 +866,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 +883,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 +894,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), ""); - } + 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 = (fn_type_id->alignment == 0) ? + g->builtin_types.entry_usize->abi_align : fn_type_id->alignment; g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); @@ -1282,14 +925,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 +951,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 +1000,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; } @@ -1611,14 +1238,10 @@ 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); - return err_set_type; } @@ -1858,10 +1481,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; } @@ -1870,181 +1493,66 @@ bool type_is_invalid(ZigType *type_entry) { static Error resolve_enum_type(CodeGen *g, ZigType *enum_type) { - assert(enum_type->id == ZigTypeIdEnum); + return resolve_enum_zero_bits(g, enum_type); +} - if (enum_type->data.enumeration.is_invalid) - return ErrorSemanticAnalyzeFail; - if (enum_type->data.enumeration.complete) - return ErrorNone; +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); - Error err; - if ((err = resolve_enum_zero_bits(g, enum_type))) - return err; + buf_init_from_str(&struct_type->name, type_name); - AstNode *decl_node = enum_type->data.enumeration.decl_node; + 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); - 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); + 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 (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]; + field->offset = next_offset; + next_offset = next_field_offset(next_offset, abi_align, + field->type_entry->abi_size, field->type_entry->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); + return struct_type; +} - Scope *scope = &enum_type->data.enumeration.decls_scope->base; - ZigType *import = get_scope_import(scope); +static size_t get_store_size_in_bits(size_t size_in_bits) { + return (size_in_bits + 7) / 8; +} - // 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; -} - - -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); - - return struct_type; -} - -static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { - assert(struct_type->id == ZigTypeIdStruct); +static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { + assert(struct_type->id == ZigTypeIdStruct); Error err; @@ -2068,454 +1576,284 @@ 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); + bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); + struct_type->data.structure.resolve_loop_flag = true; - Scope *scope = &struct_type->data.structure.decls_scope->base; + uint32_t *host_int_bytes = allocate(struct_type->data.structure.gen_field_count); - size_t gen_field_index = 0; - bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); + // Compute offsets for all the fields. size_t packed_bits_offset = 0; + size_t next_offset = 0; size_t first_packed_bits_offset_misalign = SIZE_MAX; - size_t debug_field_count = 0; + size_t gen_field_index = 0; + size_t size_in_bits = 0; + size_t abi_align = struct_type->abi_align; 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 ((err = ensure_complete_type(g, field_type))) { + if (!type_has_bits(field_type)) + continue; + + if ((err = type_resolve(g, field_type, 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; - } + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { + return ErrorSemanticAnalyzeFail; } - if (!type_has_bits(field_type)) - continue; - type_struct_field->gen_index = gen_field_index; + type_struct_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; 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) { + if (get_store_size_in_bits(full_bit_count) == full_bit_count) { // next field recovers store alignment - element_types[gen_field_index] = int_type_ref; + host_int_bytes[gen_field_index] = full_bit_count / 8; gen_field_index += 1; + // TODO: https://github.com/ziglang/zig/issues/1512 + next_offset = next_field_offset(next_offset, abi_align, full_bit_count / 8, 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_store_size_in_bits(field_type->size_in_bits) != field_size_in_bits) { first_packed_bits_offset_misalign = packed_bits_offset; type_struct_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; 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; + next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, field_type->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 store_bit_count = get_store_size_in_bits(full_bit_count); + next_offset = next_field_offset(next_offset, abi_align, store_bit_count / 8, 1); + host_int_bytes[gen_field_index] = store_bit_count / 8; 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_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' depends on its own alignment", 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; - LLVMStructSetBody(struct_type->type_ref, element_types, (unsigned)gen_field_count, packed); + 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; - // 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); + if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { + union_type->data.unionation.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } - ZigLLVMDIType **di_element_types = allocate(debug_field_count); + if (type_is_invalid(union_type)) + 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) { + if (!type_has_bits(field_type)) continue; + + if (most_aligned_union_member == nullptr || + field_type->abi_align > most_aligned_union_member->abi_align) + { + most_aligned_union_member = field_type; } + } - ZigType *field_type = type_struct_field->type_entry; + // unset temporary flag + union_type->data.unionation.resolve_loop_flag = true; + union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown; - // 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; + 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; } - - 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; + 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) { - if (!union_type->data.unionation.reported_infinite_err) { - union_type->data.unionation.reported_infinite_err = true; - union_type->data.unionation.is_invalid = true; - 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(!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; assert(union_type->data.unionation.fields); - 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; + size_t union_abi_size = 0; + size_t union_size_in_bits = 0; - Scope *scope = &union_type->data.unionation.decls_scope->base; - ZigType *import = get_scope_import(scope); + 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.resolve_status = ResolveStatusInvalid; + ErrorMsg *msg = add_node_error(g, decl_node, + buf_sprintf("union '%s' depends on its own size", buf_ptr(&union_type->name))); + emit_error_notes_for_ref_stack(g, msg); + } + return ErrorSemanticAnalyzeFail; + } // set temporary flag - union_type->data.unionation.embedded_in_current = true; - + union_type->data.unionation.resolve_loop_flag = 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); + 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); + } - biggest_size_in_bits = max(biggest_size_in_bits, store_size_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; - 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; + ZigType *tag_type = union_type->data.unionation.tag_type; + ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; + 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 { + 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[0]); + union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], field_aligns[1]); + union_type->size_in_bits = union_type->abi_size * 8; } + } else { + union_type->abi_size = union_abi_size; + union_type->size_in_bits = union_size_in_bits; } + return ErrorNone; +} - // 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; +static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { + assert(enum_type->id == ZigTypeIdEnum); - if (union_type->data.unionation.is_invalid) + if (enum_type->data.enumeration.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; - } - - uint64_t padding_in_bits = biggest_size_in_bits - size_of_most_aligned_member_in_bits; - - 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); - } else { - LLVMStructSetBody(union_type->type_ref, &most_aligned_union_member->type_ref, 1, false); - } - 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; - } - - 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.zero_bits_known) return ErrorNone; @@ -2531,7 +1869,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 +1901,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 +1928,6 @@ 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; 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,7 +2011,6 @@ 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; if (enum_type->data.enumeration.is_invalid) @@ -2698,7 +2037,6 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { 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; @@ -2767,7 +2105,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; @@ -2803,52 +2144,50 @@ 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 abi_align = 0; 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; - - // 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 - // and make sure it is fixed in stage2. This workaround is for when - // there is a false positive of a dependency loop, of alignment depending - // 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 (type_is_invalid(field->type_entry)) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - break; - } + ZigType *field_type = field->type_entry; + assert(field_type != nullptr); - if (!type_has_bits(field->type_entry)) - continue; + if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + + if (struct_type->data.structure.layout == ContainerLayoutExtern && + !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; + return ErrorSemanticAnalyzeFail; + } + + if (!type_has_bits(field_type)) + continue; - if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { + 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; + return ErrorSemanticAnalyzeFail; + } + // TODO: https://github.com/ziglang/zig/issues/1512 + if (1 > abi_align) { + abi_align = 1; + } + } else { + // TODO: https://github.com/ziglang/zig/issues/1512 + if (field_type->abi_align > abi_align) { + abi_align = field_type->abi_align; } - - this_field_align = get_abi_alignment(g, field->type_entry); - assert(this_field_align != 0); - } - // 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; } } @@ -2859,6 +2198,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; + struct_type->abi_align = abi_align; return ErrorNone; } @@ -2867,57 +2207,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 +2255,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 +2264,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 +2278,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 +2300,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 +2314,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; @@ -3010,8 +2333,8 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) { 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 +2343,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 +2399,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 +2415,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 +2426,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 +2443,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 +2464,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 +2506,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; - } - - 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; - - if (union_type->data.unionation.is_invalid) + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) { return ErrorSemanticAnalyzeFail; + } + + union_type->data.unionation.resolve_loop_flag = false; + + 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; } @@ -4007,7 +3310,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 +3321,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) { @@ -4626,18 +3929,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; } @@ -4677,6 +3988,7 @@ bool handle_is_ptr(ZigType *type_entry) { return false; case ZigTypeIdArray: case ZigTypeIdStruct: + case ZigTypeIdUnion: return type_has_bits(type_entry); case ZigTypeIdErrorUnion: return type_has_bits(type_entry->data.error_union.payload_type); @@ -4684,13 +3996,6 @@ bool handle_is_ptr(ZigType *type_entry) { return type_has_bits(type_entry->data.maybe.child_type) && !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; } zig_unreachable(); @@ -5165,10 +4470,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,7 +4934,7 @@ 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: @@ -6192,31 +5497,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,26 +5912,6 @@ 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. @@ -6841,11 +6113,8 @@ 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) { - return 0; - } - LLVMTypeRef field_type = LLVMStructGetTypeAtIndex(struct_type->type_ref, field->gen_index); - return LLVMStoreSizeOfType(g->target_data_ref, field_type); + assert(type_is_resolved(struct_type, ResolveStatusSizeKnown)); + 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 +6180,822 @@ 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) { + ZigType *ptr_type = type->data.structure.fields[slice_ptr_index].type_entry; + ZigType *child_type = ptr_type->data.pointer.child_type; + + 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); + + type->llvm_type = get_llvm_type(g, peer_slice_type); + type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); + } + + // 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); + + type->llvm_type = get_llvm_type(g, peer_slice_type); + type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); + } + } + + if (type->llvm_type != nullptr) + return; + + ZigType *usize_type = g->builtin_types.entry_usize; + LLVMTypeRef usize_llvm_type = get_llvm_type(g, usize_type); + ZigLLVMDIType *usize_llvm_di_type = get_llvm_di_type(g, usize_type); + + type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name)); + + 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); + + 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; + 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); + 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; +} + +static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { + 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); + + AstNode *decl_node = struct_type->data.structure.decl_node; + 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; + + 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; + if (get_store_size_in_bits(full_bit_count) == full_bit_count) { + // next field recovers store 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_store_size_in_bits(field_type->size_in_bits) != 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 store_bit_count = get_store_size_in_bits(full_bit_count); + element_types[gen_field_index] = LLVMIntType((unsigned)store_bit_count); + gen_field_index += 1; + } + + struct_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)); + LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed); + + ZigLLVMDIType **di_element_types = allocate(debug_field_count); + + 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; + } + + 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 = get_store_size_in_bits(field_type->size_in_bits); + debug_align_in_bits = 8 * field_type->abi_align; + debug_offset_in_bits = 8 * type_struct_field->offset; + } + di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder, + ZigLLVMTypeToScope(struct_type->llvm_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; + } + + uint64_t debug_size_in_bits = get_store_size_in_bits(struct_type->size_in_bits); + uint64_t debug_align_in_bits = 8*struct_type->abi_align; + 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->llvm_di_type, replacement_di_type); + struct_type->llvm_di_type = replacement_di_type; +} + +static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { + assert(!enum_type->data.enumeration.is_invalid); + assert(enum_type->data.enumeration.complete); + + uint32_t field_count = enum_type->data.enumeration.src_field_count; + + 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); + + 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; + + // create debug type for tag + AstNode *decl_node = enum_type->data.enumeration.decl_node; + 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) { + ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; + ZigType *tag_type = union_type->data.unionation.tag_type; + if (tag_type == nullptr || !type_has_bits(tag_type)) { + assert(most_aligned_union_member != nullptr); + assert(union_type->data.unionation.union_abi_size >= most_aligned_union_member->abi_size); + union_type->llvm_type = get_llvm_type(g, most_aligned_union_member); + union_type->llvm_di_type = get_llvm_di_type(g, most_aligned_union_member); + return; + } + 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); + 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; + 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)); + + 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; + + 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, get_llvm_di_type(g, union_field->type_entry)); + + } + union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); + + 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; +} + +static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { + 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) { + type->llvm_type = LLVMPointerType(get_llvm_type(g, elem_type), 0); + uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type); + uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type); + type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, elem_type), + debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name)); + } 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) { + 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) { + 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) { + 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) { + 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) { + 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 (!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) { + assert(type_is_resolved(type, ResolveStatusSizeKnown)); + assert(type_has_bits(type)); + switch (type->id) { + case ZigTypeIdInvalid: + case ZigTypeIdFloat: + case ZigTypeIdOpaque: + case ZigTypeIdMetaType: + case ZigTypeIdVoid: + case ZigTypeIdBool: + case ZigTypeIdUnreachable: + case ZigTypeIdComptimeFloat: + case ZigTypeIdComptimeInt: + case ZigTypeIdEnumLiteral: + case ZigTypeIdUndefined: + case ZigTypeIdNull: + case ZigTypeIdBoundFn: + case ZigTypeIdArgTuple: + zig_unreachable(); + case ZigTypeIdStruct: + if (type->data.structure.is_slice) + return resolve_llvm_types_slice(g, type); + else + return resolve_llvm_types_struct(g, type); + case ZigTypeIdEnum: + return resolve_llvm_types_enum(g, type); + case ZigTypeIdUnion: + return resolve_llvm_types_union(g, type); + case ZigTypeIdPointer: + return resolve_llvm_types_pointer(g, type); + case ZigTypeIdPromise: { + 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 (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: { + 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) { + if (type->llvm_type != nullptr) + return type->llvm_type; + resolve_llvm_types(g, type); + assert(type->llvm_type != nullptr); + assert(type->llvm_di_type != nullptr); + assert(type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); + assert(type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); + return type->llvm_type; +} + +ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) + return type->llvm_di_type; + resolve_llvm_types(g, type); + assert(type->llvm_type != nullptr); + assert(type->llvm_di_type != nullptr); + assert(type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); + assert(type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); + return type->llvm_di_type; +} -- cgit v1.2.3 From 3dc8448680cfea2b55a6064c655e400e31e5d3dd Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Apr 2019 12:53:57 -0400 Subject: introduce lazy values but I think it's a bad idea, so I'm going to back out the change --- src/all_types.hpp | 44 ++++- src/analyze.cpp | 397 ++++++++++++++++++++++++++++++++------------- src/analyze.hpp | 5 +- src/codegen.cpp | 18 +- src/ir.cpp | 478 ++++++++++++++++++++++++++++++++++++++---------------- src/ir.hpp | 3 +- 6 files changed, 681 insertions(+), 264 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index efa0bbe1a3..b61a0ba520 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -256,6 +256,7 @@ enum ConstValSpecial { ConstValSpecialRuntime, ConstValSpecialStatic, ConstValSpecialUndef, + ConstValSpecialLazy, }; enum RuntimeHintErrorUnion { @@ -291,6 +292,43 @@ struct ConstGlobalRefs { LLVMValueRef llvm_global; }; +enum LazyValueId { + LazyValueIdInvalid, + LazyValueIdAlignOf, + LazyValueIdSliceType, + LazyValueIdFnType, +}; + +struct LazyValue { + LazyValueId id; + IrExecutable *exec; +}; + +struct LazyValueAlignOf { + LazyValue base; + ZigType *target_type; +}; + +struct LazyValueSliceType { + LazyValue base; + ZigType *elem_type; + ConstExprValue *align_val; // can be null + bool is_const; + bool is_volatile; + bool is_allowzero; +}; + +struct LazyValueFnType { + LazyValue base; + AstNode *proto_node; + ConstExprValue **param_types; + ConstExprValue *align_val; // can be null + ConstExprValue *return_type; + ConstExprValue *async_allocator_type; + bool is_generic; + bool is_var_args; +}; + struct ConstExprValue { ZigType *type; ConstValSpecial special; @@ -318,6 +356,7 @@ struct ConstExprValue { ConstPtrValue x_ptr; ConstArgTuple x_arg_tuple; Buf *x_enum_literal; + LazyValue *x_lazy; // populated if special == ConstValSpecialRuntime RuntimeHintErrorUnion rh_error_union; @@ -359,6 +398,7 @@ enum TldResolution { TldResolutionUnresolved, TldResolutionResolving, TldResolutionInvalid, + TldResolutionOkLazy, TldResolutionOk, }; @@ -1064,7 +1104,8 @@ struct ZigTypeArray { struct TypeStructField { Buf *name; - ZigType *type_entry; + ZigType *type_entry; // available after ResolveStatusSizeKnown + ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown size_t src_index; size_t gen_index; size_t offset; // byte offset from beginning of struct @@ -1893,7 +1934,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 e17f9eaa66..811d1a1c02 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -19,7 +19,6 @@ 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); @@ -568,12 +567,11 @@ 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 field_align) { - BREAKPOINT; // TODO test this +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, field_align); + 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; } @@ -623,8 +621,8 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa 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[0]); - entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], field_aligns[1]); + 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; } @@ -699,6 +697,15 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) { 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]); + 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; @@ -897,8 +904,8 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { 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 = (fn_type_id->alignment == 0) ? - g->builtin_types.entry_usize->abi_align : fn_type_id->alignment; + // see also type_val_resolve_abi_align + fn_type->abi_align = (fn_type_id->alignment == 0) ? 1 : fn_type_id->alignment; g->fn_type_table.put(&fn_type->data.fn.fn_type_id, fn_type); @@ -956,15 +963,134 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind return entry; } -static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, - Buf *type_name) +static ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, + Buf *type_name, bool allow_lazy) { size_t backward_branch_count = 0; return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota, - nullptr, nullptr, node, type_name, nullptr, nullptr); + nullptr, nullptr, node, type_name, nullptr, nullptr, allow_lazy); } +static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, + Buf *type_name) +{ + return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false); +} + +static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, bool *is_zero_bits) { + Error err; + if (type_val->special != ConstValSpecialLazy) { + assert(type_val->special == ConstValSpecialStatic); + if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown))) + return err; + *is_zero_bits = (type_val->data.x_type->abi_size == 0); + return ErrorNone; + } + switch (type_val->data.x_lazy->id) { + case LazyValueIdInvalid: + case LazyValueIdAlignOf: + zig_unreachable(); + case LazyValueIdSliceType: + *is_zero_bits = false; + return ErrorNone; + case LazyValueIdFnType: { + LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); + *is_zero_bits = lazy_fn_type->is_generic; + return ErrorNone; + } + } + zig_unreachable(); +} + +static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) { + if (type_val->special != ConstValSpecialLazy) { + assert(type_val->special == ConstValSpecialStatic); + *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque); + return ErrorNone; + } + switch (type_val->data.x_lazy->id) { + case LazyValueIdInvalid: + case LazyValueIdAlignOf: + zig_unreachable(); + case LazyValueIdSliceType: + case LazyValueIdFnType: + *is_opaque_type = false; + return ErrorNone; + } + zig_unreachable(); +} + +static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) { + if (type_val->special != ConstValSpecialLazy) { + return type_requires_comptime(g, type_val->data.x_type); + } + switch (type_val->data.x_lazy->id) { + case LazyValueIdInvalid: + case LazyValueIdAlignOf: + zig_unreachable(); + case LazyValueIdSliceType: { + LazyValueSliceType *lazy_slice_type = reinterpret_cast(type_val->data.x_lazy); + return type_requires_comptime(g, lazy_slice_type->elem_type); + } + case LazyValueIdFnType: { + LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); + if (lazy_fn_type->is_generic) + return ReqCompTimeYes; + switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type)) { + case ReqCompTimeInvalid: + return ReqCompTimeInvalid; + case ReqCompTimeYes: + return ReqCompTimeYes; + case ReqCompTimeNo: + break; + } + size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length; + if (lazy_fn_type->is_var_args) param_count -= 1; + for (size_t i = 0; i < param_count; i += 1) { + switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i])) { + case ReqCompTimeInvalid: + return ReqCompTimeInvalid; + case ReqCompTimeYes: + return ReqCompTimeYes; + case ReqCompTimeNo: + break; + } + } + return ReqCompTimeNo; + } + } + zig_unreachable(); +} + +static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, size_t *abi_align) { + Error err; + if (type_val->special != ConstValSpecialLazy) { + assert(type_val->special == ConstValSpecialStatic); + if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusAlignmentKnown))) + return err; + *abi_align = type_val->data.x_type->abi_align; + return ErrorNone; + } + switch (type_val->data.x_lazy->id) { + case LazyValueIdInvalid: + case LazyValueIdAlignOf: + zig_unreachable(); + case LazyValueIdSliceType: + *abi_align = g->builtin_types.entry_usize->abi_align; + return ErrorNone; + case LazyValueIdFnType: { + LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); + if (lazy_fn_type->align_val != nullptr) + return type_val_resolve_abi_align(g, lazy_fn_type->align_val, abi_align); + *abi_align = 1; + return ErrorNone; + } + } + zig_unreachable(); +} + + ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); if (type_is_invalid(result->type)) @@ -1492,11 +1618,6 @@ bool type_is_invalid(ZigType *type_entry) { } -static Error resolve_enum_type(CodeGen *g, ZigType *enum_type) { - return resolve_enum_zero_bits(g, enum_type); -} - - ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[], ZigType *field_types[], size_t field_count) { @@ -1536,8 +1657,9 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = &struct_type->data.structure.fields[i]; field->offset = next_offset; - next_offset = next_field_offset(next_offset, abi_align, - field->type_entry->abi_size, field->type_entry->abi_align); + size_t next_abi_align = (i + 1 == field_count) ? + abi_align : struct_type->data.structure.fields[i + 1].type_entry->abi_align; + next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align); } struct_type->abi_align = abi_align; @@ -1548,7 +1670,7 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na } static size_t get_store_size_in_bits(size_t size_in_bits) { - return (size_in_bits + 7) / 8; + return ((size_in_bits + 7) / 8) * 8; } static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { @@ -1584,7 +1706,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked); struct_type->data.structure.resolve_loop_flag = true; - uint32_t *host_int_bytes = allocate(struct_type->data.structure.gen_field_count); + uint32_t *host_int_bytes = packed ? allocate(struct_type->data.structure.gen_field_count) : nullptr; // Compute offsets for all the fields. size_t packed_bits_offset = 0; @@ -1594,24 +1716,53 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { size_t size_in_bits = 0; size_t abi_align = struct_type->abi_align; + // Resolve types for fields 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; + AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); + TypeStructField *field = &struct_type->data.structure.fields[i]; - if (!type_has_bits(field_type)) - continue; + if ((err = ir_resolve_lazy(g, field_source_node, field->type_val))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return err; + } + ZigType *field_type = field->type_val->data.x_type; + field->type_entry = field_type; if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; + return err; } if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { return ErrorSemanticAnalyzeFail; } - type_struct_field->gen_index = gen_field_index; - type_struct_field->offset = next_offset; + if (packed) { + if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + } else if (struct_type->data.structure.layout == ContainerLayoutExtern && + !type_allowed_in_extern(g, field_type)) + { + 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; + return ErrorSemanticAnalyzeFail; + } + } + + // 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); + + field->gen_index = gen_field_index; + field->offset = next_offset; if (packed) { size_t field_size_in_bits = type_size_bits(g, field_type); @@ -1621,7 +1772,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { 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; if (get_store_size_in_bits(full_bit_count) == full_bit_count) { @@ -1636,10 +1787,10 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { } } else if (get_store_size_in_bits(field_type->size_in_bits) != 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. - type_struct_field->bit_offset_in_host = 0; + 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); @@ -1648,7 +1799,15 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { packed_bits_offset = next_packed_bits_offset; } else { gen_field_index += 1; - next_offset = next_field_offset(next_offset, abi_align, field_type->abi_size, field_type->abi_align); + 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; } } @@ -1679,9 +1838,10 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { 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) { @@ -1724,7 +1884,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { } // unset temporary flag - union_type->data.unionation.resolve_loop_flag = true; + union_type->data.unionation.resolve_loop_flag = false; union_type->data.unionation.resolve_status = ResolveStatusAlignmentKnown; ZigType *tag_type = union_type->data.unionation.tag_type; @@ -1836,8 +1996,8 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { 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[0]); - union_type->abi_size = next_field_offset(field2_offset, union_type->abi_align, field_sizes[1], field_aligns[1]); + 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; } } else { @@ -1928,6 +2088,9 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { } } enum_type->data.enumeration.tag_int_type = tag_int_type; + 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); @@ -2012,6 +2175,7 @@ static Error resolve_enum_zero_bits(CodeGen *g, ZigType *enum_type) { enum_type->data.enumeration.zero_bits_loop_flag = false; enum_type->data.enumeration.zero_bits_known = true; + enum_type->data.enumeration.complete = true; if (enum_type->data.enumeration.is_invalid) return ErrorSemanticAnalyzeFail; @@ -2022,22 +2186,28 @@ 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) { - struct_type->data.structure.resolve_status = ResolveStatusZeroBitsKnown; - struct_type->data.structure.resolve_loop_flag = false; - return ErrorNone; + if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + ErrorMsg *msg = add_node_error(g, decl_node, + buf_sprintf("struct '%s' depends on its own size", buf_ptr(&struct_type->name))); + emit_error_notes_for_ref_stack(g, msg); + } + return ErrorSemanticAnalyzeFail; } 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->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; @@ -2056,7 +2226,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); @@ -2065,38 +2235,55 @@ 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; + ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope, + field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true); + if (type_is_invalid(field_type_val->type)) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + assert(field_type_val->special != ConstValSpecialRuntime); + type_struct_field->type_val = field_type_val; type_struct_field->src_index = i; type_struct_field->gen_index = SIZE_MAX; + if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; + if (field_node->data.struct_field.value != nullptr) { add_node_error(g, field_node->data.struct_field.value, buf_sprintf("enums, not structs, support field assignment")); } - - if (field_type->id == ZigTypeIdOpaque) { + bool field_is_opaque_type; + if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (field_is_opaque_type) { 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)) { + switch (type_val_resolve_requires_comptime(g, field_type_val)) { 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; } - if (!type_has_bits(field_type)) + bool field_is_zero_bits; + if ((err = type_val_resolve_zero_bits(g, field_type_val, &field_is_zero_bits))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + if (field_is_zero_bits) continue; type_struct_field->gen_index = gen_field_index; @@ -2126,9 +2313,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; @@ -2136,7 +2324,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; ErrorMsg *msg = add_node_error(g, decl_node, - buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); + buf_sprintf("struct '%s' depends on its own alignment", buf_ptr(&struct_type->name))); emit_error_notes_for_ref_stack(g, msg); } return ErrorSemanticAnalyzeFail; @@ -2151,42 +2339,23 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = &struct_type->data.structure.fields[i]; - ZigType *field_type = field->type_entry; - assert(field_type != nullptr); - - if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - - if (struct_type->data.structure.layout == ContainerLayoutExtern && - !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; - return ErrorSemanticAnalyzeFail; - } - - if (!type_has_bits(field_type)) + if (field->gen_index == SIZE_MAX) continue; 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; - return ErrorSemanticAnalyzeFail; - } // TODO: https://github.com/ziglang/zig/issues/1512 if (1 > abi_align) { abi_align = 1; } } else { // TODO: https://github.com/ziglang/zig/issues/1512 - if (field_type->abi_align > abi_align) { - abi_align = field_type->abi_align; + size_t field_align; + if ((err = type_val_resolve_abi_align(g, field->type_val, &field_align))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return err; + } + if (field_align > abi_align) { + abi_align = field_align; } } } @@ -2824,7 +2993,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name); - resolve_top_level_decl(g, tld, tld->source_node); + resolve_top_level_decl(g, tld, tld->source_node, false); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; tld_var->var->const_value = value; @@ -2933,20 +3102,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(); } @@ -3066,7 +3232,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf return variable_entry; } -static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { +static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { AstNode *source_node = tld_var->base.source_node; AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; @@ -3107,7 +3273,8 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { if (explicit_type && explicit_type->id == ZigTypeIdInvalid) { implicit_type = explicit_type; } else if (var_decl->expr) { - init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); + init_value = analyze_const_value_allow_lazy(g, tld_var->base.parent_scope, var_decl->expr, + explicit_type, var_decl->symbol, allow_lazy); assert(init_value); implicit_type = init_value->type; @@ -3170,11 +3337,11 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { g->global_vars.append(tld_var); } -void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { - if (tld->resolution != TldResolutionUnresolved) +void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) { + bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy; + if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy) return; - assert(tld->resolution != TldResolutionResolving); tld->resolution = TldResolutionResolving; g->tld_ref_source_node_stack.append(source_node); @@ -3182,7 +3349,11 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { case TldIdVar: { TldVar *tld_var = (TldVar *)tld; - resolve_decl_var(g, tld_var); + if (want_resolve_lazy) { + ir_resolve_lazy(g, source_node, tld_var->var->const_value); + } else { + resolve_decl_var(g, tld_var, allow_lazy); + } break; } case TldIdFn: @@ -3205,7 +3376,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { } } - tld->resolution = TldResolutionOk; + tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk; g->tld_ref_source_node_stack.pop(); } @@ -3399,17 +3570,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: @@ -3435,6 +3603,7 @@ void resolve_container_type(CodeGen *g, ZigType *type_entry) { case ZigTypeIdVector: zig_unreachable(); } + zig_unreachable(); } ZigType *get_src_ptr_type(ZigType *type) { @@ -3536,10 +3705,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; - } } } @@ -3880,7 +4045,7 @@ void semantic_analyze(CodeGen *g) { for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { Tld *tld = g->resolve_queue.at(g->resolve_queue_index); AstNode *source_node = nullptr; - resolve_top_level_decl(g, tld, source_node); + resolve_top_level_decl(g, tld, source_node, false); } for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { @@ -4941,7 +5106,7 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { 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); } @@ -5314,6 +5479,9 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ConstValSpecialRuntime: buf_appendf(buf, "(runtime value)"); return; + case ConstValSpecialLazy: + buf_appendf(buf, "(lazy value)"); + return; case ConstValSpecialUndef: buf_appendf(buf, "undefined"); return; @@ -5930,7 +6098,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) { ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name)); - resolve_top_level_decl(codegen, tld, nullptr); + resolve_top_level_decl(codegen, tld, nullptr, false); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; ConstExprValue *var_value = tld_var->var->const_value; @@ -6114,6 +6282,8 @@ 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); assert(type_is_resolved(struct_type, ResolveStatusSizeKnown)); + if (struct_type->data.structure.host_int_bytes == nullptr) + return 0; return struct_type->data.structure.host_int_bytes[field->gen_index]; } @@ -6374,8 +6544,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed); ZigLLVMDIType **di_element_types = allocate(debug_field_count); - ZigType *import = get_scope_import(scope); + unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); + struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + dwarf_kind, buf_ptr(&struct_type->name), + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1)); + 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); diff --git a/src/analyze.hpp b/src/analyze.hpp index 02f453ae8c..48f07fd633 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -61,7 +61,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Bu ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope); Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name); -void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node); +void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy); ZigType *get_src_ptr_type(ZigType *type); ZigType *get_codegen_ptr_type(ZigType *type); @@ -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); @@ -246,4 +246,5 @@ 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 b7adae798c..f5b15bbeb4 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)); @@ -2285,7 +2287,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); } @@ -3354,6 +3358,8 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { static bool value_is_all_undef(ConstExprValue *const_val) { switch (const_val->special) { + case ConstValSpecialLazy: + zig_unreachable(); case ConstValSpecialRuntime: return false; case ConstValSpecialUndef: @@ -5818,6 +5824,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { switch (const_val->special) { + case ConstValSpecialLazy: case ConstValSpecialRuntime: zig_unreachable(); case ConstValSpecialUndef: @@ -6075,6 +6082,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c assert(type_has_bits(type_entry)); switch (const_val->special) { + case ConstValSpecialLazy: case ConstValSpecialRuntime: zig_unreachable(); case ConstValSpecialUndef: @@ -6834,9 +6842,9 @@ static void do_code_gen(CodeGen *g) { 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) { @@ -6844,7 +6852,7 @@ 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); @@ -6853,7 +6861,7 @@ static void do_code_gen(CodeGen *g) { 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), - get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(var->gen_arg_index + 1)); + get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index)); } } @@ -8241,7 +8249,7 @@ static void gen_root_source(CodeGen *g) { } Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic")); assert(panic_tld != nullptr); - resolve_top_level_decl(g, panic_tld, nullptr); + resolve_top_level_decl(g, panic_tld, nullptr, false); } diff --git a/src/ir.cpp b/src/ir.cpp index 872a943814..a4d7cf271b 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -154,6 +154,7 @@ struct ConstCastBadAllowsZero { enum UndefAllowed { UndefOk, UndefBad, + LazyOk, }; static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); @@ -10256,32 +10257,57 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio return const_instr; } +static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, + ConstExprValue *val, UndefAllowed undef_allowed) +{ + Error err; + for (;;) { + switch (val->special) { + case ConstValSpecialStatic: + return ErrorNone; + case ConstValSpecialRuntime: + if (!type_has_bits(val->type)) + return ErrorNone; + + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("unable to evaluate constant expression")); + return ErrorSemanticAnalyzeFail; + case ConstValSpecialUndef: + if (undef_allowed == UndefOk) + return ErrorNone; + + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("use of undefined value here causes undefined behavior")); + return ErrorSemanticAnalyzeFail; + case ConstValSpecialLazy: + if (undef_allowed == LazyOk) + return ErrorNone; + + if ((err = ir_resolve_lazy(codegen, source_node, val))) + return err; + + continue; + } + } +} + static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { - switch (value->value.special) { - case ConstValSpecialStatic: - return &value->value; - case ConstValSpecialRuntime: - if (!type_has_bits(value->value.type)) { - return &value->value; - } - ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); - return nullptr; - case ConstValSpecialUndef: - if (undef_allowed == UndefOk) { - return &value->value; - } else { - ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); - return nullptr; - } + Error err; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node, + &value->value, undef_allowed))) + { + return nullptr; } - zig_unreachable(); + return &value->value; } ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node) + IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy) { + Error err; + if (expected_type != nullptr && type_is_invalid(expected_type)) return &codegen->invalid_instruction->value; @@ -10326,7 +10352,24 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod fprintf(stderr, "}\n"); } - return ir_exec_const_result(codegen, analyzed_executable); + ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable); + + if (!allow_lazy) { + if ((err = ir_resolve_lazy(codegen, node, result))) + return &codegen->invalid_instruction->value; + } + return result; +} + +static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, + ConstExprValue *val) +{ + Error err; + if ((err = ir_resolve_const_val(codegen, exec, source_node, val, UndefBad))) + return codegen->builtin_types.entry_invalid; + + assert(val->data.x_type != nullptr); + return val->data.x_type; } static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { @@ -10339,12 +10382,7 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { return ira->codegen->builtin_types.entry_invalid; } - ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad); - if (!const_val) - return ira->codegen->builtin_types.entry_invalid; - - assert(const_val->data.x_type != nullptr); - return const_val->data.x_type; + return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, &type_value->value); } static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { @@ -11835,33 +11873,38 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } } -static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { - if (type_is_invalid(value->value.type)) - return false; - - IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); - if (type_is_invalid(casted_value->value.type)) - return false; - - ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); - if (!const_val) +static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, + ConstExprValue *const_val, uint32_t *out) +{ + Error err; + if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad))) return false; uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint); if (align_bytes == 0) { - ir_add_error(ira, value, buf_sprintf("alignment must be >= 1")); + exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); return false; } if (!is_power_of_2(align_bytes)) { - ir_add_error(ira, value, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); + exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); return false; } - *out = align_bytes; return true; } +static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { + if (type_is_invalid(value->value.type)) + return false; + + IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); + if (type_is_invalid(casted_value->value.type)) + return false; + + return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node, &casted_value->value, out); +} + static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) { if (type_is_invalid(value->value.type)) return false; @@ -12029,6 +12072,140 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { return result; } +static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, + LazyValueFnType *lazy_fn_type) +{ + AstNode *proto_node = lazy_fn_type->proto_node; + + FnTypeId fn_type_id = {0}; + init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); + + for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); + assert(param_node->type == NodeTypeParamDecl); + + bool param_is_var_args = param_node->data.param_decl.is_var_args; + if (param_is_var_args) { + if (fn_type_id.cc == CallingConventionC) { + fn_type_id.param_count = fn_type_id.next_param_index; + continue; + } else if (fn_type_id.cc == CallingConventionUnspecified) { + return get_generic_fn_type(codegen, &fn_type_id); + } else { + zig_unreachable(); + } + } + FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; + param_info->is_noalias = param_node->data.param_decl.is_noalias; + + if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) { + param_info->type = nullptr; + return get_generic_fn_type(codegen, &fn_type_id); + } else { + ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node, + lazy_fn_type->param_types[fn_type_id.next_param_index]); + if (type_is_invalid(param_type)) + return nullptr; + switch (type_requires_comptime(codegen, param_type)) { + case ReqCompTimeYes: + if (!calling_convention_allows_zig_types(fn_type_id.cc)) { + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", + buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); + return nullptr; + } + param_info->type = param_type; + fn_type_id.next_param_index += 1; + return get_generic_fn_type(codegen, &fn_type_id); + case ReqCompTimeInvalid: + return nullptr; + case ReqCompTimeNo: + break; + } + if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", + buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); + return nullptr; + } + param_info->type = param_type; + } + + } + + if (lazy_fn_type->align_val != nullptr) { + if (!ir_resolve_const_align(codegen, exec, source_node, lazy_fn_type->align_val, &fn_type_id.alignment)) + return nullptr; + } + + fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type); + if (type_is_invalid(fn_type_id.return_type)) + return nullptr; + if (fn_type_id.return_type->id == ZigTypeIdOpaque) { + exec_add_error_node(codegen, exec, source_node, + buf_sprintf("return type cannot be opaque")); + return nullptr; + } + + if (lazy_fn_type->async_allocator_type != nullptr) { + fn_type_id.async_allocator_type = ir_resolve_const_type(codegen, exec, source_node, + lazy_fn_type->async_allocator_type); + if (type_is_invalid(fn_type_id.async_allocator_type)) + return nullptr; + } + + return get_fn_type(codegen, &fn_type_id); +} + +Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) { + Error err; + if (val->special != ConstValSpecialLazy) + return ErrorNone; + IrExecutable *exec = val->data.x_lazy->exec; + switch (val->data.x_lazy->id) { + case LazyValueIdInvalid: + zig_unreachable(); + case LazyValueIdAlignOf: { + LazyValueAlignOf *lazy_align_of = reinterpret_cast(val->data.x_lazy); + if ((err = type_resolve(codegen, lazy_align_of->target_type, ResolveStatusAlignmentKnown))) + return err; + uint64_t align_in_bytes = get_abi_alignment(codegen, lazy_align_of->target_type); + val->special = ConstValSpecialStatic; + assert(val->type->id == ZigTypeIdComptimeInt); + bigint_init_unsigned(&val->data.x_bigint, align_in_bytes); + return ErrorNone; + } + case LazyValueIdSliceType: { + LazyValueSliceType *lazy_slice_type = reinterpret_cast(val->data.x_lazy); + uint32_t align_bytes = 0; + if (lazy_slice_type->align_val != nullptr) { + if (!ir_resolve_const_align(codegen, exec, source_node, lazy_slice_type->align_val, &align_bytes)) + return ErrorSemanticAnalyzeFail; + } + if ((err = type_resolve(codegen, lazy_slice_type->elem_type, ResolveStatusZeroBitsKnown))) + return err; + ZigType *slice_ptr_type = get_pointer_to_type_extra(codegen, lazy_slice_type->elem_type, + lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes, + 0, 0, lazy_slice_type->is_allowzero); + val->special = ConstValSpecialStatic; + assert(val->type->id == ZigTypeIdMetaType); + val->data.x_type = get_slice_type(codegen, slice_ptr_type); + return ErrorNone; + } + case LazyValueIdFnType: { + ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node, + reinterpret_cast(val->data.x_lazy)); + if (fn_type == nullptr) + return ErrorSemanticAnalyzeFail; + val->special = ConstValSpecialStatic; + assert(val->type->id == ZigTypeIdMetaType); + val->data.x_type = fn_type; + return ErrorNone; + } + } + zig_unreachable(); +} + static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, IrInstructionAddImplicitReturnType *instruction) { @@ -13964,20 +14141,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); } @@ -14003,7 +14179,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, if (linkage_makes_it_runtime) goto no_mem_slot; - if (var->const_value->special == ConstValSpecialStatic) { + if (value_is_comptime(var->const_value)) { mem_slot = var->const_value; } else { if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { @@ -14021,6 +14197,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, case ConstValSpecialRuntime: goto no_mem_slot; case ConstValSpecialStatic: // fallthrough + case ConstValSpecialLazy: // fallthrough case ConstValSpecialUndef: { ConstPtrMut ptr_mut; if (comptime_var_mem) { @@ -14301,7 +14478,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call AstNode *body_node = fn_entry->body_node; result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, - nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); + nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node, false); if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.infer_fn = nullptr; @@ -14497,7 +14674,8 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, - nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); + nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr, + false); IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); const_instruction->base.value = *align_result; @@ -15630,7 +15808,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, auto entry = container_scope->decl_table.maybe_get(field_name); Tld *tld = entry ? entry->value : nullptr; if (tld && tld->id == TldIdFn) { - resolve_top_level_decl(ira->codegen, tld, source_instr->source_node); + resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; TldFn *tld_fn = (TldFn *)tld; @@ -15821,7 +15999,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { - resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node); + resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, false); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; @@ -16477,22 +16655,29 @@ static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstructionSliceType *slice_type_instruction) { - Error err; - uint32_t align_bytes = 0; + IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type); + result->value.special = ConstValSpecialLazy; + + LazyValueSliceType *lazy_slice_type = allocate(1); + result->value.data.x_lazy = &lazy_slice_type->base; + lazy_slice_type->base.id = LazyValueIdSliceType; + lazy_slice_type->base.exec = ira->new_irb.exec; + if (slice_type_instruction->align_value != nullptr) { - if (!ir_resolve_align(ira, slice_type_instruction->align_value->child, &align_bytes)) + lazy_slice_type->align_val = ir_resolve_const(ira, slice_type_instruction->align_value->child, LazyOk); + if (lazy_slice_type->align_val == nullptr) return ira->codegen->invalid_instruction; } - ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); - if (type_is_invalid(child_type)) + lazy_slice_type->elem_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); + if (type_is_invalid(lazy_slice_type->elem_type)) return ira->codegen->invalid_instruction; - bool is_const = slice_type_instruction->is_const; - bool is_volatile = slice_type_instruction->is_volatile; - bool is_allow_zero = slice_type_instruction->is_allow_zero; + lazy_slice_type->is_const = slice_type_instruction->is_const; + lazy_slice_type->is_volatile = slice_type_instruction->is_volatile; + lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero; - switch (child_type->id) { + switch (lazy_slice_type->elem_type->id) { case ZigTypeIdInvalid: // handled above zig_unreachable(); case ZigTypeIdUnreachable: @@ -16501,7 +16686,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdArgTuple: case ZigTypeIdOpaque: ir_add_error_node(ira, slice_type_instruction->base.source_node, - buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name))); + buf_sprintf("slice of type '%s' not allowed", buf_ptr(&lazy_slice_type->elem_type->name))); return ira->codegen->invalid_instruction; case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -16523,14 +16708,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdBoundFn: case ZigTypeIdPromise: case ZigTypeIdVector: - { - if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) - return ira->codegen->invalid_instruction; - ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, - is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero); - ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type); - return ir_const_type(ira, &slice_type_instruction->base, result_type); - } + return result; } zig_unreachable(); } @@ -16637,7 +16815,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, case ZigTypeIdPromise: case ZigTypeIdVector: { - if ((err = ensure_complete_type(ira->codegen, child_type))) + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) return ira->codegen->invalid_instruction; ZigType *result_type = get_array_type(ira->codegen, child_type, size); return ir_const_type(ira, &array_type_instruction->base, result_type); @@ -17513,6 +17691,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; @@ -17541,6 +17721,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 = {}; @@ -17923,10 +18107,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; @@ -17960,7 +18145,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); @@ -17987,7 +18172,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr, while ((curr_entry = decl_it.next()) != nullptr) { // If the definition is unresolved, force it to be resolved again. if (curr_entry->value->resolution == TldResolutionUnresolved) { - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node); + resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); if (curr_entry->value->resolution != TldResolutionOk) { return ErrorSemanticAnalyzeFail; } @@ -18480,6 +18665,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); @@ -18523,6 +18711,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; @@ -18619,6 +18810,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); @@ -18696,6 +18889,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); @@ -18803,6 +18999,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); @@ -18962,7 +19161,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct ZigType *void_type = ira->codegen->builtin_types.entry_void; ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, - &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); + &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, false); if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; @@ -20509,15 +20708,11 @@ static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructio } static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { - Error err; IrInstruction *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value.type)) return ira->codegen->invalid_instruction; ZigType *type_entry = ir_resolve_type(ira, type_value); - if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_instruction; - switch (type_entry->id) { case ZigTypeIdInvalid: zig_unreachable(); @@ -20549,12 +20744,25 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdVector: - { - uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); - return ir_const_unsigned(ira, &instruction->base, align_in_bytes); - } + break; } - zig_unreachable(); + if (type_is_resolved(type_entry, ResolveStatusAlignmentKnown)) { + uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); + return ir_const_unsigned(ira, &instruction->base, align_in_bytes); + } + // Here we create a lazy value in order to avoid resolving the alignment of the type + // immediately. This avoids false positive dependency loops such as: + // const Node = struct { + // field: []align(@alignOf(Node)) Node, + // }; + LazyValueAlignOf *lazy_align_of = allocate(1); + lazy_align_of->base.id = LazyValueIdAlignOf; + lazy_align_of->base.exec = ira->new_irb.exec; + lazy_align_of->target_type = type_entry; + IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); + result->value.special = ConstValSpecialLazy; + result->value.data.x_lazy = &lazy_align_of->base; + return result; } static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { @@ -20809,96 +21017,77 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct AstNode *proto_node = instruction->base.source_node; assert(proto_node->type == NodeTypeFnProto); + IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); + result->value.special = ConstValSpecialLazy; + + LazyValueFnType *lazy_fn_type = allocate(1); + result->value.data.x_lazy = &lazy_fn_type->base; + lazy_fn_type->base.id = LazyValueIdFnType; + lazy_fn_type->base.exec = ira->new_irb.exec; + if (proto_node->data.fn_proto.auto_err_set) { ir_add_error(ira, &instruction->base, buf_sprintf("inferring error set of return type valid only for function definitions")); return ira->codegen->invalid_instruction; } - FnTypeId fn_type_id = {0}; - init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); + size_t param_count = proto_node->data.fn_proto.params.length; + lazy_fn_type->proto_node = proto_node; + lazy_fn_type->param_types = allocate(param_count); - for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { - AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); + for (size_t i = 0; i < param_count; i += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(i); assert(param_node->type == NodeTypeParamDecl); bool param_is_var_args = param_node->data.param_decl.is_var_args; + lazy_fn_type->is_var_args = true; if (param_is_var_args) { - if (fn_type_id.cc == CallingConventionC) { - fn_type_id.param_count = fn_type_id.next_param_index; - continue; - } else if (fn_type_id.cc == CallingConventionUnspecified) { - return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + if (proto_node->data.fn_proto.cc == CallingConventionC) { + break; + } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) { + lazy_fn_type->is_generic = true; + return result; } else { zig_unreachable(); } } - FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; - param_info->is_noalias = param_node->data.param_decl.is_noalias; - if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { - param_info->type = nullptr; - return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); - } else { - IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child; - if (type_is_invalid(param_type_value->value.type)) - return ira->codegen->invalid_instruction; - ZigType *param_type = ir_resolve_type(ira, param_type_value); - switch (type_requires_comptime(ira->codegen, param_type)) { - case ReqCompTimeYes: - if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - ir_add_error(ira, param_type_value, - buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", - buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); - return ira->codegen->invalid_instruction; - } - param_info->type = param_type; - fn_type_id.next_param_index += 1; - return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); - case ReqCompTimeInvalid: - return ira->codegen->invalid_instruction; - case ReqCompTimeNo: - break; - } - if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { - ir_add_error(ira, param_type_value, - buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", - buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); - return ira->codegen->invalid_instruction; - } - param_info->type = param_type; + if (instruction->param_types[i] == nullptr) { + lazy_fn_type->is_generic = true; + return result; } + IrInstruction *param_type_value = instruction->param_types[i]->child; + if (type_is_invalid(param_type_value->value.type)) + return ira->codegen->invalid_instruction; + ConstExprValue *param_type_val = ir_resolve_const(ira, param_type_value, LazyOk); + if (param_type_val == nullptr) + return ira->codegen->invalid_instruction; + lazy_fn_type->param_types[i] = param_type_val; } if (instruction->align_value != nullptr) { - if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment)) + lazy_fn_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk); + if (lazy_fn_type->align_val == nullptr) return ira->codegen->invalid_instruction; } - IrInstruction *return_type_value = instruction->return_type->child; - fn_type_id.return_type = ir_resolve_type(ira, return_type_value); - if (type_is_invalid(fn_type_id.return_type)) - return ira->codegen->invalid_instruction; - if (fn_type_id.return_type->id == ZigTypeIdOpaque) { - ir_add_error(ira, instruction->return_type, - buf_sprintf("return type cannot be opaque")); + lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk); + if (lazy_fn_type->return_type == nullptr) return ira->codegen->invalid_instruction; - } - if (fn_type_id.cc == CallingConventionAsync) { + if (proto_node->data.fn_proto.cc == CallingConventionAsync) { if (instruction->async_allocator_type_value == nullptr) { ir_add_error(ira, &instruction->base, buf_sprintf("async fn proto missing allocator type")); return ira->codegen->invalid_instruction; } - IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->child; - fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value); - if (type_is_invalid(fn_type_id.async_allocator_type)) + lazy_fn_type->async_allocator_type = ir_resolve_const(ira, instruction->async_allocator_type_value->child, LazyOk); + if (lazy_fn_type->async_allocator_type == nullptr) return ira->codegen->invalid_instruction; } - return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id)); + return result; } static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) { @@ -21567,8 +21756,11 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou val->type->data.vector.len); case ZigTypeIdEnum: switch (val->type->data.enumeration.layout) { - case ContainerLayoutAuto: - zig_panic("TODO buf_read_value_bytes enum auto"); + case ContainerLayoutAuto: { + opt_ir_add_error_node(ira, codegen, source_node, + buf_sprintf("compiler bug: TODO: implement enum byte reinterpretation")); + return ErrorSemanticAnalyzeFail; + } case ContainerLayoutPacked: zig_panic("TODO buf_read_value_bytes enum packed"); case ContainerLayoutExtern: { @@ -21864,7 +22056,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, Tld *tld = instruction->tld; LVal lval = instruction->lval; - resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node); + resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node, true); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; diff --git a/src/ir.hpp b/src/ir.hpp index 0b85ad2c55..bf65328f70 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -16,7 +16,8 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node); + IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy); +Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val); ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, ZigType *expected_type, AstNode *expected_type_source_node); -- cgit v1.2.3 From d3f2fe2cef7de1173a038365f91e8a574a08f21a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Apr 2019 17:46:31 -0400 Subject: remove the lazy value stuff let's try to keep this branch to solving one problem at a time --- src/all_types.hpp | 43 +----- src/analyze.cpp | 271 ++++++++------------------------- src/analyze.hpp | 2 +- src/codegen.cpp | 6 +- src/ir.cpp | 436 +++++++++++++++++------------------------------------- src/ir.hpp | 3 +- 6 files changed, 196 insertions(+), 565 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index b61a0ba520..5d06f7e883 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -256,7 +256,6 @@ enum ConstValSpecial { ConstValSpecialRuntime, ConstValSpecialStatic, ConstValSpecialUndef, - ConstValSpecialLazy, }; enum RuntimeHintErrorUnion { @@ -292,43 +291,6 @@ struct ConstGlobalRefs { LLVMValueRef llvm_global; }; -enum LazyValueId { - LazyValueIdInvalid, - LazyValueIdAlignOf, - LazyValueIdSliceType, - LazyValueIdFnType, -}; - -struct LazyValue { - LazyValueId id; - IrExecutable *exec; -}; - -struct LazyValueAlignOf { - LazyValue base; - ZigType *target_type; -}; - -struct LazyValueSliceType { - LazyValue base; - ZigType *elem_type; - ConstExprValue *align_val; // can be null - bool is_const; - bool is_volatile; - bool is_allowzero; -}; - -struct LazyValueFnType { - LazyValue base; - AstNode *proto_node; - ConstExprValue **param_types; - ConstExprValue *align_val; // can be null - ConstExprValue *return_type; - ConstExprValue *async_allocator_type; - bool is_generic; - bool is_var_args; -}; - struct ConstExprValue { ZigType *type; ConstValSpecial special; @@ -356,7 +318,6 @@ struct ConstExprValue { ConstPtrValue x_ptr; ConstArgTuple x_arg_tuple; Buf *x_enum_literal; - LazyValue *x_lazy; // populated if special == ConstValSpecialRuntime RuntimeHintErrorUnion rh_error_union; @@ -398,7 +359,6 @@ enum TldResolution { TldResolutionUnresolved, TldResolutionResolving, TldResolutionInvalid, - TldResolutionOkLazy, TldResolutionOk, }; @@ -1104,8 +1064,7 @@ struct ZigTypeArray { struct TypeStructField { Buf *name; - ZigType *type_entry; // available after ResolveStatusSizeKnown - ConstExprValue *type_val; // available after ResolveStatusZeroBitsKnown + ZigType *type_entry; size_t src_index; size_t gen_index; size_t offset; // byte offset from beginning of struct diff --git a/src/analyze.cpp b/src/analyze.cpp index 811d1a1c02..0f1767c76d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -902,10 +902,10 @@ ZigType *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { } buf_appendf(&fn_type->name, " %s", buf_ptr(&fn_type_id->return_type->name)); + // 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; - // see also type_val_resolve_abi_align - fn_type->abi_align = (fn_type_id->alignment == 0) ? 1 : fn_type_id->alignment; + 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); @@ -963,134 +963,15 @@ ZigType *get_partial_container_type(CodeGen *g, Scope *scope, ContainerKind kind return entry; } -static ConstExprValue *analyze_const_value_allow_lazy(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, - Buf *type_name, bool allow_lazy) +static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, + Buf *type_name) { size_t backward_branch_count = 0; return ir_eval_const_value(g, scope, node, type_entry, &backward_branch_count, default_backward_branch_quota, - nullptr, nullptr, node, type_name, nullptr, nullptr, allow_lazy); + nullptr, nullptr, node, type_name, nullptr, nullptr); } -static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, ZigType *type_entry, - Buf *type_name) -{ - return analyze_const_value_allow_lazy(g, scope, node, type_entry, type_name, false); -} - -static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, bool *is_zero_bits) { - Error err; - if (type_val->special != ConstValSpecialLazy) { - assert(type_val->special == ConstValSpecialStatic); - if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusZeroBitsKnown))) - return err; - *is_zero_bits = (type_val->data.x_type->abi_size == 0); - return ErrorNone; - } - switch (type_val->data.x_lazy->id) { - case LazyValueIdInvalid: - case LazyValueIdAlignOf: - zig_unreachable(); - case LazyValueIdSliceType: - *is_zero_bits = false; - return ErrorNone; - case LazyValueIdFnType: { - LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); - *is_zero_bits = lazy_fn_type->is_generic; - return ErrorNone; - } - } - zig_unreachable(); -} - -static Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) { - if (type_val->special != ConstValSpecialLazy) { - assert(type_val->special == ConstValSpecialStatic); - *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque); - return ErrorNone; - } - switch (type_val->data.x_lazy->id) { - case LazyValueIdInvalid: - case LazyValueIdAlignOf: - zig_unreachable(); - case LazyValueIdSliceType: - case LazyValueIdFnType: - *is_opaque_type = false; - return ErrorNone; - } - zig_unreachable(); -} - -static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue *type_val) { - if (type_val->special != ConstValSpecialLazy) { - return type_requires_comptime(g, type_val->data.x_type); - } - switch (type_val->data.x_lazy->id) { - case LazyValueIdInvalid: - case LazyValueIdAlignOf: - zig_unreachable(); - case LazyValueIdSliceType: { - LazyValueSliceType *lazy_slice_type = reinterpret_cast(type_val->data.x_lazy); - return type_requires_comptime(g, lazy_slice_type->elem_type); - } - case LazyValueIdFnType: { - LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_fn_type->is_generic) - return ReqCompTimeYes; - switch (type_val_resolve_requires_comptime(g, lazy_fn_type->return_type)) { - case ReqCompTimeInvalid: - return ReqCompTimeInvalid; - case ReqCompTimeYes: - return ReqCompTimeYes; - case ReqCompTimeNo: - break; - } - size_t param_count = lazy_fn_type->proto_node->data.fn_proto.params.length; - if (lazy_fn_type->is_var_args) param_count -= 1; - for (size_t i = 0; i < param_count; i += 1) { - switch (type_val_resolve_requires_comptime(g, lazy_fn_type->param_types[i])) { - case ReqCompTimeInvalid: - return ReqCompTimeInvalid; - case ReqCompTimeYes: - return ReqCompTimeYes; - case ReqCompTimeNo: - break; - } - } - return ReqCompTimeNo; - } - } - zig_unreachable(); -} - -static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, size_t *abi_align) { - Error err; - if (type_val->special != ConstValSpecialLazy) { - assert(type_val->special == ConstValSpecialStatic); - if ((err = type_resolve(g, type_val->data.x_type, ResolveStatusAlignmentKnown))) - return err; - *abi_align = type_val->data.x_type->abi_align; - return ErrorNone; - } - switch (type_val->data.x_lazy->id) { - case LazyValueIdInvalid: - case LazyValueIdAlignOf: - zig_unreachable(); - case LazyValueIdSliceType: - *abi_align = g->builtin_types.entry_usize->abi_align; - return ErrorNone; - case LazyValueIdFnType: { - LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_fn_type->align_val != nullptr) - return type_val_resolve_abi_align(g, lazy_fn_type->align_val, abi_align); - *abi_align = 1; - return ErrorNone; - } - } - zig_unreachable(); -} - - ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) { ConstExprValue *result = analyze_const_value(g, scope, node, g->builtin_types.entry_type, nullptr); if (type_is_invalid(result->type)) @@ -1656,9 +1537,17 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na 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_abi_align = (i + 1 == field_count) ? - abi_align : struct_type->data.structure.fields[i + 1].type_entry->abi_align; + 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); } @@ -1716,43 +1605,6 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { size_t size_in_bits = 0; size_t abi_align = struct_type->abi_align; - // Resolve types for fields - for (size_t i = 0; i < field_count; i += 1) { - AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); - TypeStructField *field = &struct_type->data.structure.fields[i]; - - if ((err = ir_resolve_lazy(g, field_source_node, field->type_val))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return err; - } - ZigType *field_type = field->type_val->data.x_type; - field->type_entry = field_type; - - if ((err = type_resolve(g, field_type, ResolveStatusSizeKnown))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return err; - } - - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) { - return ErrorSemanticAnalyzeFail; - } - - if (packed) { - if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - } else if (struct_type->data.structure.layout == ContainerLayoutExtern && - !type_allowed_in_extern(g, field_type)) - { - 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; - return ErrorSemanticAnalyzeFail; - } - } - // Calculate offsets for (size_t i = 0; i < field_count; i += 1) { TypeStructField *field = &struct_type->data.structure.fields[i]; @@ -2186,8 +2038,6 @@ 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) @@ -2238,36 +2088,29 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { return ErrorSemanticAnalyzeFail; } - ConstExprValue *field_type_val = analyze_const_value_allow_lazy(g, scope, - field_node->data.struct_field.type, g->builtin_types.entry_type, nullptr, true); - if (type_is_invalid(field_type_val->type)) { + 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; } - assert(field_type_val->special != ConstValSpecialRuntime); - type_struct_field->type_val = field_type_val; - type_struct_field->src_index = i; - type_struct_field->gen_index = SIZE_MAX; - if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) return ErrorSemanticAnalyzeFail; + type_struct_field->src_index = i; + type_struct_field->gen_index = SIZE_MAX; + if (field_node->data.struct_field.value != nullptr) { add_node_error(g, field_node->data.struct_field.value, buf_sprintf("enums, not structs, support field assignment")); } - bool field_is_opaque_type; - if ((err = type_val_resolve_is_opaque_type(g, field_type_val, &field_is_opaque_type))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - if (field_is_opaque_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 structs")); struct_type->data.structure.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } - switch (type_val_resolve_requires_comptime(g, field_type_val)) { + switch (type_requires_comptime(g, field_type)) { case ReqCompTimeYes: struct_type->data.structure.requires_comptime = true; break; @@ -2278,12 +2121,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { break; } - bool field_is_zero_bits; - if ((err = type_val_resolve_zero_bits(g, field_type_val, &field_is_zero_bits))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - if (field_is_zero_bits) + if (!type_has_bits(field_type)) continue; type_struct_field->gen_index = gen_field_index; @@ -2338,7 +2176,31 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; for (size_t i = 0; i < field_count; i += 1) { + AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); TypeStructField *field = &struct_type->data.structure.fields[i]; + ZigType *field_type = field->type_entry; + assert(field_type != nullptr); + + if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { + 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_source_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 (packed) { + if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; + } + } + if (field->gen_index == SIZE_MAX) continue; @@ -2349,13 +2211,8 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } } else { // TODO: https://github.com/ziglang/zig/issues/1512 - size_t field_align; - if ((err = type_val_resolve_abi_align(g, field->type_val, &field_align))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return err; - } - if (field_align > abi_align) { - abi_align = field_align; + if (field_type->abi_align > abi_align) { + abi_align = field_type->abi_align; } } } @@ -2993,7 +2850,7 @@ void init_tld(Tld *tld, TldId id, Buf *name, VisibMod visib_mod, AstNode *source void update_compile_var(CodeGen *g, Buf *name, ConstExprValue *value) { Tld *tld = get_container_scope(g->compile_var_import)->decl_table.get(name); - resolve_top_level_decl(g, tld, tld->source_node, false); + resolve_top_level_decl(g, tld, tld->source_node); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; tld_var->var->const_value = value; @@ -3232,7 +3089,7 @@ ZigVar *add_variable(CodeGen *g, AstNode *source_node, Scope *parent_scope, Buf return variable_entry; } -static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { +static void resolve_decl_var(CodeGen *g, TldVar *tld_var) { AstNode *source_node = tld_var->base.source_node; AstNodeVariableDeclaration *var_decl = &source_node->data.variable_declaration; @@ -3273,8 +3130,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { if (explicit_type && explicit_type->id == ZigTypeIdInvalid) { implicit_type = explicit_type; } else if (var_decl->expr) { - init_value = analyze_const_value_allow_lazy(g, tld_var->base.parent_scope, var_decl->expr, - explicit_type, var_decl->symbol, allow_lazy); + init_value = analyze_const_value(g, tld_var->base.parent_scope, var_decl->expr, explicit_type, var_decl->symbol); assert(init_value); implicit_type = init_value->type; @@ -3337,11 +3193,11 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var, bool allow_lazy) { g->global_vars.append(tld_var); } -void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy) { - bool want_resolve_lazy = tld->resolution == TldResolutionOkLazy && !allow_lazy; - if (tld->resolution != TldResolutionUnresolved && !want_resolve_lazy) +void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node) { + if (tld->resolution != TldResolutionUnresolved) return; + assert(tld->resolution != TldResolutionResolving); tld->resolution = TldResolutionResolving; g->tld_ref_source_node_stack.append(source_node); @@ -3349,11 +3205,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all case TldIdVar: { TldVar *tld_var = (TldVar *)tld; - if (want_resolve_lazy) { - ir_resolve_lazy(g, source_node, tld_var->var->const_value); - } else { - resolve_decl_var(g, tld_var, allow_lazy); - } + resolve_decl_var(g, tld_var); break; } case TldIdFn: @@ -3376,7 +3228,7 @@ void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool all } } - tld->resolution = allow_lazy ? TldResolutionOkLazy : TldResolutionOk; + tld->resolution = TldResolutionOk; g->tld_ref_source_node_stack.pop(); } @@ -4045,7 +3897,7 @@ void semantic_analyze(CodeGen *g) { for (; g->resolve_queue_index < g->resolve_queue.length; g->resolve_queue_index += 1) { Tld *tld = g->resolve_queue.at(g->resolve_queue_index); AstNode *source_node = nullptr; - resolve_top_level_decl(g, tld, source_node, false); + resolve_top_level_decl(g, tld, source_node); } for (; g->fn_defs_index < g->fn_defs.length; g->fn_defs_index += 1) { @@ -5479,9 +5331,6 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) { case ConstValSpecialRuntime: buf_appendf(buf, "(runtime value)"); return; - case ConstValSpecialLazy: - buf_appendf(buf, "(lazy value)"); - return; case ConstValSpecialUndef: buf_appendf(buf, "undefined"); return; @@ -6098,7 +5947,7 @@ bool type_ptr_eql(const ZigType *a, const ZigType *b) { ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { Tld *tld = get_container_scope(codegen->compile_var_import)->decl_table.get(buf_create_from_str(name)); - resolve_top_level_decl(codegen, tld, nullptr, false); + resolve_top_level_decl(codegen, tld, nullptr); assert(tld->id == TldIdVar); TldVar *tld_var = (TldVar *)tld; ConstExprValue *var_value = tld_var->var->const_value; diff --git a/src/analyze.hpp b/src/analyze.hpp index 48f07fd633..a3246fdf4d 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -61,7 +61,7 @@ ZigType *add_source_file(CodeGen *g, ZigPackage *package, Buf *abs_full_path, Bu ZigVar *find_variable(CodeGen *g, Scope *orig_context, Buf *name, ScopeFnDef **crossed_fndef_scope); Tld *find_decl(CodeGen *g, Scope *scope, Buf *name); Tld *find_container_decl(CodeGen *g, ScopeDecls *decls_scope, Buf *name); -void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node, bool allow_lazy); +void resolve_top_level_decl(CodeGen *g, Tld *tld, AstNode *source_node); ZigType *get_src_ptr_type(ZigType *type); ZigType *get_codegen_ptr_type(ZigType *type); diff --git a/src/codegen.cpp b/src/codegen.cpp index f5b15bbeb4..476efd53c1 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3358,8 +3358,6 @@ static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) { static bool value_is_all_undef(ConstExprValue *const_val) { switch (const_val->special) { - case ConstValSpecialLazy: - zig_unreachable(); case ConstValSpecialRuntime: return false; case ConstValSpecialUndef: @@ -5824,7 +5822,6 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ConstExprValue *un static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ConstExprValue *const_val) { switch (const_val->special) { - case ConstValSpecialLazy: case ConstValSpecialRuntime: zig_unreachable(); case ConstValSpecialUndef: @@ -6082,7 +6079,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c assert(type_has_bits(type_entry)); switch (const_val->special) { - case ConstValSpecialLazy: case ConstValSpecialRuntime: zig_unreachable(); case ConstValSpecialUndef: @@ -8249,7 +8245,7 @@ static void gen_root_source(CodeGen *g) { } Tld *panic_tld = find_decl(g, &get_container_scope(import_with_panic)->base, buf_create_from_str("panic")); assert(panic_tld != nullptr); - resolve_top_level_decl(g, panic_tld, nullptr, false); + resolve_top_level_decl(g, panic_tld, nullptr); } diff --git a/src/ir.cpp b/src/ir.cpp index a4d7cf271b..405dc16ca8 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -154,7 +154,6 @@ struct ConstCastBadAllowsZero { enum UndefAllowed { UndefOk, UndefBad, - LazyOk, }; static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, Scope *scope); @@ -10257,57 +10256,32 @@ static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instructio return const_instr; } -static Error ir_resolve_const_val(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, - ConstExprValue *val, UndefAllowed undef_allowed) -{ - Error err; - for (;;) { - switch (val->special) { - case ConstValSpecialStatic: - return ErrorNone; - case ConstValSpecialRuntime: - if (!type_has_bits(val->type)) - return ErrorNone; - - exec_add_error_node(codegen, exec, source_node, - buf_sprintf("unable to evaluate constant expression")); - return ErrorSemanticAnalyzeFail; - case ConstValSpecialUndef: - if (undef_allowed == UndefOk) - return ErrorNone; - - exec_add_error_node(codegen, exec, source_node, - buf_sprintf("use of undefined value here causes undefined behavior")); - return ErrorSemanticAnalyzeFail; - case ConstValSpecialLazy: - if (undef_allowed == LazyOk) - return ErrorNone; - - if ((err = ir_resolve_lazy(codegen, source_node, val))) - return err; - - continue; - } - } -} - static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed) { - Error err; - if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, value->source_node, - &value->value, undef_allowed))) - { - return nullptr; + switch (value->value.special) { + case ConstValSpecialStatic: + return &value->value; + case ConstValSpecialRuntime: + if (!type_has_bits(value->value.type)) { + return &value->value; + } + ir_add_error(ira, value, buf_sprintf("unable to evaluate constant expression")); + return nullptr; + case ConstValSpecialUndef: + if (undef_allowed == UndefOk) { + return &value->value; + } else { + ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior")); + return nullptr; + } } - return &value->value; + zig_unreachable(); } ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy) + IrExecutable *parent_exec, AstNode *expected_type_source_node) { - Error err; - if (expected_type != nullptr && type_is_invalid(expected_type)) return &codegen->invalid_instruction->value; @@ -10352,24 +10326,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod fprintf(stderr, "}\n"); } - ConstExprValue *result = ir_exec_const_result(codegen, analyzed_executable); - - if (!allow_lazy) { - if ((err = ir_resolve_lazy(codegen, node, result))) - return &codegen->invalid_instruction->value; - } - return result; -} - -static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, - ConstExprValue *val) -{ - Error err; - if ((err = ir_resolve_const_val(codegen, exec, source_node, val, UndefBad))) - return codegen->builtin_types.entry_invalid; - - assert(val->data.x_type != nullptr); - return val->data.x_type; + return ir_exec_const_result(codegen, analyzed_executable); } static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { @@ -10382,7 +10339,12 @@ static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { return ira->codegen->builtin_types.entry_invalid; } - return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, &type_value->value); + ConstExprValue *const_val = ir_resolve_const(ira, type_value, UndefBad); + if (!const_val) + return ira->codegen->builtin_types.entry_invalid; + + assert(const_val->data.x_type != nullptr); + return const_val->data.x_type; } static ZigType *ir_resolve_error_set_type(IrAnalyze *ira, IrInstruction *op_source, IrInstruction *type_value) { @@ -11873,38 +11835,33 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc } } -static bool ir_resolve_const_align(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, - ConstExprValue *const_val, uint32_t *out) -{ - Error err; - if ((err = ir_resolve_const_val(codegen, exec, source_node, const_val, UndefBad))) +static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { + if (type_is_invalid(value->value.type)) + return false; + + IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); + if (type_is_invalid(casted_value->value.type)) + return false; + + ConstExprValue *const_val = ir_resolve_const(ira, casted_value, UndefBad); + if (!const_val) return false; uint32_t align_bytes = bigint_as_unsigned(&const_val->data.x_bigint); if (align_bytes == 0) { - exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment must be >= 1")); + ir_add_error(ira, value, buf_sprintf("alignment must be >= 1")); return false; } if (!is_power_of_2(align_bytes)) { - exec_add_error_node(codegen, exec, source_node, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); + ir_add_error(ira, value, buf_sprintf("alignment value %" PRIu32 " is not a power of 2", align_bytes)); return false; } + *out = align_bytes; return true; } -static bool ir_resolve_align(IrAnalyze *ira, IrInstruction *value, uint32_t *out) { - if (type_is_invalid(value->value.type)) - return false; - - IrInstruction *casted_value = ir_implicit_cast(ira, value, get_align_amt_type(ira->codegen)); - if (type_is_invalid(casted_value->value.type)) - return false; - - return ir_resolve_const_align(ira->codegen, ira->new_irb.exec, value->source_node, &casted_value->value, out); -} - static bool ir_resolve_unsigned(IrAnalyze *ira, IrInstruction *value, ZigType *int_type, uint64_t *out) { if (type_is_invalid(value->value.type)) return false; @@ -12072,140 +12029,6 @@ static Buf *ir_resolve_str(IrAnalyze *ira, IrInstruction *value) { return result; } -static ZigType *ir_resolve_lazy_fn_type(CodeGen *codegen, IrExecutable *exec, AstNode *source_node, - LazyValueFnType *lazy_fn_type) -{ - AstNode *proto_node = lazy_fn_type->proto_node; - - FnTypeId fn_type_id = {0}; - init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); - - for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { - AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); - assert(param_node->type == NodeTypeParamDecl); - - bool param_is_var_args = param_node->data.param_decl.is_var_args; - if (param_is_var_args) { - if (fn_type_id.cc == CallingConventionC) { - fn_type_id.param_count = fn_type_id.next_param_index; - continue; - } else if (fn_type_id.cc == CallingConventionUnspecified) { - return get_generic_fn_type(codegen, &fn_type_id); - } else { - zig_unreachable(); - } - } - FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; - param_info->is_noalias = param_node->data.param_decl.is_noalias; - - if (lazy_fn_type->param_types[fn_type_id.next_param_index] == nullptr) { - param_info->type = nullptr; - return get_generic_fn_type(codegen, &fn_type_id); - } else { - ZigType *param_type = ir_resolve_const_type(codegen, exec, source_node, - lazy_fn_type->param_types[fn_type_id.next_param_index]); - if (type_is_invalid(param_type)) - return nullptr; - switch (type_requires_comptime(codegen, param_type)) { - case ReqCompTimeYes: - if (!calling_convention_allows_zig_types(fn_type_id.cc)) { - exec_add_error_node(codegen, exec, source_node, - buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", - buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); - return nullptr; - } - param_info->type = param_type; - fn_type_id.next_param_index += 1; - return get_generic_fn_type(codegen, &fn_type_id); - case ReqCompTimeInvalid: - return nullptr; - case ReqCompTimeNo: - break; - } - if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { - exec_add_error_node(codegen, exec, source_node, - buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", - buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); - return nullptr; - } - param_info->type = param_type; - } - - } - - if (lazy_fn_type->align_val != nullptr) { - if (!ir_resolve_const_align(codegen, exec, source_node, lazy_fn_type->align_val, &fn_type_id.alignment)) - return nullptr; - } - - fn_type_id.return_type = ir_resolve_const_type(codegen, exec, source_node, lazy_fn_type->return_type); - if (type_is_invalid(fn_type_id.return_type)) - return nullptr; - if (fn_type_id.return_type->id == ZigTypeIdOpaque) { - exec_add_error_node(codegen, exec, source_node, - buf_sprintf("return type cannot be opaque")); - return nullptr; - } - - if (lazy_fn_type->async_allocator_type != nullptr) { - fn_type_id.async_allocator_type = ir_resolve_const_type(codegen, exec, source_node, - lazy_fn_type->async_allocator_type); - if (type_is_invalid(fn_type_id.async_allocator_type)) - return nullptr; - } - - return get_fn_type(codegen, &fn_type_id); -} - -Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val) { - Error err; - if (val->special != ConstValSpecialLazy) - return ErrorNone; - IrExecutable *exec = val->data.x_lazy->exec; - switch (val->data.x_lazy->id) { - case LazyValueIdInvalid: - zig_unreachable(); - case LazyValueIdAlignOf: { - LazyValueAlignOf *lazy_align_of = reinterpret_cast(val->data.x_lazy); - if ((err = type_resolve(codegen, lazy_align_of->target_type, ResolveStatusAlignmentKnown))) - return err; - uint64_t align_in_bytes = get_abi_alignment(codegen, lazy_align_of->target_type); - val->special = ConstValSpecialStatic; - assert(val->type->id == ZigTypeIdComptimeInt); - bigint_init_unsigned(&val->data.x_bigint, align_in_bytes); - return ErrorNone; - } - case LazyValueIdSliceType: { - LazyValueSliceType *lazy_slice_type = reinterpret_cast(val->data.x_lazy); - uint32_t align_bytes = 0; - if (lazy_slice_type->align_val != nullptr) { - if (!ir_resolve_const_align(codegen, exec, source_node, lazy_slice_type->align_val, &align_bytes)) - return ErrorSemanticAnalyzeFail; - } - if ((err = type_resolve(codegen, lazy_slice_type->elem_type, ResolveStatusZeroBitsKnown))) - return err; - ZigType *slice_ptr_type = get_pointer_to_type_extra(codegen, lazy_slice_type->elem_type, - lazy_slice_type->is_const, lazy_slice_type->is_volatile, PtrLenUnknown, align_bytes, - 0, 0, lazy_slice_type->is_allowzero); - val->special = ConstValSpecialStatic; - assert(val->type->id == ZigTypeIdMetaType); - val->data.x_type = get_slice_type(codegen, slice_ptr_type); - return ErrorNone; - } - case LazyValueIdFnType: { - ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node, - reinterpret_cast(val->data.x_lazy)); - if (fn_type == nullptr) - return ErrorSemanticAnalyzeFail; - val->special = ConstValSpecialStatic; - assert(val->type->id == ZigTypeIdMetaType); - val->data.x_type = fn_type; - return ErrorNone; - } - } - zig_unreachable(); -} - static IrInstruction *ir_analyze_instruction_add_implicit_return_type(IrAnalyze *ira, IrInstructionAddImplicitReturnType *instruction) { @@ -14179,7 +14002,7 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, if (linkage_makes_it_runtime) goto no_mem_slot; - if (value_is_comptime(var->const_value)) { + if (var->const_value->special == ConstValSpecialStatic) { mem_slot = var->const_value; } else { if (var->mem_slot_index != SIZE_MAX && (comptime_var_mem || var->gen_is_const)) { @@ -14197,7 +14020,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction, case ConstValSpecialRuntime: goto no_mem_slot; case ConstValSpecialStatic: // fallthrough - case ConstValSpecialLazy: // fallthrough case ConstValSpecialUndef: { ConstPtrMut ptr_mut; if (comptime_var_mem) { @@ -14478,7 +14300,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call AstNode *body_node = fn_entry->body_node; result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry, - nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node, false); + nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node); if (inferred_err_set_type != nullptr) { inferred_err_set_type->data.error_set.infer_fn = nullptr; @@ -14674,8 +14496,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen), ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, - nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr, - false); + nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr); IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb, impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr); const_instruction->base.value = *align_result; @@ -15808,7 +15629,7 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira, auto entry = container_scope->decl_table.maybe_get(field_name); Tld *tld = entry ? entry->value : nullptr; if (tld && tld->id == TldIdFn) { - resolve_top_level_decl(ira->codegen, tld, source_instr->source_node, false); + resolve_top_level_decl(ira->codegen, tld, source_instr->source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; TldFn *tld_fn = (TldFn *)tld; @@ -15999,7 +15820,7 @@ static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, static IrInstruction *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source_instruction, Tld *tld) { - resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node, false); + resolve_top_level_decl(ira->codegen, tld, source_instruction->source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; @@ -16655,29 +16476,22 @@ static IrInstruction *ir_analyze_instruction_set_float_mode(IrAnalyze *ira, static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, IrInstructionSliceType *slice_type_instruction) { - IrInstruction *result = ir_const(ira, &slice_type_instruction->base, ira->codegen->builtin_types.entry_type); - result->value.special = ConstValSpecialLazy; - - LazyValueSliceType *lazy_slice_type = allocate(1); - result->value.data.x_lazy = &lazy_slice_type->base; - lazy_slice_type->base.id = LazyValueIdSliceType; - lazy_slice_type->base.exec = ira->new_irb.exec; - + Error err; + uint32_t align_bytes = 0; if (slice_type_instruction->align_value != nullptr) { - lazy_slice_type->align_val = ir_resolve_const(ira, slice_type_instruction->align_value->child, LazyOk); - if (lazy_slice_type->align_val == nullptr) + if (!ir_resolve_align(ira, slice_type_instruction->align_value->child, &align_bytes)) return ira->codegen->invalid_instruction; } - lazy_slice_type->elem_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); - if (type_is_invalid(lazy_slice_type->elem_type)) + ZigType *child_type = ir_resolve_type(ira, slice_type_instruction->child_type->child); + if (type_is_invalid(child_type)) return ira->codegen->invalid_instruction; - lazy_slice_type->is_const = slice_type_instruction->is_const; - lazy_slice_type->is_volatile = slice_type_instruction->is_volatile; - lazy_slice_type->is_allowzero = slice_type_instruction->is_allow_zero; + bool is_const = slice_type_instruction->is_const; + bool is_volatile = slice_type_instruction->is_volatile; + bool is_allow_zero = slice_type_instruction->is_allow_zero; - switch (lazy_slice_type->elem_type->id) { + switch (child_type->id) { case ZigTypeIdInvalid: // handled above zig_unreachable(); case ZigTypeIdUnreachable: @@ -16686,7 +16500,7 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdArgTuple: case ZigTypeIdOpaque: ir_add_error_node(ira, slice_type_instruction->base.source_node, - buf_sprintf("slice of type '%s' not allowed", buf_ptr(&lazy_slice_type->elem_type->name))); + buf_sprintf("slice of type '%s' not allowed", buf_ptr(&child_type->name))); return ira->codegen->invalid_instruction; case ZigTypeIdMetaType: case ZigTypeIdVoid: @@ -16708,7 +16522,14 @@ static IrInstruction *ir_analyze_instruction_slice_type(IrAnalyze *ira, case ZigTypeIdBoundFn: case ZigTypeIdPromise: case ZigTypeIdVector: - return result; + { + if ((err = type_resolve(ira->codegen, child_type, ResolveStatusZeroBitsKnown))) + return ira->codegen->invalid_instruction; + ZigType *slice_ptr_type = get_pointer_to_type_extra(ira->codegen, child_type, + is_const, is_volatile, PtrLenUnknown, align_bytes, 0, 0, is_allow_zero); + ZigType *result_type = get_slice_type(ira->codegen, slice_ptr_type); + return ir_const_type(ira, &slice_type_instruction->base, result_type); + } } zig_unreachable(); } @@ -16815,7 +16636,7 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira, case ZigTypeIdPromise: case ZigTypeIdVector: { - if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown))) + if ((err = ensure_complete_type(ira->codegen, child_type))) return ira->codegen->invalid_instruction; ZigType *result_type = get_array_type(ira->codegen, child_type, size); return ir_const_type(ira, &array_type_instruction->base, result_type); @@ -18172,7 +17993,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, IrInstruction *source_instr, while ((curr_entry = decl_it.next()) != nullptr) { // If the definition is unresolved, force it to be resolved again. if (curr_entry->value->resolution == TldResolutionUnresolved) { - resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node, false); + resolve_top_level_decl(ira->codegen, curr_entry->value, curr_entry->value->source_node); if (curr_entry->value->resolution != TldResolutionOk) { return ErrorSemanticAnalyzeFail; } @@ -19161,7 +18982,7 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct ZigType *void_type = ira->codegen->builtin_types.entry_void; ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type, ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr, - &cimport_scope->buf, block_node, nullptr, nullptr, nullptr, false); + &cimport_scope->buf, block_node, nullptr, nullptr, nullptr); if (type_is_invalid(cimport_result->type)) return ira->codegen->invalid_instruction; @@ -20708,11 +20529,15 @@ static IrInstruction *ir_analyze_instruction_handle(IrAnalyze *ira, IrInstructio } static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstructionAlignOf *instruction) { + Error err; IrInstruction *type_value = instruction->type_value->child; if (type_is_invalid(type_value->value.type)) return ira->codegen->invalid_instruction; ZigType *type_entry = ir_resolve_type(ira, type_value); + if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusAlignmentKnown))) + return ira->codegen->invalid_instruction; + switch (type_entry->id) { case ZigTypeIdInvalid: zig_unreachable(); @@ -20744,25 +20569,12 @@ static IrInstruction *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruct case ZigTypeIdUnion: case ZigTypeIdFn: case ZigTypeIdVector: - break; + { + uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); + return ir_const_unsigned(ira, &instruction->base, align_in_bytes); + } } - if (type_is_resolved(type_entry, ResolveStatusAlignmentKnown)) { - uint64_t align_in_bytes = get_abi_alignment(ira->codegen, type_entry); - return ir_const_unsigned(ira, &instruction->base, align_in_bytes); - } - // Here we create a lazy value in order to avoid resolving the alignment of the type - // immediately. This avoids false positive dependency loops such as: - // const Node = struct { - // field: []align(@alignOf(Node)) Node, - // }; - LazyValueAlignOf *lazy_align_of = allocate(1); - lazy_align_of->base.id = LazyValueIdAlignOf; - lazy_align_of->base.exec = ira->new_irb.exec; - lazy_align_of->target_type = type_entry; - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int); - result->value.special = ConstValSpecialLazy; - result->value.data.x_lazy = &lazy_align_of->base; - return result; + zig_unreachable(); } static IrInstruction *ir_analyze_instruction_overflow_op(IrAnalyze *ira, IrInstructionOverflowOp *instruction) { @@ -21017,77 +20829,96 @@ static IrInstruction *ir_analyze_instruction_fn_proto(IrAnalyze *ira, IrInstruct AstNode *proto_node = instruction->base.source_node; assert(proto_node->type == NodeTypeFnProto); - IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type); - result->value.special = ConstValSpecialLazy; - - LazyValueFnType *lazy_fn_type = allocate(1); - result->value.data.x_lazy = &lazy_fn_type->base; - lazy_fn_type->base.id = LazyValueIdFnType; - lazy_fn_type->base.exec = ira->new_irb.exec; - if (proto_node->data.fn_proto.auto_err_set) { ir_add_error(ira, &instruction->base, buf_sprintf("inferring error set of return type valid only for function definitions")); return ira->codegen->invalid_instruction; } - size_t param_count = proto_node->data.fn_proto.params.length; - lazy_fn_type->proto_node = proto_node; - lazy_fn_type->param_types = allocate(param_count); + FnTypeId fn_type_id = {0}; + init_fn_type_id(&fn_type_id, proto_node, proto_node->data.fn_proto.params.length); - for (size_t i = 0; i < param_count; i += 1) { - AstNode *param_node = proto_node->data.fn_proto.params.at(i); + for (; fn_type_id.next_param_index < fn_type_id.param_count; fn_type_id.next_param_index += 1) { + AstNode *param_node = proto_node->data.fn_proto.params.at(fn_type_id.next_param_index); assert(param_node->type == NodeTypeParamDecl); bool param_is_var_args = param_node->data.param_decl.is_var_args; - lazy_fn_type->is_var_args = true; if (param_is_var_args) { - if (proto_node->data.fn_proto.cc == CallingConventionC) { - break; - } else if (proto_node->data.fn_proto.cc == CallingConventionUnspecified) { - lazy_fn_type->is_generic = true; - return result; + if (fn_type_id.cc == CallingConventionC) { + fn_type_id.param_count = fn_type_id.next_param_index; + continue; + } else if (fn_type_id.cc == CallingConventionUnspecified) { + return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); } else { zig_unreachable(); } } + FnTypeParamInfo *param_info = &fn_type_id.param_info[fn_type_id.next_param_index]; + param_info->is_noalias = param_node->data.param_decl.is_noalias; - if (instruction->param_types[i] == nullptr) { - lazy_fn_type->is_generic = true; - return result; + if (instruction->param_types[fn_type_id.next_param_index] == nullptr) { + param_info->type = nullptr; + return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + } else { + IrInstruction *param_type_value = instruction->param_types[fn_type_id.next_param_index]->child; + if (type_is_invalid(param_type_value->value.type)) + return ira->codegen->invalid_instruction; + ZigType *param_type = ir_resolve_type(ira, param_type_value); + switch (type_requires_comptime(ira->codegen, param_type)) { + case ReqCompTimeYes: + if (!calling_convention_allows_zig_types(fn_type_id.cc)) { + ir_add_error(ira, param_type_value, + buf_sprintf("parameter of type '%s' not allowed in function with calling convention '%s'", + buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); + return ira->codegen->invalid_instruction; + } + param_info->type = param_type; + fn_type_id.next_param_index += 1; + return ir_const_type(ira, &instruction->base, get_generic_fn_type(ira->codegen, &fn_type_id)); + case ReqCompTimeInvalid: + return ira->codegen->invalid_instruction; + case ReqCompTimeNo: + break; + } + if (!type_has_bits(param_type) && !calling_convention_allows_zig_types(fn_type_id.cc)) { + ir_add_error(ira, param_type_value, + buf_sprintf("parameter of type '%s' has 0 bits; not allowed in function with calling convention '%s'", + buf_ptr(¶m_type->name), calling_convention_name(fn_type_id.cc))); + return ira->codegen->invalid_instruction; + } + param_info->type = param_type; } - IrInstruction *param_type_value = instruction->param_types[i]->child; - if (type_is_invalid(param_type_value->value.type)) - return ira->codegen->invalid_instruction; - ConstExprValue *param_type_val = ir_resolve_const(ira, param_type_value, LazyOk); - if (param_type_val == nullptr) - return ira->codegen->invalid_instruction; - lazy_fn_type->param_types[i] = param_type_val; } if (instruction->align_value != nullptr) { - lazy_fn_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk); - if (lazy_fn_type->align_val == nullptr) + if (!ir_resolve_align(ira, instruction->align_value->child, &fn_type_id.alignment)) return ira->codegen->invalid_instruction; } - lazy_fn_type->return_type = ir_resolve_const(ira, instruction->return_type->child, LazyOk); - if (lazy_fn_type->return_type == nullptr) + IrInstruction *return_type_value = instruction->return_type->child; + fn_type_id.return_type = ir_resolve_type(ira, return_type_value); + if (type_is_invalid(fn_type_id.return_type)) return ira->codegen->invalid_instruction; + if (fn_type_id.return_type->id == ZigTypeIdOpaque) { + ir_add_error(ira, instruction->return_type, + buf_sprintf("return type cannot be opaque")); + return ira->codegen->invalid_instruction; + } - if (proto_node->data.fn_proto.cc == CallingConventionAsync) { + if (fn_type_id.cc == CallingConventionAsync) { if (instruction->async_allocator_type_value == nullptr) { ir_add_error(ira, &instruction->base, buf_sprintf("async fn proto missing allocator type")); return ira->codegen->invalid_instruction; } - lazy_fn_type->async_allocator_type = ir_resolve_const(ira, instruction->async_allocator_type_value->child, LazyOk); - if (lazy_fn_type->async_allocator_type == nullptr) + IrInstruction *async_allocator_type_value = instruction->async_allocator_type_value->child; + fn_type_id.async_allocator_type = ir_resolve_type(ira, async_allocator_type_value); + if (type_is_invalid(fn_type_id.async_allocator_type)) return ira->codegen->invalid_instruction; } - return result; + return ir_const_type(ira, &instruction->base, get_fn_type(ira->codegen, &fn_type_id)); } static IrInstruction *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstructionTestComptime *instruction) { @@ -21756,11 +21587,8 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou val->type->data.vector.len); case ZigTypeIdEnum: switch (val->type->data.enumeration.layout) { - case ContainerLayoutAuto: { - opt_ir_add_error_node(ira, codegen, source_node, - buf_sprintf("compiler bug: TODO: implement enum byte reinterpretation")); - return ErrorSemanticAnalyzeFail; - } + case ContainerLayoutAuto: + zig_panic("TODO buf_read_value_bytes enum auto"); case ContainerLayoutPacked: zig_panic("TODO buf_read_value_bytes enum packed"); case ContainerLayoutExtern: { @@ -22056,7 +21884,7 @@ static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira, Tld *tld = instruction->tld; LVal lval = instruction->lval; - resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node, true); + resolve_top_level_decl(ira->codegen, tld, instruction->base.source_node); if (tld->resolution == TldResolutionInvalid) return ira->codegen->invalid_instruction; diff --git a/src/ir.hpp b/src/ir.hpp index bf65328f70..0b85ad2c55 100644 --- a/src/ir.hpp +++ b/src/ir.hpp @@ -16,8 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry); ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node, ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota, ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name, - IrExecutable *parent_exec, AstNode *expected_type_source_node, bool allow_lazy); -Error ir_resolve_lazy(CodeGen *codegen, AstNode *source_node, ConstExprValue *val); + IrExecutable *parent_exec, AstNode *expected_type_source_node); ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable, ZigType *expected_type, AstNode *expected_type_source_node); -- cgit v1.2.3 From d7bc7635c0e3324fa08fc809ec21ba014464ea03 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Apr 2019 18:07:07 -0400 Subject: put the hack from master branch back in --- src/analyze.cpp | 83 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 44 insertions(+), 39 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 0f1767c76d..2c501b9a70 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -2038,6 +2038,8 @@ 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) @@ -2047,13 +2049,12 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { assert(decl_node->type == NodeTypeContainerDecl); if (struct_type->data.structure.resolve_loop_flag) { - if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - ErrorMsg *msg = add_node_error(g, decl_node, - buf_sprintf("struct '%s' depends on its own size", buf_ptr(&struct_type->name))); - emit_error_notes_for_ref_stack(g, msg); - } - return ErrorSemanticAnalyzeFail; + // 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; } struct_type->data.structure.resolve_loop_flag = true; @@ -2097,6 +2098,21 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { 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; @@ -2171,49 +2187,39 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { struct_type->data.structure.resolve_loop_flag = true; assert(decl_node->type == NodeTypeContainerDecl); - size_t abi_align = 0; size_t field_count = struct_type->data.structure.src_field_count; bool packed = struct_type->data.structure.layout == ContainerLayoutPacked; for (size_t i = 0; i < field_count; i += 1) { - AstNode *field_source_node = decl_node->data.container_decl.fields.at(i); TypeStructField *field = &struct_type->data.structure.fields[i]; - ZigType *field_type = field->type_entry; - assert(field_type != nullptr); - - if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { - 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_source_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 (packed) { - if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) { - struct_type->data.structure.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } - } - if (field->gen_index == SIZE_MAX) continue; + size_t this_field_align; if (packed) { // TODO: https://github.com/ziglang/zig/issues/1512 - if (1 > abi_align) { - abi_align = 1; - } + 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 + // and make sure it is fixed in stage2. This workaround is for when + // there is a false positive of a dependency loop, of alignment depending + // 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 + } else if (field->type_entry == nullptr) { + this_field_align = g->builtin_types.entry_usize->abi_align; } else { - // TODO: https://github.com/ziglang/zig/issues/1512 - if (field_type->abi_align > abi_align) { - abi_align = field_type->abi_align; + if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { + struct_type->data.structure.resolve_status = ResolveStatusInvalid; + return ErrorSemanticAnalyzeFail; } + this_field_align = field->type_entry->abi_align; + } + + // TODO: https://github.com/ziglang/zig/issues/1512 + if (this_field_align > struct_type->abi_align) { + struct_type->abi_align = this_field_align; } } @@ -2224,7 +2230,6 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { } struct_type->data.structure.resolve_status = ResolveStatusAlignmentKnown; - struct_type->abi_align = abi_align; return ErrorNone; } -- cgit v1.2.3 From 30b2fb2fb545794beb44f80af308c4280d94deba Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 1 Apr 2019 19:53:52 -0400 Subject: bug fixes --- src/analyze.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 2c501b9a70..78680e8b6b 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1642,6 +1642,7 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { field->bit_offset_in_host = 0; } else { // This is a byte-aligned field (both start and end) in a packed struct. + 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 @@ -2050,8 +2051,8 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { 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->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; @@ -6335,15 +6336,25 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { assert(struct_type->data.structure.resolve_status >= ResolveStatusSizeKnown); assert(struct_type->data.structure.fields || struct_type->data.structure.src_field_count == 0); + // Do this early for the benefit of recursion. + struct_type->llvm_type = type_has_bits(struct_type) ? + LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType(); AstNode *decl_node = struct_type->data.structure.decl_node; assert(decl_node->type == NodeTypeContainerDecl); + Scope *scope = &struct_type->data.structure.decls_scope->base; + ZigType *import = get_scope_import(scope); + unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); + struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, + dwarf_kind, buf_ptr(&struct_type->name), + ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1)); + + 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; @@ -6394,17 +6405,11 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { gen_field_index += 1; } - struct_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)); - LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed); + 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); - ZigType *import = get_scope_import(scope); - unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); - struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, - dwarf_kind, buf_ptr(&struct_type->name), - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1)); - 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); @@ -6501,6 +6506,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { get_llvm_di_type(g, tag_int_type), ""); enum_type->llvm_di_type = tag_di_type; + enum_type->llvm_type = get_llvm_type(g, tag_int_type); } static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { @@ -6922,7 +6928,7 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_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; + 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) { @@ -6945,7 +6951,6 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { static void resolve_llvm_types(CodeGen *g, ZigType *type) { assert(type_is_resolved(type, ResolveStatusSizeKnown)); - assert(type_has_bits(type)); switch (type->id) { case ZigTypeIdInvalid: case ZigTypeIdFloat: -- cgit v1.2.3 From ddb8aa73f542d3432538e6de466ac216c89fd12b Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 11:11:42 -0400 Subject: more regression fixes --- src/analyze.cpp | 121 +++++++++++++++++++++++++++++++++----------- src/codegen.cpp | 36 ++++++++----- src/ir.cpp | 8 ++- std/special/test_runner.zig | 2 +- 4 files changed, 117 insertions(+), 50 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 78680e8b6b..c7fac471ec 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -343,8 +343,9 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) { } ZigType *entry = new_type_table_entry(ZigTypeIdPromise); - entry->abi_size = g->pointer_size_bytes; - entry->size_in_bits = g->pointer_size_bytes * 8; + 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) { @@ -775,9 +776,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->abi_size = 0; - bound_fn_type->size_in_bits = 0; - bound_fn_type->abi_align = 0; buf_resize(&bound_fn_type->name, 0); buf_appendf(&bound_fn_type->name, "(bound %s)", buf_ptr(&fn_type->name)); @@ -1248,6 +1246,9 @@ ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) { 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; + 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; } @@ -1597,7 +1598,16 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { uint32_t *host_int_bytes = packed ? allocate(struct_type->data.structure.gen_field_count) : nullptr; - // Compute offsets for all the fields. + // 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; + return ErrorSemanticAnalyzeFail; + } + } + size_t packed_bits_offset = 0; size_t next_offset = 0; size_t first_packed_bits_offset_misalign = SIZE_MAX; @@ -1739,6 +1749,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { // 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)) { @@ -1788,6 +1799,7 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { 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); @@ -1827,13 +1839,18 @@ static Error resolve_union_type(CodeGen *g, ZigType *union_type) { union_size_in_bits = max(union_size_in_bits, field_type->size_in_bits); } + // 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); + } + // 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; - ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; if (tag_type != nullptr && type_has_bits(tag_type)) { if ((err = type_resolve(g, tag_type, ResolveStatusSizeKnown))) { union_type->data.unionation.resolve_status = ResolveStatusInvalid; @@ -6340,16 +6357,25 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { struct_type->llvm_type = type_has_bits(struct_type) ? LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType(); AstNode *decl_node = struct_type->data.structure.decl_node; - assert(decl_node->type == NodeTypeContainerDecl); - Scope *scope = &struct_type->data.structure.decls_scope->base; - ZigType *import = get_scope_import(scope); + 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; + } unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); struct_type->llvm_di_type = ZigLLVMCreateReplaceableCompositeType(g->dbuilder, dwarf_kind, buf_ptr(&struct_type->name), - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1)); - - + di_scope, di_file, line); size_t field_count = struct_type->data.structure.src_field_count; size_t gen_field_count = struct_type->data.structure.gen_field_count; @@ -6412,7 +6438,6 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { ZigLLVMDIType **di_element_types = allocate(debug_field_count); 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) { @@ -6445,9 +6470,16 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { 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), - import->data.structure.root_struct->di_file, (unsigned)(field_node->line + 1), + di_file, line, debug_size_in_bits, debug_align_in_bits, debug_offset_in_bits, @@ -6459,9 +6491,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { uint64_t debug_size_in_bits = get_store_size_in_bits(struct_type->size_in_bits); uint64_t debug_align_in_bits = 8*struct_type->abi_align; ZigLLVMDIType *replacement_di_type = ZigLLVMCreateDebugStructType(g->dbuilder, - ZigLLVMFileToScope(import->data.structure.root_struct->di_file), + di_scope, buf_ptr(&struct_type->name), - import->data.structure.root_struct->di_file, (unsigned)(decl_node->line + 1), + di_file, line, debug_size_in_bits, debug_align_in_bits, 0, nullptr, di_element_types, (int)debug_field_count, 0, nullptr, ""); @@ -6512,19 +6544,14 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { ZigType *most_aligned_union_member = union_type->data.unionation.most_aligned_union_member; ZigType *tag_type = union_type->data.unionation.tag_type; - if (tag_type == nullptr || !type_has_bits(tag_type)) { - assert(most_aligned_union_member != nullptr); - assert(union_type->data.unionation.union_abi_size >= most_aligned_union_member->abi_size); - union_type->llvm_type = get_llvm_type(g, most_aligned_union_member); - union_type->llvm_di_type = get_llvm_di_type(g, most_aligned_union_member); - return; - } 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); return; } + // Do this first for the benefit of recursive calls. + union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); Scope *scope = &union_type->data.unionation.decls_scope->base; ZigType *import = get_scope_import(scope); AstNode *decl_node = union_type->data.unionation.decl_node; @@ -6535,6 +6562,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { ZigLLVMFileToScope(import->data.structure.root_struct->di_file), import->data.structure.root_struct->di_file, (unsigned)(line + 1)); + 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; @@ -6555,7 +6583,40 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { 0, get_llvm_di_type(g, union_field->type_entry)); } - union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); + + 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; + (void)get_llvm_type(g, most_aligned_union_member); + 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; + return; + } LLVMTypeRef union_type_ref; size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size; @@ -7018,8 +7079,8 @@ LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) { resolve_llvm_types(g, type); assert(type->llvm_type != nullptr); assert(type->llvm_di_type != nullptr); - assert(type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); - assert(type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); + 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; } @@ -7029,7 +7090,7 @@ ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type) { resolve_llvm_types(g, type); assert(type->llvm_type != nullptr); assert(type->llvm_di_type != nullptr); - assert(type->abi_size == LLVMABISizeOfType(g->target_data_ref, type->llvm_type)); - assert(type->abi_align == LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type)); + 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_di_type; } diff --git a/src/codegen.cpp b/src/codegen.cpp index 476efd53c1..a7863c45af 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -498,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, @@ -6292,14 +6294,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c } case ZigTypeIdUnion: { - BREAKPOINT; // TODO rework this logic to take into account the new layout - // Force type_entry->data.unionation.union_llvm_type to get resolved (void)get_llvm_type(g, type_entry); - LLVMTypeRef union_type_ref = type_entry->data.unionation.union_llvm_type; - assert(union_type_ref != nullptr); - if (type_entry->data.unionation.gen_field_count == 0) { if (type_entry->data.unionation.tag_type == nullptr) { return nullptr; @@ -6309,6 +6306,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c } } + 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; @@ -7740,8 +7740,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; } @@ -8148,6 +8155,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) { @@ -8155,14 +8164,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); @@ -8194,7 +8202,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 405dc16ca8..ea7a27f312 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -8945,11 +8945,9 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp err_set_type->data.error_set.err_count = intersection_list.length; err_set_type->data.error_set.errors = intersection_list.items; - if (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; - } + 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, "}"); diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index 857739e82d..36b098bd61 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 { -- cgit v1.2.3 From 5aee17e888c0db7ed0d220334f3adeff6e323cb2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 14:44:25 -0400 Subject: regression fixes and fix packed struct abi size --- doc/langref.html.in | 8 +- src/all_types.hpp | 2 + src/analyze.cpp | 259 +++++++++++++++++++++++++--------------- test/stage1/behavior/struct.zig | 16 ++- 4 files changed, 179 insertions(+), 106 deletions(-) (limited to 'src/analyze.cpp') diff --git a/doc/langref.html.in b/doc/langref.html.in index 9ea5028282..23d63f2db2 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 5d06f7e883..d5d708fd09 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1079,6 +1079,8 @@ enum ResolveStatus { ResolveStatusZeroBitsKnown, ResolveStatusAlignmentKnown, ResolveStatusSizeKnown, + ResolveStatusLLVMFwdDecl, + ResolveStatusLLVMFull, }; struct ZigPackage { diff --git a/src/analyze.cpp b/src/analyze.cpp index c7fac471ec..a82d8efd7d 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -27,6 +27,7 @@ static Error ATTRIBUTE_MUST_USE resolve_enum_zero_bits(CodeGen *g, ZigType *enum 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; @@ -278,6 +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; + case ResolveStatusLLVMFwdDecl: + case ResolveStatusLLVMFull: + return type_entry->llvm_di_type != nullptr; } zig_unreachable(); case ZigTypeIdOpaque: @@ -1120,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, @@ -1559,8 +1564,21 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na return struct_type; } -static size_t get_store_size_in_bits(size_t size_in_bits) { - return ((size_in_bits + 7) / 8) * 8; +static size_t get_store_size_bytes(size_t size_in_bits) { + return (size_in_bits + 7) / 8; +} + +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); +} + +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) { @@ -1637,17 +1655,18 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { 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; - if (get_store_size_in_bits(full_bit_count) == full_bit_count) { - // next field recovers store alignment - host_int_bytes[gen_field_index] = full_bit_count / 8; + 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_bit_count / 8, 1); + 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 (get_store_size_in_bits(field_type->size_in_bits) != 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; field->bit_offset_in_host = 0; } else { @@ -1676,9 +1695,9 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) { } if (first_packed_bits_offset_misalign != SIZE_MAX) { size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; - size_t store_bit_count = get_store_size_in_bits(full_bit_count); - next_offset = next_field_offset(next_offset, abi_align, store_bit_count / 8, 1); - host_int_bytes[gen_field_index] = store_bit_count / 8; + 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; } @@ -4986,6 +5005,10 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { return resolve_union_type(g, ty); } return ErrorNone; + case ResolveStatusLLVMFwdDecl: + case ResolveStatusLLVMFull: + resolve_llvm_types(g, ty, status); + return ErrorNone; } zig_unreachable(); } @@ -6223,57 +6246,68 @@ Buf *type_h_name(ZigType *t) { return type_bare_name(t); } -static void resolve_llvm_types_slice(CodeGen *g, ZigType *type) { +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; + 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 (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); - - type->llvm_type = get_llvm_type(g, peer_slice_type); - type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); - } - - // 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) + if (type->data.structure.resolve_status < ResolveStatusLLVMFwdDecl) { + 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 *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, + 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); type->llvm_type = get_llvm_type(g, peer_slice_type); type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); + done = true; } - } - if (type->llvm_type != nullptr) - return; + // 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); + + type->llvm_type = get_llvm_type(g, peer_slice_type); + type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); + done = true; + } + } - ZigType *usize_type = g->builtin_types.entry_usize; - LLVMTypeRef usize_llvm_type = get_llvm_type(g, usize_type); - ZigLLVMDIType *usize_llvm_di_type = get_llvm_di_type(g, usize_type); + if (done) { + type->data.structure.resolve_status = ResolveStatusLLVMFull; + return; + } - type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name)); + type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&type->name)); - 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); + 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[] = { @@ -6304,6 +6338,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type) { ZigLLVMReplaceTemporary(g->dbuilder, type->llvm_di_type, replacement_di_type); type->llvm_di_type = replacement_di_type; + type->data.structure.resolve_status = ResolveStatusLLVMFull; return; } @@ -6345,17 +6380,16 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type) { 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) { +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; - // Do this early for the benefit of recursion. - struct_type->llvm_type = type_has_bits(struct_type) ? - LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&struct_type->name)) : LLVMVoidType(); AstNode *decl_node = struct_type->data.structure.decl_node; ZigLLVMDIFile *di_file; ZigLLVMDIScope *di_scope; @@ -6372,10 +6406,18 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { di_scope = ZigLLVMCompileUnitToScope(g->compile_unit); line = 0; } - 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); + + 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; @@ -6402,14 +6444,15 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { // 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; - if (get_store_size_in_bits(full_bit_count) == full_bit_count) { - // next field recovers store alignment + 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_store_size_in_bits(field_type->size_in_bits) != 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; } else { // This is a byte-aligned field (both start and end) in a packed struct. @@ -6426,8 +6469,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { } if (first_packed_bits_offset_misalign != SIZE_MAX) { size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign; - size_t store_bit_count = get_store_size_in_bits(full_bit_count); - 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); + element_types[gen_field_index] = LLVMIntType((unsigned)full_abi_size * 8); gen_field_index += 1; } @@ -6466,7 +6509,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { 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 = get_store_size_in_bits(field_type->size_in_bits); + 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; } @@ -6488,7 +6531,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { debug_field_index += 1; } - uint64_t debug_size_in_bits = get_store_size_in_bits(struct_type->size_in_bits); + 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, @@ -6500,11 +6543,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type) { 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; uint32_t field_count = enum_type->data.enumeration.src_field_count; @@ -6541,27 +6586,34 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { enum_type->llvm_type = get_llvm_type(g, tag_int_type); } -static void resolve_llvm_types_union(CodeGen *g, ZigType *union_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; } - // Do this first for the benefit of recursive calls. - union_type->llvm_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(&union_type->name)); Scope *scope = &union_type->data.unionation.decls_scope->base; ZigType *import = get_scope_import(scope); AstNode *decl_node = union_type->data.unionation.decl_node; - 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)); + 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); @@ -6615,6 +6667,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { 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; } @@ -6685,9 +6738,12 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type) { 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; + ZigType *elem_type = type->data.pointer.child_type; if (type->data.pointer.is_const || type->data.pointer.is_volatile || @@ -6702,10 +6758,11 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { } if (type->data.pointer.host_int_bytes == 0) { - type->llvm_type = LLVMPointerType(get_llvm_type(g, elem_type), 0); - uint64_t debug_size_in_bits = 8*LLVMStoreSizeOfType(g->target_data_ref, type->llvm_type); - uint64_t debug_align_in_bits = 8*LLVMABIAlignmentOfType(g->target_data_ref, type->llvm_type); - type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, get_llvm_di_type(g, elem_type), + 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)); } else { ZigType *host_int_type = get_int_type(g, false, type->data.pointer.host_int_bytes * 8); @@ -6719,6 +6776,8 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { } static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + unsigned dwarf_tag; if (type->data.integral.is_signed) { if (type->size_in_bits == 8) { @@ -6739,6 +6798,8 @@ static void resolve_llvm_types_integer(CodeGen *g, ZigType *type) { } 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); @@ -6807,6 +6868,8 @@ static void resolve_llvm_types_optional(CodeGen *g, ZigType *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; @@ -6874,6 +6937,8 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) { } static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { + if (type->llvm_di_type != nullptr) return; + ZigType *elem_type = type->data.array.child_type; // TODO https://github.com/ziglang/zig/issues/1424 @@ -6887,6 +6952,8 @@ static void resolve_llvm_types_array(CodeGen *g, ZigType *type) { } 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; @@ -7010,16 +7077,12 @@ static void resolve_llvm_types_anyerror(CodeGen *g) { get_llvm_di_type(g, g->err_tag_type), ""); } -static void resolve_llvm_types(CodeGen *g, ZigType *type) { - assert(type_is_resolved(type, ResolveStatusSizeKnown)); +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 ZigTypeIdFloat: - case ZigTypeIdOpaque: case ZigTypeIdMetaType: - case ZigTypeIdVoid: - case ZigTypeIdBool: - case ZigTypeIdUnreachable: case ZigTypeIdComptimeFloat: case ZigTypeIdComptimeInt: case ZigTypeIdEnumLiteral: @@ -7028,18 +7091,26 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type) { 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); + return resolve_llvm_types_slice(g, type, wanted_resolve_status); else - return resolve_llvm_types_struct(g, type); + 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); + 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); @@ -7056,6 +7127,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *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); } @@ -7064,6 +7137,8 @@ static void resolve_llvm_types(CodeGen *g, ZigType *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); @@ -7074,23 +7149,13 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type) { } LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type) { - if (type->llvm_type != nullptr) - return type->llvm_type; - resolve_llvm_types(g, type); - assert(type->llvm_type != nullptr); - assert(type->llvm_di_type != nullptr); + 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) { - if (type->llvm_di_type != nullptr) - return type->llvm_di_type; - resolve_llvm_types(g, type); - assert(type->llvm_type != nullptr); - assert(type->llvm_di_type != nullptr); - 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)); + assertNoError(type_resolve(g, type, ResolveStatusLLVMFull)); return type->llvm_di_type; } diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index aa77892602..62fb41ca28 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); -- cgit v1.2.3 From 4c38a8cce17979a9e8ce15c8ccfe1b7ccdb59832 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 17:12:09 -0400 Subject: more regression fixes. empty test passes again --- src/analyze.cpp | 93 ++++++++++++++++++++++++++++++++------------------------ src/codegen.cpp | 11 ++++--- src/zig_llvm.cpp | 1 + 3 files changed, 62 insertions(+), 43 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index a82d8efd7d..ba664fc19e 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6252,53 +6252,55 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa 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; - 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) { - 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) + 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 *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false, + 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); - type->llvm_type = get_llvm_type(g, peer_slice_type); - type->llvm_di_type = get_llvm_di_type(g, peer_slice_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); - - type->llvm_type = get_llvm_type(g, peer_slice_type); - type->llvm_di_type = get_llvm_di_type(g, peer_slice_type); - done = true; - } - } + if (done) return; - if (done) { - type->data.structure.resolve_status = ResolveStatusLLVMFull; - 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, @@ -6551,6 +6553,12 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { assert(enum_type->data.enumeration.complete); if (enum_type->llvm_di_type != nullptr) return; + if (!type_has_bits(enum_type)) { + enum_type->llvm_type = g->builtin_types.entry_void->llvm_type; + enum_type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type; + return; + } + uint32_t field_count = enum_type->data.enumeration.src_field_count; assert(enum_type->data.enumeration.fields); @@ -6569,6 +6577,7 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { } 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 AstNode *decl_node = enum_type->data.enumeration.decl_node; @@ -6583,7 +6592,6 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { get_llvm_di_type(g, tag_int_type), ""); enum_type->llvm_di_type = tag_di_type; - enum_type->llvm_type = get_llvm_type(g, tag_int_type); } static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveStatus wanted_resolve_status) { @@ -6764,6 +6772,7 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { 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); @@ -6939,6 +6948,12 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *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 @@ -7014,7 +7029,7 @@ static void resolve_llvm_types_fn(CodeGen *g, ZigType *fn_type) { gen_param_info->src_index = i; gen_param_info->gen_index = SIZE_MAX; - if (!type_has_bits(type_entry)) + if (is_c_abi || !type_has_bits(type_entry)) continue; ZigType *gen_type; diff --git a/src/codegen.cpp b/src/codegen.cpp index a7863c45af..33cbdade23 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3566,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); @@ -5695,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); @@ -6855,9 +6858,9 @@ static void do_code_gen(CodeGen *g) { } 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), - get_llvm_di_type(g, gen_type), !g->strip_debug_symbols, 0, (unsigned)(gen_info->gen_index)); + 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)); } } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 93c34f0385..7d45871b2a 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, -- cgit v1.2.3 From cb0241fe44e347bd14fd5568a240f1237dafacc3 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 17:25:44 -0400 Subject: behavior tests passing again --- src/analyze.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index ba664fc19e..c3fb774a50 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -4047,7 +4047,6 @@ bool handle_is_ptr(ZigType *type_entry) { return false; case ZigTypeIdArray: case ZigTypeIdStruct: - case ZigTypeIdUnion: return type_has_bits(type_entry); case ZigTypeIdErrorUnion: return type_has_bits(type_entry->data.error_union.payload_type); @@ -4055,6 +4054,8 @@ bool handle_is_ptr(ZigType *type_entry) { return type_has_bits(type_entry->data.maybe.child_type) && !type_is_nonnull_ptr(type_entry->data.maybe.child_type) && type_entry->data.maybe.child_type->id != ZigTypeIdErrorSet; + case ZigTypeIdUnion: + return type_has_bits(type_entry) && type_entry->data.unionation.gen_field_count != 0; } zig_unreachable(); -- cgit v1.2.3 From 9780fd59f063d23e69ceadf4305453531b704c11 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 17:40:01 -0400 Subject: put the alignment hack in for unions too. fixes std tests --- src/analyze.cpp | 35 +++++++++++++++++++++++------------ 1 file changed, 23 insertions(+), 12 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index c3fb774a50..69a69b51a1 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1742,26 +1742,36 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { 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; 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; + TypeUnionField *field = &union_type->data.unionation.fields[i]; + if (field->gen_index == UINT32_MAX) + continue; - if ((err = type_resolve(g, field_type, ResolveStatusAlignmentKnown))) { - union_type->data.unionation.resolve_status = ResolveStatusInvalid; - return ErrorSemanticAnalyzeFail; - } + 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; + } - if (type_is_invalid(union_type)) - return ErrorSemanticAnalyzeFail; + if (union_type->data.unionation.resolve_status == ResolveStatusInvalid) + return ErrorSemanticAnalyzeFail; - if (!type_has_bits(field_type)) - continue; + this_field_align = field->type_entry->abi_align; + } if (most_aligned_union_member == nullptr || - field_type->abi_align > most_aligned_union_member->abi_align) + this_field_align > most_aligned_union_member->abi_align) { - most_aligned_union_member = field_type; + most_aligned_union_member = field->type_entry; } } @@ -2395,6 +2405,7 @@ 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) { -- cgit v1.2.3 From d577dde636173e5ec799e67ead32722ac59148db Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 18:11:53 -0400 Subject: passing all tests --- src/analyze.cpp | 4 ++-- src/codegen.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 69a69b51a1..614f907f70 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -1731,7 +1731,7 @@ static Error resolve_union_alignment(CodeGen *g, ZigType *union_type) { 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' depends on its own alignment", buf_ptr(&union_type->name))); + buf_sprintf("union '%s' contains itself", buf_ptr(&union_type->name))); emit_error_notes_for_ref_stack(g, msg); } return ErrorSemanticAnalyzeFail; @@ -2225,7 +2225,7 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { if (struct_type->data.structure.resolve_status != ResolveStatusInvalid) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; ErrorMsg *msg = add_node_error(g, decl_node, - buf_sprintf("struct '%s' depends on its own alignment", buf_ptr(&struct_type->name))); + buf_sprintf("struct '%s' contains itself", buf_ptr(&struct_type->name))); emit_error_notes_for_ref_stack(g, msg); } return ErrorSemanticAnalyzeFail; diff --git a/src/codegen.cpp b/src/codegen.cpp index 33cbdade23..5573346452 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -6737,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; -- cgit v1.2.3 From e9dc504141a18e315fe547c54885811927608319 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 18:30:53 -0400 Subject: avoid tripping assertion for setting struct body twice --- src/analyze.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 614f907f70..ea31717ca2 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6443,6 +6443,16 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS 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; @@ -6661,6 +6671,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size; (void)get_llvm_type(g, most_aligned_union_member); + if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return; if (padding_bytes > 0) { ZigType *u8_type = get_int_type(g, false, 8); ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); -- cgit v1.2.3 From 15bd4aa54fcebc9f8296be6138c7775f23082746 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 18:43:25 -0400 Subject: fix setting union body twice --- src/analyze.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index ea31717ca2..c1640bd19b 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6653,6 +6653,9 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta 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); @@ -6662,7 +6665,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta store_size_in_bits, abi_align_in_bits, 0, - 0, get_llvm_di_type(g, union_field->type_entry)); + 0, field_di_type); } @@ -6670,8 +6673,6 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta assert(most_aligned_union_member != nullptr); size_t padding_bytes = union_type->data.unionation.union_abi_size - most_aligned_union_member->abi_size; - (void)get_llvm_type(g, most_aligned_union_member); - if (union_type->data.unionation.resolve_status >= wanted_resolve_status) return; if (padding_bytes > 0) { ZigType *u8_type = get_int_type(g, false, 8); ZigType *padding_array = get_array_type(g, u8_type, padding_bytes); -- cgit v1.2.3 From 6a7b75b73c502ecd6f34c497cc86bded02746cb2 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 19:09:25 -0400 Subject: fix LLVM assertion failures --- src/analyze.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index c1640bd19b..0f6f7ac799 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6359,6 +6359,7 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa 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; @@ -6776,6 +6777,12 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta 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 || @@ -6811,6 +6818,12 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) { 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) { -- cgit v1.2.3 From 025a1475c45f0ba9d196e6584ea70d793a921c40 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 2 Apr 2019 19:40:33 -0400 Subject: emit better debug info for enums fixes llvm assertion when building for windows --- src/analyze.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'src/analyze.cpp') diff --git a/src/analyze.cpp b/src/analyze.cpp index 0f6f7ac799..394364c68f 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -6576,9 +6576,24 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { 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; - enum_type->llvm_di_type = g->builtin_types.entry_void->llvm_di_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; } @@ -6587,9 +6602,6 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { 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); - for (uint32_t i = 0; i < field_count; i += 1) { TypeEnumField *enum_field = &enum_type->data.enumeration.fields[i]; @@ -6603,7 +6615,6 @@ static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type) { enum_type->llvm_type = get_llvm_type(g, tag_int_type); // create debug type for tag - AstNode *decl_node = enum_type->data.enumeration.decl_node; 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, -- cgit v1.2.3