From 0de35af98b3404f0cf7cd9497f661239d197bbbf Mon Sep 17 00:00:00 2001 From: antlilja Date: Mon, 22 Jun 2020 12:14:52 +0200 Subject: [PATCH 1/8] Add duplicate checking for switch on types * Add compile error tests --- src/ir.cpp | 32 +++++++++++++++++++++++++++++++- test/compile_errors.zig | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/ir.cpp b/src/ir.cpp index 3fa138ed8e1cf270176562507f8a87e40d094236..01c7936f75277b739db930798d6648166b1a50c1 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -28861,7 +28861,37 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, ir_add_error(ira, &instruction->base.base, buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name))); return ira->codegen->invalid_inst_gen; - } + } else if(switch_type->id == ZigTypeIdMetaType) { + HashMap prevs; + // HashMap doubles capacity when reaching 60% capacity, + // because we know the size at init we can avoid reallocation by doubling it here + prevs.init(instruction->range_count * 2); + for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) { + IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i]; + + IrInstGen *value = range->start->child; + IrInstGen *casted_value = ir_implicit_cast(ira, value, switch_type); + if (type_is_invalid(casted_value->value->type)) { + prevs.deinit(); + return ira->codegen->invalid_inst_gen; + } + + ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad); + if (!const_expr_val) { + prevs.deinit(); + return ira->codegen->invalid_inst_gen; + } + + auto entry = prevs.put_unique(const_expr_val->data.x_type, value); + if(entry != nullptr) { + ErrorMsg *msg = ir_add_error(ira, &value->base, buf_sprintf("duplicate switch value")); + add_error_note(ira->codegen, msg, entry->value->base.source_node, buf_sprintf("previous value is here")); + prevs.deinit(); + return ira->codegen->invalid_inst_gen; + } + } + prevs.deinit(); + } return ir_const_void(ira, &instruction->base.base); } diff --git a/test/compile_errors.zig b/test/compile_errors.zig index e3dd1f0d8f4161fc09ac7f132faba42bfae1c2f9..e8b7e610ee70e6ce82201eb3369606d6fbcb9acb 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4362,6 +4362,40 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:5:14: note: previous value is here", }); + cases.add("switch expression - duplicate type", + \\fn foo(comptime T: type, x: T) u8 { + \\ return switch (T) { + \\ u32 => 0, + \\ u64 => 1, + \\ u32 => 2, + \\ else => 3, + \\ }; + \\} + \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); } + , &[_][]const u8{ + "tmp.zig:5:9: error: duplicate switch value", + "tmp.zig:3:9: note: previous value is here", + }); + + cases.add("switch expression - duplicate type (struct alias)", + \\const Test = struct { + \\ bar: i32, + \\}; + \\const Test2 = Test; + \\fn foo(comptime T: type, x: T) u8 { + \\ return switch (T) { + \\ Test => 0, + \\ u64 => 1, + \\ Test2 => 2, + \\ else => 3, + \\ }; + \\} + \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); } + , &[_][]const u8{ + "tmp.zig:9:9: error: duplicate switch value", + "tmp.zig:7:9: note: previous value is here", + }); + cases.add("switch expression - switch on pointer type with no else", \\fn foo(x: *u8) void { \\ switch (x) { -- 2.54.0 From 66e5205047576768f075ec8f016f6fe21ce71bd0 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 23 Jun 2020 21:54:36 +0200 Subject: [PATCH 2/8] Refactor PreopenList.find() This commit generalizes `std.fs.wasi.PreopenList.find(...)` allowing search by `std.fs.wasi.PreopenType` union type rather than by dir name. In the future releases of WASI, it is expected to have more preopen types (or capabilities) than just directories. This commit aligns itself with that vision. This is a potentially breaking change. However, since `std.fs.wasi.PreopenList` wasn't made part of any Zig release yet, I think we should be OK to introduce those changes without pointing to any deprecations. --- doc/langref.html.in | 2 +- lib/std/fs/wasi.zig | 77 ++++++++++++++++++++++++--------------------- lib/std/testing.zig | 2 +- 3 files changed, 44 insertions(+), 37 deletions(-) diff --git a/doc/langref.html.in b/doc/langref.html.in index aaa15e91d03758be100a0463f6c2f5c6ab3c333a..8974e6d175b6178fa544fe0e538c93aec356696e 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -9738,7 +9738,7 @@ pub fn main() !void { } {#code_end#}
$ wasmtime --dir=. preopens.wasm
-0: { .fd = 3, .Dir = '.' }
+0: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } }
 
