aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/link/Dwarf.zig131
-rw-r--r--src/translate_c.zig4
-rw-r--r--src/translate_c/ast.zig15
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,