Skip to content

Commit bb70501

Browse files
authored
Merge pull request ziglang#21078 from jacobly0/new-dwarf
Dwarf: rework self-hosted debug info from scratch
2 parents 90989be + ed19ecd commit bb70501

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+5267
-3536
lines changed

build.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,15 @@ pub fn build(b: *std.Build) !void {
549549
test_step.dependOn(tests.addStackTraceTests(b, test_filters, optimization_modes));
550550
test_step.dependOn(tests.addCliTests(b));
551551
test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filters, optimization_modes));
552+
if (tests.addDebuggerTests(b, .{
553+
.test_filters = test_filters,
554+
.gdb = b.option([]const u8, "gdb", "path to gdb binary"),
555+
.lldb = b.option([]const u8, "lldb", "path to lldb binary"),
556+
.optimize_modes = optimization_modes,
557+
.skip_single_threaded = skip_single_threaded,
558+
.skip_non_native = skip_non_native,
559+
.skip_libc = skip_libc,
560+
})) |test_debugger_step| test_step.dependOn(test_debugger_step);
552561

553562
try addWasiUpdateStep(b, version);
554563

ci/x86_64-linux-debug.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ stage3-debug/bin/zig build \
6464

6565
stage3-debug/bin/zig build test docs \
6666
--maxrss 21000000000 \
67+
-Dlldb=$HOME/deps/lldb-zig/Debug/bin/lldb \
6768
-fqemu \
6869
-fwasmtime \
6970
-Dstatic-llvm \

ci/x86_64-linux-release.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ stage3-release/bin/zig build \
6464

6565
stage3-release/bin/zig build test docs \
6666
--maxrss 21000000000 \
67+
-Dlldb=$HOME/deps/lldb-zig/Release/bin/lldb \
6768
-fqemu \
6869
-fwasmtime \
6970
-Dstatic-llvm \

lib/std/array_list.zig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,24 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
359359
return m.len;
360360
}
361361

362+
pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed);
363+
364+
/// Initializes a Writer which will append to the list but will return
365+
/// `error.OutOfMemory` rather than increasing capacity.
366+
pub fn fixedWriter(self: *Self) FixedWriter {
367+
return .{ .context = self };
368+
}
369+
370+
/// The purpose of this function existing is to match `std.io.Writer` API.
371+
fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize {
372+
const available_capacity = self.capacity - self.items.len;
373+
if (m.len > available_capacity)
374+
return error.OutOfMemory;
375+
376+
self.appendSliceAssumeCapacity(m);
377+
return m.len;
378+
}
379+
362380
/// Append a value to the list `n` times.
363381
/// Allocates more memory as necessary.
364382
/// Invalidates element pointers if additional memory is needed.

lib/std/debug.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1360,6 +1360,9 @@ test "manage resources correctly" {
13601360
return error.SkipZigTest;
13611361
}
13621362

1363+
// self-hosted debug info is still too buggy
1364+
if (builtin.zig_backend != .stage2_llvm) return error.SkipZigTest;
1365+
13631366
const writer = std.io.null_writer;
13641367
var di = try SelfInfo.open(testing.allocator);
13651368
defer di.deinit();

lib/std/dwarf.zig

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ pub const LNE = struct {
9595
pub const set_discriminator = 0x04;
9696
pub const lo_user = 0x80;
9797
pub const hi_user = 0xff;
98+
99+
// Zig extensions
100+
pub const ZIG_set_decl = 0xec;
98101
};
99102

