authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-03-24 22:29:20+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2022-03-24 22:29:20+01:00
log20cc560c2dba4834e683692dabd43162a5ce8d22
treecf11423a3e228a20b1f78d24f74030c1a47ae20d
parentb09280b48452be8b57b87bbf4eaacd430e6e3537
parent04523db6ae214e92f9c842436e66d5618d73d48f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #11286 from ziglang/stage2-aggregate-init

stage2: add debug info for tuples (and anon structs), and implement aggregate_init for structs and arrays

5 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);
28872889
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 }
28972917
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}
56725692
5673fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void {5693fn 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 };
56825731
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_type884 // 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.sdata886 // 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);
900889
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 }
906922
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.member926 // 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.string929 // 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.ref4932 // 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.sdata936 // 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 }
924942
925 // DW.AT.structure_type delimit children943 // 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; // TODO501 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
502 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO502 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
503 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO503 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
504 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
505504
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; // TODO302 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO303 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
304 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
305304
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}
10201019
1021test "type coercion of anon struct literal to struct" {1020test "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; // TODO1021 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1024 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO1022 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1025 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO1023 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;
4const expect = testing.expect;4const expect = testing.expect;
55
6test "tuple concatenation" {6test "tuple concatenation" {
7 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
8 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO7 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
9 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO8 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
109
...@@ -47,7 +46,6 @@ test "tuple multiplication" {...@@ -47,7 +46,6 @@ test "tuple multiplication" {
47}46}
4847
49test "more tuple concatenation" {48test "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; // TODO49 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
52 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO50 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
5351