authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 15:36:59-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 15:36:59-04:00
loge42b7702eb2c74b923aa88492886c3f316188e99
tree7e4d18651c354ffb7f846316a9661059d963483d
parent14aa08fcd3ca6ef32fff9422969cb684cb81b9d7
parent129a4fb251f8eab22eacf219fbf81006baec3251

Merge remote-tracking branch 'origin/master' into zig-ast-to-zir


9 files changed, 136 insertions(+), 44 deletions(-)

ci/azure/pipelines.yml+13-5
......@@ -40,12 +40,20 @@ jobs:
4040 timeoutInMinutes: 360
4141
4242 steps:
43 - powershell: |
44 (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")
45 .\sfx.exe -y -o\
46 del sfx.exe
47 displayName: Download/Extract/Install MSYS2
4348 - script: |
44 git clone https://github.com/msys2/msys2-ci-base.git %CD:~0,2%\msys64
45 %CD:~0,2%\msys64\usr\bin\rm -rf %CD:~0,2%\msys64\.git
46 set PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem
47 %CD:~0,2%\msys64\usr\bin\pacman --noconfirm -Syyuu
48 displayName: Install and Update MSYS2
49 @REM install updated filesystem package first without dependency checking
50 @REM because of: https://github.com/msys2/MSYS2-packages/issues/2021
51 %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Sydd filesystem"
52 displayName: Workaround filesystem dash MSYS2 dependency issue
53 - script: |
54 %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
55 %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Syuu"
56 displayName: Update MSYS2
4957 - task: DownloadSecureFile@1
5058 inputs:
5159 secureFile: s3cfg
ci/azure/windows_msvc_install+1-1
......@@ -4,7 +4,7 @@ set -x
44set -e
55
66pacman -Su --needed --noconfirm
7pacman -S --needed --noconfirm wget p7zip python3-pip
7pacman -S --needed --noconfirm wget p7zip python3-pip tar xz
88pip install s3cmd
99wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz"
1010tar xf llvm+clang+lld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz
doc/langref.html.in+1-1
......@@ -9738,7 +9738,7 @@ pub fn main() !void {
97389738}
97399739 {#code_end#}
97409740 <pre><code>$ wasmtime --dir=. preopens.wasm
97410: { .fd = 3, .Dir = '.' }
97410: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } }
97429742</code></pre>
97439743 {#header_close#}
97449744 {#header_close#}
lib/std/fs/wasi.zig+41-35
......@@ -5,13 +5,39 @@ const Allocator = mem.Allocator;
55
66usingnamespace std.os.wasi;
77
8/// Type of WASI preopen.
8/// Type-tag of WASI preopen.
99///
1010/// WASI currently offers only `Dir` as a valid preopen resource.
11pub const PreopenType = enum {
11pub const PreopenTypeTag = enum {
1212 Dir,
1313};
1414
15/// Type of WASI preopen.
16///
17/// WASI currently offers only `Dir` as a valid preopen resource.
18pub const PreopenType = union(PreopenTypeTag) {
19 /// Preopened directory type.
20 Dir: []const u8,
21
22 const Self = @This();
23
24 pub fn eql(self: Self, other: PreopenType) bool {
25 if (!mem.eql(u8, @tagName(self), @tagName(other))) return false;
26
27 switch (self) {
28 PreopenTypeTag.Dir => |this_path| return mem.eql(u8, this_path, other.Dir),
29 }
30 }
31
32 pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void {
33 try out_stream.print("PreopenType{{ ", .{});
34 switch (self) {
35 PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}),
36 }
37 return out_stream.print(" }}", .{});
38 }
39};
40
1541/// WASI preopen struct. This struct consists of a WASI file descriptor
1642/// and type of WASI preopen. It can be obtained directly from the WASI
1743/// runtime using `PreopenList.populate()` method.
......@@ -20,29 +46,15 @@ pub const Preopen = struct {
2046 fd: fd_t,
2147
2248 /// Type of the preopen.
23 @"type": union(PreopenType) {
24 /// Path to a preopened directory.
25 Dir: []const u8,
26 },
49 @"type": PreopenType,
2750
28 const Self = @This();
29
30 /// Construct new `Preopen` instance of type `PreopenType.Dir` from
31 /// WASI file descriptor and WASI path.
32 pub fn newDir(fd: fd_t, path: []const u8) Self {
33 return Self{
51 /// Construct new `Preopen` instance.
52 pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen {
53 return Preopen{
3454 .fd = fd,
35 .@"type" = .{ .Dir = path },
55 .@"type" = preopen_type,
3656 };
3757 }
38
39 pub fn format(self: Self, comptime fmt: []const u8, options: std.fmt.FormatOptions, out_stream: var) !void {
40 try out_stream.print("{{ .fd = {}, ", .{self.fd});
41 switch (self.@"type") {
42 PreopenType.Dir => |path| try out_stream.print(".Dir = '{}'", .{path}),
43 }
44 return out_stream.print(" }}", .{});
45 }
4658};
4759
4860/// Dynamically-sized array list of WASI preopens. This struct is a
......@@ -113,24 +125,18 @@ pub const PreopenList = struct {
113125 ESUCCESS => {},
114126 else => |err| return os.unexpectedErrno(err),
115127 }
116 const preopen = Preopen.newDir(fd, path_buf);
128 const preopen = Preopen.new(fd, PreopenType{ .Dir = path_buf });
117129 try self.buffer.append(preopen);
118130 fd += 1;
119131 }
120132 }
121133
122 /// Find preopen by path. If the preopen exists, return it.
134 /// Find preopen by type. If the preopen exists, return it.
123135 /// Otherwise, return `null`.
124 ///
125 /// TODO make the function more generic by searching by `PreopenType` union. This will
126 /// be needed in the future when WASI extends its capabilities to resources
127 /// other than preopened directories.
128 pub fn find(self: Self, path: []const u8) ?*const Preopen {
129 for (self.buffer.items) |preopen| {
130 switch (preopen.@"type") {
131 PreopenType.Dir => |preopen_path| {
132 if (mem.eql(u8, path, preopen_path)) return &preopen;
133 },
136 pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen {
137 for (self.buffer.items) |*preopen| {
138 if (preopen.@"type".eql(preopen_type)) {
139 return preopen;
134140 }
135141 }
136142 return null;
......@@ -156,7 +162,7 @@ test "extracting WASI preopens" {
156162 try preopens.populate();
157163
158164 std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len);
159 const preopen = preopens.find(".") orelse unreachable;
160 std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir));
165 const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable;
166 std.testing.expect(preopen.@"type".eql(PreopenType{ .Dir = "." }));
161167 std.testing.expectEqual(@as(usize, 3), preopen.fd);
162168}
lib/std/testing.zig+1-1
......@@ -215,7 +215,7 @@ fn getCwdOrWasiPreopen() std.fs.Dir {
215215 defer preopens.deinit();
216216 preopens.populate() catch
217217 @panic("unable to make tmp dir for testing: unable to populate preopens");
218 const preopen = preopens.find(".") orelse
218 const preopen = preopens.find(std.fs.wasi.PreopenType{ .Dir = "." }) orelse
219219 @panic("unable to make tmp dir for testing: didn't find '.' in the preopens");
220220
221221 return std.fs.Dir{ .fd = preopen.fd };
src/analyze.cpp+6
......@@ -9597,6 +9597,12 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
95979597 break;
95989598 }
95999599 }
9600 } else if (dest->type->id == ZigTypeIdUnion) {
9601 bigint_init_bigint(&dest->data.x_union.tag, &src->data.x_union.tag);
9602 dest->data.x_union.payload = g->pass1_arena->create<ZigValue>();
9603 copy_const_val(g, dest->data.x_union.payload, src->data.x_union.payload);
9604 dest->data.x_union.payload->parent.id = ConstParentIdUnion;
9605 dest->data.x_union.payload->parent.data.p_union.union_val = dest;
96009606 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
96019607 dest->data.x_optional = g->pass1_arena->create<ZigValue>();
96029608 copy_const_val(g, dest->data.x_optional, src->data.x_optional);
src/ir.cpp+31-1
......@@ -28861,7 +28861,37 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
2886128861 ir_add_error(ira, &instruction->base.base,
2886228862 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
2886328863 return ira->codegen->invalid_inst_gen;
28864 }
28864 } else if(switch_type->id == ZigTypeIdMetaType) {
28865 HashMap<const ZigType*, IrInstGen*, type_ptr_hash, type_ptr_eql> prevs;
28866 // HashMap doubles capacity when reaching 60% capacity,
28867 // because we know the size at init we can avoid reallocation by doubling it here
28868 prevs.init(instruction->range_count * 2);
28869 for (size_t range_i = 0; range_i < instruction->range_count; range_i += 1) {
28870 IrInstSrcCheckSwitchProngsRange *range = &instruction->ranges[range_i];
28871
28872 IrInstGen *value = range->start->child;
28873 IrInstGen *casted_value = ir_implicit_cast(ira, value, switch_type);
28874 if (type_is_invalid(casted_value->value->type)) {
28875 prevs.deinit();
28876 return ira->codegen->invalid_inst_gen;
28877 }
28878
28879 ZigValue *const_expr_val = ir_resolve_const(ira, casted_value, UndefBad);
28880 if (!const_expr_val) {
28881 prevs.deinit();
28882 return ira->codegen->invalid_inst_gen;
28883 }
28884
28885 auto entry = prevs.put_unique(const_expr_val->data.x_type, value);
28886 if(entry != nullptr) {
28887 ErrorMsg *msg = ir_add_error(ira, &value->base, buf_sprintf("duplicate switch value"));
28888 add_error_note(ira->codegen, msg, entry->value->base.source_node, buf_sprintf("previous value is here"));
28889 prevs.deinit();
28890 return ira->codegen->invalid_inst_gen;
28891 }
28892 }
28893 prevs.deinit();
28894 }
2886528895 return ir_const_void(ira, &instruction->base.base);
2886628896}
2886728897
test/compile_errors.zig+34
......@@ -4362,6 +4362,40 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
43624362 "tmp.zig:5:14: note: previous value is here",
43634363 });
43644364
4365 cases.add("switch expression - duplicate type",
4366 \\fn foo(comptime T: type, x: T) u8 {
4367 \\ return switch (T) {
4368 \\ u32 => 0,
4369 \\ u64 => 1,
4370 \\ u32 => 2,
4371 \\ else => 3,
4372 \\ };
4373 \\}
4374 \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); }
4375 , &[_][]const u8{
4376 "tmp.zig:5:9: error: duplicate switch value",
4377 "tmp.zig:3:9: note: previous value is here",
4378 });
4379
4380 cases.add("switch expression - duplicate type (struct alias)",
4381 \\const Test = struct {
4382 \\ bar: i32,
4383 \\};
4384 \\const Test2 = Test;
4385 \\fn foo(comptime T: type, x: T) u8 {
4386 \\ return switch (T) {
4387 \\ Test => 0,
4388 \\ u64 => 1,
4389 \\ Test2 => 2,
4390 \\ else => 3,
4391 \\ };
4392 \\}
4393 \\export fn entry() usize { return @sizeOf(@TypeOf(foo(u32, 0))); }
4394 , &[_][]const u8{
4395 "tmp.zig:9:9: error: duplicate switch value",
4396 "tmp.zig:7:9: note: previous value is here",
4397 });
4398
43654399 cases.add("switch expression - switch on pointer type with no else",
43664400 \\fn foo(x: *u8) void {
43674401 \\ switch (x) {
test/stage1/behavior/type_info.zig+8
......@@ -402,3 +402,11 @@ test "type info for async frames" {
402402 else => unreachable,
403403 }
404404}
405
406test "type info: value is correctly copied" {
407 comptime {
408 var ptrInfo = @typeInfo([]u32);
409 ptrInfo.Pointer.size = .One;
410 expect(@typeInfo([]u32).Pointer.size == .Slice);
411 }
412}