authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-07 11:17:42-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-09-07 11:17:42-07:00
log52b8239a22aa37fe3914427cd4e2905231769e59
treecd60ca825c14b5befbcddf674bdb7d3feda81d23
parent338f155a02b72117ff710f72c8578e7d2f8eb296
parent533bfc68bf8b4ad7ffbe5814a622f200dc345b69

Merge remote-tracking branch 'origin/master' into llvm11


84 files changed, 1591 insertions(+), 734 deletions(-)

doc/langref.html.in+15-15
...@@ -2156,7 +2156,7 @@ test "pointer casting" {...@@ -2156,7 +2156,7 @@ test "pointer casting" {
21562156
2157test "pointer child type" {2157test "pointer child type" {
2158 // pointer types have a `child` field which tells you the type they point to.2158 // pointer types have a `child` field which tells you the type they point to.
2159 assert((*u32).Child == u32);2159 assert(@typeInfo(*u32).Pointer.child == u32);
2160}2160}
2161 {#code_end#}2161 {#code_end#}
2162 {#header_open|Alignment#}2162 {#header_open|Alignment#}
...@@ -2184,7 +2184,7 @@ test "variable alignment" {...@@ -2184,7 +2184,7 @@ test "variable alignment" {
2184 assert(@TypeOf(&x) == *i32);2184 assert(@TypeOf(&x) == *i32);
2185 assert(*i32 == *align(align_of_i32) i32);2185 assert(*i32 == *align(align_of_i32) i32);
2186 if (std.Target.current.cpu.arch == .x86_64) {2186 if (std.Target.current.cpu.arch == .x86_64) {
2187 assert((*i32).alignment == 4);2187 assert(@typeInfo(*i32).Pointer.alignment == 4);
2188 }2188 }
2189}2189}
2190 {#code_end#}2190 {#code_end#}
...@@ -2202,7 +2202,7 @@ const assert = @import("std").debug.assert;...@@ -2202,7 +2202,7 @@ const assert = @import("std").debug.assert;
2202var foo: u8 align(4) = 100;2202var foo: u8 align(4) = 100;
22032203
2204test "global variable alignment" {2204test "global variable alignment" {
2205 assert(@TypeOf(&foo).alignment == 4);2205 assert(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
2206 assert(@TypeOf(&foo) == *align(4) u8);2206 assert(@TypeOf(&foo) == *align(4) u8);
2207 const as_pointer_to_array: *[1]u8 = &foo;2207 const as_pointer_to_array: *[1]u8 = &foo;
2208 const as_slice: []u8 = as_pointer_to_array;2208 const as_slice: []u8 = as_pointer_to_array;
...@@ -4310,8 +4310,8 @@ test "fn type inference" {...@@ -4310,8 +4310,8 @@ test "fn type inference" {
4310const assert = @import("std").debug.assert;4310const assert = @import("std").debug.assert;
43114311
4312test "fn reflection" {4312test "fn reflection" {
4313 assert(@TypeOf(assert).ReturnType == void);4313 assert(@typeInfo(@TypeOf(assert)).Fn.return_type.? == void);
4314 assert(@TypeOf(assert).is_var_args == false);4314 assert(@typeInfo(@TypeOf(assert)).Fn.is_var_args == false);
4315}4315}
4316 {#code_end#}4316 {#code_end#}
4317 {#header_close#}4317 {#header_close#}
...@@ -4611,10 +4611,10 @@ test "error union" {...@@ -4611,10 +4611,10 @@ test "error union" {
4611 foo = error.SomeError;4611 foo = error.SomeError;
46124612
4613 // Use compile-time reflection to access the payload type of an error union:4613 // Use compile-time reflection to access the payload type of an error union:
4614 comptime assert(@TypeOf(foo).Payload == i32);4614 comptime assert(@typeInfo(@TypeOf(foo)).ErrorUnion.payload == i32);
46154615
4616 // Use compile-time reflection to access the error set type of an error union:4616 // Use compile-time reflection to access the error set type of an error union:
4617 comptime assert(@TypeOf(foo).ErrorSet == anyerror);4617 comptime assert(@typeInfo(@TypeOf(foo)).ErrorUnion.error_set == anyerror);
4618}4618}
4619 {#code_end#}4619 {#code_end#}
4620 {#header_open|Merging Error Sets#}4620 {#header_open|Merging Error Sets#}
...@@ -4991,7 +4991,7 @@ test "optional type" {...@@ -4991,7 +4991,7 @@ test "optional type" {
4991 foo = 1234;4991 foo = 1234;
49924992
4993 // Use compile-time reflection to access the child type of the optional:4993 // Use compile-time reflection to access the child type of the optional:
4994 comptime assert(@TypeOf(foo).Child == i32);4994 comptime assert(@typeInfo(@TypeOf(foo)).Optional.child == i32);
4995}4995}
4996 {#code_end#}4996 {#code_end#}
4997 {#header_close#}4997 {#header_close#}
...@@ -6889,7 +6889,7 @@ fn func(y: *i32) void {...@@ -6889,7 +6889,7 @@ fn func(y: *i32) void {
6889 This builtin function atomically dereferences a pointer and returns the value.6889 This builtin function atomically dereferences a pointer and returns the value.
6890 </p>6890 </p>
6891 <p>6891 <p>
6892 {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,6892 {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
6893 an integer or an enum.6893 an integer or an enum.
6894 </p>6894 </p>
6895 {#header_close#}6895 {#header_close#}
...@@ -6899,7 +6899,7 @@ fn func(y: *i32) void {...@@ -6899,7 +6899,7 @@ fn func(y: *i32) void {
6899 This builtin function atomically modifies memory and then returns the previous value.6899 This builtin function atomically modifies memory and then returns the previous value.
6900 </p>6900 </p>
6901 <p>6901 <p>
6902 {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,6902 {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
6903 an integer or an enum.6903 an integer or an enum.
6904 </p>6904 </p>
6905 <p>6905 <p>
...@@ -6925,7 +6925,7 @@ fn func(y: *i32) void {...@@ -6925,7 +6925,7 @@ fn func(y: *i32) void {
6925 This builtin function atomically stores a value.6925 This builtin function atomically stores a value.
6926 </p>6926 </p>
6927 <p>6927 <p>
6928 {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,6928 {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
6929 an integer or an enum.6929 an integer or an enum.
6930 </p>6930 </p>
6931 {#header_close#}6931 {#header_close#}
...@@ -7208,10 +7208,10 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v...@@ -7208,10 +7208,10 @@ fn cmpxchgStrongButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_v
7208 more efficiently in machine instructions.7208 more efficiently in machine instructions.
7209 </p>7209 </p>
7210 <p>7210 <p>
7211 {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,7211 {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
7212 an integer or an enum.7212 an integer or an enum.
7213 </p>7213 </p>
7214 <p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>7214 <p>{#syntax#}@typeInfo(@TypeOf(ptr)).Pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
7215 {#see_also|Compile Variables|cmpxchgWeak#}7215 {#see_also|Compile Variables|cmpxchgWeak#}
7216 {#header_close#}7216 {#header_close#}
7217 {#header_open|@cmpxchgWeak#}7217 {#header_open|@cmpxchgWeak#}
...@@ -7237,10 +7237,10 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val...@@ -7237,10 +7237,10 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val
7237 However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.7237 However if you need a stronger guarantee, use {#link|@cmpxchgStrong#}.
7238 </p>7238 </p>
7239 <p>7239 <p>
7240 {#syntax#}T{#endsyntax#} must be a {#syntax#}bool{#endsyntax#}, a float,7240 {#syntax#}T{#endsyntax#} must be a pointer, a {#syntax#}bool{#endsyntax#}, a float,
7241 an integer or an enum.7241 an integer or an enum.
7242 </p>7242 </p>
7243 <p>{#syntax#}@TypeOf(ptr).alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>7243 <p>{#syntax#}@typeInfo(@TypeOf(ptr)).Pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}</p>
7244 {#see_also|Compile Variables|cmpxchgStrong#}7244 {#see_also|Compile Variables|cmpxchgStrong#}
7245 {#header_close#}7245 {#header_close#}
72467246
lib/std/array_list.zig+10-2
...@@ -46,7 +46,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {...@@ -46,7 +46,11 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
46 /// Deinitialize with `deinit` or use `toOwnedSlice`.46 /// Deinitialize with `deinit` or use `toOwnedSlice`.
47 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {47 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
48 var self = Self.init(allocator);48 var self = Self.init(allocator);
49 try self.ensureCapacity(num);49
50 const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
51 self.items.ptr = new_memory.ptr;
52 self.capacity = new_memory.len;
53
50 return self;54 return self;
51 }55 }
5256
...@@ -366,7 +370,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ...@@ -366,7 +370,11 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
366 /// Deinitialize with `deinit` or use `toOwnedSlice`.370 /// Deinitialize with `deinit` or use `toOwnedSlice`.
367 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {371 pub fn initCapacity(allocator: *Allocator, num: usize) !Self {
368 var self = Self{};372 var self = Self{};
369 try self.ensureCapacity(allocator, num);373
374 const new_memory = try self.allocator.allocAdvanced(T, alignment, num, .at_least);
375 self.items.ptr = new_memory.ptr;
376 self.capacity = new_memory.len;
377
370 return self;378 return self;
371 }379 }
372380
lib/std/child_process.zig+3-5
...@@ -275,9 +275,7 @@ pub const ChildProcess = struct {...@@ -275,9 +275,7 @@ pub const ChildProcess = struct {
275 }275 }
276276
277 fn handleWaitResult(self: *ChildProcess, status: u32) void {277 fn handleWaitResult(self: *ChildProcess, status: u32) void {
278 // TODO https://github.com/ziglang/zig/issues/3190278 self.term = self.cleanupAfterWait(status);
279 var term = self.cleanupAfterWait(status);
280 self.term = term;
281 }279 }
282280
283 fn cleanupStreams(self: *ChildProcess) void {281 fn cleanupStreams(self: *ChildProcess) void {
...@@ -487,8 +485,8 @@ pub const ChildProcess = struct {...@@ -487,8 +485,8 @@ pub const ChildProcess = struct {
487 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);485 const any_ignore = (self.stdin_behavior == StdIo.Ignore or self.stdout_behavior == StdIo.Ignore or self.stderr_behavior == StdIo.Ignore);
488486
489 const nul_handle = if (any_ignore)487 const nul_handle = if (any_ignore)
490 windows.OpenFile(&[_]u16{ 'N', 'U', 'L' }, .{488 // "\Device\Null" or "\??\NUL"
491 .dir = std.fs.cwd().fd,489 windows.OpenFile(&[_]u16{ '\\', 'D', 'e', 'v', 'i', 'c', 'e', '\\', 'N', 'u', 'l', 'l' }, .{
492 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,490 .access_mask = windows.GENERIC_READ | windows.SYNCHRONIZE,
493 .share_access = windows.FILE_SHARE_READ,491 .share_access = windows.FILE_SHARE_READ,
494 .creation = windows.OPEN_EXISTING,492 .creation = windows.OPEN_EXISTING,
lib/std/coff.zig+66
...@@ -18,11 +18,77 @@ const IMAGE_FILE_MACHINE_I386 = 0x014c;...@@ -18,11 +18,77 @@ const IMAGE_FILE_MACHINE_I386 = 0x014c;
18const IMAGE_FILE_MACHINE_IA64 = 0x0200;18const IMAGE_FILE_MACHINE_IA64 = 0x0200;
19const IMAGE_FILE_MACHINE_AMD64 = 0x8664;19const IMAGE_FILE_MACHINE_AMD64 = 0x8664;
2020
21pub const MachineType = enum(u16) {
22 Unknown = 0x0,
23 /// Matsushita AM33
24 AM33 = 0x1d3,
25 /// x64
26 X64 = 0x8664,
27 /// ARM little endian
28 ARM = 0x1c0,
29 /// ARM64 little endian
30 ARM64 = 0xaa64,
31 /// ARM Thumb-2 little endian
32 ARMNT = 0x1c4,
33 /// EFI byte code
34 EBC = 0xebc,
35 /// Intel 386 or later processors and compatible processors
36 I386 = 0x14c,
37 /// Intel Itanium processor family
38 IA64 = 0x200,
39 /// Mitsubishi M32R little endian
40 M32R = 0x9041,
41 /// MIPS16
42 MIPS16 = 0x266,
43 /// MIPS with FPU
44 MIPSFPU = 0x366,
45 /// MIPS16 with FPU
46 MIPSFPU16 = 0x466,
47 /// Power PC little endian
48 POWERPC = 0x1f0,
49 /// Power PC with floating point support
50 POWERPCFP = 0x1f1,
51 /// MIPS little endian
52 R4000 = 0x166,
53 /// RISC-V 32-bit address space
54 RISCV32 = 0x5032,
55 /// RISC-V 64-bit address space
56 RISCV64 = 0x5064,
57 /// RISC-V 128-bit address space
58 RISCV128 = 0x5128,
59 /// Hitachi SH3
60 SH3 = 0x1a2,
61 /// Hitachi SH3 DSP
62 SH3DSP = 0x1a3,
63 /// Hitachi SH4
64 SH4 = 0x1a6,
65 /// Hitachi SH5
66 SH5 = 0x1a8,
67 /// Thumb
68 Thumb = 0x1c2,
69 /// MIPS little-endian WCE v2
70 WCEMIPSV2 = 0x169,
71};
72
21// OptionalHeader.magic values73// OptionalHeader.magic values
22// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx74// see https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx
23const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;75const IMAGE_NT_OPTIONAL_HDR32_MAGIC = 0x10b;
24const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;76const IMAGE_NT_OPTIONAL_HDR64_MAGIC = 0x20b;
2577
78// Image Characteristics
79pub const IMAGE_FILE_RELOCS_STRIPPED = 0x1;
80pub const IMAGE_FILE_DEBUG_STRIPPED = 0x200;
81pub const IMAGE_FILE_EXECUTABLE_IMAGE = 0x2;
82pub const IMAGE_FILE_32BIT_MACHINE = 0x100;
83pub const IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x20;
84
85// Section flags
86pub const IMAGE_SCN_CNT_INITIALIZED_DATA = 0x40;
87pub const IMAGE_SCN_MEM_READ = 0x40000000;
88pub const IMAGE_SCN_CNT_CODE = 0x20;
89pub const IMAGE_SCN_MEM_EXECUTE = 0x20000000;
90pub const IMAGE_SCN_MEM_WRITE = 0x80000000;
91
26const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;92const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
27const IMAGE_DEBUG_TYPE_CODEVIEW = 2;93const IMAGE_DEBUG_TYPE_CODEVIEW = 2;
28const DEBUG_DIRECTORY = 6;94const DEBUG_DIRECTORY = 6;
lib/std/debug/leb128.zig+24-23
...@@ -9,10 +9,10 @@ const testing = std.testing;...@@ -9,10 +9,10 @@ const testing = std.testing;
9/// Read a single unsigned LEB128 value from the given reader as type T,9/// Read a single unsigned LEB128 value from the given reader as type T,
10/// or error.Overflow if the value cannot fit.10/// or error.Overflow if the value cannot fit.
11pub fn readULEB128(comptime T: type, reader: anytype) !T {11pub fn readULEB128(comptime T: type, reader: anytype) !T {
12 const U = if (T.bit_count < 8) u8 else T;12 const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
13 const ShiftT = std.math.Log2Int(U);13 const ShiftT = std.math.Log2Int(U);
1414
15 const max_group = (U.bit_count + 6) / 7;15 const max_group = (@typeInfo(U).Int.bits + 6) / 7;
1616
17 var value = @as(U, 0);17 var value = @as(U, 0);
18 var group = @as(ShiftT, 0);18 var group = @as(ShiftT, 0);
...@@ -40,7 +40,7 @@ pub fn readULEB128(comptime T: type, reader: anytype) !T {...@@ -40,7 +40,7 @@ pub fn readULEB128(comptime T: type, reader: anytype) !T {
40/// Write a single unsigned integer as unsigned LEB128 to the given writer.40/// Write a single unsigned integer as unsigned LEB128 to the given writer.
41pub fn writeULEB128(writer: anytype, uint_value: anytype) !void {41pub fn writeULEB128(writer: anytype, uint_value: anytype) !void {
42 const T = @TypeOf(uint_value);42 const T = @TypeOf(uint_value);
43 const U = if (T.bit_count < 8) u8 else T;43 const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
44 var value = @intCast(U, uint_value);44 var value = @intCast(U, uint_value);
4545
46 while (true) {46 while (true) {
...@@ -68,7 +68,7 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[]const u8) !T {...@@ -68,7 +68,7 @@ pub fn readULEB128Mem(comptime T: type, ptr: *[]const u8) !T {
68/// returning the number of bytes written.68/// returning the number of bytes written.
69pub fn writeULEB128Mem(ptr: []u8, uint_value: anytype) !usize {69pub fn writeULEB128Mem(ptr: []u8, uint_value: anytype) !usize {
70 const T = @TypeOf(uint_value);70 const T = @TypeOf(uint_value);
71 const max_group = (T.bit_count + 6) / 7;71 const max_group = (@typeInfo(T).Int.bits + 6) / 7;
72 var buf = std.io.fixedBufferStream(ptr);72 var buf = std.io.fixedBufferStream(ptr);
73 try writeULEB128(buf.writer(), uint_value);73 try writeULEB128(buf.writer(), uint_value);
74 return buf.pos;74 return buf.pos;
...@@ -77,11 +77,11 @@ pub fn writeULEB128Mem(ptr: []u8, uint_value: anytype) !usize {...@@ -77,11 +77,11 @@ pub fn writeULEB128Mem(ptr: []u8, uint_value: anytype) !usize {
77/// Read a single signed LEB128 value from the given reader as type T,77/// Read a single signed LEB128 value from the given reader as type T,
78/// or error.Overflow if the value cannot fit.78/// or error.Overflow if the value cannot fit.
79pub fn readILEB128(comptime T: type, reader: anytype) !T {79pub fn readILEB128(comptime T: type, reader: anytype) !T {
80 const S = if (T.bit_count < 8) i8 else T;80 const S = if (@typeInfo(T).Int.bits < 8) i8 else T;
81 const U = std.meta.Int(false, S.bit_count);81 const U = std.meta.Int(false, @typeInfo(S).Int.bits);
82 const ShiftU = std.math.Log2Int(U);82 const ShiftU = std.math.Log2Int(U);
8383
84 const max_group = (U.bit_count + 6) / 7;84 const max_group = (@typeInfo(U).Int.bits + 6) / 7;
8585
86 var value = @as(U, 0);86 var value = @as(U, 0);
87 var group = @as(ShiftU, 0);87 var group = @as(ShiftU, 0);
...@@ -97,7 +97,7 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T {...@@ -97,7 +97,7 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T {
97 if (@bitCast(S, temp) >= 0) return error.Overflow;97 if (@bitCast(S, temp) >= 0) return error.Overflow;
9898
99 // and all the overflowed bits are 199 // and all the overflowed bits are 1
100 const remaining_shift = @intCast(u3, U.bit_count - @as(u16, shift));100 const remaining_shift = @intCast(u3, @typeInfo(U).Int.bits - @as(u16, shift));
101 const remaining_bits = @bitCast(i8, byte | 0x80) >> remaining_shift;101 const remaining_bits = @bitCast(i8, byte | 0x80) >> remaining_shift;
102 if (remaining_bits != -1) return error.Overflow;102 if (remaining_bits != -1) return error.Overflow;
103 }103 }
...@@ -127,8 +127,8 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T {...@@ -127,8 +127,8 @@ pub fn readILEB128(comptime T: type, reader: anytype) !T {
127/// Write a single signed integer as signed LEB128 to the given writer.127/// Write a single signed integer as signed LEB128 to the given writer.
128pub fn writeILEB128(writer: anytype, int_value: anytype) !void {128pub fn writeILEB128(writer: anytype, int_value: anytype) !void {
129 const T = @TypeOf(int_value);129 const T = @TypeOf(int_value);
130 const S = if (T.bit_count < 8) i8 else T;130 const S = if (@typeInfo(T).Int.bits < 8) i8 else T;
131 const U = std.meta.Int(false, S.bit_count);131 const U = std.meta.Int(false, @typeInfo(S).Int.bits);
132132
133 var value = @intCast(S, int_value);133 var value = @intCast(S, int_value);
134134
...@@ -173,7 +173,7 @@ pub fn writeILEB128Mem(ptr: []u8, int_value: anytype) !usize {...@@ -173,7 +173,7 @@ pub fn writeILEB128Mem(ptr: []u8, int_value: anytype) !usize {
173/// different value without shifting all the following code.173/// different value without shifting all the following code.
174pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(false, l * 7)) void {174pub fn writeUnsignedFixed(comptime l: usize, ptr: *[l]u8, int: std.meta.Int(false, l * 7)) void {
175 const T = @TypeOf(int);175 const T = @TypeOf(int);
176 const U = if (T.bit_count < 8) u8 else T;176 const U = if (@typeInfo(T).Int.bits < 8) u8 else T;
177 var value = @intCast(U, int);177 var value = @intCast(U, int);
178178
179 comptime var i = 0;179 comptime var i = 0;
...@@ -346,28 +346,29 @@ test "deserialize unsigned LEB128" {...@@ -346,28 +346,29 @@ test "deserialize unsigned LEB128" {
346346
347fn test_write_leb128(value: anytype) !void {347fn test_write_leb128(value: anytype) !void {
348 const T = @TypeOf(value);348 const T = @TypeOf(value);
349 const t_signed = @typeInfo(T).Int.is_signed;
349350
350 const writeStream = if (T.is_signed) writeILEB128 else writeULEB128;351 const writeStream = if (t_signed) writeILEB128 else writeULEB128;
351 const writeMem = if (T.is_signed) writeILEB128Mem else writeULEB128Mem;352 const writeMem = if (t_signed) writeILEB128Mem else writeULEB128Mem;
352 const readStream = if (T.is_signed) readILEB128 else readULEB128;353 const readStream = if (t_signed) readILEB128 else readULEB128;
353 const readMem = if (T.is_signed) readILEB128Mem else readULEB128Mem;354 const readMem = if (t_signed) readILEB128Mem else readULEB128Mem;
354355
355 // decode to a larger bit size too, to ensure sign extension356 // decode to a larger bit size too, to ensure sign extension
356 // is working as expected357 // is working as expected
357 const larger_type_bits = ((T.bit_count + 8) / 8) * 8;358 const larger_type_bits = ((@typeInfo(T).Int.bits + 8) / 8) * 8;
358 const B = std.meta.Int(T.is_signed, larger_type_bits);359 const B = std.meta.Int(t_signed, larger_type_bits);
359360
360 const bytes_needed = bn: {361 const bytes_needed = bn: {
361 const S = std.meta.Int(T.is_signed, @sizeOf(T) * 8);362 const S = std.meta.Int(t_signed, @sizeOf(T) * 8);
362 if (T.bit_count <= 7) break :bn @as(u16, 1);363 if (@typeInfo(T).Int.bits <= 7) break :bn @as(u16, 1);
363364
364 const unused_bits = if (value < 0) @clz(T, ~value) else @clz(T, value);365 const unused_bits = if (value < 0) @clz(T, ~value) else @clz(T, value);
365 const used_bits: u16 = (T.bit_count - unused_bits) + @boolToInt(T.is_signed);366 const used_bits: u16 = (@typeInfo(T).Int.bits - unused_bits) + @boolToInt(t_signed);
366 if (used_bits <= 7) break :bn @as(u16, 1);367 if (used_bits <= 7) break :bn @as(u16, 1);
367 break :bn ((used_bits + 6) / 7);368 break :bn ((used_bits + 6) / 7);
368 };369 };
369370
370 const max_groups = if (T.bit_count == 0) 1 else (T.bit_count + 6) / 7;371 const max_groups = if (@typeInfo(T).Int.bits == 0) 1 else (@typeInfo(T).Int.bits + 6) / 7;
371372
372 var buf: [max_groups]u8 = undefined;373 var buf: [max_groups]u8 = undefined;
373 var fbs = std.io.fixedBufferStream(&buf);374 var fbs = std.io.fixedBufferStream(&buf);
...@@ -414,7 +415,7 @@ test "serialize unsigned LEB128" {...@@ -414,7 +415,7 @@ test "serialize unsigned LEB128" {
414 const T = std.meta.Int(false, t);415 const T = std.meta.Int(false, t);
415 const min = std.math.minInt(T);416 const min = std.math.minInt(T);
416 const max = std.math.maxInt(T);417 const max = std.math.maxInt(T);
417 var i = @as(std.meta.Int(false, T.bit_count + 1), min);418 var i = @as(std.meta.Int(false, @typeInfo(T).Int.bits + 1), min);
418419
419 while (i <= max) : (i += 1) try test_write_leb128(@intCast(T, i));420 while (i <= max) : (i += 1) try test_write_leb128(@intCast(T, i));
420 }421 }
...@@ -432,7 +433,7 @@ test "serialize signed LEB128" {...@@ -432,7 +433,7 @@ test "serialize signed LEB128" {
432 const T = std.meta.Int(true, t);433 const T = std.meta.Int(true, t);
433 const min = std.math.minInt(T);434 const min = std.math.minInt(T);
434 const max = std.math.maxInt(T);435 const max = std.math.maxInt(T);
435 var i = @as(std.meta.Int(true, T.bit_count + 1), min);436 var i = @as(std.meta.Int(true, @typeInfo(T).Int.bits + 1), min);
436437
437 while (i <= max) : (i += 1) try test_write_leb128(@intCast(T, i));438 while (i <= max) : (i += 1) try test_write_leb128(@intCast(T, i));
438 }439 }
lib/std/fmt.zig+13-10
...@@ -82,6 +82,8 @@ fn peekIsAlign(comptime fmt: []const u8) bool {...@@ -82,6 +82,8 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
82/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.82/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
83///83///
84/// A user type may be a `struct`, `vector`, `union` or `enum` type.84/// A user type may be a `struct`, `vector`, `union` or `enum` type.
85///
86/// To print literal curly braces, escape them by writing them twice, e.g. `{{` or `}}`.
85pub fn format(87pub fn format(
86 writer: anytype,88 writer: anytype,
87 comptime fmt: []const u8,89 comptime fmt: []const u8,
...@@ -91,7 +93,7 @@ pub fn format(...@@ -91,7 +93,7 @@ pub fn format(
91 if (@typeInfo(@TypeOf(args)) != .Struct) {93 if (@typeInfo(@TypeOf(args)) != .Struct) {
92 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));94 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
93 }95 }
94 if (args.len > ArgSetType.bit_count) {96 if (args.len > @typeInfo(ArgSetType).Int.bits) {
95 @compileError("32 arguments max are supported per format call");97 @compileError("32 arguments max are supported per format call");
96 }98 }
9799
...@@ -325,7 +327,7 @@ pub fn formatType(...@@ -325,7 +327,7 @@ pub fn formatType(
325 max_depth: usize,327 max_depth: usize,
326) @TypeOf(writer).Error!void {328) @TypeOf(writer).Error!void {
327 if (comptime std.mem.eql(u8, fmt, "*")) {329 if (comptime std.mem.eql(u8, fmt, "*")) {
328 try writer.writeAll(@typeName(@TypeOf(value).Child));330 try writer.writeAll(@typeName(@typeInfo(@TypeOf(value)).Pointer.child));
329 try writer.writeAll("@");331 try writer.writeAll("@");
330 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);332 try formatInt(@ptrToInt(value), 16, false, FormatOptions{}, writer);
331 return;333 return;
...@@ -430,12 +432,12 @@ pub fn formatType(...@@ -430,12 +432,12 @@ pub fn formatType(
430 if (info.child == u8) {432 if (info.child == u8) {
431 return formatText(value, fmt, options, writer);433 return formatText(value, fmt, options, writer);
432 }434 }
433 return format(writer, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });435 return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) });
434 },436 },
435 .Enum, .Union, .Struct => {437 .Enum, .Union, .Struct => {
436 return formatType(value.*, fmt, options, writer, max_depth);438 return formatType(value.*, fmt, options, writer, max_depth);
437 },439 },
438 else => return format(writer, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) }),440 else => return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) }),
439 },441 },
440 .Many, .C => {442 .Many, .C => {
441 if (ptr_info.sentinel) |sentinel| {443 if (ptr_info.sentinel) |sentinel| {
...@@ -446,7 +448,7 @@ pub fn formatType(...@@ -446,7 +448,7 @@ pub fn formatType(
446 return formatText(mem.span(value), fmt, options, writer);448 return formatText(mem.span(value), fmt, options, writer);
447 }449 }
448 }450 }
449 return format(writer, "{}@{x}", .{ @typeName(T.Child), @ptrToInt(value) });451 return format(writer, "{}@{x}", .{ @typeName(@typeInfo(T).Pointer.child), @ptrToInt(value) });
450 },452 },
451 .Slice => {453 .Slice => {
452 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {454 if (fmt.len > 0 and ((fmt[0] == 'x') or (fmt[0] == 'X'))) {
...@@ -536,7 +538,7 @@ pub fn formatIntValue(...@@ -536,7 +538,7 @@ pub fn formatIntValue(
536 radix = 10;538 radix = 10;
537 uppercase = false;539 uppercase = false;
538 } else if (comptime std.mem.eql(u8, fmt, "c")) {540 } else if (comptime std.mem.eql(u8, fmt, "c")) {
539 if (@TypeOf(int_value).bit_count <= 8) {541 if (@typeInfo(@TypeOf(int_value)).Int.bits <= 8) {
540 return formatAsciiChar(@as(u8, int_value), options, writer);542 return formatAsciiChar(@as(u8, int_value), options, writer);
541 } else {543 } else {
542 @compileError("Cannot print integer that is larger than 8 bits as a ascii");544 @compileError("Cannot print integer that is larger than 8 bits as a ascii");
...@@ -945,7 +947,7 @@ pub fn formatInt(...@@ -945,7 +947,7 @@ pub fn formatInt(
945 } else947 } else
946 value;948 value;
947949
948 if (@TypeOf(int_value).is_signed) {950 if (@typeInfo(@TypeOf(int_value)).Int.is_signed) {
949 return formatIntSigned(int_value, base, uppercase, options, writer);951 return formatIntSigned(int_value, base, uppercase, options, writer);
950 } else {952 } else {
951 return formatIntUnsigned(int_value, base, uppercase, options, writer);953 return formatIntUnsigned(int_value, base, uppercase, options, writer);
...@@ -987,9 +989,10 @@ fn formatIntUnsigned(...@@ -987,9 +989,10 @@ fn formatIntUnsigned(
987 writer: anytype,989 writer: anytype,
988) !void {990) !void {
989 assert(base >= 2);991 assert(base >= 2);
990 var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined;992 const value_info = @typeInfo(@TypeOf(value)).Int;
991 const min_int_bits = comptime math.max(@TypeOf(value).bit_count, @TypeOf(base).bit_count);993 var buf: [math.max(value_info.bits, 1)]u8 = undefined;
992 const MinInt = std.meta.Int(@TypeOf(value).is_signed, min_int_bits);994 const min_int_bits = comptime math.max(value_info.bits, @typeInfo(@TypeOf(base)).Int.bits);
995 const MinInt = std.meta.Int(value_info.is_signed, min_int_bits);
993 var a: MinInt = value;996 var a: MinInt = value;
994 var index: usize = buf.len;997 var index: usize = buf.len;
995998
lib/std/fmt/parse_float.zig+1-1
...@@ -374,7 +374,7 @@ test "fmt.parseFloat" {...@@ -374,7 +374,7 @@ test "fmt.parseFloat" {
374 const epsilon = 1e-7;374 const epsilon = 1e-7;
375375
376 inline for ([_]type{ f16, f32, f64, f128 }) |T| {376 inline for ([_]type{ f16, f32, f64, f128 }) |T| {
377 const Z = std.meta.Int(false, T.bit_count);377 const Z = std.meta.Int(false, @typeInfo(T).Float.bits);
378378
379 testing.expectError(error.InvalidCharacter, parseFloat(T, ""));379 testing.expectError(error.InvalidCharacter, parseFloat(T, ""));
380 testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));380 testing.expectError(error.InvalidCharacter, parseFloat(T, " 1"));
lib/std/fs.zig+9-3
...@@ -1437,26 +1437,32 @@ pub const Dir = struct {...@@ -1437,26 +1437,32 @@ pub const Dir = struct {
1437 /// On success, caller owns returned buffer.1437 /// On success, caller owns returned buffer.
1438 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.1438 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1439 pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {1439 pub fn readFileAlloc(self: Dir, allocator: *mem.Allocator, file_path: []const u8, max_bytes: usize) ![]u8 {
1440 return self.readFileAllocOptions(allocator, file_path, max_bytes, @alignOf(u8), null);1440 return self.readFileAllocOptions(allocator, file_path, max_bytes, null, @alignOf(u8), null);
1441 }1441 }
14421442
1443 /// On success, caller owns returned buffer.1443 /// On success, caller owns returned buffer.
1444 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.1444 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
1445 /// If `size_hint` is specified the initial buffer size is calculated using
1446 /// that value, otherwise the effective file size is used instead.
1445 /// Allows specifying alignment and a sentinel value.1447 /// Allows specifying alignment and a sentinel value.
1446 pub fn readFileAllocOptions(1448 pub fn readFileAllocOptions(
1447 self: Dir,1449 self: Dir,
1448 allocator: *mem.Allocator,1450 allocator: *mem.Allocator,
1449 file_path: []const u8,1451 file_path: []const u8,
1450 max_bytes: usize,1452 max_bytes: usize,
1453 size_hint: ?usize,
1451 comptime alignment: u29,1454 comptime alignment: u29,
1452 comptime optional_sentinel: ?u8,1455 comptime optional_sentinel: ?u8,
1453 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {1456 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
1454 var file = try self.openFile(file_path, .{});1457 var file = try self.openFile(file_path, .{});
1455 defer file.close();1458 defer file.close();
14561459
1457 const stat_size = try file.getEndPos();1460 // If the file size doesn't fit a usize it'll be certainly greater than
1461 // `max_bytes`
1462 const stat_size = size_hint orelse math.cast(usize, try file.getEndPos()) catch
1463 return error.FileTooBig;
14581464
1459 return file.readAllAllocOptions(allocator, stat_size, max_bytes, alignment, optional_sentinel);1465 return file.readToEndAllocOptions(allocator, max_bytes, stat_size, alignment, optional_sentinel);
1460 }1466 }
14611467
1462 pub const DeleteTreeError = error{1468 pub const DeleteTreeError = error{
lib/std/fs/file.zig+29-11
...@@ -363,31 +363,49 @@ pub const File = struct {...@@ -363,31 +363,49 @@ pub const File = struct {
363 try os.futimens(self.handle, &times);363 try os.futimens(self.handle, &times);
364 }364 }
365365
366 /// Reads all the bytes from the current position to the end of the file.
366 /// On success, caller owns returned buffer.367 /// On success, caller owns returned buffer.
367 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.368 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
368 pub fn readAllAlloc(self: File, allocator: *mem.Allocator, stat_size: u64, max_bytes: usize) ![]u8 {369 pub fn readToEndAlloc(self: File, allocator: *mem.Allocator, max_bytes: usize) ![]u8 {
369 return self.readAllAllocOptions(allocator, stat_size, max_bytes, @alignOf(u8), null);370 return self.readToEndAllocOptions(allocator, max_bytes, null, @alignOf(u8), null);
370 }371 }
371372
373 /// Reads all the bytes from the current position to the end of the file.
372 /// On success, caller owns returned buffer.374 /// On success, caller owns returned buffer.
373 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.375 /// If the file is larger than `max_bytes`, returns `error.FileTooBig`.
376 /// If `size_hint` is specified the initial buffer size is calculated using
377 /// that value, otherwise an arbitrary value is used instead.
374 /// Allows specifying alignment and a sentinel value.378 /// Allows specifying alignment and a sentinel value.
375 pub fn readAllAllocOptions(379 pub fn readToEndAllocOptions(
376 self: File,380 self: File,
377 allocator: *mem.Allocator,381 allocator: *mem.Allocator,
378 stat_size: u64,
379 max_bytes: usize,382 max_bytes: usize,
383 size_hint: ?usize,
380 comptime alignment: u29,384 comptime alignment: u29,
381 comptime optional_sentinel: ?u8,385 comptime optional_sentinel: ?u8,
382 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {386 ) !(if (optional_sentinel) |s| [:s]align(alignment) u8 else []align(alignment) u8) {
383 const size = math.cast(usize, stat_size) catch math.maxInt(usize);387 // If no size hint is provided fall back to the size=0 code path
384 if (size > max_bytes) return error.FileTooBig;388 const size = size_hint orelse 0;
385389
386 const buf = try allocator.allocWithOptions(u8, size, alignment, optional_sentinel);390 // The file size returned by stat is used as hint to set the buffer
387 errdefer allocator.free(buf);391 // size. If the reported size is zero, as it happens on Linux for files
392 // in /proc, a small buffer is allocated instead.
393 const initial_cap = (if (size > 0) size else 1024) + @boolToInt(optional_sentinel != null);
394 var array_list = try std.ArrayListAligned(u8, alignment).initCapacity(allocator, initial_cap);
395 defer array_list.deinit();
396
397 self.reader().readAllArrayList(&array_list, max_bytes) catch |err| switch (err) {
398 error.StreamTooLong => return error.FileTooBig,
399 else => |e| return e,
400 };
388401
389 try self.reader().readNoEof(buf);402 if (optional_sentinel) |sentinel| {
390 return buf;403 try array_list.append(sentinel);
404 const buf = array_list.toOwnedSlice();
405 return buf[0 .. buf.len - 1 :sentinel];
406 } else {
407 return array_list.toOwnedSlice();
408 }
391 }409 }
392410
393 pub const ReadError = os.ReadError;411 pub const ReadError = os.ReadError;
lib/std/fs/test.zig+5-5
...@@ -188,30 +188,30 @@ test "readAllAlloc" {...@@ -188,30 +188,30 @@ test "readAllAlloc" {
188 var file = try tmp_dir.dir.createFile("test_file", .{ .read = true });188 var file = try tmp_dir.dir.createFile("test_file", .{ .read = true });
189 defer file.close();189 defer file.close();
190190
191 const buf1 = try file.readAllAlloc(testing.allocator, 0, 1024);191 const buf1 = try file.readToEndAlloc(testing.allocator, 1024);
192 defer testing.allocator.free(buf1);192 defer testing.allocator.free(buf1);
193 testing.expect(buf1.len == 0);193 testing.expect(buf1.len == 0);
194194
195 const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n";195 const write_buf: []const u8 = "this is a test.\nthis is a test.\nthis is a test.\nthis is a test.\n";
196 try file.writeAll(write_buf);196 try file.writeAll(write_buf);
197 try file.seekTo(0);197 try file.seekTo(0);
198 const file_size = try file.getEndPos();
199198
200 // max_bytes > file_size199 // max_bytes > file_size
201 const buf2 = try file.readAllAlloc(testing.allocator, file_size, 1024);200 const buf2 = try file.readToEndAlloc(testing.allocator, 1024);
202 defer testing.allocator.free(buf2);201 defer testing.allocator.free(buf2);
203 testing.expectEqual(write_buf.len, buf2.len);202 testing.expectEqual(write_buf.len, buf2.len);
204 testing.expect(std.mem.eql(u8, write_buf, buf2));203 testing.expect(std.mem.eql(u8, write_buf, buf2));
205 try file.seekTo(0);204 try file.seekTo(0);
206205
207 // max_bytes == file_size206 // max_bytes == file_size
208 const buf3 = try file.readAllAlloc(testing.allocator, file_size, write_buf.len);207 const buf3 = try file.readToEndAlloc(testing.allocator, write_buf.len);
209 defer testing.allocator.free(buf3);208 defer testing.allocator.free(buf3);
210 testing.expectEqual(write_buf.len, buf3.len);209 testing.expectEqual(write_buf.len, buf3.len);
211 testing.expect(std.mem.eql(u8, write_buf, buf3));210 testing.expect(std.mem.eql(u8, write_buf, buf3));
211 try file.seekTo(0);
212212
213 // max_bytes < file_size213 // max_bytes < file_size
214 testing.expectError(error.FileTooBig, file.readAllAlloc(testing.allocator, file_size, write_buf.len - 1));214 testing.expectError(error.FileTooBig, file.readToEndAlloc(testing.allocator, write_buf.len - 1));
215}215}
216216
217test "directory operations on files" {217test "directory operations on files" {
lib/std/hash/auto_hash.zig+1-1
...@@ -113,7 +113,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {...@@ -113,7 +113,7 @@ pub fn hash(hasher: anytype, key: anytype, comptime strat: HashStrategy) void {
113 .Array => hashArray(hasher, key, strat),113 .Array => hashArray(hasher, key, strat),
114114
115 .Vector => |info| {115 .Vector => |info| {
116 if (info.child.bit_count % 8 == 0) {116 if (std.meta.bitCount(info.child) % 8 == 0) {
117 // If there's no unused bits in the child type, we can just hash117 // If there's no unused bits in the child type, we can just hash
118 // this as an array of bytes.118 // this as an array of bytes.
119 hasher.update(mem.asBytes(&key));119 hasher.update(mem.asBytes(&key));
lib/std/heap.zig+5-1
...@@ -915,6 +915,10 @@ pub fn testAllocator(base_allocator: *mem.Allocator) !void {...@@ -915,6 +915,10 @@ pub fn testAllocator(base_allocator: *mem.Allocator) !void {
915 testing.expect(slice.len == 10);915 testing.expect(slice.len == 10);
916916
917 allocator.free(slice);917 allocator.free(slice);
918
919 const zero_bit_ptr = try allocator.create(u0);
920 zero_bit_ptr.* = 0;
921 allocator.destroy(zero_bit_ptr);
918}922}
919923
920pub fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void {924pub fn testAllocatorAligned(base_allocator: *mem.Allocator, comptime alignment: u29) !void {
...@@ -952,7 +956,7 @@ pub fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator...@@ -952,7 +956,7 @@ pub fn testAllocatorLargeAlignment(base_allocator: *mem.Allocator) mem.Allocator
952 // very near usize?956 // very near usize?
953 if (mem.page_size << 2 > maxInt(usize)) return;957 if (mem.page_size << 2 > maxInt(usize)) return;
954958
955 const USizeShift = std.meta.Int(false, std.math.log2(usize.bit_count));959 const USizeShift = std.meta.Int(false, std.math.log2(std.meta.bitCount(usize)));
956 const large_align = @as(u29, mem.page_size << 2);960 const large_align = @as(u29, mem.page_size << 2);
957961
958 var align_mask: usize = undefined;962 var align_mask: usize = undefined;
lib/std/io/reader.zig+5-5
...@@ -198,28 +198,28 @@ pub fn Reader(...@@ -198,28 +198,28 @@ pub fn Reader(
198198
199 /// Reads a native-endian integer199 /// Reads a native-endian integer
200 pub fn readIntNative(self: Self, comptime T: type) !T {200 pub fn readIntNative(self: Self, comptime T: type) !T {
201 const bytes = try self.readBytesNoEof((T.bit_count + 7) / 8);201 const bytes = try self.readBytesNoEof((@typeInfo(T).Int.bits + 7) / 8);
202 return mem.readIntNative(T, &bytes);202 return mem.readIntNative(T, &bytes);
203 }203 }
204204
205 /// Reads a foreign-endian integer205 /// Reads a foreign-endian integer
206 pub fn readIntForeign(self: Self, comptime T: type) !T {206 pub fn readIntForeign(self: Self, comptime T: type) !T {
207 const bytes = try self.readBytesNoEof((T.bit_count + 7) / 8);207 const bytes = try self.readBytesNoEof((@typeInfo(T).Int.bits + 7) / 8);
208 return mem.readIntForeign(T, &bytes);208 return mem.readIntForeign(T, &bytes);
209 }209 }
210210
211 pub fn readIntLittle(self: Self, comptime T: type) !T {211 pub fn readIntLittle(self: Self, comptime T: type) !T {
212 const bytes = try self.readBytesNoEof((T.bit_count + 7) / 8);212 const bytes = try self.readBytesNoEof((@typeInfo(T).Int.bits + 7) / 8);
213 return mem.readIntLittle(T, &bytes);213 return mem.readIntLittle(T, &bytes);
214 }214 }
215215
216 pub fn readIntBig(self: Self, comptime T: type) !T {216 pub fn readIntBig(self: Self, comptime T: type) !T {
217 const bytes = try self.readBytesNoEof((T.bit_count + 7) / 8);217 const bytes = try self.readBytesNoEof((@typeInfo(T).Int.bits + 7) / 8);
218 return mem.readIntBig(T, &bytes);218 return mem.readIntBig(T, &bytes);
219 }219 }
220220
221 pub fn readInt(self: Self, comptime T: type, endian: builtin.Endian) !T {221 pub fn readInt(self: Self, comptime T: type, endian: builtin.Endian) !T {
222 const bytes = try self.readBytesNoEof((T.bit_count + 7) / 8);222 const bytes = try self.readBytesNoEof((@typeInfo(T).Int.bits + 7) / 8);
223 return mem.readInt(T, &bytes, endian);223 return mem.readInt(T, &bytes, endian);
224 }224 }
225225
lib/std/io/serialization.zig+3-3
...@@ -60,7 +60,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -60,7 +60,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
6060
61 const U = std.meta.Int(false, t_bit_count);61 const U = std.meta.Int(false, t_bit_count);
62 const Log2U = math.Log2Int(U);62 const Log2U = math.Log2Int(U);
63 const int_size = (U.bit_count + 7) / 8;63 const int_size = (t_bit_count + 7) / 8;
6464
65 if (packing == .Bit) {65 if (packing == .Bit) {
66 const result = try self.in_stream.readBitsNoEof(U, t_bit_count);66 const result = try self.in_stream.readBitsNoEof(U, t_bit_count);
...@@ -73,7 +73,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,...@@ -73,7 +73,7 @@ pub fn Deserializer(comptime endian: builtin.Endian, comptime packing: Packing,
7373
74 if (int_size == 1) {74 if (int_size == 1) {
75 if (t_bit_count == 8) return @bitCast(T, buffer[0]);75 if (t_bit_count == 8) return @bitCast(T, buffer[0]);
76 const PossiblySignedByte = std.meta.Int(T.is_signed, 8);76 const PossiblySignedByte = std.meta.Int(@typeInfo(T).Int.is_signed, 8);
77 return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));77 return @truncate(T, @bitCast(PossiblySignedByte, buffer[0]));
78 }78 }
7979
...@@ -247,7 +247,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co...@@ -247,7 +247,7 @@ pub fn Serializer(comptime endian: builtin.Endian, comptime packing: Packing, co
247247
248 const U = std.meta.Int(false, t_bit_count);248 const U = std.meta.Int(false, t_bit_count);
249 const Log2U = math.Log2Int(U);249 const Log2U = math.Log2Int(U);
250 const int_size = (U.bit_count + 7) / 8;250 const int_size = (t_bit_count + 7) / 8;
251251
252 const u_value = @bitCast(U, value);252 const u_value = @bitCast(U, value);
253253
lib/std/io/writer.zig+5-5
...@@ -53,7 +53,7 @@ pub fn Writer(...@@ -53,7 +53,7 @@ pub fn Writer(
53 /// Write a native-endian integer.53 /// Write a native-endian integer.
54 /// TODO audit non-power-of-two int sizes54 /// TODO audit non-power-of-two int sizes
55 pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {55 pub fn writeIntNative(self: Self, comptime T: type, value: T) Error!void {
56 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;56 var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
57 mem.writeIntNative(T, &bytes, value);57 mem.writeIntNative(T, &bytes, value);
58 return self.writeAll(&bytes);58 return self.writeAll(&bytes);
59 }59 }
...@@ -61,28 +61,28 @@ pub fn Writer(...@@ -61,28 +61,28 @@ pub fn Writer(
61 /// Write a foreign-endian integer.61 /// Write a foreign-endian integer.
62 /// TODO audit non-power-of-two int sizes62 /// TODO audit non-power-of-two int sizes
63 pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {63 pub fn writeIntForeign(self: Self, comptime T: type, value: T) Error!void {
64 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;64 var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
65 mem.writeIntForeign(T, &bytes, value);65 mem.writeIntForeign(T, &bytes, value);
66 return self.writeAll(&bytes);66 return self.writeAll(&bytes);
67 }67 }
6868
69 /// TODO audit non-power-of-two int sizes69 /// TODO audit non-power-of-two int sizes
70 pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {70 pub fn writeIntLittle(self: Self, comptime T: type, value: T) Error!void {
71 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;71 var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
72 mem.writeIntLittle(T, &bytes, value);72 mem.writeIntLittle(T, &bytes, value);
73 return self.writeAll(&bytes);73 return self.writeAll(&bytes);
74 }74 }
7575
76 /// TODO audit non-power-of-two int sizes76 /// TODO audit non-power-of-two int sizes
77 pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {77 pub fn writeIntBig(self: Self, comptime T: type, value: T) Error!void {
78 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;78 var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
79 mem.writeIntBig(T, &bytes, value);79 mem.writeIntBig(T, &bytes, value);
80 return self.writeAll(&bytes);80 return self.writeAll(&bytes);
81 }81 }
8282
83 /// TODO audit non-power-of-two int sizes83 /// TODO audit non-power-of-two int sizes
84 pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {84 pub fn writeInt(self: Self, comptime T: type, value: T, endian: builtin.Endian) Error!void {
85 var bytes: [(T.bit_count + 7) / 8]u8 = undefined;85 var bytes: [(@typeInfo(T).Int.bits + 7) / 8]u8 = undefined;
86 mem.writeInt(T, &bytes, value, endian);86 mem.writeInt(T, &bytes, value, endian);
87 return self.writeAll(&bytes);87 return self.writeAll(&bytes);
88 }88 }
lib/std/log.zig+4
...@@ -127,6 +127,10 @@ fn log(...@@ -127,6 +127,10 @@ fn log(
127 if (@enumToInt(message_level) <= @enumToInt(level)) {127 if (@enumToInt(message_level) <= @enumToInt(level)) {
128 if (@hasDecl(root, "log")) {128 if (@hasDecl(root, "log")) {
129 root.log(message_level, scope, format, args);129 root.log(message_level, scope, format, args);
130 } else if (std.Target.current.os.tag == .freestanding) {
131 // On freestanding one must provide a log function; we do not have
132 // any I/O configured.
133 return;
130 } else if (builtin.mode != .ReleaseSmall) {134 } else if (builtin.mode != .ReleaseSmall) {
131 const held = std.debug.getStderrMutex().acquire();135 const held = std.debug.getStderrMutex().acquire();
132 defer held.release();136 defer held.release();
lib/std/math.zig+32-31
...@@ -195,7 +195,7 @@ test "" {...@@ -195,7 +195,7 @@ test "" {
195pub fn floatMantissaBits(comptime T: type) comptime_int {195pub fn floatMantissaBits(comptime T: type) comptime_int {
196 assert(@typeInfo(T) == .Float);196 assert(@typeInfo(T) == .Float);
197197
198 return switch (T.bit_count) {198 return switch (@typeInfo(T).Float.bits) {
199 16 => 10,199 16 => 10,
200 32 => 23,200 32 => 23,
201 64 => 52,201 64 => 52,
...@@ -208,7 +208,7 @@ pub fn floatMantissaBits(comptime T: type) comptime_int {...@@ -208,7 +208,7 @@ pub fn floatMantissaBits(comptime T: type) comptime_int {
208pub fn floatExponentBits(comptime T: type) comptime_int {208pub fn floatExponentBits(comptime T: type) comptime_int {
209 assert(@typeInfo(T) == .Float);209 assert(@typeInfo(T) == .Float);
210210
211 return switch (T.bit_count) {211 return switch (@typeInfo(T).Float.bits) {
212 16 => 5,212 16 => 5,
213 32 => 8,213 32 => 8,
214 64 => 11,214 64 => 11,
...@@ -347,9 +347,9 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {...@@ -347,9 +347,9 @@ pub fn shlExact(comptime T: type, a: T, shift_amt: Log2Int(T)) !T {
347/// A negative shift amount results in a right shift.347/// A negative shift amount results in a right shift.
348pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {348pub fn shl(comptime T: type, a: T, shift_amt: anytype) T {
349 const abs_shift_amt = absCast(shift_amt);349 const abs_shift_amt = absCast(shift_amt);
350 const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);350 const casted_shift_amt = if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0 else @intCast(Log2Int(T), abs_shift_amt);
351351
352 if (@TypeOf(shift_amt) == comptime_int or @TypeOf(shift_amt).is_signed) {352 if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.is_signed) {
353 if (shift_amt < 0) {353 if (shift_amt < 0) {
354 return a >> casted_shift_amt;354 return a >> casted_shift_amt;
355 }355 }
...@@ -373,9 +373,9 @@ test "math.shl" {...@@ -373,9 +373,9 @@ test "math.shl" {
373/// A negative shift amount results in a left shift.373/// A negative shift amount results in a left shift.
374pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {374pub fn shr(comptime T: type, a: T, shift_amt: anytype) T {
375 const abs_shift_amt = absCast(shift_amt);375 const abs_shift_amt = absCast(shift_amt);
376 const casted_shift_amt = if (abs_shift_amt >= T.bit_count) return 0 else @intCast(Log2Int(T), abs_shift_amt);376 const casted_shift_amt = if (abs_shift_amt >= @typeInfo(T).Int.bits) return 0 else @intCast(Log2Int(T), abs_shift_amt);
377377
378 if (@TypeOf(shift_amt) == comptime_int or @TypeOf(shift_amt).is_signed) {378 if (@TypeOf(shift_amt) == comptime_int or @typeInfo(@TypeOf(shift_amt)).Int.is_signed) {
379 if (shift_amt >= 0) {379 if (shift_amt >= 0) {
380 return a >> casted_shift_amt;380 return a >> casted_shift_amt;
381 } else {381 } else {
...@@ -400,11 +400,11 @@ test "math.shr" {...@@ -400,11 +400,11 @@ test "math.shr" {
400/// Rotates right. Only unsigned values can be rotated.400/// Rotates right. Only unsigned values can be rotated.
401/// Negative shift values results in shift modulo the bit count.401/// Negative shift values results in shift modulo the bit count.
402pub fn rotr(comptime T: type, x: T, r: anytype) T {402pub fn rotr(comptime T: type, x: T, r: anytype) T {
403 if (T.is_signed) {403 if (@typeInfo(T).Int.is_signed) {
404 @compileError("cannot rotate signed integer");404 @compileError("cannot rotate signed integer");
405 } else {405 } else {
406 const ar = @mod(r, T.bit_count);406 const ar = @mod(r, @typeInfo(T).Int.bits);
407 return shr(T, x, ar) | shl(T, x, T.bit_count - ar);407 return shr(T, x, ar) | shl(T, x, @typeInfo(T).Int.bits - ar);
408 }408 }
409}409}
410410
...@@ -419,11 +419,11 @@ test "math.rotr" {...@@ -419,11 +419,11 @@ test "math.rotr" {
419/// Rotates left. Only unsigned values can be rotated.419/// Rotates left. Only unsigned values can be rotated.
420/// Negative shift values results in shift modulo the bit count.420/// Negative shift values results in shift modulo the bit count.
421pub fn rotl(comptime T: type, x: T, r: anytype) T {421pub fn rotl(comptime T: type, x: T, r: anytype) T {
422 if (T.is_signed) {422 if (@typeInfo(T).Int.is_signed) {
423 @compileError("cannot rotate signed integer");423 @compileError("cannot rotate signed integer");
424 } else {424 } else {
425 const ar = @mod(r, T.bit_count);425 const ar = @mod(r, @typeInfo(T).Int.bits);
426 return shl(T, x, ar) | shr(T, x, T.bit_count - ar);426 return shl(T, x, ar) | shr(T, x, @typeInfo(T).Int.bits - ar);
427 }427 }
428}428}
429429
...@@ -438,7 +438,7 @@ test "math.rotl" {...@@ -438,7 +438,7 @@ test "math.rotl" {
438pub fn Log2Int(comptime T: type) type {438pub fn Log2Int(comptime T: type) type {
439 // comptime ceil log2439 // comptime ceil log2
440 comptime var count = 0;440 comptime var count = 0;
441 comptime var s = T.bit_count - 1;441 comptime var s = @typeInfo(T).Int.bits - 1;
442 inline while (s != 0) : (s >>= 1) {442 inline while (s != 0) : (s >>= 1) {
443 count += 1;443 count += 1;
444 }444 }
...@@ -524,7 +524,7 @@ fn testOverflow() void {...@@ -524,7 +524,7 @@ fn testOverflow() void {
524pub fn absInt(x: anytype) !@TypeOf(x) {524pub fn absInt(x: anytype) !@TypeOf(x) {
525 const T = @TypeOf(x);525 const T = @TypeOf(x);
526 comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt526 comptime assert(@typeInfo(T) == .Int); // must pass an integer to absInt
527 comptime assert(T.is_signed); // must pass a signed integer to absInt527 comptime assert(@typeInfo(T).Int.is_signed); // must pass a signed integer to absInt
528528
529 if (x == minInt(@TypeOf(x))) {529 if (x == minInt(@TypeOf(x))) {
530 return error.Overflow;530 return error.Overflow;
...@@ -557,7 +557,7 @@ fn testAbsFloat() void {...@@ -557,7 +557,7 @@ fn testAbsFloat() void {
557pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {557pub fn divTrunc(comptime T: type, numerator: T, denominator: T) !T {
558 @setRuntimeSafety(false);558 @setRuntimeSafety(false);
559 if (denominator == 0) return error.DivisionByZero;559 if (denominator == 0) return error.DivisionByZero;
560 if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;560 if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
561 return @divTrunc(numerator, denominator);561 return @divTrunc(numerator, denominator);
562}562}
563563
...@@ -578,7 +578,7 @@ fn testDivTrunc() void {...@@ -578,7 +578,7 @@ fn testDivTrunc() void {
578pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {578pub fn divFloor(comptime T: type, numerator: T, denominator: T) !T {
579 @setRuntimeSafety(false);579 @setRuntimeSafety(false);
580 if (denominator == 0) return error.DivisionByZero;580 if (denominator == 0) return error.DivisionByZero;
581 if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;581 if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
582 return @divFloor(numerator, denominator);582 return @divFloor(numerator, denominator);
583}583}
584584
...@@ -652,7 +652,7 @@ fn testDivCeil() void {...@@ -652,7 +652,7 @@ fn testDivCeil() void {
652pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {652pub fn divExact(comptime T: type, numerator: T, denominator: T) !T {
653 @setRuntimeSafety(false);653 @setRuntimeSafety(false);
654 if (denominator == 0) return error.DivisionByZero;654 if (denominator == 0) return error.DivisionByZero;
655 if (@typeInfo(T) == .Int and T.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;655 if (@typeInfo(T) == .Int and @typeInfo(T).Int.is_signed and numerator == minInt(T) and denominator == -1) return error.Overflow;
656 const result = @divTrunc(numerator, denominator);656 const result = @divTrunc(numerator, denominator);
657 if (result * denominator != numerator) return error.UnexpectedRemainder;657 if (result * denominator != numerator) return error.UnexpectedRemainder;
658 return result;658 return result;
...@@ -757,10 +757,10 @@ test "math.absCast" {...@@ -757,10 +757,10 @@ test "math.absCast" {
757757
758/// Returns the negation of the integer parameter.758/// Returns the negation of the integer parameter.
759/// Result is a signed integer.759/// Result is a signed integer.
760pub fn negateCast(x: anytype) !std.meta.Int(true, @TypeOf(x).bit_count) {760pub fn negateCast(x: anytype) !std.meta.Int(true, std.meta.bitCount(@TypeOf(x))) {
761 if (@TypeOf(x).is_signed) return negate(x);761 if (@typeInfo(@TypeOf(x)).Int.is_signed) return negate(x);
762762
763 const int = std.meta.Int(true, @TypeOf(x).bit_count);763 const int = std.meta.Int(true, std.meta.bitCount(@TypeOf(x)));
764 if (x > -minInt(int)) return error.Overflow;764 if (x > -minInt(int)) return error.Overflow;
765765
766 if (x == -minInt(int)) return minInt(int);766 if (x == -minInt(int)) return minInt(int);
...@@ -823,7 +823,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T {...@@ -823,7 +823,7 @@ pub fn floorPowerOfTwo(comptime T: type, value: T) T {
823 var x = value;823 var x = value;
824824
825 comptime var i = 1;825 comptime var i = 1;
826 inline while (T.bit_count > i) : (i *= 2) {826 inline while (@typeInfo(T).Int.bits > i) : (i *= 2) {
827 x |= (x >> i);827 x |= (x >> i);
828 }828 }
829829
...@@ -847,13 +847,13 @@ fn testFloorPowerOfTwo() void {...@@ -847,13 +847,13 @@ fn testFloorPowerOfTwo() void {
847/// Returns the next power of two (if the value is not already a power of two).847/// Returns the next power of two (if the value is not already a power of two).
848/// Only unsigned integers can be used. Zero is not an allowed input.848/// Only unsigned integers can be used. Zero is not an allowed input.
849/// Result is a type with 1 more bit than the input type.849/// Result is a type with 1 more bit than the input type.
850pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(T.is_signed, T.bit_count + 1) {850pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(@typeInfo(T).Int.is_signed, @typeInfo(T).Int.bits + 1) {
851 comptime assert(@typeInfo(T) == .Int);851 comptime assert(@typeInfo(T) == .Int);
852 comptime assert(!T.is_signed);852 comptime assert(!@typeInfo(T).Int.is_signed);
853 assert(value != 0);853 assert(value != 0);
854 comptime const PromotedType = std.meta.Int(T.is_signed, T.bit_count + 1);854 comptime const PromotedType = std.meta.Int(@typeInfo(T).Int.is_signed, @typeInfo(T).Int.bits + 1);
855 comptime const shiftType = std.math.Log2Int(PromotedType);855 comptime const shiftType = std.math.Log2Int(PromotedType);
856 return @as(PromotedType, 1) << @intCast(shiftType, T.bit_count - @clz(T, value - 1));856 return @as(PromotedType, 1) << @intCast(shiftType, @typeInfo(T).Int.bits - @clz(T, value - 1));
857}857}
858858
859/// Returns the next power of two (if the value is not already a power of two).859/// Returns the next power of two (if the value is not already a power of two).
...@@ -861,9 +861,10 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(T.is_signe...@@ -861,9 +861,10 @@ pub fn ceilPowerOfTwoPromote(comptime T: type, value: T) std.meta.Int(T.is_signe
861/// If the value doesn't fit, returns an error.861/// If the value doesn't fit, returns an error.
862pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {862pub fn ceilPowerOfTwo(comptime T: type, value: T) (error{Overflow}!T) {
863 comptime assert(@typeInfo(T) == .Int);863 comptime assert(@typeInfo(T) == .Int);
864 comptime assert(!T.is_signed);864 const info = @typeInfo(T).Int;
865 comptime const PromotedType = std.meta.Int(T.is_signed, T.bit_count + 1);865 comptime assert(!info.is_signed);
866 comptime const overflowBit = @as(PromotedType, 1) << T.bit_count;866 comptime const PromotedType = std.meta.Int(info.is_signed, info.bits + 1);
867 comptime const overflowBit = @as(PromotedType, 1) << info.bits;
867 var x = ceilPowerOfTwoPromote(T, value);868 var x = ceilPowerOfTwoPromote(T, value);
868 if (overflowBit & x != 0) {869 if (overflowBit & x != 0) {
869 return error.Overflow;870 return error.Overflow;
...@@ -911,7 +912,7 @@ fn testCeilPowerOfTwo() !void {...@@ -911,7 +912,7 @@ fn testCeilPowerOfTwo() !void {
911912
912pub fn log2_int(comptime T: type, x: T) Log2Int(T) {913pub fn log2_int(comptime T: type, x: T) Log2Int(T) {
913 assert(x != 0);914 assert(x != 0);
914 return @intCast(Log2Int(T), T.bit_count - 1 - @clz(T, x));915 return @intCast(Log2Int(T), @typeInfo(T).Int.bits - 1 - @clz(T, x));
915}916}
916917
917pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {918pub fn log2_int_ceil(comptime T: type, x: T) Log2Int(T) {
...@@ -1008,8 +1009,8 @@ test "max value type" {...@@ -1008,8 +1009,8 @@ test "max value type" {
1008 testing.expect(x == 2147483647);1009 testing.expect(x == 2147483647);
1009}1010}
10101011
1011pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int(T.is_signed, T.bit_count * 2) {1012pub fn mulWide(comptime T: type, a: T, b: T) std.meta.Int(@typeInfo(T).Int.is_signed, @typeInfo(T).Int.bits * 2) {
1012 const ResultInt = std.meta.Int(T.is_signed, T.bit_count * 2);1013 const ResultInt = std.meta.Int(@typeInfo(T).Int.is_signed, @typeInfo(T).Int.bits * 2);
1013 return @as(ResultInt, a) * @as(ResultInt, b);1014 return @as(ResultInt, a) * @as(ResultInt, b);
1014}1015}
10151016
lib/std/math/big.zig+6-5
...@@ -9,14 +9,15 @@ const assert = std.debug.assert;...@@ -9,14 +9,15 @@ const assert = std.debug.assert;
9pub const Rational = @import("big/rational.zig").Rational;9pub const Rational = @import("big/rational.zig").Rational;
10pub const int = @import("big/int.zig");10pub const int = @import("big/int.zig");
11pub const Limb = usize;11pub const Limb = usize;
12pub const DoubleLimb = std.meta.IntType(false, 2 * Limb.bit_count);12const limb_info = @typeInfo(Limb).Int;
13pub const SignedDoubleLimb = std.meta.IntType(true, DoubleLimb.bit_count);13pub const DoubleLimb = std.meta.IntType(false, 2 * limb_info.bits);
14pub const SignedDoubleLimb = std.meta.IntType(true, 2 * limb_info.bits);
14pub const Log2Limb = std.math.Log2Int(Limb);15pub const Log2Limb = std.math.Log2Int(Limb);
1516
16comptime {17comptime {
17 assert(std.math.floorPowerOfTwo(usize, Limb.bit_count) == Limb.bit_count);18 assert(std.math.floorPowerOfTwo(usize, limb_info.bits) == limb_info.bits);
18 assert(Limb.bit_count <= 64); // u128 set is unsupported19 assert(limb_info.bits <= 64); // u128 set is unsupported
19 assert(Limb.is_signed == false);20 assert(limb_info.is_signed == false);
20}21}
2122
22test "" {23test "" {
lib/std/math/big/int.zig+44-43
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6const std = @import("../../std.zig");6const std = @import("../../std.zig");
7const math = std.math;7const math = std.math;
8const Limb = std.math.big.Limb;8const Limb = std.math.big.Limb;
9const limb_bits = @typeInfo(Limb).Int.bits;
9const DoubleLimb = std.math.big.DoubleLimb;10const DoubleLimb = std.math.big.DoubleLimb;
10const SignedDoubleLimb = std.math.big.SignedDoubleLimb;11const SignedDoubleLimb = std.math.big.SignedDoubleLimb;
11const Log2Limb = std.math.big.Log2Limb;12const Log2Limb = std.math.big.Log2Limb;
...@@ -28,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize {...@@ -28,7 +29,7 @@ pub fn calcLimbLen(scalar: anytype) usize {
28 },29 },
29 .ComptimeInt => {30 .ComptimeInt => {
30 const w_value = if (scalar < 0) -scalar else scalar;31 const w_value = if (scalar < 0) -scalar else scalar;
31 return @divFloor(math.log2(w_value), Limb.bit_count) + 1;32 return @divFloor(math.log2(w_value), limb_bits) + 1;
32 },33 },
33 else => @compileError("parameter must be a primitive integer type"),34 else => @compileError("parameter must be a primitive integer type"),
34 }35 }
...@@ -54,7 +55,7 @@ pub fn calcSetStringLimbsBufferLen(base: u8, string_len: usize) usize {...@@ -54,7 +55,7 @@ pub fn calcSetStringLimbsBufferLen(base: u8, string_len: usize) usize {
54}55}
5556
56pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {57pub fn calcSetStringLimbCount(base: u8, string_len: usize) usize {
57 return (string_len + (Limb.bit_count / base - 1)) / (Limb.bit_count / base);58 return (string_len + (limb_bits / base - 1)) / (limb_bits / base);
58}59}
5960
60/// a + b * c + *carry, sets carry to the overflow bits61/// a + b * c + *carry, sets carry to the overflow bits
...@@ -68,7 +69,7 @@ pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {...@@ -68,7 +69,7 @@ pub fn addMulLimbWithCarry(a: Limb, b: Limb, c: Limb, carry: *Limb) Limb {
68 // r2 = b * c69 // r2 = b * c
69 const bc = @as(DoubleLimb, math.mulWide(Limb, b, c));70 const bc = @as(DoubleLimb, math.mulWide(Limb, b, c));
70 const r2 = @truncate(Limb, bc);71 const r2 = @truncate(Limb, bc);
71 const c2 = @truncate(Limb, bc >> Limb.bit_count);72 const c2 = @truncate(Limb, bc >> limb_bits);
7273
73 // r1 = r1 + r274 // r1 = r1 + r2
74 const c3: Limb = @boolToInt(@addWithOverflow(Limb, r1, r2, &r1));75 const c3: Limb = @boolToInt(@addWithOverflow(Limb, r1, r2, &r1));
...@@ -181,7 +182,7 @@ pub const Mutable = struct {...@@ -181,7 +182,7 @@ pub const Mutable = struct {
181182
182 switch (@typeInfo(T)) {183 switch (@typeInfo(T)) {
183 .Int => |info| {184 .Int => |info| {
184 const UT = if (T.is_signed) std.meta.Int(false, T.bit_count - 1) else T;185 const UT = if (info.is_signed) std.meta.Int(false, info.bits - 1) else T;
185186
186 const needed_limbs = @sizeOf(UT) / @sizeOf(Limb);187 const needed_limbs = @sizeOf(UT) / @sizeOf(Limb);
187 assert(needed_limbs <= self.limbs.len); // value too big188 assert(needed_limbs <= self.limbs.len); // value too big
...@@ -190,7 +191,7 @@ pub const Mutable = struct {...@@ -190,7 +191,7 @@ pub const Mutable = struct {
190191
191 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);192 var w_value: UT = if (value < 0) @intCast(UT, -value) else @intCast(UT, value);
192193
193 if (info.bits <= Limb.bit_count) {194 if (info.bits <= limb_bits) {
194 self.limbs[0] = @as(Limb, w_value);195 self.limbs[0] = @as(Limb, w_value);
195 self.len += 1;196 self.len += 1;
196 } else {197 } else {
...@@ -200,15 +201,15 @@ pub const Mutable = struct {...@@ -200,15 +201,15 @@ pub const Mutable = struct {
200 self.len += 1;201 self.len += 1;
201202
202 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.203 // TODO: shift == 64 at compile-time fails. Fails on u128 limbs.
203 w_value >>= Limb.bit_count / 2;204 w_value >>= limb_bits / 2;
204 w_value >>= Limb.bit_count / 2;205 w_value >>= limb_bits / 2;
205 }206 }
206 }207 }
207 },208 },
208 .ComptimeInt => {209 .ComptimeInt => {
209 comptime var w_value = if (value < 0) -value else value;210 comptime var w_value = if (value < 0) -value else value;
210211
211 const req_limbs = @divFloor(math.log2(w_value), Limb.bit_count) + 1;212 const req_limbs = @divFloor(math.log2(w_value), limb_bits) + 1;
212 assert(req_limbs <= self.limbs.len); // value too big213 assert(req_limbs <= self.limbs.len); // value too big
213214
214 self.len = req_limbs;215 self.len = req_limbs;
...@@ -217,14 +218,14 @@ pub const Mutable = struct {...@@ -217,14 +218,14 @@ pub const Mutable = struct {
217 if (w_value <= maxInt(Limb)) {218 if (w_value <= maxInt(Limb)) {
218 self.limbs[0] = w_value;219 self.limbs[0] = w_value;
219 } else {220 } else {
220 const mask = (1 << Limb.bit_count) - 1;221 const mask = (1 << limb_bits) - 1;
221222
222 comptime var i = 0;223 comptime var i = 0;
223 inline while (w_value != 0) : (i += 1) {224 inline while (w_value != 0) : (i += 1) {
224 self.limbs[i] = w_value & mask;225 self.limbs[i] = w_value & mask;
225226
226 w_value >>= Limb.bit_count / 2;227 w_value >>= limb_bits / 2;
227 w_value >>= Limb.bit_count / 2;228 w_value >>= limb_bits / 2;
228 }229 }
229 }230 }
230 },231 },
...@@ -506,7 +507,7 @@ pub const Mutable = struct {...@@ -506,7 +507,7 @@ pub const Mutable = struct {
506 /// `a.limbs.len + (shift / (@sizeOf(Limb) * 8))`.507 /// `a.limbs.len + (shift / (@sizeOf(Limb) * 8))`.
507 pub fn shiftLeft(r: *Mutable, a: Const, shift: usize) void {508 pub fn shiftLeft(r: *Mutable, a: Const, shift: usize) void {
508 llshl(r.limbs[0..], a.limbs[0..a.limbs.len], shift);509 llshl(r.limbs[0..], a.limbs[0..a.limbs.len], shift);
509 r.normalize(a.limbs.len + (shift / Limb.bit_count) + 1);510 r.normalize(a.limbs.len + (shift / limb_bits) + 1);
510 r.positive = a.positive;511 r.positive = a.positive;
511 }512 }
512513
...@@ -516,7 +517,7 @@ pub const Mutable = struct {...@@ -516,7 +517,7 @@ pub const Mutable = struct {
516 /// Asserts there is enough memory to fit the result. The upper bound Limb count is517 /// Asserts there is enough memory to fit the result. The upper bound Limb count is
517 /// `a.limbs.len - (shift / (@sizeOf(Limb) * 8))`.518 /// `a.limbs.len - (shift / (@sizeOf(Limb) * 8))`.
518 pub fn shiftRight(r: *Mutable, a: Const, shift: usize) void {519 pub fn shiftRight(r: *Mutable, a: Const, shift: usize) void {
519 if (a.limbs.len <= shift / Limb.bit_count) {520 if (a.limbs.len <= shift / limb_bits) {
520 r.len = 1;521 r.len = 1;
521 r.positive = true;522 r.positive = true;
522 r.limbs[0] = 0;523 r.limbs[0] = 0;
...@@ -524,7 +525,7 @@ pub const Mutable = struct {...@@ -524,7 +525,7 @@ pub const Mutable = struct {
524 }525 }
525526
526 const r_len = llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);527 const r_len = llshr(r.limbs[0..], a.limbs[0..a.limbs.len], shift);
527 r.len = a.limbs.len - (shift / Limb.bit_count);528 r.len = a.limbs.len - (shift / limb_bits);
528 r.positive = a.positive;529 r.positive = a.positive;
529 }530 }
530531
...@@ -772,7 +773,7 @@ pub const Mutable = struct {...@@ -772,7 +773,7 @@ pub const Mutable = struct {
772 }773 }
773774
774 if (ab_zero_limb_count != 0) {775 if (ab_zero_limb_count != 0) {
775 rem.shiftLeft(rem.toConst(), ab_zero_limb_count * Limb.bit_count);776 rem.shiftLeft(rem.toConst(), ab_zero_limb_count * limb_bits);
776 }777 }
777 }778 }
778779
...@@ -803,10 +804,10 @@ pub const Mutable = struct {...@@ -803,10 +804,10 @@ pub const Mutable = struct {
803 };804 };
804 tmp.limbs[0] = 0;805 tmp.limbs[0] = 0;
805806
806 // Normalize so y > Limb.bit_count / 2 (i.e. leading bit is set) and even807 // Normalize so y > limb_bits / 2 (i.e. leading bit is set) and even
807 var norm_shift = @clz(Limb, y.limbs[y.len - 1]);808 var norm_shift = @clz(Limb, y.limbs[y.len - 1]);
808 if (norm_shift == 0 and y.toConst().isOdd()) {809 if (norm_shift == 0 and y.toConst().isOdd()) {
809 norm_shift = Limb.bit_count;810 norm_shift = limb_bits;
810 }811 }
811 x.shiftLeft(x.toConst(), norm_shift);812 x.shiftLeft(x.toConst(), norm_shift);
812 y.shiftLeft(y.toConst(), norm_shift);813 y.shiftLeft(y.toConst(), norm_shift);
...@@ -820,7 +821,7 @@ pub const Mutable = struct {...@@ -820,7 +821,7 @@ pub const Mutable = struct {
820 mem.set(Limb, q.limbs[0..q.len], 0);821 mem.set(Limb, q.limbs[0..q.len], 0);
821822
822 // 2.823 // 2.
823 tmp.shiftLeft(y.toConst(), Limb.bit_count * (n - t));824 tmp.shiftLeft(y.toConst(), limb_bits * (n - t));
824 while (x.toConst().order(tmp.toConst()) != .lt) {825 while (x.toConst().order(tmp.toConst()) != .lt) {
825 q.limbs[n - t] += 1;826 q.limbs[n - t] += 1;
826 x.sub(x.toConst(), tmp.toConst());827 x.sub(x.toConst(), tmp.toConst());
...@@ -833,7 +834,7 @@ pub const Mutable = struct {...@@ -833,7 +834,7 @@ pub const Mutable = struct {
833 if (x.limbs[i] == y.limbs[t]) {834 if (x.limbs[i] == y.limbs[t]) {
834 q.limbs[i - t - 1] = maxInt(Limb);835 q.limbs[i - t - 1] = maxInt(Limb);
835 } else {836 } else {
836 const num = (@as(DoubleLimb, x.limbs[i]) << Limb.bit_count) | @as(DoubleLimb, x.limbs[i - 1]);837 const num = (@as(DoubleLimb, x.limbs[i]) << limb_bits) | @as(DoubleLimb, x.limbs[i - 1]);
837 const z = @intCast(Limb, num / @as(DoubleLimb, y.limbs[t]));838 const z = @intCast(Limb, num / @as(DoubleLimb, y.limbs[t]));
838 q.limbs[i - t - 1] = if (z > maxInt(Limb)) maxInt(Limb) else @as(Limb, z);839 q.limbs[i - t - 1] = if (z > maxInt(Limb)) maxInt(Limb) else @as(Limb, z);
839 }840 }
...@@ -862,11 +863,11 @@ pub const Mutable = struct {...@@ -862,11 +863,11 @@ pub const Mutable = struct {
862 // 3.3863 // 3.3
863 tmp.set(q.limbs[i - t - 1]);864 tmp.set(q.limbs[i - t - 1]);
864 tmp.mul(tmp.toConst(), y.toConst(), mul_limb_buf, allocator);865 tmp.mul(tmp.toConst(), y.toConst(), mul_limb_buf, allocator);
865 tmp.shiftLeft(tmp.toConst(), Limb.bit_count * (i - t - 1));866 tmp.shiftLeft(tmp.toConst(), limb_bits * (i - t - 1));
866 x.sub(x.toConst(), tmp.toConst());867 x.sub(x.toConst(), tmp.toConst());
867868
868 if (!x.positive) {869 if (!x.positive) {
869 tmp.shiftLeft(y.toConst(), Limb.bit_count * (i - t - 1));870 tmp.shiftLeft(y.toConst(), limb_bits * (i - t - 1));
870 x.add(x.toConst(), tmp.toConst());871 x.add(x.toConst(), tmp.toConst());
871 q.limbs[i - t - 1] -= 1;872 q.limbs[i - t - 1] -= 1;
872 }873 }
...@@ -949,7 +950,7 @@ pub const Const = struct {...@@ -949,7 +950,7 @@ pub const Const = struct {
949950
950 /// Returns the number of bits required to represent the absolute value of an integer.951 /// Returns the number of bits required to represent the absolute value of an integer.
951 pub fn bitCountAbs(self: Const) usize {952 pub fn bitCountAbs(self: Const) usize {
952 return (self.limbs.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(Limb, self.limbs[self.limbs.len - 1]));953 return (self.limbs.len - 1) * limb_bits + (limb_bits - @clz(Limb, self.limbs[self.limbs.len - 1]));
953 }954 }
954955
955 /// Returns the number of bits required to represent the integer in twos-complement form.956 /// Returns the number of bits required to represent the integer in twos-complement form.
...@@ -1019,10 +1020,10 @@ pub const Const = struct {...@@ -1019,10 +1020,10 @@ pub const Const = struct {
1019 /// Returns an error if self cannot be narrowed into the requested type without truncation.1020 /// Returns an error if self cannot be narrowed into the requested type without truncation.
1020 pub fn to(self: Const, comptime T: type) ConvertError!T {1021 pub fn to(self: Const, comptime T: type) ConvertError!T {
1021 switch (@typeInfo(T)) {1022 switch (@typeInfo(T)) {
1022 .Int => {1023 .Int => |info| {
1023 const UT = std.meta.Int(false, T.bit_count);1024 const UT = std.meta.Int(false, info.bits);
10241025
1025 if (self.bitCountTwosComp() > T.bit_count) {1026 if (self.bitCountTwosComp() > info.bits) {
1026 return error.TargetTooSmall;1027 return error.TargetTooSmall;
1027 }1028 }
10281029
...@@ -1033,12 +1034,12 @@ pub const Const = struct {...@@ -1033,12 +1034,12 @@ pub const Const = struct {
1033 } else {1034 } else {
1034 for (self.limbs[0..self.limbs.len]) |_, ri| {1035 for (self.limbs[0..self.limbs.len]) |_, ri| {
1035 const limb = self.limbs[self.limbs.len - ri - 1];1036 const limb = self.limbs[self.limbs.len - ri - 1];
1036 r <<= Limb.bit_count;1037 r <<= limb_bits;
1037 r |= limb;1038 r |= limb;
1038 }1039 }
1039 }1040 }
10401041
1041 if (!T.is_signed) {1042 if (!info.is_signed) {
1042 return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;1043 return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned;
1043 } else {1044 } else {
1044 if (self.positive) {1045 if (self.positive) {
...@@ -1149,7 +1150,7 @@ pub const Const = struct {...@@ -1149,7 +1150,7 @@ pub const Const = struct {
11491150
1150 outer: for (self.limbs[0..self.limbs.len]) |limb| {1151 outer: for (self.limbs[0..self.limbs.len]) |limb| {
1151 var shift: usize = 0;1152 var shift: usize = 0;
1152 while (shift < Limb.bit_count) : (shift += base_shift) {1153 while (shift < limb_bits) : (shift += base_shift) {
1153 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & @as(Limb, base - 1));1154 const r = @intCast(u8, (limb >> @intCast(Log2Limb, shift)) & @as(Limb, base - 1));
1154 const ch = std.fmt.digitToChar(r, uppercase);1155 const ch = std.fmt.digitToChar(r, uppercase);
1155 string[digits_len] = ch;1156 string[digits_len] = ch;
...@@ -1295,7 +1296,7 @@ pub const Const = struct {...@@ -1295,7 +1296,7 @@ pub const Const = struct {
1295/// Memory is allocated as needed to ensure operations never overflow. The range1296/// Memory is allocated as needed to ensure operations never overflow. The range
1296/// is bounded only by available memory.1297/// is bounded only by available memory.
1297pub const Managed = struct {1298pub const Managed = struct {
1298 pub const sign_bit: usize = 1 << (usize.bit_count - 1);1299 pub const sign_bit: usize = 1 << (@typeInfo(usize).Int.bits - 1);
12991300
1300 /// Default number of limbs to allocate on creation of a `Managed`.1301 /// Default number of limbs to allocate on creation of a `Managed`.
1301 pub const default_capacity = 4;1302 pub const default_capacity = 4;
...@@ -1448,7 +1449,7 @@ pub const Managed = struct {...@@ -1448,7 +1449,7 @@ pub const Managed = struct {
1448 for (self.limbs[0..self.len()]) |limb| {1449 for (self.limbs[0..self.len()]) |limb| {
1449 std.debug.warn("{x} ", .{limb});1450 std.debug.warn("{x} ", .{limb});
1450 }1451 }
1451 std.debug.warn("capacity={} positive={}\n", .{ self.limbs.len, self.positive });1452 std.debug.warn("capacity={} positive={}\n", .{ self.limbs.len, self.isPositive() });
1452 }1453 }
14531454
1454 /// Negate the sign.1455 /// Negate the sign.
...@@ -1716,7 +1717,7 @@ pub const Managed = struct {...@@ -1716,7 +1717,7 @@ pub const Managed = struct {
17161717
1717 /// r = a << shift, in other words, r = a * 2^shift1718 /// r = a << shift, in other words, r = a * 2^shift
1718 pub fn shiftLeft(r: *Managed, a: Managed, shift: usize) !void {1719 pub fn shiftLeft(r: *Managed, a: Managed, shift: usize) !void {
1719 try r.ensureCapacity(a.len() + (shift / Limb.bit_count) + 1);1720 try r.ensureCapacity(a.len() + (shift / limb_bits) + 1);
1720 var m = r.toMutable();1721 var m = r.toMutable();
1721 m.shiftLeft(a.toConst(), shift);1722 m.shiftLeft(a.toConst(), shift);
1722 r.setMetadata(m.positive, m.len);1723 r.setMetadata(m.positive, m.len);
...@@ -1724,13 +1725,13 @@ pub const Managed = struct {...@@ -1724,13 +1725,13 @@ pub const Managed = struct {
17241725
1725 /// r = a >> shift1726 /// r = a >> shift
1726 pub fn shiftRight(r: *Managed, a: Managed, shift: usize) !void {1727 pub fn shiftRight(r: *Managed, a: Managed, shift: usize) !void {
1727 if (a.len() <= shift / Limb.bit_count) {1728 if (a.len() <= shift / limb_bits) {
1728 r.metadata = 1;1729 r.metadata = 1;
1729 r.limbs[0] = 0;1730 r.limbs[0] = 0;
1730 return;1731 return;
1731 }1732 }
17321733
1733 try r.ensureCapacity(a.len() - (shift / Limb.bit_count));1734 try r.ensureCapacity(a.len() - (shift / limb_bits));
1734 var m = r.toMutable();1735 var m = r.toMutable();
1735 m.shiftRight(a.toConst(), shift);1736 m.shiftRight(a.toConst(), shift);
1736 r.setMetadata(m.positive, m.len);1737 r.setMetadata(m.positive, m.len);
...@@ -2021,7 +2022,7 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {...@@ -2021,7 +2022,7 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {
2021 rem.* = 0;2022 rem.* = 0;
2022 for (a) |_, ri| {2023 for (a) |_, ri| {
2023 const i = a.len - ri - 1;2024 const i = a.len - ri - 1;
2024 const pdiv = ((@as(DoubleLimb, rem.*) << Limb.bit_count) | a[i]);2025 const pdiv = ((@as(DoubleLimb, rem.*) << limb_bits) | a[i]);
20252026
2026 if (pdiv == 0) {2027 if (pdiv == 0) {
2027 quo[i] = 0;2028 quo[i] = 0;
...@@ -2042,10 +2043,10 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {...@@ -2042,10 +2043,10 @@ fn lldiv1(quo: []Limb, rem: *Limb, a: []const Limb, b: Limb) void {
2042fn llshl(r: []Limb, a: []const Limb, shift: usize) void {2043fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
2043 @setRuntimeSafety(debug_safety);2044 @setRuntimeSafety(debug_safety);
2044 assert(a.len >= 1);2045 assert(a.len >= 1);
2045 assert(r.len >= a.len + (shift / Limb.bit_count) + 1);2046 assert(r.len >= a.len + (shift / limb_bits) + 1);
20462047
2047 const limb_shift = shift / Limb.bit_count + 1;2048 const limb_shift = shift / limb_bits + 1;
2048 const interior_limb_shift = @intCast(Log2Limb, shift % Limb.bit_count);2049 const interior_limb_shift = @intCast(Log2Limb, shift % limb_bits);
20492050
2050 var carry: Limb = 0;2051 var carry: Limb = 0;
2051 var i: usize = 0;2052 var i: usize = 0;
...@@ -2057,7 +2058,7 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {...@@ -2057,7 +2058,7 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
2057 r[dst_i] = carry | @call(.{ .modifier = .always_inline }, math.shr, .{2058 r[dst_i] = carry | @call(.{ .modifier = .always_inline }, math.shr, .{
2058 Limb,2059 Limb,
2059 src_digit,2060 src_digit,
2060 Limb.bit_count - @intCast(Limb, interior_limb_shift),2061 limb_bits - @intCast(Limb, interior_limb_shift),
2061 });2062 });
2062 carry = (src_digit << interior_limb_shift);2063 carry = (src_digit << interior_limb_shift);
2063 }2064 }
...@@ -2069,10 +2070,10 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {...@@ -2069,10 +2070,10 @@ fn llshl(r: []Limb, a: []const Limb, shift: usize) void {
2069fn llshr(r: []Limb, a: []const Limb, shift: usize) void {2070fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
2070 @setRuntimeSafety(debug_safety);2071 @setRuntimeSafety(debug_safety);
2071 assert(a.len >= 1);2072 assert(a.len >= 1);
2072 assert(r.len >= a.len - (shift / Limb.bit_count));2073 assert(r.len >= a.len - (shift / limb_bits));
20732074
2074 const limb_shift = shift / Limb.bit_count;2075 const limb_shift = shift / limb_bits;
2075 const interior_limb_shift = @intCast(Log2Limb, shift % Limb.bit_count);2076 const interior_limb_shift = @intCast(Log2Limb, shift % limb_bits);
20762077
2077 var carry: Limb = 0;2078 var carry: Limb = 0;
2078 var i: usize = 0;2079 var i: usize = 0;
...@@ -2085,7 +2086,7 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {...@@ -2085,7 +2086,7 @@ fn llshr(r: []Limb, a: []const Limb, shift: usize) void {
2085 carry = @call(.{ .modifier = .always_inline }, math.shl, .{2086 carry = @call(.{ .modifier = .always_inline }, math.shl, .{
2086 Limb,2087 Limb,
2087 src_digit,2088 src_digit,
2088 Limb.bit_count - @intCast(Limb, interior_limb_shift),2089 limb_bits - @intCast(Limb, interior_limb_shift),
2089 });2090 });
2090 }2091 }
2091}2092}
...@@ -2135,7 +2136,7 @@ fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {...@@ -2135,7 +2136,7 @@ fn fixedIntFromSignedDoubleLimb(A: SignedDoubleLimb, storage: []Limb) Mutable {
2135 const A_is_positive = A >= 0;2136 const A_is_positive = A >= 0;
2136 const Au = @intCast(DoubleLimb, if (A < 0) -A else A);2137 const Au = @intCast(DoubleLimb, if (A < 0) -A else A);
2137 storage[0] = @truncate(Limb, Au);2138 storage[0] = @truncate(Limb, Au);
2138 storage[1] = @truncate(Limb, Au >> Limb.bit_count);2139 storage[1] = @truncate(Limb, Au >> limb_bits);
2139 return .{2140 return .{
2140 .limbs = storage[0..2],2141 .limbs = storage[0..2],
2141 .positive = A_is_positive,2142 .positive = A_is_positive,
lib/std/math/big/int_test.zig+3-3
...@@ -23,13 +23,13 @@ test "big.int comptime_int set" {...@@ -23,13 +23,13 @@ test "big.int comptime_int set" {
23 var a = try Managed.initSet(testing.allocator, s);23 var a = try Managed.initSet(testing.allocator, s);
24 defer a.deinit();24 defer a.deinit();
2525
26 const s_limb_count = 128 / Limb.bit_count;26 const s_limb_count = 128 / @typeInfo(Limb).Int.bits;
2727
28 comptime var i: usize = 0;28 comptime var i: usize = 0;
29 inline while (i < s_limb_count) : (i += 1) {29 inline while (i < s_limb_count) : (i += 1) {
30 const result = @as(Limb, s & maxInt(Limb));30 const result = @as(Limb, s & maxInt(Limb));
31 s >>= Limb.bit_count / 2;31 s >>= @typeInfo(Limb).Int.bits / 2;
32 s >>= Limb.bit_count / 2;32 s >>= @typeInfo(Limb).Int.bits / 2;
33 testing.expect(a.limbs[i] == result);33 testing.expect(a.limbs[i] == result);
34 }34 }
35}35}
lib/std/math/big/rational.zig+9-7
...@@ -136,7 +136,7 @@ pub const Rational = struct {...@@ -136,7 +136,7 @@ pub const Rational = struct {
136 // Translated from golang.go/src/math/big/rat.go.136 // Translated from golang.go/src/math/big/rat.go.
137 debug.assert(@typeInfo(T) == .Float);137 debug.assert(@typeInfo(T) == .Float);
138138
139 const UnsignedInt = std.meta.Int(false, T.bit_count);139 const UnsignedInt = std.meta.Int(false, @typeInfo(T).Float.bits);
140 const f_bits = @bitCast(UnsignedInt, f);140 const f_bits = @bitCast(UnsignedInt, f);
141141
142 const exponent_bits = math.floatExponentBits(T);142 const exponent_bits = math.floatExponentBits(T);
...@@ -194,8 +194,8 @@ pub const Rational = struct {...@@ -194,8 +194,8 @@ pub const Rational = struct {
194 // TODO: Indicate whether the result is not exact.194 // TODO: Indicate whether the result is not exact.
195 debug.assert(@typeInfo(T) == .Float);195 debug.assert(@typeInfo(T) == .Float);
196196
197 const fsize = T.bit_count;197 const fsize = @typeInfo(T).Float.bits;
198 const BitReprType = std.meta.Int(false, T.bit_count);198 const BitReprType = std.meta.Int(false, fsize);
199199
200 const msize = math.floatMantissaBits(T);200 const msize = math.floatMantissaBits(T);
201 const msize1 = msize + 1;201 const msize1 = msize + 1;
...@@ -475,16 +475,18 @@ pub const Rational = struct {...@@ -475,16 +475,18 @@ pub const Rational = struct {
475fn extractLowBits(a: Int, comptime T: type) T {475fn extractLowBits(a: Int, comptime T: type) T {
476 testing.expect(@typeInfo(T) == .Int);476 testing.expect(@typeInfo(T) == .Int);
477477
478 if (T.bit_count <= Limb.bit_count) {478 const t_bits = @typeInfo(T).Int.bits;
479 const limb_bits = @typeInfo(Limb).Int.bits;
480 if (t_bits <= limb_bits) {
479 return @truncate(T, a.limbs[0]);481 return @truncate(T, a.limbs[0]);
480 } else {482 } else {
481 var r: T = 0;483 var r: T = 0;
482 comptime var i: usize = 0;484 comptime var i: usize = 0;
483485
484 // Remainder is always 0 since if T.bit_count >= Limb.bit_count -> Limb | T and both486 // Remainder is always 0 since if t_bits >= limb_bits -> Limb | T and both
485 // are powers of two.487 // are powers of two.
486 inline while (i < T.bit_count / Limb.bit_count) : (i += 1) {488 inline while (i < t_bits / limb_bits) : (i += 1) {
487 r |= math.shl(T, a.limbs[i], i * Limb.bit_count);489 r |= math.shl(T, a.limbs[i], i * limb_bits);
488 }490 }
489491
490 return r;492 return r;
lib/std/math/cos.zig+1-1
...@@ -49,7 +49,7 @@ const pi4c = 2.69515142907905952645E-15;...@@ -49,7 +49,7 @@ const pi4c = 2.69515142907905952645E-15;
49const m4pi = 1.273239544735162542821171882678754627704620361328125;49const m4pi = 1.273239544735162542821171882678754627704620361328125;
5050
51fn cos_(comptime T: type, x_: T) T {51fn cos_(comptime T: type, x_: T) T {
52 const I = std.meta.Int(true, T.bit_count);52 const I = std.meta.Int(true, @typeInfo(T).Float.bits);
5353
54 var x = x_;54 var x = x_;
55 if (math.isNan(x) or math.isInf(x)) {55 if (math.isNan(x) or math.isInf(x)) {
lib/std/math/pow.zig+2-2
...@@ -128,7 +128,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -128,7 +128,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
128 if (yf != 0 and x < 0) {128 if (yf != 0 and x < 0) {
129 return math.nan(T);129 return math.nan(T);
130 }130 }
131 if (yi >= 1 << (T.bit_count - 1)) {131 if (yi >= 1 << (@typeInfo(T).Float.bits - 1)) {
132 return math.exp(y * math.ln(x));132 return math.exp(y * math.ln(x));
133 }133 }
134134
...@@ -150,7 +150,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -150,7 +150,7 @@ pub fn pow(comptime T: type, x: T, y: T) T {
150 var xe = r2.exponent;150 var xe = r2.exponent;
151 var x1 = r2.significand;151 var x1 = r2.significand;
152152
153 var i = @floatToInt(std.meta.Int(true, T.bit_count), yi);153 var i = @floatToInt(std.meta.Int(true, @typeInfo(T).Float.bits), yi);
154 while (i != 0) : (i >>= 1) {154 while (i != 0) : (i >>= 1) {
155 const overflow_shift = math.floatExponentBits(T) + 1;155 const overflow_shift = math.floatExponentBits(T) + 1;
156 if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) {156 if (xe < -(1 << overflow_shift) or (1 << overflow_shift) < xe) {
lib/std/math/sin.zig+1-1
...@@ -50,7 +50,7 @@ const pi4c = 2.69515142907905952645E-15;...@@ -50,7 +50,7 @@ const pi4c = 2.69515142907905952645E-15;
50const m4pi = 1.273239544735162542821171882678754627704620361328125;50const m4pi = 1.273239544735162542821171882678754627704620361328125;
5151
52fn sin_(comptime T: type, x_: T) T {52fn sin_(comptime T: type, x_: T) T {
53 const I = std.meta.Int(true, T.bit_count);53 const I = std.meta.Int(true, @typeInfo(T).Float.bits);
5454
55 var x = x_;55 var x = x_;
56 if (x == 0 or math.isNan(x)) {56 if (x == 0 or math.isNan(x)) {
lib/std/math/sqrt.zig+3-3
...@@ -36,10 +36,10 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {...@@ -36,10 +36,10 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {
36 }36 }
37}37}
3838
39fn sqrt_int(comptime T: type, value: T) std.meta.Int(false, T.bit_count / 2) {39fn sqrt_int(comptime T: type, value: T) std.meta.Int(false, @typeInfo(T).Int.bits / 2) {
40 var op = value;40 var op = value;
41 var res: T = 0;41 var res: T = 0;
42 var one: T = 1 << (T.bit_count - 2);42 var one: T = 1 << (@typeInfo(T).Int.bits - 2);
4343
44 // "one" starts at the highest power of four <= than the argument.44 // "one" starts at the highest power of four <= than the argument.
45 while (one > op) {45 while (one > op) {
...@@ -55,7 +55,7 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(false, T.bit_count / 2) {...@@ -55,7 +55,7 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(false, T.bit_count / 2) {
55 one >>= 2;55 one >>= 2;
56 }56 }
5757
58 const ResultType = std.meta.Int(false, T.bit_count / 2);58 const ResultType = std.meta.Int(false, @typeInfo(T).Int.bits / 2);
59 return @intCast(ResultType, res);59 return @intCast(ResultType, res);
60}60}
6161
lib/std/math/tan.zig+1-1
...@@ -43,7 +43,7 @@ const pi4c = 2.69515142907905952645E-15;...@@ -43,7 +43,7 @@ const pi4c = 2.69515142907905952645E-15;
43const m4pi = 1.273239544735162542821171882678754627704620361328125;43const m4pi = 1.273239544735162542821171882678754627704620361328125;
4444
45fn tan_(comptime T: type, x_: T) T {45fn tan_(comptime T: type, x_: T) T {
46 const I = std.meta.Int(true, T.bit_count);46 const I = std.meta.Int(true, @typeInfo(T).Float.bits);
4747
48 var x = x_;48 var x = x_;
49 if (x == 0 or math.isNan(x)) {49 if (x == 0 or math.isNan(x)) {
lib/std/mem.zig+21-21
...@@ -949,7 +949,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin....@@ -949,7 +949,7 @@ pub fn readVarInt(comptime ReturnType: type, bytes: []const u8, endian: builtin.
949/// This function cannot fail and cannot cause undefined behavior.949/// This function cannot fail and cannot cause undefined behavior.
950/// Assumes the endianness of memory is native. This means the function can950/// Assumes the endianness of memory is native. This means the function can
951/// simply pointer cast memory.951/// simply pointer cast memory.
952pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {952pub fn readIntNative(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits, 8)]u8) T {
953 return @ptrCast(*align(1) const T, bytes).*;953 return @ptrCast(*align(1) const T, bytes).*;
954}954}
955955
...@@ -957,7 +957,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]...@@ -957,7 +957,7 @@ pub fn readIntNative(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]
957/// The bit count of T must be evenly divisible by 8.957/// The bit count of T must be evenly divisible by 8.
958/// This function cannot fail and cannot cause undefined behavior.958/// This function cannot fail and cannot cause undefined behavior.
959/// Assumes the endianness of memory is foreign, so it must byte-swap.959/// Assumes the endianness of memory is foreign, so it must byte-swap.
960pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8) T {960pub fn readIntForeign(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits, 8)]u8) T {
961 return @byteSwap(T, readIntNative(T, bytes));961 return @byteSwap(T, readIntNative(T, bytes));
962}962}
963963
...@@ -971,18 +971,18 @@ pub const readIntBig = switch (builtin.endian) {...@@ -971,18 +971,18 @@ pub const readIntBig = switch (builtin.endian) {
971 .Big => readIntNative,971 .Big => readIntNative,
972};972};
973973
974/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0974/// Asserts that bytes.len >= @typeInfo(T).Int.bits / 8. Reads the integer starting from index 0
975/// and ignores extra bytes.975/// and ignores extra bytes.
976/// The bit count of T must be evenly divisible by 8.976/// The bit count of T must be evenly divisible by 8.
977/// Assumes the endianness of memory is native. This means the function can977/// Assumes the endianness of memory is native. This means the function can
978/// simply pointer cast memory.978/// simply pointer cast memory.
979pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {979pub fn readIntSliceNative(comptime T: type, bytes: []const u8) T {
980 const n = @divExact(T.bit_count, 8);980 const n = @divExact(@typeInfo(T).Int.bits, 8);
981 assert(bytes.len >= n);981 assert(bytes.len >= n);
982 return readIntNative(T, bytes[0..n]);982 return readIntNative(T, bytes[0..n]);
983}983}
984984
985/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 0985/// Asserts that bytes.len >= @typeInfo(T).Int.bits / 8. Reads the integer starting from index 0
986/// and ignores extra bytes.986/// and ignores extra bytes.
987/// The bit count of T must be evenly divisible by 8.987/// The bit count of T must be evenly divisible by 8.
988/// Assumes the endianness of memory is foreign, so it must byte-swap.988/// Assumes the endianness of memory is foreign, so it must byte-swap.
...@@ -1003,7 +1003,7 @@ pub const readIntSliceBig = switch (builtin.endian) {...@@ -1003,7 +1003,7 @@ pub const readIntSliceBig = switch (builtin.endian) {
1003/// Reads an integer from memory with bit count specified by T.1003/// Reads an integer from memory with bit count specified by T.
1004/// The bit count of T must be evenly divisible by 8.1004/// The bit count of T must be evenly divisible by 8.
1005/// This function cannot fail and cannot cause undefined behavior.1005/// This function cannot fail and cannot cause undefined behavior.
1006pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, endian: builtin.Endian) T {1006pub fn readInt(comptime T: type, bytes: *const [@divExact(@typeInfo(T).Int.bits, 8)]u8, endian: builtin.Endian) T {
1007 if (endian == builtin.endian) {1007 if (endian == builtin.endian) {
1008 return readIntNative(T, bytes);1008 return readIntNative(T, bytes);
1009 } else {1009 } else {
...@@ -1011,11 +1011,11 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, en...@@ -1011,11 +1011,11 @@ pub fn readInt(comptime T: type, bytes: *const [@divExact(T.bit_count, 8)]u8, en
1011 }1011 }
1012}1012}
10131013
1014/// Asserts that bytes.len >= T.bit_count / 8. Reads the integer starting from index 01014/// Asserts that bytes.len >= @typeInfo(T).Int.bits / 8. Reads the integer starting from index 0
1015/// and ignores extra bytes.1015/// and ignores extra bytes.
1016/// The bit count of T must be evenly divisible by 8.1016/// The bit count of T must be evenly divisible by 8.
1017pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {1017pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian) T {
1018 const n = @divExact(T.bit_count, 8);1018 const n = @divExact(@typeInfo(T).Int.bits, 8);
1019 assert(bytes.len >= n);1019 assert(bytes.len >= n);
1020 return readInt(T, bytes[0..n], endian);1020 return readInt(T, bytes[0..n], endian);
1021}1021}
...@@ -1060,7 +1060,7 @@ test "readIntBig and readIntLittle" {...@@ -1060,7 +1060,7 @@ test "readIntBig and readIntLittle" {
1060/// accepts any integer bit width.1060/// accepts any integer bit width.
1061/// This function stores in native endian, which means it is implemented as a simple1061/// This function stores in native endian, which means it is implemented as a simple
1062/// memory store.1062/// memory store.
1063pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value: T) void {1063pub fn writeIntNative(comptime T: type, buf: *[(@typeInfo(T).Int.bits + 7) / 8]u8, value: T) void {
1064 @ptrCast(*align(1) T, buf).* = value;1064 @ptrCast(*align(1) T, buf).* = value;
1065}1065}
10661066
...@@ -1068,7 +1068,7 @@ pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value:...@@ -1068,7 +1068,7 @@ pub fn writeIntNative(comptime T: type, buf: *[(T.bit_count + 7) / 8]u8, value:
1068/// This function always succeeds, has defined behavior for all inputs, but1068/// This function always succeeds, has defined behavior for all inputs, but
1069/// the integer bit width must be divisible by 8.1069/// the integer bit width must be divisible by 8.
1070/// This function stores in foreign endian, which means it does a @byteSwap first.1070/// This function stores in foreign endian, which means it does a @byteSwap first.
1071pub fn writeIntForeign(comptime T: type, buf: *[@divExact(T.bit_count, 8)]u8, value: T) void {1071pub fn writeIntForeign(comptime T: type, buf: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T) void {
1072 writeIntNative(T, buf, @byteSwap(T, value));1072 writeIntNative(T, buf, @byteSwap(T, value));
1073}1073}
10741074
...@@ -1085,7 +1085,7 @@ pub const writeIntBig = switch (builtin.endian) {...@@ -1085,7 +1085,7 @@ pub const writeIntBig = switch (builtin.endian) {
1085/// Writes an integer to memory, storing it in twos-complement.1085/// Writes an integer to memory, storing it in twos-complement.
1086/// This function always succeeds, has defined behavior for all inputs, but1086/// This function always succeeds, has defined behavior for all inputs, but
1087/// the integer bit width must be divisible by 8.1087/// the integer bit width must be divisible by 8.
1088pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value: T, endian: builtin.Endian) void {1088pub fn writeInt(comptime T: type, buffer: *[@divExact(@typeInfo(T).Int.bits, 8)]u8, value: T, endian: builtin.Endian) void {
1089 if (endian == builtin.endian) {1089 if (endian == builtin.endian) {
1090 return writeIntNative(T, buffer, value);1090 return writeIntNative(T, buffer, value);
1091 } else {1091 } else {
...@@ -1094,19 +1094,19 @@ pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value:...@@ -1094,19 +1094,19 @@ pub fn writeInt(comptime T: type, buffer: *[@divExact(T.bit_count, 8)]u8, value:
1094}1094}
10951095
1096/// Writes a twos-complement little-endian integer to memory.1096/// Writes a twos-complement little-endian integer to memory.
1097/// Asserts that buf.len >= T.bit_count / 8.1097/// Asserts that buf.len >= @typeInfo(T).Int.bits / 8.
1098/// The bit count of T must be divisible by 8.1098/// The bit count of T must be divisible by 8.
1099/// Any extra bytes in buffer after writing the integer are set to zero. To1099/// Any extra bytes in buffer after writing the integer are set to zero. To
1100/// avoid the branch to check for extra buffer bytes, use writeIntLittle1100/// avoid the branch to check for extra buffer bytes, use writeIntLittle
1101/// instead.1101/// instead.
1102pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {1102pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
1103 assert(buffer.len >= @divExact(T.bit_count, 8));1103 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));
11041104
1105 if (T.bit_count == 0)1105 if (@typeInfo(T).Int.bits == 0)
1106 return set(u8, buffer, 0);1106 return set(u8, buffer, 0);
11071107
1108 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough1108 // TODO I want to call writeIntLittle here but comptime eval facilities aren't good enough
1109 const uint = std.meta.Int(false, T.bit_count);1109 const uint = std.meta.Int(false, @typeInfo(T).Int.bits);
1110 var bits = @truncate(uint, value);1110 var bits = @truncate(uint, value);
1111 for (buffer) |*b| {1111 for (buffer) |*b| {
1112 b.* = @truncate(u8, bits);1112 b.* = @truncate(u8, bits);
...@@ -1115,18 +1115,18 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {...@@ -1115,18 +1115,18 @@ pub fn writeIntSliceLittle(comptime T: type, buffer: []u8, value: T) void {
1115}1115}
11161116
1117/// Writes a twos-complement big-endian integer to memory.1117/// Writes a twos-complement big-endian integer to memory.
1118/// Asserts that buffer.len >= T.bit_count / 8.1118/// Asserts that buffer.len >= @typeInfo(T).Int.bits / 8.
1119/// The bit count of T must be divisible by 8.1119/// The bit count of T must be divisible by 8.
1120/// Any extra bytes in buffer before writing the integer are set to zero. To1120/// Any extra bytes in buffer before writing the integer are set to zero. To
1121/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.1121/// avoid the branch to check for extra buffer bytes, use writeIntBig instead.
1122pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {1122pub fn writeIntSliceBig(comptime T: type, buffer: []u8, value: T) void {
1123 assert(buffer.len >= @divExact(T.bit_count, 8));1123 assert(buffer.len >= @divExact(@typeInfo(T).Int.bits, 8));
11241124
1125 if (T.bit_count == 0)1125 if (@typeInfo(T).Int.bits == 0)
1126 return set(u8, buffer, 0);1126 return set(u8, buffer, 0);
11271127
1128 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough1128 // TODO I want to call writeIntBig here but comptime eval facilities aren't good enough
1129 const uint = std.meta.Int(false, T.bit_count);1129 const uint = std.meta.Int(false, @typeInfo(T).Int.bits);
1130 var bits = @truncate(uint, value);1130 var bits = @truncate(uint, value);
1131 var index: usize = buffer.len;1131 var index: usize = buffer.len;
1132 while (index != 0) {1132 while (index != 0) {
...@@ -1147,13 +1147,13 @@ pub const writeIntSliceForeign = switch (builtin.endian) {...@@ -1147,13 +1147,13 @@ pub const writeIntSliceForeign = switch (builtin.endian) {
1147};1147};
11481148
1149/// Writes a twos-complement integer to memory, with the specified endianness.1149/// Writes a twos-complement integer to memory, with the specified endianness.
1150/// Asserts that buf.len >= T.bit_count / 8.1150/// Asserts that buf.len >= @typeInfo(T).Int.bits / 8.
1151/// The bit count of T must be evenly divisible by 8.1151/// The bit count of T must be evenly divisible by 8.
1152/// Any extra bytes in buffer not part of the integer are set to zero, with1152/// Any extra bytes in buffer not part of the integer are set to zero, with
1153/// respect to endianness. To avoid the branch to check for extra buffer bytes,1153/// respect to endianness. To avoid the branch to check for extra buffer bytes,
1154/// use writeInt instead.1154/// use writeInt instead.
1155pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {1155pub fn writeIntSlice(comptime T: type, buffer: []u8, value: T, endian: builtin.Endian) void {
1156 comptime assert(T.bit_count % 8 == 0);1156 comptime assert(@typeInfo(T).Int.bits % 8 == 0);
1157 return switch (endian) {1157 return switch (endian) {
1158 .Little => writeIntSliceLittle(T, buffer, value),1158 .Little => writeIntSliceLittle(T, buffer, value),
1159 .Big => writeIntSliceBig(T, buffer, value),1159 .Big => writeIntSliceBig(T, buffer, value),
lib/std/mem/Allocator.zig+4-4
...@@ -159,7 +159,7 @@ fn moveBytes(...@@ -159,7 +159,7 @@ fn moveBytes(
159/// Returns a pointer to undefined memory.159/// Returns a pointer to undefined memory.
160/// Call `destroy` with the result to free the memory.160/// Call `destroy` with the result to free the memory.
161pub fn create(self: *Allocator, comptime T: type) Error!*T {161pub fn create(self: *Allocator, comptime T: type) Error!*T {
162 if (@sizeOf(T) == 0) return &(T{});162 if (@sizeOf(T) == 0) return @as(*T, undefined);
163 const slice = try self.allocAdvancedWithRetAddr(T, null, 1, .exact, @returnAddress());163 const slice = try self.allocAdvancedWithRetAddr(T, null, 1, .exact, @returnAddress());
164 return &slice[0];164 return &slice[0];
165}165}
...@@ -167,11 +167,11 @@ pub fn create(self: *Allocator, comptime T: type) Error!*T {...@@ -167,11 +167,11 @@ pub fn create(self: *Allocator, comptime T: type) Error!*T {
167/// `ptr` should be the return value of `create`, or otherwise167/// `ptr` should be the return value of `create`, or otherwise
168/// have the same address and alignment property.168/// have the same address and alignment property.
169pub fn destroy(self: *Allocator, ptr: anytype) void {169pub fn destroy(self: *Allocator, ptr: anytype) void {
170 const T = @TypeOf(ptr).Child;170 const info = @typeInfo(@TypeOf(ptr)).Pointer;
171 const T = info.child;
171 if (@sizeOf(T) == 0) return;172 if (@sizeOf(T) == 0) return;
172 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));173 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(ptr));
173 const ptr_align = @typeInfo(@TypeOf(ptr)).Pointer.alignment;174 _ = self.shrinkBytes(non_const_ptr[0..@sizeOf(T)], info.alignment, 0, 0, @returnAddress());
174 _ = self.shrinkBytes(non_const_ptr[0..@sizeOf(T)], ptr_align, 0, 0, @returnAddress());
175}175}
176176
177/// Allocates an array of `n` items of type `T` and sets all the177/// Allocates an array of `n` items of type `T` and sets all the
lib/std/os.zig+1-1
...@@ -4526,7 +4526,7 @@ pub fn res_mkquery(...@@ -4526,7 +4526,7 @@ pub fn res_mkquery(
4526 // Make a reasonably unpredictable id4526 // Make a reasonably unpredictable id
4527 var ts: timespec = undefined;4527 var ts: timespec = undefined;
4528 clock_gettime(CLOCK_REALTIME, &ts) catch {};4528 clock_gettime(CLOCK_REALTIME, &ts) catch {};
4529 const UInt = std.meta.Int(false, @TypeOf(ts.tv_nsec).bit_count);4529 const UInt = std.meta.Int(false, std.meta.bitCount(@TypeOf(ts.tv_nsec)));
4530 const unsec = @bitCast(UInt, ts.tv_nsec);4530 const unsec = @bitCast(UInt, ts.tv_nsec);
4531 const id = @truncate(u32, unsec + unsec / 65536);4531 const id = @truncate(u32, unsec + unsec / 65536);
4532 q[0] = @truncate(u8, id / 256);4532 q[0] = @truncate(u8, id / 256);
lib/std/os/bits/linux.zig+1-1
...@@ -846,7 +846,7 @@ pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));...@@ -846,7 +846,7 @@ pub const SIG_ERR = @intToPtr(?Sigaction.sigaction_fn, maxInt(usize));
846pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);846pub const SIG_DFL = @intToPtr(?Sigaction.sigaction_fn, 0);
847pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);847pub const SIG_IGN = @intToPtr(?Sigaction.sigaction_fn, 1);
848848
849pub const empty_sigset = [_]u32{0} ** sigset_t.len;849pub const empty_sigset = [_]u32{0} ** @typeInfo(sigset_t).Array.len;
850850
851pub const signalfd_siginfo = extern struct {851pub const signalfd_siginfo = extern struct {
852 signo: u32,852 signo: u32,
lib/std/os/linux.zig+5-3
...@@ -829,17 +829,19 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti...@@ -829,17 +829,19 @@ pub fn sigaction(sig: u6, noalias act: *const Sigaction, noalias oact: ?*Sigacti
829 return 0;829 return 0;
830}830}
831831
832const usize_bits = @typeInfo(usize).Int.bits;
833
832pub fn sigaddset(set: *sigset_t, sig: u6) void {834pub fn sigaddset(set: *sigset_t, sig: u6) void {
833 const s = sig - 1;835 const s = sig - 1;
834 // shift in musl: s&8*sizeof *set->__bits-1836 // shift in musl: s&8*sizeof *set->__bits-1
835 const shift = @intCast(u5, s & (usize.bit_count - 1));837 const shift = @intCast(u5, s & (usize_bits - 1));
836 const val = @intCast(u32, 1) << shift;838 const val = @intCast(u32, 1) << shift;
837 (set.*)[@intCast(usize, s) / usize.bit_count] |= val;839 (set.*)[@intCast(usize, s) / usize_bits] |= val;
838}840}
839841
840pub fn sigismember(set: *const sigset_t, sig: u6) bool {842pub fn sigismember(set: *const sigset_t, sig: u6) bool {
841 const s = sig - 1;843 const s = sig - 1;
842 return ((set.*)[@intCast(usize, s) / usize.bit_count] & (@intCast(usize, 1) << (s & (usize.bit_count - 1)))) != 0;844 return ((set.*)[@intCast(usize, s) / usize_bits] & (@intCast(usize, 1) << (s & (usize_bits - 1)))) != 0;
843}845}
844846
845pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {847pub fn getsockname(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize {
lib/std/os/windows/ws2_32.zig+1-1
...@@ -12,7 +12,7 @@ pub const SOCKET_ERROR = -1;...@@ -12,7 +12,7 @@ pub const SOCKET_ERROR = -1;
12pub const WSADESCRIPTION_LEN = 256;12pub const WSADESCRIPTION_LEN = 256;
13pub const WSASYS_STATUS_LEN = 128;13pub const WSASYS_STATUS_LEN = 128;
1414
15pub const WSADATA = if (usize.bit_count == u64.bit_count)15pub const WSADATA = if (@sizeOf(usize) == @sizeOf(u64))
16 extern struct {16 extern struct {
17 wVersion: WORD,17 wVersion: WORD,
18 wHighVersion: WORD,18 wHighVersion: WORD,
lib/std/pdb.zig+1-1
...@@ -636,7 +636,7 @@ const MsfStream = struct {...@@ -636,7 +636,7 @@ const MsfStream = struct {
636 blocks: []u32 = undefined,636 blocks: []u32 = undefined,
637 block_size: u32 = undefined,637 block_size: u32 = undefined,
638638
639 pub const Error = @TypeOf(read).ReturnType.ErrorSet;639 pub const Error = @typeInfo(@typeInfo(@TypeOf(read)).Fn.return_type.?).ErrorUnion.error_set;
640640
641 fn init(block_size: u32, file: File, blocks: []u32) MsfStream {641 fn init(block_size: u32, file: File, blocks: []u32) MsfStream {
642 const stream = MsfStream{642 const stream = MsfStream{
lib/std/rand.zig+33-24
...@@ -51,8 +51,9 @@ pub const Random = struct {...@@ -51,8 +51,9 @@ pub const Random = struct {
51 /// Returns a random int `i` such that `0 <= i <= maxInt(T)`.51 /// Returns a random int `i` such that `0 <= i <= maxInt(T)`.
52 /// `i` is evenly distributed.52 /// `i` is evenly distributed.
53 pub fn int(r: *Random, comptime T: type) T {53 pub fn int(r: *Random, comptime T: type) T {
54 const UnsignedT = std.meta.Int(false, T.bit_count);54 const bits = @typeInfo(T).Int.bits;
55 const ByteAlignedT = std.meta.Int(false, @divTrunc(T.bit_count + 7, 8) * 8);55 const UnsignedT = std.meta.Int(false, bits);
56 const ByteAlignedT = std.meta.Int(false, @divTrunc(bits + 7, 8) * 8);
5657
57 var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined;58 var rand_bytes: [@sizeOf(ByteAlignedT)]u8 = undefined;
58 r.bytes(rand_bytes[0..]);59 r.bytes(rand_bytes[0..]);
...@@ -68,10 +69,11 @@ pub const Random = struct {...@@ -68,10 +69,11 @@ pub const Random = struct {
68 /// Constant-time implementation off `uintLessThan`.69 /// Constant-time implementation off `uintLessThan`.
69 /// The results of this function may be biased.70 /// The results of this function may be biased.
70 pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {71 pub fn uintLessThanBiased(r: *Random, comptime T: type, less_than: T) T {
71 comptime assert(T.is_signed == false);72 comptime assert(@typeInfo(T).Int.is_signed == false);
72 comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!73 const bits = @typeInfo(T).Int.bits;
74 comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
73 assert(0 < less_than);75 assert(0 < less_than);
74 if (T.bit_count <= 32) {76 if (bits <= 32) {
75 return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than));77 return @intCast(T, limitRangeBiased(u32, r.int(u32), less_than));
76 } else {78 } else {
77 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));79 return @intCast(T, limitRangeBiased(u64, r.int(u64), less_than));
...@@ -87,13 +89,15 @@ pub const Random = struct {...@@ -87,13 +89,15 @@ pub const Random = struct {
87 /// this function is guaranteed to return.89 /// this function is guaranteed to return.
88 /// If you need deterministic runtime bounds, use `uintLessThanBiased`.90 /// If you need deterministic runtime bounds, use `uintLessThanBiased`.
89 pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {91 pub fn uintLessThan(r: *Random, comptime T: type, less_than: T) T {
90 comptime assert(T.is_signed == false);92 comptime assert(@typeInfo(T).Int.is_signed == false);
91 comptime assert(T.bit_count <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!93 const bits = @typeInfo(T).Int.bits;
94 comptime assert(bits <= 64); // TODO: workaround: LLVM ERROR: Unsupported library call operation!
92 assert(0 < less_than);95 assert(0 < less_than);
93 // Small is typically u3296 // Small is typically u32
94 const Small = std.meta.Int(false, @divTrunc(T.bit_count + 31, 32) * 32);97 const small_bits = @divTrunc(bits + 31, 32) * 32;
98 const Small = std.meta.Int(false, small_bits);
95 // Large is typically u6499 // Large is typically u64
96 const Large = std.meta.Int(false, Small.bit_count * 2);100 const Large = std.meta.Int(false, small_bits * 2);
97101
98 // adapted from:102 // adapted from:
99 // http://www.pcg-random.org/posts/bounded-rands.html103 // http://www.pcg-random.org/posts/bounded-rands.html
...@@ -105,7 +109,7 @@ pub const Random = struct {...@@ -105,7 +109,7 @@ pub const Random = struct {
105 // TODO: workaround for https://github.com/ziglang/zig/issues/1770109 // TODO: workaround for https://github.com/ziglang/zig/issues/1770
106 // should be:110 // should be:
107 // var t: Small = -%less_than;111 // var t: Small = -%less_than;
108 var t: Small = @bitCast(Small, -%@bitCast(std.meta.Int(true, Small.bit_count), @as(Small, less_than)));112 var t: Small = @bitCast(Small, -%@bitCast(std.meta.Int(true, small_bits), @as(Small, less_than)));
109113
110 if (t >= less_than) {114 if (t >= less_than) {
111 t -= less_than;115 t -= less_than;
...@@ -119,13 +123,13 @@ pub const Random = struct {...@@ -119,13 +123,13 @@ pub const Random = struct {
119 l = @truncate(Small, m);123 l = @truncate(Small, m);
120 }124 }
121 }125 }
122 return @intCast(T, m >> Small.bit_count);126 return @intCast(T, m >> small_bits);
123 }127 }
124128
125 /// Constant-time implementation off `uintAtMost`.129 /// Constant-time implementation off `uintAtMost`.
126 /// The results of this function may be biased.130 /// The results of this function may be biased.
127 pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {131 pub fn uintAtMostBiased(r: *Random, comptime T: type, at_most: T) T {
128 assert(T.is_signed == false);132 assert(@typeInfo(T).Int.is_signed == false);
129 if (at_most == maxInt(T)) {133 if (at_most == maxInt(T)) {
130 // have the full range134 // have the full range
131 return r.int(T);135 return r.int(T);
...@@ -137,7 +141,7 @@ pub const Random = struct {...@@ -137,7 +141,7 @@ pub const Random = struct {
137 /// See `uintLessThan`, which this function uses in most cases,141 /// See `uintLessThan`, which this function uses in most cases,
138 /// for commentary on the runtime of this function.142 /// for commentary on the runtime of this function.
139 pub fn uintAtMost(r: *Random, comptime T: type, at_most: T) T {143 pub fn uintAtMost(r: *Random, comptime T: type, at_most: T) T {
140 assert(T.is_signed == false);144 assert(@typeInfo(T).Int.is_signed == false);
141 if (at_most == maxInt(T)) {145 if (at_most == maxInt(T)) {
142 // have the full range146 // have the full range
143 return r.int(T);147 return r.int(T);
...@@ -149,9 +153,10 @@ pub const Random = struct {...@@ -149,9 +153,10 @@ pub const Random = struct {
149 /// The results of this function may be biased.153 /// The results of this function may be biased.
150 pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {154 pub fn intRangeLessThanBiased(r: *Random, comptime T: type, at_least: T, less_than: T) T {
151 assert(at_least < less_than);155 assert(at_least < less_than);
152 if (T.is_signed) {156 const info = @typeInfo(T).Int;
157 if (info.is_signed) {
153 // Two's complement makes this math pretty easy.158 // Two's complement makes this math pretty easy.
154 const UnsignedT = std.meta.Int(false, T.bit_count);159 const UnsignedT = std.meta.Int(false, info.bits);
155 const lo = @bitCast(UnsignedT, at_least);160 const lo = @bitCast(UnsignedT, at_least);
156 const hi = @bitCast(UnsignedT, less_than);161 const hi = @bitCast(UnsignedT, less_than);
157 const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);162 const result = lo +% r.uintLessThanBiased(UnsignedT, hi -% lo);
...@@ -167,9 +172,10 @@ pub const Random = struct {...@@ -167,9 +172,10 @@ pub const Random = struct {
167 /// for commentary on the runtime of this function.172 /// for commentary on the runtime of this function.
168 pub fn intRangeLessThan(r: *Random, comptime T: type, at_least: T, less_than: T) T {173 pub fn intRangeLessThan(r: *Random, comptime T: type, at_least: T, less_than: T) T {
169 assert(at_least < less_than);174 assert(at_least < less_than);
170 if (T.is_signed) {175 const info = @typeInfo(T).Int;
176 if (info.is_signed) {
171 // Two's complement makes this math pretty easy.177 // Two's complement makes this math pretty easy.
172 const UnsignedT = std.meta.Int(false, T.bit_count);178 const UnsignedT = std.meta.Int(false, info.bits);
173 const lo = @bitCast(UnsignedT, at_least);179 const lo = @bitCast(UnsignedT, at_least);
174 const hi = @bitCast(UnsignedT, less_than);180 const hi = @bitCast(UnsignedT, less_than);
175 const result = lo +% r.uintLessThan(UnsignedT, hi -% lo);181 const result = lo +% r.uintLessThan(UnsignedT, hi -% lo);
...@@ -184,9 +190,10 @@ pub const Random = struct {...@@ -184,9 +190,10 @@ pub const Random = struct {
184 /// The results of this function may be biased.190 /// The results of this function may be biased.
185 pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {191 pub fn intRangeAtMostBiased(r: *Random, comptime T: type, at_least: T, at_most: T) T {
186 assert(at_least <= at_most);192 assert(at_least <= at_most);
187 if (T.is_signed) {193 const info = @typeInfo(T).Int;
194 if (info.is_signed) {
188 // Two's complement makes this math pretty easy.195 // Two's complement makes this math pretty easy.
189 const UnsignedT = std.meta.Int(false, T.bit_count);196 const UnsignedT = std.meta.Int(false, info.bits);
190 const lo = @bitCast(UnsignedT, at_least);197 const lo = @bitCast(UnsignedT, at_least);
191 const hi = @bitCast(UnsignedT, at_most);198 const hi = @bitCast(UnsignedT, at_most);
192 const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);199 const result = lo +% r.uintAtMostBiased(UnsignedT, hi -% lo);
...@@ -202,9 +209,10 @@ pub const Random = struct {...@@ -202,9 +209,10 @@ pub const Random = struct {
202 /// for commentary on the runtime of this function.209 /// for commentary on the runtime of this function.
203 pub fn intRangeAtMost(r: *Random, comptime T: type, at_least: T, at_most: T) T {210 pub fn intRangeAtMost(r: *Random, comptime T: type, at_least: T, at_most: T) T {
204 assert(at_least <= at_most);211 assert(at_least <= at_most);
205 if (T.is_signed) {212 const info = @typeInfo(T).Int;
213 if (info.is_signed) {
206 // Two's complement makes this math pretty easy.214 // Two's complement makes this math pretty easy.
207 const UnsignedT = std.meta.Int(false, T.bit_count);215 const UnsignedT = std.meta.Int(false, info.bits);
208 const lo = @bitCast(UnsignedT, at_least);216 const lo = @bitCast(UnsignedT, at_least);
209 const hi = @bitCast(UnsignedT, at_most);217 const hi = @bitCast(UnsignedT, at_most);
210 const result = lo +% r.uintAtMost(UnsignedT, hi -% lo);218 const result = lo +% r.uintAtMost(UnsignedT, hi -% lo);
...@@ -280,14 +288,15 @@ pub const Random = struct {...@@ -280,14 +288,15 @@ pub const Random = struct {
280/// into an integer 0 <= result < less_than.288/// into an integer 0 <= result < less_than.
281/// This function introduces a minor bias.289/// This function introduces a minor bias.
282pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {290pub fn limitRangeBiased(comptime T: type, random_int: T, less_than: T) T {
283 comptime assert(T.is_signed == false);291 comptime assert(@typeInfo(T).Int.is_signed == false);
284 const T2 = std.meta.Int(false, T.bit_count * 2);292 const bits = @typeInfo(T).Int.bits;
293 const T2 = std.meta.Int(false, bits * 2);
285294
286 // adapted from:295 // adapted from:
287 // http://www.pcg-random.org/posts/bounded-rands.html296 // http://www.pcg-random.org/posts/bounded-rands.html
288 // "Integer Multiplication (Biased)"297 // "Integer Multiplication (Biased)"
289 var m: T2 = @as(T2, random_int) * @as(T2, less_than);298 var m: T2 = @as(T2, random_int) * @as(T2, less_than);
290 return @intCast(T, m >> T.bit_count);299 return @intCast(T, m >> bits);
291}300}
292301
293const SequentialPrng = struct {302const SequentialPrng = struct {
lib/std/special/build_runner.zig+1-1
...@@ -133,7 +133,7 @@ pub fn main() !void {...@@ -133,7 +133,7 @@ pub fn main() !void {
133}133}
134134
135fn runBuild(builder: *Builder) anyerror!void {135fn runBuild(builder: *Builder) anyerror!void {
136 switch (@typeInfo(@TypeOf(root.build).ReturnType)) {136 switch (@typeInfo(@typeInfo(@TypeOf(root.build)).Fn.return_type.?)) {
137 .Void => root.build(builder),137 .Void => root.build(builder),
138 .ErrorUnion => try root.build(builder),138 .ErrorUnion => try root.build(builder),
139 else => @compileError("expected return type of build to be 'void' or '!void'"),139 else => @compileError("expected return type of build to be 'void' or '!void'"),
lib/std/special/c.zig+3-2
...@@ -516,11 +516,12 @@ export fn roundf(a: f32) f32 {...@@ -516,11 +516,12 @@ export fn roundf(a: f32) f32 {
516fn generic_fmod(comptime T: type, x: T, y: T) T {516fn generic_fmod(comptime T: type, x: T, y: T) T {
517 @setRuntimeSafety(false);517 @setRuntimeSafety(false);
518518
519 const uint = std.meta.Int(false, T.bit_count);519 const bits = @typeInfo(T).Float.bits;
520 const uint = std.meta.Int(false, bits);
520 const log2uint = math.Log2Int(uint);521 const log2uint = math.Log2Int(uint);
521 const digits = if (T == f32) 23 else 52;522 const digits = if (T == f32) 23 else 52;
522 const exp_bits = if (T == f32) 9 else 12;523 const exp_bits = if (T == f32) 9 else 12;
523 const bits_minus_1 = T.bit_count - 1;524 const bits_minus_1 = bits - 1;
524 const mask = if (T == f32) 0xff else 0x7ff;525 const mask = if (T == f32) 0xff else 0x7ff;
525 var ux = @bitCast(uint, x);526 var ux = @bitCast(uint, x);
526 var uy = @bitCast(uint, y);527 var uy = @bitCast(uint, y);
lib/std/special/compiler_rt/addXf3.zig+10-8
...@@ -59,23 +59,25 @@ pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 {...@@ -59,23 +59,25 @@ pub fn __aeabi_dsub(a: f64, b: f64) callconv(.AAPCS) f64 {
59}59}
6060
61// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/215461// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
62fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i32 {62fn normalize(comptime T: type, significand: *std.meta.Int(false, @typeInfo(T).Float.bits)) i32 {
63 const Z = std.meta.Int(false, T.bit_count);63 const bits = @typeInfo(T).Float.bits;
64 const S = std.meta.Int(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));64 const Z = std.meta.Int(false, bits);
65 const S = std.meta.Int(false, bits - @clz(Z, @as(Z, bits) - 1));
65 const significandBits = std.math.floatMantissaBits(T);66 const significandBits = std.math.floatMantissaBits(T);
66 const implicitBit = @as(Z, 1) << significandBits;67 const implicitBit = @as(Z, 1) << significandBits;
6768
68 const shift = @clz(std.meta.Int(false, T.bit_count), significand.*) - @clz(Z, implicitBit);69 const shift = @clz(std.meta.Int(false, bits), significand.*) - @clz(Z, implicitBit);
69 significand.* <<= @intCast(S, shift);70 significand.* <<= @intCast(S, shift);
70 return 1 - shift;71 return 1 - shift;
71}72}
7273
73// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/215474// TODO: restore inline keyword, see: https://github.com/ziglang/zig/issues/2154
74fn addXf3(comptime T: type, a: T, b: T) T {75fn addXf3(comptime T: type, a: T, b: T) T {
75 const Z = std.meta.Int(false, T.bit_count);76 const bits = @typeInfo(T).Float.bits;
76 const S = std.meta.Int(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));77 const Z = std.meta.Int(false, bits);
78 const S = std.meta.Int(false, bits - @clz(Z, @as(Z, bits) - 1));
7779
78 const typeWidth = T.bit_count;80 const typeWidth = bits;
79 const significandBits = std.math.floatMantissaBits(T);81 const significandBits = std.math.floatMantissaBits(T);
80 const exponentBits = std.math.floatExponentBits(T);82 const exponentBits = std.math.floatExponentBits(T);
8183
...@@ -187,7 +189,7 @@ fn addXf3(comptime T: type, a: T, b: T) T {...@@ -187,7 +189,7 @@ fn addXf3(comptime T: type, a: T, b: T) T {
187 // If partial cancellation occured, we need to left-shift the result189 // If partial cancellation occured, we need to left-shift the result
188 // and adjust the exponent:190 // and adjust the exponent:
189 if (aSignificand < implicitBit << 3) {191 if (aSignificand < implicitBit << 3) {
190 const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(false, T.bit_count), implicitBit << 3));192 const shift = @intCast(i32, @clz(Z, aSignificand)) - @intCast(i32, @clz(std.meta.Int(false, bits), implicitBit << 3));
191 aSignificand <<= @intCast(S, shift);193 aSignificand <<= @intCast(S, shift);
192 aExponent -= shift;194 aExponent -= shift;
193 }195 }
lib/std/special/compiler_rt/aulldiv.zig+2-2
...@@ -7,8 +7,8 @@ const builtin = @import("builtin");...@@ -7,8 +7,8 @@ const builtin = @import("builtin");
77
8pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {8pub fn _alldiv(a: i64, b: i64) callconv(.Stdcall) i64 {
9 @setRuntimeSafety(builtin.is_test);9 @setRuntimeSafety(builtin.is_test);
10 const s_a = a >> (i64.bit_count - 1);10 const s_a = a >> (64 - 1);
11 const s_b = b >> (i64.bit_count - 1);11 const s_b = b >> (64 - 1);
1212
13 const an = (a ^ s_a) -% s_a;13 const an = (a ^ s_a) -% s_a;
14 const bn = (b ^ s_b) -% s_b;14 const bn = (b ^ s_b) -% s_b;
lib/std/special/compiler_rt/aullrem.zig+2-2
...@@ -7,8 +7,8 @@ const builtin = @import("builtin");...@@ -7,8 +7,8 @@ const builtin = @import("builtin");
77
8pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {8pub fn _allrem(a: i64, b: i64) callconv(.Stdcall) i64 {
9 @setRuntimeSafety(builtin.is_test);9 @setRuntimeSafety(builtin.is_test);
10 const s_a = a >> (i64.bit_count - 1);10 const s_a = a >> (64 - 1);
11 const s_b = b >> (i64.bit_count - 1);11 const s_b = b >> (64 - 1);
1212
13 const an = (a ^ s_a) -% s_a;13 const an = (a ^ s_a) -% s_a;
14 const bn = (b ^ s_b) -% s_b;14 const bn = (b ^ s_b) -% s_b;
lib/std/special/compiler_rt/compareXf2.zig+4-3
...@@ -27,8 +27,9 @@ const GE = extern enum(i32) {...@@ -27,8 +27,9 @@ const GE = extern enum(i32) {
27pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {27pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
28 @setRuntimeSafety(builtin.is_test);28 @setRuntimeSafety(builtin.is_test);
2929
30 const srep_t = std.meta.Int(true, T.bit_count);30 const bits = @typeInfo(T).Float.bits;
31 const rep_t = std.meta.Int(false, T.bit_count);31 const srep_t = std.meta.Int(true, bits);
32 const rep_t = std.meta.Int(false, bits);
3233
33 const significandBits = std.math.floatMantissaBits(T);34 const significandBits = std.math.floatMantissaBits(T);
34 const exponentBits = std.math.floatExponentBits(T);35 const exponentBits = std.math.floatExponentBits(T);
...@@ -73,7 +74,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {...@@ -73,7 +74,7 @@ pub fn cmp(comptime T: type, comptime RT: type, a: T, b: T) RT {
73pub fn unordcmp(comptime T: type, a: T, b: T) i32 {74pub fn unordcmp(comptime T: type, a: T, b: T) i32 {
74 @setRuntimeSafety(builtin.is_test);75 @setRuntimeSafety(builtin.is_test);
7576
76 const rep_t = std.meta.Int(false, T.bit_count);77 const rep_t = std.meta.Int(false, @typeInfo(T).Float.bits);
7778
78 const significandBits = std.math.floatMantissaBits(T);79 const significandBits = std.math.floatMantissaBits(T);
79 const exponentBits = std.math.floatExponentBits(T);80 const exponentBits = std.math.floatExponentBits(T);
lib/std/special/compiler_rt/divdf3.zig+4-5
...@@ -12,10 +12,9 @@ const builtin = @import("builtin");...@@ -12,10 +12,9 @@ const builtin = @import("builtin");
1212
13pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {13pub fn __divdf3(a: f64, b: f64) callconv(.C) f64 {
14 @setRuntimeSafety(builtin.is_test);14 @setRuntimeSafety(builtin.is_test);
15 const Z = std.meta.Int(false, f64.bit_count);15 const Z = std.meta.Int(false, 64);
16 const SignedZ = std.meta.Int(true, f64.bit_count);16 const SignedZ = std.meta.Int(true, 64);
1717
18 const typeWidth = f64.bit_count;
19 const significandBits = std.math.floatMantissaBits(f64);18 const significandBits = std.math.floatMantissaBits(f64);
20 const exponentBits = std.math.floatExponentBits(f64);19 const exponentBits = std.math.floatExponentBits(f64);
2120
...@@ -317,9 +316,9 @@ pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {...@@ -317,9 +316,9 @@ pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
317 }316 }
318}317}
319318
320pub fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i32 {319pub fn normalize(comptime T: type, significand: *std.meta.Int(false, @typeInfo(T).Float.bits)) i32 {
321 @setRuntimeSafety(builtin.is_test);320 @setRuntimeSafety(builtin.is_test);
322 const Z = std.meta.Int(false, T.bit_count);321 const Z = std.meta.Int(false, @typeInfo(T).Float.bits);
323 const significandBits = std.math.floatMantissaBits(T);322 const significandBits = std.math.floatMantissaBits(T);
324 const implicitBit = @as(Z, 1) << significandBits;323 const implicitBit = @as(Z, 1) << significandBits;
325324
lib/std/special/compiler_rt/divsf3.zig+3-4
...@@ -12,9 +12,8 @@ const builtin = @import("builtin");...@@ -12,9 +12,8 @@ const builtin = @import("builtin");
1212
13pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {13pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
14 @setRuntimeSafety(builtin.is_test);14 @setRuntimeSafety(builtin.is_test);
15 const Z = std.meta.Int(false, f32.bit_count);15 const Z = std.meta.Int(false, 32);
1616
17 const typeWidth = f32.bit_count;
18 const significandBits = std.math.floatMantissaBits(f32);17 const significandBits = std.math.floatMantissaBits(f32);
19 const exponentBits = std.math.floatExponentBits(f32);18 const exponentBits = std.math.floatExponentBits(f32);
2019
...@@ -190,9 +189,9 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {...@@ -190,9 +189,9 @@ pub fn __divsf3(a: f32, b: f32) callconv(.C) f32 {
190 }189 }
191}190}
192191
193fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i32 {192fn normalize(comptime T: type, significand: *std.meta.Int(false, @typeInfo(T).Float.bits)) i32 {
194 @setRuntimeSafety(builtin.is_test);193 @setRuntimeSafety(builtin.is_test);
195 const Z = std.meta.Int(false, T.bit_count);194 const Z = std.meta.Int(false, @typeInfo(T).Float.bits);
196 const significandBits = std.math.floatMantissaBits(T);195 const significandBits = std.math.floatMantissaBits(T);
197 const implicitBit = @as(Z, 1) << significandBits;196 const implicitBit = @as(Z, 1) << significandBits;
198197
lib/std/special/compiler_rt/divtf3.zig+2-3
...@@ -11,10 +11,9 @@ const wideMultiply = @import("divdf3.zig").wideMultiply;...@@ -11,10 +11,9 @@ const wideMultiply = @import("divdf3.zig").wideMultiply;
1111
12pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {12pub fn __divtf3(a: f128, b: f128) callconv(.C) f128 {
13 @setRuntimeSafety(builtin.is_test);13 @setRuntimeSafety(builtin.is_test);
14 const Z = std.meta.Int(false, f128.bit_count);14 const Z = std.meta.Int(false, 128);
15 const SignedZ = std.meta.Int(true, f128.bit_count);15 const SignedZ = std.meta.Int(true, 128);
1616
17 const typeWidth = f128.bit_count;
18 const significandBits = std.math.floatMantissaBits(f128);17 const significandBits = std.math.floatMantissaBits(f128);
19 const exponentBits = std.math.floatExponentBits(f128);18 const exponentBits = std.math.floatExponentBits(f128);
2019
lib/std/special/compiler_rt/divti3.zig+2-2
...@@ -9,8 +9,8 @@ const builtin = @import("builtin");...@@ -9,8 +9,8 @@ const builtin = @import("builtin");
9pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {9pub fn __divti3(a: i128, b: i128) callconv(.C) i128 {
10 @setRuntimeSafety(builtin.is_test);10 @setRuntimeSafety(builtin.is_test);
1111
12 const s_a = a >> (i128.bit_count - 1);12 const s_a = a >> (128 - 1);
13 const s_b = b >> (i128.bit_count - 1);13 const s_b = b >> (128 - 1);
1414
15 const an = (a ^ s_a) -% s_a;15 const an = (a ^ s_a) -% s_a;
16 const bn = (b ^ s_b) -% s_b;16 const bn = (b ^ s_b) -% s_b;
lib/std/special/compiler_rt/fixint.zig+5-4
...@@ -28,7 +28,7 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {...@@ -28,7 +28,7 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
28 else => unreachable,28 else => unreachable,
29 };29 };
3030
31 const typeWidth = rep_t.bit_count;31 const typeWidth = @typeInfo(rep_t).Int.bits;
32 const exponentBits = (typeWidth - significandBits - 1);32 const exponentBits = (typeWidth - significandBits - 1);
33 const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));33 const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
34 const maxExponent = ((1 << exponentBits) - 1);34 const maxExponent = ((1 << exponentBits) - 1);
...@@ -50,12 +50,13 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {...@@ -50,12 +50,13 @@ pub fn fixint(comptime fp_t: type, comptime fixint_t: type, a: fp_t) fixint_t {
50 if (exponent < 0) return 0;50 if (exponent < 0) return 0;
5151
52 // The unsigned result needs to be large enough to handle an fixint_t or rep_t52 // The unsigned result needs to be large enough to handle an fixint_t or rep_t
53 const fixuint_t = std.meta.Int(false, fixint_t.bit_count);53 const fixint_bits = @typeInfo(fixint_t).Int.bits;
54 const UintResultType = if (fixint_t.bit_count > rep_t.bit_count) fixuint_t else rep_t;54 const fixuint_t = std.meta.Int(false, fixint_bits);
55 const UintResultType = if (fixint_bits > typeWidth) fixuint_t else rep_t;
55 var uint_result: UintResultType = undefined;56 var uint_result: UintResultType = undefined;
5657
57 // If the value is too large for the integer type, saturate.58 // If the value is too large for the integer type, saturate.
58 if (@intCast(usize, exponent) >= fixint_t.bit_count) {59 if (@intCast(usize, exponent) >= fixint_bits) {
59 return if (negative) @as(fixint_t, minInt(fixint_t)) else @as(fixint_t, maxInt(fixint_t));60 return if (negative) @as(fixint_t, minInt(fixint_t)) else @as(fixint_t, maxInt(fixint_t));
60 }61 }
6162
lib/std/special/compiler_rt/fixuint.zig+3-3
...@@ -15,14 +15,14 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t...@@ -15,14 +15,14 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
15 f128 => u128,15 f128 => u128,
16 else => unreachable,16 else => unreachable,
17 };17 };
18 const srep_t = @import("std").meta.Int(true, rep_t.bit_count);18 const typeWidth = @typeInfo(rep_t).Int.bits;
19 const srep_t = @import("std").meta.Int(true, typeWidth);
19 const significandBits = switch (fp_t) {20 const significandBits = switch (fp_t) {
20 f32 => 23,21 f32 => 23,
21 f64 => 52,22 f64 => 52,
22 f128 => 112,23 f128 => 112,
23 else => unreachable,24 else => unreachable,
24 };25 };
25 const typeWidth = rep_t.bit_count;
26 const exponentBits = (typeWidth - significandBits - 1);26 const exponentBits = (typeWidth - significandBits - 1);
27 const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));27 const signBit = (@as(rep_t, 1) << (significandBits + exponentBits));
28 const maxExponent = ((1 << exponentBits) - 1);28 const maxExponent = ((1 << exponentBits) - 1);
...@@ -44,7 +44,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t...@@ -44,7 +44,7 @@ pub fn fixuint(comptime fp_t: type, comptime fixuint_t: type, a: fp_t) fixuint_t
44 if (sign == -1 or exponent < 0) return 0;44 if (sign == -1 or exponent < 0) return 0;
4545
46 // If the value is too large for the integer type, saturate.46 // If the value is too large for the integer type, saturate.
47 if (@intCast(c_uint, exponent) >= fixuint_t.bit_count) return ~@as(fixuint_t, 0);47 if (@intCast(c_uint, exponent) >= @typeInfo(fixuint_t).Int.bits) return ~@as(fixuint_t, 0);
4848
49 // If 0 <= exponent < significandBits, right shift to get the result.49 // If 0 <= exponent < significandBits, right shift to get the result.
50 // Otherwise, shift left.50 // Otherwise, shift left.
lib/std/special/compiler_rt/floatXisf.zig+5-4
...@@ -12,15 +12,16 @@ const FLT_MANT_DIG = 24;...@@ -12,15 +12,16 @@ const FLT_MANT_DIG = 24;
12fn __floatXisf(comptime T: type, arg: T) f32 {12fn __floatXisf(comptime T: type, arg: T) f32 {
13 @setRuntimeSafety(builtin.is_test);13 @setRuntimeSafety(builtin.is_test);
1414
15 const Z = std.meta.Int(false, T.bit_count);15 const bits = @typeInfo(T).Int.bits;
16 const S = std.meta.Int(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));16 const Z = std.meta.Int(false, bits);
17 const S = std.meta.Int(false, bits - @clz(Z, @as(Z, bits) - 1));
1718
18 if (arg == 0) {19 if (arg == 0) {
19 return @as(f32, 0.0);20 return @as(f32, 0.0);
20 }21 }
2122
22 var ai = arg;23 var ai = arg;
23 const N: u32 = T.bit_count;24 const N: u32 = bits;
24 const si = ai >> @intCast(S, (N - 1));25 const si = ai >> @intCast(S, (N - 1));
25 ai = ((ai ^ si) -% si);26 ai = ((ai ^ si) -% si);
26 var a = @bitCast(Z, ai);27 var a = @bitCast(Z, ai);
...@@ -66,7 +67,7 @@ fn __floatXisf(comptime T: type, arg: T) f32 {...@@ -66,7 +67,7 @@ fn __floatXisf(comptime T: type, arg: T) f32 {
66 // a is now rounded to FLT_MANT_DIG bits67 // a is now rounded to FLT_MANT_DIG bits
67 }68 }
6869
69 const s = @bitCast(Z, arg) >> (T.bit_count - 32);70 const s = @bitCast(Z, arg) >> (@typeInfo(T).Int.bits - 32);
70 const r = (@intCast(u32, s) & 0x80000000) | // sign71 const r = (@intCast(u32, s) & 0x80000000) | // sign
71 (@intCast(u32, (e + 127)) << 23) | // exponent72 (@intCast(u32, (e + 127)) << 23) | // exponent
72 (@truncate(u32, a) & 0x007fffff); // mantissa-high73 (@truncate(u32, a) & 0x007fffff); // mantissa-high
lib/std/special/compiler_rt/floatsiXf.zig+4-3
...@@ -10,8 +10,9 @@ const maxInt = std.math.maxInt;...@@ -10,8 +10,9 @@ const maxInt = std.math.maxInt;
10fn floatsiXf(comptime T: type, a: i32) T {10fn floatsiXf(comptime T: type, a: i32) T {
11 @setRuntimeSafety(builtin.is_test);11 @setRuntimeSafety(builtin.is_test);
1212
13 const Z = std.meta.Int(false, T.bit_count);13 const bits = @typeInfo(T).Float.bits;
14 const S = std.meta.Int(false, T.bit_count - @clz(Z, @as(Z, T.bit_count) - 1));14 const Z = std.meta.Int(false, bits);
15 const S = std.meta.Int(false, bits - @clz(Z, @as(Z, bits) - 1));
1516
16 if (a == 0) {17 if (a == 0) {
17 return @as(T, 0.0);18 return @as(T, 0.0);
...@@ -22,7 +23,7 @@ fn floatsiXf(comptime T: type, a: i32) T {...@@ -22,7 +23,7 @@ fn floatsiXf(comptime T: type, a: i32) T {
22 const exponentBias = ((1 << exponentBits - 1) - 1);23 const exponentBias = ((1 << exponentBits - 1) - 1);
2324
24 const implicitBit = @as(Z, 1) << significandBits;25 const implicitBit = @as(Z, 1) << significandBits;
25 const signBit = @as(Z, 1 << Z.bit_count - 1);26 const signBit = @as(Z, 1 << bits - 1);
2627
27 const sign = a >> 31;28 const sign = a >> 31;
28 // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).29 // Take absolute value of a via abs(x) = (x^(x >> 31)) - (x >> 31).
lib/std/special/compiler_rt/floatundisf.zig+1-1
...@@ -15,7 +15,7 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 {...@@ -15,7 +15,7 @@ pub fn __floatundisf(arg: u64) callconv(.C) f32 {
15 if (arg == 0) return 0;15 if (arg == 0) return 0;
1616
17 var a = arg;17 var a = arg;
18 const N: usize = @TypeOf(a).bit_count;18 const N: usize = @typeInfo(@TypeOf(a)).Int.bits;
19 // Number of significant digits19 // Number of significant digits
20 const sd = N - @clz(u64, a);20 const sd = N - @clz(u64, a);
21 // 8 exponent21 // 8 exponent
lib/std/special/compiler_rt/floatunditf.zig+1-1
...@@ -19,7 +19,7 @@ pub fn __floatunditf(a: u64) callconv(.C) f128 {...@@ -19,7 +19,7 @@ pub fn __floatunditf(a: u64) callconv(.C) f128 {
19 const exponent_bias = (1 << (exponent_bits - 1)) - 1;19 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
20 const implicit_bit = 1 << mantissa_bits;20 const implicit_bit = 1 << mantissa_bits;
2121
22 const exp: u128 = (u64.bit_count - 1) - @clz(u64, a);22 const exp: u128 = (64 - 1) - @clz(u64, a);
23 const shift: u7 = mantissa_bits - @intCast(u7, exp);23 const shift: u7 = mantissa_bits - @intCast(u7, exp);
2424
25 var result: u128 = (@intCast(u128, a) << shift) ^ implicit_bit;25 var result: u128 = (@intCast(u128, a) << shift) ^ implicit_bit;
lib/std/special/compiler_rt/floatunsitf.zig+1-1
...@@ -19,7 +19,7 @@ pub fn __floatunsitf(a: u64) callconv(.C) f128 {...@@ -19,7 +19,7 @@ pub fn __floatunsitf(a: u64) callconv(.C) f128 {
19 const exponent_bias = (1 << (exponent_bits - 1)) - 1;19 const exponent_bias = (1 << (exponent_bits - 1)) - 1;
20 const implicit_bit = 1 << mantissa_bits;20 const implicit_bit = 1 << mantissa_bits;
2121
22 const exp = (u64.bit_count - 1) - @clz(u64, a);22 const exp = (64 - 1) - @clz(u64, a);
23 const shift = mantissa_bits - @intCast(u7, exp);23 const shift = mantissa_bits - @intCast(u7, exp);
2424
25 // TODO(#1148): @bitCast alignment error25 // TODO(#1148): @bitCast alignment error
lib/std/special/compiler_rt/int.zig+1-1
...@@ -219,7 +219,7 @@ fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void {...@@ -219,7 +219,7 @@ fn test_one_divsi3(a: i32, b: i32, expected_q: i32) void {
219pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 {219pub fn __udivsi3(n: u32, d: u32) callconv(.C) u32 {
220 @setRuntimeSafety(builtin.is_test);220 @setRuntimeSafety(builtin.is_test);
221221
222 const n_uword_bits: c_uint = u32.bit_count;222 const n_uword_bits: c_uint = 32;
223 // special cases223 // special cases
224 if (d == 0) return 0; // ?!224 if (d == 0) return 0; // ?!
225 if (n == 0) return 0;225 if (n == 0) return 0;
lib/std/special/compiler_rt/modti3.zig+2-2
...@@ -14,8 +14,8 @@ const compiler_rt = @import("../compiler_rt.zig");...@@ -14,8 +14,8 @@ const compiler_rt = @import("../compiler_rt.zig");
14pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {14pub fn __modti3(a: i128, b: i128) callconv(.C) i128 {
15 @setRuntimeSafety(builtin.is_test);15 @setRuntimeSafety(builtin.is_test);
1616
17 const s_a = a >> (i128.bit_count - 1); // s = a < 0 ? -1 : 017 const s_a = a >> (128 - 1); // s = a < 0 ? -1 : 0
18 const s_b = b >> (i128.bit_count - 1); // s = b < 0 ? -1 : 018 const s_b = b >> (128 - 1); // s = b < 0 ? -1 : 0
1919
20 const an = (a ^ s_a) -% s_a; // negate if s == -120 const an = (a ^ s_a) -% s_a; // negate if s == -1
21 const bn = (b ^ s_b) -% s_b; // negate if s == -121 const bn = (b ^ s_b) -% s_b; // negate if s == -1
lib/std/special/compiler_rt/mulXf3.zig+5-5
...@@ -33,9 +33,9 @@ pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {...@@ -33,9 +33,9 @@ pub fn __aeabi_dmul(a: f64, b: f64) callconv(.C) f64 {
3333
34fn mulXf3(comptime T: type, a: T, b: T) T {34fn mulXf3(comptime T: type, a: T, b: T) T {
35 @setRuntimeSafety(builtin.is_test);35 @setRuntimeSafety(builtin.is_test);
36 const Z = std.meta.Int(false, T.bit_count);36 const typeWidth = @typeInfo(T).Float.bits;
37 const Z = std.meta.Int(false, typeWidth);
3738
38 const typeWidth = T.bit_count;
39 const significandBits = std.math.floatMantissaBits(T);39 const significandBits = std.math.floatMantissaBits(T);
40 const exponentBits = std.math.floatExponentBits(T);40 const exponentBits = std.math.floatExponentBits(T);
4141
...@@ -269,9 +269,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {...@@ -269,9 +269,9 @@ fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void {
269 }269 }
270}270}
271271
272fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i32 {272fn normalize(comptime T: type, significand: *std.meta.Int(false, @typeInfo(T).Float.bits)) i32 {
273 @setRuntimeSafety(builtin.is_test);273 @setRuntimeSafety(builtin.is_test);
274 const Z = std.meta.Int(false, T.bit_count);274 const Z = std.meta.Int(false, @typeInfo(T).Float.bits);
275 const significandBits = std.math.floatMantissaBits(T);275 const significandBits = std.math.floatMantissaBits(T);
276 const implicitBit = @as(Z, 1) << significandBits;276 const implicitBit = @as(Z, 1) << significandBits;
277277
...@@ -282,7 +282,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i...@@ -282,7 +282,7 @@ fn normalize(comptime T: type, significand: *std.meta.Int(false, T.bit_count)) i
282282
283fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {283fn wideRightShiftWithSticky(comptime Z: type, hi: *Z, lo: *Z, count: u32) void {
284 @setRuntimeSafety(builtin.is_test);284 @setRuntimeSafety(builtin.is_test);
285 const typeWidth = Z.bit_count;285 const typeWidth = @typeInfo(Z).Int.bits;
286 const S = std.math.Log2Int(Z);286 const S = std.math.Log2Int(Z);
287 if (count < typeWidth) {287 if (count < typeWidth) {
288 const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));288 const sticky = @truncate(u8, lo.* << @intCast(S, typeWidth -% count));
lib/std/special/compiler_rt/mulodi4.zig+1-1
...@@ -11,7 +11,7 @@ const minInt = std.math.minInt;...@@ -11,7 +11,7 @@ const minInt = std.math.minInt;
11pub fn __mulodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 {11pub fn __mulodi4(a: i64, b: i64, overflow: *c_int) callconv(.C) i64 {
12 @setRuntimeSafety(builtin.is_test);12 @setRuntimeSafety(builtin.is_test);
1313
14 const min = @bitCast(i64, @as(u64, 1 << (i64.bit_count - 1)));14 const min = @bitCast(i64, @as(u64, 1 << (64 - 1)));
15 const max = ~min;15 const max = ~min;
1616
17 overflow.* = 0;17 overflow.* = 0;
lib/std/special/compiler_rt/muloti4.zig+3-3
...@@ -9,7 +9,7 @@ const compiler_rt = @import("../compiler_rt.zig");...@@ -9,7 +9,7 @@ const compiler_rt = @import("../compiler_rt.zig");
9pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {9pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {
10 @setRuntimeSafety(builtin.is_test);10 @setRuntimeSafety(builtin.is_test);
1111
12 const min = @bitCast(i128, @as(u128, 1 << (i128.bit_count - 1)));12 const min = @bitCast(i128, @as(u128, 1 << (128 - 1)));
13 const max = ~min;13 const max = ~min;
14 overflow.* = 0;14 overflow.* = 0;
1515
...@@ -27,9 +27,9 @@ pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {...@@ -27,9 +27,9 @@ pub fn __muloti4(a: i128, b: i128, overflow: *c_int) callconv(.C) i128 {
27 return r;27 return r;
28 }28 }
2929
30 const sa = a >> (i128.bit_count - 1);30 const sa = a >> (128 - 1);
31 const abs_a = (a ^ sa) -% sa;31 const abs_a = (a ^ sa) -% sa;
32 const sb = b >> (i128.bit_count - 1);32 const sb = b >> (128 - 1);
33 const abs_b = (b ^ sb) -% sb;33 const abs_b = (b ^ sb) -% sb;
3434
35 if (abs_a < 2 or abs_b < 2) {35 if (abs_a < 2 or abs_b < 2) {
lib/std/special/compiler_rt/negXf2.zig+1-2
...@@ -24,9 +24,8 @@ pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 {...@@ -24,9 +24,8 @@ pub fn __aeabi_dneg(arg: f64) callconv(.AAPCS) f64 {
24}24}
2525
26fn negXf2(comptime T: type, a: T) T {26fn negXf2(comptime T: type, a: T) T {
27 const Z = std.meta.Int(false, T.bit_count);27 const Z = std.meta.Int(false, @typeInfo(T).Float.bits);
2828
29 const typeWidth = T.bit_count;
30 const significandBits = std.math.floatMantissaBits(T);29 const significandBits = std.math.floatMantissaBits(T);
31 const exponentBits = std.math.floatExponentBits(T);30 const exponentBits = std.math.floatExponentBits(T);
3231
lib/std/special/compiler_rt/shift.zig+13-12
...@@ -9,8 +9,9 @@ const Log2Int = std.math.Log2Int;...@@ -9,8 +9,9 @@ const Log2Int = std.math.Log2Int;
99
10fn Dwords(comptime T: type, comptime signed_half: bool) type {10fn Dwords(comptime T: type, comptime signed_half: bool) type {
11 return extern union {11 return extern union {
12 pub const HalfTU = std.meta.Int(false, @divExact(T.bit_count, 2));12 pub const bits = @divExact(@typeInfo(T).Int.bits, 2);
13 pub const HalfTS = std.meta.Int(true, @divExact(T.bit_count, 2));13 pub const HalfTU = std.meta.Int(false, bits);
14 pub const HalfTS = std.meta.Int(true, bits);
14 pub const HalfT = if (signed_half) HalfTS else HalfTU;15 pub const HalfT = if (signed_half) HalfTS else HalfTU;
1516
16 all: T,17 all: T,
...@@ -30,15 +31,15 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T {...@@ -30,15 +31,15 @@ pub fn ashlXi3(comptime T: type, a: T, b: i32) T {
30 const input = dwords{ .all = a };31 const input = dwords{ .all = a };
31 var output: dwords = undefined;32 var output: dwords = undefined;
3233
33 if (b >= dwords.HalfT.bit_count) {34 if (b >= dwords.bits) {
34 output.s.low = 0;35 output.s.low = 0;
35 output.s.high = input.s.low << @intCast(S, b - dwords.HalfT.bit_count);36 output.s.high = input.s.low << @intCast(S, b - dwords.bits);
36 } else if (b == 0) {37 } else if (b == 0) {
37 return a;38 return a;
38 } else {39 } else {
39 output.s.low = input.s.low << @intCast(S, b);40 output.s.low = input.s.low << @intCast(S, b);
40 output.s.high = input.s.high << @intCast(S, b);41 output.s.high = input.s.high << @intCast(S, b);
41 output.s.high |= input.s.low >> @intCast(S, dwords.HalfT.bit_count - b);42 output.s.high |= input.s.low >> @intCast(S, dwords.bits - b);
42 }43 }
4344
44 return output.all;45 return output.all;
...@@ -53,14 +54,14 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T {...@@ -53,14 +54,14 @@ pub fn ashrXi3(comptime T: type, a: T, b: i32) T {
53 const input = dwords{ .all = a };54 const input = dwords{ .all = a };
54 var output: dwords = undefined;55 var output: dwords = undefined;
5556
56 if (b >= dwords.HalfT.bit_count) {57 if (b >= dwords.bits) {
57 output.s.high = input.s.high >> (dwords.HalfT.bit_count - 1);58 output.s.high = input.s.high >> (dwords.bits - 1);
58 output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);59 output.s.low = input.s.high >> @intCast(S, b - dwords.bits);
59 } else if (b == 0) {60 } else if (b == 0) {
60 return a;61 return a;
61 } else {62 } else {
62 output.s.high = input.s.high >> @intCast(S, b);63 output.s.high = input.s.high >> @intCast(S, b);
63 output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);64 output.s.low = input.s.high << @intCast(S, dwords.bits - b);
64 // Avoid sign-extension here65 // Avoid sign-extension here
65 output.s.low |= @bitCast(66 output.s.low |= @bitCast(
66 dwords.HalfT,67 dwords.HalfT,
...@@ -80,14 +81,14 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T {...@@ -80,14 +81,14 @@ pub fn lshrXi3(comptime T: type, a: T, b: i32) T {
80 const input = dwords{ .all = a };81 const input = dwords{ .all = a };
81 var output: dwords = undefined;82 var output: dwords = undefined;
8283
83 if (b >= dwords.HalfT.bit_count) {84 if (b >= dwords.bits) {
84 output.s.high = 0;85 output.s.high = 0;
85 output.s.low = input.s.high >> @intCast(S, b - dwords.HalfT.bit_count);86 output.s.low = input.s.high >> @intCast(S, b - dwords.bits);
86 } else if (b == 0) {87 } else if (b == 0) {
87 return a;88 return a;
88 } else {89 } else {
89 output.s.high = input.s.high >> @intCast(S, b);90 output.s.high = input.s.high >> @intCast(S, b);
90 output.s.low = input.s.high << @intCast(S, dwords.HalfT.bit_count - b);91 output.s.low = input.s.high << @intCast(S, dwords.bits - b);
91 output.s.low |= input.s.low >> @intCast(S, b);92 output.s.low |= input.s.low >> @intCast(S, b);
92 }93 }
9394
lib/std/special/compiler_rt/truncXfYf2.zig+2-2
...@@ -50,7 +50,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {...@@ -50,7 +50,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
5050
51 // Various constants whose values follow from the type parameters.51 // Various constants whose values follow from the type parameters.
52 // Any reasonable optimizer will fold and propagate all of these.52 // Any reasonable optimizer will fold and propagate all of these.
53 const srcBits = src_t.bit_count;53 const srcBits = @typeInfo(src_t).Float.bits;
54 const srcExpBits = srcBits - srcSigBits - 1;54 const srcExpBits = srcBits - srcSigBits - 1;
55 const srcInfExp = (1 << srcExpBits) - 1;55 const srcInfExp = (1 << srcExpBits) - 1;
56 const srcExpBias = srcInfExp >> 1;56 const srcExpBias = srcInfExp >> 1;
...@@ -65,7 +65,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {...@@ -65,7 +65,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
65 const srcQNaN = 1 << (srcSigBits - 1);65 const srcQNaN = 1 << (srcSigBits - 1);
66 const srcNaNCode = srcQNaN - 1;66 const srcNaNCode = srcQNaN - 1;
6767
68 const dstBits = dst_t.bit_count;68 const dstBits = @typeInfo(dst_t).Float.bits;
69 const dstExpBits = dstBits - dstSigBits - 1;69 const dstExpBits = dstBits - dstSigBits - 1;
70 const dstInfExp = (1 << dstExpBits) - 1;70 const dstInfExp = (1 << dstExpBits) - 1;
71 const dstExpBias = dstInfExp >> 1;71 const dstExpBias = dstInfExp >> 1;
lib/std/special/compiler_rt/udivmod.zig+36-34
...@@ -15,8 +15,10 @@ const high = 1 - low;...@@ -15,8 +15,10 @@ const high = 1 - low;
15pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?*DoubleInt) DoubleInt {15pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem: ?*DoubleInt) DoubleInt {
16 @setRuntimeSafety(is_test);16 @setRuntimeSafety(is_test);
1717
18 const SingleInt = @import("std").meta.Int(false, @divExact(DoubleInt.bit_count, 2));18 const double_int_bits = @typeInfo(DoubleInt).Int.bits;
19 const SignedDoubleInt = @import("std").meta.Int(true, DoubleInt.bit_count);19 const single_int_bits = @divExact(double_int_bits, 2);
20 const SingleInt = @import("std").meta.Int(false, single_int_bits);
21 const SignedDoubleInt = @import("std").meta.Int(true, double_int_bits);
20 const Log2SingleInt = @import("std").math.Log2Int(SingleInt);22 const Log2SingleInt = @import("std").math.Log2Int(SingleInt);
2123
22 const n = @ptrCast(*const [2]SingleInt, &a).*; // TODO issue #42124 const n = @ptrCast(*const [2]SingleInt, &a).*; // TODO issue #421
...@@ -82,21 +84,21 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -82,21 +84,21 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
82 // ---84 // ---
83 // K 085 // K 0
84 sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high])));86 sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high])));
85 // 0 <= sr <= SingleInt.bit_count - 2 or sr large87 // 0 <= sr <= single_int_bits - 2 or sr large
86 if (sr > SingleInt.bit_count - 2) {88 if (sr > single_int_bits - 2) {
87 if (maybe_rem) |rem| {89 if (maybe_rem) |rem| {
88 rem.* = a;90 rem.* = a;
89 }91 }
90 return 0;92 return 0;
91 }93 }
92 sr += 1;94 sr += 1;
93 // 1 <= sr <= SingleInt.bit_count - 195 // 1 <= sr <= single_int_bits - 1
94 // q.all = a << (DoubleInt.bit_count - sr);96 // q.all = a << (double_int_bits - sr);
95 q[low] = 0;97 q[low] = 0;
96 q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);98 q[high] = n[low] << @intCast(Log2SingleInt, single_int_bits - sr);
97 // r.all = a >> sr;99 // r.all = a >> sr;
98 r[high] = n[high] >> @intCast(Log2SingleInt, sr);100 r[high] = n[high] >> @intCast(Log2SingleInt, sr);
99 r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));101 r[low] = (n[high] << @intCast(Log2SingleInt, single_int_bits - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
100 } else {102 } else {
101 // d[low] != 0103 // d[low] != 0
102 if (d[high] == 0) {104 if (d[high] == 0) {
...@@ -113,74 +115,74 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -113,74 +115,74 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
113 }115 }
114 sr = @ctz(SingleInt, d[low]);116 sr = @ctz(SingleInt, d[low]);
115 q[high] = n[high] >> @intCast(Log2SingleInt, sr);117 q[high] = n[high] >> @intCast(Log2SingleInt, sr);
116 q[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));118 q[low] = (n[high] << @intCast(Log2SingleInt, single_int_bits - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
117 return @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421119 return @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &q[0]).*; // TODO issue #421
118 }120 }
119 // K X121 // K X
120 // ---122 // ---
121 // 0 K123 // 0 K
122 sr = 1 + SingleInt.bit_count + @as(c_uint, @clz(SingleInt, d[low])) - @as(c_uint, @clz(SingleInt, n[high]));124 sr = 1 + single_int_bits + @as(c_uint, @clz(SingleInt, d[low])) - @as(c_uint, @clz(SingleInt, n[high]));
123 // 2 <= sr <= DoubleInt.bit_count - 1125 // 2 <= sr <= double_int_bits - 1
124 // q.all = a << (DoubleInt.bit_count - sr);126 // q.all = a << (double_int_bits - sr);
125 // r.all = a >> sr;127 // r.all = a >> sr;
126 if (sr == SingleInt.bit_count) {128 if (sr == single_int_bits) {
127 q[low] = 0;129 q[low] = 0;
128 q[high] = n[low];130 q[high] = n[low];
129 r[high] = 0;131 r[high] = 0;
130 r[low] = n[high];132 r[low] = n[high];
131 } else if (sr < SingleInt.bit_count) {133 } else if (sr < single_int_bits) {
132 // 2 <= sr <= SingleInt.bit_count - 1134 // 2 <= sr <= single_int_bits - 1
133 q[low] = 0;135 q[low] = 0;
134 q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);136 q[high] = n[low] << @intCast(Log2SingleInt, single_int_bits - sr);
135 r[high] = n[high] >> @intCast(Log2SingleInt, sr);137 r[high] = n[high] >> @intCast(Log2SingleInt, sr);
136 r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));138 r[low] = (n[high] << @intCast(Log2SingleInt, single_int_bits - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
137 } else {139 } else {
138 // SingleInt.bit_count + 1 <= sr <= DoubleInt.bit_count - 1140 // single_int_bits + 1 <= sr <= double_int_bits - 1
139 q[low] = n[low] << @intCast(Log2SingleInt, DoubleInt.bit_count - sr);141 q[low] = n[low] << @intCast(Log2SingleInt, double_int_bits - sr);
140 q[high] = (n[high] << @intCast(Log2SingleInt, DoubleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr - SingleInt.bit_count));142 q[high] = (n[high] << @intCast(Log2SingleInt, double_int_bits - sr)) | (n[low] >> @intCast(Log2SingleInt, sr - single_int_bits));
141 r[high] = 0;143 r[high] = 0;
142 r[low] = n[high] >> @intCast(Log2SingleInt, sr - SingleInt.bit_count);144 r[low] = n[high] >> @intCast(Log2SingleInt, sr - single_int_bits);
143 }145 }
144 } else {146 } else {
145 // K X147 // K X
146 // ---148 // ---
147 // K K149 // K K
148 sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high])));150 sr = @bitCast(c_uint, @as(c_int, @clz(SingleInt, d[high])) - @as(c_int, @clz(SingleInt, n[high])));
149 // 0 <= sr <= SingleInt.bit_count - 1 or sr large151 // 0 <= sr <= single_int_bits - 1 or sr large
150 if (sr > SingleInt.bit_count - 1) {152 if (sr > single_int_bits - 1) {
151 if (maybe_rem) |rem| {153 if (maybe_rem) |rem| {
152 rem.* = a;154 rem.* = a;
153 }155 }
154 return 0;156 return 0;
155 }157 }
156 sr += 1;158 sr += 1;
157 // 1 <= sr <= SingleInt.bit_count159 // 1 <= sr <= single_int_bits
158 // q.all = a << (DoubleInt.bit_count - sr);160 // q.all = a << (double_int_bits - sr);
159 // r.all = a >> sr;161 // r.all = a >> sr;
160 q[low] = 0;162 q[low] = 0;
161 if (sr == SingleInt.bit_count) {163 if (sr == single_int_bits) {
162 q[high] = n[low];164 q[high] = n[low];
163 r[high] = 0;165 r[high] = 0;
164 r[low] = n[high];166 r[low] = n[high];
165 } else {167 } else {
166 r[high] = n[high] >> @intCast(Log2SingleInt, sr);168 r[high] = n[high] >> @intCast(Log2SingleInt, sr);
167 r[low] = (n[high] << @intCast(Log2SingleInt, SingleInt.bit_count - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));169 r[low] = (n[high] << @intCast(Log2SingleInt, single_int_bits - sr)) | (n[low] >> @intCast(Log2SingleInt, sr));
168 q[high] = n[low] << @intCast(Log2SingleInt, SingleInt.bit_count - sr);170 q[high] = n[low] << @intCast(Log2SingleInt, single_int_bits - sr);
169 }171 }
170 }172 }
171 }173 }
172 // Not a special case174 // Not a special case
173 // q and r are initialized with:175 // q and r are initialized with:
174 // q.all = a << (DoubleInt.bit_count - sr);176 // q.all = a << (double_int_bits - sr);
175 // r.all = a >> sr;177 // r.all = a >> sr;
176 // 1 <= sr <= DoubleInt.bit_count - 1178 // 1 <= sr <= double_int_bits - 1
177 var carry: u32 = 0;179 var carry: u32 = 0;
178 var r_all: DoubleInt = undefined;180 var r_all: DoubleInt = undefined;
179 while (sr > 0) : (sr -= 1) {181 while (sr > 0) : (sr -= 1) {
180 // r:q = ((r:q) << 1) | carry182 // r:q = ((r:q) << 1) | carry
181 r[high] = (r[high] << 1) | (r[low] >> (SingleInt.bit_count - 1));183 r[high] = (r[high] << 1) | (r[low] >> (single_int_bits - 1));
182 r[low] = (r[low] << 1) | (q[high] >> (SingleInt.bit_count - 1));184 r[low] = (r[low] << 1) | (q[high] >> (single_int_bits - 1));
183 q[high] = (q[high] << 1) | (q[low] >> (SingleInt.bit_count - 1));185 q[high] = (q[high] << 1) | (q[low] >> (single_int_bits - 1));
184 q[low] = (q[low] << 1) | carry;186 q[low] = (q[low] << 1) | carry;
185 // carry = 0;187 // carry = 0;
186 // if (r.all >= b)188 // if (r.all >= b)
...@@ -189,7 +191,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:...@@ -189,7 +191,7 @@ pub fn udivmod(comptime DoubleInt: type, a: DoubleInt, b: DoubleInt, maybe_rem:
189 // carry = 1;191 // carry = 1;
190 // }192 // }
191 r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421193 r_all = @ptrCast(*align(@alignOf(SingleInt)) DoubleInt, &r[0]).*; // TODO issue #421
192 const s: SignedDoubleInt = @bitCast(SignedDoubleInt, b -% r_all -% 1) >> (DoubleInt.bit_count - 1);194 const s: SignedDoubleInt = @bitCast(SignedDoubleInt, b -% r_all -% 1) >> (double_int_bits - 1);
193 carry = @intCast(u32, s & 1);195 carry = @intCast(u32, s & 1);
194 r_all -= b & @bitCast(DoubleInt, s);196 r_all -= b & @bitCast(DoubleInt, s);
195 r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421197 r = @ptrCast(*[2]SingleInt, &r_all).*; // TODO issue #421
lib/std/start.zig+2-2
...@@ -67,7 +67,7 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv...@@ -67,7 +67,7 @@ fn EfiMain(handle: uefi.Handle, system_table: *uefi.tables.SystemTable) callconv
67 uefi.handle = handle;67 uefi.handle = handle;
68 uefi.system_table = system_table;68 uefi.system_table = system_table;
6969
70 switch (@TypeOf(root.main).ReturnType) {70 switch (@typeInfo(@TypeOf(root.main)).Fn.return_type.?) {
71 noreturn => {71 noreturn => {
72 root.main();72 root.main();
73 },73 },
...@@ -239,7 +239,7 @@ fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 {...@@ -239,7 +239,7 @@ fn callMainAsync(loop: *std.event.Loop) callconv(.Async) u8 {
239// This is not marked inline because it is called with @asyncCall when239// This is not marked inline because it is called with @asyncCall when
240// there is an event loop.240// there is an event loop.
241pub fn callMain() u8 {241pub fn callMain() u8 {
242 switch (@typeInfo(@TypeOf(root.main).ReturnType)) {242 switch (@typeInfo(@typeInfo(@TypeOf(root.main)).Fn.return_type.?)) {
243 .NoReturn => {243 .NoReturn => {
244 root.main();244 root.main();
245 },245 },
lib/std/target.zig+58
...@@ -468,6 +468,7 @@ pub const Target = struct {...@@ -468,6 +468,7 @@ pub const Target = struct {
468 /// TODO Get rid of this one.468 /// TODO Get rid of this one.
469 unknown,469 unknown,
470 coff,470 coff,
471 pe,
471 elf,472 elf,
472 macho,473 macho,
473 wasm,474 wasm,
...@@ -771,6 +772,63 @@ pub const Target = struct {...@@ -771,6 +772,63 @@ pub const Target = struct {
771 };772 };
772 }773 }
773774
775 pub fn toCoffMachine(arch: Arch) std.coff.MachineType {
776 return switch (arch) {
777 .avr => .Unknown,
778 .msp430 => .Unknown,
779 .arc => .Unknown,
780 .arm => .ARM,
781 .armeb => .Unknown,
782 .hexagon => .Unknown,
783 .le32 => .Unknown,
784 .mips => .Unknown,
785 .mipsel => .Unknown,
786 .powerpc => .POWERPC,
787 .r600 => .Unknown,
788 .riscv32 => .RISCV32,
789 .sparc => .Unknown,
790 .sparcel => .Unknown,
791 .tce => .Unknown,
792 .tcele => .Unknown,
793 .thumb => .Thumb,
794 .thumbeb => .Thumb,
795 .i386 => .I386,
796 .xcore => .Unknown,
797 .nvptx => .Unknown,
798 .amdil => .Unknown,
799 .hsail => .Unknown,
800 .spir => .Unknown,
801 .kalimba => .Unknown,
802 .shave => .Unknown,
803 .lanai => .Unknown,
804 .wasm32 => .Unknown,
805 .renderscript32 => .Unknown,
806 .aarch64_32 => .ARM64,
807 .aarch64 => .ARM64,
808 .aarch64_be => .Unknown,
809 .mips64 => .Unknown,
810 .mips64el => .Unknown,
811 .powerpc64 => .Unknown,
812 .powerpc64le => .Unknown,
813 .riscv64 => .RISCV64,
814 .x86_64 => .X64,
815 .nvptx64 => .Unknown,
816 .le64 => .Unknown,
817 .amdil64 => .Unknown,
818 .hsail64 => .Unknown,
819 .spir64 => .Unknown,
820 .wasm64 => .Unknown,
821 .renderscript64 => .Unknown,
822 .amdgcn => .Unknown,
823 .bpfel => .Unknown,
824 .bpfeb => .Unknown,
825 .sparcv9 => .Unknown,
826 .s390x => .Unknown,
827 .ve => .Unknown,
828 .spu_2 => .Unknown,
829 };
830 }
831
774 pub fn endian(arch: Arch) builtin.Endian {832 pub fn endian(arch: Arch) builtin.Endian {
775 return switch (arch) {833 return switch (arch) {
776 .avr,834 .avr,
lib/std/thread.zig+3-3
...@@ -166,7 +166,7 @@ pub const Thread = struct {...@@ -166,7 +166,7 @@ pub const Thread = struct {
166 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {166 fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
167 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;167 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
168168
169 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {169 switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
170 .NoReturn => {170 .NoReturn => {
171 startFn(arg);171 startFn(arg);
172 },172 },
...@@ -227,7 +227,7 @@ pub const Thread = struct {...@@ -227,7 +227,7 @@ pub const Thread = struct {
227 fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 {227 fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 {
228 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;228 const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
229229
230 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {230 switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
231 .NoReturn => {231 .NoReturn => {
232 startFn(arg);232 startFn(arg);
233 },233 },
...@@ -259,7 +259,7 @@ pub const Thread = struct {...@@ -259,7 +259,7 @@ pub const Thread = struct {
259 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {259 fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {
260 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), ctx)).*;260 const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), ctx)).*;
261261
262 switch (@typeInfo(@TypeOf(startFn).ReturnType)) {262 switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
263 .NoReturn => {263 .NoReturn => {
264 startFn(arg);264 startFn(arg);
265 },265 },
lib/std/zig.zig+1-1
...@@ -22,7 +22,7 @@ pub const SrcHash = [16]u8;...@@ -22,7 +22,7 @@ pub const SrcHash = [16]u8;
22/// If it is long, blake3 hash is computed.22/// If it is long, blake3 hash is computed.
23pub fn hashSrc(src: []const u8) SrcHash {23pub fn hashSrc(src: []const u8) SrcHash {
24 var out: SrcHash = undefined;24 var out: SrcHash = undefined;
25 if (src.len <= SrcHash.len) {25 if (src.len <= @typeInfo(SrcHash).Array.len) {
26 std.mem.copy(u8, &out, src);26 std.mem.copy(u8, &out, src);
27 std.mem.set(u8, out[src.len..], 0);27 std.mem.set(u8, out[src.len..], 0);
28 } else {28 } else {
src-self-hosted/Module.zig+7
...@@ -626,6 +626,7 @@ pub const Scope = struct {...@@ -626,6 +626,7 @@ pub const Scope = struct {
626 module.gpa,626 module.gpa,
627 self.sub_file_path,627 self.sub_file_path,
628 std.math.maxInt(u32),628 std.math.maxInt(u32),
629 null,
629 1,630 1,
630 0,631 0,
631 );632 );
...@@ -723,6 +724,7 @@ pub const Scope = struct {...@@ -723,6 +724,7 @@ pub const Scope = struct {
723 module.gpa,724 module.gpa,
724 self.sub_file_path,725 self.sub_file_path,
725 std.math.maxInt(u32),726 std.math.maxInt(u32),
727 null,
726 1,728 1,
727 0,729 0,
728 );730 );
...@@ -1820,6 +1822,9 @@ fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void {...@@ -1820,6 +1822,9 @@ fn analyzeContainer(self: *Module, container_scope: *Scope.Container) !void {
1820 try self.markOutdatedDecl(decl);1822 try self.markOutdatedDecl(decl);
1821 decl.contents_hash = contents_hash;1823 decl.contents_hash = contents_hash;
1822 } else switch (self.bin_file.tag) {1824 } else switch (self.bin_file.tag) {
1825 .coff => {
1826 // TODO Implement for COFF
1827 },
1823 .elf => if (decl.fn_link.elf.len != 0) {1828 .elf => if (decl.fn_link.elf.len != 0) {
1824 // TODO Look into detecting when this would be unnecessary by storing enough state1829 // TODO Look into detecting when this would be unnecessary by storing enough state
1825 // in `Decl` to notice that the line number did not change.1830 // in `Decl` to notice that the line number did not change.
...@@ -2078,12 +2083,14 @@ fn allocateNewDecl(...@@ -2078,12 +2083,14 @@ fn allocateNewDecl(
2078 .deletion_flag = false,2083 .deletion_flag = false,
2079 .contents_hash = contents_hash,2084 .contents_hash = contents_hash,
2080 .link = switch (self.bin_file.tag) {2085 .link = switch (self.bin_file.tag) {
2086 .coff => .{ .coff = link.File.Coff.TextBlock.empty },
2081 .elf => .{ .elf = link.File.Elf.TextBlock.empty },2087 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
2082 .macho => .{ .macho = link.File.MachO.TextBlock.empty },2088 .macho => .{ .macho = link.File.MachO.TextBlock.empty },
2083 .c => .{ .c = {} },2089 .c => .{ .c = {} },
2084 .wasm => .{ .wasm = {} },2090 .wasm => .{ .wasm = {} },
2085 },2091 },
2086 .fn_link = switch (self.bin_file.tag) {2092 .fn_link = switch (self.bin_file.tag) {
2093 .coff => .{ .coff = {} },
2087 .elf => .{ .elf = link.File.Elf.SrcFn.empty },2094 .elf => .{ .elf = link.File.Elf.SrcFn.empty },
2088 .macho => .{ .macho = link.File.MachO.SrcFn.empty },2095 .macho => .{ .macho = link.File.MachO.SrcFn.empty },
2089 .c => .{ .c = {} },2096 .c => .{ .c = {} },
src-self-hosted/codegen.zig+166-112
...@@ -59,14 +59,21 @@ pub const GenerateSymbolError = error{...@@ -59,14 +59,21 @@ pub const GenerateSymbolError = error{
59 AnalysisFail,59 AnalysisFail,
60};60};
6161
62pub const DebugInfoOutput = union(enum) {
63 dwarf: struct {
64 dbg_line: *std.ArrayList(u8),
65 dbg_info: *std.ArrayList(u8),
66 dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
67 },
68 none,
69};
70
62pub fn generateSymbol(71pub fn generateSymbol(
63 bin_file: *link.File,72 bin_file: *link.File,
64 src: usize,73 src: usize,
65 typed_value: TypedValue,74 typed_value: TypedValue,
66 code: *std.ArrayList(u8),75 code: *std.ArrayList(u8),
67 dbg_line: *std.ArrayList(u8),76 debug_output: DebugInfoOutput,
68 dbg_info: *std.ArrayList(u8),
69 dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
70) GenerateSymbolError!Result {77) GenerateSymbolError!Result {
71 const tracy = trace(@src());78 const tracy = trace(@src());
72 defer tracy.end();79 defer tracy.end();
...@@ -76,56 +83,56 @@ pub fn generateSymbol(...@@ -76,56 +83,56 @@ pub fn generateSymbol(
76 switch (bin_file.options.target.cpu.arch) {83 switch (bin_file.options.target.cpu.arch) {
77 .wasm32 => unreachable, // has its own code path84 .wasm32 => unreachable, // has its own code path
78 .wasm64 => unreachable, // has its own code path85 .wasm64 => unreachable, // has its own code path
79 .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),86 .arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, debug_output),
80 .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),87 .armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
81 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),88 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, debug_output),
82 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),89 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, debug_output),
83 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),90 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, debug_output),
84 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),91 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, debug_output),
85 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),92 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, debug_output),
86 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),93 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, debug_output),
87 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),94 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
88 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),95 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, debug_output),
89 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),96 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, debug_output),
90 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),97 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, debug_output),
91 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),98 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, debug_output),
92 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),99 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, debug_output),
93 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),100 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, debug_output),
94 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),101 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, debug_output),
95 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),102 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, debug_output),
96 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),103 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, debug_output),
97 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),104 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, debug_output),
98 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),105 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, debug_output),
99 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),106 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, debug_output),
100 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),107 .riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, debug_output),
101 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),108 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, debug_output),
102 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),109 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, debug_output),
103 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),110 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, debug_output),
104 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),111 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, debug_output),
105 .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),112 .spu_2 => return Function(.spu_2).generateSymbol(bin_file, src, typed_value, code, debug_output),
106 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),113 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, debug_output),
107 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),114 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, debug_output),
108 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),115 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, debug_output),
109 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),116 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, debug_output),
110 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),117 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, debug_output),
111 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),118 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, debug_output),
112 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),119 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, debug_output),
113 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),120 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, debug_output),
114 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),121 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, debug_output),
115 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),122 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, debug_output),
116 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),123 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, debug_output),
117 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),124 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, debug_output),
118 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),125 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, debug_output),
119 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),126 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, debug_output),
120 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),127 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, debug_output),
121 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),128 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, debug_output),
122 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),129 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, debug_output),
123 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),130 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, debug_output),
124 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),131 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, debug_output),
125 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),132 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, debug_output),
126 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),133 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, debug_output),
127 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),134 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, debug_output),
128 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line, dbg_info, dbg_info_type_relocs),135 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, debug_output),
129 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),136 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
130 }137 }
131 },138 },
...@@ -139,7 +146,7 @@ pub fn generateSymbol(...@@ -139,7 +146,7 @@ pub fn generateSymbol(
139 switch (try generateSymbol(bin_file, src, .{146 switch (try generateSymbol(bin_file, src, .{
140 .ty = typed_value.ty.elemType(),147 .ty = typed_value.ty.elemType(),
141 .val = sentinel,148 .val = sentinel,
142 }, code, dbg_line, dbg_info, dbg_info_type_relocs)) {149 }, code, debug_output)) {
143 .appended => return Result{ .appended = {} },150 .appended => return Result{ .appended = {} },
144 .externally_managed => |slice| {151 .externally_managed => |slice| {
145 code.appendSliceAssumeCapacity(slice);152 code.appendSliceAssumeCapacity(slice);
...@@ -239,9 +246,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -239,9 +246,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
239 target: *const std.Target,246 target: *const std.Target,
240 mod_fn: *const Module.Fn,247 mod_fn: *const Module.Fn,
241 code: *std.ArrayList(u8),248 code: *std.ArrayList(u8),
242 dbg_line: *std.ArrayList(u8),249 debug_output: DebugInfoOutput,
243 dbg_info: *std.ArrayList(u8),
244 dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
245 err_msg: ?*ErrorMsg,250 err_msg: ?*ErrorMsg,
246 args: []MCValue,251 args: []MCValue,
247 ret_mcv: MCValue,252 ret_mcv: MCValue,
...@@ -419,9 +424,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -419,9 +424,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
419 src: usize,424 src: usize,
420 typed_value: TypedValue,425 typed_value: TypedValue,
421 code: *std.ArrayList(u8),426 code: *std.ArrayList(u8),
422 dbg_line: *std.ArrayList(u8),427 debug_output: DebugInfoOutput,
423 dbg_info: *std.ArrayList(u8),
424 dbg_info_type_relocs: *link.File.DbgInfoTypeRelocsTable,
425 ) GenerateSymbolError!Result {428 ) GenerateSymbolError!Result {
426 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;429 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
427430
...@@ -457,9 +460,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -457,9 +460,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
457 .bin_file = bin_file,460 .bin_file = bin_file,
458 .mod_fn = module_fn,461 .mod_fn = module_fn,
459 .code = code,462 .code = code,
460 .dbg_line = dbg_line,463 .debug_output = debug_output,
461 .dbg_info = dbg_info,
462 .dbg_info_type_relocs = dbg_info_type_relocs,
463 .err_msg = null,464 .err_msg = null,
464 .args = undefined, // populated after `resolveCallingConventionValues`465 .args = undefined, // populated after `resolveCallingConventionValues`
465 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`466 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -598,35 +599,50 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -598,35 +599,50 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
598 }599 }
599600
600 fn dbgSetPrologueEnd(self: *Self) InnerError!void {601 fn dbgSetPrologueEnd(self: *Self) InnerError!void {
601 try self.dbg_line.append(DW.LNS_set_prologue_end);602 switch (self.debug_output) {
602 try self.dbgAdvancePCAndLine(self.prev_di_src);603 .dwarf => |dbg_out| {
604 try dbg_out.dbg_line.append(DW.LNS_set_prologue_end);
605 try self.dbgAdvancePCAndLine(self.prev_di_src);
606 },
607 .none => {},
608 }
603 }609 }
604610
605 fn dbgSetEpilogueBegin(self: *Self) InnerError!void {611 fn dbgSetEpilogueBegin(self: *Self) InnerError!void {
606 try self.dbg_line.append(DW.LNS_set_epilogue_begin);612 switch (self.debug_output) {
607 try self.dbgAdvancePCAndLine(self.prev_di_src);613 .dwarf => |dbg_out| {
614 try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin);
615 try self.dbgAdvancePCAndLine(self.prev_di_src);
616 },
617 .none => {},
618 }
608 }619 }
609620
610 fn dbgAdvancePCAndLine(self: *Self, src: usize) InnerError!void {621 fn dbgAdvancePCAndLine(self: *Self, src: usize) InnerError!void {
611 // TODO Look into improving the performance here by adding a token-index-to-line
612 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
613 // this involves scanning over the source code for newlines
614 // (but only from the previous byte offset to the new one).
615 const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, src);
616 const delta_pc = self.code.items.len - self.prev_di_pc;
617 self.prev_di_src = src;622 self.prev_di_src = src;
618 self.prev_di_pc = self.code.items.len;623 self.prev_di_pc = self.code.items.len;
619 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit624 switch (self.debug_output) {
620 // single-byte opcodes that add different numbers to both the PC and the line number625 .dwarf => |dbg_out| {
621 // at the same time.626 // TODO Look into improving the performance here by adding a token-index-to-line
622 try self.dbg_line.ensureCapacity(self.dbg_line.items.len + 11);627 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
623 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);628 // this involves scanning over the source code for newlines
624 leb128.writeULEB128(self.dbg_line.writer(), delta_pc) catch unreachable;629 // (but only from the previous byte offset to the new one).
625 if (delta_line != 0) {630 const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, src);
626 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_line);631 const delta_pc = self.code.items.len - self.prev_di_pc;
627 leb128.writeILEB128(self.dbg_line.writer(), delta_line) catch unreachable;632 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit
633 // single-byte opcodes that add different numbers to both the PC and the line number
634 // at the same time.
635 try dbg_out.dbg_line.ensureCapacity(dbg_out.dbg_line.items.len + 11);
636 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);
637 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
638 if (delta_line != 0) {
639 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_line);
640 leb128.writeILEB128(dbg_out.dbg_line.writer(), delta_line) catch unreachable;
641 }
642 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_copy);
643 },
644 .none => {},
628 }645 }
629 self.dbg_line.appendAssumeCapacity(DW.LNS_copy);
630 }646 }
631647
632 /// Asserts there is already capacity to insert into top branch inst_table.648 /// Asserts there is already capacity to insert into top branch inst_table.
...@@ -654,18 +670,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -654,18 +670,23 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
654 /// Adds a Type to the .debug_info at the current position. The bytes will be populated later,670 /// Adds a Type to the .debug_info at the current position. The bytes will be populated later,
655 /// after codegen for this symbol is done.671 /// after codegen for this symbol is done.
656 fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {672 fn addDbgInfoTypeReloc(self: *Self, ty: Type) !void {
657 assert(ty.hasCodeGenBits());673 switch (self.debug_output) {
658 const index = self.dbg_info.items.len;674 .dwarf => |dbg_out| {
659 try self.dbg_info.resize(index + 4); // DW.AT_type, DW.FORM_ref4675 assert(ty.hasCodeGenBits());
660676 const index = dbg_out.dbg_info.items.len;
661 const gop = try self.dbg_info_type_relocs.getOrPut(self.gpa, ty);677 try dbg_out.dbg_info.resize(index + 4); // DW.AT_type, DW.FORM_ref4
662 if (!gop.found_existing) {678
663 gop.entry.value = .{679 const gop = try dbg_out.dbg_info_type_relocs.getOrPut(self.gpa, ty);
664 .off = undefined,680 if (!gop.found_existing) {
665 .relocs = .{},681 gop.entry.value = .{
666 };682 .off = undefined,
683 .relocs = .{},
684 };
685 }
686 try gop.entry.value.relocs.append(self.gpa, @intCast(u32, index));
687 },
688 .none => {},
667 }689 }
668 try gop.entry.value.relocs.append(self.gpa, @intCast(u32, index));
669 }690 }
670691
671 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {692 fn genFuncInst(self: *Self, inst: *ir.Inst) !MCValue {
...@@ -1258,14 +1279,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1258,14 +1279,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1258 self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base);1279 self.registers.putAssumeCapacityNoClobber(toCanonicalReg(reg), &inst.base);
1259 self.markRegUsed(reg);1280 self.markRegUsed(reg);
12601281
1261 try self.dbg_info.ensureCapacity(self.dbg_info.items.len + 8 + name_with_null.len);1282 switch (self.debug_output) {
1262 self.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);1283 .dwarf => |dbg_out| {
1263 self.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc1284 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 8 + name_with_null.len);
1264 1, // ULEB128 dwarf expression length1285 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1265 reg.dwarfLocOp(),1286 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1266 });1287 1, // ULEB128 dwarf expression length
1267 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref41288 reg.dwarfLocOp(),
1268 self.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string1289 });
1290 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1291 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
1292 },
1293 .none => {},
1294 }
1269 },1295 },
1270 else => {},1296 else => {},
1271 }1297 }
...@@ -1302,7 +1328,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1302,7 +1328,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
13021328
1303 // Due to incremental compilation, how function calls are generated depends1329 // Due to incremental compilation, how function calls are generated depends
1304 // on linking.1330 // on linking.
1305 if (self.bin_file.cast(link.File.Elf)) |elf_file| {1331 if (self.bin_file.tag == link.File.Elf.base_tag or self.bin_file.tag == link.File.Coff.base_tag) {
1306 switch (arch) {1332 switch (arch) {
1307 .x86_64 => {1333 .x86_64 => {
1308 for (info.args) |mc_arg, arg_i| {1334 for (info.args) |mc_arg, arg_i| {
...@@ -1341,10 +1367,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1341,10 +1367,17 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1341 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1367 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1342 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1368 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1343 const func = func_val.func;1369 const func = func_val.func;
1344 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];1370
1345 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1371 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1346 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1372 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1347 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);1373 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1374 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1375 break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
1376 } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
1377 @intCast(u32, coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes)
1378 else
1379 unreachable;
1380
1348 // ff 14 25 xx xx xx xx call [addr]1381 // ff 14 25 xx xx xx xx call [addr]
1349 try self.code.ensureCapacity(self.code.items.len + 7);1382 try self.code.ensureCapacity(self.code.items.len + 7);
1350 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });1383 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
...@@ -1362,10 +1395,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1362,10 +1395,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1362 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1395 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1363 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1396 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1364 const func = func_val.func;1397 const func = func_val.func;
1365 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];1398
1366 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1399 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1367 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1400 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1368 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);1401 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1402 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1403 break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
1404 } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
1405 coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes
1406 else
1407 unreachable;
13691408
1370 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });1409 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
1371 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32());1410 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32());
...@@ -1383,8 +1422,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1383,8 +1422,14 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1383 }1422 }
1384 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1423 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1385 const func = func_val.func;1424 const func = func_val.func;
1386 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];1425 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1387 const got_addr = @intCast(u16, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * 2);1426 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1427 break :blk @intCast(u16, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * 2);
1428 } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
1429 @intCast(u16, coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * 2)
1430 else
1431 unreachable;
1432
1388 const return_type = func.owner_decl.typed_value.most_recent.typed_value.ty.fnReturnType();1433 const return_type = func.owner_decl.typed_value.most_recent.typed_value.ty.fnReturnType();
1389 // First, push the return address, then jump; if noreturn, don't bother with the first step1434 // First, push the return address, then jump; if noreturn, don't bother with the first step
1390 // TODO: implement packed struct -> u16 at comptime and move the bitcast here1435 // TODO: implement packed struct -> u16 at comptime and move the bitcast here
...@@ -1420,10 +1465,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1420,10 +1465,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1420 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {1465 if (inst.func.cast(ir.Inst.Constant)) |func_inst| {
1421 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {1466 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
1422 const func = func_val.func;1467 const func = func_val.func;
1423 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1424 const ptr_bits = self.target.cpu.arch.ptrBitWidth();1468 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
1425 const ptr_bytes: u64 = @divExact(ptr_bits, 8);1469 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
1426 const got_addr = @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);1470 const got_addr = if (self.bin_file.cast(link.File.Elf)) |elf_file| blk: {
1471 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
1472 break :blk @intCast(u32, got.p_vaddr + func.owner_decl.link.elf.offset_table_index * ptr_bytes);
1473 } else if (self.bin_file.cast(link.File.Coff)) |coff_file|
1474 coff_file.offset_table_virtual_address + func.owner_decl.link.coff.offset_table_index * ptr_bytes
1475 else
1476 unreachable;
14271477
1428 // TODO only works with leaf functions1478 // TODO only works with leaf functions
1429 // at the moment, which works fine for1479 // at the moment, which works fine for
...@@ -1983,7 +2033,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1983,7 +2033,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
19832033
1984 if (mem.eql(u8, inst.asm_source, "syscall")) {2034 if (mem.eql(u8, inst.asm_source, "syscall")) {
1985 try self.code.appendSlice(&[_]u8{ 0x0f, 0x05 });2035 try self.code.appendSlice(&[_]u8{ 0x0f, 0x05 });
1986 } else {2036 } else if (inst.asm_source.len != 0) {
1987 return self.fail(inst.base.src, "TODO implement support for more x86 assembly instructions", .{});2037 return self.fail(inst.base.src, "TODO implement support for more x86 assembly instructions", .{});
1988 }2038 }
19892039
...@@ -2541,6 +2591,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2541,6 +2591,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2541 const got = &macho_file.sections.items[macho_file.got_section_index.?];2591 const got = &macho_file.sections.items[macho_file.got_section_index.?];
2542 const got_addr = got.addr + decl.link.macho.offset_table_index.? * ptr_bytes;2592 const got_addr = got.addr + decl.link.macho.offset_table_index.? * ptr_bytes;
2543 return MCValue{ .memory = got_addr };2593 return MCValue{ .memory = got_addr };
2594 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
2595 const decl = payload.decl;
2596 const got_addr = coff_file.offset_table_virtual_address + decl.link.coff.offset_table_index * ptr_bytes;
2597 return MCValue{ .memory = got_addr };
2544 } else {2598 } else {
2545 return self.fail(src, "TODO codegen non-ELF const Decl pointer", .{});2599 return self.fail(src, "TODO codegen non-ELF const Decl pointer", .{});
2546 }2600 }
src-self-hosted/link.zig+20-2
...@@ -34,6 +34,7 @@ pub const File = struct {...@@ -34,6 +34,7 @@ pub const File = struct {
3434
35 pub const LinkBlock = union {35 pub const LinkBlock = union {
36 elf: Elf.TextBlock,36 elf: Elf.TextBlock,
37 coff: Coff.TextBlock,
37 macho: MachO.TextBlock,38 macho: MachO.TextBlock,
38 c: void,39 c: void,
39 wasm: void,40 wasm: void,
...@@ -41,6 +42,7 @@ pub const File = struct {...@@ -41,6 +42,7 @@ pub const File = struct {
4142
42 pub const LinkFn = union {43 pub const LinkFn = union {
43 elf: Elf.SrcFn,44 elf: Elf.SrcFn,
45 coff: Coff.SrcFn,
44 macho: MachO.SrcFn,46 macho: MachO.SrcFn,
45 c: void,47 c: void,
46 wasm: ?Wasm.FnData,48 wasm: ?Wasm.FnData,
...@@ -66,7 +68,7 @@ pub const File = struct {...@@ -66,7 +68,7 @@ pub const File = struct {
66 pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File {68 pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: Options) !*File {
67 switch (options.object_format) {69 switch (options.object_format) {
68 .unknown => unreachable,70 .unknown => unreachable,
69 .coff => return error.TODOImplementCoff,71 .coff, .pe => return Coff.openPath(allocator, dir, sub_path, options),
70 .elf => return Elf.openPath(allocator, dir, sub_path, options),72 .elf => return Elf.openPath(allocator, dir, sub_path, options),
71 .macho => return MachO.openPath(allocator, dir, sub_path, options),73 .macho => return MachO.openPath(allocator, dir, sub_path, options),
72 .wasm => return Wasm.openPath(allocator, dir, sub_path, options),74 .wasm => return Wasm.openPath(allocator, dir, sub_path, options),
...@@ -85,7 +87,7 @@ pub const File = struct {...@@ -85,7 +87,7 @@ pub const File = struct {
8587
86 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {88 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
87 switch (base.tag) {89 switch (base.tag) {
88 .elf, .macho => {90 .coff, .elf, .macho => {
89 if (base.file != null) return;91 if (base.file != null) return;
90 base.file = try dir.createFile(sub_path, .{92 base.file = try dir.createFile(sub_path, .{
91 .truncate = false,93 .truncate = false,
...@@ -112,6 +114,7 @@ pub const File = struct {...@@ -112,6 +114,7 @@ pub const File = struct {
112 /// after allocateDeclIndexes for any given Decl.114 /// after allocateDeclIndexes for any given Decl.
113 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {115 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
114 switch (base.tag) {116 switch (base.tag) {
117 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
115 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),118 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
116 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),119 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
117 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),120 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
...@@ -121,6 +124,7 @@ pub const File = struct {...@@ -121,6 +124,7 @@ pub const File = struct {
121124
122 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {125 pub fn updateDeclLineNumber(base: *File, module: *Module, decl: *Module.Decl) !void {
123 switch (base.tag) {126 switch (base.tag) {
127 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclLineNumber(module, decl),
124 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),128 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclLineNumber(module, decl),
125 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),129 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclLineNumber(module, decl),
126 .c, .wasm => {},130 .c, .wasm => {},
...@@ -131,6 +135,7 @@ pub const File = struct {...@@ -131,6 +135,7 @@ pub const File = struct {
131 /// any given Decl.135 /// any given Decl.
132 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {136 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
133 switch (base.tag) {137 switch (base.tag) {
138 .coff => return @fieldParentPtr(Coff, "base", base).allocateDeclIndexes(decl),
134 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),139 .elf => return @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
135 .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl),140 .macho => return @fieldParentPtr(MachO, "base", base).allocateDeclIndexes(decl),
136 .c, .wasm => {},141 .c, .wasm => {},
...@@ -140,6 +145,7 @@ pub const File = struct {...@@ -140,6 +145,7 @@ pub const File = struct {
140 pub fn deinit(base: *File) void {145 pub fn deinit(base: *File) void {
141 if (base.file) |f| f.close();146 if (base.file) |f| f.close();
142 switch (base.tag) {147 switch (base.tag) {
148 .coff => @fieldParentPtr(Coff, "base", base).deinit(),
143 .elf => @fieldParentPtr(Elf, "base", base).deinit(),149 .elf => @fieldParentPtr(Elf, "base", base).deinit(),
144 .macho => @fieldParentPtr(MachO, "base", base).deinit(),150 .macho => @fieldParentPtr(MachO, "base", base).deinit(),
145 .c => @fieldParentPtr(C, "base", base).deinit(),151 .c => @fieldParentPtr(C, "base", base).deinit(),
...@@ -149,6 +155,11 @@ pub const File = struct {...@@ -149,6 +155,11 @@ pub const File = struct {
149155
150 pub fn destroy(base: *File) void {156 pub fn destroy(base: *File) void {
151 switch (base.tag) {157 switch (base.tag) {
158 .coff => {
159 const parent = @fieldParentPtr(Coff, "base", base);
160 parent.deinit();
161 base.allocator.destroy(parent);
162 },
152 .elf => {163 .elf => {
153 const parent = @fieldParentPtr(Elf, "base", base);164 const parent = @fieldParentPtr(Elf, "base", base);
154 parent.deinit();165 parent.deinit();
...@@ -177,6 +188,7 @@ pub const File = struct {...@@ -177,6 +188,7 @@ pub const File = struct {
177 defer tracy.end();188 defer tracy.end();
178189
179 try switch (base.tag) {190 try switch (base.tag) {
191 .coff => @fieldParentPtr(Coff, "base", base).flush(module),
180 .elf => @fieldParentPtr(Elf, "base", base).flush(module),192 .elf => @fieldParentPtr(Elf, "base", base).flush(module),
181 .macho => @fieldParentPtr(MachO, "base", base).flush(module),193 .macho => @fieldParentPtr(MachO, "base", base).flush(module),
182 .c => @fieldParentPtr(C, "base", base).flush(module),194 .c => @fieldParentPtr(C, "base", base).flush(module),
...@@ -186,6 +198,7 @@ pub const File = struct {...@@ -186,6 +198,7 @@ pub const File = struct {
186198
187 pub fn freeDecl(base: *File, decl: *Module.Decl) void {199 pub fn freeDecl(base: *File, decl: *Module.Decl) void {
188 switch (base.tag) {200 switch (base.tag) {
201 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),
189 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),202 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
190 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),203 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
191 .c => unreachable,204 .c => unreachable,
...@@ -195,6 +208,7 @@ pub const File = struct {...@@ -195,6 +208,7 @@ pub const File = struct {
195208
196 pub fn errorFlags(base: *File) ErrorFlags {209 pub fn errorFlags(base: *File) ErrorFlags {
197 return switch (base.tag) {210 return switch (base.tag) {
211 .coff => @fieldParentPtr(Coff, "base", base).error_flags,
198 .elf => @fieldParentPtr(Elf, "base", base).error_flags,212 .elf => @fieldParentPtr(Elf, "base", base).error_flags,
199 .macho => @fieldParentPtr(MachO, "base", base).error_flags,213 .macho => @fieldParentPtr(MachO, "base", base).error_flags,
200 .c => return .{ .no_entry_point_found = false },214 .c => return .{ .no_entry_point_found = false },
...@@ -211,6 +225,7 @@ pub const File = struct {...@@ -211,6 +225,7 @@ pub const File = struct {
211 exports: []const *Module.Export,225 exports: []const *Module.Export,
212 ) !void {226 ) !void {
213 switch (base.tag) {227 switch (base.tag) {
228 .coff => return @fieldParentPtr(Coff, "base", base).updateDeclExports(module, decl, exports),
214 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),229 .elf => return @fieldParentPtr(Elf, "base", base).updateDeclExports(module, decl, exports),
215 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports),230 .macho => return @fieldParentPtr(MachO, "base", base).updateDeclExports(module, decl, exports),
216 .c => return {},231 .c => return {},
...@@ -220,6 +235,7 @@ pub const File = struct {...@@ -220,6 +235,7 @@ pub const File = struct {
220235
221 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 {236 pub fn getDeclVAddr(base: *File, decl: *const Module.Decl) u64 {
222 switch (base.tag) {237 switch (base.tag) {
238 .coff => return @fieldParentPtr(Coff, "base", base).getDeclVAddr(decl),
223 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl),239 .elf => return @fieldParentPtr(Elf, "base", base).getDeclVAddr(decl),
224 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl),240 .macho => return @fieldParentPtr(MachO, "base", base).getDeclVAddr(decl),
225 .c => unreachable,241 .c => unreachable,
...@@ -228,6 +244,7 @@ pub const File = struct {...@@ -228,6 +244,7 @@ pub const File = struct {
228 }244 }
229245
230 pub const Tag = enum {246 pub const Tag = enum {
247 coff,
231 elf,248 elf,
232 macho,249 macho,
233 c,250 c,
...@@ -239,6 +256,7 @@ pub const File = struct {...@@ -239,6 +256,7 @@ pub const File = struct {
239 };256 };
240257
241 pub const C = @import("link/C.zig");258 pub const C = @import("link/C.zig");
259 pub const Coff = @import("link/Coff.zig");
242 pub const Elf = @import("link/Elf.zig");260 pub const Elf = @import("link/Elf.zig");
243 pub const MachO = @import("link/MachO.zig");261 pub const MachO = @import("link/MachO.zig");
244 pub const Wasm = @import("link/Wasm.zig");262 pub const Wasm = @import("link/Wasm.zig");
src-self-hosted/link/Coff.zig created+792
...@@ -0,0 +1,792 @@
1const Coff = @This();
2
3const std = @import("std");
4const log = std.log.scoped(.link);
5const Allocator = std.mem.Allocator;
6const assert = std.debug.assert;
7const fs = std.fs;
8
9const trace = @import("../tracy.zig").trace;
10const Module = @import("../Module.zig");
11const codegen = @import("../codegen.zig");
12const link = @import("../link.zig");
13
14const allocation_padding = 4 / 3;
15const minimum_text_block_size = 64 * allocation_padding;
16
17const section_alignment = 4096;
18const file_alignment = 512;
19const image_base = 0x400_000;
20const section_table_size = 2 * 40;
21comptime {
22 std.debug.assert(std.mem.isAligned(image_base, section_alignment));
23}
24
25pub const base_tag: link.File.Tag = .coff;
26
27const msdos_stub = @embedFile("msdos-stub.bin");
28
29base: link.File,
30ptr_width: enum { p32, p64 },
31error_flags: link.File.ErrorFlags = .{},
32
33text_block_free_list: std.ArrayListUnmanaged(*TextBlock) = .{},
34last_text_block: ?*TextBlock = null,
35
36/// Section table file pointer.
37section_table_offset: u32 = 0,
38/// Section data file pointer.
39section_data_offset: u32 = 0,
40/// Optiona header file pointer.
41optional_header_offset: u32 = 0,
42
43/// Absolute virtual address of the offset table when the executable is loaded in memory.
44offset_table_virtual_address: u32 = 0,
45/// Current size of the offset table on disk, must be a multiple of `file_alignment`
46offset_table_size: u32 = 0,
47/// Contains absolute virtual addresses
48offset_table: std.ArrayListUnmanaged(u64) = .{},
49/// Free list of offset table indices
50offset_table_free_list: std.ArrayListUnmanaged(u32) = .{},
51
52/// Virtual address of the entry point procedure relative to `image_base`
53entry_addr: ?u32 = null,
54
55/// Absolute virtual address of the text section when the executable is loaded in memory.
56text_section_virtual_address: u32 = 0,
57/// Current size of the `.text` section on disk, must be a multiple of `file_alignment`
58text_section_size: u32 = 0,
59
60offset_table_size_dirty: bool = false,
61text_section_size_dirty: bool = false,
62/// This flag is set when the virtual size of the whole image file when loaded in memory has changed
63/// and needs to be updated in the optional header.
64size_of_image_dirty: bool = false,
65
66pub const TextBlock = struct {
67 /// Offset of the code relative to the start of the text section
68 text_offset: u32,
69 /// Used size of the text block
70 size: u32,
71 /// This field is undefined for symbols with size = 0.
72 offset_table_index: u32,
73 /// Points to the previous and next neighbors, based on the `text_offset`.
74 /// This can be used to find, for example, the capacity of this `TextBlock`.
75 prev: ?*TextBlock,
76 next: ?*TextBlock,
77
78 pub const empty = TextBlock{
79 .text_offset = 0,
80 .size = 0,
81 .offset_table_index = undefined,
82 .prev = null,
83 .next = null,
84 };
85
86 /// Returns how much room there is to grow in virtual address space.
87 fn capacity(self: TextBlock) u64 {
88 if (self.next) |next| {
89 return next.text_offset - self.text_offset;
90 }
91 // This is the last block, the capacity is only limited by the address space.
92 return std.math.maxInt(u32) - self.text_offset;
93 }
94
95 fn freeListEligible(self: TextBlock) bool {
96 // No need to keep a free list node for the last block.
97 const next = self.next orelse return false;
98 const cap = next.text_offset - self.text_offset;
99 const ideal_cap = self.size * allocation_padding;
100 if (cap <= ideal_cap) return false;
101 const surplus = cap - ideal_cap;
102 return surplus >= minimum_text_block_size;
103 }
104
105 /// Absolute virtual address of the text block when the file is loaded in memory.
106 fn getVAddr(self: TextBlock, coff: Coff) u32 {
107 return coff.text_section_virtual_address + self.text_offset;
108 }
109};
110
111pub const SrcFn = void;
112
113pub fn openPath(allocator: *Allocator, dir: fs.Dir, sub_path: []const u8, options: link.Options) !*link.File {
114 assert(options.object_format == .coff);
115
116 const file = try dir.createFile(sub_path, .{ .truncate = false, .read = true, .mode = link.determineMode(options) });
117 errdefer file.close();
118
119 var coff_file = try allocator.create(Coff);
120 errdefer allocator.destroy(coff_file);
121
122 coff_file.* = openFile(allocator, file, options) catch |err| switch (err) {
123 error.IncrFailed => try createFile(allocator, file, options),
124 else => |e| return e,
125 };
126
127 return &coff_file.base;
128}
129
130/// Returns error.IncrFailed if incremental update could not be performed.
131fn openFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff {
132 switch (options.output_mode) {
133 .Exe => {},
134 .Obj => return error.IncrFailed,
135 .Lib => return error.IncrFailed,
136 }
137 var self: Coff = .{
138 .base = .{
139 .file = file,
140 .tag = .coff,
141 .options = options,
142 .allocator = allocator,
143 },
144 .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
145 32 => .p32,
146 64 => .p64,
147 else => return error.UnsupportedELFArchitecture,
148 },
149 };
150 errdefer self.deinit();
151
152 // TODO implement reading the PE/COFF file
153 return error.IncrFailed;
154}
155
156/// Truncates the existing file contents and overwrites the contents.
157/// Returns an error if `file` is not already open with +read +write +seek abilities.
158fn createFile(allocator: *Allocator, file: fs.File, options: link.Options) !Coff {
159 // TODO Write object specific relocations, COFF symbol table, then enable object file output.
160 switch (options.output_mode) {
161 .Exe => {},
162 .Obj => return error.TODOImplementWritingObjFiles,
163 .Lib => return error.TODOImplementWritingLibFiles,
164 }
165 var self: Coff = .{
166 .base = .{
167 .tag = .coff,
168 .options = options,
169 .allocator = allocator,
170 .file = file,
171 },
172 .ptr_width = switch (options.target.cpu.arch.ptrBitWidth()) {
173 32 => .p32,
174 64 => .p64,
175 else => return error.UnsupportedCOFFArchitecture,
176 },
177 };
178 errdefer self.deinit();
179
180 var coff_file_header_offset: u32 = 0;
181 if (options.output_mode == .Exe) {
182 // Write the MS-DOS stub and the PE signature
183 try self.base.file.?.pwriteAll(msdos_stub ++ "PE\x00\x00", 0);
184 coff_file_header_offset = msdos_stub.len + 4;
185 }
186
187 // COFF file header
188 const data_directory_count = 0;
189 var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined;
190 var index: usize = 0;
191
192 const machine = self.base.options.target.cpu.arch.toCoffMachine();
193 if (machine == .Unknown) {
194 return error.UnsupportedCOFFArchitecture;
195 }
196 std.mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
197 index += 2;
198
199 // Number of sections (we only use .got, .text)
200 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
201 index += 2;
202 // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
203 std.mem.set(u8, hdr_data[index..][0..12], 0);
204 index += 12;
205
206 const optional_header_size = switch (options.output_mode) {
207 .Exe => data_directory_count * 8 + switch (self.ptr_width) {
208 .p32 => @as(u16, 96),
209 .p64 => 112,
210 },
211 else => 0,
212 };
213
214 const section_table_offset = coff_file_header_offset + 20 + optional_header_size;
215 const default_offset_table_size = file_alignment;
216 const default_size_of_code = 0;
217
218 self.section_data_offset = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
219 const section_data_relative_virtual_address = std.mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
220 self.offset_table_virtual_address = image_base + section_data_relative_virtual_address;
221 self.offset_table_size = default_offset_table_size;
222 self.section_table_offset = section_table_offset;
223 self.text_section_virtual_address = image_base + section_data_relative_virtual_address + section_alignment;
224 self.text_section_size = default_size_of_code;
225
226 // Size of file when loaded in memory
227 const size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + default_size_of_code, section_alignment);
228
229 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
230 index += 2;
231
232 // Characteristics
233 var characteristics: u16 = std.coff.IMAGE_FILE_DEBUG_STRIPPED | std.coff.IMAGE_FILE_RELOCS_STRIPPED; // TODO Remove debug info stripped flag when necessary
234 if (options.output_mode == .Exe) {
235 characteristics |= std.coff.IMAGE_FILE_EXECUTABLE_IMAGE;
236 }
237 switch (self.ptr_width) {
238 .p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
239 .p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
240 }
241 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
242 index += 2;
243
244 assert(index == 20);
245 try self.base.file.?.pwriteAll(hdr_data[0..index], coff_file_header_offset);
246
247 if (options.output_mode == .Exe) {
248 self.optional_header_offset = coff_file_header_offset + 20;
249 // Optional header
250 index = 0;
251 std.mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
252 .p32 => @as(u16, 0x10b),
253 .p64 => 0x20b,
254 });
255 index += 2;
256
257 // Linker version (u8 + u8)
258 std.mem.set(u8, hdr_data[index..][0..2], 0);
259 index += 2;
260
261 // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
262 std.mem.set(u8, hdr_data[index..][0..20], 0);
263 index += 20;
264
265 if (self.ptr_width == .p32) {
266 // Base of data relative to the image base (UNUSED)
267 std.mem.set(u8, hdr_data[index..][0..4], 0);
268 index += 4;
269
270 // Image base address
271 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], image_base);
272 index += 4;
273 } else {
274 // Image base address
275 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], image_base);
276 index += 8;
277 }
278
279 // Section alignment
280 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
281 index += 4;
282 // File alignment
283 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
284 index += 4;
285 // Required OS version, 6.0 is vista
286 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
287 index += 2;
288 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
289 index += 2;
290 // Image version
291 std.mem.set(u8, hdr_data[index..][0..4], 0);
292 index += 4;
293 // Required subsystem version, same as OS version
294 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
295 index += 2;
296 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
297 index += 2;
298 // Reserved zeroes (u32)
299 std.mem.set(u8, hdr_data[index..][0..4], 0);
300 index += 4;
301 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
302 index += 4;
303 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
304 index += 4;
305 // CheckSum (u32)
306 std.mem.set(u8, hdr_data[index..][0..4], 0);
307 index += 4;
308 // Subsystem, TODO: Let users specify the subsystem, always CUI for now
309 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
310 index += 2;
311 // DLL characteristics
312 std.mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
313 index += 2;
314
315 switch (self.ptr_width) {
316 .p32 => {
317 // Size of stack reserve + commit
318 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
319 index += 4;
320 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
321 index += 4;
322 // Size of heap reserve + commit
323 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
324 index += 4;
325 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
326 index += 4;
327 },
328 .p64 => {
329 // Size of stack reserve + commit
330 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
331 index += 8;
332 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
333 index += 8;
334 // Size of heap reserve + commit
335 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
336 index += 8;
337 std.mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
338 index += 8;
339 },
340 }
341
342 // Reserved zeroes
343 std.mem.set(u8, hdr_data[index..][0..4], 0);
344 index += 4;
345
346 // Number of data directories
347 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
348 index += 4;
349 // Initialize data directories to zero
350 std.mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
351 index += data_directory_count * 8;
352
353 assert(index == optional_header_size);
354 }
355
356 // Write section table.
357 // First, the .got section
358 hdr_data[index..][0..8].* = ".got\x00\x00\x00\x00".*;
359 index += 8;
360 if (options.output_mode == .Exe) {
361 // Virtual size (u32)
362 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
363 index += 4;
364 // Virtual address (u32)
365 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - image_base);
366 index += 4;
367 } else {
368 std.mem.set(u8, hdr_data[index..][0..8], 0);
369 index += 8;
370 }
371 // Size of raw data (u32)
372 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
373 index += 4;
374 // File pointer to the start of the section
375 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
376 index += 4;
377 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
378 std.mem.set(u8, hdr_data[index..][0..12], 0);
379 index += 12;
380 // Section flags
381 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
382 index += 4;
383 // Then, the .text section
384 hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
385 index += 8;
386 if (options.output_mode == .Exe) {
387 // Virtual size (u32)
388 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
389 index += 4;
390 // Virtual address (u32)
391 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - image_base);
392 index += 4;
393 } else {
394 std.mem.set(u8, hdr_data[index..][0..8], 0);
395 index += 8;
396 }
397 // Size of raw data (u32)
398 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
399 index += 4;
400 // File pointer to the start of the section
401 std.mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
402 index += 4;
403 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
404 std.mem.set(u8, hdr_data[index..][0..12], 0);
405 index += 12;
406 // Section flags
407 std.mem.writeIntLittle(
408 u32,
409 hdr_data[index..][0..4],
410 std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
411 );
412 index += 4;
413
414 assert(index == optional_header_size + section_table_size);
415 try self.base.file.?.pwriteAll(hdr_data[0..index], self.optional_header_offset);
416 try self.base.file.?.setEndPos(self.section_data_offset + default_offset_table_size + default_size_of_code);
417
418 return self;
419}
420
421pub fn allocateDeclIndexes(self: *Coff, decl: *Module.Decl) !void {
422 try self.offset_table.ensureCapacity(self.base.allocator, self.offset_table.items.len + 1);
423
424 if (self.offset_table_free_list.popOrNull()) |i| {
425 decl.link.coff.offset_table_index = i;
426 } else {
427 decl.link.coff.offset_table_index = @intCast(u32, self.offset_table.items.len);
428 _ = self.offset_table.addOneAssumeCapacity();
429
430 const entry_size = self.base.options.target.cpu.arch.ptrBitWidth() / 8;
431 if (self.offset_table.items.len > self.offset_table_size / entry_size) {
432 self.offset_table_size_dirty = true;
433 }
434 }
435
436 self.offset_table.items[decl.link.coff.offset_table_index] = 0;
437}
438
439fn allocateTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
440 const new_block_min_capacity = new_block_size * allocation_padding;
441
442 // We use these to indicate our intention to update metadata, placing the new block,
443 // and possibly removing a free list node.
444 // It would be simpler to do it inside the for loop below, but that would cause a
445 // problem if an error was returned later in the function. So this action
446 // is actually carried out at the end of the function, when errors are no longer possible.
447 var block_placement: ?*TextBlock = null;
448 var free_list_removal: ?usize = null;
449
450 const vaddr = blk: {
451 var i: usize = 0;
452 while (i < self.text_block_free_list.items.len) {
453 const free_block = self.text_block_free_list.items[i];
454
455 const next_block_text_offset = free_block.text_offset + free_block.capacity();
456 const new_block_text_offset = std.mem.alignForwardGeneric(u64, free_block.getVAddr(self.*) + free_block.size, alignment) - self.text_section_virtual_address;
457 if (new_block_text_offset < next_block_text_offset and next_block_text_offset - new_block_text_offset >= new_block_min_capacity) {
458 block_placement = free_block;
459
460 const remaining_capacity = next_block_text_offset - new_block_text_offset - new_block_min_capacity;
461 if (remaining_capacity < minimum_text_block_size) {
462 free_list_removal = i;
463 }
464
465 break :blk new_block_text_offset + self.text_section_virtual_address;
466 } else {
467 if (!free_block.freeListEligible()) {
468 _ = self.text_block_free_list.swapRemove(i);
469 } else {
470 i += 1;
471 }
472 continue;
473 }
474 } else if (self.last_text_block) |last| {
475 const new_block_vaddr = std.mem.alignForwardGeneric(u64, last.getVAddr(self.*) + last.size, alignment);
476 block_placement = last;
477 break :blk new_block_vaddr;
478 } else {
479 break :blk self.text_section_virtual_address;
480 }
481 };
482
483 const expand_text_section = block_placement == null or block_placement.?.next == null;
484 if (expand_text_section) {
485 const needed_size = @intCast(u32, std.mem.alignForwardGeneric(u64, vaddr + new_block_size - self.text_section_virtual_address, file_alignment));
486 if (needed_size > self.text_section_size) {
487 const current_text_section_virtual_size = std.mem.alignForwardGeneric(u32, self.text_section_size, section_alignment);
488 const new_text_section_virtual_size = std.mem.alignForwardGeneric(u32, needed_size, section_alignment);
489 if (current_text_section_virtual_size != new_text_section_virtual_size) {
490 self.size_of_image_dirty = true;
491 // Write new virtual size
492 var buf: [4]u8 = undefined;
493 std.mem.writeIntLittle(u32, &buf, new_text_section_virtual_size);
494 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 8);
495 }
496
497 self.text_section_size = needed_size;
498 self.text_section_size_dirty = true;
499 }
500 self.last_text_block = text_block;
501 }
502 text_block.text_offset = @intCast(u32, vaddr - self.text_section_virtual_address);
503 text_block.size = @intCast(u32, new_block_size);
504
505 // This function can also reallocate a text block.
506 // In this case we need to "unplug" it from its previous location before
507 // plugging it in to its new location.
508 if (text_block.prev) |prev| {
509 prev.next = text_block.next;
510 }
511 if (text_block.next) |next| {
512 next.prev = text_block.prev;
513 }
514
515 if (block_placement) |big_block| {
516 text_block.prev = big_block;
517 text_block.next = big_block.next;
518 big_block.next = text_block;
519 } else {
520 text_block.prev = null;
521 text_block.next = null;
522 }
523 if (free_list_removal) |i| {
524 _ = self.text_block_free_list.swapRemove(i);
525 }
526 return vaddr;
527}
528
529fn growTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
530 const block_vaddr = text_block.getVAddr(self.*);
531 const align_ok = std.mem.alignBackwardGeneric(u64, block_vaddr, alignment) == block_vaddr;
532 const need_realloc = !align_ok or new_block_size > text_block.capacity();
533 if (!need_realloc) return @as(u64, block_vaddr);
534 return self.allocateTextBlock(text_block, new_block_size, alignment);
535}
536
537fn shrinkTextBlock(self: *Coff, text_block: *TextBlock, new_block_size: u64) void {
538 text_block.size = @intCast(u32, new_block_size);
539 if (text_block.capacity() - text_block.size >= minimum_text_block_size) {
540 self.text_block_free_list.append(self.base.allocator, text_block) catch {};
541 }
542}
543
544fn freeTextBlock(self: *Coff, text_block: *TextBlock) void {
545 var already_have_free_list_node = false;
546 {
547 var i: usize = 0;
548 // TODO turn text_block_free_list into a hash map
549 while (i < self.text_block_free_list.items.len) {
550 if (self.text_block_free_list.items[i] == text_block) {
551 _ = self.text_block_free_list.swapRemove(i);
552 continue;
553 }
554 if (self.text_block_free_list.items[i] == text_block.prev) {
555 already_have_free_list_node = true;
556 }
557 i += 1;
558 }
559 }
560 if (self.last_text_block == text_block) {
561 self.last_text_block = text_block.prev;
562 }
563 if (text_block.prev) |prev| {
564 prev.next = text_block.next;
565
566 if (!already_have_free_list_node and prev.freeListEligible()) {
567 // The free list is heuristics, it doesn't have to be perfect, so we can
568 // ignore the OOM here.
569 self.text_block_free_list.append(self.base.allocator, prev) catch {};
570 }
571 }
572
573 if (text_block.next) |next| {
574 next.prev = text_block.prev;
575 }
576}
577
578fn writeOffsetTableEntry(self: *Coff, index: usize) !void {
579 const entry_size = self.base.options.target.cpu.arch.ptrBitWidth() / 8;
580 const endian = self.base.options.target.cpu.arch.endian();
581
582 const offset_table_start = self.section_data_offset;
583 if (self.offset_table_size_dirty) {
584 const current_raw_size = self.offset_table_size;
585 const new_raw_size = self.offset_table_size * 2;
586 log.debug("growing offset table from raw size {} to {}\n", .{ current_raw_size, new_raw_size });
587
588 // Move the text section to a new place in the executable
589 const current_text_section_start = self.section_data_offset + current_raw_size;
590 const new_text_section_start = self.section_data_offset + new_raw_size;
591
592 const amt = try self.base.file.?.copyRangeAll(current_text_section_start, self.base.file.?, new_text_section_start, self.text_section_size);
593 if (amt != self.text_section_size) return error.InputOutput;
594
595 // Write the new raw size in the .got header
596 var buf: [8]u8 = undefined;
597 std.mem.writeIntLittle(u32, buf[0..4], new_raw_size);
598 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 16);
599 // Write the new .text section file offset in the .text section header
600 std.mem.writeIntLittle(u32, buf[0..4], new_text_section_start);
601 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 20);
602
603 const current_virtual_size = std.mem.alignForwardGeneric(u32, self.offset_table_size, section_alignment);
604 const new_virtual_size = std.mem.alignForwardGeneric(u32, new_raw_size, section_alignment);
605 // If we had to move in the virtual address space, we need to fix the VAs in the offset table, as well as the virtual address of the `.text` section
606 // and the virutal size of the `.got` section
607
608 if (new_virtual_size != current_virtual_size) {
609 log.debug("growing offset table from virtual size {} to {}\n", .{ current_virtual_size, new_virtual_size });
610 self.size_of_image_dirty = true;
611 const va_offset = new_virtual_size - current_virtual_size;
612
613 // Write .got virtual size
614 std.mem.writeIntLittle(u32, buf[0..4], new_virtual_size);
615 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 8);
616
617 // Write .text new virtual address
618 self.text_section_virtual_address = self.text_section_virtual_address + va_offset;
619 std.mem.writeIntLittle(u32, buf[0..4], self.text_section_virtual_address - image_base);
620 try self.base.file.?.pwriteAll(buf[0..4], self.section_table_offset + 40 + 12);
621
622 // Fix the VAs in the offset table
623 for (self.offset_table.items) |*va, idx| {
624 if (va.* != 0) {
625 va.* += va_offset;
626
627 switch (entry_size) {
628 4 => {
629 std.mem.writeInt(u32, buf[0..4], @intCast(u32, va.*), endian);
630 try self.base.file.?.pwriteAll(buf[0..4], offset_table_start + idx * entry_size);
631 },
632 8 => {
633 std.mem.writeInt(u64, &buf, va.*, endian);
634 try self.base.file.?.pwriteAll(&buf, offset_table_start + idx * entry_size);
635 },
636 else => unreachable,
637 }
638 }
639 }
640 }
641 self.offset_table_size = new_raw_size;
642 self.offset_table_size_dirty = false;
643 }
644 // Write the new entry
645 switch (entry_size) {
646 4 => {
647 var buf: [4]u8 = undefined;
648 std.mem.writeInt(u32, &buf, @intCast(u32, self.offset_table.items[index]), endian);
649 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
650 },
651 8 => {
652 var buf: [8]u8 = undefined;
653 std.mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
654 try self.base.file.?.pwriteAll(&buf, offset_table_start + index * entry_size);
655 },
656 else => unreachable,
657 }
658}
659
660pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
661 // TODO COFF/PE debug information
662 // TODO Implement exports
663 const tracy = trace(@src());
664 defer tracy.end();
665
666 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
667 defer code_buffer.deinit();
668
669 const typed_value = decl.typed_value.most_recent.typed_value;
670 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);
671 const code = switch (res) {
672 .externally_managed => |x| x,
673 .appended => code_buffer.items,
674 .fail => |em| {
675 decl.analysis = .codegen_failure;
676 try module.failed_decls.put(module.gpa, decl, em);
677 return;
678 },
679 };
680
681 const required_alignment = typed_value.ty.abiAlignment(self.base.options.target);
682 const curr_size = decl.link.coff.size;
683 if (curr_size != 0) {
684 const capacity = decl.link.coff.capacity();
685 const need_realloc = code.len > capacity or
686 !std.mem.isAlignedGeneric(u32, decl.link.coff.text_offset, required_alignment);
687 if (need_realloc) {
688 const curr_vaddr = self.getDeclVAddr(decl);
689 const vaddr = try self.growTextBlock(&decl.link.coff, code.len, required_alignment);
690 log.debug("growing {} from 0x{x} to 0x{x}\n", .{ decl.name, curr_vaddr, vaddr });
691 if (vaddr != curr_vaddr) {
692 log.debug(" (writing new offset table entry)\n", .{});
693 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;
694 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);
695 }
696 } else if (code.len < curr_size) {
697 self.shrinkTextBlock(&decl.link.coff, code.len);
698 }
699 } else {
700 const vaddr = try self.allocateTextBlock(&decl.link.coff, code.len, required_alignment);
701 log.debug("allocated text block for {} at 0x{x} (size: {Bi})\n", .{ std.mem.spanZ(decl.name), vaddr, code.len });
702 errdefer self.freeTextBlock(&decl.link.coff);
703 self.offset_table.items[decl.link.coff.offset_table_index] = vaddr;
704 try self.writeOffsetTableEntry(decl.link.coff.offset_table_index);
705 }
706
707 // Write the code into the file
708 try self.base.file.?.pwriteAll(code, self.section_data_offset + self.offset_table_size + decl.link.coff.text_offset);
709
710 // Since we updated the vaddr and the size, each corresponding export symbol also needs to be updated.
711 const decl_exports = module.decl_exports.get(decl) orelse &[0]*Module.Export{};
712 return self.updateDeclExports(module, decl, decl_exports);
713}
714
715pub fn freeDecl(self: *Coff, decl: *Module.Decl) void {
716 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
717 self.freeTextBlock(&decl.link.coff);
718 self.offset_table_free_list.append(self.base.allocator, decl.link.coff.offset_table_index) catch {};
719}
720
721pub fn updateDeclExports(self: *Coff, module: *Module, decl: *const Module.Decl, exports: []const *Module.Export) !void {
722 for (exports) |exp| {
723 if (exp.options.section) |section_name| {
724 if (!std.mem.eql(u8, section_name, ".text")) {
725 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
726 module.failed_exports.putAssumeCapacityNoClobber(
727 exp,
728 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: ExportOptions.section", .{}),
729 );
730 continue;
731 }
732 }
733 if (std.mem.eql(u8, exp.options.name, "_start")) {
734 self.entry_addr = decl.link.coff.getVAddr(self.*) - image_base;
735 } else {
736 try module.failed_exports.ensureCapacity(module.gpa, module.failed_exports.items().len + 1);
737 module.failed_exports.putAssumeCapacityNoClobber(
738 exp,
739 try Module.ErrorMsg.create(self.base.allocator, 0, "Unimplemented: Exports other than '_start'", .{}),
740 );
741 continue;
742 }
743 }
744}
745
746pub fn flush(self: *Coff, module: *Module) !void {
747 if (self.text_section_size_dirty) {
748 // Write the new raw size in the .text header
749 var buf: [4]u8 = undefined;
750 std.mem.writeIntLittle(u32, &buf, self.text_section_size);
751 try self.base.file.?.pwriteAll(&buf, self.section_table_offset + 40 + 16);
752 try self.base.file.?.setEndPos(self.section_data_offset + self.offset_table_size + self.text_section_size);
753 self.text_section_size_dirty = false;
754 }
755
756 if (self.base.options.output_mode == .Exe and self.size_of_image_dirty) {
757 const new_size_of_image = std.mem.alignForwardGeneric(u32, self.text_section_virtual_address - image_base + self.text_section_size, section_alignment);
758 var buf: [4]u8 = undefined;
759 std.mem.writeIntLittle(u32, &buf, new_size_of_image);
760 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 56);
761 self.size_of_image_dirty = false;
762 }
763
764 if (self.entry_addr == null and self.base.options.output_mode == .Exe) {
765 log.debug("flushing. no_entry_point_found = true\n", .{});
766 self.error_flags.no_entry_point_found = true;
767 } else {
768 log.debug("flushing. no_entry_point_found = false\n", .{});
769 self.error_flags.no_entry_point_found = false;
770
771 if (self.base.options.output_mode == .Exe) {
772 // Write AddressOfEntryPoint
773 var buf: [4]u8 = undefined;
774 std.mem.writeIntLittle(u32, &buf, self.entry_addr.?);
775 try self.base.file.?.pwriteAll(&buf, self.optional_header_offset + 16);
776 }
777 }
778}
779
780pub fn getDeclVAddr(self: *Coff, decl: *const Module.Decl) u64 {
781 return self.text_section_virtual_address + decl.link.coff.text_offset;
782}
783
784pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !void {
785 // TODO Implement this
786}
787
788pub fn deinit(self: *Coff) void {
789 self.text_block_free_list.deinit(self.base.allocator);
790 self.offset_table.deinit(self.base.allocator);
791 self.offset_table_free_list.deinit(self.base.allocator);
792}
src-self-hosted/link/Elf.zig+7-1
...@@ -1735,7 +1735,13 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -1735,7 +1735,13 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
1735 } else {1735 } else {
1736 // TODO implement .debug_info for global variables1736 // TODO implement .debug_info for global variables
1737 }1737 }
1738 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, &dbg_line_buffer, &dbg_info_buffer, &dbg_info_type_relocs);1738 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{
1739 .dwarf = .{
1740 .dbg_line = &dbg_line_buffer,
1741 .dbg_info = &dbg_info_buffer,
1742 .dbg_info_type_relocs = &dbg_info_type_relocs,
1743 },
1744 });
1739 const code = switch (res) {1745 const code = switch (res) {
1740 .externally_managed => |x| x,1746 .externally_managed => |x| x,
1741 .appended => code_buffer.items,1747 .appended => code_buffer.items,
src-self-hosted/link/MachO.zig+1-24
...@@ -316,31 +316,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -316,31 +316,8 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
316 var code_buffer = std.ArrayList(u8).init(self.base.allocator);316 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
317 defer code_buffer.deinit();317 defer code_buffer.deinit();
318318
319 var dbg_line_buffer = std.ArrayList(u8).init(self.base.allocator);
320 defer dbg_line_buffer.deinit();
321
322 var dbg_info_buffer = std.ArrayList(u8).init(self.base.allocator);
323 defer dbg_info_buffer.deinit();
324
325 var dbg_info_type_relocs: File.DbgInfoTypeRelocsTable = .{};
326 defer {
327 var it = dbg_info_type_relocs.iterator();
328 while (it.next()) |entry| {
329 entry.value.relocs.deinit(self.base.allocator);
330 }
331 dbg_info_type_relocs.deinit(self.base.allocator);
332 }
333
334 const typed_value = decl.typed_value.most_recent.typed_value;319 const typed_value = decl.typed_value.most_recent.typed_value;
335 const res = try codegen.generateSymbol(320 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);
336 &self.base,
337 decl.src(),
338 typed_value,
339 &code_buffer,
340 &dbg_line_buffer,
341 &dbg_info_buffer,
342 &dbg_info_type_relocs,
343 );
344321
345 const code = switch (res) {322 const code = switch (res) {
346 .externally_managed => |x| x,323 .externally_managed => |x| x,
src-self-hosted/link/msdos-stub.bin created
Binary files /dev/null and b/src-self-hosted/link/msdos-stub.bin differ
src-self-hosted/main.zig+16-7
...@@ -153,8 +153,8 @@ const usage_build_generic =...@@ -153,8 +153,8 @@ const usage_build_generic =
153 \\ elf Executable and Linking Format153 \\ elf Executable and Linking Format
154 \\ c Compile to C source code154 \\ c Compile to C source code
155 \\ wasm WebAssembly155 \\ wasm WebAssembly
156 \\ pe Portable Executable (Windows)
156 \\ coff (planned) Common Object File Format (Windows)157 \\ coff (planned) Common Object File Format (Windows)
157 \\ pe (planned) Portable Executable (Windows)
158 \\ macho (planned) macOS relocatables158 \\ macho (planned) macOS relocatables
159 \\ hex (planned) Intel IHEX159 \\ hex (planned) Intel IHEX
160 \\ raw (planned) Dump machine code directly160 \\ raw (planned) Dump machine code directly
...@@ -451,7 +451,7 @@ fn buildOutputType(...@@ -451,7 +451,7 @@ fn buildOutputType(
451 } else if (mem.eql(u8, ofmt, "coff")) {451 } else if (mem.eql(u8, ofmt, "coff")) {
452 break :blk .coff;452 break :blk .coff;
453 } else if (mem.eql(u8, ofmt, "pe")) {453 } else if (mem.eql(u8, ofmt, "pe")) {
454 break :blk .coff;454 break :blk .pe;
455 } else if (mem.eql(u8, ofmt, "macho")) {455 } else if (mem.eql(u8, ofmt, "macho")) {
456 break :blk .macho;456 break :blk .macho;
457 } else if (mem.eql(u8, ofmt, "wasm")) {457 } else if (mem.eql(u8, ofmt, "wasm")) {
...@@ -524,17 +524,19 @@ fn buildOutputType(...@@ -524,17 +524,19 @@ fn buildOutputType(
524 try stderr.print("\nUnable to parse command: {}\n", .{@errorName(err)});524 try stderr.print("\nUnable to parse command: {}\n", .{@errorName(err)});
525 continue;525 continue;
526 }) |line| {526 }) |line| {
527 if (mem.eql(u8, line, "update")) {527 const actual_line = mem.trimRight(u8, line, "\r\n ");
528
529 if (mem.eql(u8, actual_line, "update")) {
528 if (output_mode == .Exe) {530 if (output_mode == .Exe) {
529 try module.makeBinFileWritable();531 try module.makeBinFileWritable();
530 }532 }
531 try updateModule(gpa, &module, zir_out_path);533 try updateModule(gpa, &module, zir_out_path);
532 } else if (mem.eql(u8, line, "exit")) {534 } else if (mem.eql(u8, actual_line, "exit")) {
533 break;535 break;
534 } else if (mem.eql(u8, line, "help")) {536 } else if (mem.eql(u8, actual_line, "help")) {
535 try stderr.writeAll(repl_help);537 try stderr.writeAll(repl_help);
536 } else {538 } else {
537 try stderr.print("unknown command: {}\n", .{line});539 try stderr.print("unknown command: {}\n", .{actual_line});
538 }540 }
539 } else {541 } else {
540 break;542 break;
...@@ -742,6 +744,7 @@ const FmtError = error{...@@ -742,6 +744,7 @@ const FmtError = error{
742 LinkQuotaExceeded,744 LinkQuotaExceeded,
743 FileBusy,745 FileBusy,
744 EndOfStream,746 EndOfStream,
747 Unseekable,
745 NotOpenForWriting,748 NotOpenForWriting,
746} || fs.File.OpenError;749} || fs.File.OpenError;
747750
...@@ -805,7 +808,13 @@ fn fmtPathFile(...@@ -805,7 +808,13 @@ fn fmtPathFile(
805 if (stat.kind == .Directory)808 if (stat.kind == .Directory)
806 return error.IsDir;809 return error.IsDir;
807810
808 const source_code = source_file.readAllAlloc(fmt.gpa, stat.size, max_src_size) catch |err| switch (err) {811 const source_code = source_file.readToEndAllocOptions(
812 fmt.gpa,
813 max_src_size,
814 stat.size,
815 @alignOf(u8),
816 null,
817 ) catch |err| switch (err) {
809 error.ConnectionResetByPeer => unreachable,818 error.ConnectionResetByPeer => unreachable,
810 error.ConnectionTimedOut => unreachable,819 error.ConnectionTimedOut => unreachable,
811 error.NotOpenForReading => unreachable,820 error.NotOpenForReading => unreachable,
src-self-hosted/stage2.zig-1
...@@ -615,7 +615,6 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [...@@ -615,7 +615,6 @@ export fn stage2_libc_parse(stage1_libc: *Stage2LibCInstallation, libc_file_z: [
615 error.NotOpenForWriting => unreachable,615 error.NotOpenForWriting => unreachable,
616 error.NotOpenForReading => unreachable,616 error.NotOpenForReading => unreachable,
617 error.Unexpected => return .Unexpected,617 error.Unexpected => return .Unexpected,
618 error.EndOfStream => return .EndOfFile,
619 error.IsDir => return .IsDir,618 error.IsDir => return .IsDir,
620 error.ConnectionResetByPeer => unreachable,619 error.ConnectionResetByPeer => unreachable,
621 error.ConnectionTimedOut => unreachable,620 error.ConnectionTimedOut => unreachable,
src/analyze.cpp+1-1
...@@ -1810,7 +1810,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {...@@ -1810,7 +1810,7 @@ Error type_allowed_in_extern(CodeGen *g, ZigType *type_entry, bool *result) {
1810ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {1810ZigType *get_auto_err_set_type(CodeGen *g, ZigFn *fn_entry) {
1811 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);1811 ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
1812 buf_resize(&err_set_type->name, 0);1812 buf_resize(&err_set_type->name, 0);
1813 buf_appendf(&err_set_type->name, "@TypeOf(%s).ReturnType.ErrorSet", buf_ptr(&fn_entry->symbol_name));1813 buf_appendf(&err_set_type->name, "@typeInfo(@typeInfo(@TypeOf(%s)).Fn.return_type.?).ErrorUnion.error_set", buf_ptr(&fn_entry->symbol_name));
1814 err_set_type->data.error_set.err_count = 0;1814 err_set_type->data.error_set.err_count = 0;
1815 err_set_type->data.error_set.errors = nullptr;1815 err_set_type->data.error_set.errors = nullptr;
1816 err_set_type->data.error_set.infer_fn = fn_entry;1816 err_set_type->data.error_set.infer_fn = fn_entry;
src/ir.cpp+3-161
...@@ -22836,167 +22836,9 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel...@@ -22836,167 +22836,9 @@ static IrInstGen *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstSrcFiel
22836 bool ptr_is_volatile = false;22836 bool ptr_is_volatile = false;
22837 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, const_val,22837 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base, const_val,
22838 err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);22838 err_set_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22839 } else if (child_type->id == ZigTypeIdInt) {
22840 if (buf_eql_str(field_name, "bit_count")) {
22841 bool ptr_is_const = true;
22842 bool ptr_is_volatile = false;
22843 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22844 create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int,
22845 child_type->data.integral.bit_count, false),
22846 ira->codegen->builtin_types.entry_num_lit_int,
22847 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22848 } else if (buf_eql_str(field_name, "is_signed")) {
22849 bool ptr_is_const = true;
22850 bool ptr_is_volatile = false;
22851 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22852 create_const_bool(ira->codegen, child_type->data.integral.is_signed),
22853 ira->codegen->builtin_types.entry_bool,
22854 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22855 } else {
22856 ir_add_error(ira, &field_ptr_instruction->base.base,
22857 buf_sprintf("type '%s' has no member called '%s'",
22858 buf_ptr(&child_type->name), buf_ptr(field_name)));
22859 return ira->codegen->invalid_inst_gen;
22860 }
22861 } else if (child_type->id == ZigTypeIdFloat) {
22862 if (buf_eql_str(field_name, "bit_count")) {
22863 bool ptr_is_const = true;
22864 bool ptr_is_volatile = false;
22865 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22866 create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int,
22867 child_type->data.floating.bit_count, false),
22868 ira->codegen->builtin_types.entry_num_lit_int,
22869 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22870 } else {
22871 ir_add_error(ira, &field_ptr_instruction->base.base,
22872 buf_sprintf("type '%s' has no member called '%s'",
22873 buf_ptr(&child_type->name), buf_ptr(field_name)));
22874 return ira->codegen->invalid_inst_gen;
22875 }
22876 } else if (child_type->id == ZigTypeIdPointer) {
22877 if (buf_eql_str(field_name, "Child")) {
22878 bool ptr_is_const = true;
22879 bool ptr_is_volatile = false;
22880 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22881 create_const_type(ira->codegen, child_type->data.pointer.child_type),
22882 ira->codegen->builtin_types.entry_type,
22883 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22884 } else if (buf_eql_str(field_name, "alignment")) {
22885 bool ptr_is_const = true;
22886 bool ptr_is_volatile = false;
22887 if ((err = type_resolve(ira->codegen, child_type->data.pointer.child_type,
22888 ResolveStatusAlignmentKnown)))
22889 {
22890 return ira->codegen->invalid_inst_gen;
22891 }
22892 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22893 create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int,
22894 get_ptr_align(ira->codegen, child_type), false),
22895 ira->codegen->builtin_types.entry_num_lit_int,
22896 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22897 } else {
22898 ir_add_error(ira, &field_ptr_instruction->base.base,
22899 buf_sprintf("type '%s' has no member called '%s'",
22900 buf_ptr(&child_type->name), buf_ptr(field_name)));
22901 return ira->codegen->invalid_inst_gen;
22902 }
22903 } else if (child_type->id == ZigTypeIdArray) {
22904 if (buf_eql_str(field_name, "Child")) {
22905 bool ptr_is_const = true;
22906 bool ptr_is_volatile = false;
22907 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22908 create_const_type(ira->codegen, child_type->data.array.child_type),
22909 ira->codegen->builtin_types.entry_type,
22910 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22911 } else if (buf_eql_str(field_name, "len")) {
22912 bool ptr_is_const = true;
22913 bool ptr_is_volatile = false;
22914 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22915 create_const_unsigned_negative(ira->codegen, ira->codegen->builtin_types.entry_num_lit_int,
22916 child_type->data.array.len, false),
22917 ira->codegen->builtin_types.entry_num_lit_int,
22918 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22919 } else {
22920 ir_add_error(ira, &field_ptr_instruction->base.base,
22921 buf_sprintf("type '%s' has no member called '%s'",
22922 buf_ptr(&child_type->name), buf_ptr(field_name)));
22923 return ira->codegen->invalid_inst_gen;
22924 }
22925 } else if (child_type->id == ZigTypeIdErrorUnion) {
22926 if (buf_eql_str(field_name, "Payload")) {
22927 bool ptr_is_const = true;
22928 bool ptr_is_volatile = false;
22929 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22930 create_const_type(ira->codegen, child_type->data.error_union.payload_type),
22931 ira->codegen->builtin_types.entry_type,
22932 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22933 } else if (buf_eql_str(field_name, "ErrorSet")) {
22934 bool ptr_is_const = true;
22935 bool ptr_is_volatile = false;
22936 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22937 create_const_type(ira->codegen, child_type->data.error_union.err_set_type),
22938 ira->codegen->builtin_types.entry_type,
22939 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22940 } else {
22941 ir_add_error(ira, &field_ptr_instruction->base.base,
22942 buf_sprintf("type '%s' has no member called '%s'",
22943 buf_ptr(&child_type->name), buf_ptr(field_name)));
22944 return ira->codegen->invalid_inst_gen;
22945 }
22946 } else if (child_type->id == ZigTypeIdOptional) {
22947 if (buf_eql_str(field_name, "Child")) {
22948 bool ptr_is_const = true;
22949 bool ptr_is_volatile = false;
22950 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22951 create_const_type(ira->codegen, child_type->data.maybe.child_type),
22952 ira->codegen->builtin_types.entry_type,
22953 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22954 } else {
22955 ir_add_error(ira, &field_ptr_instruction->base.base,
22956 buf_sprintf("type '%s' has no member called '%s'",
22957 buf_ptr(&child_type->name), buf_ptr(field_name)));
22958 return ira->codegen->invalid_inst_gen;
22959 }
22960 } else if (child_type->id == ZigTypeIdFn) {
22961 if (buf_eql_str(field_name, "ReturnType")) {
22962 if (child_type->data.fn.fn_type_id.return_type == nullptr) {
22963 // Return type can only ever be null, if the function is generic
22964 assert(child_type->data.fn.is_generic);
22965
22966 ir_add_error(ira, &field_ptr_instruction->base.base,
22967 buf_sprintf("ReturnType has not been resolved because '%s' is generic", buf_ptr(&child_type->name)));
22968 return ira->codegen->invalid_inst_gen;
22969 }
22970
22971 bool ptr_is_const = true;
22972 bool ptr_is_volatile = false;
22973 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22974 create_const_type(ira->codegen, child_type->data.fn.fn_type_id.return_type),
22975 ira->codegen->builtin_types.entry_type,
22976 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22977 } else if (buf_eql_str(field_name, "is_var_args")) {
22978 bool ptr_is_const = true;
22979 bool ptr_is_volatile = false;
22980 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22981 create_const_bool(ira->codegen, child_type->data.fn.fn_type_id.is_var_args),
22982 ira->codegen->builtin_types.entry_bool,
22983 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22984 } else if (buf_eql_str(field_name, "arg_count")) {
22985 bool ptr_is_const = true;
22986 bool ptr_is_volatile = false;
22987 return ir_get_const_ptr(ira, &field_ptr_instruction->base.base,
22988 create_const_usize(ira->codegen, child_type->data.fn.fn_type_id.param_count),
22989 ira->codegen->builtin_types.entry_usize,
22990 ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile, 0);
22991 } else {
22992 ir_add_error(ira, &field_ptr_instruction->base.base,
22993 buf_sprintf("type '%s' has no member called '%s'",
22994 buf_ptr(&child_type->name), buf_ptr(field_name)));
22995 return ira->codegen->invalid_inst_gen;
22996 }
22997 } else {22839 } else {
22998 ir_add_error(ira, &field_ptr_instruction->base.base,22840 ir_add_error(ira, &field_ptr_instruction->base.base,
22999 buf_sprintf("type '%s' does not support field access", buf_ptr(&child_type->name)));22841 buf_sprintf("type '%s' does not support field access", buf_ptr(&container_type->name)));
23000 return ira->codegen->invalid_inst_gen;22842 return ira->codegen->invalid_inst_gen;
23001 }22843 }
23002 } else if (field_ptr_instruction->initializing) {22844 } else if (field_ptr_instruction->initializing) {
...@@ -26753,7 +26595,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch...@@ -26753,7 +26595,7 @@ static IrInstGen *ir_analyze_instruction_cmpxchg(IrAnalyze *ira, IrInstSrcCmpxch
2675326595
26754 if (operand_type->id == ZigTypeIdFloat) {26596 if (operand_type->id == ZigTypeIdFloat) {
26755 ir_add_error(ira, &instruction->type_value->child->base,26597 ir_add_error(ira, &instruction->type_value->child->base,
26756 buf_sprintf("expected integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name)));26598 buf_sprintf("expected bool, integer, enum or pointer type, found '%s'", buf_ptr(&operand_type->name)));
26757 return ira->codegen->invalid_inst_gen;26599 return ira->codegen->invalid_inst_gen;
26758 }26600 }
2675926601
...@@ -30408,7 +30250,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {...@@ -30408,7 +30250,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstGen *op) {
30408 return ira->codegen->builtin_types.entry_invalid;30250 return ira->codegen->builtin_types.entry_invalid;
30409 if (operand_ptr_type == nullptr) {30251 if (operand_ptr_type == nullptr) {
30410 ir_add_error(ira, &op->base,30252 ir_add_error(ira, &op->base,
30411 buf_sprintf("expected integer, float, enum or pointer type, found '%s'",30253 buf_sprintf("expected bool, integer, float, enum or pointer type, found '%s'",
30412 buf_ptr(&operand_type->name)));30254 buf_ptr(&operand_type->name)));
30413 return ira->codegen->builtin_types.entry_invalid;30255 return ira->codegen->builtin_types.entry_invalid;
30414 }30256 }
test/compile_errors.zig+8-17
...@@ -176,11 +176,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -176,11 +176,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
176 , &[_][]const u8{176 , &[_][]const u8{
177 "tmp.zig:2:17: error: expected type 'u32', found 'error{Ohno}'",177 "tmp.zig:2:17: error: expected type 'u32', found 'error{Ohno}'",
178 "tmp.zig:1:17: note: function cannot return an error",178 "tmp.zig:1:17: note: function cannot return an error",
179 "tmp.zig:8:5: error: expected type 'void', found '@TypeOf(bar).ReturnType.ErrorSet'",179 "tmp.zig:8:5: error: expected type 'void', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set'",
180 "tmp.zig:7:17: note: function cannot return an error",180 "tmp.zig:7:17: note: function cannot return an error",
181 "tmp.zig:11:15: error: expected type 'u32', found '@TypeOf(bar).ReturnType.ErrorSet!u32'",181 "tmp.zig:11:15: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'",
182 "tmp.zig:10:17: note: function cannot return an error",182 "tmp.zig:10:17: note: function cannot return an error",
183 "tmp.zig:15:14: error: expected type 'u32', found '@TypeOf(bar).ReturnType.ErrorSet!u32'",183 "tmp.zig:15:14: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(bar)).Fn.return_type.?).ErrorUnion.error_set!u32'",
184 "tmp.zig:14:5: note: cannot store an error in type 'u32'",184 "tmp.zig:14:5: note: cannot store an error in type 'u32'",
185 });185 });
186186
...@@ -899,7 +899,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -899,7 +899,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
899 \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst);899 \\ _ = @cmpxchgWeak(f32, &x, 1, 2, .SeqCst, .SeqCst);
900 \\}900 \\}
901 , &[_][]const u8{901 , &[_][]const u8{
902 "tmp.zig:3:22: error: expected integer, enum or pointer type, found 'f32'",902 "tmp.zig:3:22: error: expected bool, integer, enum or pointer type, found 'f32'",
903 });903 });
904904
905 cases.add("atomicrmw with float op not .Xchg, .Add or .Sub",905 cases.add("atomicrmw with float op not .Xchg, .Add or .Sub",
...@@ -1224,7 +1224,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1224,7 +1224,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1224 \\ };1224 \\ };
1225 \\}1225 \\}
1226 , &[_][]const u8{1226 , &[_][]const u8{
1227 "tmp.zig:11:25: error: expected type 'u32', found '@TypeOf(get_uval).ReturnType.ErrorSet!u32'",1227 "tmp.zig:11:25: error: expected type 'u32', found '@typeInfo(@typeInfo(@TypeOf(get_uval)).Fn.return_type.?).ErrorUnion.error_set!u32'",
1228 });1228 });
12291229
1230 cases.add("assigning to struct or union fields that are not optionals with a function that returns an optional",1230 cases.add("assigning to struct or union fields that are not optionals with a function that returns an optional",
...@@ -1929,7 +1929,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -1929,7 +1929,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
1929 \\ const info = @TypeOf(slice).unknown;1929 \\ const info = @TypeOf(slice).unknown;
1930 \\}1930 \\}
1931 , &[_][]const u8{1931 , &[_][]const u8{
1932 "tmp.zig:3:32: error: type '[]i32' does not support field access",1932 "tmp.zig:3:32: error: type 'type' does not support field access",
1933 });1933 });
19341934
1935 cases.add("peer cast then implicit cast const pointer to mutable C pointer",1935 cases.add("peer cast then implicit cast const pointer to mutable C pointer",
...@@ -3542,7 +3542,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3542,7 +3542,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3542 \\ }3542 \\ }
3543 \\}3543 \\}
3544 , &[_][]const u8{3544 , &[_][]const u8{
3545 "tmp.zig:5:14: error: duplicate switch value: '@TypeOf(foo).ReturnType.ErrorSet.Foo'",3545 "tmp.zig:5:14: error: duplicate switch value: '@typeInfo(@typeInfo(@TypeOf(foo)).Fn.return_type.?).ErrorUnion.error_set.Foo'",
3546 "tmp.zig:3:14: note: other value is here",3546 "tmp.zig:3:14: note: other value is here",
3547 });3547 });
35483548
...@@ -3674,7 +3674,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3674,7 +3674,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3674 \\ try foo();3674 \\ try foo();
3675 \\}3675 \\}
3676 , &[_][]const u8{3676 , &[_][]const u8{
3677 "tmp.zig:5:5: error: cannot resolve inferred error set '@TypeOf(foo).ReturnType.ErrorSet': function 'foo' not fully analyzed yet",3677 "tmp.zig:5:5: error: cannot resolve inferred error set '@typeInfo(@typeInfo(@TypeOf(foo)).Fn.return_type.?).ErrorUnion.error_set': function 'foo' not fully analyzed yet",
3678 });3678 });
36793679
3680 cases.add("implicit cast of error set not a subset",3680 cases.add("implicit cast of error set not a subset",
...@@ -7206,15 +7206,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -7206,15 +7206,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
7206 "tmp.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set",7206 "tmp.zig:7:24: error: accessing union field 'Bar' while field 'Baz' is set",
7207 });7207 });
72087208
7209 cases.add("getting return type of generic function",
7210 \\fn generic(a: anytype) void {}
7211 \\comptime {
7212 \\ _ = @TypeOf(generic).ReturnType;
7213 \\}
7214 , &[_][]const u8{
7215 "tmp.zig:3:25: error: ReturnType has not been resolved because 'fn(anytype) anytype' is generic",
7216 });
7217
7218 cases.add("unsupported modifier at start of asm output constraint",7209 cases.add("unsupported modifier at start of asm output constraint",
7219 \\export fn foo() void {7210 \\export fn foo() void {
7220 \\ var bar: u32 = 3;7211 \\ var bar: u32 = 3;
test/stage1/behavior/align.zig+1-1
...@@ -5,7 +5,7 @@ const builtin = @import("builtin");...@@ -5,7 +5,7 @@ const builtin = @import("builtin");
5var foo: u8 align(4) = 100;5var foo: u8 align(4) = 100;
66
7test "global variable alignment" {7test "global variable alignment" {
8 comptime expect(@TypeOf(&foo).alignment == 4);8 comptime expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
9 comptime expect(@TypeOf(&foo) == *align(4) u8);9 comptime expect(@TypeOf(&foo) == *align(4) u8);
10 {10 {
11 const slice = @as(*[1]u8, &foo)[0..];11 const slice = @as(*[1]u8, &foo)[0..];
test/stage1/behavior/array.zig-10
...@@ -136,16 +136,6 @@ test "array literal with specified size" {...@@ -136,16 +136,6 @@ test "array literal with specified size" {
136 expect(array[1] == 2);136 expect(array[1] == 2);
137}137}
138138
139test "array child property" {
140 var x: [5]i32 = undefined;
141 expect(@TypeOf(x).Child == i32);
142}
143
144test "array len property" {
145 var x: [5]i32 = undefined;
146 expect(@TypeOf(x).len == 5);
147}
148
149test "array len field" {139test "array len field" {
150 var arr = [4]u8{ 0, 0, 0, 0 };140 var arr = [4]u8{ 0, 0, 0, 0 };
151 var ptr = &arr;141 var ptr = &arr;
test/stage1/behavior/async_fn.zig+3-3
...@@ -331,7 +331,7 @@ test "async fn with inferred error set" {...@@ -331,7 +331,7 @@ test "async fn with inferred error set" {
331 fn doTheTest() void {331 fn doTheTest() void {
332 var frame: [1]@Frame(middle) = undefined;332 var frame: [1]@Frame(middle) = undefined;
333 var fn_ptr = middle;333 var fn_ptr = middle;
334 var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined;334 var result: @typeInfo(@typeInfo(@TypeOf(fn_ptr)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
335 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});335 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr, .{});
336 resume global_frame;336 resume global_frame;
337 std.testing.expectError(error.Fail, result);337 std.testing.expectError(error.Fail, result);
...@@ -950,7 +950,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {...@@ -950,7 +950,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" {
950950
951 fn doTheTest() void {951 fn doTheTest() void {
952 var frame: [1]@Frame(middle) = undefined;952 var frame: [1]@Frame(middle) = undefined;
953 var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined;953 var result: @typeInfo(@typeInfo(@TypeOf(middle)).Fn.return_type.?).ErrorUnion.error_set!void = undefined;
954 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});954 _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle, .{});
955 resume global_frame;955 resume global_frame;
956 std.testing.expectError(error.Fail, result);956 std.testing.expectError(error.Fail, result);
...@@ -1018,7 +1018,7 @@ test "@TypeOf an async function call of generic fn with error union type" {...@@ -1018,7 +1018,7 @@ test "@TypeOf an async function call of generic fn with error union type" {
1018 const S = struct {1018 const S = struct {
1019 fn func(comptime x: anytype) anyerror!i32 {1019 fn func(comptime x: anytype) anyerror!i32 {
1020 const T = @TypeOf(async func(x));1020 const T = @TypeOf(async func(x));
1021 comptime expect(T == @TypeOf(@frame()).Child);1021 comptime expect(T == @typeInfo(@TypeOf(@frame())).Pointer.child);
1022 return undefined;1022 return undefined;
1023 }1023 }
1024 };1024 };
test/stage1/behavior/bit_shifting.zig+7-5
...@@ -2,16 +2,18 @@ const std = @import("std");...@@ -2,16 +2,18 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
33
4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {4fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type {
5 expect(Key == std.meta.Int(false, Key.bit_count));5 const key_bits = @typeInfo(Key).Int.bits;
6 expect(Key.bit_count >= mask_bit_count);6 expect(Key == std.meta.Int(false, key_bits));
7 expect(key_bits >= mask_bit_count);
8 const shard_key_bits = mask_bit_count;
7 const ShardKey = std.meta.Int(false, mask_bit_count);9 const ShardKey = std.meta.Int(false, mask_bit_count);
8 const shift_amount = Key.bit_count - ShardKey.bit_count;10 const shift_amount = key_bits - shard_key_bits;
9 return struct {11 return struct {
10 const Self = @This();12 const Self = @This();
11 shards: [1 << ShardKey.bit_count]?*Node,13 shards: [1 << shard_key_bits]?*Node,
1214
13 pub fn create() Self {15 pub fn create() Self {
14 return Self{ .shards = [_]?*Node{null} ** (1 << ShardKey.bit_count) };16 return Self{ .shards = [_]?*Node{null} ** (1 << shard_key_bits) };
15 }17 }
1618
17 fn getShardKey(key: Key) ShardKey {19 fn getShardKey(key: Key) ShardKey {
test/stage1/behavior/bugs/5487.zig+2-2
...@@ -3,8 +3,8 @@ const io = @import("std").io;...@@ -3,8 +3,8 @@ const io = @import("std").io;
3pub fn write(_: void, bytes: []const u8) !usize {3pub fn write(_: void, bytes: []const u8) !usize {
4 return 0;4 return 0;
5}5}
6pub fn outStream() io.OutStream(void, @TypeOf(write).ReturnType.ErrorSet, write) {6pub fn outStream() io.OutStream(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write) {
7 return io.OutStream(void, @TypeOf(write).ReturnType.ErrorSet, write){ .context = {} };7 return io.OutStream(void, @typeInfo(@typeInfo(@TypeOf(write)).Fn.return_type.?).ErrorUnion.error_set, write){ .context = {} };
8}8}
99
10test "crash" {10test "crash" {
test/stage1/behavior/error.zig+2-2
...@@ -84,8 +84,8 @@ fn testErrorUnionType() void {...@@ -84,8 +84,8 @@ fn testErrorUnionType() void {
84 const x: anyerror!i32 = 1234;84 const x: anyerror!i32 = 1234;
85 if (x) |value| expect(value == 1234) else |_| unreachable;85 if (x) |value| expect(value == 1234) else |_| unreachable;
86 expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);86 expect(@typeInfo(@TypeOf(x)) == .ErrorUnion);
87 expect(@typeInfo(@TypeOf(x).ErrorSet) == .ErrorSet);87 expect(@typeInfo(@typeInfo(@TypeOf(x)).ErrorUnion.error_set) == .ErrorSet);
88 expect(@TypeOf(x).ErrorSet == anyerror);88 expect(@typeInfo(@TypeOf(x)).ErrorUnion.error_set == anyerror);
89}89}
9090
91test "error set type" {91test "error set type" {
test/stage1/behavior/misc.zig-10
...@@ -24,12 +24,6 @@ test "call disabled extern fn" {...@@ -24,12 +24,6 @@ test "call disabled extern fn" {
24 disabledExternFn();24 disabledExternFn();
25}25}
2626
27test "floating point primitive bit counts" {
28 expect(f16.bit_count == 16);
29 expect(f32.bit_count == 32);
30 expect(f64.bit_count == 64);
31}
32
33test "short circuit" {27test "short circuit" {
34 testShortCircuit(false, true);28 testShortCircuit(false, true);
35 comptime testShortCircuit(false, true);29 comptime testShortCircuit(false, true);
...@@ -577,10 +571,6 @@ test "slice string literal has correct type" {...@@ -577,10 +571,6 @@ test "slice string literal has correct type" {
577 comptime expect(@TypeOf(array[runtime_zero..]) == []const i32);571 comptime expect(@TypeOf(array[runtime_zero..]) == []const i32);
578}572}
579573
580test "pointer child field" {
581 expect((*u32).Child == u32);
582}
583
584test "struct inside function" {574test "struct inside function" {
585 testStructInFn();575 testStructInFn();
586 comptime testStructInFn();576 comptime testStructInFn();
test/stage1/behavior/reflection.zig+7-15
...@@ -2,23 +2,15 @@ const expect = @import("std").testing.expect;...@@ -2,23 +2,15 @@ const expect = @import("std").testing.expect;
2const mem = @import("std").mem;2const mem = @import("std").mem;
3const reflection = @This();3const reflection = @This();
44
5test "reflection: array, pointer, optional, error union type child" {
6 comptime {
7 expect(([10]u8).Child == u8);
8 expect((*u8).Child == u8);
9 expect((anyerror!u8).Payload == u8);
10 expect((?u8).Child == u8);
11 }
12}
13
14test "reflection: function return type, var args, and param types" {5test "reflection: function return type, var args, and param types" {
15 comptime {6 comptime {
16 expect(@TypeOf(dummy).ReturnType == i32);7 const info = @typeInfo(@TypeOf(dummy)).Fn;
17 expect(!@TypeOf(dummy).is_var_args);8 expect(info.return_type.? == i32);
18 expect(@TypeOf(dummy).arg_count == 3);9 expect(!info.is_var_args);
19 expect(@typeInfo(@TypeOf(dummy)).Fn.args[0].arg_type.? == bool);10 expect(info.args.len == 3);
20 expect(@typeInfo(@TypeOf(dummy)).Fn.args[1].arg_type.? == i32);11 expect(info.args[0].arg_type.? == bool);
21 expect(@typeInfo(@TypeOf(dummy)).Fn.args[2].arg_type.? == f32);12 expect(info.args[1].arg_type.? == i32);
13 expect(info.args[2].arg_type.? == f32);
22 }14 }
23}15}
2416