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:...@@ -40,12 +40,20 @@ jobs:
40 timeoutInMinutes: 36040 timeoutInMinutes: 360
4141
42 steps:42 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
43 - script: |48 - script: |
44 git clone https://github.com/msys2/msys2-ci-base.git %CD:~0,2%\msys6449 @REM install updated filesystem package first without dependency checking
45 %CD:~0,2%\msys64\usr\bin\rm -rf %CD:~0,2%\msys64\.git50 @REM because of: https://github.com/msys2/MSYS2-packages/issues/2021
46 set PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem51 %CD:~0,2%\msys64\usr\bin\bash -lc "pacman --noconfirm -Sydd filesystem"
47 %CD:~0,2%\msys64\usr\bin\pacman --noconfirm -Syyuu52 displayName: Workaround filesystem dash MSYS2 dependency issue
48 displayName: Install and Update MSYS253 - 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
49 - task: DownloadSecureFile@157 - task: DownloadSecureFile@1
50 inputs:58 inputs:
51 secureFile: s3cfg59 secureFile: s3cfg
ci/azure/windows_msvc_install+1-1
...@@ -4,7 +4,7 @@ set -x...@@ -4,7 +4,7 @@ set -x
4set -e4set -e
55
6pacman -Su --needed --noconfirm6pacman -Su --needed --noconfirm
7pacman -S --needed --noconfirm wget p7zip python3-pip7pacman -S --needed --noconfirm wget p7zip python3-pip tar xz
8pip install s3cmd8pip install s3cmd
9wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz"9wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz"
10tar xf llvm+clang+lld-10.0.0-x86_64-windows-msvc-release-mt.tar.xz10tar 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 {...@@ -9738,7 +9738,7 @@ pub fn main() !void {
9738}9738}
9739 {#code_end#}9739 {#code_end#}
9740 <pre><code>$ wasmtime --dir=. preopens.wasm9740 <pre><code>$ wasmtime --dir=. preopens.wasm
97410: { .fd = 3, .Dir = '.' }97410: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } }
9742</code></pre>9742</code></pre>
9743 {#header_close#}9743 {#header_close#}
9744 {#header_close#}9744 {#header_close#}
lib/std/fs/wasi.zig+41-35
...@@ -5,13 +5,39 @@ const Allocator = mem.Allocator;...@@ -5,13 +5,39 @@ const Allocator = mem.Allocator;
55
6usingnamespace std.os.wasi;6usingnamespace std.os.wasi;
77
8/// Type of WASI preopen.8/// Type-tag of WASI preopen.
9///9///
10/// WASI currently offers only `Dir` as a valid preopen resource.10/// WASI currently offers only `Dir` as a valid preopen resource.
11pub const PreopenType = enum {11pub const PreopenTypeTag = enum {
12 Dir,12 Dir,
13};13};
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
15/// WASI preopen struct. This struct consists of a WASI file descriptor41/// WASI preopen struct. This struct consists of a WASI file descriptor
16/// and type of WASI preopen. It can be obtained directly from the WASI42/// and type of WASI preopen. It can be obtained directly from the WASI
17/// runtime using `PreopenList.populate()` method.43/// runtime using `PreopenList.populate()` method.
...@@ -20,29 +46,15 @@ pub const Preopen = struct {...@@ -20,29 +46,15 @@ pub const Preopen = struct {
20 fd: fd_t,46 fd: fd_t,
2147
22 /// Type of the preopen.48 /// Type of the preopen.
23 @"type": union(PreopenType) {49 @"type": PreopenType,
24 /// Path to a preopened directory.
25 Dir: []const u8,
26 },
2750
28 const Self = @This();51 /// Construct new `Preopen` instance.
2952 pub fn new(fd: fd_t, preopen_type: PreopenType) Preopen {
30 /// Construct new `Preopen` instance of type `PreopenType.Dir` from53 return Preopen{
31 /// WASI file descriptor and WASI path.
32 pub fn newDir(fd: fd_t, path: []const u8) Self {
33 return Self{
34 .fd = fd,54 .fd = fd,
35 .@"type" = .{ .Dir = path },55 .@"type" = preopen_type,
36 };56 };
37 }57 }
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 }
46};58};
4759
48/// Dynamically-sized array list of WASI preopens. This struct is a60/// Dynamically-sized array list of WASI preopens. This struct is a
...@@ -113,24 +125,18 @@ pub const PreopenList = struct {...@@ -113,24 +125,18 @@ pub const PreopenList = struct {
113 ESUCCESS => {},125 ESUCCESS => {},
114 else => |err| return os.unexpectedErrno(err),126 else => |err| return os.unexpectedErrno(err),
115 }127 }
116 const preopen = Preopen.newDir(fd, path_buf);128 const preopen = Preopen.new(fd, PreopenType{ .Dir = path_buf });
117 try self.buffer.append(preopen);129 try self.buffer.append(preopen);
118 fd += 1;130 fd += 1;
119 }131 }
120 }132 }
121133
122 /// Find preopen by path. If the preopen exists, return it.134 /// Find preopen by type. If the preopen exists, return it.
123 /// Otherwise, return `null`.135 /// Otherwise, return `null`.
124 ///136 pub fn find(self: Self, preopen_type: PreopenType) ?*const Preopen {
125 /// TODO make the function more generic by searching by `PreopenType` union. This will137 for (self.buffer.items) |*preopen| {
126 /// be needed in the future when WASI extends its capabilities to resources138 if (preopen.@"type".eql(preopen_type)) {
127 /// other than preopened directories.139 return preopen;
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 },
134 }140 }
135 }141 }
136 return null;142 return null;
...@@ -156,7 +162,7 @@ test "extracting WASI preopens" {...@@ -156,7 +162,7 @@ test "extracting WASI preopens" {
156 try preopens.populate();162 try preopens.populate();
157163
158 std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len);164 std.testing.expectEqual(@as(usize, 1), preopens.asSlice().len);
159 const preopen = preopens.find(".") orelse unreachable;165 const preopen = preopens.find(PreopenType{ .Dir = "." }) orelse unreachable;
160 std.testing.expect(std.mem.eql(u8, ".", preopen.@"type".Dir));166 std.testing.expect(preopen.@"type".eql(PreopenType{ .Dir = "." }));
161 std.testing.expectEqual(@as(usize, 3), preopen.fd);167 std.testing.expectEqual(@as(usize, 3), preopen.fd);
162}168}
lib/std/testing.zig+1-1
...@@ -215,7 +215,7 @@ fn getCwdOrWasiPreopen() std.fs.Dir {...@@ -215,7 +215,7 @@ fn getCwdOrWasiPreopen() std.fs.Dir {
215 defer preopens.deinit();215 defer preopens.deinit();
216 preopens.populate() catch216 preopens.populate() catch
217 @panic("unable to make tmp dir for testing: unable to populate preopens");217 @panic("unable to make tmp dir for testing: unable to populate preopens");
218 const preopen = preopens.find(".") orelse218 const preopen = preopens.find(std.fs.wasi.PreopenType{ .Dir = "." }) orelse
219 @panic("unable to make tmp dir for testing: didn't find '.' in the preopens");219 @panic("unable to make tmp dir for testing: didn't find '.' in the preopens");
220220
221 return std.fs.Dir{ .fd = preopen.fd };221 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) {...@@ -9597,6 +9597,12 @@ void copy_const_val(CodeGen *g, ZigValue *dest, ZigValue *src) {
9597 break;9597 break;
9598 }9598 }
9599 }9599 }
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;
9600 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {9606 } else if (type_has_optional_repr(dest->type) && dest->data.x_optional != nullptr) {
9601 dest->data.x_optional = g->pass1_arena->create<ZigValue>();9607 dest->data.x_optional = g->pass1_arena->create<ZigValue>();
9602 copy_const_val(g, dest->data.x_optional, src->data.x_optional);9608 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,...@@ -28861,7 +28861,37 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
28861 ir_add_error(ira, &instruction->base.base,28861 ir_add_error(ira, &instruction->base.base,
28862 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));28862 buf_sprintf("else prong required when switching on type '%s'", buf_ptr(&switch_type->name)));
28863 return ira->codegen->invalid_inst_gen;28863 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 }
28865 return ir_const_void(ira, &instruction->base.base);28895 return ir_const_void(ira, &instruction->base.base);
28866}28896}
2886728897
test/compile_errors.zig+34
...@@ -4362,6 +4362,40 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4362,6 +4362,40 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4362 "tmp.zig:5:14: note: previous value is here",4362 "tmp.zig:5:14: note: previous value is here",
4363 });4363 });
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
4365 cases.add("switch expression - switch on pointer type with no else",4399 cases.add("switch expression - switch on pointer type with no else",
4366 \\fn foo(x: *u8) void {4400 \\fn foo(x: *u8) void {
4367 \\ switch (x) {4401 \\ switch (x) {
test/stage1/behavior/type_info.zig+8
...@@ -402,3 +402,11 @@ test "type info for async frames" {...@@ -402,3 +402,11 @@ test "type info for async frames" {
402 else => unreachable,402 else => unreachable,
403 }403 }
404}404}
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}