From 47f1a43bb73607b7bdfcb50de2c4ac8d2bc796af Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 22 Mar 2022 21:27:10 +0100 Subject: [PATCH] dwarf: lower enums --- src/codegen.zig | 1 - src/link/Dwarf.zig | 69 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/src/codegen.zig b/src/codegen.zig index 20599f3eb6..cc7014a136 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -479,7 +479,6 @@ pub fn generateSymbol( return Result{ .appended = {} }; }, .Enum => { - // TODO populate .debug_info for the enum var int_buffer: Value.Payload.U64 = undefined; const int_val = typed_value.enumToInt(&int_buffer); diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 8f0eb96132..7643fe55c4 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -81,8 +81,10 @@ pub const abbrev_base_type = 4; pub const abbrev_ptr_type = 5; pub const abbrev_struct_type = 6; pub const abbrev_struct_member = 7; -pub const abbrev_pad1 = 8; -pub const abbrev_parameter = 9; +pub const abbrev_enum_type = 8; +pub const abbrev_enum_variant = 9; +pub const abbrev_pad1 = 10; +pub const abbrev_parameter = 11; /// The reloc offset for the virtual address of a function in its Line Number Program. /// Size is a virtual address integer. @@ -879,6 +881,11 @@ 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); @@ -918,6 +925,46 @@ fn addDbgInfoType( // DW.AT.structure_type delimit children try dbg_info_buffer.append(0); }, + .Enum => { + // DW.AT.enumeration_type + try dbg_info_buffer.append(abbrev_enum_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 enum_name = try ty.nameAllocArena(arena, target); + try dbg_info_buffer.ensureUnusedCapacity(enum_name.len + 1); + dbg_info_buffer.appendSliceAssumeCapacity(enum_name); + dbg_info_buffer.appendAssumeCapacity(0); + + const fields = ty.enumFields(); + const values: ?Module.EnumFull.ValueMap = switch (ty.tag()) { + .enum_full, .enum_nonexhaustive => ty.cast(Type.Payload.EnumFull).?.data.values, + .enum_simple => null, + .enum_numbered => ty.castTag(.enum_numbered).?.data.values, + else => unreachable, + }; + const target_endian = self.target.cpu.arch.endian(); + for (fields.keys()) |field_name, field_i| { + // DW.AT.enumerator + try dbg_info_buffer.ensureUnusedCapacity(field_name.len + 2 + @sizeOf(u64)); + dbg_info_buffer.appendAssumeCapacity(abbrev_enum_variant); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity(field_name); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.const_value, DW.FORM.data8 + const value: u64 = if (values) |vals| value: { + if (vals.count() == 0) break :value @intCast(u64, field_i); // auto-numbered + const value = vals.keys()[field_i]; + var int_buffer: Value.Payload.U64 = undefined; + break :value value.enumToInt(ty, &int_buffer).toUnsignedInt(target); + } else @intCast(u64, field_i); + mem.writeInt(u64, dbg_info_buffer.addManyAsArrayAssumeCapacity(8), value, target_endian); + } + + // DW.AT.enumeration_type delimit children + try dbg_info_buffer.append(0); + }, else => { log.debug("TODO implement .debug_info for type '{}'", .{ty.fmtDebug()}); try dbg_info_buffer.append(abbrev_pad1); @@ -1006,6 +1053,24 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { DW.FORM.sdata, 0, 0, // table sentinel + abbrev_enum_type, + DW.TAG.enumeration_type, + DW.CHILDREN.yes, // header + DW.AT.byte_size, + DW.FORM.sdata, + DW.AT.name, + DW.FORM.string, + 0, + 0, // table sentinel + abbrev_enum_variant, + DW.TAG.enumerator, + DW.CHILDREN.no, // header + DW.AT.name, + DW.FORM.string, + DW.AT.const_value, + DW.FORM.data8, + 0, + 0, // table sentinel abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header