| author | |
| committer | |
| log | 6ff7b437ff34e9a416a041c0c0ff8a65bae8daf5 |
| tree | e8be8a2b2a1fa6524bead911f3607941d005d8ee |
| parent | 3cb387338234620e00645417565dc234dc5105c2 |
| parent | 413577c881963559f7f357bfd90f4ade6d6de20d |
| signature |
`zig2 build test-std` finale11 files changed, 155 insertions(+), 53 deletions(-)
lib/std/io/bit_reader.zig+3-7| ... | @@ -87,13 +87,9 @@ pub fn BitReader(endian: std.builtin.Endian, comptime ReaderType: type) type { | ... | @@ -87,13 +87,9 @@ pub fn BitReader(endian: std.builtin.Endian, comptime ReaderType: type) type { |
| 87 | //copy bytes until we have enough bits, then leave the rest in bit_buffer | 87 | //copy bytes until we have enough bits, then leave the rest in bit_buffer |
| 88 | while (out_bits.* < bits) { | 88 | while (out_bits.* < bits) { |
| 89 | const n = bits - out_bits.*; | 89 | const n = bits - out_bits.*; |
| 90 | const next_byte = self.forward_reader.readByte() catch |err| { | 90 | const next_byte = self.forward_reader.readByte() catch |err| switch (err) { |
| 91 | if (err == error.EndOfStream) { | 91 | error.EndOfStream => return @intCast(U, out_buffer), |
| 92 | return @intCast(U, out_buffer); | 92 | else => |e| return e, |
| 93 | } | ||
| 94 | //@BUG: See #1810. Not sure if the bug is that I have to do this for some | ||
| 95 | // streams, or that I don't for streams with emtpy errorsets. | ||
| 96 | return @errSetCast(Error, err); | ||
| 97 | }; | 93 | }; |
| 98 | 94 | ||
| 99 | switch (endian) { | 95 | switch (endian) { |
lib/std/io/stream_source.zig+1| ... | @@ -114,6 +114,7 @@ test "StreamSource (mutable buffer)" { | ... | @@ -114,6 +114,7 @@ test "StreamSource (mutable buffer)" { |
| 114 | } | 114 | } |
| 115 | 115 | ||
| 116 | test "StreamSource (const buffer)" { | 116 | test "StreamSource (const buffer)" { |
| 117 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 117 | const buffer: [64]u8 = "Hello, World!".* ++ ([1]u8{0xAA} ** 51); | 118 | const buffer: [64]u8 = "Hello, World!".* ++ ([1]u8{0xAA} ** 51); |
| 118 | var source = StreamSource{ .const_buffer = std.io.fixedBufferStream(&buffer) }; | 119 | var source = StreamSource{ .const_buffer = std.io.fixedBufferStream(&buffer) }; |
| 119 | 120 |
lib/std/math/big/rational.zig+2| ... | @@ -573,6 +573,7 @@ test "big.rational setFloatString" { | ... | @@ -573,6 +573,7 @@ test "big.rational setFloatString" { |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | test "big.rational toFloat" { | 575 | test "big.rational toFloat" { |
| 576 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 576 | var a = try Rational.init(testing.allocator); | 577 | var a = try Rational.init(testing.allocator); |
| 577 | defer a.deinit(); | 578 | defer a.deinit(); |
| 578 | 579 | ||
| ... | @@ -586,6 +587,7 @@ test "big.rational toFloat" { | ... | @@ -586,6 +587,7 @@ test "big.rational toFloat" { |
| 586 | } | 587 | } |
| 587 | 588 | ||
| 588 | test "big.rational set/to Float round-trip" { | 589 | test "big.rational set/to Float round-trip" { |
| 590 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 589 | var a = try Rational.init(testing.allocator); | 591 | var a = try Rational.init(testing.allocator); |
| 590 | defer a.deinit(); | 592 | defer a.deinit(); |
| 591 | var prng = std.rand.DefaultPrng.init(0x5EED); | 593 | var prng = std.rand.DefaultPrng.init(0x5EED); |
lib/std/net.zig+8-3| ... | @@ -1342,7 +1342,8 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { | ... | @@ -1342,7 +1342,8 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { |
| 1342 | }; | 1342 | }; |
| 1343 | defer file.close(); | 1343 | defer file.close(); |
| 1344 | 1344 | ||
| 1345 | const stream = std.io.bufferedReader(file.reader()).reader(); | 1345 | var buf_reader = std.io.bufferedReader(file.reader()); |
| 1346 | const stream = buf_reader.reader(); | ||
| 1346 | var line_buf: [512]u8 = undefined; | 1347 | var line_buf: [512]u8 = undefined; |
| 1347 | while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { | 1348 | while (stream.readUntilDelimiterOrEof(&line_buf, '\n') catch |err| switch (err) { |
| 1348 | error.StreamTooLong => blk: { | 1349 | error.StreamTooLong => blk: { |
| ... | @@ -1353,7 +1354,10 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { | ... | @@ -1353,7 +1354,10 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { |
| 1353 | }, | 1354 | }, |
| 1354 | else => |e| return e, | 1355 | else => |e| return e, |
| 1355 | }) |line| { | 1356 | }) |line| { |
| 1356 | const no_comment_line = mem.split(u8, line, "#").next().?; | 1357 | const no_comment_line = no_comment_line: { |
| 1358 | var split = mem.split(u8, line, "#"); | ||
| 1359 | break :no_comment_line split.next().?; | ||
| 1360 | }; | ||
| 1357 | var line_it = mem.tokenize(u8, no_comment_line, " \t"); | 1361 | var line_it = mem.tokenize(u8, no_comment_line, " \t"); |
| 1358 | 1362 | ||
| 1359 | const token = line_it.next() orelse continue; | 1363 | const token = line_it.next() orelse continue; |
| ... | @@ -1363,7 +1367,8 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { | ... | @@ -1363,7 +1367,8 @@ fn getResolvConf(allocator: mem.Allocator, rc: *ResolvConf) !void { |
| 1363 | const name = colon_it.next().?; | 1367 | const name = colon_it.next().?; |
| 1364 | const value_txt = colon_it.next() orelse continue; | 1368 | const value_txt = colon_it.next() orelse continue; |
| 1365 | const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) { | 1369 | const value = std.fmt.parseInt(u8, value_txt, 10) catch |err| switch (err) { |
| 1366 | error.Overflow => 255, | 1370 | // TODO https://github.com/ziglang/zig/issues/11812 |
| 1371 | error.Overflow => @as(u8, 255), | ||
| 1367 | error.InvalidCharacter => continue, | 1372 | error.InvalidCharacter => continue, |
| 1368 | }; | 1373 | }; |
| 1369 | if (mem.eql(u8, name, "ndots")) { | 1374 | if (mem.eql(u8, name, "ndots")) { |
lib/std/net/test.zig+4| ... | @@ -5,6 +5,7 @@ const mem = std.mem; | ... | @@ -5,6 +5,7 @@ const mem = std.mem; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| 6 | 6 | ||
| 7 | test "parse and render IPv6 addresses" { | 7 | test "parse and render IPv6 addresses" { |
| 8 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 8 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | 9 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 9 | 10 | ||
| 10 | var buffer: [100]u8 = undefined; | 11 | var buffer: [100]u8 = undefined; |
| ... | @@ -67,6 +68,7 @@ test "invalid but parseable IPv6 scope ids" { | ... | @@ -67,6 +68,7 @@ test "invalid but parseable IPv6 scope ids" { |
| 67 | } | 68 | } |
| 68 | 69 | ||
| 69 | test "parse and render IPv4 addresses" { | 70 | test "parse and render IPv4 addresses" { |
| 71 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 70 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | 72 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 71 | 73 | ||
| 72 | var buffer: [18]u8 = undefined; | 74 | var buffer: [18]u8 = undefined; |
| ... | @@ -91,6 +93,7 @@ test "parse and render IPv4 addresses" { | ... | @@ -91,6 +93,7 @@ test "parse and render IPv4 addresses" { |
| 91 | } | 93 | } |
| 92 | 94 | ||
| 93 | test "parse and render UNIX addresses" { | 95 | test "parse and render UNIX addresses" { |
| 96 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 94 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | 97 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 95 | if (!net.has_unix_sockets) return error.SkipZigTest; | 98 | if (!net.has_unix_sockets) return error.SkipZigTest; |
| 96 | 99 | ||
| ... | @@ -104,6 +107,7 @@ test "parse and render UNIX addresses" { | ... | @@ -104,6 +107,7 @@ test "parse and render UNIX addresses" { |
| 104 | } | 107 | } |
| 105 | 108 | ||
| 106 | test "resolve DNS" { | 109 | test "resolve DNS" { |
| 110 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 107 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | 111 | if (builtin.os.tag == .wasi) return error.SkipZigTest; |
| 108 | 112 | ||
| 109 | if (builtin.os.tag == .windows) { | 113 | if (builtin.os.tag == .windows) { |
lib/std/priority_queue.zig+1| ... | @@ -399,6 +399,7 @@ test "std.PriorityQueue: fromOwnedSlice trivial case 1" { | ... | @@ -399,6 +399,7 @@ test "std.PriorityQueue: fromOwnedSlice trivial case 1" { |
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | test "std.PriorityQueue: fromOwnedSlice" { | 401 | test "std.PriorityQueue: fromOwnedSlice" { |
| 402 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 402 | const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 }; | 403 | const items = [_]u32{ 15, 7, 21, 14, 13, 22, 12, 6, 7, 25, 5, 24, 11, 16, 15, 24, 2, 1 }; |
| 403 | const heap_items = try testing.allocator.dupe(u32, items[0..]); | 404 | const heap_items = try testing.allocator.dupe(u32, items[0..]); |
| 404 | var queue = PQlt.fromOwnedSlice(testing.allocator, heap_items[0..], {}); | 405 | var queue = PQlt.fromOwnedSlice(testing.allocator, heap_items[0..], {}); |
lib/std/simd.zig+1| ... | @@ -160,6 +160,7 @@ pub fn extract( | ... | @@ -160,6 +160,7 @@ pub fn extract( |
| 160 | } | 160 | } |
| 161 | 161 | ||
| 162 | test "vector patterns" { | 162 | test "vector patterns" { |
| 163 | if (@import("builtin").zig_backend != .stage1) return error.SkipZigTest; | ||
| 163 | const base = @Vector(4, u32){ 10, 20, 30, 40 }; | 164 | const base = @Vector(4, u32){ 10, 20, 30, 40 }; |
| 164 | const other_base = @Vector(4, u32){ 55, 66, 77, 88 }; | 165 | const other_base = @Vector(4, u32){ 55, 66, 77, 88 }; |
| 165 | 166 |
src/AstGen.zig+4-1| ... | @@ -6876,6 +6876,9 @@ fn asmExpr( | ... | @@ -6876,6 +6876,9 @@ fn asmExpr( |
| 6876 | const constraint = (try astgen.strLitAsString(constraint_token)).index; | 6876 | const constraint = (try astgen.strLitAsString(constraint_token)).index; |
| 6877 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; | 6877 | const has_arrow = token_tags[symbolic_name + 4] == .arrow; |
| 6878 | if (has_arrow) { | 6878 | if (has_arrow) { |
| 6879 | if (output_type_bits != 0) { | ||
| 6880 | return astgen.failNode(output_node, "inline assembly allows up to one output value", .{}); | ||
| 6881 | } | ||
| 6879 | output_type_bits |= @as(u32, 1) << @intCast(u5, i); | 6882 | output_type_bits |= @as(u32, 1) << @intCast(u5, i); |
| 6880 | const out_type_node = node_datas[output_node].lhs; | 6883 | const out_type_node = node_datas[output_node].lhs; |
| 6881 | const out_type_inst = try typeExpr(gz, scope, out_type_node); | 6884 | const out_type_inst = try typeExpr(gz, scope, out_type_node); |
| ... | @@ -6892,7 +6895,7 @@ fn asmExpr( | ... | @@ -6892,7 +6895,7 @@ fn asmExpr( |
| 6892 | outputs[i] = .{ | 6895 | outputs[i] = .{ |
| 6893 | .name = name, | 6896 | .name = name, |
| 6894 | .constraint = constraint, | 6897 | .constraint = constraint, |
| 6895 | .operand = try localVarRef(gz, scope, rl, node, ident_token), | 6898 | .operand = try localVarRef(gz, scope, .ref, node, ident_token), |
| 6896 | }; | 6899 | }; |
| 6897 | } | 6900 | } |
| 6898 | } | 6901 | } |
src/Sema.zig+74-32| ... | @@ -7774,7 +7774,12 @@ fn zirSwitchCapture( | ... | @@ -7774,7 +7774,12 @@ fn zirSwitchCapture( |
| 7774 | } | 7774 | } |
| 7775 | 7775 | ||
| 7776 | switch (operand_ty.zigTypeTag()) { | 7776 | switch (operand_ty.zigTypeTag()) { |
| 7777 | .ErrorSet => return sema.bitCast(block, block.switch_else_err_ty.?, operand, operand_src), | 7777 | .ErrorSet => if (block.switch_else_err_ty) |some| { |
| 7778 | return sema.bitCast(block, some, operand, operand_src); | ||
| 7779 | } else { | ||
| 7780 | try block.addUnreachable(operand_src, false); | ||
| 7781 | return Air.Inst.Ref.unreachable_value; | ||
| 7782 | }, | ||
| 7778 | else => return operand, | 7783 | else => return operand, |
| 7779 | } | 7784 | } |
| 7780 | } | 7785 | } |
| ... | @@ -8194,7 +8199,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8194,7 +8199,7 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8194 | ); | 8199 | ); |
| 8195 | } | 8200 | } |
| 8196 | else_error_ty = Type.@"anyerror"; | 8201 | else_error_ty = Type.@"anyerror"; |
| 8197 | } else { | 8202 | } else else_validation: { |
| 8198 | var maybe_msg: ?*Module.ErrorMsg = null; | 8203 | var maybe_msg: ?*Module.ErrorMsg = null; |
| 8199 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); | 8204 | errdefer if (maybe_msg) |msg| msg.destroy(sema.gpa); |
| 8200 | 8205 | ||
| ... | @@ -8231,6 +8236,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError | ... | @@ -8231,6 +8236,27 @@ fn zirSwitchBlock(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 8231 | } | 8236 | } |
| 8232 | 8237 | ||
| 8233 | if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) { | 8238 | if (special_prong == .@"else" and seen_errors.count() == operand_ty.errorSetNames().len) { |
| 8239 | |||
| 8240 | // In order to enable common patterns for generic code allow simple else bodies | ||
| 8241 | // else => unreachable, | ||
| 8242 | // else => return, | ||
| 8243 | // else => |e| return e, | ||
| 8244 | // even if all the possible errors were already handled. | ||
| 8245 | const tags = sema.code.instructions.items(.tag); | ||
| 8246 | for (special.body) |else_inst| switch (tags[else_inst]) { | ||
| 8247 | .dbg_block_begin, | ||
| 8248 | .dbg_block_end, | ||
| 8249 | .dbg_stmt, | ||
| 8250 | .dbg_var_val, | ||
| 8251 | .switch_capture, | ||
| 8252 | .ret_type, | ||
| 8253 | .as_node, | ||
| 8254 | .ret_node, | ||
| 8255 | .@"unreachable", | ||
| 8256 | => {}, | ||
| 8257 | else => break, | ||
| 8258 | } else break :else_validation; | ||
| 8259 | |||
| 8234 | return sema.fail( | 8260 | return sema.fail( |
| 8235 | block, | 8261 | block, |
| 8236 | special_prong_src, | 8262 | special_prong_src, |
| ... | @@ -11308,43 +11334,40 @@ fn zirAsm( | ... | @@ -11308,43 +11334,40 @@ fn zirAsm( |
| 11308 | try sema.requireRuntimeBlock(block, src); | 11334 | try sema.requireRuntimeBlock(block, src); |
| 11309 | } | 11335 | } |
| 11310 | 11336 | ||
| 11311 | if (outputs_len > 1) { | ||
| 11312 | return sema.fail(block, src, "TODO implement Sema for asm with more than 1 output", .{}); | ||
| 11313 | } | ||
| 11314 | |||
| 11315 | var extra_i = extra.end; | 11337 | var extra_i = extra.end; |
| 11316 | var output_type_bits = extra.data.output_type_bits; | 11338 | var output_type_bits = extra.data.output_type_bits; |
| 11317 | var needed_capacity: usize = @typeInfo(Air.Asm).Struct.fields.len + outputs_len + inputs_len; | 11339 | var needed_capacity: usize = @typeInfo(Air.Asm).Struct.fields.len + outputs_len + inputs_len; |
| 11318 | 11340 | ||
| 11319 | const Output = struct { | 11341 | const ConstraintName = struct { c: []const u8, n: []const u8 }; |
| 11320 | constraint: []const u8, | 11342 | const out_args = try sema.arena.alloc(Air.Inst.Ref, outputs_len); |
| 11321 | name: []const u8, | 11343 | const outputs = try sema.arena.alloc(ConstraintName, outputs_len); |
| 11322 | ty: Type, | 11344 | var expr_ty = Air.Inst.Ref.void_type; |
| 11323 | }; | 11345 | |
| 11324 | const output: ?Output = if (outputs_len == 0) null else blk: { | 11346 | for (out_args) |*arg, out_i| { |
| 11325 | const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i); | 11347 | const output = sema.code.extraData(Zir.Inst.Asm.Output, extra_i); |
| 11326 | extra_i = output.end; | 11348 | extra_i = output.end; |
| 11327 | 11349 | ||
| 11328 | const is_type = @truncate(u1, output_type_bits) != 0; | 11350 | const is_type = @truncate(u1, output_type_bits) != 0; |
| 11329 | output_type_bits >>= 1; | 11351 | output_type_bits >>= 1; |
| 11330 | 11352 | ||
| 11331 | if (!is_type) { | 11353 | if (is_type) { |
| 11332 | return sema.fail(block, src, "TODO implement Sema for asm with non `->` output", .{}); | 11354 | // Indicate the output is the asm instruction return value. |
| 11355 | arg.* = .none; | ||
| 11356 | const out_ty = try sema.resolveType(block, ret_ty_src, output.data.operand); | ||
| 11357 | expr_ty = try sema.addType(out_ty); | ||
| 11358 | } else { | ||
| 11359 | arg.* = try sema.resolveInst(output.data.operand); | ||
| 11333 | } | 11360 | } |
| 11334 | 11361 | ||
| 11335 | const constraint = sema.code.nullTerminatedString(output.data.constraint); | 11362 | const constraint = sema.code.nullTerminatedString(output.data.constraint); |
| 11336 | const name = sema.code.nullTerminatedString(output.data.name); | 11363 | const name = sema.code.nullTerminatedString(output.data.name); |
| 11337 | needed_capacity += (constraint.len + name.len + (2 + 3)) / 4; | 11364 | needed_capacity += (constraint.len + name.len + (2 + 3)) / 4; |
| 11338 | 11365 | ||
| 11339 | break :blk Output{ | 11366 | outputs[out_i] = .{ .c = constraint, .n = name }; |
| 11340 | .constraint = constraint, | 11367 | } |
| 11341 | .name = name, | ||
| 11342 | .ty = try sema.resolveType(block, ret_ty_src, output.data.operand), | ||
| 11343 | }; | ||
| 11344 | }; | ||
| 11345 | 11368 | ||
| 11346 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); | 11369 | const args = try sema.arena.alloc(Air.Inst.Ref, inputs_len); |
| 11347 | const inputs = try sema.arena.alloc(struct { c: []const u8, n: []const u8 }, inputs_len); | 11370 | const inputs = try sema.arena.alloc(ConstraintName, inputs_len); |
| 11348 | 11371 | ||
| 11349 | for (args) |*arg, arg_i| { | 11372 | for (args) |*arg, arg_i| { |
| 11350 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); | 11373 | const input = sema.code.extraData(Zir.Inst.Asm.Input, extra_i); |
| ... | @@ -11379,7 +11402,7 @@ fn zirAsm( | ... | @@ -11379,7 +11402,7 @@ fn zirAsm( |
| 11379 | const asm_air = try block.addInst(.{ | 11402 | const asm_air = try block.addInst(.{ |
| 11380 | .tag = .assembly, | 11403 | .tag = .assembly, |
| 11381 | .data = .{ .ty_pl = .{ | 11404 | .data = .{ .ty_pl = .{ |
| 11382 | .ty = if (output) |o| try sema.addType(o.ty) else Air.Inst.Ref.void_type, | 11405 | .ty = expr_ty, |
| 11383 | .payload = sema.addExtraAssumeCapacity(Air.Asm{ | 11406 | .payload = sema.addExtraAssumeCapacity(Air.Asm{ |
| 11384 | .source_len = @intCast(u32, asm_source.len), | 11407 | .source_len = @intCast(u32, asm_source.len), |
| 11385 | .outputs_len = outputs_len, | 11408 | .outputs_len = outputs_len, |
| ... | @@ -11388,18 +11411,15 @@ fn zirAsm( | ... | @@ -11388,18 +11411,15 @@ fn zirAsm( |
| 11388 | }), | 11411 | }), |
| 11389 | } }, | 11412 | } }, |
| 11390 | }); | 11413 | }); |
| 11391 | if (output != null) { | 11414 | sema.appendRefsAssumeCapacity(out_args); |
| 11392 | // Indicate the output is the asm instruction return value. | ||
| 11393 | sema.air_extra.appendAssumeCapacity(@enumToInt(Air.Inst.Ref.none)); | ||
| 11394 | } | ||
| 11395 | sema.appendRefsAssumeCapacity(args); | 11415 | sema.appendRefsAssumeCapacity(args); |
| 11396 | if (output) |o| { | 11416 | for (outputs) |o| { |
| 11397 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | 11417 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
| 11398 | mem.copy(u8, buffer, o.constraint); | 11418 | mem.copy(u8, buffer, o.c); |
| 11399 | buffer[o.constraint.len] = 0; | 11419 | buffer[o.c.len] = 0; |
| 11400 | mem.copy(u8, buffer[o.constraint.len + 1 ..], o.name); | 11420 | mem.copy(u8, buffer[o.c.len + 1 ..], o.n); |
| 11401 | buffer[o.constraint.len + 1 + o.name.len] = 0; | 11421 | buffer[o.c.len + 1 + o.n.len] = 0; |
| 11402 | sema.air_extra.items.len += (o.constraint.len + o.name.len + (2 + 3)) / 4; | 11422 | sema.air_extra.items.len += (o.c.len + o.n.len + (2 + 3)) / 4; |
| 11403 | } | 11423 | } |
| 11404 | for (inputs) |input| { | 11424 | for (inputs) |input| { |
| 11405 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); | 11425 | const buffer = mem.sliceAsBytes(sema.air_extra.unusedCapacitySlice()); |
| ... | @@ -21870,6 +21890,28 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -21870,6 +21890,28 @@ fn analyzeIsNonErrComptimeOnly( |
| 21870 | if (ies.is_anyerror) break :blk; | 21890 | if (ies.is_anyerror) break :blk; |
| 21871 | if (ies.errors.count() != 0) break :blk; | 21891 | if (ies.errors.count() != 0) break :blk; |
| 21872 | if (maybe_operand_val == null) { | 21892 | if (maybe_operand_val == null) { |
| 21893 | // Try to avoid resolving inferred error set if possible. | ||
| 21894 | if (ies.errors.count() != 0) break :blk; | ||
| 21895 | if (ies.is_anyerror) break :blk; | ||
| 21896 | var it = ies.inferred_error_sets.keyIterator(); | ||
| 21897 | while (it.next()) |other_error_set_ptr| { | ||
| 21898 | const other_ies: *Module.Fn.InferredErrorSet = other_error_set_ptr.*; | ||
| 21899 | if (ies == other_ies) continue; | ||
| 21900 | try sema.resolveInferredErrorSet(block, src, other_ies); | ||
| 21901 | if (other_ies.is_anyerror) { | ||
| 21902 | ies.is_anyerror = true; | ||
| 21903 | ies.is_resolved = true; | ||
| 21904 | break :blk; | ||
| 21905 | } | ||
| 21906 | |||
| 21907 | if (other_ies.errors.count() != 0) break :blk; | ||
| 21908 | } | ||
| 21909 | if (ies.func == sema.owner_func) { | ||
| 21910 | // We're checking the inferred errorset of the current function and none of | ||
| 21911 | // its child inferred error sets contained any errors meaning that any value | ||
| 21912 | // so far with this type can't contain errors either. | ||
| 21913 | return Air.Inst.Ref.bool_true; | ||
| 21914 | } | ||
| 21873 | try sema.resolveInferredErrorSet(block, src, ies); | 21915 | try sema.resolveInferredErrorSet(block, src, ies); |
| 21874 | if (ies.is_anyerror) break :blk; | 21916 | if (ies.is_anyerror) break :blk; |
| 21875 | if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true; | 21917 | if (ies.errors.count() == 0) return Air.Inst.Ref.bool_true; |
src/codegen/llvm.zig+15-10| ... | @@ -5012,7 +5012,7 @@ pub const FuncGen = struct { | ... | @@ -5012,7 +5012,7 @@ pub const FuncGen = struct { |
| 5012 | const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); | 5012 | const compiler_rt_operand_abbrev = compilerRtFloatAbbrev(operand_bits); |
| 5013 | 5013 | ||
| 5014 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); | 5014 | const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); |
| 5015 | const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "un"; | 5015 | const sign_prefix = if (dest_scalar_ty.isSignedInt()) "" else "uns"; |
| 5016 | 5016 | ||
| 5017 | var fn_name_buf: [64]u8 = undefined; | 5017 | var fn_name_buf: [64]u8 = undefined; |
| 5018 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ | 5018 | const fn_name = std.fmt.bufPrintZ(&fn_name_buf, "__fix{s}{s}f{s}i", .{ |
| ... | @@ -5435,10 +5435,6 @@ pub const FuncGen = struct { | ... | @@ -5435,10 +5435,6 @@ pub const FuncGen = struct { |
| 5435 | const inputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]); | 5435 | const inputs = @ptrCast([]const Air.Inst.Ref, self.air.extra[extra_i..][0..extra.data.inputs_len]); |
| 5436 | extra_i += inputs.len; | 5436 | extra_i += inputs.len; |
| 5437 | 5437 | ||
| 5438 | if (outputs.len > 1) { | ||
| 5439 | return self.todo("implement llvm codegen for asm with more than 1 output", .{}); | ||
| 5440 | } | ||
| 5441 | |||
| 5442 | var llvm_constraints: std.ArrayListUnmanaged(u8) = .{}; | 5438 | var llvm_constraints: std.ArrayListUnmanaged(u8) = .{}; |
| 5443 | defer llvm_constraints.deinit(self.gpa); | 5439 | defer llvm_constraints.deinit(self.gpa); |
| 5444 | 5440 | ||
| ... | @@ -5446,7 +5442,10 @@ pub const FuncGen = struct { | ... | @@ -5446,7 +5442,10 @@ pub const FuncGen = struct { |
| 5446 | defer arena_allocator.deinit(); | 5442 | defer arena_allocator.deinit(); |
| 5447 | const arena = arena_allocator.allocator(); | 5443 | const arena = arena_allocator.allocator(); |
| 5448 | 5444 | ||
| 5449 | const llvm_params_len = inputs.len; | 5445 | const return_count: u8 = for (outputs) |output| { |
| 5446 | if (output == .none) break 1; | ||
| 5447 | } else 0; | ||
| 5448 | const llvm_params_len = inputs.len + outputs.len - return_count; | ||
| 5450 | const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len); | 5449 | const llvm_param_types = try arena.alloc(*const llvm.Type, llvm_params_len); |
| 5451 | const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len); | 5450 | const llvm_param_values = try arena.alloc(*const llvm.Value, llvm_params_len); |
| 5452 | var llvm_param_i: usize = 0; | 5451 | var llvm_param_i: usize = 0; |
| ... | @@ -5456,9 +5455,6 @@ pub const FuncGen = struct { | ... | @@ -5456,9 +5455,6 @@ pub const FuncGen = struct { |
| 5456 | try name_map.ensureUnusedCapacity(arena, outputs.len + inputs.len); | 5455 | try name_map.ensureUnusedCapacity(arena, outputs.len + inputs.len); |
| 5457 | 5456 | ||
| 5458 | for (outputs) |output| { | 5457 | for (outputs) |output| { |
| 5459 | if (output != .none) { | ||
| 5460 | return self.todo("implement inline asm with non-returned output", .{}); | ||
| 5461 | } | ||
| 5462 | const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); | 5458 | const extra_bytes = std.mem.sliceAsBytes(self.air.extra[extra_i..]); |
| 5463 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); | 5459 | const constraint = std.mem.sliceTo(std.mem.sliceAsBytes(self.air.extra[extra_i..]), 0); |
| 5464 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); | 5460 | const name = std.mem.sliceTo(extra_bytes[constraint.len + 1 ..], 0); |
| ... | @@ -5471,6 +5467,15 @@ pub const FuncGen = struct { | ... | @@ -5471,6 +5467,15 @@ pub const FuncGen = struct { |
| 5471 | llvm_constraints.appendAssumeCapacity(','); | 5467 | llvm_constraints.appendAssumeCapacity(','); |
| 5472 | } | 5468 | } |
| 5473 | llvm_constraints.appendAssumeCapacity('='); | 5469 | llvm_constraints.appendAssumeCapacity('='); |
| 5470 | if (output != .none) { | ||
| 5471 | try llvm_constraints.ensureUnusedCapacity(self.gpa, llvm_constraints.capacity + 1); | ||
| 5472 | llvm_constraints.appendAssumeCapacity('*'); | ||
| 5473 | |||
| 5474 | const output_inst = try self.resolveInst(output); | ||
| 5475 | llvm_param_values[llvm_param_i] = output_inst; | ||
| 5476 | llvm_param_types[llvm_param_i] = output_inst.typeOf(); | ||
| 5477 | llvm_param_i += 1; | ||
| 5478 | } | ||
| 5474 | llvm_constraints.appendSliceAssumeCapacity(constraint[1..]); | 5479 | llvm_constraints.appendSliceAssumeCapacity(constraint[1..]); |
| 5475 | 5480 | ||
| 5476 | name_map.putAssumeCapacityNoClobber(name, {}); | 5481 | name_map.putAssumeCapacityNoClobber(name, {}); |
| ... | @@ -9284,7 +9289,7 @@ fn needDbgVarWorkaround(dg: *DeclGen, ty: Type) bool { | ... | @@ -9284,7 +9289,7 @@ fn needDbgVarWorkaround(dg: *DeclGen, ty: Type) bool { |
| 9284 | } | 9289 | } |
| 9285 | 9290 | ||
| 9286 | fn compilerRtIntBits(bits: u16) u16 { | 9291 | fn compilerRtIntBits(bits: u16) u16 { |
| 9287 | inline for (.{ 8, 16, 32, 64, 128 }) |b| { | 9292 | inline for (.{ 32, 64, 128 }) |b| { |
| 9288 | if (bits <= b) { | 9293 | if (bits <= b) { |
| 9289 | return b; | 9294 | return b; |
| 9290 | } | 9295 | } |
test/behavior/error.zig+42| ... | @@ -754,3 +754,45 @@ test "error union payload is properly aligned" { | ... | @@ -754,3 +754,45 @@ test "error union payload is properly aligned" { |
| 754 | const blk = S.foo() catch unreachable; | 754 | const blk = S.foo() catch unreachable; |
| 755 | if (blk.a != 1) unreachable; | 755 | if (blk.a != 1) unreachable; |
| 756 | } | 756 | } |
| 757 | |||
| 758 | test "ret_ptr doesn't cause own inferred error set to be resolved" { | ||
| 759 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 760 | |||
| 761 | const S = struct { | ||
| 762 | fn foo() !void {} | ||
| 763 | |||
| 764 | fn doTheTest() !void { | ||
| 765 | errdefer @compileError("bad"); | ||
| 766 | |||
| 767 | return try @This().foo(); | ||
| 768 | } | ||
| 769 | }; | ||
| 770 | try S.doTheTest(); | ||
| 771 | } | ||
| 772 | |||
| 773 | test "simple else prong allowed even when all errors handled" { | ||
| 774 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | ||
| 775 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | ||
| 776 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | ||
| 777 | |||
| 778 | const S = struct { | ||
| 779 | fn foo() !u8 { | ||
| 780 | return error.Foo; | ||
| 781 | } | ||
| 782 | }; | ||
| 783 | var value = S.foo() catch |err| switch (err) { | ||
| 784 | error.Foo => 255, | ||
| 785 | else => |e| return e, | ||
| 786 | }; | ||
| 787 | try expect(value == 255); | ||
| 788 | value = S.foo() catch |err| switch (err) { | ||
| 789 | error.Foo => 255, | ||
| 790 | else => unreachable, | ||
| 791 | }; | ||
| 792 | try expect(value == 255); | ||
| 793 | value = S.foo() catch |err| switch (err) { | ||
| 794 | error.Foo => 255, | ||
| 795 | else => return, | ||
| 796 | }; | ||
| 797 | try expect(value == 255); | ||
| 798 | } |