| author | |
| committer | |
| log | 20cc560c2dba4834e683692dabd43162a5ce8d22 |
| tree | cf11423a3e228a20b1f78d24f74030c1a47ae20d |
| parent | b09280b48452be8b57b87bbf4eaacd430e6e3537 |
| parent | 04523db6ae214e92f9c842436e66d5618d73d48f |
| signature |
stage2: add debug info for tuples (and anon structs), and implement aggregate_init for structs and arrays5 files changed, 103 insertions(+), 41 deletions(-)
src/arch/x86_64/CodeGen.zig+53-4| ... | @@ -2884,6 +2884,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2884,6 +2884,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2884 | break :blk dst_mcv; | 2884 | break :blk dst_mcv; |
| 2885 | } | 2885 | } |
| 2886 | }; | 2886 | }; |
| 2887 | dst_mcv.freezeIfRegister(&self.register_manager); | ||
| 2888 | defer dst_mcv.unfreezeIfRegister(&self.register_manager); | ||
| 2887 | 2889 | ||
| 2888 | // Shift by struct_field_offset. | 2890 | // Shift by struct_field_offset. |
| 2889 | const shift = @intCast(u8, struct_field_offset * @sizeOf(usize)); | 2891 | const shift = @intCast(u8, struct_field_offset * @sizeOf(usize)); |
| ... | @@ -2893,7 +2895,25 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2893,7 +2895,25 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2893 | const max_reg_bit_width = Register.rax.size(); | 2895 | const max_reg_bit_width = Register.rax.size(); |
| 2894 | const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*))); | 2896 | const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*))); |
| 2895 | const mask = (~@as(u64, 0)) >> mask_shift; | 2897 | const mask = (~@as(u64, 0)) >> mask_shift; |
| 2896 | try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .immediate = mask }); | 2898 | |
| 2899 | const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); | ||
| 2900 | try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg }); | ||
| 2901 | |||
| 2902 | const signedness: std.builtin.Signedness = blk: { | ||
| 2903 | if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned; | ||
| 2904 | break :blk struct_field_ty.intInfo(self.target.*).signedness; | ||
| 2905 | }; | ||
| 2906 | const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); | ||
| 2907 | if (signedness == .signed and field_size < 8) { | ||
| 2908 | _ = try self.addInst(.{ | ||
| 2909 | .tag = .mov_sign_extend, | ||
| 2910 | .ops = (Mir.Ops{ | ||
| 2911 | .reg1 = dst_mcv.register, | ||
| 2912 | .reg2 = registerAlias(dst_mcv.register, field_size), | ||
| 2913 | }).encode(), | ||
| 2914 | .data = undefined, | ||
| 2915 | }); | ||
| 2916 | } | ||
| 2897 | 2917 | ||
| 2898 | break :result dst_mcv; | 2918 | break :result dst_mcv; |
| 2899 | }, | 2919 | }, |
| ... | @@ -5671,13 +5691,42 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5671,13 +5691,42 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { |
| 5671 | } | 5691 | } |
| 5672 | 5692 | ||
| 5673 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { | 5693 | fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { |
| 5674 | const vector_ty = self.air.typeOfIndex(inst); | 5694 | const result_ty = self.air.typeOfIndex(inst); |
| 5675 | const len = vector_ty.vectorLen(); | 5695 | const len = @intCast(usize, result_ty.arrayLen()); |
| 5676 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 5696 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 5677 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); | 5697 | const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); |
| 5698 | const abi_size = @intCast(u32, result_ty.abiSize(self.target.*)); | ||
| 5699 | const abi_align = result_ty.abiAlignment(self.target.*); | ||
| 5678 | const result: MCValue = res: { | 5700 | const result: MCValue = res: { |
| 5679 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; | 5701 | if (self.liveness.isUnused(inst)) break :res MCValue.dead; |
| 5680 | return self.fail("TODO implement airAggregateInit for x86_64", .{}); | 5702 | switch (result_ty.zigTypeTag()) { |
| 5703 | .Struct => { | ||
| 5704 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); | ||
| 5705 | for (elements) |elem, elem_i| { | ||
| 5706 | if (result_ty.structFieldValueComptime(elem_i) != null) continue; // comptime elem | ||
| 5707 | |||
| 5708 | const elem_ty = result_ty.structFieldType(elem_i); | ||
| 5709 | const elem_off = result_ty.structFieldOffset(elem_i, self.target.*); | ||
| 5710 | const elem_mcv = try self.resolveInst(elem); | ||
| 5711 | try self.genSetStack(elem_ty, stack_offset - @intCast(i32, elem_off), elem_mcv, .{}); | ||
| 5712 | } | ||
| 5713 | break :res MCValue{ .stack_offset = stack_offset }; | ||
| 5714 | }, | ||
| 5715 | .Array => { | ||
| 5716 | const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); | ||
| 5717 | const elem_ty = result_ty.childType(); | ||
| 5718 | const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); | ||
| 5719 | |||
| 5720 | for (elements) |elem, elem_i| { | ||
| 5721 | const elem_mcv = try self.resolveInst(elem); | ||
| 5722 | const elem_off = @intCast(i32, elem_size * elem_i); | ||
| 5723 | try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); | ||
| 5724 | } | ||
| 5725 | break :res MCValue{ .stack_offset = stack_offset }; | ||
| 5726 | }, | ||
| 5727 | .Vector => return self.fail("TODO implement aggregate_init for vectors", .{}), | ||
| 5728 | else => unreachable, | ||
| 5729 | } | ||
| 5681 | }; | 5730 | }; |
| 5682 | 5731 | ||
| 5683 | if (elements.len <= Liveness.bpi - 1) { | 5732 | if (elements.len <= Liveness.bpi - 1) { |
src/link/Dwarf.zig+50-32| ... | @@ -881,45 +881,63 @@ fn addDbgInfoType( | ... | @@ -881,45 +881,63 @@ fn addDbgInfoType( |
| 881 | } | 881 | } |
| 882 | }, | 882 | }, |
| 883 | .Struct => blk: { | 883 | .Struct => blk: { |
| 884 | if (ty.tag() == .tuple) { | ||
| 885 | log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()}); | ||
| 886 | try dbg_info_buffer.append(abbrev_pad1); | ||
| 887 | break :blk; | ||
| 888 | } | ||
| 889 | // try dbg_info_buffer.ensureUnusedCapacity(23); | ||
| 890 | // DW.AT.structure_type | 884 | // DW.AT.structure_type |
| 891 | try dbg_info_buffer.append(abbrev_struct_type); | 885 | try dbg_info_buffer.append(abbrev_struct_type); |
| 892 | // DW.AT.byte_size, DW.FORM.sdata | 886 | // DW.AT.byte_size, DW.FORM.sdata |
| 893 | const abi_size = ty.abiSize(target); | 887 | const abi_size = ty.abiSize(target); |
| 894 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); | 888 | try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); |
| 895 | // DW.AT.name, DW.FORM.string | ||
| 896 | const struct_name = try ty.nameAllocArena(arena, target); | ||
| 897 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); | ||
| 898 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); | ||
| 899 | dbg_info_buffer.appendAssumeCapacity(0); | ||
| 900 | 889 | ||
| 901 | const struct_obj = ty.castTag(.@"struct").?.data; | 890 | switch (ty.tag()) { |
| 902 | if (struct_obj.layout == .Packed) { | 891 | .tuple, .anon_struct => { |
| 903 | log.debug("TODO implement .debug_info for packed structs", .{}); | 892 | // DW.AT.name, DW.FORM.string |
| 904 | break :blk; | 893 | try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); |
| 905 | } | 894 | |
| 895 | const fields = ty.tupleFields(); | ||
| 896 | for (fields.types) |field, field_index| { | ||
| 897 | // DW.AT.member | ||
| 898 | try dbg_info_buffer.append(abbrev_struct_member); | ||
| 899 | // DW.AT.name, DW.FORM.string | ||
| 900 | try dbg_info_buffer.writer().print("{d}\x00", .{field_index}); | ||
| 901 | // DW.AT.type, DW.FORM.ref4 | ||
| 902 | var index = dbg_info_buffer.items.len; | ||
| 903 | try dbg_info_buffer.resize(index + 4); | ||
| 904 | try relocs.append(.{ .ty = field, .reloc = @intCast(u32, index) }); | ||
| 905 | // DW.AT.data_member_location, DW.FORM.sdata | ||
| 906 | const field_off = ty.structFieldOffset(field_index, target); | ||
| 907 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | ||
| 908 | } | ||
| 909 | }, | ||
| 910 | else => { | ||
| 911 | // DW.AT.name, DW.FORM.string | ||
| 912 | const struct_name = try ty.nameAllocArena(arena, target); | ||
| 913 | try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); | ||
| 914 | dbg_info_buffer.appendSliceAssumeCapacity(struct_name); | ||
| 915 | dbg_info_buffer.appendAssumeCapacity(0); | ||
| 916 | |||
| 917 | const struct_obj = ty.castTag(.@"struct").?.data; | ||
| 918 | if (struct_obj.layout == .Packed) { | ||
| 919 | log.debug("TODO implement .debug_info for packed structs", .{}); | ||
| 920 | break :blk; | ||
| 921 | } | ||
| 906 | 922 | ||
| 907 | const fields = ty.structFields(); | 923 | const fields = ty.structFields(); |
| 908 | for (fields.keys()) |field_name, field_index| { | 924 | for (fields.keys()) |field_name, field_index| { |
| 909 | const field = fields.get(field_name).?; | 925 | const field = fields.get(field_name).?; |
| 910 | // DW.AT.member | 926 | // DW.AT.member |
| 911 | try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); | 927 | try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); |
| 912 | dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); | 928 | dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); |
| 913 | // DW.AT.name, DW.FORM.string | 929 | // DW.AT.name, DW.FORM.string |
| 914 | dbg_info_buffer.appendSliceAssumeCapacity(field_name); | 930 | dbg_info_buffer.appendSliceAssumeCapacity(field_name); |
| 915 | dbg_info_buffer.appendAssumeCapacity(0); | 931 | dbg_info_buffer.appendAssumeCapacity(0); |
| 916 | // DW.AT.type, DW.FORM.ref4 | 932 | // DW.AT.type, DW.FORM.ref4 |
| 917 | var index = dbg_info_buffer.items.len; | 933 | var index = dbg_info_buffer.items.len; |
| 918 | try dbg_info_buffer.resize(index + 4); | 934 | try dbg_info_buffer.resize(index + 4); |
| 919 | try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); | 935 | try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); |
| 920 | // DW.AT.data_member_location, DW.FORM.sdata | 936 | // DW.AT.data_member_location, DW.FORM.sdata |
| 921 | const field_off = ty.structFieldOffset(field_index, target); | 937 | const field_off = ty.structFieldOffset(field_index, target); |
| 922 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); | 938 | try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); |
| 939 | } | ||
| 940 | }, | ||
| 923 | } | 941 | } |
| 924 | 942 | ||
| 925 | // DW.AT.structure_type delimit children | 943 | // DW.AT.structure_type delimit children |
test/behavior/array.zig-1| ... | @@ -501,7 +501,6 @@ test "type coercion of anon struct literal to array" { | ... | @@ -501,7 +501,6 @@ test "type coercion of anon struct literal to array" { |
| 501 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 501 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 502 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 502 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 503 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 503 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 504 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 505 | 504 | ||
| 506 | const S = struct { | 505 | const S = struct { |
| 507 | const U = union { | 506 | const U = union { |
test/behavior/struct.zig-2| ... | @@ -301,7 +301,6 @@ test "void struct fields" { | ... | @@ -301,7 +301,6 @@ test "void struct fields" { |
| 301 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 301 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 302 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 302 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 303 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 303 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 304 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 305 | 304 | ||
| 306 | const foo = VoidStructFieldsFoo{ | 305 | const foo = VoidStructFieldsFoo{ |
| 307 | .a = void{}, | 306 | .a = void{}, |
| ... | @@ -1019,7 +1018,6 @@ test "struct with union field" { | ... | @@ -1019,7 +1018,6 @@ test "struct with union field" { |
| 1019 | } | 1018 | } |
| 1020 | 1019 | ||
| 1021 | test "type coercion of anon struct literal to struct" { | 1020 | test "type coercion of anon struct literal to struct" { |
| 1022 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1023 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | 1021 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO |
| 1024 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1022 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1025 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1023 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
test/behavior/tuple.zig-2| ... | @@ -4,7 +4,6 @@ const testing = std.testing; | ... | @@ -4,7 +4,6 @@ const testing = std.testing; |
| 4 | const expect = testing.expect; | 4 | const expect = testing.expect; |
| 5 | 5 | ||
| 6 | test "tuple concatenation" { | 6 | test "tuple concatenation" { |
| 7 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 7 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 8 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 10 | 9 | ||
| ... | @@ -47,7 +46,6 @@ test "tuple multiplication" { | ... | @@ -47,7 +46,6 @@ test "tuple multiplication" { |
| 47 | } | 46 | } |
| 48 | 47 | ||
| 49 | test "more tuple concatenation" { | 48 | test "more tuple concatenation" { |
| 50 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 49 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 52 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 50 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 53 | 51 |