From bd7eab573a5e5f1366cd5dc3639fef28c4acb32a Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Tue, 6 Oct 2020 12:08:12 +0200 Subject: [PATCH 1/2] Fix building the zig compiler for 32-bit targets --- lib/std/fs/file.zig | 21 +++++++++++---------- src/link/Elf.zig | 4 ++-- src/link/MachO.zig | 2 +- src/main.zig | 4 ++-- src/value.zig | 2 +- 5 files changed, 17 insertions(+), 16 deletions(-) diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index 8d4f5df2e8..e0795f4c1c 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -615,7 +615,7 @@ pub const File = struct { } } - pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!usize { + pub fn pwritev(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!usize { if (is_windows) { // TODO improve this to use WriteFileScatter if (iovecs.len == 0) return @as(usize, 0); @@ -632,11 +632,11 @@ pub const File = struct { /// The `iovecs` parameter is mutable because this function needs to mutate the fields in /// order to handle partial writes from the underlying OS layer. - pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: usize) PWriteError!void { + pub fn pwritevAll(self: File, iovecs: []os.iovec_const, offset: u64) PWriteError!void { if (iovecs.len == 0) return; var i: usize = 0; - var off: usize = 0; + var off: u64 = 0; while (true) { var amt = try self.pwritev(iovecs[i..], offset + off); off += amt; @@ -652,24 +652,25 @@ pub const File = struct { pub const CopyRangeError = os.CopyFileRangeError; - pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize { - return os.copy_file_range(in.handle, in_offset, out.handle, out_offset, len, 0); + pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!usize { + const adjusted_len = math.cast(usize, len) catch math.maxInt(usize); + return os.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); } /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it /// means the in file reached the end. Reaching the end of a file is not an error condition. - pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: usize) CopyRangeError!usize { - var total_bytes_copied: usize = 0; + pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!usize { + var total_bytes_copied: u64 = 0; var in_off = in_offset; var out_off = out_offset; while (total_bytes_copied < len) { - const amt_copied = try copyRange(in, in_off, out, out_off, len - total_bytes_copied); - if (amt_copied == 0) return total_bytes_copied; + const amt_copied = try copyRange(in, in_off, out, out_off, len); + if (amt_copied == 0) return @intCast(usize, total_bytes_copied); total_bytes_copied += amt_copied; in_off += amt_copied; out_off += amt_copied; } - return total_bytes_copied; + return @intCast(usize, total_bytes_copied); } pub const WriteFileOptions = struct { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 4be47ccdf7..3a847a623d 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2757,7 +2757,7 @@ fn writeSymbol(self: *Elf, index: usize) !void { if (needed_size > self.allocatedSize(syms_sect.sh_offset)) { // Move all the symbols to a new file location. const new_offset = self.findFreeSpace(needed_size, sym_align); - const existing_size = @as(u64, syms_sect.sh_info) * sym_size; + const existing_size = syms_sect.sh_info * sym_size; const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size); if (amt != existing_size) return error.InputOutput; syms_sect.sh_offset = new_offset; @@ -2911,7 +2911,7 @@ fn pwriteDbgLineNops( prev_padding_size: usize, buf: []const u8, next_padding_size: usize, - offset: usize, + offset: u64, ) !void { const tracy = trace(@src()); defer tracy.end(); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 1675c56b03..732ed1e8d9 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1267,7 +1267,7 @@ fn updateString(self: *MachO, old_str_off: u32, new_name: []const u8) !u32 { fn addPadding(self: *MachO, size: u64, file_offset: u64) !void { if (size == 0) return; - const buf = try self.base.allocator.alloc(u8, size); + const buf = try self.base.allocator.alloc(u8, @intCast(usize, size)); defer self.base.allocator.free(buf); mem.set(u8, buf[0..], 0); diff --git a/src/main.zig b/src/main.zig index 7564342739..0b75d479d8 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2541,7 +2541,7 @@ fn fmtPathFile( check_mode: bool, dir: fs.Dir, sub_path: []const u8, -) FmtError!void { +) (FmtError || error{Overflow})!void { const source_file = try dir.openFile(sub_path, .{}); var file_closed = false; errdefer if (!file_closed) source_file.close(); @@ -2554,7 +2554,7 @@ fn fmtPathFile( const source_code = source_file.readToEndAllocOptions( fmt.gpa, max_src_size, - stat.size, + try std.math.cast(usize, stat.size), @alignOf(u8), null, ) catch |err| switch (err) { diff --git a/src/value.zig b/src/value.zig index 6e38b1bed4..a99ea4c04b 100644 --- a/src/value.zig +++ b/src/value.zig @@ -842,7 +842,7 @@ pub const Value = extern union { .int_u64 => { const x = self.cast(Payload.Int_u64).?.int; if (x == 0) return 0; - return std.math.log2(x) + 1; + return @intCast(usize, std.math.log2(x) + 1); }, .int_i64 => { @panic("TODO implement i64 intBitCountTwosComp"); From b2b0bf0506e708e6b8c143eb438a84592310b5a9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 7 Oct 2020 00:39:13 -0700 Subject: [PATCH 2/2] fixups for the previous commit * std.fs.File.copyRange and copyRangeAll return u64 instead of usize - the returned value is how much of the `len` is transferred, so the types should match. This removes the need for an `@intCast`. * fix typo that removed a subtraction * Fix the size of codegen.AnyMCValue which gave me a compile error when I tried to build self-hosted for i386-linux. * restore the coercion to u64 of syms_sect.sh_info. We want to make sure the multiplication happens with 64 bits and not the smaller type used by the ELF format. * fix another offset parameter in link/Elf.zig to be u64 instead of usize * add a nice little TODO note to help out Jakub * FmtError already has FileTooBig in it; we just need to return it. --- lib/std/fs/file.zig | 13 +++++++------ src/codegen.zig | 2 +- src/link/Elf.zig | 4 ++-- src/link/MachO.zig | 4 ++++ src/main.zig | 4 ++-- 5 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/std/fs/file.zig b/lib/std/fs/file.zig index e0795f4c1c..bfa6dec3ed 100644 --- a/lib/std/fs/file.zig +++ b/lib/std/fs/file.zig @@ -652,25 +652,26 @@ pub const File = struct { pub const CopyRangeError = os.CopyFileRangeError; - pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!usize { + pub fn copyRange(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { const adjusted_len = math.cast(usize, len) catch math.maxInt(usize); - return os.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); + const result = try os.copy_file_range(in.handle, in_offset, out.handle, out_offset, adjusted_len, 0); + return result; } /// Returns the number of bytes copied. If the number read is smaller than `buffer.len`, it /// means the in file reached the end. Reaching the end of a file is not an error condition. - pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!usize { + pub fn copyRangeAll(in: File, in_offset: u64, out: File, out_offset: u64, len: u64) CopyRangeError!u64 { var total_bytes_copied: u64 = 0; var in_off = in_offset; var out_off = out_offset; while (total_bytes_copied < len) { - const amt_copied = try copyRange(in, in_off, out, out_off, len); - if (amt_copied == 0) return @intCast(usize, total_bytes_copied); + const amt_copied = try copyRange(in, in_off, out, out_off, len - total_bytes_copied); + if (amt_copied == 0) return total_bytes_copied; total_bytes_copied += amt_copied; in_off += amt_copied; out_off += amt_copied; } - return @intCast(usize, total_bytes_copied); + return total_bytes_copied; } pub const WriteFileOptions = struct { diff --git a/src/codegen.zig b/src/codegen.zig index 7dbbf7093e..70c97ca531 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -32,7 +32,7 @@ pub const BlockData = struct { /// comptime assert that makes sure we guessed correctly about the size. This only /// exists so that we can bitcast an arch-independent field to and from the real MCValue. pub const AnyMCValue = extern struct { - a: u64, + a: usize, b: u64, }; diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 3a847a623d..c62bb29f78 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -2757,7 +2757,7 @@ fn writeSymbol(self: *Elf, index: usize) !void { if (needed_size > self.allocatedSize(syms_sect.sh_offset)) { // Move all the symbols to a new file location. const new_offset = self.findFreeSpace(needed_size, sym_align); - const existing_size = syms_sect.sh_info * sym_size; + const existing_size = @as(u64, syms_sect.sh_info) * sym_size; const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size); if (amt != existing_size) return error.InputOutput; syms_sect.sh_offset = new_offset; @@ -2990,7 +2990,7 @@ fn pwriteDbgInfoNops( buf: []const u8, next_padding_size: usize, trailing_zero: bool, - offset: usize, + offset: u64, ) !void { const tracy = trace(@src()); defer tracy.end(); diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 732ed1e8d9..68307a5fc6 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1264,6 +1264,10 @@ fn updateString(self: *MachO, old_str_off: u32, new_name: []const u8) !u32 { return self.makeString(new_name); } +/// TODO This should not heap allocate, instead it should utilize a fixed size, statically allocated +/// global const array. You could even use pwritev to write the same buffer multiple times with only +/// 1 syscall if you needed to, for example, write 8192 bytes using a buffer of only 4096 bytes. +/// This size parameter should probably be a usize not u64. fn addPadding(self: *MachO, size: u64, file_offset: u64) !void { if (size == 0) return; diff --git a/src/main.zig b/src/main.zig index 0b75d479d8..b89ac3768e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -2541,7 +2541,7 @@ fn fmtPathFile( check_mode: bool, dir: fs.Dir, sub_path: []const u8, -) (FmtError || error{Overflow})!void { +) FmtError!void { const source_file = try dir.openFile(sub_path, .{}); var file_closed = false; errdefer if (!file_closed) source_file.close(); @@ -2554,7 +2554,7 @@ fn fmtPathFile( const source_code = source_file.readToEndAllocOptions( fmt.gpa, max_src_size, - try std.math.cast(usize, stat.size), + std.math.cast(usize, stat.size) catch return error.FileTooBig, @alignOf(u8), null, ) catch |err| switch (err) {