authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-09-21 13:46:13-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2019-09-21 13:46:13-04:00
logf3a7c346ddfdac516cf82f5c0771fd07398a20ef
tree67a36116490b97048e0a445712ea26f79e7e32ca
parent533aff3a6a6a72ac09261c395c479570fe81d1d8
parent34d02f249b8c0742d5d575c439c38a3ed78f9583
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #3278 from LemonBoy/struct-gen

A few steps towards AArch64 & ARM passing the behavior tests

8 files changed, 65 insertions(+), 12 deletions(-)

src/analyze.cpp+10-3
...@@ -7633,6 +7633,11 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa...@@ -7633,6 +7633,11 @@ static void resolve_llvm_types_slice(CodeGen *g, ZigType *type, ResolveStatus wa
7633 type->data.structure.resolve_status = ResolveStatusLLVMFull;7633 type->data.structure.resolve_status = ResolveStatusLLVMFull;
7634}7634}
76357635
7636static LLVMTypeRef get_llvm_array_type(unsigned byte_size) {
7637 return byte_size == 1 ?
7638 LLVMInt8Type() : LLVMArrayType(LLVMInt8Type(), byte_size);
7639}
7640
7636static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,7641static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveStatus wanted_resolve_status,
7637 ZigType *async_frame_type)7642 ZigType *async_frame_type)
7638{7643{
...@@ -7730,9 +7735,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7730,9 +7735,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7730 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);7735 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);
7731 if (full_abi_size * 8 == full_bit_count) {7736 if (full_abi_size * 8 == full_bit_count) {
7732 // next field recovers ABI alignment7737 // next field recovers ABI alignment
7733 element_types[gen_field_index] = LLVMIntType((unsigned)(full_bit_count));7738 element_types[gen_field_index] = get_llvm_array_type(full_abi_size);
7734 gen_field_index += 1;7739 gen_field_index += 1;
7735
7736 first_packed_bits_offset_misalign = SIZE_MAX;7740 first_packed_bits_offset_misalign = SIZE_MAX;
7737 }7741 }
7738 } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) {7742 } else if (get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) * 8 != field_size_in_bits) {
...@@ -7740,6 +7744,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7740,6 +7744,8 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7740 } else {7744 } else {
7741 // This is a byte-aligned field (both start and end) in a packed struct.7745 // This is a byte-aligned field (both start and end) in a packed struct.
7742 element_types[gen_field_index] = get_llvm_type(g, field_type);7746 element_types[gen_field_index] = get_llvm_type(g, field_type);
7747 assert(get_abi_size_bytes(field_type->size_in_bits, g->pointer_size_bytes) ==
7748 LLVMStoreSizeOfType(g->target_data_ref, element_types[gen_field_index]));
7743 gen_field_index += 1;7749 gen_field_index += 1;
7744 }7750 }
7745 packed_bits_offset = next_packed_bits_offset;7751 packed_bits_offset = next_packed_bits_offset;
...@@ -7802,11 +7808,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7802,11 +7808,12 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7802 if (first_packed_bits_offset_misalign != SIZE_MAX) {7808 if (first_packed_bits_offset_misalign != SIZE_MAX) {
7803 size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;7809 size_t full_bit_count = packed_bits_offset - first_packed_bits_offset_misalign;
7804 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);7810 size_t full_abi_size = get_abi_size_bytes(full_bit_count, g->pointer_size_bytes);
7805 element_types[gen_field_index] = LLVMIntType((unsigned)full_abi_size * 8);7811 element_types[gen_field_index] = get_llvm_array_type(full_abi_size);
7806 gen_field_index += 1;7812 gen_field_index += 1;
7807 }7813 }
78087814
7809 if (type_has_bits(struct_type)) {7815 if (type_has_bits(struct_type)) {
7816 assert(struct_type->data.structure.gen_field_count == gen_field_index);
7810 LLVMStructSetBody(struct_type->llvm_type, element_types,7817 LLVMStructSetBody(struct_type->llvm_type, element_types,
7811 (unsigned)struct_type->data.structure.gen_field_count, packed);7818 (unsigned)struct_type->data.structure.gen_field_count, packed);
7812 }7819 }
src/codegen.cpp+29-6
...@@ -1644,7 +1644,9 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,...@@ -1644,7 +1644,9 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
16441644
1645 bool big_endian = g->is_big_endian;1645 bool big_endian = g->is_big_endian;
16461646
1647 LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");1647 LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0);
1648 LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, "");
1649 LLVMValueRef containing_int = gen_load(g, int_ptr, ptr_type, "");
1648 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));1650 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
1649 assert(host_bit_count == host_int_bytes * 8);1651 assert(host_bit_count == host_int_bytes * 8);
1650 uint32_t size_in_bits = type_size_bits(g, child_type);1652 uint32_t size_in_bits = type_size_bits(g, child_type);
...@@ -1668,7 +1670,7 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,...@@ -1668,7 +1670,7 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type,
1668 LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, "");1670 LLVMValueRef shifted_value = LLVMBuildShl(g->builder, extended_value, shift_amt_val, "");
1669 LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, "");1671 LLVMValueRef ored_value = LLVMBuildOr(g->builder, shifted_value, anded_containing_int, "");
16701672
1671 gen_store(g, ored_value, ptr, ptr_type);1673 gen_store(g, ored_value, int_ptr, ptr_type);
1672}1674}
16731675
1674static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {1676static void gen_var_debug_decl(CodeGen *g, ZigVar *var) {
...@@ -3396,7 +3398,10 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI...@@ -3396,7 +3398,10 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
33963398
3397 bool big_endian = g->is_big_endian;3399 bool big_endian = g->is_big_endian;
33983400
3399 LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");3401 LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0);
3402 LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, "");
3403 LLVMValueRef containing_int = gen_load(g, int_ptr, ptr_type, "");
3404
3400 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));3405 uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
3401 assert(host_bit_count == host_int_bytes * 8);3406 assert(host_bit_count == host_int_bytes * 8);
3402 uint32_t size_in_bits = type_size_bits(g, child_type);3407 uint32_t size_in_bits = type_size_bits(g, child_type);
...@@ -3722,7 +3727,8 @@ static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {...@@ -3722,7 +3727,8 @@ static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) {
37223727
3723 LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), "");3728 LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), "");
3724 LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, "");3729 LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, "");
3725 LLVMValueRef align_amt = LLVMConstInt(LLVMTypeOf(end_addr), get_abi_alignment(g, g->builtin_types.entry_usize), false);3730 const unsigned alignment_factor = ZigLLVMDataLayoutGetStackAlignment(g->target_data_ref);
3731 LLVMValueRef align_amt = LLVMConstInt(LLVMTypeOf(end_addr), alignment_factor, false);
3726 LLVMValueRef align_adj = LLVMBuildURem(g->builder, end_addr, align_amt, "");3732 LLVMValueRef align_adj = LLVMBuildURem(g->builder, end_addr, align_amt, "");
3727 return LLVMBuildNUWSub(g->builder, end_addr, align_adj, "");3733 return LLVMBuildNUWSub(g->builder, end_addr, align_adj, "");
3728}3734}
...@@ -6723,8 +6729,10 @@ check: switch (const_val->special) {...@@ -6723,8 +6729,10 @@ check: switch (const_val->special) {
6723 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);6729 make_unnamed_struct = make_unnamed_struct || is_llvm_value_unnamed_type(g, field_val->type, val);
6724 } else {6730 } else {
6725 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type6731 bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
6726 LLVMTypeRef big_int_type_ref = LLVMStructGetTypeAtIndex(get_llvm_type(g, type_entry),6732 LLVMTypeRef field_ty = LLVMStructGetTypeAtIndex(get_llvm_type(g, type_entry),
6727 (unsigned)type_struct_field->gen_index);6733 (unsigned)type_struct_field->gen_index);
6734 const size_t size_in_bytes = LLVMStoreSizeOfType(g->target_data_ref, field_ty);
6735 LLVMTypeRef big_int_type_ref = LLVMIntType(size_in_bytes * 8);
6728 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);6736 LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
6729 size_t used_bits = 0;6737 size_t used_bits = 0;
6730 for (size_t i = src_field_index; i < src_field_index_end; i += 1) {6738 for (size_t i = src_field_index; i < src_field_index_end; i += 1) {
...@@ -6747,7 +6755,22 @@ check: switch (const_val->special) {...@@ -6747,7 +6755,22 @@ check: switch (const_val->special) {
6747 used_bits += packed_bits_size;6755 used_bits += packed_bits_size;
6748 }6756 }
6749 }6757 }
6750 fields[type_struct_field->gen_index] = val;6758 if (LLVMGetTypeKind(field_ty) != LLVMArrayTypeKind) {
6759 assert(LLVMGetTypeKind(field_ty) == LLVMIntegerTypeKind);
6760 fields[type_struct_field->gen_index] = val;
6761 } else {
6762 const LLVMValueRef MASK = LLVMConstInt(LLVMInt8Type(), 255, false);
6763 const LLVMValueRef AMT = LLVMConstInt(LLVMInt8Type(), 8, false);
6764
6765 LLVMValueRef *values = allocate<LLVMValueRef>(size_in_bytes);
6766 for (size_t i = 0; i < size_in_bytes; i++) {
6767 const size_t idx = is_big_endian ? size_in_bytes - 1 - i : i;
6768 values[idx] = LLVMConstTruncOrBitCast(LLVMConstAnd(val, MASK), LLVMInt8Type());
6769 val = LLVMConstLShr(val, AMT);
6770 }
6771
6772 fields[type_struct_field->gen_index] = LLVMConstArray(LLVMInt8Type(), values, size_in_bytes);
6773 }
6751 }6774 }
67526775
6753 src_field_index = src_field_index_end;6776 src_field_index = src_field_index_end;
src/zig_llvm.cpp+4
...@@ -149,6 +149,10 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri...@@ -149,6 +149,10 @@ LLVMTargetMachineRef ZigLLVMCreateTargetMachine(LLVMTargetRef T, const char *Tri
149 return reinterpret_cast<LLVMTargetMachineRef>(TM);149 return reinterpret_cast<LLVMTargetMachineRef>(TM);
150}150}
151151
152unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD) {
153 return unwrap(TD)->getStackAlignment();
154}
155
152bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,156bool ZigLLVMTargetMachineEmitToFile(LLVMTargetMachineRef targ_machine_ref, LLVMModuleRef module_ref,
153 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,157 const char *filename, ZigLLVM_EmitOutputType output_type, char **error_message, bool is_debug,
154 bool is_small, bool time_report)158 bool is_small, bool time_report)
src/zig_llvm.h+2
...@@ -469,4 +469,6 @@ ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum...@@ -469,4 +469,6 @@ ZIG_EXTERN_C void ZigLLVMGetNativeTarget(enum ZigLLVM_ArchType *arch_type, enum
469 enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,469 enum ZigLLVM_VendorType *vendor_type, enum ZigLLVM_OSType *os_type, enum ZigLLVM_EnvironmentType *environ_type,
470 enum ZigLLVM_ObjectFormatType *oformat);470 enum ZigLLVM_ObjectFormatType *oformat);
471471
472ZIG_EXTERN_C unsigned ZigLLVMDataLayoutGetStackAlignment(LLVMTargetDataRef TD);
473
472#endif474#endif
test/stage1/behavior.zig+3-1
...@@ -72,7 +72,9 @@ comptime {...@@ -72,7 +72,9 @@ comptime {
72 _ = @import("behavior/misc.zig");72 _ = @import("behavior/misc.zig");
73 _ = @import("behavior/muladd.zig");73 _ = @import("behavior/muladd.zig");
74 _ = @import("behavior/namespace_depends_on_compile_var.zig");74 _ = @import("behavior/namespace_depends_on_compile_var.zig");
75 _ = @import("behavior/new_stack_call.zig");75 // See #3268
76 if (@import("builtin").arch != .aarch64)
77 _ = @import("behavior/new_stack_call.zig");
76 _ = @import("behavior/null.zig");78 _ = @import("behavior/null.zig");
77 _ = @import("behavior/optional.zig");79 _ = @import("behavior/optional.zig");
78 _ = @import("behavior/pointers.zig");80 _ = @import("behavior/pointers.zig");
test/stage1/behavior/error.zig+2-1
...@@ -361,7 +361,8 @@ test "nested catch" {...@@ -361,7 +361,8 @@ test "nested catch" {
361test "implicit cast to optional to error union to return result loc" {361test "implicit cast to optional to error union to return result loc" {
362 const S = struct {362 const S = struct {
363 fn entry() void {363 fn entry() void {
364 if (func(undefined)) |opt| {364 var x: Foo = undefined;
365 if (func(&x)) |opt| {
365 expect(opt != null);366 expect(opt != null);
366 } else |_| @panic("expected non error");367 } else |_| @panic("expected non error");
367 }368 }
test/stage1/behavior/struct.zig+12
...@@ -658,3 +658,15 @@ test "struct field init with catch" {...@@ -658,3 +658,15 @@ test "struct field init with catch" {
658 S.doTheTest();658 S.doTheTest();
659 comptime S.doTheTest();659 comptime S.doTheTest();
660}660}
661
662test "packed struct with non-ABI-aligned field" {
663 const S = packed struct {
664 x: u9,
665 y: u183,
666 };
667 var s: S = undefined;
668 s.x = 1;
669 s.y = 42;
670 expect(s.x == 1);
671 expect(s.y == 42);
672}
test/stage1/behavior/widening.zig+3-1
...@@ -23,5 +23,7 @@ test "float widening" {...@@ -23,5 +23,7 @@ test "float widening" {
23 var b: f32 = a;23 var b: f32 = a;
24 var c: f64 = b;24 var c: f64 = b;
25 var d: f128 = c;25 var d: f128 = c;
26 expect(d == a);26 expect(a == b);
27 expect(b == c);
28 expect(c == d);
27}29}