authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 19:56:37-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-05-26 19:56:37-04:00
log2b42e910bf4696032158cc7ae268d3c69d699f70
treed00255e0c8d3a857e62777524f4271edbaa69c75
parent44a049e01eef654fee82a1ee4e1aaf37447319ce
signature Commit is signed but in an unrecognized format.

behavior tests passing on Linux


13 files changed, 119 insertions(+), 81 deletions(-)

std/c.zig+6-3
...@@ -1,4 +1,6 @@...@@ -1,4 +1,6 @@
1const builtin = @import("builtin");1const builtin = @import("builtin");
2const std = @import("std");
3const page_size = std.mem.page_size;
24
3pub use @import("os/bits.zig");5pub use @import("os/bits.zig");
46
...@@ -33,7 +35,7 @@ pub extern "c" fn close(fd: fd_t) c_int;...@@ -33,7 +35,7 @@ pub extern "c" fn close(fd: fd_t) c_int;
33pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;35pub extern "c" fn fstat(fd: fd_t, buf: *Stat) c_int;
34pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;36pub extern "c" fn @"fstat$INODE64"(fd: fd_t, buf: *Stat) c_int;
35pub extern "c" fn lseek(fd: fd_t, offset: isize, whence: c_int) isize;37pub extern "c" fn lseek(fd: fd_t, offset: isize, whence: c_int) isize;
36pub extern "c" fn open(path: [*]const u8, oflag: c_int, ...) c_int;38pub extern "c" fn open(path: [*]const u8, oflag: c_uint, ...) c_int;
37pub extern "c" fn raise(sig: c_int) c_int;39pub extern "c" fn raise(sig: c_int) c_int;
38pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;40pub extern "c" fn read(fd: fd_t, buf: [*]u8, nbyte: usize) isize;
39pub extern "c" fn pread(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize;41pub extern "c" fn pread(fd: fd_t, buf: [*]u8, nbyte: usize, offset: u64) isize;
...@@ -42,8 +44,9 @@ pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec, iovcnt: c_int, offset:...@@ -42,8 +44,9 @@ pub extern "c" fn pwritev(fd: c_int, iov: [*]const iovec, iovcnt: c_int, offset:
42pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;44pub extern "c" fn stat(noalias path: [*]const u8, noalias buf: *Stat) c_int;
43pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;45pub extern "c" fn write(fd: fd_t, buf: [*]const u8, nbyte: usize) isize;
44pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: u64) isize;46pub extern "c" fn pwrite(fd: fd_t, buf: [*]const u8, nbyte: usize, offset: u64) isize;
45pub extern "c" fn mmap(addr: ?*c_void, len: usize, prot: c_int, flags: c_int, fd: fd_t, offset: isize) usize;47pub extern "c" fn mmap(addr: ?*align(page_size) c_void, len: usize, prot: c_uint, flags: c_uint, fd: fd_t, offset: isize) *c_void;
46pub extern "c" fn munmap(addr: ?*c_void, len: usize) c_int;48pub extern "c" fn munmap(addr: *align(page_size) c_void, len: usize) c_int;
49pub extern "c" fn mprotect(addr: *align(page_size) c_void, len: usize, prot: c_uint) c_int;
47pub extern "c" fn unlink(path: [*]const u8) c_int;50pub extern "c" fn unlink(path: [*]const u8) c_int;
48pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;51pub extern "c" fn getcwd(buf: [*]u8, size: usize) ?[*]u8;
49pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_int, options: c_int) c_int;52pub extern "c" fn waitpid(pid: c_int, stat_loc: *c_int, options: c_int) c_int;
std/debug.zig+3-4
...@@ -1011,7 +1011,7 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {...@@ -1011,7 +1011,7 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {
1011 S.self_exe_file = try fs.openSelfExe();1011 S.self_exe_file = try fs.openSelfExe();
1012 errdefer S.self_exe_file.close();1012 errdefer S.self_exe_file.close();
10131013
1014 const self_exe_mmap_len = try S.self_exe_file.getEndPos();1014 const self_exe_mmap_len = mem.alignForward(try S.self_exe_file.getEndPos(), mem.page_size);
1015 const self_exe_mmap = try os.mmap(1015 const self_exe_mmap = try os.mmap(
1016 null,1016 null,
1017 self_exe_mmap_len,1017 self_exe_mmap_len,
...@@ -1020,10 +1020,9 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {...@@ -1020,10 +1020,9 @@ fn openSelfDebugInfoPosix(allocator: *mem.Allocator) !DwarfInfo {
1020 S.self_exe_file.handle,1020 S.self_exe_file.handle,
1021 0,1021 0,
1022 );1022 );
1023 errdefer os.munmap(self_exe_mmap, self_exe_mmap_len);1023 errdefer os.munmap(self_exe_mmap);
10241024
1025 const file_mmap_slice = @intToPtr([*]const u8, self_exe_mmap)[0..self_exe_mmap_len];1025 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(self_exe_mmap);
1026 S.self_exe_mmap_seekable = io.SliceSeekableInStream.init(file_mmap_slice);
10271026
1028 return openElfDebugInfo(1027 return openElfDebugInfo(
1029 allocator,1028 allocator,
std/fs.zig+2-2
...@@ -595,8 +595,8 @@ pub const Dir = struct {...@@ -595,8 +595,8 @@ pub const Dir = struct {
595 }595 }
596596
597 while (true) {597 while (true) {
598 const rc = os.system.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);598 const rc = os.linux.getdents64(self.handle.fd, self.handle.buf.ptr, self.handle.buf.len);
599 switch (os.errno(rc)) {599 switch (os.linux.getErrno(rc)) {
600 0 => {},600 0 => {},
601 os.EBADF => unreachable,601 os.EBADF => unreachable,
602 os.EFAULT => unreachable,602 os.EFAULT => unreachable,
std/heap.zig+16-13
...@@ -104,35 +104,36 @@ pub const DirectAllocator = struct {...@@ -104,35 +104,36 @@ pub const DirectAllocator = struct {
104 }104 }
105105
106 const alloc_size = if (alignment <= mem.page_size) n else n + alignment;106 const alloc_size = if (alignment <= mem.page_size) n else n + alignment;
107 const addr = os.mmap(107 const slice = os.mmap(
108 null,108 null,
109 alloc_size,109 mem.alignForward(alloc_size, mem.page_size),
110 os.PROT_READ | os.PROT_WRITE,110 os.PROT_READ | os.PROT_WRITE,
111 os.MAP_PRIVATE | os.MAP_ANONYMOUS,111 os.MAP_PRIVATE | os.MAP_ANONYMOUS,
112 -1,112 -1,
113 0,113 0,
114 ) catch return error.OutOfMemory;114 ) catch return error.OutOfMemory;
115 if (alloc_size == n) return @intToPtr([*]u8, addr)[0..n];115 if (alloc_size == n) return slice;
116116
117 const aligned_addr = mem.alignForward(addr, alignment);117 const aligned_addr = mem.alignForward(@ptrToInt(slice.ptr), alignment);
118118
119 // Unmap the extra bytes that were only requested in order to guarantee119 // Unmap the extra bytes that were only requested in order to guarantee
120 // that the range of memory we were provided had a proper alignment in120 // that the range of memory we were provided had a proper alignment in
121 // it somewhere. The extra bytes could be at the beginning, or end, or both.121 // it somewhere. The extra bytes could be at the beginning, or end, or both.
122 const unused_start_len = aligned_addr - addr;122 const unused_start_len = aligned_addr - @ptrToInt(slice.ptr);
123 if (unused_start_len != 0) {123 if (unused_start_len != 0) {
124 os.munmap(addr, unused_start_len);124 os.munmap(slice[0..unused_start_len]);
125 }125 }
126 const aligned_end_addr = std.mem.alignForward(aligned_addr + n, mem.page_size);126 const aligned_end_addr = mem.alignForward(aligned_addr + n, mem.page_size);
127 const unused_end_len = addr + alloc_size - aligned_end_addr;127 const unused_end_len = @ptrToInt(slice.ptr) + slice.len - aligned_end_addr;
128 if (unused_end_len != 0) {128 if (unused_end_len != 0) {
129 os.munmap(aligned_end_addr, unused_end_len);129 os.munmap(@intToPtr([*]align(mem.page_size) u8, aligned_end_addr)[0..unused_end_len]);
130 }130 }
131131
132 return @intToPtr([*]u8, aligned_addr)[0..n];132 return @intToPtr([*]u8, aligned_addr)[0..n];
133 }133 }
134134
135 fn shrink(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {135 fn shrink(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) []u8 {
136 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
136 if (os.windows.is_the_target) {137 if (os.windows.is_the_target) {
137 const w = os.windows;138 const w = os.windows;
138 if (new_size == 0) {139 if (new_size == 0) {
...@@ -165,12 +166,14 @@ pub const DirectAllocator = struct {...@@ -165,12 +166,14 @@ pub const DirectAllocator = struct {
165 const new_addr_end = base_addr + new_size;166 const new_addr_end = base_addr + new_size;
166 const new_addr_end_rounded = mem.alignForward(new_addr_end, mem.page_size);167 const new_addr_end_rounded = mem.alignForward(new_addr_end, mem.page_size);
167 if (old_addr_end > new_addr_end_rounded) {168 if (old_addr_end > new_addr_end_rounded) {
168 os.munmap(new_addr_end_rounded, old_addr_end - new_addr_end_rounded);169 const ptr = @intToPtr([*]align(mem.page_size) u8, new_addr_end_rounded);
170 os.munmap(ptr[0 .. old_addr_end - new_addr_end_rounded]);
169 }171 }
170 return old_mem[0..new_size];172 return old_mem[0..new_size];
171 }173 }
172174
173 fn realloc(allocator: *Allocator, old_mem: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {175 fn realloc(allocator: *Allocator, old_mem_unaligned: []u8, old_align: u29, new_size: usize, new_align: u29) ![]u8 {
176 const old_mem = @alignCast(mem.page_size, old_mem_unaligned);
174 if (os.windows.is_the_target) {177 if (os.windows.is_the_target) {
175 if (old_mem.len == 0) {178 if (old_mem.len == 0) {
176 return alloc(allocator, new_size, new_align);179 return alloc(allocator, new_size, new_align);
...@@ -231,7 +234,7 @@ pub const DirectAllocator = struct {...@@ -231,7 +234,7 @@ pub const DirectAllocator = struct {
231 const result = try alloc(allocator, new_size, new_align);234 const result = try alloc(allocator, new_size, new_align);
232 if (old_mem.len != 0) {235 if (old_mem.len != 0) {
233 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));236 @memcpy(result.ptr, old_mem.ptr, std.math.min(old_mem.len, result.len));
234 os.munmap(@ptrToInt(old_mem.ptr), old_mem.len);237 os.munmap(old_mem);
235 }238 }
236 return result;239 return result;
237 }240 }
std/io.zig+3-3
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
3const Os = builtin.Os;
4const c = std.c;3const c = std.c;
54
6const math = std.math;5const math = std.math;
7const debug = std.debug;6const debug = std.debug;
8const assert = debug.assert;7const assert = debug.assert;
9const os = std.os;8const os = std.os;
9const fs = std.fs;
10const mem = std.mem;10const mem = std.mem;
11const meta = std.meta;11const meta = std.meta;
12const trait = meta.trait;12const trait = meta.trait;
...@@ -985,7 +985,7 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {...@@ -985,7 +985,7 @@ pub fn BitOutStream(endian: builtin.Endian, comptime Error: type) type {
985}985}
986986
987pub const BufferedAtomicFile = struct {987pub const BufferedAtomicFile = struct {
988 atomic_file: os.AtomicFile,988 atomic_file: fs.AtomicFile,
989 file_stream: File.OutStream,989 file_stream: File.OutStream,
990 buffered_stream: BufferedOutStream(File.WriteError),990 buffered_stream: BufferedOutStream(File.WriteError),
991 allocator: *mem.Allocator,991 allocator: *mem.Allocator,
...@@ -1001,7 +1001,7 @@ pub const BufferedAtomicFile = struct {...@@ -1001,7 +1001,7 @@ pub const BufferedAtomicFile = struct {
1001 };1001 };
1002 errdefer allocator.destroy(self);1002 errdefer allocator.destroy(self);
10031003
1004 self.atomic_file = try os.AtomicFile.init(dest_path, File.default_mode);1004 self.atomic_file = try fs.AtomicFile.init(dest_path, File.default_mode);
1005 errdefer self.atomic_file.deinit();1005 errdefer self.atomic_file.deinit();
10061006
1007 self.file_stream = self.atomic_file.file.outStream();1007 self.file_stream = self.atomic_file.file.outStream();
std/io/c_out_stream.zig+1-1
...@@ -37,7 +37,7 @@ pub const COutStream = struct {...@@ -37,7 +37,7 @@ pub const COutStream = struct {
37 os.ENOSPC => return error.NoSpaceLeft,37 os.ENOSPC => return error.NoSpaceLeft,
38 os.EPERM => return error.AccessDenied,38 os.EPERM => return error.AccessDenied,
39 os.EPIPE => return error.BrokenPipe,39 os.EPIPE => return error.BrokenPipe,
40 else => return os.unexpectedErrno(@intCast(usize, errno)),40 else => |err| return os.unexpectedErrno(@intCast(usize, err)),
41 }41 }
42 }42 }
43};43};
std/mem.zig+50-23
...@@ -585,14 +585,14 @@ pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian)...@@ -585,14 +585,14 @@ pub fn readIntSlice(comptime T: type, bytes: []const u8, endian: builtin.Endian)
585test "comptime read/write int" {585test "comptime read/write int" {
586 comptime {586 comptime {
587 var bytes: [2]u8 = undefined;587 var bytes: [2]u8 = undefined;
588 std.mem.writeIntLittle(u16, &bytes, 0x1234);588 writeIntLittle(u16, &bytes, 0x1234);
589 const result = std.mem.readIntBig(u16, &bytes);589 const result = readIntBig(u16, &bytes);
590 testing.expect(result == 0x3412);590 testing.expect(result == 0x3412);
591 }591 }
592 comptime {592 comptime {
593 var bytes: [2]u8 = undefined;593 var bytes: [2]u8 = undefined;
594 std.mem.writeIntBig(u16, &bytes, 0x1234);594 writeIntBig(u16, &bytes, 0x1234);
595 const result = std.mem.readIntLittle(u16, &bytes);595 const result = readIntLittle(u16, &bytes);
596 testing.expect(result == 0x3412);596 testing.expect(result == 0x3412);
597 }597 }
598}598}
...@@ -1053,7 +1053,7 @@ fn testReadIntImpl() void {...@@ -1053,7 +1053,7 @@ fn testReadIntImpl() void {
1053 }1053 }
1054}1054}
10551055
1056test "std.mem.writeIntSlice" {1056test "writeIntSlice" {
1057 testWriteIntImpl();1057 testWriteIntImpl();
1058 comptime testWriteIntImpl();1058 comptime testWriteIntImpl();
1059}1059}
...@@ -1184,7 +1184,7 @@ pub fn reverse(comptime T: type, items: []T) void {...@@ -1184,7 +1184,7 @@ pub fn reverse(comptime T: type, items: []T) void {
1184 }1184 }
1185}1185}
11861186
1187test "std.mem.reverse" {1187test "reverse" {
1188 var arr = []i32{1188 var arr = []i32{
1189 5,1189 5,
1190 3,1190 3,
...@@ -1211,7 +1211,7 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {...@@ -1211,7 +1211,7 @@ pub fn rotate(comptime T: type, items: []T, amount: usize) void {
1211 reverse(T, items);1211 reverse(T, items);
1212}1212}
12131213
1214test "std.mem.rotate" {1214test "rotate" {
1215 var arr = []i32{1215 var arr = []i32{
1216 5,1216 5,
1217 3,1217 3,
...@@ -1296,14 +1296,14 @@ pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr)) {...@@ -1296,14 +1296,14 @@ pub fn asBytes(ptr: var) AsBytesReturnType(@typeOf(ptr)) {
1296 return @ptrCast(AsBytesReturnType(P), ptr);1296 return @ptrCast(AsBytesReturnType(P), ptr);
1297}1297}
12981298
1299test "std.mem.asBytes" {1299test "asBytes" {
1300 const deadbeef = u32(0xDEADBEEF);1300 const deadbeef = u32(0xDEADBEEF);
1301 const deadbeef_bytes = switch (builtin.endian) {1301 const deadbeef_bytes = switch (builtin.endian) {
1302 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",1302 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
1303 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",1303 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
1304 };1304 };
13051305
1306 testing.expect(std.mem.eql(u8, asBytes(&deadbeef), deadbeef_bytes));1306 testing.expect(eql(u8, asBytes(&deadbeef), deadbeef_bytes));
13071307
1308 var codeface = u32(0xC0DEFACE);1308 var codeface = u32(0xC0DEFACE);
1309 for (asBytes(&codeface).*) |*b|1309 for (asBytes(&codeface).*) |*b|
...@@ -1323,7 +1323,7 @@ test "std.mem.asBytes" {...@@ -1323,7 +1323,7 @@ test "std.mem.asBytes" {
1323 .c = 0xDE,1323 .c = 0xDE,
1324 .d = 0xA1,1324 .d = 0xA1,
1325 };1325 };
1326 testing.expect(std.mem.eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));1326 testing.expect(eql(u8, asBytes(&inst), "\xBE\xEF\xDE\xA1"));
1327}1327}
13281328
1329///Given any value, returns a copy of its bytes in an array.1329///Given any value, returns a copy of its bytes in an array.
...@@ -1331,17 +1331,17 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {...@@ -1331,17 +1331,17 @@ pub fn toBytes(value: var) [@sizeOf(@typeOf(value))]u8 {
1331 return asBytes(&value).*;1331 return asBytes(&value).*;
1332}1332}
13331333
1334test "std.mem.toBytes" {1334test "toBytes" {
1335 var my_bytes = toBytes(u32(0x12345678));1335 var my_bytes = toBytes(u32(0x12345678));
1336 switch (builtin.endian) {1336 switch (builtin.endian) {
1337 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x12\x34\x56\x78")),1337 builtin.Endian.Big => testing.expect(eql(u8, my_bytes, "\x12\x34\x56\x78")),
1338 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x78\x56\x34\x12")),1338 builtin.Endian.Little => testing.expect(eql(u8, my_bytes, "\x78\x56\x34\x12")),
1339 }1339 }
13401340
1341 my_bytes[0] = '\x99';1341 my_bytes[0] = '\x99';
1342 switch (builtin.endian) {1342 switch (builtin.endian) {
1343 builtin.Endian.Big => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x34\x56\x78")),1343 builtin.Endian.Big => testing.expect(eql(u8, my_bytes, "\x99\x34\x56\x78")),
1344 builtin.Endian.Little => testing.expect(std.mem.eql(u8, my_bytes, "\x99\x56\x34\x12")),1344 builtin.Endian.Little => testing.expect(eql(u8, my_bytes, "\x99\x56\x34\x12")),
1345 }1345 }
1346}1346}
13471347
...@@ -1363,7 +1363,7 @@ pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typ...@@ -1363,7 +1363,7 @@ pub fn bytesAsValue(comptime T: type, bytes: var) BytesAsValueReturnType(T, @typ
1363 return @ptrCast(BytesAsValueReturnType(T, @typeOf(bytes)), bytes);1363 return @ptrCast(BytesAsValueReturnType(T, @typeOf(bytes)), bytes);
1364}1364}
13651365
1366test "std.mem.bytesAsValue" {1366test "bytesAsValue" {
1367 const deadbeef = u32(0xDEADBEEF);1367 const deadbeef = u32(0xDEADBEEF);
1368 const deadbeef_bytes = switch (builtin.endian) {1368 const deadbeef_bytes = switch (builtin.endian) {
1369 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",1369 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
...@@ -1405,7 +1405,7 @@ test "std.mem.bytesAsValue" {...@@ -1405,7 +1405,7 @@ test "std.mem.bytesAsValue" {
1405pub fn bytesToValue(comptime T: type, bytes: var) T {1405pub fn bytesToValue(comptime T: type, bytes: var) T {
1406 return bytesAsValue(T, &bytes).*;1406 return bytesAsValue(T, &bytes).*;
1407}1407}
1408test "std.mem.bytesToValue" {1408test "bytesToValue" {
1409 const deadbeef_bytes = switch (builtin.endian) {1409 const deadbeef_bytes = switch (builtin.endian) {
1410 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",1410 builtin.Endian.Big => "\xDE\xAD\xBE\xEF",
1411 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",1411 builtin.Endian.Little => "\xEF\xBE\xAD\xDE",
...@@ -1430,25 +1430,25 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA...@@ -1430,25 +1430,25 @@ pub fn subArrayPtr(ptr: var, comptime start: usize, comptime length: usize) SubA
1430 return @ptrCast(ReturnType, &ptr[start]);1430 return @ptrCast(ReturnType, &ptr[start]);
1431}1431}
14321432
1433test "std.mem.subArrayPtr" {1433test "subArrayPtr" {
1434 const a1 = "abcdef";1434 const a1 = "abcdef";
1435 const sub1 = subArrayPtr(&a1, 2, 3);1435 const sub1 = subArrayPtr(&a1, 2, 3);
1436 testing.expect(std.mem.eql(u8, sub1.*, "cde"));1436 testing.expect(eql(u8, sub1.*, "cde"));
14371437
1438 var a2 = "abcdef";1438 var a2 = "abcdef";
1439 var sub2 = subArrayPtr(&a2, 2, 3);1439 var sub2 = subArrayPtr(&a2, 2, 3);
14401440
1441 testing.expect(std.mem.eql(u8, sub2, "cde"));1441 testing.expect(eql(u8, sub2, "cde"));
1442 sub2[1] = 'X';1442 sub2[1] = 'X';
1443 testing.expect(std.mem.eql(u8, a2, "abcXef"));1443 testing.expect(eql(u8, a2, "abcXef"));
1444}1444}
14451445
1446/// Round an address up to the nearest aligned address1446/// Round an address up to the nearest aligned address
1447pub fn alignForward(addr: usize, alignment: usize) usize {1447pub fn alignForward(addr: usize, alignment: usize) usize {
1448 return (addr + alignment - 1) & ~(alignment - 1);1448 return alignBackward(addr + (alignment - 1), alignment);
1449}1449}
14501450
1451test "std.mem.alignForward" {1451test "alignForward" {
1452 testing.expect(alignForward(1, 1) == 1);1452 testing.expect(alignForward(1, 1) == 1);
1453 testing.expect(alignForward(2, 1) == 2);1453 testing.expect(alignForward(2, 1) == 2);
1454 testing.expect(alignForward(1, 2) == 2);1454 testing.expect(alignForward(1, 2) == 2);
...@@ -1462,3 +1462,30 @@ test "std.mem.alignForward" {...@@ -1462,3 +1462,30 @@ test "std.mem.alignForward" {
1462 testing.expect(alignForward(16, 8) == 16);1462 testing.expect(alignForward(16, 8) == 16);
1463 testing.expect(alignForward(17, 8) == 24);1463 testing.expect(alignForward(17, 8) == 24);
1464}1464}
1465
1466pub fn alignBackward(addr: usize, alignment: usize) usize {
1467 // 000010000 // example addr
1468 // 000001111 // subtract 1
1469 // 111110000 // binary not
1470 return addr & ~(alignment - 1);
1471}
1472
1473pub fn isAligned(addr: usize, alignment: usize) bool {
1474 return alignBackward(addr, alignment) == addr;
1475}
1476
1477test "isAligned" {
1478 testing.expect(isAligned(0, 4));
1479 testing.expect(isAligned(1, 1));
1480 testing.expect(isAligned(2, 1));
1481 testing.expect(isAligned(2, 2));
1482 testing.expect(!isAligned(2, 4));
1483 testing.expect(isAligned(3, 1));
1484 testing.expect(!isAligned(3, 2));
1485 testing.expect(!isAligned(3, 4));
1486 testing.expect(isAligned(4, 4));
1487 testing.expect(isAligned(4, 2));
1488 testing.expect(isAligned(4, 1));
1489 testing.expect(!isAligned(4, 8));
1490 testing.expect(!isAligned(4, 16));
1491}
std/os.zig+27-21
...@@ -251,7 +251,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {...@@ -251,7 +251,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
251 // Linux can return EINVAL when read amount is > 0x7ffff000251 // Linux can return EINVAL when read amount is > 0x7ffff000
252 // See https://github.com/ziglang/zig/pull/743#issuecomment-363158274252 // See https://github.com/ziglang/zig/pull/743#issuecomment-363158274
253 // TODO audit this. Shawn Landden says that this is not actually true.253 // TODO audit this. Shawn Landden says that this is not actually true.
254 // if this logic should stay, move it to std.os.linux.sys254 // if this logic should stay, move it to std.os.linux
255 const max_buf_len = 0x7ffff000;255 const max_buf_len = 0x7ffff000;
256256
257 var index: usize = 0;257 var index: usize = 0;
...@@ -260,8 +260,9 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {...@@ -260,8 +260,9 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize {
260 const rc = system.read(fd, buf.ptr + index, want_to_read);260 const rc = system.read(fd, buf.ptr + index, want_to_read);
261 switch (errno(rc)) {261 switch (errno(rc)) {
262 0 => {262 0 => {
263 index += rc;263 const amt_read = @intCast(usize, rc);
264 if (rc == want_to_read) continue;264 index += amt_read;
265 if (amt_read == want_to_read) continue;
265 // Read returned less than buf.len.266 // Read returned less than buf.len.
266 return index;267 return index;
267 },268 },
...@@ -374,7 +375,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {...@@ -374,7 +375,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
374 // Linux can return EINVAL when write amount is > 0x7ffff000375 // Linux can return EINVAL when write amount is > 0x7ffff000
375 // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856376 // See https://github.com/ziglang/zig/pull/743#issuecomment-363165856
376 // TODO audit this. Shawn Landden says that this is not actually true.377 // TODO audit this. Shawn Landden says that this is not actually true.
377 // if this logic should stay, move it to std.os.linux.sys378 // if this logic should stay, move it to std.os.linux
378 const max_bytes_len = 0x7ffff000;379 const max_bytes_len = 0x7ffff000;
379380
380 var index: usize = 0;381 var index: usize = 0;
...@@ -383,7 +384,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {...@@ -383,7 +384,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!void {
383 const rc = system.write(fd, bytes.ptr + index, amt_to_write);384 const rc = system.write(fd, bytes.ptr + index, amt_to_write);
384 switch (errno(rc)) {385 switch (errno(rc)) {
385 0 => {386 0 => {
386 index += rc;387 index += @intCast(usize, rc);
387 continue;388 continue;
388 },389 },
389 EINTR => continue,390 EINTR => continue,
...@@ -1863,14 +1864,10 @@ pub const MProtectError = error{...@@ -1863,14 +1864,10 @@ pub const MProtectError = error{
1863 Unexpected,1864 Unexpected,
1864};1865};
18651866
1866/// address and length must be page-aligned1867/// `memory.len` must be page-aligned.
1867pub fn mprotect(address: usize, length: usize, protection: u32) MProtectError!void {1868pub fn mprotect(memory: [*]align(mem.page_size) u8, protection: u32) MProtectError!void {
1868 const negative_page_size = @bitCast(usize, -isize(mem.page_size));1869 assert(mem.isAligned(memory.len, mem.page_size));
1869 const aligned_address = address & negative_page_size;1870 switch (errno(system.mprotect(memory.ptr, memory.len, protection))) {
1870 const aligned_end = (address + length + mem.page_size - 1) & negative_page_size;
1871 assert(address == aligned_address);
1872 assert(length == aligned_end - aligned_address);
1873 switch (errno(system.mprotect(address, length, protection))) {
1874 0 => return,1871 0 => return,
1875 EINVAL => unreachable,1872 EINVAL => unreachable,
1876 EACCES => return error.AccessDenied,1873 EACCES => return error.AccessDenied,
...@@ -1906,17 +1903,26 @@ pub const MMapError = error{...@@ -1906,17 +1903,26 @@ pub const MMapError = error{
19061903
1907/// Map files or devices into memory.1904/// Map files or devices into memory.
1908/// Use of a mapped region can result in these signals:1905/// Use of a mapped region can result in these signals:
1906/// `length` must be page-aligned.
1909/// * SIGSEGV - Attempted write into a region mapped as read-only.1907/// * SIGSEGV - Attempted write into a region mapped as read-only.
1910/// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file1908/// * SIGBUS - Attempted access to a portion of the buffer that does not correspond to the file
1911pub fn mmap(address: ?[*]u8, length: usize, prot: u32, flags: u32, fd: fd_t, offset: isize) MMapError!usize {1909pub fn mmap(
1910 ptr: ?[*]align(mem.page_size) u8,
1911 length: usize,
1912 prot: u32,
1913 flags: u32,
1914 fd: fd_t,
1915 offset: isize,
1916) MMapError![]align(mem.page_size) u8 {
1917 assert(mem.isAligned(length, mem.page_size));
1912 const err = if (builtin.link_libc) blk: {1918 const err = if (builtin.link_libc) blk: {
1913 const rc = system.mmap(address, length, prot, flags, fd, offset);1919 const rc = std.c.mmap(ptr, length, prot, flags, fd, offset);
1914 if (rc != system.MMAP_FAILED) return rc;1920 if (rc != MAP_FAILED) return @ptrCast([*]align(mem.page_size) u8, @alignCast(mem.page_size, rc))[0..length];
1915 break :blk system._errno().*;1921 break :blk @intCast(usize, system._errno().*);
1916 } else blk: {1922 } else blk: {
1917 const rc = system.mmap(address, length, prot, flags, fd, offset);1923 const rc = system.mmap(ptr, length, prot, flags, fd, offset);
1918 const err = errno(rc);1924 const err = errno(rc);
1919 if (err == 0) return rc;1925 if (err == 0) return @intToPtr([*]align(mem.page_size) u8, rc)[0..length];
1920 break :blk err;1926 break :blk err;
1921 };1927 };
1922 switch (err) {1928 switch (err) {
...@@ -1940,8 +1946,8 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: u32, flags: u32, fd: fd_t, off...@@ -1940,8 +1946,8 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: u32, flags: u32, fd: fd_t, off
1940/// Zig's munmap function does not, for two reasons:1946/// Zig's munmap function does not, for two reasons:
1941/// * It violates the Zig principle that resource deallocation must succeed.1947/// * It violates the Zig principle that resource deallocation must succeed.
1942/// * The Windows function, VirtualFree, has this restriction.1948/// * The Windows function, VirtualFree, has this restriction.
1943pub fn munmap(address: usize, length: usize) void {1949pub fn munmap(memory: []align(mem.page_size) u8) void {
1944 switch (errno(system.munmap(address, length))) {1950 switch (errno(system.munmap(memory.ptr, memory.len))) {
1945 0 => return,1951 0 => return,
1946 EINVAL => unreachable, // Invalid parameters.1952 EINVAL => unreachable, // Invalid parameters.
1947 ENOMEM => unreachable, // Attempted to unmap a region in the middle of an existing mapping.1953 ENOMEM => unreachable, // Attempted to unmap a region in the middle of an existing mapping.
std/os/bits/linux.zig+2-1
...@@ -1,4 +1,5 @@...@@ -1,4 +1,5 @@
1const std = @import("../../std.zig");1const std = @import("../../std.zig");
2const maxInt = std.math.maxInt;
23
3pub use @import("linux/errno.zig");4pub use @import("linux/errno.zig");
4pub use switch (builtin.arch) {5pub use switch (builtin.arch) {
...@@ -39,7 +40,7 @@ pub const PROT_EXEC = 4;...@@ -39,7 +40,7 @@ pub const PROT_EXEC = 4;
39pub const PROT_GROWSDOWN = 0x01000000;40pub const PROT_GROWSDOWN = 0x01000000;
40pub const PROT_GROWSUP = 0x02000000;41pub const PROT_GROWSUP = 0x02000000;
4142
42pub const MAP_FAILED = maxInt(usize);43pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
43pub const MAP_SHARED = 0x01;44pub const MAP_SHARED = 0x01;
44pub const MAP_PRIVATE = 0x02;45pub const MAP_PRIVATE = 0x02;
45pub const MAP_TYPE = 0x0f;46pub const MAP_TYPE = 0x0f;
std/os/linux.zig+4-4
...@@ -173,12 +173,12 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of...@@ -173,12 +173,12 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: u32, fd: i32, of
173 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));173 return syscall6(SYS_mmap, @ptrToInt(address), length, prot, flags, @bitCast(usize, isize(fd)), @bitCast(usize, offset));
174}174}
175175
176pub fn mprotect(address: usize, length: usize, protection: usize) usize {176pub fn mprotect(address: [*]const u8, length: usize, protection: usize) usize {
177 return syscall3(SYS_mprotect, address, length, protection);177 return syscall3(SYS_mprotect, @ptrToInt(address), length, protection);
178}178}
179179
180pub fn munmap(address: usize, length: usize) usize {180pub fn munmap(address: [*]const u8, length: usize) usize {
181 return syscall2(SYS_munmap, address, length);181 return syscall2(SYS_munmap, @ptrToInt(address), length);
182}182}
183183
184pub fn read(fd: i32, buf: [*]u8, count: usize) usize {184pub fn read(fd: i32, buf: [*]u8, count: usize) usize {
std/os/linux/tls.zig+2-2
...@@ -237,7 +237,7 @@ pub fn allocateTLS(size: usize) usize {...@@ -237,7 +237,7 @@ pub fn allocateTLS(size: usize) usize {
237 return @ptrToInt(&main_thread_tls_buffer);237 return @ptrToInt(&main_thread_tls_buffer);
238 }238 }
239239
240 const addr = os.mmap(240 const slice = os.mmap(
241 null,241 null,
242 size,242 size,
243 os.PROT_READ | os.PROT_WRITE,243 os.PROT_READ | os.PROT_WRITE,
...@@ -246,5 +246,5 @@ pub fn allocateTLS(size: usize) usize {...@@ -246,5 +246,5 @@ pub fn allocateTLS(size: usize) usize {
246 0,246 0,
247 ) catch @panic("out of memory");247 ) catch @panic("out of memory");
248248
249 return addr;249 return @ptrToInt(slice.ptr);
250}250}
test/stage1/behavior/cast.zig+1-1
...@@ -318,7 +318,7 @@ fn testCastPtrOfArrayToSliceAndPtr() void {...@@ -318,7 +318,7 @@ fn testCastPtrOfArrayToSliceAndPtr() void {
318test "cast *[1][*]const u8 to [*]const ?[*]const u8" {318test "cast *[1][*]const u8 to [*]const ?[*]const u8" {
319 const window_name = [1][*]const u8{c"window name"};319 const window_name = [1][*]const u8{c"window name"};
320 const x: [*]const ?[*]const u8 = &window_name;320 const x: [*]const ?[*]const u8 = &window_name;
321 expect(mem.eql(u8, std.cstr.toSliceConst(x[0].?), "window name"));321 expect(mem.eql(u8, std.mem.toSliceConst(u8, x[0].?), "window name"));
322}322}
323323
324test "@intCast comptime_int" {324test "@intCast comptime_int" {
test/stage1/behavior/misc.zig+2-3
...@@ -2,7 +2,6 @@ const std = @import("std");...@@ -2,7 +2,6 @@ const std = @import("std");
2const expect = std.testing.expect;2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;3const expectEqualSlices = std.testing.expectEqualSlices;
4const mem = std.mem;4const mem = std.mem;
5const cstr = std.cstr;
6const builtin = @import("builtin");5const builtin = @import("builtin");
7const maxInt = std.math.maxInt;6const maxInt = std.math.maxInt;
87
...@@ -210,7 +209,7 @@ test "multiline C string" {...@@ -210,7 +209,7 @@ test "multiline C string" {
210 c\\three209 c\\three
211 ;210 ;
212 const s2 = c"one\ntwo)\nthree";211 const s2 = c"one\ntwo)\nthree";
213 expect(cstr.cmp(s1, s2) == 0);212 expect(std.cstr.cmp(s1, s2) == 0);
214}213}
215214
216test "type equality" {215test "type equality" {
...@@ -363,7 +362,7 @@ test "C string concatenation" {...@@ -363,7 +362,7 @@ test "C string concatenation" {
363 const a = c"OK" ++ c" IT " ++ c"WORKED";362 const a = c"OK" ++ c" IT " ++ c"WORKED";
364 const b = c"OK IT WORKED";363 const b = c"OK IT WORKED";
365364
366 const len = cstr.len(b);365 const len = mem.len(u8, b);
367 const len_with_null = len + 1;366 const len_with_null = len + 1;
368 {367 {
369 var i: u32 = 0;368 var i: u32 = 0;