mirror of
https://github.com/ziglang/zig.git
synced 2025-12-21 21:53:08 +00:00
alignment of structs no longer depends on LLVM
fixes async function tests in optimized builds
This commit is contained in:
parent
8a9289996a
commit
12ff91c1c9
@ -1,3 +1,4 @@
|
|||||||
|
* alignment of variables not being respected in async functions
|
||||||
* for loops need to spill the index. other payload captures probably also need to spill
|
* for loops need to spill the index. other payload captures probably also need to spill
|
||||||
* compile error (instead of crashing) for trying to get @Frame of generic function
|
* compile error (instead of crashing) for trying to get @Frame of generic function
|
||||||
* compile error (instead of crashing) for trying to async call and passing @Frame of wrong function
|
* compile error (instead of crashing) for trying to async call and passing @Frame of wrong function
|
||||||
|
|||||||
@ -1148,6 +1148,8 @@ struct ZigTypeOptional {
|
|||||||
struct ZigTypeErrorUnion {
|
struct ZigTypeErrorUnion {
|
||||||
ZigType *err_set_type;
|
ZigType *err_set_type;
|
||||||
ZigType *payload_type;
|
ZigType *payload_type;
|
||||||
|
size_t pad_bytes;
|
||||||
|
LLVMTypeRef pad_llvm_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ZigTypeErrorSet {
|
struct ZigTypeErrorSet {
|
||||||
@ -3564,6 +3566,7 @@ struct IrInstructionAllocaGen {
|
|||||||
|
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
const char *name_hint;
|
const char *name_hint;
|
||||||
|
size_t field_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IrInstructionEndExpr {
|
struct IrInstructionEndExpr {
|
||||||
|
|||||||
133
src/analyze.cpp
133
src/analyze.cpp
@ -630,6 +630,7 @@ ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payloa
|
|||||||
size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[1]);
|
size_t field2_offset = next_field_offset(0, entry->abi_align, field_sizes[0], field_aligns[1]);
|
||||||
entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], entry->abi_align);
|
entry->abi_size = next_field_offset(field2_offset, entry->abi_align, field_sizes[1], entry->abi_align);
|
||||||
entry->size_in_bits = entry->abi_size * 8;
|
entry->size_in_bits = entry->abi_size * 8;
|
||||||
|
entry->data.error_union.pad_bytes = entry->abi_size - (field2_offset + field_sizes[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
g->type_table.put(type_id, entry);
|
g->type_table.put(type_id, entry);
|
||||||
@ -1499,7 +1500,7 @@ bool type_is_invalid(ZigType *type_entry) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
|
static ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
|
||||||
ZigType *field_types[], size_t field_count, unsigned min_abi_align)
|
ZigType *field_types[], size_t field_count, unsigned min_abi_align)
|
||||||
{
|
{
|
||||||
ZigType *struct_type = new_type_table_entry(ZigTypeIdStruct);
|
ZigType *struct_type = new_type_table_entry(ZigTypeIdStruct);
|
||||||
@ -1524,10 +1525,6 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
|
|||||||
if (field->type_entry->abi_align > abi_align) {
|
if (field->type_entry->abi_align > abi_align) {
|
||||||
abi_align = field->type_entry->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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
|
auto prev_entry = struct_type->data.structure.fields_by_name.put_unique(field->name, field);
|
||||||
@ -1537,15 +1534,17 @@ ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_na
|
|||||||
size_t next_offset = 0;
|
size_t next_offset = 0;
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
TypeStructField *field = &struct_type->data.structure.fields[i];
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
if (field->gen_index == SIZE_MAX)
|
if (!type_has_bits(field->type_entry))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
field->offset = next_offset;
|
field->offset = next_offset;
|
||||||
|
|
||||||
|
// find the next non-zero-byte field for offset calculations
|
||||||
size_t next_src_field_index = i + 1;
|
size_t next_src_field_index = i + 1;
|
||||||
for (; next_src_field_index < field_count; next_src_field_index += 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) {
|
if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
size_t next_abi_align = (next_src_field_index == field_count) ?
|
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;
|
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);
|
next_offset = next_field_offset(next_offset, abi_align, field->type_entry->abi_size, next_abi_align);
|
||||||
@ -5304,6 +5303,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
|
|||||||
|
|
||||||
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
|
for (size_t alloca_i = 0; alloca_i < fn->alloca_gen_list.length; alloca_i += 1) {
|
||||||
IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
|
IrInstructionAllocaGen *instruction = fn->alloca_gen_list.at(alloca_i);
|
||||||
|
instruction->field_index = SIZE_MAX;
|
||||||
ZigType *ptr_type = instruction->base.value.type;
|
ZigType *ptr_type = instruction->base.value.type;
|
||||||
assert(ptr_type->id == ZigTypeIdPointer);
|
assert(ptr_type->id == ZigTypeIdPointer);
|
||||||
ZigType *child_type = ptr_type->data.pointer.child_type;
|
ZigType *child_type = ptr_type->data.pointer.child_type;
|
||||||
@ -5327,6 +5327,7 @@ static Error resolve_coro_frame(CodeGen *g, ZigType *frame_type) {
|
|||||||
} else {
|
} else {
|
||||||
name = buf_ptr(buf_sprintf("%s.%" ZIG_PRI_usize, instruction->name_hint, alloca_i));
|
name = buf_ptr(buf_sprintf("%s.%" ZIG_PRI_usize, instruction->name_hint, alloca_i));
|
||||||
}
|
}
|
||||||
|
instruction->field_index = field_types.length;
|
||||||
field_names.append(name);
|
field_names.append(name);
|
||||||
field_types.append(child_type);
|
field_types.append(child_type);
|
||||||
}
|
}
|
||||||
@ -5949,6 +5950,15 @@ ZigType *make_int_type(CodeGen *g, bool is_signed, uint32_t size_in_bits) {
|
|||||||
entry->llvm_type = LLVMIntType(size_in_bits);
|
entry->llvm_type = LLVMIntType(size_in_bits);
|
||||||
entry->abi_size = LLVMABISizeOfType(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);
|
entry->abi_align = LLVMABIAlignmentOfType(g->target_data_ref, entry->llvm_type);
|
||||||
|
|
||||||
|
if (size_in_bits >= 128) {
|
||||||
|
// Override the incorrect alignment reported by LLVM. Clang does this as well.
|
||||||
|
// On x86_64 there are some instructions like CMPXCHG16B which require this.
|
||||||
|
// On all targets, integers 128 bits and above have ABI alignment of 16.
|
||||||
|
// See: https://github.com/ziglang/zig/issues/2987
|
||||||
|
assert(entry->abi_align == 8); // if this trips we can remove the workaround
|
||||||
|
entry->abi_align = 16;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char u_or_i = is_signed ? 'i' : 'u';
|
const char u_or_i = is_signed ? 'i' : 'u';
|
||||||
@ -6810,10 +6820,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t field_count = struct_type->data.structure.src_field_count;
|
size_t field_count = struct_type->data.structure.src_field_count;
|
||||||
size_t gen_field_count = struct_type->data.structure.gen_field_count;
|
// Every field could potentially have a generated padding field after it.
|
||||||
LLVMTypeRef *element_types = allocate<LLVMTypeRef>(gen_field_count);
|
LLVMTypeRef *element_types = allocate<LLVMTypeRef>(field_count * 2);
|
||||||
|
|
||||||
size_t gen_field_index = 0;
|
|
||||||
bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
|
bool packed = (struct_type->data.structure.layout == ContainerLayoutPacked);
|
||||||
size_t packed_bits_offset = 0;
|
size_t packed_bits_offset = 0;
|
||||||
size_t first_packed_bits_offset_misalign = SIZE_MAX;
|
size_t first_packed_bits_offset_misalign = SIZE_MAX;
|
||||||
@ -6821,20 +6830,36 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
|
|
||||||
// trigger all the recursive get_llvm_type calls
|
// trigger all the recursive get_llvm_type calls
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
ZigType *field_type = type_struct_field->type_entry;
|
ZigType *field_type = field->type_entry;
|
||||||
if (!type_has_bits(field_type))
|
if (!type_has_bits(field_type))
|
||||||
continue;
|
continue;
|
||||||
(void)get_llvm_type(g, field_type);
|
(void)get_llvm_type(g, field_type);
|
||||||
if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return;
|
if (struct_type->data.structure.resolve_status >= wanted_resolve_status) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
size_t gen_field_index = 0;
|
||||||
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
|
|
||||||
ZigType *field_type = type_struct_field->type_entry;
|
|
||||||
|
|
||||||
|
// Calculate what LLVM thinks the ABI align of the struct will be. We do this to avoid
|
||||||
|
// inserting padding bytes where LLVM would do it automatically.
|
||||||
|
size_t llvm_struct_abi_align = 0;
|
||||||
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
|
ZigType *field_type = struct_type->data.structure.fields[i].type_entry;
|
||||||
if (!type_has_bits(field_type))
|
if (!type_has_bits(field_type))
|
||||||
continue;
|
continue;
|
||||||
|
LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
|
||||||
|
size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type);
|
||||||
|
llvm_struct_abi_align = max(llvm_struct_abi_align, llvm_field_abi_align);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
|
ZigType *field_type = field->type_entry;
|
||||||
|
|
||||||
|
if (!type_has_bits(field_type)) {
|
||||||
|
field->gen_index = SIZE_MAX;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (packed) {
|
if (packed) {
|
||||||
size_t field_size_in_bits = type_size_bits(g, field_type);
|
size_t field_size_in_bits = type_size_bits(g, field_type);
|
||||||
@ -6871,11 +6896,44 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
llvm_type = get_llvm_type(g, field_type);
|
llvm_type = get_llvm_type(g, field_type);
|
||||||
}
|
}
|
||||||
element_types[gen_field_index] = llvm_type;
|
element_types[gen_field_index] = llvm_type;
|
||||||
|
field->gen_index = gen_field_index;
|
||||||
gen_field_index += 1;
|
gen_field_index += 1;
|
||||||
|
|
||||||
|
// find the next non-zero-byte field for offset calculations
|
||||||
|
size_t next_src_field_index = i + 1;
|
||||||
|
for (; next_src_field_index < field_count; next_src_field_index += 1) {
|
||||||
|
if (type_has_bits(struct_type->data.structure.fields[next_src_field_index].type_entry))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size_t next_abi_align = (next_src_field_index == field_count) ?
|
||||||
|
struct_type->abi_align :
|
||||||
|
struct_type->data.structure.fields[next_src_field_index].type_entry->abi_align;
|
||||||
|
size_t llvm_next_abi_align = (next_src_field_index == field_count) ?
|
||||||
|
llvm_struct_abi_align :
|
||||||
|
LLVMABIAlignmentOfType(g->target_data_ref,
|
||||||
|
get_llvm_type(g, struct_type->data.structure.fields[next_src_field_index].type_entry));
|
||||||
|
|
||||||
|
size_t next_offset = next_field_offset(field->offset, struct_type->abi_align,
|
||||||
|
field_type->abi_size, next_abi_align);
|
||||||
|
size_t llvm_next_offset = next_field_offset(field->offset, llvm_struct_abi_align,
|
||||||
|
LLVMABISizeOfType(g->target_data_ref, llvm_type), llvm_next_abi_align);
|
||||||
|
|
||||||
|
assert(next_offset >= llvm_next_offset);
|
||||||
|
if (next_offset > llvm_next_offset) {
|
||||||
|
size_t pad_bytes = next_offset - (field->offset + field_type->abi_size);
|
||||||
|
if (pad_bytes != 0) {
|
||||||
|
LLVMTypeRef pad_llvm_type = LLVMArrayType(LLVMInt8Type(), pad_bytes);
|
||||||
|
element_types[gen_field_index] = pad_llvm_type;
|
||||||
|
gen_field_index += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
debug_field_count += 1;
|
debug_field_count += 1;
|
||||||
}
|
}
|
||||||
|
if (!packed) {
|
||||||
|
struct_type->data.structure.gen_field_count = gen_field_index;
|
||||||
|
}
|
||||||
|
|
||||||
if (first_packed_bits_offset_misalign != SIZE_MAX) {
|
if (first_packed_bits_offset_misalign != SIZE_MAX) {
|
||||||
size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;
|
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);
|
size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);
|
||||||
@ -6884,19 +6942,20 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type_has_bits(struct_type)) {
|
if (type_has_bits(struct_type)) {
|
||||||
LLVMStructSetBody(struct_type->llvm_type, element_types, (unsigned)gen_field_count, packed);
|
LLVMStructSetBody(struct_type->llvm_type, element_types,
|
||||||
|
(unsigned)struct_type->data.structure.gen_field_count, packed);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count);
|
ZigLLVMDIType **di_element_types = allocate<ZigLLVMDIType*>(debug_field_count);
|
||||||
size_t debug_field_index = 0;
|
size_t debug_field_index = 0;
|
||||||
for (size_t i = 0; i < field_count; i += 1) {
|
for (size_t i = 0; i < field_count; i += 1) {
|
||||||
TypeStructField *type_struct_field = &struct_type->data.structure.fields[i];
|
TypeStructField *field = &struct_type->data.structure.fields[i];
|
||||||
size_t gen_field_index = type_struct_field->gen_index;
|
size_t gen_field_index = field->gen_index;
|
||||||
if (gen_field_index == SIZE_MAX) {
|
if (gen_field_index == SIZE_MAX) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZigType *field_type = type_struct_field->type_entry;
|
ZigType *field_type = field->type_entry;
|
||||||
|
|
||||||
// if the field is a function, actually the debug info should be a pointer.
|
// if the field is a function, actually the debug info should be a pointer.
|
||||||
ZigLLVMDIType *field_di_type;
|
ZigLLVMDIType *field_di_type;
|
||||||
@ -6914,13 +6973,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
uint64_t debug_align_in_bits;
|
uint64_t debug_align_in_bits;
|
||||||
uint64_t debug_offset_in_bits;
|
uint64_t debug_offset_in_bits;
|
||||||
if (packed) {
|
if (packed) {
|
||||||
debug_size_in_bits = type_struct_field->type_entry->size_in_bits;
|
debug_size_in_bits = field->type_entry->size_in_bits;
|
||||||
debug_align_in_bits = 8 * type_struct_field->type_entry->abi_align;
|
debug_align_in_bits = 8 * field->type_entry->abi_align;
|
||||||
debug_offset_in_bits = 8 * type_struct_field->offset + type_struct_field->bit_offset_in_host;
|
debug_offset_in_bits = 8 * field->offset + field->bit_offset_in_host;
|
||||||
} else {
|
} else {
|
||||||
debug_size_in_bits = 8 * get_store_size_bytes(field_type->size_in_bits);
|
debug_size_in_bits = 8 * get_store_size_bytes(field_type->size_in_bits);
|
||||||
debug_align_in_bits = 8 * field_type->abi_align;
|
debug_align_in_bits = 8 * field_type->abi_align;
|
||||||
debug_offset_in_bits = 8 * type_struct_field->offset;
|
debug_offset_in_bits = 8 * field->offset;
|
||||||
}
|
}
|
||||||
unsigned line;
|
unsigned line;
|
||||||
if (decl_node != nullptr) {
|
if (decl_node != nullptr) {
|
||||||
@ -6930,7 +6989,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
|
|||||||
line = 0;
|
line = 0;
|
||||||
}
|
}
|
||||||
di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
|
di_element_types[debug_field_index] = ZigLLVMCreateDebugMemberType(g->dbuilder,
|
||||||
ZigLLVMTypeToScope(struct_type->llvm_di_type), buf_ptr(type_struct_field->name),
|
ZigLLVMTypeToScope(struct_type->llvm_di_type), buf_ptr(field->name),
|
||||||
di_file, line,
|
di_file, line,
|
||||||
debug_size_in_bits,
|
debug_size_in_bits,
|
||||||
debug_align_in_bits,
|
debug_align_in_bits,
|
||||||
@ -7171,7 +7230,7 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
|
|||||||
union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
|
union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) {
|
static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type, ResolveStatus wanted_resolve_status) {
|
||||||
if (type->llvm_di_type != nullptr) return;
|
if (type->llvm_di_type != nullptr) return;
|
||||||
|
|
||||||
if (!type_has_bits(type)) {
|
if (!type_has_bits(type)) {
|
||||||
@ -7200,7 +7259,7 @@ static void resolve_llvm_types_pointer(CodeGen *g, ZigType *type) {
|
|||||||
uint64_t debug_align_in_bits = 8*type->abi_align;
|
uint64_t debug_align_in_bits = 8*type->abi_align;
|
||||||
type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, elem_type->llvm_di_type,
|
type->llvm_di_type = ZigLLVMCreateDebugPointerType(g->dbuilder, elem_type->llvm_di_type,
|
||||||
debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name));
|
debug_size_in_bits, debug_align_in_bits, buf_ptr(&type->name));
|
||||||
assertNoError(type_resolve(g, elem_type, ResolveStatusLLVMFull));
|
assertNoError(type_resolve(g, elem_type, wanted_resolve_status));
|
||||||
} else {
|
} else {
|
||||||
ZigType *host_int_type = get_int_type(g, false, type->data.pointer.host_int_bytes * 8);
|
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);
|
LLVMTypeRef host_int_llvm_type = get_llvm_type(g, host_int_type);
|
||||||
@ -7326,10 +7385,17 @@ static void resolve_llvm_types_error_union(CodeGen *g, ZigType *type) {
|
|||||||
} else {
|
} else {
|
||||||
LLVMTypeRef err_set_llvm_type = get_llvm_type(g, err_set_type);
|
LLVMTypeRef err_set_llvm_type = get_llvm_type(g, err_set_type);
|
||||||
LLVMTypeRef payload_llvm_type = get_llvm_type(g, payload_type);
|
LLVMTypeRef payload_llvm_type = get_llvm_type(g, payload_type);
|
||||||
LLVMTypeRef elem_types[2];
|
LLVMTypeRef elem_types[3];
|
||||||
elem_types[err_union_err_index] = err_set_llvm_type;
|
elem_types[err_union_err_index] = err_set_llvm_type;
|
||||||
elem_types[err_union_payload_index] = payload_llvm_type;
|
elem_types[err_union_payload_index] = payload_llvm_type;
|
||||||
|
|
||||||
type->llvm_type = LLVMStructType(elem_types, 2, false);
|
type->llvm_type = LLVMStructType(elem_types, 2, false);
|
||||||
|
if (LLVMABISizeOfType(g->target_data_ref, type->llvm_type) != type->abi_size) {
|
||||||
|
// we need to do our own padding
|
||||||
|
type->data.error_union.pad_llvm_type = LLVMArrayType(LLVMInt8Type(), type->data.error_union.pad_bytes);
|
||||||
|
elem_types[2] = type->data.error_union.pad_llvm_type;
|
||||||
|
type->llvm_type = LLVMStructType(elem_types, 3, false);
|
||||||
|
}
|
||||||
|
|
||||||
ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
|
ZigLLVMDIScope *compile_unit_scope = ZigLLVMCompileUnitToScope(g->compile_unit);
|
||||||
ZigLLVMDIFile *di_file = nullptr;
|
ZigLLVMDIFile *di_file = nullptr;
|
||||||
@ -7511,6 +7577,7 @@ static void resolve_llvm_types_fn_type(CodeGen *g, ZigType *fn_type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
|
void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
|
||||||
|
Error err;
|
||||||
if (fn->raw_di_type != nullptr) return;
|
if (fn->raw_di_type != nullptr) return;
|
||||||
|
|
||||||
ZigType *fn_type = fn->type_entry;
|
ZigType *fn_type = fn->type_entry;
|
||||||
@ -7529,8 +7596,10 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn) {
|
|||||||
|
|
||||||
ZigType *frame_type = get_coro_frame_type(g, fn);
|
ZigType *frame_type = get_coro_frame_type(g, fn);
|
||||||
ZigType *ptr_type = get_pointer_to_type(g, frame_type, false);
|
ZigType *ptr_type = get_pointer_to_type(g, frame_type, false);
|
||||||
gen_param_types.append(get_llvm_type(g, ptr_type));
|
if ((err = type_resolve(g, ptr_type, ResolveStatusLLVMFwdDecl)))
|
||||||
param_di_types.append(get_llvm_di_type(g, ptr_type));
|
zig_unreachable();
|
||||||
|
gen_param_types.append(ptr_type->llvm_type);
|
||||||
|
param_di_types.append(ptr_type->llvm_di_type);
|
||||||
|
|
||||||
// this parameter is used to pass the result pointer when await completes
|
// this parameter is used to pass the result pointer when await completes
|
||||||
gen_param_types.append(get_llvm_type(g, g->builtin_types.entry_usize));
|
gen_param_types.append(get_llvm_type(g, g->builtin_types.entry_usize));
|
||||||
@ -7726,7 +7795,7 @@ static void resolve_llvm_types(CodeGen *g, ZigType *type, ResolveStatus wanted_r
|
|||||||
case ZigTypeIdUnion:
|
case ZigTypeIdUnion:
|
||||||
return resolve_llvm_types_union(g, type, wanted_resolve_status);
|
return resolve_llvm_types_union(g, type, wanted_resolve_status);
|
||||||
case ZigTypeIdPointer:
|
case ZigTypeIdPointer:
|
||||||
return resolve_llvm_types_pointer(g, type);
|
return resolve_llvm_types_pointer(g, type, wanted_resolve_status);
|
||||||
case ZigTypeIdInt:
|
case ZigTypeIdInt:
|
||||||
return resolve_llvm_types_integer(g, type);
|
return resolve_llvm_types_integer(g, type);
|
||||||
case ZigTypeIdOptional:
|
case ZigTypeIdOptional:
|
||||||
|
|||||||
@ -38,8 +38,6 @@ ZigType *get_smallest_unsigned_int_type(CodeGen *g, uint64_t x);
|
|||||||
ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
|
ZigType *get_error_union_type(CodeGen *g, ZigType *err_set_type, ZigType *payload_type);
|
||||||
ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
|
ZigType *get_bound_fn_type(CodeGen *g, ZigFn *fn_entry);
|
||||||
ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name);
|
ZigType *get_opaque_type(CodeGen *g, Scope *scope, AstNode *source_node, const char *full_name, Buf *bare_name);
|
||||||
ZigType *get_struct_type(CodeGen *g, const char *type_name, const char *field_names[],
|
|
||||||
ZigType *field_types[], size_t field_count, unsigned min_abi_align);
|
|
||||||
ZigType *get_test_fn_type(CodeGen *g);
|
ZigType *get_test_fn_type(CodeGen *g);
|
||||||
ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
|
ZigType *get_any_frame_type(CodeGen *g, ZigType *result_type);
|
||||||
bool handle_is_ptr(ZigType *type_entry);
|
bool handle_is_ptr(ZigType *type_entry);
|
||||||
|
|||||||
@ -3765,29 +3765,17 @@ static void render_async_spills(CodeGen *g) {
|
|||||||
gen_var_debug_decl(g, var);
|
gen_var_debug_decl(g, var);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// label (grep this): [coro_frame_struct_layout]
|
|
||||||
if (codegen_fn_has_err_ret_tracing_stack(g, g->cur_fn, true)) {
|
ZigType *frame_type = g->cur_fn->frame_type->data.frame.locals_struct;
|
||||||
async_var_index += 2;
|
|
||||||
}
|
|
||||||
for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {
|
for (size_t alloca_i = 0; alloca_i < g->cur_fn->alloca_gen_list.length; alloca_i += 1) {
|
||||||
IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i);
|
IrInstructionAllocaGen *instruction = g->cur_fn->alloca_gen_list.at(alloca_i);
|
||||||
ZigType *ptr_type = instruction->base.value.type;
|
if (instruction->field_index == SIZE_MAX)
|
||||||
assert(ptr_type->id == ZigTypeIdPointer);
|
|
||||||
ZigType *child_type = ptr_type->data.pointer.child_type;
|
|
||||||
if (!type_has_bits(child_type))
|
|
||||||
continue;
|
continue;
|
||||||
if (instruction->base.ref_count == 0)
|
|
||||||
continue;
|
size_t gen_index = frame_type->data.structure.fields[instruction->field_index].gen_index;
|
||||||
if (instruction->base.value.special != ConstValSpecialRuntime) {
|
instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index,
|
||||||
if (const_ptr_pointee(nullptr, g, &instruction->base.value, nullptr)->special !=
|
|
||||||
ConstValSpecialRuntime)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, async_var_index,
|
|
||||||
instruction->name_hint);
|
instruction->name_hint);
|
||||||
async_var_index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6363,6 +6351,9 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = type_resolve(g, type_entry, ResolveStatusLLVMFull)))
|
||||||
|
zig_unreachable();
|
||||||
|
|
||||||
switch (type_entry->id) {
|
switch (type_entry->id) {
|
||||||
case ZigTypeIdInt:
|
case ZigTypeIdInt:
|
||||||
return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_bigint);
|
return bigint_to_llvm_const(get_llvm_type(g, type_entry), &const_val->data.x_bigint);
|
||||||
@ -6434,6 +6425,7 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||||||
LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
|
LLVMValueRef *fields = allocate<LLVMValueRef>(type_entry->data.structure.gen_field_count);
|
||||||
size_t src_field_count = type_entry->data.structure.src_field_count;
|
size_t src_field_count = type_entry->data.structure.src_field_count;
|
||||||
bool make_unnamed_struct = false;
|
bool make_unnamed_struct = false;
|
||||||
|
assert(type_entry->data.structure.resolve_status == ResolveStatusLLVMFull);
|
||||||
if (type_entry->data.structure.layout == ContainerLayoutPacked) {
|
if (type_entry->data.structure.layout == ContainerLayoutPacked) {
|
||||||
size_t src_field_index = 0;
|
size_t src_field_index = 0;
|
||||||
while (src_field_index < src_field_count) {
|
while (src_field_index < src_field_count) {
|
||||||
@ -6503,6 +6495,22 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||||||
LLVMValueRef val = gen_const_val(g, field_val, "");
|
LLVMValueRef val = gen_const_val(g, field_val, "");
|
||||||
fields[type_struct_field->gen_index] = val;
|
fields[type_struct_field->gen_index] = val;
|
||||||
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
|
make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
|
||||||
|
|
||||||
|
size_t end_pad_gen_index = (i + 1 < src_field_count) ?
|
||||||
|
type_entry->data.structure.fields[i + 1].gen_index :
|
||||||
|
type_entry->data.structure.gen_field_count;
|
||||||
|
size_t next_offset = (i + 1 < src_field_count) ?
|
||||||
|
type_entry->data.structure.fields[i + 1].offset : type_entry->abi_size;
|
||||||
|
if (end_pad_gen_index != SIZE_MAX) {
|
||||||
|
for (size_t gen_i = type_struct_field->gen_index + 1; gen_i < end_pad_gen_index;
|
||||||
|
gen_i += 1)
|
||||||
|
{
|
||||||
|
size_t pad_bytes = next_offset -
|
||||||
|
(type_struct_field->offset + type_struct_field->type_entry->abi_size);
|
||||||
|
LLVMTypeRef llvm_array_type = LLVMArrayType(LLVMInt8Type(), pad_bytes);
|
||||||
|
fields[gen_i] = LLVMGetUndef(llvm_array_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (make_unnamed_struct) {
|
if (make_unnamed_struct) {
|
||||||
@ -6690,13 +6698,18 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
|||||||
err_payload_value = gen_const_val(g, payload_val, "");
|
err_payload_value = gen_const_val(g, payload_val, "");
|
||||||
make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_val->type, err_payload_value);
|
make_unnamed_struct = is_llvm_value_unnamed_type(g, payload_val->type, err_payload_value);
|
||||||
}
|
}
|
||||||
LLVMValueRef fields[2];
|
LLVMValueRef fields[3];
|
||||||
fields[err_union_err_index] = err_tag_value;
|
fields[err_union_err_index] = err_tag_value;
|
||||||
fields[err_union_payload_index] = err_payload_value;
|
fields[err_union_payload_index] = err_payload_value;
|
||||||
|
size_t field_count = 2;
|
||||||
|
if (type_entry->data.error_union.pad_llvm_type != nullptr) {
|
||||||
|
fields[2] = LLVMGetUndef(type_entry->data.error_union.pad_llvm_type);
|
||||||
|
field_count = 3;
|
||||||
|
}
|
||||||
if (make_unnamed_struct) {
|
if (make_unnamed_struct) {
|
||||||
return LLVMConstStruct(fields, 2, false);
|
return LLVMConstStruct(fields, field_count, false);
|
||||||
} else {
|
} else {
|
||||||
return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, 2);
|
return LLVMConstNamedStruct(get_llvm_type(g, type_entry), fields, field_count);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7139,6 +7152,7 @@ static void do_code_gen(CodeGen *g) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_async) {
|
if (is_async) {
|
||||||
|
(void)get_llvm_type(g, fn_table_entry->frame_type);
|
||||||
g->cur_resume_block_count = 0;
|
g->cur_resume_block_count = 0;
|
||||||
|
|
||||||
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
|
LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
|
||||||
|
|||||||
@ -307,11 +307,9 @@ test "std.event.Channel" {
|
|||||||
// https://github.com/ziglang/zig/issues/1908
|
// https://github.com/ziglang/zig/issues/1908
|
||||||
if (builtin.single_threaded) return error.SkipZigTest;
|
if (builtin.single_threaded) return error.SkipZigTest;
|
||||||
|
|
||||||
const allocator = std.heap.direct_allocator;
|
|
||||||
|
|
||||||
var loop: Loop = undefined;
|
var loop: Loop = undefined;
|
||||||
// TODO make a multi threaded test
|
// TODO make a multi threaded test
|
||||||
try loop.initSingleThreaded(allocator);
|
try loop.initSingleThreaded(std.heap.direct_allocator);
|
||||||
defer loop.deinit();
|
defer loop.deinit();
|
||||||
|
|
||||||
const channel = try Channel(i32).create(&loop, 0);
|
const channel = try Channel(i32).create(&loop, 0);
|
||||||
|
|||||||
@ -228,3 +228,65 @@ test "alignment of extern() void" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
extern fn nothing() void {}
|
extern fn nothing() void {}
|
||||||
|
|
||||||
|
test "return error union with 128-bit integer" {
|
||||||
|
expect(3 == try give());
|
||||||
|
}
|
||||||
|
fn give() anyerror!u128 {
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
test "alignment of >= 128-bit integer type" {
|
||||||
|
expect(@alignOf(u128) == 16);
|
||||||
|
expect(@alignOf(u129) == 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "alignment of struct with 128-bit field" {
|
||||||
|
expect(@alignOf(struct {
|
||||||
|
x: u128,
|
||||||
|
}) == 16);
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
expect(@alignOf(struct {
|
||||||
|
x: u128,
|
||||||
|
}) == 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
test "size of extern struct with 128-bit field" {
|
||||||
|
expect(@sizeOf(extern struct {
|
||||||
|
x: u128,
|
||||||
|
y: u8,
|
||||||
|
}) == 32);
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
expect(@sizeOf(extern struct {
|
||||||
|
x: u128,
|
||||||
|
y: u8,
|
||||||
|
}) == 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const DefaultAligned = struct {
|
||||||
|
nevermind: u32,
|
||||||
|
badguy: i128,
|
||||||
|
};
|
||||||
|
|
||||||
|
test "read 128-bit field from default aligned struct in stack memory" {
|
||||||
|
var default_aligned = DefaultAligned{
|
||||||
|
.nevermind = 1,
|
||||||
|
.badguy = 12,
|
||||||
|
};
|
||||||
|
expect((@ptrToInt(&default_aligned.badguy) % 16) == 0);
|
||||||
|
expect(12 == default_aligned.badguy);
|
||||||
|
}
|
||||||
|
|
||||||
|
var default_aligned_global = DefaultAligned{
|
||||||
|
.nevermind = 1,
|
||||||
|
.badguy = 12,
|
||||||
|
};
|
||||||
|
|
||||||
|
test "read 128-bit field from default aligned struct in global memory" {
|
||||||
|
expect((@ptrToInt(&default_aligned_global.badguy) % 16) == 0);
|
||||||
|
expect(12 == default_aligned_global.badguy);
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user