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