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

This commit is contained in:
Andrew Kelley
2020-06-24 15:36:59 -04:00
9 changed files with 136 additions and 44 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -9738,7 +9738,7 @@ pub fn main() !void {
}
{#code_end#}
<pre><code>$ wasmtime --dir=. preopens.wasm
0: { .fd = 3, .Dir = '.' }
0: Preopen{ .fd = 3, .type = PreopenType{ .Dir = '.' } }
</code></pre>
{#header_close#}
{#header_close#}

View File

@@ -5,11 +5,37 @@ const Allocator = mem.Allocator;
usingnamespace std.os.wasi;
/// Type-tag of WASI preopen.
///
/// WASI currently offers only `Dir` as a valid preopen resource.
pub const PreopenTypeTag = enum {
Dir,
};
/// Type of WASI preopen.
///
/// WASI currently offers only `Dir` as a valid preopen resource.
pub const PreopenType = enum {
Dir,
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
@@ -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,7 @@ 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.testing.expect(preopen.@"type".eql(PreopenType{ .Dir = "." }));
std.testing.expectEqual(@as(usize, 3), preopen.fd);
}

View File

@@ -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 };

View File

@@ -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<ZigValue>();
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<ZigValue>();
copy_const_val(g, dest->data.x_optional, src->data.x_optional);

View File

@@ -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<const ZigType*, IrInstGen*, type_ptr_hash, type_ptr_eql> 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);
}

View File

@@ -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) {

View File

@@ -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);
}
}