100103
pub const UT = struct {
@@ -118,6 +121,8 @@ pub const LNCT = struct {
118121

119122
pub const lo_user = 0x2000;
120123
pub const hi_user = 0x3fff;
124+
125+
pub const LLVM_source = 0x2001;
121126
};
122127

123128
pub const RLE = struct {
@@ -142,6 +147,37 @@ pub const CC = enum(u8) {
142147
GNU_renesas_sh = 0x40,
143148
GNU_borland_fastcall_i386 = 0x41,
144149

150+
BORLAND_safecall = 0xb0,
151+
BORLAND_stdcall = 0xb1,
152+
BORLAND_pascal = 0xb2,
153+
BORLAND_msfastcall = 0xb3,
154+
BORLAND_msreturn = 0xb4,
155+
BORLAND_thiscall = 0xb5,
156+
BORLAND_fastcall = 0xb6,
157+
158+
LLVM_vectorcall = 0xc0,
159+
LLVM_Win64 = 0xc1,
160+
LLVM_X86_64SysV = 0xc2,
161+
LLVM_AAPCS = 0xc3,
162+
LLVM_AAPCS_VFP = 0xc4,
163+
LLVM_IntelOclBicc = 0xc5,
164+
LLVM_SpirFunction = 0xc6,
165+
LLVM_OpenCLKernel = 0xc7,
166+
LLVM_Swift = 0xc8,
167+
LLVM_PreserveMost = 0xc9,
168+
LLVM_PreserveAll = 0xca,
169+
LLVM_X86RegCall = 0xcb,
170+
LLVM_M68kRTD = 0xcc,
171+
LLVM_PreserveNone = 0xcd,
172+
LLVM_RISCVVectorCall = 0xce,
173+
LLVM_SwiftTail = 0xcf,
174+
145175
pub const lo_user = 0x40;
146176
pub const hi_user = 0xff;
147177
};
178+
179+
pub const ACCESS = struct {
180+
pub const public = 0x01;
181+
pub const protected = 0x02;
182+
pub const private = 0x03;
183+
};

lib/std/dwarf/AT.zig

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,15 @@ pub const VMS_rtnbeg_pd_address = 0x2201;
218218
// See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type .
219219
pub const use_GNAT_descriptive_type = 0x2301;
220220
pub const GNAT_descriptive_type = 0x2302;
221+
222+
// Zig extensions.
223+
pub const ZIG_parent = 0x2ccd;
224+
pub const ZIG_padding = 0x2cce;
225+
pub const ZIG_relative_decl = 0x2cd0;
226+
pub const ZIG_decl_line_relative = 0x2cd1;
227+
pub const ZIG_is_allowzero = 0x2ce1;
228+
pub const ZIG_sentinel = 0x2ce2;
229+
221230
// UPC extension.
222231
pub const upc_threads_scaled = 0x3210;
223232
// PGI (STMicroelectronics) extensions.

lib/std/dwarf/LANG.zig

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,30 @@ pub const Fortran03 = 0x0022;
3535
pub const Fortran08 = 0x0023;
3636
pub const RenderScript = 0x0024;
3737
pub const BLISS = 0x0025;
38+
pub const Kotlin = 0x0026;
39+
pub const Zig = 0x0027;
40+
pub const Crystal = 0x0028;
41+
pub const C_plus_plus_17 = 0x002a;
42+
pub const C_plus_plus_20 = 0x002b;
43+
pub const C17 = 0x002c;
44+
pub const Fortran18 = 0x002d;
45+
pub const Ada2005 = 0x002e;
46+
pub const Ada2012 = 0x002f;
47+
pub const HIP = 0x0030;
48+
pub const Assembly = 0x0031;
49+
pub const C_sharp = 0x0032;
50+
pub const Mojo = 0x0033;
51+
pub const GLSL = 0x0034;
52+
pub const GLSL_ES = 0x0035;
53+
pub const HLSL = 0x0036;
54+
pub const OpenCL_CPP = 0x0037;
55+
pub const CPP_for_OpenCL = 0x0038;
56+
pub const SYCL = 0x0039;
57+
pub const C_plus_plus_23 = 0x003a;
58+
pub const Odin = 0x003b;
59+
pub const Ruby = 0x0040;
60+
pub const Move = 0x0041;
61+
pub const Hylo = 0x0042;
3862

3963
pub const lo_user = 0x8000;
4064
pub const hi_user = 0xffff;

lib/std/io.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,7 @@ pub const tty = @import("io/tty.zig");
419419
/// A Writer that doesn't write to anything.
420420
pub const null_writer: NullWriter = .{ .context = {} };
421421

422-
const NullWriter = Writer(void, error{}, dummyWrite);
422+
pub const NullWriter = Writer(void, error{}, dummyWrite);
423423
fn dummyWrite(context: void, data: []const u8) error{}!usize {
424424
_ = context;
425425
return data.len;

lib/std/leb128.zig

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,14 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T {
3636
pub const readULEB128 = readUleb128;
3737

3838
/// Write a single unsigned integer as unsigned LEB128 to the given writer.
39-
pub fn writeUleb128(writer: anytype, uint_value: anytype) !void {
40-
const T = @TypeOf(uint_value);
41-
const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
42-
var value: U = @intCast(uint_value);
39+
pub fn writeUleb128(writer: anytype, arg: anytype) !void {
40+
const Arg = @TypeOf(arg);
41+
const Int = switch (Arg) {
42+
comptime_int => std.math.IntFittingRange(arg, arg),
43+
else => Arg,
44+
};
45+
const Value = if (@typeInfo(Int).Int.bits < 8) u8 else Int;
46+
var value: Value = arg;
4347

4448
while (true) {
4549
const byte: u8 = @truncate(value & 0x7f);
@@ -118,16 +122,19 @@ pub fn readIleb128(comptime T: type, reader: anytype) !T {
118122
pub const readILEB128 = readIleb128;
119123

120124
/// Write a single signed integer as signed LEB128 to the given writer.
121-
pub fn writeIleb128(writer: anytype, int_value: anytype) !void {
122-
const T = @TypeOf(int_value);
123-
const S = if (@typeInfo(T).Int.bits < 8) i8 else T;
124-
const U = std.meta.Int(.unsigned, @typeInfo(S).Int.bits);
125-
126-
var value: S = @intCast(int_value);
125+
pub fn writeIleb128(writer: anytype, arg: anytype) !void {
126+
const Arg = @TypeOf(arg);
127+
const Int = switch (Arg) {
128+
comptime_int => std.math.IntFittingRange(-arg - 1, arg),
129+
else => Arg,
130+
};
131+
const Signed = if (@typeInfo(Int).Int.bits < 8) i8 else Int;
132+
const Unsigned = std.meta.Int(.unsigned, @typeInfo(Signed).Int.bits);
133+
var value: Signed = arg;
127134

128135
while (true) {
129-
const uvalue: U = @bitCast(value);
130-
const byte: u8 = @truncate(uvalue);
136+
const unsigned: Unsigned = @bitCast(value);
137+
const byte: u8 = @truncate(unsigned);
131138
value >>= 6;
132139
if (value == -1 or value == 0) {
133140
try writer.writeByte(byte & 0x7F);
@@ -147,17 +154,25 @@ pub fn writeIleb128(writer: anytype, int_value: anytype) !void {
147154
/// "relocatable", meaning that it becomes possible to later go back and patch the number to be a
148155
/// different value without shifting all the following code.
149156
pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.unsigned, l * 7)) void {
150-
const T = @TypeOf(int);
151-
const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
152-
var value: U = @intCast(int);
157+
writeUnsignedExtended(ptr, int);
158+
}
153159

154-
comptime var i = 0;
155-
inline while (i < (l - 1)) : (i += 1) {
156-
const byte = @as(u8, @truncate(value)) | 0b1000_0000;
160+
/// Same as `writeUnsignedFixed` but with a runtime-known length.
161+
/// Asserts `slice.len > 0`.
162+
pub fn writeUnsignedExtended(slice: []u8, arg: anytype) void {
163+
const Arg = @TypeOf(arg);
164+
const Int = switch (Arg) {
165+
comptime_int => std.math.IntFittingRange(arg, arg),
166+
else => Arg,
167+
};
168+
const Value = if (@typeInfo(Int).Int.bits < 8) u8 else Int;
169+
var value: Value = arg;
170+
171+
for (slice[0 .. slice.len - 1]) |*byte| {
172+
byte.* = @truncate(0x80 | value);
157173
value >>= 7;
158-
ptr[i] = byte;
159174
}
160-
ptr[i] = @truncate(value);
175+
slice[slice.len - 1] = @as(u7, @intCast(value));
161176
}
162177

163178
/// Deprecated: use `writeIleb128`

lib/std/math/big/int.zig

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,12 @@ pub const Const = struct {
20922092
return bits;
20932093
}
20942094

2095+
/// Returns the number of bits required to represent the integer in twos-complement form
2096+
/// with the given signedness.
2097+
pub fn bitCountTwosCompForSignedness(self: Const, signedness: std.builtin.Signedness) usize {
2098+
return self.bitCountTwosComp() + @intFromBool(self.positive and signedness == .signed);
2099+
}
2100+
20952101
/// @popCount with two's complement semantics.
20962102
///
20972103
/// This returns the number of 1 bits set when the value would be represented in
@@ -2147,9 +2153,7 @@ pub const Const = struct {
21472153
if (signedness == .unsigned and !self.positive) {
21482154
return false;
21492155
}
2150-
2151-
const req_bits = self.bitCountTwosComp() + @intFromBool(self.positive and signedness == .signed);
2152-
return bit_count >= req_bits;
2156+
return bit_count >= self.bitCountTwosCompForSignedness(signedness);
21532157
}
21542158

21552159
/// Returns whether self can fit into an integer of the requested type.

lib/std/mem.zig

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ pub fn alignAllocLen(full_len: usize, alloc_len: usize, len_align: u29) usize {
128128
assert(full_len >= alloc_len);
129129
if (len_align == 0)
130130
return alloc_len;
131-
const adjusted = alignBackwardAnyAlign(full_len, len_align);
131+
const adjusted = alignBackwardAnyAlign(usize, full_len, len_align);
132132
assert(adjusted >= alloc_len);
133133
return adjusted;
134134
}
@@ -4312,6 +4312,15 @@ test "sliceAsBytes preserves pointer attributes" {
43124312
try testing.expectEqual(in.alignment, out.alignment);
43134313
}
43144314

4315+
/// Round an address down to the next (or current) aligned address.
4316+
/// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2.
4317+
pub fn alignForwardAnyAlign(comptime T: type, addr: T, alignment: T) T {
4318+
if (isValidAlignGeneric(T, alignment))
4319+
return alignForward(T, addr, alignment);
4320+
assert(alignment != 0);
4321+
return alignBackwardAnyAlign(T, addr + (alignment - 1), alignment);
4322+
}
4323+
43154324
/// Round an address up to the next (or current) aligned address.
43164325
/// The alignment must be a power of 2 and greater than 0.
43174326
/// Asserts that rounding up the address does not cause integer overflow.
@@ -4433,11 +4442,11 @@ test alignForward {
44334442

44344443
/// Round an address down to the previous (or current) aligned address.
44354444
/// Unlike `alignBackward`, `alignment` can be any positive number, not just a power of 2.
4436-
pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize {
4437-
if (isValidAlign(alignment))
4438-
return alignBackward(usize, i, alignment);
4445+
pub fn alignBackwardAnyAlign(comptime T: type, addr: T, alignment: T) T {
4446+
if (isValidAlignGeneric(T, alignment))
4447+
return alignBackward(T, addr, alignment);
44394448
assert(alignment != 0);
4440-
return i - @mod(i, alignment);
4449+
return addr - @mod(addr, alignment);
44414450
}
44424451

44434452
/// Round an address down to the previous (or current) aligned address.

lib/std/zig/AstGen.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4405,7 +4405,6 @@ fn globalVarDecl(
44054405
.decl_line = astgen.source_line,
44064406
.astgen = astgen,
44074407
.is_comptime = true,
4408-
.anon_name_strategy = .parent,
44094408
.instructions = gz.instructions,
44104409
.instructions_top = gz.instructions.items.len,
44114410
};
@@ -4463,6 +4462,8 @@ fn globalVarDecl(
44634462
else
44644463
.none;
44654464

4465+
block_scope.anon_name_strategy = .parent;
4466+
44664467
const init_inst = try expr(
44674468
&block_scope,
44684469
&block_scope.base,
@@ -4490,6 +4491,8 @@ fn globalVarDecl(
44904491
// Extern variable which has an explicit type.
44914492
const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node);
44924493

4494+
block_scope.anon_name_strategy = .parent;
4495+
44934496
const var_inst = try block_scope.addVar(.{
44944497
.var_type = type_inst,
44954498
.lib_name = lib_name,

src/Compilation.zig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,7 @@ const Job = union(enum) {
363363
/// It must be deinited when the job is processed.
364364
air: Air,
365365
},
366+
codegen_type: InternPool.Index,
366367
/// The `Cau` must be semantically analyzed (and possibly export itself).
367368
/// This may be its first time being analyzed, or it may be outdated.
368369
analyze_cau: InternPool.Cau.Index,
@@ -423,6 +424,7 @@ const CodegenJob = union(enum) {
423424
/// It must be deinited when the job is processed.
424425
air: Air,
425426
},
427+
type: InternPool.Index,
426428
};
427429

428430
pub const CObject = struct {
@@ -3712,6 +3714,7 @@ fn processOneJob(tid: usize, comp: *Compilation, job: Job, prog_node: std.Progre
37123714
.air = func.air,
37133715
} });
37143716
},
3717+
.codegen_type => |ty| try comp.queueCodegenJob(tid, .{ .type = ty }),
37153718
.analyze_func => |func| {
37163719
const named_frame = tracy.namedFrame("analyze_func");
37173720
defer named_frame.end();
@@ -4001,6 +4004,13 @@ fn processOneCodegenJob(tid: usize, comp: *Compilation, codegen_job: CodegenJob)
40014004
// This call takes ownership of `func.air`.
40024005
try pt.linkerUpdateFunc(func.func, func.air);
40034006
},
4007+
.type => |ty| {
4008+
const named_frame = tracy.namedFrame("codegen_type");
4009+
defer named_frame.end();
4010+
4011+
const pt: Zcu.PerThread = .{ .zcu = comp.module.?, .tid = @enumFromInt(tid) };
4012+
try pt.linkerUpdateContainerType(ty);
4013+
},
40044014
}
40054015
}
40064016

src/InternPool.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4003,7 +4003,7 @@ pub fn loadStructType(ip: *const InternPool, index: Index) LoadedStructType {
40034003
}
40044004
}
40054005

4006-
const LoadedEnumType = struct {
4006+
pub const LoadedEnumType = struct {
40074007
// TODO: the non-fqn will be needed by the new dwarf structure
40084008
/// The name of this enum type.
40094009
name: NullTerminatedString,

0 commit comments

Comments
 (0)