diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2024-08-06 11:22:37 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2024-08-16 15:22:55 -0400 |
| commit | ef11bc9899002620d67cfce9c79b6c0dc0f5ea61 (patch) | |
| tree | 7b05fe17340c06e4c40c45ebe249361c0c281c72 /lib/std | |
| parent | 90989be0e31a91335f8d1c1eafb84c3b34792a8c (diff) | |
| download | zig-ef11bc9899002620d67cfce9c79b6c0dc0f5ea61.tar.gz zig-ef11bc9899002620d67cfce9c79b6c0dc0f5ea61.zip | |
Dwarf: rework self-hosted debug info from scratch
This is in preparation for incremental and actually being able to debug
executables built by the x86_64 backend.
Diffstat (limited to 'lib/std')
| -rw-r--r-- | lib/std/array_list.zig | 18 | ||||
| -rw-r--r-- | lib/std/dwarf.zig | 36 | ||||
| -rw-r--r-- | lib/std/dwarf/AT.zig | 9 | ||||
| -rw-r--r-- | lib/std/dwarf/LANG.zig | 24 | ||||
| -rw-r--r-- | lib/std/io.zig | 2 | ||||
| -rw-r--r-- | lib/std/leb128.zig | 55 | ||||
| -rw-r--r-- | lib/std/math/big/int.zig | 10 | ||||
| -rw-r--r-- | lib/std/mem.zig | 19 | ||||
| -rw-r--r-- | lib/std/zig/AstGen.zig | 5 |
9 files changed, 148 insertions, 30 deletions
diff --git a/lib/std/array_list.zig b/lib/std/array_list.zig index 7b93668c5c..2510973692 100644 --- a/lib/std/array_list.zig +++ b/lib/std/array_list.zig @@ -359,6 +359,24 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { return m.len; } + pub const FixedWriter = std.io.Writer(*Self, Allocator.Error, appendWriteFixed); + + /// Initializes a Writer which will append to the list but will return + /// `error.OutOfMemory` rather than increasing capacity. + pub fn fixedWriter(self: *Self) FixedWriter { + return .{ .context = self }; + } + + /// The purpose of this function existing is to match `std.io.Writer` API. + fn appendWriteFixed(self: *Self, m: []const u8) error{OutOfMemory}!usize { + const available_capacity = self.capacity - self.items.len; + if (m.len > available_capacity) + return error.OutOfMemory; + + self.appendSliceAssumeCapacity(m); + return m.len; + } + /// Append a value to the list `n` times. /// Allocates more memory as necessary. /// Invalidates element pointers if additional memory is needed. diff --git a/lib/std/dwarf.zig b/lib/std/dwarf.zig index 6703574d4e..f836d75ae0 100644 --- a/lib/std/dwarf.zig +++ b/lib/std/dwarf.zig @@ -95,6 +95,9 @@ pub const LNE = struct { pub const set_discriminator = 0x04; pub const lo_user = 0x80; pub const hi_user = 0xff; + + // Zig extensions + pub const ZIG_set_decl = 0xec; }; pub const UT = struct { @@ -118,6 +121,8 @@ pub const LNCT = struct { pub const lo_user = 0x2000; pub const hi_user = 0x3fff; + + pub const LLVM_source = 0x2001; }; pub const RLE = struct { @@ -142,6 +147,37 @@ pub const CC = enum(u8) { GNU_renesas_sh = 0x40, GNU_borland_fastcall_i386 = 0x41, + BORLAND_safecall = 0xb0, + BORLAND_stdcall = 0xb1, + BORLAND_pascal = 0xb2, + BORLAND_msfastcall = 0xb3, + BORLAND_msreturn = 0xb4, + BORLAND_thiscall = 0xb5, + BORLAND_fastcall = 0xb6, + + LLVM_vectorcall = 0xc0, + LLVM_Win64 = 0xc1, + LLVM_X86_64SysV = 0xc2, + LLVM_AAPCS = 0xc3, + LLVM_AAPCS_VFP = 0xc4, + LLVM_IntelOclBicc = 0xc5, + LLVM_SpirFunction = 0xc6, + LLVM_OpenCLKernel = 0xc7, + LLVM_Swift = 0xc8, + LLVM_PreserveMost = 0xc9, + LLVM_PreserveAll = 0xca, + LLVM_X86RegCall = 0xcb, + LLVM_M68kRTD = 0xcc, + LLVM_PreserveNone = 0xcd, + LLVM_RISCVVectorCall = 0xce, + LLVM_SwiftTail = 0xcf, + pub const lo_user = 0x40; pub const hi_user = 0xff; }; + +pub const ACCESS = struct { + pub const public = 0x01; + pub const protected = 0x02; + pub const private = 0x03; +}; diff --git a/lib/std/dwarf/AT.zig b/lib/std/dwarf/AT.zig index 8a242d8330..7f04f0d7f7 100644 --- a/lib/std/dwarf/AT.zig +++ b/lib/std/dwarf/AT.zig @@ -218,6 +218,15 @@ pub const VMS_rtnbeg_pd_address = 0x2201; // See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type . pub const use_GNAT_descriptive_type = 0x2301; pub const GNAT_descriptive_type = 0x2302; + +// Zig extensions. +pub const ZIG_parent = 0x2ccd; +pub const ZIG_padding = 0x2cce; +pub const ZIG_relative_decl = 0x2cd0; +pub const ZIG_decl_line_relative = 0x2cd1; +pub const ZIG_is_allowzero = 0x2ce1; +pub const ZIG_sentinel = 0x2ce2; + // UPC extension. pub const upc_threads_scaled = 0x3210; // PGI (STMicroelectronics) extensions. diff --git a/lib/std/dwarf/LANG.zig b/lib/std/dwarf/LANG.zig index e24b61ecae..e890b6e38f 100644 --- a/lib/std/dwarf/LANG.zig +++ b/lib/std/dwarf/LANG.zig @@ -35,6 +35,30 @@ pub const Fortran03 = 0x0022; pub const Fortran08 = 0x0023; pub const RenderScript = 0x0024; pub const BLISS = 0x0025; +pub const Kotlin = 0x0026; +pub const Zig = 0x0027; +pub const Crystal = 0x0028; +pub const C_plus_plus_17 = 0x002a; +pub const C_plus_plus_20 = 0x002b; +pub const C17 = 0x002c; +pub const Fortran18 = 0x002d; +pub const Ada2005 = 0x002e; +pub const Ada2012 = 0x002f; +pub const HIP = 0x0030; +pub const Assembly = 0x0031; +pub const C_sharp = 0x0032; +pub const Mojo = 0x0033; +pub const GLSL = 0x0034; +pub const GLSL_ES = 0x0035; +pub const HLSL = 0x0036; +pub const OpenCL_CPP = 0x0037; +pub const CPP_for_OpenCL = 0x0038; +pub const SYCL = 0x0039; +pub const C_plus_plus_23 = 0x003a; +pub const Odin = 0x003b; +pub const Ruby = 0x0040; +pub const Move = 0x0041; +pub const Hylo = 0x0042; pub const lo_user = 0x8000; pub const hi_user = 0xffff; diff --git a/lib/std/io.zig b/lib/std/io.zig index dd6daef7d0..1f4cb411b4 100644 --- a/lib/std/io.zig +++ b/lib/std/io.zig @@ -419,7 +419,7 @@ pub const tty = @import("io/tty.zig"); /// A Writer that doesn't write to anything. pub const null_writer: NullWriter = .{ .context = {} }; -const NullWriter = Writer(void, error{}, dummyWrite); +pub const NullWriter = Writer(void, error{}, dummyWrite); fn dummyWrite(context: void, data: []const u8) error{}!usize { _ = context; return data.len; diff --git a/lib/std/leb128.zig b/lib/std/leb128.zig index 087df559fe..1915782459 100644 --- a/lib/std/leb128.zig +++ b/lib/std/leb128.zig @@ -36,10 +36,14 @@ pub fn readUleb128(comptime T: type, reader: anytype) !T { pub const readULEB128 = readUleb128; /// Write a single unsigned integer as unsigned LEB128 to the given writer. -pub fn writeUleb128(writer: anytype, uint_value: anytype) !void { - const T = @TypeOf(uint_value); - const U = if (@typeInfo(T).Int.bits < 8) u8 else T; - var value: U = @intCast(uint_value); +pub fn writeUleb128(writer: anytype, arg: anytype) !void { + const Arg = @TypeOf(arg); + const Int = switch (Arg) { + comptime_int => std.math.IntFittingRange(arg, arg), + else => Arg, + }; + const Value = if (@typeInfo(Int).Int.bits < 8) u8 else Int; + var value: Value = arg; while (true) { const byte: u8 = @truncate(value & 0x7f); @@ -118,16 +122,19 @@ pub fn readIleb128(comptime T: type, reader: anytype) !T { pub const readILEB128 = readIleb128; /// Write a single signed integer as signed LEB128 to the given writer. -pub fn writeIleb128(writer: anytype, int_value: anytype) !void { - const T = @TypeOf(int_value); - const S = if (@typeInfo(T).Int.bits < 8) i8 else T; - const U = std.meta.Int(.unsigned, @typeInfo(S).Int.bits); - - var value: S = @intCast(int_value); +pub fn writeIleb128(writer: anytype, arg: anytype) !void { + const Arg = @TypeOf(arg); + const Int = switch (Arg) { + comptime_int => std.math.IntFittingRange(-arg - 1, arg), + else => Arg, + }; + const Signed = if (@typeInfo(Int).Int.bits < 8) i8 else Int; + const Unsigned = std.meta.Int(.unsigned, @typeInfo(Signed).Int.bits); + var value: Signed = arg; while (true) { - const uvalue: U = @bitCast(value); - const byte: u8 = @truncate(uvalue); + const unsigned: Unsigned = @bitCast(value); + const byte: u8 = @truncate(unsigned); value >>= 6; if (value == -1 or value == 0) { try writer.writeByte(byte & 0x7F); @@ -147,17 +154,25 @@ pub fn writeIleb128(writer: anytype, int_value: anytype) !void { /// "relocatable", meaning that it becomes possible to later go back and patch the number to be a /// different value without shifting all the following code. pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(.unsigned, l * 7)) void { - const T = @TypeOf(int); - const U = if (@typeInfo(T).Int.bits < 8) u8 else T; - var value: U = @intCast(int); + writeUnsignedExtended(ptr, int); +} - comptime var i = 0; - inline while (i < (l - 1)) : (i += 1) { - const byte = @as(u8, @truncate(value)) | 0b1000_0000; +/// Same as `writeUnsignedFixed` but with a runtime-known length. +/// Asserts `slice.len > 0`. +pub fn writeUnsignedExtended(slice: []u8, arg: anytype) void { + const Arg = @TypeOf(arg); + const Int = switch (Arg) { + comptime_int => std.math.IntFittingRange(arg, arg), + else => Arg, + }; + const Value = if (@typeInfo(Int).Int.bits < 8) u8 else Int; + var value: Value = arg; + + for (slice[0 .. slice.len - 1]) |*byte| { + byte.* = @truncate(0x80 | value); value >>= 7; - ptr[i] = byte; } - ptr[i] = @truncate(value); + slice[slice.len - 1] = @as(u7, @intCast(value)); } /// Deprecated: use `writeIleb128` diff --git a/lib/std/math/big/int.zig b/lib/std/math/big/int.zig index a7881a8905..f0fd6fca4e 100644 --- a/lib/std/math/big/int.zig +++ b/lib/std/math/big/int.zig @@ -2092,6 +2092,12 @@ pub const Const = struct { return bits; } + /// Returns the number of bits required to represent the integer in twos-complement form + /// with the given signedness. + pub fn bitCountTwosCompForSignedness(self: Const, signedness: std.builtin.Signedness) usize { + return self.bitCountTwosComp() + @intFromBool(self.positive and signedness == .signed); + } + /// @popCount with two's complement semantics. /// /// This returns the number of 1 bits set when the value would be represented in @@ -2147,9 +2153,7 @@ pub const Const = struct { if (signedness == .unsigned and !self.positive) { return false; } - - const req_bits = self.bitCountTwosComp() + @intFromBool(self.positive and signedness == .signed); - return bit_count >= req_bits; + return bit_count >= self.bitCountTwosCompForSignedness(signedness); } /// Returns whether self can fit into an integer of the requested type. diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 685e36feae..c2c168a2ae 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -128,7 +128,7 @@ pub fn alignAllocLen(full_len: usize, alloc_len: usize, len_align: u29) usize { assert(full_len >= alloc_len); if (len_align == 0) return alloc_len; - const adjusted = alignBackwardAnyAlign(full_len, len_align); + const adjusted = alignBackwardAnyAlign(usize, full_len, len_align); assert(adjusted >= alloc_len); return adjusted; } @@ -4312,6 +4312,15 @@ test "sliceAsBytes preserves pointer attributes" { try testing.expectEqual(in.alignment, out.alignment); } +/// Round an address down to the next (or current) aligned address. +/// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2. +pub fn alignForwardAnyAlign(comptime T: type, addr: T, alignment: T) T { + if (isValidAlignGeneric(T, alignment)) + return alignForward(T, addr, alignment); + assert(alignment != 0); + return alignBackwardAnyAlign(T, addr + (alignment - 1), alignment); +} + /// Round an address up to the next (or current) aligned address. /// The alignment must be a power of 2 and greater than 0. /// Asserts that rounding up the address does not cause integer overflow. @@ -4433,11 +4442,11 @@ test alignForward { /// Round an address down to the previous (or current) aligned address. /// Unlike `alignBackward`, `alignment` can be any positive number, not just a power of 2. -pub fn alignBackwardAnyAlign(i: usize, alignment: usize) usize { - if (isValidAlign(alignment)) - return alignBackward(usize, i, alignment); +pub fn alignBackwardAnyAlign(comptime T: type, addr: T, alignment: T) T { + if (isValidAlignGeneric(T, alignment)) + return alignBackward(T, addr, alignment); assert(alignment != 0); - return i - @mod(i, alignment); + return addr - @mod(addr, alignment); } /// Round an address down to the previous (or current) aligned address. diff --git a/lib/std/zig/AstGen.zig b/lib/std/zig/AstGen.zig index c24aa6d063..d73c83bb41 100644 --- a/lib/std/zig/AstGen.zig +++ b/lib/std/zig/AstGen.zig @@ -4405,7 +4405,6 @@ fn globalVarDecl( .decl_line = astgen.source_line, .astgen = astgen, .is_comptime = true, - .anon_name_strategy = .parent, .instructions = gz.instructions, .instructions_top = gz.instructions.items.len, }; @@ -4463,6 +4462,8 @@ fn globalVarDecl( else .none; + block_scope.anon_name_strategy = .parent; + const init_inst = try expr( &block_scope, &block_scope.base, @@ -4490,6 +4491,8 @@ fn globalVarDecl( // Extern variable which has an explicit type. const type_inst = try typeExpr(&block_scope, &block_scope.base, var_decl.ast.type_node); + block_scope.anon_name_strategy = .parent; + const var_inst = try block_scope.addVar(.{ .var_type = type_inst, .lib_name = lib_name, |