{#header_close#} {#header_close#} diff --git a/lib/std/fs/wasi.zig b/lib/std/fs/wasi.zig index f08c74c129a36ec7049563e0c2a23b68eac1ada1..fb6e6679fd1ecbd59db8f7f9e2da0e3e4a00e96b 100644 --- a/lib/std/fs/wasi.zig +++ b/lib/std/fs/wasi.zig @@ -5,13 +5,39 @@ const Allocator = mem.Allocator; usingnamespace std.os.wasi; -/// Type of WASI preopen. +/// Type-tag of WASI preopen. /// /// WASI currently offers only `Dir` as a valid preopen resource. -pub const PreopenType = enum { +pub const PreopenTypeTag = enum { Dir, }; +/// Type of WASI preopen. +/// +/// WASI currently offers only `Dir` as a valid preopen resource. +pub const PreopenType = union(PreopenTypeTag) { + /// Preopened directory type. + Dir: []const u8, + + const Self = @This(); + + pub fn eql(self: Self, other: PreopenType) bool { + if (!mem.eql(u8, @tagName(self), @tagName(other))) return false; + + switch (self) { + PreopenTypeTag.Dir => |this_path| return mem.eql(u8, this_path, other.Dir), + } + } + + pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { + try out_stream.print("PreopenType{{ ", .{}); + switch (self) { + PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), + } + return out_stream.print(" }}", .{}); + } +}; + /// WASI preopen struct. This struct consists of a WASI file descriptor /// and type of WASI preopen. It can be obtained directly from the WASI /// runtime using `PreopenList.populate()` method. @@ -20,29 +46,15 @@ pub const Preopen = struct { fd: fd_t, /// Type of the preopen. - @"type": union(PreopenType) { - /// Path to a preopened directory. - Dir: []const u8, - }, + @"type": PreopenType, - const Self = @This(); - - /// Construct new `Preopen` instance of type `PreopenType.Dir` from - /// WASI file descriptor and WASI path. - pub fn newDir(fd: fd_t, path: []const u8) Self { - return Self{ + /// Construct new `Preopen` instance. + pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen { + return Preopen{ .fd = fd, - .@"type" = .{ .Dir = path }, + .@"type" = preopen_type, }; } - - pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void { - try out_stream.print("{{ .fd = {}, ", .{self.fd}); - switch (self.@"type") { - PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}), - } - return out_stream.print(" }}", .{}); - } }; /// Dynamically-sized array list of WASI preopens. This struct is a @@ -113,24 +125,18 @@ pub const PreopenList = struct { ESUCCESS => {}, else => |err| return os.unexpectedErrno(err), } - const preopen = Preopen.newDir(fd, path_buf); + const preopen = Preopen.new(fd, PreopenType{ .Dir = path_buf }); try self.buffer.append(preopen); fd += 1; } } - /// Find preopen by path. If the preopen exists, return it. + /// Find preopen by type. If the preopen exists, return it. /// Otherwise, return `null`. - /// - /// TODO make the function more generic by searching by `PreopenType` union. This will - /// be needed in the future when WASI extends its capabilities to resources - /// other than preopened directories. - pub fn find(self: Self, path: []const u8) ?*const Preopen { - for (self.buffer.items) |preopen| { - switch (preopen.@"type") { - PreopenType.Dir => |preopen_path| { - if (mem.eql(u8, path, preopen_path)) return &preopen; - }, + pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen { + for (self.buffer.items) |*preopen| { + if (preopen.@"type".eql(preopen_type)) { + return preopen; } } return null; @@ -156,7 +162,8 @@ test "extracting WASI preopens" { try preopens.populate(); std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); - const preopen = preopens.find(".") orelse unreachable; - std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir)); + const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable; + std.debug.print("\n{}\n", .{preopen}); + std.testing.expect(!preopen.@"type".eql(PreopenType{ .Dir = "." })); std.testing.expectEqual(@as(usize, 3), preopen.fd); } diff --git a/lib/std/testing.zig b/lib/std/testing.zig index 2d136d56c9a3373e331437f30e0f5398b3369324..117a788e1662b3bee787f9e81c52ad270ddc3454 100644 --- a/lib/std/testing.zig +++ b/lib/std/testing.zig @@ -215,7 +215,7 @@ fn getCwdOrWasiPreopen() std.fs.Dir { defer preopens.deinit(); preopens.populate() catch @panic("unable to make tmp dir for testing: unable to populate preopens"); - const preopen = preopens.find(".") orelse + const preopen = preopens.find(std.fs.wasi.PreopenType{ .Dir = "." }) orelse @panic("unable to make tmp dir for testing: didn't find '.' in the preopens"); return std.fs.Dir{ .fd = preopen.fd }; -- 2.54.0 From 5fed725e0a4e8d2617f2b8fc98191103d1ebd3ea Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Tue, 23 Jun 2020 23:59:32 +0200 Subject: [PATCH 3/8] Remove some leftover debugging checks --- lib/std/fs/wasi.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/fs/wasi.zig b/lib/std/fs/wasi.zig index fb6e6679fd1ecbd59db8f7f9e2da0e3e4a00e96b..db4317064dc1878405e05e2a6a179640f21dab0a 100644 --- a/lib/std/fs/wasi.zig +++ b/lib/std/fs/wasi.zig @@ -163,7 +163,6 @@ test "extracting WASI preopens" { std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len); const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable; - std.debug.print("\n{}\n", .{preopen}); - std.testing.expect(!preopen.@"type".eql(PreopenType{ .Dir = "." })); + std.testing.expect(preopen.@"type".eql(PreopenType{ .Dir = "." })); std.testing.expectEqual(@as(usize, 3), preopen.fd); } -- 2.54.0 From 93f0bcb649087b5db5cfcba5de5faaaf59047751 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 24 Jun 2020 01:59:19 -0400 Subject: [PATCH 4/8] building mingw-w64 for windows ARM looks in lib64/lib32 for .def files --- src/link.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/link.cpp b/src/link.cpp index 0f27cee9ab7897eda756eadaac40f54024f9c8c5..df33a5494ec99fd27bc2fd04181aa946741b02fd 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -2377,6 +2377,17 @@ static Error find_mingw_lib_def(LinkJob *lj, const char *name, Buf *out_path) { return err; } + if (!does_exist && target_is_arm(g->zig_target)) { + // Try lib32 or lib64 + const bool is_32 = target_arch_pointer_bit_width(g->zig_target->arch) == 32; + lib_path = is_32 ? "lib32" : "lib64"; + buf_resize(&override_path, 0); + buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), lib_path, name); + if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) { + return err; + } + } + if (!does_exist) { // Try the generic version buf_resize(&override_path, 0); -- 2.54.0 From 3aab6012c471522e2d1cd5a456f56cb9a7addeb6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 24 Jun 2020 02:08:08 -0400 Subject: [PATCH 5/8] Revert "building mingw-w64 for windows ARM looks in lib64/lib32 for .def files" This reverts commit 93f0bcb649087b5db5cfcba5de5faaaf59047751. This is not correct (from #mingw-w64 IRC): is there no .def file for ntdll on arm 64 bit? or does mingw-w64-crt/lib64/ntdll.def apply to both x86_64 and aarch64? andrewrk: there's none at the moment (as apps rarely link directly against ntdll, and I didn't want to guess needlessly around that one originally when I added arm64 support, before I actually had a real arm64 windows device) andrewrk: but I guess I could/should complete that now (if you need one right now, the libarm32 one probably is the closest match) --- src/link.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/link.cpp b/src/link.cpp index df33a5494ec99fd27bc2fd04181aa946741b02fd..0f27cee9ab7897eda756eadaac40f54024f9c8c5 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -2377,17 +2377,6 @@ static Error find_mingw_lib_def(LinkJob *lj, const char *name, Buf *out_path) { return err; } - if (!does_exist && target_is_arm(g->zig_target)) { - // Try lib32 or lib64 - const bool is_32 = target_arch_pointer_bit_width(g->zig_target->arch) == 32; - lib_path = is_32 ? "lib32" : "lib64"; - buf_resize(&override_path, 0); - buf_appendf(&override_path, "%s" OS_SEP "libc" OS_SEP "mingw" OS_SEP "%s" OS_SEP "%s.def", buf_ptr(g->zig_lib_dir), lib_path, name); - if ((err = os_file_exists(&override_path, &does_exist)) != ErrorNone) { - return err; - } - } - if (!does_exist) { // Try the generic version buf_resize(&override_path, 0); -- 2.54.0 From 3a2cc5decf5674b2d85c15b7d051c2f3bcf30904 Mon Sep 17 00:00:00 2001 From: Jonathan Marler Date: Tue, 23 Jun 2020 23:56:27 -0600 Subject: [PATCH 6/8] azure-pipelines: fix msys2 install --- ci/azure/pipelines.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/ci/azure/pipelines.yml b/ci/azure/pipelines.yml index fdf9d92d7d30d0125c3b3cb839612b450c937606..388d6db0449a1ce9539ead32fede0cda0deb0534 100644 --- a/ci/azure/pipelines.yml +++ b/ci/azure/pipelines.yml @@ -40,12 +40,20 @@ jobs: timeoutInMinutes: 360 steps: + - powershell: | + (New-Object Net.WebClient).DownloadFile("https://github.com/msys2/msys2-installer/releases/download/2020-06-02/msys2-base-x86_64-20200602.sfx.exe", "sfx.exe") + .\sfx.exe -y -o\ + del sfx.exe + displayName: Download/Extract/Install MSYS2 - script: | - git clone https://github.com/msys2/msys2-ci-base.git %CD:~0,2%\msys64 - %CD:~0,2%\msys64\usr\bin\rm -rf %CD:~0,2%\msys64\.git - set PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem - %CD:~0,2%\msys64\usr\bin\pacman --noconfirm -Syyuu - displayName: Install and Update MSYS2 + @REM install updated filesystem package first without dependency checking + @REM because of: https://github.com/msys2/MSYS2-packages/issues/2021 + %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Sydd filesystem" + displayName: Workaround filesystem dash MSYS2 dependency issue + - script: | + %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" + %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu" + displayName: Update MSYS2 - task: DownloadSecureFile@1 inputs: secureFile: s3cfg -- 2.54.0 From 489c31b6f5ad74bfa0ff1d91c049d0c11f931d94 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 24 Jun 2020 14:36:10 -0400 Subject: [PATCH 7/8] azure ci: install tar and xz with pacman --- ci/azure/windows_msvc_install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/azure/windows_msvc_install b/ci/azure/windows_msvc_install index ece3bbde114da94f1abe8ee5d1f90e30658a182f..8ac5181cab07d9de6d406fd1c61a018a0de98cdc 100644 --- a/ci/azure/windows_msvc_install +++ b/ci/azure/windows_msvc_install @@ -4,7 +4,7 @@ set -x set -e pacman -Su --needed --noconfirm -pacman -S --needed --noconfirm wget p7zip python3-pip +pacman -S --needed --noconfirm wget p7zip python3-pip tar xz pip install s3cmd wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz" tar xf llvm+clang+lld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz -- 2.54.0 From 129a4fb251f8eab22eacf219fbf81006baec3251 Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Wed, 24 Jun 2020 20:00:11 +0300 Subject: [PATCH 8/8] Copy union const values correctly --- src/analyze.cpp | 6 ++++++ test/stage1/behavior/type_info.zig | 8 ++++++++ 2 files changed, 14 insertions(+) diff --git a/src/analyze.cpp b/src/analyze.cpp index 542fbb56ce184b8fd52cb9ed168ad5165b18d51e..699b1212767d3bb1294f4b2d6490d21b441f4a22 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -9597,6 +9597,12 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) { break; } } + } else if (dest->type->id == ZigTypeIdUnion) { + bigint_init_bigint(&dest->data.x_union.tag, &src->data.x_union.tag); + dest->data.x_union.payload = g->pass1_arena->create(); + copy_const_val(g, dest->data.x_union.payload, src->data.x_union.payload); + dest->data.x_union.payload->parent.id = ConstParentIdUnion; + dest->data.x_union.payload->parent.data.p_union.union_val = dest; } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) { dest->data.x_optional = g->pass1_arena->create(); copy_const_val(g, dest->data.x_optional, src->data.x_optional); diff --git a/test/stage1/behavior/type_info.zig b/test/stage1/behavior/type_info.zig index 41301f290d9e5bccdff9813a480ccba47b4ca498..68ff3aa31030f361962aa13ceb3345367f81f6a6 100644 --- a/test/stage1/behavior/type_info.zig +++ b/test/stage1/behavior/type_info.zig @@ -402,3 +402,11 @@ test "type info for async frames" { else => unreachable, } } + +test "type info: value is correctly copied" { + comptime { + var ptrInfo = @typeInfo([]u32); + ptrInfo.Pointer.size = .One; + expect(@typeInfo([]u32).Pointer.size == .Slice); + } +} -- 2.54.0