diff options
| -rw-r--r-- | src/link/Dwarf.zig | 131 | ||||
| -rw-r--r-- | src/translate_c.zig | 4 | ||||
| -rw-r--r-- | src/translate_c/ast.zig | 15 |
3 files changed, 135 insertions, 15 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 5e1af101de..370aac2734 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -83,8 +83,9 @@ pub const abbrev_struct_type = 6; pub const abbrev_struct_member = 7; pub const abbrev_enum_type = 8; pub const abbrev_enum_variant = 9; -pub const abbrev_pad1 = 10; -pub const abbrev_parameter = 11; +pub const abbrev_union_type = 10; +pub const abbrev_pad1 = 11; +pub const abbrev_parameter = 12; /// The reloc offset for the virtual address of a function in its Line Number Program. /// Size is a virtual address integer. @@ -452,6 +453,8 @@ pub fn commitDeclDebugInfo( var dbg_type_arena = std.heap.ArenaAllocator.init(gpa); defer dbg_type_arena.deinit(); + var nested_ref4_relocs = std.ArrayList(u32).init(gpa); + defer nested_ref4_relocs.deinit(); { // Now we emit the .debug_info types of the Decl. These will count towards the size of // the buffer, so we have to do it before computing the offset, and we can't perform the actual @@ -463,7 +466,13 @@ pub fn commitDeclDebugInfo( .target = self.target, }).?; value_ptr.off = @intCast(u32, dbg_info_buffer.items.len); - try self.addDbgInfoType(dbg_type_arena.allocator(), ty, dbg_info_buffer, dbg_info_type_relocs); + try self.addDbgInfoType( + dbg_type_arena.allocator(), + ty, + dbg_info_buffer, + dbg_info_type_relocs, + &nested_ref4_relocs, + ); } } @@ -478,13 +487,27 @@ pub fn commitDeclDebugInfo( // Now that we have the offset assigned we can finally perform type relocations. for (dbg_info_type_relocs.values()) |value| { for (value.relocs.items) |off| { - mem.writeIntLittle( + mem.writeInt( u32, dbg_info_buffer.items[off..][0..4], atom.off + value.off, + target_endian, ); } } + // Offsets to positions with known a priori relative displacement values. + // Here, we just need to add the offset of the atom to the read value in the + // relocated cell. + // TODO Should probably generalise this with type relocs. + for (nested_ref4_relocs.items) |off| { + const addend = mem.readInt(u32, dbg_info_buffer.items[off..][0..4], target_endian); + mem.writeInt( + u32, + dbg_info_buffer.items[off..][0..4], + atom.off + addend, + target_endian, + ); + } } try self.writeDeclDebugInfo(file, atom, dbg_info_buffer.items); @@ -751,8 +774,10 @@ fn addDbgInfoType( ty: Type, dbg_info_buffer: *std.ArrayList(u8), dbg_info_type_relocs: *File.DbgInfoTypeRelocsTable, + nested_ref4_relocs: *std.ArrayList(u32), ) error{OutOfMemory}!void { const target = self.target; + const target_endian = self.target.cpu.arch.endian(); var relocs = std.ArrayList(struct { ty: Type, reloc: u32 }).init(arena); switch (ty.zigTypeTag()) { @@ -962,7 +987,6 @@ fn addDbgInfoType( .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)); @@ -983,6 +1007,94 @@ fn addDbgInfoType( // DW.AT.enumeration_type delimit children try dbg_info_buffer.append(0); }, + .Union => { + const layout = ty.unionGetLayout(target); + const union_obj = ty.cast(Type.Payload.Union).?.data; + const payload_offset = if (layout.tag_align >= layout.payload_align) layout.tag_size else 0; + const tag_offset = if (layout.tag_align >= layout.payload_align) 0 else layout.payload_size; + const is_tagged = layout.tag_size > 0; + const union_name = try ty.nameAllocArena(arena, target); + + // TODO this is temporary to match current state of unions in Zig - we don't yet have + // safety checks implemented meaning the implicit tag is not yet stored and generated + // for untagged unions. + if (is_tagged) { + // DW.AT.structure_type + try dbg_info_buffer.append(abbrev_struct_type); + // DW.AT.byte_size, DW.FORM.sdata + try leb128.writeULEB128(dbg_info_buffer.writer(), layout.abi_size); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.ensureUnusedCapacity(union_name.len + 1); + dbg_info_buffer.appendSliceAssumeCapacity(union_name); + dbg_info_buffer.appendAssumeCapacity(0); + + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(9); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("payload"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + const inner_union_index = dbg_info_buffer.items.len; + try dbg_info_buffer.ensureUnusedCapacity(4); + mem.writeInt( + u32, + dbg_info_buffer.addManyAsArrayAssumeCapacity(4), + @intCast(u32, inner_union_index + 5), + target_endian, + ); + try nested_ref4_relocs.append(@intCast(u32, inner_union_index)); + // DW.AT.data_member_location, DW.FORM.sdata + try leb128.writeULEB128(dbg_info_buffer.writer(), payload_offset); + } + + // DW.AT.union_type + try dbg_info_buffer.append(abbrev_union_type); + // DW.AT.byte_size, DW.FORM.sdata, + try leb128.writeULEB128(dbg_info_buffer.writer(), layout.payload_size); + // DW.AT.name, DW.FORM.string + if (is_tagged) { + try dbg_info_buffer.writer().print("AnonUnion\x00", .{}); + } else { + try dbg_info_buffer.writer().print("{s}\x00", .{union_name}); + } + + const fields = ty.unionFields(); + for (fields.keys()) |field_name| { + const field = fields.get(field_name).?; + if (!field.ty.hasRuntimeBits()) continue; + // DW.AT.member + try dbg_info_buffer.append(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + try dbg_info_buffer.writer().print("{s}\x00", .{field_name}); + // DW.AT.type, DW.FORM.ref4 + const 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 + try dbg_info_buffer.append(0); + } + // DW.AT.union_type delimit children + try dbg_info_buffer.append(0); + + if (is_tagged) { + // DW.AT.member + try dbg_info_buffer.ensureUnusedCapacity(5); + dbg_info_buffer.appendAssumeCapacity(abbrev_struct_member); + // DW.AT.name, DW.FORM.string + dbg_info_buffer.appendSliceAssumeCapacity("tag"); + dbg_info_buffer.appendAssumeCapacity(0); + // DW.AT.type, DW.FORM.ref4 + const index = dbg_info_buffer.items.len; + try dbg_info_buffer.resize(index + 4); + try relocs.append(.{ .ty = union_obj.tag_ty, .reloc = @intCast(u32, index) }); + // DW.AT.data_member_location, DW.FORM.sdata + try leb128.writeULEB128(dbg_info_buffer.writer(), tag_offset); + + // DW.AT.structure_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); @@ -1089,6 +1201,15 @@ pub fn writeDbgAbbrev(self: *Dwarf, file: *File) !void { DW.FORM.data8, 0, 0, // table sentinel + abbrev_union_type, + DW.TAG.union_type, + DW.CHILDREN.yes, // header + DW.AT.byte_size, + DW.FORM.sdata, + DW.AT.name, + DW.FORM.string, + 0, + 0, // table sentinel abbrev_pad1, DW.TAG.unspecified_type, DW.CHILDREN.no, // header diff --git a/src/translate_c.zig b/src/translate_c.zig index 8b79dd53ab..39733dd246 100644 --- a/src/translate_c.zig +++ b/src/translate_c.zig @@ -1441,7 +1441,7 @@ fn makeShuffleMask(c: *Context, scope: *Scope, expr: *const clang.ShuffleVectorE assert(num_subexprs >= 3); // two source vectors + at least 1 index expression const mask_len = num_subexprs - 2; - const mask_type = try Tag.std_meta_vector.create(c.arena, .{ + const mask_type = try Tag.vector.create(c.arena, .{ .lhs = try transCreateNodeNumber(c, mask_len, .int), .rhs = try Tag.type.create(c.arena, "i32"), }); @@ -4800,7 +4800,7 @@ fn transType(c: *Context, scope: *Scope, ty: *const clang.Type, source_loc: clan const vector_ty = @ptrCast(*const clang.VectorType, ty); const num_elements = vector_ty.getNumElements(); const element_qt = vector_ty.getElementType(); - return Tag.std_meta_vector.create(c.arena, .{ + return Tag.vector.create(c.arena, .{ .lhs = try transCreateNodeNumber(c, num_elements, .int), .rhs = try transQualType(c, scope, element_qt, source_loc), }); diff --git a/src/translate_c/ast.zig b/src/translate_c/ast.zig index 6351f67214..66c2406187 100644 --- a/src/translate_c/ast.zig +++ b/src/translate_c/ast.zig @@ -192,8 +192,8 @@ pub const Node = extern union { helpers_shuffle_vector_index, /// @import("std").zig.c_translation.Macro.<operand> helpers_macro, - /// @import("std").meta.Vector(lhs, rhs) - std_meta_vector, + /// @Vector(lhs, rhs) + vector, /// @import("std").mem.zeroes(operand) std_mem_zeroes, /// @import("std").mem.zeroInit(lhs, rhs) @@ -322,7 +322,7 @@ pub const Node = extern union { .std_mem_zeroinit, .helpers_flexible_array_type, .helpers_shuffle_vector_index, - .std_meta_vector, + .vector, .ptr_cast, .div_exact, .offset_of, @@ -899,10 +899,9 @@ fn renderNode(c: *Context, node: Node) Allocator.Error!NodeIndex { const import_node = try renderStdImport(c, &.{ "zig", "c_translation", "shuffleVectorIndex" }); return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); }, - .std_meta_vector => { - const payload = node.castTag(.std_meta_vector).?.data; - const import_node = try renderStdImport(c, &.{ "meta", "Vector" }); - return renderCall(c, import_node, &.{ payload.lhs, payload.rhs }); + .vector => { + const payload = node.castTag(.vector).?.data; + return renderBuiltinCall(c, "@Vector", &.{ payload.lhs, payload.rhs }); }, .call => { const payload = node.castTag(.call).?.data; @@ -2221,7 +2220,7 @@ fn renderNodeGrouped(c: *Context, node: Node) !NodeIndex { .typeof, .typeinfo, .std_meta_alignment, - .std_meta_vector, + .vector, .helpers_sizeof, .helpers_cast, .helpers_promoteIntLiteral, |
