From a9f0681f85679b602cd5f322f6b9b4b2d18a5c4a Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 19 Jul 2018 10:47:17 -0400 Subject: [PATCH 01/17] prevent non-export symbols from clobbering builtins closes #1263 --- src/codegen.cpp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/codegen.cpp b/src/codegen.cpp index 6e121be270d45aa765a3b6ff321acc588bdf677b..7420da97976300809059df8a9d792530cb8107e4 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -60,6 +60,33 @@ PackageTableEntry *new_anonymous_package(void) { return new_package("", ""); } +static const char *symbols_that_llvm_depends_on[] = { + "memcpy", + "memset", + "sqrt", + "powi", + "sin", + "cos", + "pow", + "exp", + "exp2", + "log", + "log10", + "log2", + "fma", + "fabs", + "minnum", + "maxnum", + "copysign", + "floor", + "ceil", + "trunc", + "rint", + "nearbyint", + "round", + // TODO probably all of compiler-rt needs to go here +}; + CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode, Buf *zig_lib_dir) { @@ -94,6 +121,10 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib); buf_resize(&g->global_asm, 0); + for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { + g->external_prototypes.put(buf_create_from_str(symbols_that_llvm_depends_on[i]), nullptr); + } + if (root_src_path) { Buf *src_basename = buf_alloc(); Buf *src_dir = buf_alloc(); -- 2.54.0 From 0736e6aa347f065c15c7acaa0a7d2cc61b85bba6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 19 Jul 2018 13:06:13 -0400 Subject: [PATCH 02/17] std.os.File: add missing pub modifiers --- std/os/file.zig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/std/os/file.zig b/std/os/file.zig index 055f18512137c5db131084aeba0f87dc9c74abe9..c160e90e0e638d24fb998efdd6ca0ff00b2e1872 100644 --- a/std/os/file.zig +++ b/std/os/file.zig @@ -15,7 +15,7 @@ pub const File = struct { /// The OS-specific file descriptor or file handle. handle: os.FileHandle, - const OpenError = os.WindowsOpenError || os.PosixOpenError; + pub const OpenError = os.WindowsOpenError || os.PosixOpenError; /// `path` needs to be copied in memory to add a null terminating byte, hence the allocator. /// Call close to clean up. @@ -289,7 +289,7 @@ pub const File = struct { Unexpected, }; - fn mode(self: *File) ModeError!os.FileMode { + pub fn mode(self: *File) ModeError!os.FileMode { if (is_posix) { var stat: posix.Stat = undefined; const err = posix.getErrno(posix.fstat(self.handle, &stat)); @@ -364,7 +364,7 @@ pub const File = struct { pub const WriteError = os.WindowsWriteError || os.PosixWriteError; - fn write(self: *File, bytes: []const u8) WriteError!void { + pub fn write(self: *File, bytes: []const u8) WriteError!void { if (is_posix) { try os.posixWrite(self.handle, bytes); } else if (is_windows) { -- 2.54.0 From 0a880d5e6034ab35778e4f4db33a385b2a5ad7cc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 19 Jul 2018 18:05:01 -0400 Subject: [PATCH 03/17] fix generation of error defers for fns inside fns closes #878 --- src/ir.cpp | 84 +++++++++++++++++++++++++++++++------------- test/cases/defer.zig | 15 ++++++++ 2 files changed, 74 insertions(+), 25 deletions(-) diff --git a/src/ir.cpp b/src/ir.cpp index 96ade9d392711290fdb7d2d87468d38961ed9d38..fe5fb77085690f78a1465693cd4c85cd8e8b03af 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -2961,16 +2961,34 @@ static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_sco results[ReturnKindUnconditional] = 0; results[ReturnKindError] = 0; - while (inner_scope != outer_scope) { - assert(inner_scope); - if (inner_scope->id == ScopeIdDefer) { - AstNode *defer_node = inner_scope->source_node; - assert(defer_node->type == NodeTypeDefer); - ReturnKind defer_kind = defer_node->data.defer.kind; - results[defer_kind] += 1; + Scope *scope = inner_scope; + while (scope != outer_scope) { + assert(scope); + switch (scope->id) { + case ScopeIdDefer: { + AstNode *defer_node = scope->source_node; + assert(defer_node->type == NodeTypeDefer); + ReturnKind defer_kind = defer_node->data.defer.kind; + results[defer_kind] += 1; + scope = scope->parent; + continue; + } + case ScopeIdDecls: + case ScopeIdFnDef: + return; + case ScopeIdBlock: + case ScopeIdVarDecl: + case ScopeIdLoop: + case ScopeIdSuspend: + case ScopeIdCompTime: + scope = scope->parent; + continue; + case ScopeIdDeferExpr: + case ScopeIdCImport: + case ScopeIdCoroPrelude: + zig_unreachable(); } - inner_scope = inner_scope->parent; } } @@ -2986,27 +3004,43 @@ static bool ir_gen_defers_for_block(IrBuilder *irb, Scope *inner_scope, Scope *o if (!scope) return is_noreturn; - if (scope->id == ScopeIdDefer) { - AstNode *defer_node = scope->source_node; - assert(defer_node->type == NodeTypeDefer); - ReturnKind defer_kind = defer_node->data.defer.kind; - if (defer_kind == ReturnKindUnconditional || - (gen_error_defers && defer_kind == ReturnKindError)) - { - AstNode *defer_expr_node = defer_node->data.defer.expr; - Scope *defer_expr_scope = defer_node->data.defer.expr_scope; - IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); - if (defer_expr_value != irb->codegen->invalid_instruction) { - if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) { - is_noreturn = true; - } else { - ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); + switch (scope->id) { + case ScopeIdDefer: { + AstNode *defer_node = scope->source_node; + assert(defer_node->type == NodeTypeDefer); + ReturnKind defer_kind = defer_node->data.defer.kind; + if (defer_kind == ReturnKindUnconditional || + (gen_error_defers && defer_kind == ReturnKindError)) + { + AstNode *defer_expr_node = defer_node->data.defer.expr; + Scope *defer_expr_scope = defer_node->data.defer.expr_scope; + IrInstruction *defer_expr_value = ir_gen_node(irb, defer_expr_node, defer_expr_scope); + if (defer_expr_value != irb->codegen->invalid_instruction) { + if (defer_expr_value->value.type != nullptr && defer_expr_value->value.type->id == TypeTableEntryIdUnreachable) { + is_noreturn = true; + } else { + ir_mark_gen(ir_build_check_statement_is_void(irb, defer_expr_scope, defer_expr_node, defer_expr_value)); + } } } + scope = scope->parent; + continue; } - + case ScopeIdDecls: + case ScopeIdFnDef: + return is_noreturn; + case ScopeIdBlock: + case ScopeIdVarDecl: + case ScopeIdLoop: + case ScopeIdSuspend: + case ScopeIdCompTime: + scope = scope->parent; + continue; + case ScopeIdDeferExpr: + case ScopeIdCImport: + case ScopeIdCoroPrelude: + zig_unreachable(); } - scope = scope->parent; } return is_noreturn; } diff --git a/test/cases/defer.zig b/test/cases/defer.zig index d2b00d1f911f8627cc6577097d1b3b3e997c954a..7d4d1bc3d8cd7a7bbf3cc517ff6c00251741db25 100644 --- a/test/cases/defer.zig +++ b/test/cases/defer.zig @@ -61,3 +61,18 @@ test "defer and labeled break" { assert(i == 1); } + +test "errdefer does not apply to fn inside fn" { + if (testNestedFnErrDefer()) |_| @panic("expected error") else |e| assert(e == error.Bad); +} + +fn testNestedFnErrDefer() error!void { + var a: i32 = 0; + errdefer a += 1; + const S = struct { + fn baz() error { + return error.Bad; + } + }; + return S.baz(); +} -- 2.54.0 From 1f4c7d5ebfd4ae88d57b6c923d9ef4d2154e193d Mon Sep 17 00:00:00 2001 From: Jimmi HC Date: Fri, 20 Jul 2018 23:05:53 +0200 Subject: [PATCH 04/17] Fixed windows getPos --- std/os/file.zig | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/std/os/file.zig b/std/os/file.zig index c160e90e0e638d24fb998efdd6ca0ff00b2e1872..26fd9ca5146d92668e5212780229070d1bbcc6aa 100644 --- a/std/os/file.zig +++ b/std/os/file.zig @@ -242,7 +242,7 @@ pub const File = struct { }, Os.windows => { var pos: windows.LARGE_INTEGER = undefined; - if (windows.SetFilePointerEx(self.handle, 0, *pos, windows.FILE_CURRENT) == 0) { + if (windows.SetFilePointerEx(self.handle, 0, &pos, windows.FILE_CURRENT) == 0) { const err = windows.GetLastError(); return switch (err) { windows.ERROR.INVALID_PARAMETER => error.BadFd, @@ -251,13 +251,7 @@ pub const File = struct { } assert(pos >= 0); - if (@sizeOf(@typeOf(pos)) > @sizeOf(usize)) { - if (pos > @maxValue(usize)) { - return error.FilePosLargerThanPointerRange; - } - } - - return usize(pos); + return math.cast(usize, pos) catch error.FilePosLargerThanPointerRange; }, else => @compileError("unsupported OS"), } -- 2.54.0 From 7ef110b484b84a0215b715d9defad59138f892d8 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 21 Jul 2018 19:14:14 +0900 Subject: [PATCH 05/17] std.os.posix: Add AF_* for darwin; Tracking issue #1271; --- std/os/darwin.zig | 1 + std/os/darwin_socket.zig | 75 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) create mode 100644 std/os/darwin_socket.zig diff --git a/std/os/darwin.zig b/std/os/darwin.zig index 4134e382fcb5f26dc8547c5eb343fce7052c7515..4258e33c932c8e170c25968c5834346388417cb7 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -3,6 +3,7 @@ const c = std.c; const assert = std.debug.assert; pub use @import("darwin_errno.zig"); +pub use @import("darwin_socket.zig"); pub const PATH_MAX = 1024; diff --git a/std/os/darwin_socket.zig b/std/os/darwin_socket.zig new file mode 100644 index 0000000000000000000000000000000000000000..5f2e32d6f9770fe49a949b0b2edcf629bb75a078 --- /dev/null +++ b/std/os/darwin_socket.zig @@ -0,0 +1,75 @@ +pub const AF_UNSPEC: c_int = 0; +pub const AF_LOCAL: c_int = 1; +pub const AF_UNIX: c_int = AF_LOCAL; +pub const AF_INET: c_int = 2; +pub const AF_SYS_CONTROL: c_int = 2; +pub const AF_IMPLINK: c_int = 3; +pub const AF_PUP: c_int = 4; +pub const AF_CHAOS: c_int = 5; +pub const AF_NS: c_int = 6; +pub const AF_ISO: c_int = 7; +pub const AF_OSI: c_int = AF_ISO; +pub const AF_ECMA: c_int = 8; +pub const AF_DATAKIT: c_int = 9; +pub const AF_CCITT: c_int = 10; +pub const AF_SNA: c_int = 11; +pub const AF_DECnet: c_int = 12; +pub const AF_DLI: c_int = 13; +pub const AF_LAT: c_int = 14; +pub const AF_HYLINK: c_int = 15; +pub const AF_APPLETALK: c_int = 16; +pub const AF_ROUTE: c_int = 17; +pub const AF_LINK: c_int = 18; +pub const AF_XTP: c_int = 19; +pub const AF_COIP: c_int = 20; +pub const AF_CNT: c_int = 21; +pub const AF_RTIP: c_int = 22; +pub const AF_IPX: c_int = 23; +pub const AF_SIP: c_int = 24; +pub const AF_PIP: c_int = 25; +pub const AF_ISDN: c_int = 28; +pub const AF_E164: c_int = AF_ISDN; +pub const AF_KEY: c_int = 29; +pub const AF_INET6: c_int = 30; +pub const AF_NATM: c_int = 31; +pub const AF_SYSTEM: c_int = 32; +pub const AF_NETBIOS: c_int = 33; +pub const AF_PPP: c_int = 34; +pub const AF_MAX: c_int = 40; + +pub const PF_UNSPEC: c_int = AF_UNSPEC; +pub const PF_LOCAL: c_int = AF_LOCAL; +pub const PF_UNIX: c_int = PF_LOCAL; +pub const PF_INET: c_int = AF_INET; +pub const PF_IMPLINK: c_int = AF_IMPLINK; +pub const PF_PUP: c_int = AF_PUP; +pub const PF_CHAOS: c_int = AF_CHAOS; +pub const PF_NS: c_int = AF_NS; +pub const PF_ISO: c_int = AF_ISO; +pub const PF_OSI: c_int = AF_ISO; +pub const PF_ECMA: c_int = AF_ECMA; +pub const PF_DATAKIT: c_int = AF_DATAKIT; +pub const PF_CCITT: c_int = AF_CCITT; +pub const PF_SNA: c_int = AF_SNA; +pub const PF_DECnet: c_int = AF_DECnet; +pub const PF_DLI: c_int = AF_DLI; +pub const PF_LAT: c_int = AF_LAT; +pub const PF_HYLINK: c_int = AF_HYLINK; +pub const PF_APPLETALK: c_int = AF_APPLETALK; +pub const PF_ROUTE: c_int = AF_ROUTE; +pub const PF_LINK: c_int = AF_LINK; +pub const PF_XTP: c_int = AF_XTP; +pub const PF_COIP: c_int = AF_COIP; +pub const PF_CNT: c_int = AF_CNT; +pub const PF_SIP: c_int = AF_SIP; +pub const PF_IPX: c_int = AF_IPX; +pub const PF_RTIP: c_int = AF_RTIP; +pub const PF_PIP: c_int = AF_PIP; +pub const PF_ISDN: c_int = AF_ISDN; +pub const PF_KEY: c_int = AF_KEY; +pub const PF_INET6: c_int = AF_INET6; +pub const PF_NATM: c_int = AF_NATM; +pub const PF_SYSTEM: c_int = AF_SYSTEM; +pub const PF_NETBIOS: c_int = AF_NETBIOS; +pub const PF_PPP: c_int = AF_PPP; +pub const PF_MAX: c_int = AF_MAX; -- 2.54.0 From 8062afcb31c1545b13070876809a0f51cb9aa034 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 21 Jul 2018 19:14:40 +0900 Subject: [PATCH 06/17] std.os.posix: Add SYSPROTO_* for darwin; Tracking issue #1271; --- std/os/darwin_socket.zig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/std/os/darwin_socket.zig b/std/os/darwin_socket.zig index 5f2e32d6f9770fe49a949b0b2edcf629bb75a078..25968d000c322d8f48438a430e0da6d03afe3fff 100644 --- a/std/os/darwin_socket.zig +++ b/std/os/darwin_socket.zig @@ -73,3 +73,6 @@ pub const PF_SYSTEM: c_int = AF_SYSTEM; pub const PF_NETBIOS: c_int = AF_NETBIOS; pub const PF_PPP: c_int = AF_PPP; pub const PF_MAX: c_int = AF_MAX; + +pub const SYSPROTO_EVENT: c_int = 1; +pub const SYSPROTO_CONTROL: c_int = 2; -- 2.54.0 From 460c2662167758b049d46fa8df94a9cd37a3438e Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sat, 21 Jul 2018 19:15:03 +0900 Subject: [PATCH 07/17] std.os.posix: Add SOCK_* for darwin; Tracking issue #1271; --- std/os/darwin_socket.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/std/os/darwin_socket.zig b/std/os/darwin_socket.zig index 25968d000c322d8f48438a430e0da6d03afe3fff..0c613c65043a4b91487003f1a7fd46dbdaeaf33c 100644 --- a/std/os/darwin_socket.zig +++ b/std/os/darwin_socket.zig @@ -76,3 +76,10 @@ pub const PF_MAX: c_int = AF_MAX; pub const SYSPROTO_EVENT: c_int = 1; pub const SYSPROTO_CONTROL: c_int = 2; + +pub const SOCK_STREAM: c_int = 1; +pub const SOCK_DGRAM: c_int = 2; +pub const SOCK_RAW: c_int = 3; +pub const SOCK_RDM: c_int = 4; +pub const SOCK_SEQPACKET: c_int = 5; +pub const SOCK_MAXADDRLEN: c_int = 255; -- 2.54.0 From 501dd5f28452171f8d681c3c54b52e75682838c7 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 22 Jul 2018 01:47:53 +0900 Subject: [PATCH 08/17] CMakeLists.txt: add darwin_socket.zig; Tracking issue #1271; thanks @Hejsil; --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 096ac50cfd6773245521fb74ef33a8ca5f222da7..662f14b799649f777799110828ba232303882de2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -555,6 +555,7 @@ set(ZIG_STD_FILES "os/child_process.zig" "os/darwin.zig" "os/darwin_errno.zig" + "os/darwin_socket.zig" "os/epoch.zig" "os/file.zig" "os/get_app_data_dir.zig" -- 2.54.0 From df574ccf8655726dc204142e7bcfb36770426257 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 22 Jul 2018 02:20:03 +0900 Subject: [PATCH 09/17] std.special.test_runner.zig: make tests skippable; tracking issue #1274; tests can be skipped by returnning `error.skip` : --- std/special/test_runner.zig | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index 76a54a5018da9bc4b8ae9df456256618968dc8dd..46ed7e23e998d597db6c88aa1cd6693fa2109341 100644 --- a/std/special/test_runner.zig +++ b/std/special/test_runner.zig @@ -8,7 +8,13 @@ pub fn main() !void { for (test_fn_list) |test_fn, i| { warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); - try test_fn.func(); + test_fn.func() catch |err| { + if (err == error.skip) { + warn("SKIPPED\n"); + continue; + } + return err; + }; warn("OK\n"); } -- 2.54.0 From bc411af4ffb07fa0e8d713c300c2badd1116acff Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 22 Jul 2018 02:21:52 +0900 Subject: [PATCH 10/17] std.event.tcp: SKIP test instead of OKing test; tracking issue #1274 ; --- std/event/tcp.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 5151ecf9344d085c9d375c74b022610d415deaee..27eab9f0bbe71c597bf48f95713e9777ab1d995f 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -125,7 +125,7 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File test "listen on a port, send bytes, receive bytes" { if (builtin.os != builtin.Os.linux) { // TODO build abstractions for other operating systems - return; + return error.skip; } const MyServer = struct { tcp_server: Server, -- 2.54.0 From c5c053b6fdde911edd0b488c29fbef0e2aa0a904 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 22 Jul 2018 03:11:55 +0900 Subject: [PATCH 11/17] std.event.tcp: add switch statement in preparation for building-out abstractions; depends on issue #1274 ; --- std/event/tcp.zig | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 27eab9f0bbe71c597bf48f95713e9777ab1d995f..1542538082eeb6e9871e988dd33d923dd3d0d57d 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -123,10 +123,17 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File } test "listen on a port, send bytes, receive bytes" { - if (builtin.os != builtin.Os.linux) { - // TODO build abstractions for other operating systems + // TODO build abstractions for other operating systems + const skip_test: bool = switch (builtin.os) { + builtin.Os.linux => false, + //builtin.Os.macosx, builtin.Os.ios => false, + else => true, + }; + + if (skip_test == true) { return error.skip; } + const MyServer = struct { tcp_server: Server, -- 2.54.0 From bb1b7967111dd5add6172fb33fd9c17e7a344321 Mon Sep 17 00:00:00 2001 From: kristopher tate Date: Sun, 22 Jul 2018 12:26:52 +0900 Subject: [PATCH 12/17] README: include link to channel logs (#1278) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a5868bf44e6d8b1585e3405b7f110bafc331ecfd..99e224c36736e4c44293a842f07c778de48420f5 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ that counts as "freestanding" for the purposes of this table. ## Community - * IRC: `#zig` on Freenode. + * IRC: `#zig` on Freenode ([Channel Logs](https://irclog.whitequark.org/zig/)). * Reddit: [/r/zig](https://www.reddit.com/r/zig) * Email list: [ziglang@googlegroups.com](https://groups.google.com/forum/#!forum/ziglang) -- 2.54.0 From 4d9964a457084d41ba2995082d0e25b195757751 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 21 Jul 2018 23:43:43 -0400 Subject: [PATCH 13/17] rename error.skip to error.SkipZigTest also print stats at the end of test runner --- std/event/tcp.zig | 12 +++--------- std/special/test_runner.zig | 26 +++++++++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/std/event/tcp.zig b/std/event/tcp.zig index 1542538082eeb6e9871e988dd33d923dd3d0d57d..416a8c07dc1015d054ce5d40271bab09f10f0e04 100644 --- a/std/event/tcp.zig +++ b/std/event/tcp.zig @@ -123,15 +123,9 @@ pub async fn connect(loop: *Loop, _address: *const std.net.Address) !std.os.File } test "listen on a port, send bytes, receive bytes" { - // TODO build abstractions for other operating systems - const skip_test: bool = switch (builtin.os) { - builtin.Os.linux => false, - //builtin.Os.macosx, builtin.Os.ios => false, - else => true, - }; - - if (skip_test == true) { - return error.skip; + if (builtin.os != builtin.Os.linux) { + // TODO build abstractions for other operating systems + return error.SkipZigTest; } const MyServer = struct { diff --git a/std/special/test_runner.zig b/std/special/test_runner.zig index 46ed7e23e998d597db6c88aa1cd6693fa2109341..857739e82d29191a7f77ef74651461c06875c30c 100644 --- a/std/special/test_runner.zig +++ b/std/special/test_runner.zig @@ -5,17 +5,25 @@ const test_fn_list = builtin.__zig_test_fn_slice; const warn = std.debug.warn; pub fn main() !void { + var ok_count: usize = 0; + var skip_count: usize = 0; for (test_fn_list) |test_fn, i| { warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); - test_fn.func() catch |err| { - if (err == error.skip) { - warn("SKIPPED\n"); - continue; - } - return err; - }; - - warn("OK\n"); + if (test_fn.func()) |_| { + ok_count += 1; + warn("OK\n"); + } else |err| switch (err) { + error.SkipZigTest => { + skip_count += 1; + warn("SKIP\n"); + }, + else => return err, + } + } + if (ok_count == test_fn_list.len) { + warn("All tests passed.\n"); + } else { + warn("{} passed; {} skipped.\n", ok_count, skip_count); } } -- 2.54.0 From 20f286f22aa1ea06b6c914cfd25a2bac5d324f69 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 22 Jul 2018 00:04:24 -0400 Subject: [PATCH 14/17] re-organize std lib darwin files --- CMakeLists.txt | 3 +- std/c/darwin.zig | 2 +- std/os/darwin.zig | 89 ++++++++++++++++++- std/os/{darwin_errno.zig => darwin/errno.zig} | 0 std/os/darwin_socket.zig | 85 ------------------ std/os/index.zig | 2 +- 6 files changed, 90 insertions(+), 91 deletions(-) rename std/os/{darwin_errno.zig => darwin/errno.zig} (100%) delete mode 100644 std/os/darwin_socket.zig diff --git a/CMakeLists.txt b/CMakeLists.txt index 662f14b799649f777799110828ba232303882de2..137cefb5b472bc3dbe9e25b83958728b5b4c4a8b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -554,8 +554,7 @@ set(ZIG_STD_FILES "net.zig" "os/child_process.zig" "os/darwin.zig" - "os/darwin_errno.zig" - "os/darwin_socket.zig" + "os/darwin/errno.zig" "os/epoch.zig" "os/file.zig" "os/get_app_data_dir.zig" diff --git a/std/c/darwin.zig b/std/c/darwin.zig index 4189dfeadcda8e73a5699e80edfd27a271e1ea0f..1bd1d6c4c997ee99bd8998cf4a5a9c22f4f845dd 100644 --- a/std/c/darwin.zig +++ b/std/c/darwin.zig @@ -30,7 +30,7 @@ pub extern "c" fn sysctl(name: [*]c_int, namelen: c_uint, oldp: ?*c_void, oldlen pub extern "c" fn sysctlbyname(name: [*]const u8, oldp: ?*c_void, oldlenp: ?*usize, newp: ?*c_void, newlen: usize) c_int; pub extern "c" fn sysctlnametomib(name: [*]const u8, mibp: ?*c_int, sizep: ?*usize) c_int; -pub use @import("../os/darwin_errno.zig"); +pub use @import("../os/darwin/errno.zig"); pub const _errno = __error; diff --git a/std/os/darwin.zig b/std/os/darwin.zig index 4258e33c932c8e170c25968c5834346388417cb7..cf67b01d5a25a728f0fd36ff2e237071a2a20aa3 100644 --- a/std/os/darwin.zig +++ b/std/os/darwin.zig @@ -2,8 +2,7 @@ const std = @import("../index.zig"); const c = std.c; const assert = std.debug.assert; -pub use @import("darwin_errno.zig"); -pub use @import("darwin_socket.zig"); +pub use @import("darwin/errno.zig"); pub const PATH_MAX = 1024; @@ -483,6 +482,92 @@ pub const NOTE_MACH_CONTINUOUS_TIME = 0x00000080; /// data is mach absolute time units pub const NOTE_MACHTIME = 0x00000100; +pub const AF_UNSPEC: c_int = 0; +pub const AF_LOCAL: c_int = 1; +pub const AF_UNIX: c_int = AF_LOCAL; +pub const AF_INET: c_int = 2; +pub const AF_SYS_CONTROL: c_int = 2; +pub const AF_IMPLINK: c_int = 3; +pub const AF_PUP: c_int = 4; +pub const AF_CHAOS: c_int = 5; +pub const AF_NS: c_int = 6; +pub const AF_ISO: c_int = 7; +pub const AF_OSI: c_int = AF_ISO; +pub const AF_ECMA: c_int = 8; +pub const AF_DATAKIT: c_int = 9; +pub const AF_CCITT: c_int = 10; +pub const AF_SNA: c_int = 11; +pub const AF_DECnet: c_int = 12; +pub const AF_DLI: c_int = 13; +pub const AF_LAT: c_int = 14; +pub const AF_HYLINK: c_int = 15; +pub const AF_APPLETALK: c_int = 16; +pub const AF_ROUTE: c_int = 17; +pub const AF_LINK: c_int = 18; +pub const AF_XTP: c_int = 19; +pub const AF_COIP: c_int = 20; +pub const AF_CNT: c_int = 21; +pub const AF_RTIP: c_int = 22; +pub const AF_IPX: c_int = 23; +pub const AF_SIP: c_int = 24; +pub const AF_PIP: c_int = 25; +pub const AF_ISDN: c_int = 28; +pub const AF_E164: c_int = AF_ISDN; +pub const AF_KEY: c_int = 29; +pub const AF_INET6: c_int = 30; +pub const AF_NATM: c_int = 31; +pub const AF_SYSTEM: c_int = 32; +pub const AF_NETBIOS: c_int = 33; +pub const AF_PPP: c_int = 34; +pub const AF_MAX: c_int = 40; + +pub const PF_UNSPEC: c_int = AF_UNSPEC; +pub const PF_LOCAL: c_int = AF_LOCAL; +pub const PF_UNIX: c_int = PF_LOCAL; +pub const PF_INET: c_int = AF_INET; +pub const PF_IMPLINK: c_int = AF_IMPLINK; +pub const PF_PUP: c_int = AF_PUP; +pub const PF_CHAOS: c_int = AF_CHAOS; +pub const PF_NS: c_int = AF_NS; +pub const PF_ISO: c_int = AF_ISO; +pub const PF_OSI: c_int = AF_ISO; +pub const PF_ECMA: c_int = AF_ECMA; +pub const PF_DATAKIT: c_int = AF_DATAKIT; +pub const PF_CCITT: c_int = AF_CCITT; +pub const PF_SNA: c_int = AF_SNA; +pub const PF_DECnet: c_int = AF_DECnet; +pub const PF_DLI: c_int = AF_DLI; +pub const PF_LAT: c_int = AF_LAT; +pub const PF_HYLINK: c_int = AF_HYLINK; +pub const PF_APPLETALK: c_int = AF_APPLETALK; +pub const PF_ROUTE: c_int = AF_ROUTE; +pub const PF_LINK: c_int = AF_LINK; +pub const PF_XTP: c_int = AF_XTP; +pub const PF_COIP: c_int = AF_COIP; +pub const PF_CNT: c_int = AF_CNT; +pub const PF_SIP: c_int = AF_SIP; +pub const PF_IPX: c_int = AF_IPX; +pub const PF_RTIP: c_int = AF_RTIP; +pub const PF_PIP: c_int = AF_PIP; +pub const PF_ISDN: c_int = AF_ISDN; +pub const PF_KEY: c_int = AF_KEY; +pub const PF_INET6: c_int = AF_INET6; +pub const PF_NATM: c_int = AF_NATM; +pub const PF_SYSTEM: c_int = AF_SYSTEM; +pub const PF_NETBIOS: c_int = AF_NETBIOS; +pub const PF_PPP: c_int = AF_PPP; +pub const PF_MAX: c_int = AF_MAX; + +pub const SYSPROTO_EVENT: c_int = 1; +pub const SYSPROTO_CONTROL: c_int = 2; + +pub const SOCK_STREAM: c_int = 1; +pub const SOCK_DGRAM: c_int = 2; +pub const SOCK_RAW: c_int = 3; +pub const SOCK_RDM: c_int = 4; +pub const SOCK_SEQPACKET: c_int = 5; +pub const SOCK_MAXADDRLEN: c_int = 255; + fn wstatus(x: i32) i32 { return x & 0o177; } diff --git a/std/os/darwin_errno.zig b/std/os/darwin/errno.zig similarity index 100% rename from std/os/darwin_errno.zig rename to std/os/darwin/errno.zig diff --git a/std/os/darwin_socket.zig b/std/os/darwin_socket.zig deleted file mode 100644 index 0c613c65043a4b91487003f1a7fd46dbdaeaf33c..0000000000000000000000000000000000000000 --- a/std/os/darwin_socket.zig +++ /dev/null @@ -1,85 +0,0 @@ -pub const AF_UNSPEC: c_int = 0; -pub const AF_LOCAL: c_int = 1; -pub const AF_UNIX: c_int = AF_LOCAL; -pub const AF_INET: c_int = 2; -pub const AF_SYS_CONTROL: c_int = 2; -pub const AF_IMPLINK: c_int = 3; -pub const AF_PUP: c_int = 4; -pub const AF_CHAOS: c_int = 5; -pub const AF_NS: c_int = 6; -pub const AF_ISO: c_int = 7; -pub const AF_OSI: c_int = AF_ISO; -pub const AF_ECMA: c_int = 8; -pub const AF_DATAKIT: c_int = 9; -pub const AF_CCITT: c_int = 10; -pub const AF_SNA: c_int = 11; -pub const AF_DECnet: c_int = 12; -pub const AF_DLI: c_int = 13; -pub const AF_LAT: c_int = 14; -pub const AF_HYLINK: c_int = 15; -pub const AF_APPLETALK: c_int = 16; -pub const AF_ROUTE: c_int = 17; -pub const AF_LINK: c_int = 18; -pub const AF_XTP: c_int = 19; -pub const AF_COIP: c_int = 20; -pub const AF_CNT: c_int = 21; -pub const AF_RTIP: c_int = 22; -pub const AF_IPX: c_int = 23; -pub const AF_SIP: c_int = 24; -pub const AF_PIP: c_int = 25; -pub const AF_ISDN: c_int = 28; -pub const AF_E164: c_int = AF_ISDN; -pub const AF_KEY: c_int = 29; -pub const AF_INET6: c_int = 30; -pub const AF_NATM: c_int = 31; -pub const AF_SYSTEM: c_int = 32; -pub const AF_NETBIOS: c_int = 33; -pub const AF_PPP: c_int = 34; -pub const AF_MAX: c_int = 40; - -pub const PF_UNSPEC: c_int = AF_UNSPEC; -pub const PF_LOCAL: c_int = AF_LOCAL; -pub const PF_UNIX: c_int = PF_LOCAL; -pub const PF_INET: c_int = AF_INET; -pub const PF_IMPLINK: c_int = AF_IMPLINK; -pub const PF_PUP: c_int = AF_PUP; -pub const PF_CHAOS: c_int = AF_CHAOS; -pub const PF_NS: c_int = AF_NS; -pub const PF_ISO: c_int = AF_ISO; -pub const PF_OSI: c_int = AF_ISO; -pub const PF_ECMA: c_int = AF_ECMA; -pub const PF_DATAKIT: c_int = AF_DATAKIT; -pub const PF_CCITT: c_int = AF_CCITT; -pub const PF_SNA: c_int = AF_SNA; -pub const PF_DECnet: c_int = AF_DECnet; -pub const PF_DLI: c_int = AF_DLI; -pub const PF_LAT: c_int = AF_LAT; -pub const PF_HYLINK: c_int = AF_HYLINK; -pub const PF_APPLETALK: c_int = AF_APPLETALK; -pub const PF_ROUTE: c_int = AF_ROUTE; -pub const PF_LINK: c_int = AF_LINK; -pub const PF_XTP: c_int = AF_XTP; -pub const PF_COIP: c_int = AF_COIP; -pub const PF_CNT: c_int = AF_CNT; -pub const PF_SIP: c_int = AF_SIP; -pub const PF_IPX: c_int = AF_IPX; -pub const PF_RTIP: c_int = AF_RTIP; -pub const PF_PIP: c_int = AF_PIP; -pub const PF_ISDN: c_int = AF_ISDN; -pub const PF_KEY: c_int = AF_KEY; -pub const PF_INET6: c_int = AF_INET6; -pub const PF_NATM: c_int = AF_NATM; -pub const PF_SYSTEM: c_int = AF_SYSTEM; -pub const PF_NETBIOS: c_int = AF_NETBIOS; -pub const PF_PPP: c_int = AF_PPP; -pub const PF_MAX: c_int = AF_MAX; - -pub const SYSPROTO_EVENT: c_int = 1; -pub const SYSPROTO_CONTROL: c_int = 2; - -pub const SOCK_STREAM: c_int = 1; -pub const SOCK_DGRAM: c_int = 2; -pub const SOCK_RAW: c_int = 3; -pub const SOCK_RDM: c_int = 4; -pub const SOCK_SEQPACKET: c_int = 5; -pub const SOCK_MAXADDRLEN: c_int = 255; diff --git a/std/os/index.zig b/std/os/index.zig index 87053fd8dfefcafb5617d4f3f69f934ac9854e00..77fd2a78ad69a242b756e527d61697d5ef560116 100644 --- a/std/os/index.zig +++ b/std/os/index.zig @@ -11,7 +11,7 @@ const os = this; test "std.os" { _ = @import("child_process.zig"); _ = @import("darwin.zig"); - _ = @import("darwin_errno.zig"); + _ = @import("darwin/errno.zig"); _ = @import("get_user_id.zig"); _ = @import("linux/index.zig"); _ = @import("path.zig"); -- 2.54.0 From 07b6a3d335450778f69a6ee5afa5716e4fe83fe3 Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Sat, 21 Jul 2018 23:33:28 +1200 Subject: [PATCH 15/17] Tighten Int.to bounds and add twos-complement bitcount --- std/math/big/int.zig | 103 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 91 insertions(+), 12 deletions(-) diff --git a/std/math/big/int.zig b/std/math/big/int.zig index caa9d0a7edc8850f05b9d3e985a898d9ed5b7b0f..026933bd644ff3861e406aeabce952eba2a34dbf 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -115,13 +115,47 @@ pub const Int = struct { return !r.isOdd(); } - fn bitcount(self: Int) usize { - const u_bit_count = (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1])); - return usize(@boolToInt(!self.positive)) + u_bit_count; + // Returns the number of bits required to represent the absolute value of self. + fn bitCountAbs(self: Int) usize { + return (self.len - 1) * Limb.bit_count + (Limb.bit_count - @clz(self.limbs[self.len - 1])); } + // Returns the number of bits required to represent the integer in twos-complement form. + // + // If the integer is negative the value returned is the number of bits needed by a signed + // integer to represent the value. If positive the value is the number of bits for an + // unsigned integer. Any unsigned integer will fit in the signed integer with bitcount + // one greater than the returned value. + // + // e.g. -127 returns 8 as it will fit in an i8. 127 returns 7 since it fits in a u7. + fn bitCountTwosComp(self: Int) usize { + var bits = self.bitCountAbs(); + + // If the entire value has only one bit set (e.g. 0b100000000) then the negation in twos + // complement requires one less bit. + if (!self.positive) block: { + bits += 1; + + if (@popCount(self.limbs[self.len - 1]) == 1) { + for (self.limbs[0 .. self.len - 1]) |limb| { + if (@popCount(limb) != 0) { + break :block; + } + } + + bits -= 1; + } + } + + return bits; + } + + // Returns the approximate size of the integer in the given base. Negative values accomodate for + // the minus sign. This is used for determining the number of characters needed to print the + // value. It is inexact and will exceed the given value by 1-2 digits. pub fn sizeInBase(self: Int, base: usize) usize { - return (self.bitcount() / math.log2(base)) + 1; + const bit_count = usize(@boolToInt(!self.positive)) + self.bitCountAbs(); + return (bit_count / math.log2(base)) + 1; } pub fn set(self: *Int, value: var) Allocator.Error!void { @@ -189,9 +223,9 @@ pub const Int = struct { pub fn to(self: Int, comptime T: type) ConvertError!T { switch (@typeId(T)) { TypeId.Int => { - const UT = if (T.is_signed) @IntType(false, T.bit_count - 1) else T; + const UT = @IntType(false, T.bit_count); - if (self.bitcount() > 8 * @sizeOf(UT)) { + if (self.bitCountTwosComp() > T.bit_count) { return error.TargetTooSmall; } @@ -208,9 +242,17 @@ pub const Int = struct { } if (!T.is_signed) { - return if (self.positive) r else error.NegativeIntoUnsigned; + return if (self.positive) @intCast(T, r) else error.NegativeIntoUnsigned; } else { - return if (self.positive) @intCast(T, r) else -@intCast(T, r); + if (self.positive) { + return @intCast(T, r); + } else { + if (math.cast(T, r)) |ok| { + return -ok; + } else |_| { + return @minValue(T); + } + } } }, else => { @@ -1120,24 +1162,61 @@ test "big.int bitcount + sizeInBase" { var a = try Int.init(al); try a.set(0b100); - debug.assert(a.bitcount() == 3); + debug.assert(a.bitCountAbs() == 3); debug.assert(a.sizeInBase(2) >= 3); debug.assert(a.sizeInBase(10) >= 1); + a.negate(); + debug.assert(a.bitCountAbs() == 3); + debug.assert(a.sizeInBase(2) >= 4); + debug.assert(a.sizeInBase(10) >= 2); + try a.set(0xffffffff); - debug.assert(a.bitcount() == 32); + debug.assert(a.bitCountAbs() == 32); debug.assert(a.sizeInBase(2) >= 32); debug.assert(a.sizeInBase(10) >= 10); try a.shiftLeft(a, 5000); - debug.assert(a.bitcount() == 5032); + debug.assert(a.bitCountAbs() == 5032); debug.assert(a.sizeInBase(2) >= 5032); a.positive = false; - debug.assert(a.bitcount() == 5033); + debug.assert(a.bitCountAbs() == 5032); debug.assert(a.sizeInBase(2) >= 5033); } +test "big.int bitcount/to" { + var a = try Int.init(al); + + try a.set(0); + debug.assert(a.bitCountTwosComp() == 0); + + // TODO: stack smashing + // debug.assert((try a.to(u0)) == 0); + // TODO: sigsegv + // debug.assert((try a.to(i0)) == 0); + + try a.set(-1); + debug.assert(a.bitCountTwosComp() == 1); + debug.assert((try a.to(i1)) == -1); + + try a.set(-8); + debug.assert(a.bitCountTwosComp() == 4); + debug.assert((try a.to(i4)) == -8); + + try a.set(127); + debug.assert(a.bitCountTwosComp() == 7); + debug.assert((try a.to(u7)) == 127); + + try a.set(-128); + debug.assert(a.bitCountTwosComp() == 8); + debug.assert((try a.to(i8)) == -128); + + try a.set(-129); + debug.assert(a.bitCountTwosComp() == 9); + debug.assert((try a.to(i9)) == -129); +} + test "big.int string set" { var a = try Int.init(al); try a.setString(10, "120317241209124781241290847124"); -- 2.54.0 From d53fae3551f6215b99f065e837f1f4439ba850fd Mon Sep 17 00:00:00 2001 From: Marc Tiehuis Date: Mon, 23 Jul 2018 02:11:27 +1200 Subject: [PATCH 16/17] Add big int fits function (#1279) Returns whether the current value in an Int fits in the requested type. --- std/math/big/int.zig | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/std/math/big/int.zig b/std/math/big/int.zig index 026933bd644ff3861e406aeabce952eba2a34dbf..acd2a687464c7c51066e620b6f2c16006a152fd4 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -150,6 +150,18 @@ pub const Int = struct { return bits; } + pub fn fits(self: Int, comptime T: type) bool { + if (self.eqZero()) { + return true; + } + if (!T.is_signed and !self.positive) { + return false; + } + + const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and T.is_signed); + return T.bit_count >= req_bits; + } + // Returns the approximate size of the integer in the given base. Negative values accomodate for // the minus sign. This is used for determining the number of characters needed to print the // value. It is inexact and will exceed the given value by 1-2 digits. @@ -1217,6 +1229,33 @@ test "big.int bitcount/to" { debug.assert((try a.to(i9)) == -129); } +test "big.int fits" { + var a = try Int.init(al); + + try a.set(0); + debug.assert(a.fits(u0)); + debug.assert(a.fits(i0)); + + try a.set(255); + debug.assert(!a.fits(u0)); + debug.assert(!a.fits(u1)); + debug.assert(!a.fits(i8)); + debug.assert(a.fits(u8)); + debug.assert(a.fits(u9)); + debug.assert(a.fits(i9)); + + try a.set(-128); + debug.assert(!a.fits(i7)); + debug.assert(a.fits(i8)); + debug.assert(a.fits(i9)); + debug.assert(!a.fits(u9)); + + try a.set(0x1ffffffffeeeeeeee); + debug.assert(!a.fits(u32)); + debug.assert(!a.fits(u64)); + debug.assert(a.fits(u65)); +} + test "big.int string set" { var a = try Int.init(al); try a.setString(10, "120317241209124781241290847124"); -- 2.54.0 From 99153ac0aa390f01091308073b39947c45851ae6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 22 Jul 2018 10:58:45 -0400 Subject: [PATCH 17/17] add std.math.big.Int.fitsInTwosComp so that we can pass runtime-known values --- std/math/big/int.zig | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/std/math/big/int.zig b/std/math/big/int.zig index acd2a687464c7c51066e620b6f2c16006a152fd4..09bbfe58659e7f1541ac3347a5cd738269586f8a 100644 --- a/std/math/big/int.zig +++ b/std/math/big/int.zig @@ -150,16 +150,20 @@ pub const Int = struct { return bits; } - pub fn fits(self: Int, comptime T: type) bool { + pub fn fitsInTwosComp(self: Int, is_signed: bool, bit_count: usize) bool { if (self.eqZero()) { return true; } - if (!T.is_signed and !self.positive) { + if (!is_signed and !self.positive) { return false; } - const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and T.is_signed); - return T.bit_count >= req_bits; + const req_bits = self.bitCountTwosComp() + @boolToInt(self.positive and is_signed); + return bit_count >= req_bits; + } + + pub fn fits(self: Int, comptime T: type) bool { + return self.fitsInTwosComp(T.is_signed, T.bit_count); } // Returns the approximate size of the integer in the given base. Negative values accomodate for -- 2.54.0