diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-03-24 22:29:20 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-24 22:29:20 +0100 |
| commit | 20cc560c2dba4834e683692dabd43162a5ce8d22 (patch) | |
| tree | cf11423a3e228a20b1f78d24f74030c1a47ae20d /src | |
| parent | b09280b48452be8b57b87bbf4eaacd430e6e3537 (diff) | |
| parent | 04523db6ae214e92f9c842436e66d5618d73d48f (diff) | |
| download | zig-20cc560c2dba4834e683692dabd43162a5ce8d22.tar.gz zig-20cc560c2dba4834e683692dabd43162a5ce8d22.zip | |
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
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 57 | ||||
| -rw-r--r-- | src/link/Dwarf.zig | 82 |
2 files changed, 103 insertions, 36 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index f2977977c5..1e79119997 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2884,6 +2884,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { break :blk dst_mcv; } }; + dst_mcv.freezeIfRegister(&self.register_manager); + defer dst_mcv.unfreezeIfRegister(&self.register_manager); // Shift by struct_field_offset. const shift = @intCast(u8, struct_field_offset * @sizeOf(usize)); @@ -2893,7 +2895,25 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { const max_reg_bit_width = Register.rax.size(); const mask_shift = @intCast(u6, (max_reg_bit_width - struct_field_ty.bitSize(self.target.*))); const mask = (~@as(u64, 0)) >> mask_shift; - try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .immediate = mask }); + + const tmp_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = mask }); + try self.genBinMathOpMir(.@"and", Type.usize, dst_mcv, .{ .register = tmp_reg }); + + const signedness: std.builtin.Signedness = blk: { + if (struct_field_ty.zigTypeTag() != .Int) break :blk .unsigned; + break :blk struct_field_ty.intInfo(self.target.*).signedness; + }; + const field_size = @intCast(u32, struct_field_ty.abiSize(self.target.*)); + if (signedness == .signed and field_size < 8) { + _ = try self.addInst(.{ + .tag = .mov_sign_extend, + .ops = (Mir.Ops{ + .reg1 = dst_mcv.register, + .reg2 = registerAlias(dst_mcv.register, field_size), + }).encode(), + .data = undefined, + }); + } break :result dst_mcv; }, @@ -5671,13 +5691,42 @@ fn airReduce(self: *Self, inst: Air.Inst.Index) !void { } fn airAggregateInit(self: *Self, inst: Air.Inst.Index) !void { - const vector_ty = self.air.typeOfIndex(inst); - const len = vector_ty.vectorLen(); + const result_ty = self.air.typeOfIndex(inst); + const len = @intCast(usize, result_ty.arrayLen()); const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const elements = @bitCast([]const Air.Inst.Ref, self.air.extra[ty_pl.payload..][0..len]); + const abi_size = @intCast(u32, result_ty.abiSize(self.target.*)); + const abi_align = result_ty.abiAlignment(self.target.*); const result: MCValue = res: { if (self.liveness.isUnused(inst)) break :res MCValue.dead; - return self.fail("TODO implement airAggregateInit for x86_64", .{}); + switch (result_ty.zigTypeTag()) { + .Struct => { + const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); + for (elements) |elem, elem_i| { + if (result_ty.structFieldValueComptime(elem_i) != null) continue; // comptime elem + + const elem_ty = result_ty.structFieldType(elem_i); + const elem_off = result_ty.structFieldOffset(elem_i, self.target.*); + const elem_mcv = try self.resolveInst(elem); + try self.genSetStack(elem_ty, stack_offset - @intCast(i32, elem_off), elem_mcv, .{}); + } + break :res MCValue{ .stack_offset = stack_offset }; + }, + .Array => { + const stack_offset = @intCast(i32, try self.allocMem(inst, abi_size, abi_align)); + const elem_ty = result_ty.childType(); + const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*)); + + for (elements) |elem, elem_i| { + const elem_mcv = try self.resolveInst(elem); + const elem_off = @intCast(i32, elem_size * elem_i); + try self.genSetStack(elem_ty, stack_offset - elem_off, elem_mcv, .{}); + } + break :res MCValue{ .stack_offset = stack_offset }; + }, + .Vector => return self.fail("TODO implement aggregate_init for vectors", .{}), + else => unreachable, + } }; if (elements.len <= Liveness.bpi - 1) { diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 7643fe55c4..5e1af101de 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -881,45 +881,63 @@ fn addDbgInfoType( } }, .Struct => blk: { - if (ty.tag() == .tuple) { - log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()}); - try dbg_info_buffer.append(abbrev_pad1); - break :blk; - } - // try dbg_info_buffer.ensureUnusedCapacity(23); // DW.AT.structure_type try dbg_info_buffer.append(abbrev_struct_type); // DW.AT.byte_size, DW.FORM.sdata const abi_size = ty.abiSize(target); try leb128.writeULEB128(dbg_info_buffer.writer(), abi_size); - // DW.AT.name, DW.FORM.string - const struct_name = try ty.nameAllocArena(arena, target); - try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); - dbg_info_buffer.appendSliceAssumeCapacity(struct_name); - dbg_info_buffer.appendAssumeCapacity(0); - const struct_obj = ty.castTag(.@"struct").?.data; - if (struct_obj.layout == .Packed) { - log.debug("TODO implement .debug_info for packed structs", .{}); - break :blk; - } + switch (ty.tag()) { + .tuple, .anon_struct => { + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{}\x00", .{ty.fmt(target)}); + + const fields = ty.tupleFields(); + for (fields.types) |field, field_index| { + // DW.AT.member + try dbg_info_buffer.append(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{d}\x00", .{field_index}); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = field, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + const field_off = ty.structFieldOffset(field_index, target); + try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + } + }, + else => { + // DW.AT.name, DW.FORM.string + const struct_name = try ty.nameAllocArena(arena, target); + try dbg_info_buffer.ensureUnusedCapacity(struct_name.len + 1); + dbg_info_buffer.appendSliceAssumeCapacity(struct_name); + dbg_info_buffer.appendAssumeCapacity(0); + + const struct_obj = ty.castTag(.@"struct").?.data; + if (struct_obj.layout == .Packed) { + log.debug("TODO implement .debug_info for packed structs", .{}); + break :blk; + } - const fields = ty.structFields(); - for (fields.keys()) |field_name, field_index| { - const field = fields.get(field_name).?; - // DW.AT.member - try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); - dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); - // DW.AT.name, DW.FORM.string - dbg_info_buffer.appendSliceAssumeCapacity(field_name); - dbg_info_buffer.appendAssumeCapacity(0); - // DW.AT.type, DW.FORM.ref4 - var index = dbg_info_buffer.items.len; - try dbg_info_buffer.resize(index + 4); - try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); - // DW.AT.data_member_location, DW.FORM.sdata - const field_off = ty.structFieldOffset(field_index, target); - try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + const fields = ty.structFields(); + for (fields.keys()) |field_name, field_index| { + const field = fields.get(field_name).?; + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity(field_name); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + var index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = field.ty, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + const field_off = ty.structFieldOffset(field_index, target); + try leb128.writeULEB128(dbg_info_buffer.writer(), field_off); + } + }, } // DW.AT.structure_type delimit children |
