| author | |
| committer | |
| log | 4261fa3c49be715355c9623102bad0bf93d537a3 |
| tree | ba8da3ef0611a547fe67c61ed2d42d4ea67e6d2e |
| parent | 659c1bdeeebce7bf32e122be6a728fe727112c56 |
| signature |
10 files changed, 91 insertions(+), 59 deletions(-)
lib/std/heap.zig+4-4| ... | @@ -273,17 +273,17 @@ const WasmPageAllocator = struct { | ... | @@ -273,17 +273,17 @@ const WasmPageAllocator = struct { |
| 273 | if (new_end_index > num_pages * mem.page_size) { | 273 | if (new_end_index > num_pages * mem.page_size) { |
| 274 | const required_memory = new_end_index - (num_pages * mem.page_size); | 274 | const required_memory = new_end_index - (num_pages * mem.page_size); |
| 275 | 275 | ||
| 276 | var num_pages: usize = required_memory / mem.page_size; | 276 | var inner_num_pages: usize = required_memory / mem.page_size; |
| 277 | if (required_memory % mem.page_size != 0) { | 277 | if (required_memory % mem.page_size != 0) { |
| 278 | num_pages += 1; | 278 | inner_num_pages += 1; |
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | const prev_page = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, num_pages)); | 281 | const prev_page = @"llvm.wasm.memory.grow.i32"(0, @intCast(u32, inner_num_pages)); |
| 282 | if (prev_page == -1) { | 282 | if (prev_page == -1) { |
| 283 | return error.OutOfMemory; | 283 | return error.OutOfMemory; |
| 284 | } | 284 | } |
| 285 | 285 | ||
| 286 | num_pages += num_pages; | 286 | num_pages += inner_num_pages; |
| 287 | } | 287 | } |
| 288 | 288 | ||
| 289 | const result = start_ptr[adjusted_index..new_end_index]; | 289 | const result = start_ptr[adjusted_index..new_end_index]; |
lib/std/os.zig+43-1| ... | @@ -1527,7 +1527,22 @@ pub fn isatty(handle: fd_t) bool { | ... | @@ -1527,7 +1527,22 @@ pub fn isatty(handle: fd_t) bool { |
| 1527 | return system.isatty(handle) != 0; | 1527 | return system.isatty(handle) != 0; |
| 1528 | } | 1528 | } |
| 1529 | if (builtin.os == .wasi) { | 1529 | if (builtin.os == .wasi) { |
| 1530 | return system.isatty(handle); | 1530 | var statbuf: fdstat_t = undefined; |
| 1531 | const err = system.fd_fdstat_get(handle, &statbuf); | ||
| 1532 | if (err != 0) { | ||
| 1533 | // errno = err; | ||
| 1534 | return false; | ||
| 1535 | } | ||
| 1536 | |||
| 1537 | // A tty is a character device that we can't seek or tell on. | ||
| 1538 | if (statbuf.fs_filetype != FILETYPE_CHARACTER_DEVICE or | ||
| 1539 | (statbuf.fs_rights_base & (RIGHT_FD_SEEK | RIGHT_FD_TELL)) != 0) | ||
| 1540 | { | ||
| 1541 | // errno = ENOTTY; | ||
| 1542 | return false; | ||
| 1543 | } | ||
| 1544 | |||
| 1545 | return true; | ||
| 1531 | } | 1546 | } |
| 1532 | if (builtin.os == .linux) { | 1547 | if (builtin.os == .linux) { |
| 1533 | var wsz: linux.winsize = undefined; | 1548 | var wsz: linux.winsize = undefined; |
| ... | @@ -2720,6 +2735,20 @@ pub fn dl_iterate_phdr( | ... | @@ -2720,6 +2735,20 @@ pub fn dl_iterate_phdr( |
| 2720 | pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; | 2735 | pub const ClockGetTimeError = error{UnsupportedClock} || UnexpectedError; |
| 2721 | 2736 | ||
| 2722 | pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { | 2737 | pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { |
| 2738 | if (comptime std.Target.current.getOs() == .wasi) { | ||
| 2739 | var ts: timestamp_t = undefined; | ||
| 2740 | switch (system.clock_time_get(@bitCast(u32, clk_id), 1, &ts)) { | ||
| 2741 | 0 => { | ||
| 2742 | tp.* = .{ | ||
| 2743 | .tv_sec = @intCast(i64, ts / std.time.ns_per_s), | ||
| 2744 | .tv_nsec = @intCast(isize, ts % std.time.ns_per_s), | ||
| 2745 | }; | ||
| 2746 | }, | ||
| 2747 | EINVAL => return error.UnsupportedClock, | ||
| 2748 | else => |err| return unexpectedErrno(err), | ||
| 2749 | } | ||
| 2750 | return; | ||
| 2751 | } | ||
| 2723 | switch (errno(system.clock_gettime(clk_id, tp))) { | 2752 | switch (errno(system.clock_gettime(clk_id, tp))) { |
| 2724 | 0 => return, | 2753 | 0 => return, |
| 2725 | EFAULT => unreachable, | 2754 | EFAULT => unreachable, |
| ... | @@ -2729,6 +2758,19 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { | ... | @@ -2729,6 +2758,19 @@ pub fn clock_gettime(clk_id: i32, tp: *timespec) ClockGetTimeError!void { |
| 2729 | } | 2758 | } |
| 2730 | 2759 | ||
| 2731 | pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { | 2760 | pub fn clock_getres(clk_id: i32, res: *timespec) ClockGetTimeError!void { |
| 2761 | if (comptime std.Target.current.getOs() == .wasi) { | ||
| 2762 | var ts: timestamp_t = undefined; | ||
| 2763 | switch (system.clock_res_get(@bitCast(u32, clk_id), &ts)) { | ||
| 2764 | 0 => res.* = .{ | ||
| 2765 | .tv_sec = @intCast(i64, ts / std.time.ns_per_s), | ||
| 2766 | .tv_nsec = @intCast(isize, ts % std.time.ns_per_s), | ||
| 2767 | }, | ||
| 2768 | EINVAL => return error.UnsupportedClock, | ||
| 2769 | else => |err| return unexpectedErrno(err), | ||
| 2770 | } | ||
| 2771 | return; | ||
| 2772 | } | ||
| 2773 | |||
| 2732 | switch (errno(system.clock_getres(clk_id, res))) { | 2774 | switch (errno(system.clock_getres(clk_id, res))) { |
| 2733 | 0 => return, | 2775 | 0 => return, |
| 2734 | EFAULT => unreachable, | 2776 | EFAULT => unreachable, |
lib/std/os/wasi.zig+2-48| ... | @@ -78,52 +78,6 @@ pub extern "wasi_unstable" fn sock_send(sock: fd_t, si_data: *const ciovec_t, si | ... | @@ -78,52 +78,6 @@ pub extern "wasi_unstable" fn sock_send(sock: fd_t, si_data: *const ciovec_t, si |
| 78 | pub extern "wasi_unstable" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t; | 78 | pub extern "wasi_unstable" fn sock_shutdown(sock: fd_t, how: sdflags_t) errno_t; |
| 79 | 79 | ||
| 80 | /// Get the errno from a syscall return value, or 0 for no error. | 80 | /// Get the errno from a syscall return value, or 0 for no error. |
| 81 | pub fn getErrno(r: usize) usize { | 81 | pub fn getErrno(r: errno_t) usize { |
| 82 | const signed_r = @bitCast(isize, r); | 82 | return r; |
| 83 | return if (signed_r > -4096 and signed_r < 0) @intCast(usize, -signed_r) else 0; | ||
| 84 | } | ||
| 85 | |||
| 86 | pub fn clock_getres(clock_id: i32, res: *timespec) errno_t { | ||
| 87 | var ts: timestamp_t = undefined; | ||
| 88 | const err = clock_res_get(@bitCast(u32, clock_id), &ts); | ||
| 89 | if (err != 0) { | ||
| 90 | return err; | ||
| 91 | } | ||
| 92 | res.* = .{ | ||
| 93 | .tv_sec = @intCast(i64, ts / std.time.ns_per_s), | ||
| 94 | .tv_nsec = @intCast(isize, ts % std.time.ns_per_s), | ||
| 95 | }; | ||
| 96 | return 0; | ||
| 97 | } | ||
| 98 | |||
| 99 | pub fn clock_gettime(clock_id: i32, tp: *timespec) errno_t { | ||
| 100 | var ts: timestamp_t = undefined; | ||
| 101 | const err = clock_time_get(@bitCast(u32, clock_id), 1, &ts); | ||
| 102 | if (err != 0) { | ||
| 103 | return err; | ||
| 104 | } | ||
| 105 | tp.* = .{ | ||
| 106 | .tv_sec = @intCast(i64, ts / std.time.ns_per_s), | ||
| 107 | .tv_nsec = @intCast(isize, ts % std.time.ns_per_s), | ||
| 108 | }; | ||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | pub fn isatty(fd: fd_t) bool { | ||
| 113 | var statbuf: fdstat_t = undefined; | ||
| 114 | const err = fd_fdstat_get(fd, &statbuf); | ||
| 115 | if (err != 0) { | ||
| 116 | // errno = err; | ||
| 117 | return false; | ||
| 118 | } | ||
| 119 | |||
| 120 | // A tty is a character device that we can't seek or tell on. | ||
| 121 | if (statbuf.fs_filetype != FILETYPE_CHARACTER_DEVICE or | ||
| 122 | (statbuf.fs_rights_base & (RIGHT_FD_SEEK | RIGHT_FD_TELL)) != 0) | ||
| 123 | { | ||
| 124 | // errno = ENOTTY; | ||
| 125 | return false; | ||
| 126 | } | ||
| 127 | |||
| 128 | return true; | ||
| 129 | } | 83 | } |
lib/std/target.zig+5-1| ... | @@ -607,6 +607,10 @@ pub const Target = union(enum) { | ... | @@ -607,6 +607,10 @@ pub const Target = union(enum) { |
| 607 | } | 607 | } |
| 608 | } | 608 | } |
| 609 | 609 | ||
| 610 | pub fn supportsNewStackCall(self: Target) bool { | ||
| 611 | return !self.isWasm(); | ||
| 612 | } | ||
| 613 | |||
| 610 | pub const Executor = union(enum) { | 614 | pub const Executor = union(enum) { |
| 611 | native, | 615 | native, |
| 612 | qemu: []const u8, | 616 | qemu: []const u8, |
| ... | @@ -650,7 +654,7 @@ pub const Target = union(enum) { | ... | @@ -650,7 +654,7 @@ pub const Target = union(enum) { |
| 650 | } | 654 | } |
| 651 | } | 655 | } |
| 652 | 656 | ||
| 653 | if (self.isWasm()) { | 657 | if (self.getOs() == .wasi) { |
| 654 | switch (self.getArchPtrBitWidth()) { | 658 | switch (self.getArchPtrBitWidth()) { |
| 655 | 32 => return Executor{ .wasmtime = "wasmtime" }, | 659 | 32 => return Executor{ .wasmtime = "wasmtime" }, |
| 656 | else => return .unavailable, | 660 | else => return .unavailable, |
src/analyze.cpp+2-1| ... | @@ -978,7 +978,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -978,7 +978,8 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) { |
| 978 | if (g->zig_target->arch == ZigLLVM_x86 || | 978 | if (g->zig_target->arch == ZigLLVM_x86 || |
| 979 | g->zig_target->arch == ZigLLVM_x86_64 || | 979 | g->zig_target->arch == ZigLLVM_x86_64 || |
| 980 | target_is_arm(g->zig_target) || | 980 | target_is_arm(g->zig_target) || |
| 981 | target_is_riscv(g->zig_target)) | 981 | target_is_riscv(g->zig_target) || |
| 982 | target_is_wasm(g->zig_target)) | ||
| 982 | { | 983 | { |
| 983 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); | 984 | X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type); |
| 984 | return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval; | 985 | return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval; |
src/ir.cpp+8| ... | @@ -17095,6 +17095,14 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall | ... | @@ -17095,6 +17095,14 @@ static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCall |
| 17095 | if (call_instruction->new_stack == nullptr) | 17095 | if (call_instruction->new_stack == nullptr) |
| 17096 | return nullptr; | 17096 | return nullptr; |
| 17097 | 17097 | ||
| 17098 | if (!call_instruction->is_async_call_builtin && | ||
| 17099 | arch_stack_pointer_register_name(ira->codegen->zig_target->arch) == nullptr) | ||
| 17100 | { | ||
| 17101 | ir_add_error(ira, &call_instruction->base, | ||
| 17102 | buf_sprintf("target arch '%s' does not support @newStackCall", | ||
| 17103 | target_arch_name(ira->codegen->zig_target->arch))); | ||
| 17104 | } | ||
| 17105 | |||
| 17098 | IrInstruction *new_stack = call_instruction->new_stack->child; | 17106 | IrInstruction *new_stack = call_instruction->new_stack->child; |
| 17099 | if (type_is_invalid(new_stack->value->type)) | 17107 | if (type_is_invalid(new_stack->value->type)) |
| 17100 | return ira->codegen->invalid_instruction; | 17108 | return ira->codegen->invalid_instruction; |
src/target.cpp+4-2| ... | @@ -1458,6 +1458,10 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { | ... | @@ -1458,6 +1458,10 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { |
| 1458 | case ZigLLVM_mipsel: | 1458 | case ZigLLVM_mipsel: |
| 1459 | return "sp"; | 1459 | return "sp"; |
| 1460 | 1460 | ||
| 1461 | case ZigLLVM_wasm32: | ||
| 1462 | case ZigLLVM_wasm64: | ||
| 1463 | return nullptr; // known to be not available | ||
| 1464 | |||
| 1461 | case ZigLLVM_amdgcn: | 1465 | case ZigLLVM_amdgcn: |
| 1462 | case ZigLLVM_amdil: | 1466 | case ZigLLVM_amdil: |
| 1463 | case ZigLLVM_amdil64: | 1467 | case ZigLLVM_amdil64: |
| ... | @@ -1491,8 +1495,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { | ... | @@ -1491,8 +1495,6 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { |
| 1491 | case ZigLLVM_systemz: | 1495 | case ZigLLVM_systemz: |
| 1492 | case ZigLLVM_tce: | 1496 | case ZigLLVM_tce: |
| 1493 | case ZigLLVM_tcele: | 1497 | case ZigLLVM_tcele: |
| 1494 | case ZigLLVM_wasm32: | ||
| 1495 | case ZigLLVM_wasm64: | ||
| 1496 | case ZigLLVM_xcore: | 1498 | case ZigLLVM_xcore: |
| 1497 | case ZigLLVM_ppc: | 1499 | case ZigLLVM_ppc: |
| 1498 | case ZigLLVM_ppc64: | 1500 | case ZigLLVM_ppc64: |
test/compile_errors.zig+18-1| ... | @@ -2,6 +2,24 @@ const tests = @import("tests.zig"); | ... | @@ -2,6 +2,24 @@ const tests = @import("tests.zig"); |
| 2 | const builtin = @import("builtin"); | 2 | const builtin = @import("builtin"); |
| 3 | 3 | ||
| 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { | 4 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 5 | cases.addCase(x: { | ||
| 6 | var tc = cases.create("@newStackCall on unsupported target", | ||
| 7 | \\export fn entry() void { | ||
| 8 | \\ var buf: [10]u8 align(16) = undefined; | ||
| 9 | \\ @newStackCall(&buf, foo); | ||
| 10 | \\} | ||
| 11 | \\fn foo() void {} | ||
| 12 | , "tmp.zig:3:5: error: target arch 'wasm32' does not support @newStackCall"); | ||
| 13 | tc.target = tests.Target{ | ||
| 14 | .Cross = tests.CrossTarget{ | ||
| 15 | .arch = .wasm32, | ||
| 16 | .os = .wasi, | ||
| 17 | .abi = .none, | ||
| 18 | }, | ||
| 19 | }; | ||
| 20 | break :x tc; | ||
| 21 | }); | ||
| 22 | |||
| 5 | cases.add( | 23 | cases.add( |
| 6 | "incompatible sentinels", | 24 | "incompatible sentinels", |
| 7 | \\export fn entry1(ptr: [*:255]u8) [*:0]u8 { | 25 | \\export fn entry1(ptr: [*:255]u8) [*:0]u8 { |
| ... | @@ -26,7 +44,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { | ... | @@ -26,7 +44,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 26 | "tmp.zig:8:35: note: destination array requires a terminating '0' sentinel, but source array has a terminating '255' sentinel", | 44 | "tmp.zig:8:35: note: destination array requires a terminating '0' sentinel, but source array has a terminating '255' sentinel", |
| 27 | "tmp.zig:11:31: error: expected type '[2:0]u8', found '[2]u8'", | 45 | "tmp.zig:11:31: error: expected type '[2:0]u8', found '[2]u8'", |
| 28 | "tmp.zig:11:31: note: destination array requires a terminating '0' sentinel", | 46 | "tmp.zig:11:31: note: destination array requires a terminating '0' sentinel", |
| 29 | |||
| 30 | ); | 47 | ); |
| 31 | 48 | ||
| 32 | cases.add( | 49 | cases.add( |
test/stage1/behavior/asm.zig+2-1| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const std = @import("std"); | ||
| 1 | const config = @import("builtin"); | 2 | const config = @import("builtin"); |
| 2 | const expect = @import("std").testing.expect; | 3 | const expect = std.testing.expect; |
| 3 | 4 | ||
| 4 | comptime { | 5 | comptime { |
| 5 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { | 6 | if (config.arch == config.Arch.x86_64 and config.os == config.Os.linux) { |
test/stage1/behavior/new_stack_call.zig+3| ... | @@ -12,6 +12,9 @@ test "calling a function with a new stack" { | ... | @@ -12,6 +12,9 @@ test "calling a function with a new stack" { |
| 12 | // TODO: https://github.com/ziglang/zig/issues/3338 | 12 | // TODO: https://github.com/ziglang/zig/issues/3338 |
| 13 | return error.SkipZigTest; | 13 | return error.SkipZigTest; |
| 14 | } | 14 | } |
| 15 | if (comptime !std.Target.current.supportsNewStackCall()) { | ||
| 16 | return error.SkipZigTest; | ||
| 17 | } | ||
| 15 | 18 | ||
| 16 | const arg = 1234; | 19 | const arg = 1234; |
| 17 | 20 |