| author | |
| committer | |
| log | b5066fdae292f44a6e4c60db9a9db012672dd10e |
| tree | 6367bdaa9d4f19ed8905061a670aaff5e6f974f6 |
| parent | c03b733f0999418b234067cac51eac0e4412dfe1 |
| parent | 9f59189c954298fd2be576b7e3dd26388d07751d |
| signature |
stage2: make formatted printing work9 files changed, 87 insertions(+), 25 deletions(-)
lib/std/os/linux.zig+8-2| ... | ... | @@ -865,10 +865,16 @@ pub fn flock(fd: fd_t, operation: i32) usize { |
| 865 | 865 | return syscall2(.flock, @bitCast(usize, @as(isize, fd)), @bitCast(usize, @as(isize, operation))); |
| 866 | 866 | } |
| 867 | 867 | |
| 868 | var vdso_clock_gettime = @ptrCast(?*const anyopaque, init_vdso_clock_gettime); | |
| 868 | var vdso_clock_gettime = if (builtin.zig_backend == .stage1) | |
| 869 | @ptrCast(?*const anyopaque, init_vdso_clock_gettime) | |
| 870 | else | |
| 871 | @ptrCast(?*const anyopaque, &init_vdso_clock_gettime); | |
| 869 | 872 | |
| 870 | 873 | // We must follow the C calling convention when we call into the VDSO |
| 871 | const vdso_clock_gettime_ty = fn (i32, *timespec) callconv(.C) usize; | |
| 874 | const vdso_clock_gettime_ty = if (builtin.zig_backend == .stage1) | |
| 875 | fn (i32, *timespec) callconv(.C) usize | |
| 876 | else | |
| 877 | *const fn (i32, *timespec) callconv(.C) usize; | |
| 872 | 878 | |
| 873 | 879 | pub fn clock_gettime(clk_id: i32, tp: *timespec) usize { |
| 874 | 880 | if (@hasDecl(VDSO, "CGT_SYM")) { |
lib/std/special/test_runner.zig+9-8| ... | ... | @@ -23,10 +23,12 @@ fn processArgs() void { |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | pub fn main() void { |
| 26 | if (builtin.zig_backend != .stage1) { | |
| 26 | if (builtin.zig_backend != .stage1 and | |
| 27 | builtin.zig_backend != .stage2_llvm) | |
| 28 | { | |
| 27 | 29 | return main2() catch @panic("test failure"); |
| 28 | 30 | } |
| 29 | processArgs(); | |
| 31 | if (builtin.zig_backend == .stage1) processArgs(); | |
| 30 | 32 | const test_fn_list = builtin.test_functions; |
| 31 | 33 | var ok_count: usize = 0; |
| 32 | 34 | var skip_count: usize = 0; |
| ... | ... | @@ -44,9 +46,9 @@ pub fn main() void { |
| 44 | 46 | |
| 45 | 47 | var leaks: usize = 0; |
| 46 | 48 | for (test_fn_list) |test_fn, i| { |
| 47 | std.testing.allocator_instance = .{}; | |
| 49 | if (builtin.zig_backend != .stage2_llvm) std.testing.allocator_instance = .{}; | |
| 48 | 50 | defer { |
| 49 | if (std.testing.allocator_instance.deinit()) { | |
| 51 | if (builtin.zig_backend != .stage2_llvm and std.testing.allocator_instance.deinit()) { | |
| 50 | 52 | leaks += 1; |
| 51 | 53 | } |
| 52 | 54 | } |
| ... | ... | @@ -90,9 +92,9 @@ pub fn main() void { |
| 90 | 92 | fail_count += 1; |
| 91 | 93 | progress.log("FAIL ({s})\n", .{@errorName(err)}); |
| 92 | 94 | if (!have_tty) std.debug.print("FAIL ({s})\n", .{@errorName(err)}); |
| 93 | if (@errorReturnTrace()) |trace| { | |
| 95 | if (builtin.zig_backend != .stage2_llvm) if (@errorReturnTrace()) |trace| { | |
| 94 | 96 | std.debug.dumpStackTrace(trace.*); |
| 95 | } | |
| 97 | }; | |
| 96 | 98 | test_node.end(); |
| 97 | 99 | }, |
| 98 | 100 | } |
| ... | ... | @@ -141,8 +143,7 @@ pub fn main2() anyerror!void { |
| 141 | 143 | } |
| 142 | 144 | }; |
| 143 | 145 | } |
| 144 | if (builtin.zig_backend == .stage2_llvm or | |
| 145 | builtin.zig_backend == .stage2_wasm or | |
| 146 | if (builtin.zig_backend == .stage2_wasm or | |
| 146 | 147 | builtin.zig_backend == .stage2_x86_64) |
| 147 | 148 | { |
| 148 | 149 | const passed = builtin.test_functions.len - skipped - failed; |
src/AstGen.zig+8-1| ... | ... | @@ -244,10 +244,14 @@ pub const ResultLoc = union(enum) { |
| 244 | 244 | fn strategy(rl: ResultLoc, block_scope: *GenZir) Strategy { |
| 245 | 245 | switch (rl) { |
| 246 | 246 | // In this branch there will not be any store_to_block_ptr instructions. |
| 247 | .discard, .none, .ty, .coerced_ty, .ref => return .{ | |
| 247 | .none, .ty, .coerced_ty, .ref => return .{ | |
| 248 | 248 | .tag = .break_operand, |
| 249 | 249 | .elide_store_to_block_ptr_instructions = false, |
| 250 | 250 | }, |
| 251 | .discard => return .{ | |
| 252 | .tag = .break_void, | |
| 253 | .elide_store_to_block_ptr_instructions = false, | |
| 254 | }, | |
| 251 | 255 | // The pointer got passed through to the sub-expressions, so we will use |
| 252 | 256 | // break_void here. |
| 253 | 257 | // In this branch there will not be any store_to_block_ptr instructions. |
| ... | ... | @@ -1766,6 +1770,9 @@ fn breakExpr(parent_gz: *GenZir, parent_scope: *Scope, node: Ast.Node.Index) Inn |
| 1766 | 1770 | // we assume the result location is written, and we break with void. |
| 1767 | 1771 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); |
| 1768 | 1772 | }, |
| 1773 | .discard => { | |
| 1774 | _ = try parent_gz.addBreak(break_tag, block_inst, .void_value); | |
| 1775 | }, | |
| 1769 | 1776 | else => { |
| 1770 | 1777 | _ = try parent_gz.addBreak(break_tag, block_inst, operand); |
| 1771 | 1778 | }, |
src/Module.zig+1-1| ... | ... | @@ -3762,7 +3762,7 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { |
| 3762 | 3762 | // Note this resolves the type of the Decl, not the value; if this Decl |
| 3763 | 3763 | // is a struct, for example, this resolves `type` (which needs no resolution), |
| 3764 | 3764 | // not the struct itself. |
| 3765 | try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty); | |
| 3765 | try sema.resolveTypeFully(&block_scope, src, decl_tv.ty); | |
| 3766 | 3766 | |
| 3767 | 3767 | const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State); |
| 3768 | 3768 |
src/Sema.zig+23-9| ... | ... | @@ -4494,6 +4494,10 @@ fn analyzeCall( |
| 4494 | 4494 | |
| 4495 | 4495 | try sema.emitBackwardBranch(&child_block, call_src); |
| 4496 | 4496 | |
| 4497 | // Whether this call should be memoized, set to false if the call can mutate | |
| 4498 | // comptime state. | |
| 4499 | var should_memoize = true; | |
| 4500 | ||
| 4497 | 4501 | // This will have return instructions analyzed as break instructions to |
| 4498 | 4502 | // the block_inst above. Here we are performing "comptime/inline semantic analysis" |
| 4499 | 4503 | // for a function body, which means we must map the parameter ZIR instructions to |
| ... | ... | @@ -4527,6 +4531,7 @@ fn analyzeCall( |
| 4527 | 4531 | }, |
| 4528 | 4532 | else => {}, |
| 4529 | 4533 | } |
| 4534 | should_memoize = should_memoize and !arg_val.isComptimeMutablePtr(); | |
| 4530 | 4535 | memoized_call_key.args[arg_i] = .{ |
| 4531 | 4536 | .ty = param_ty, |
| 4532 | 4537 | .val = arg_val, |
| ... | ... | @@ -4552,6 +4557,7 @@ fn analyzeCall( |
| 4552 | 4557 | }, |
| 4553 | 4558 | else => {}, |
| 4554 | 4559 | } |
| 4560 | should_memoize = should_memoize and !arg_val.isComptimeMutablePtr(); | |
| 4555 | 4561 | memoized_call_key.args[arg_i] = .{ |
| 4556 | 4562 | .ty = sema.typeOf(uncasted_arg), |
| 4557 | 4563 | .val = arg_val, |
| ... | ... | @@ -4597,7 +4603,7 @@ fn analyzeCall( |
| 4597 | 4603 | // This `res2` is here instead of directly breaking from `res` due to a stage1 |
| 4598 | 4604 | // bug generating invalid LLVM IR. |
| 4599 | 4605 | const res2: Air.Inst.Ref = res2: { |
| 4600 | if (is_comptime_call) { | |
| 4606 | if (should_memoize and is_comptime_call) { | |
| 4601 | 4607 | if (mod.memoized_calls.get(memoized_call_key)) |result| { |
| 4602 | 4608 | const ty_inst = try sema.addType(fn_ret_ty); |
| 4603 | 4609 | try sema.air_values.append(gpa, result.val); |
| ... | ... | @@ -4621,7 +4627,7 @@ fn analyzeCall( |
| 4621 | 4627 | break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges); |
| 4622 | 4628 | }; |
| 4623 | 4629 | |
| 4624 | if (is_comptime_call) { | |
| 4630 | if (should_memoize and is_comptime_call) { | |
| 4625 | 4631 | const result_val = try sema.resolveConstMaybeUndefVal(block, call_src, result); |
| 4626 | 4632 | |
| 4627 | 4633 | // TODO: check whether any external comptime memory was mutated by the |
| ... | ... | @@ -10975,8 +10981,7 @@ fn zirCondbr( |
| 10975 | 10981 | |
| 10976 | 10982 | if (try sema.resolveDefinedValue(parent_block, src, cond)) |cond_val| { |
| 10977 | 10983 | const body = if (cond_val.toBool()) then_body else else_body; |
| 10978 | _ = try sema.analyzeBody(parent_block, body); | |
| 10979 | return always_noreturn; | |
| 10984 | return sema.analyzeBodyInner(parent_block, body); | |
| 10980 | 10985 | } |
| 10981 | 10986 | |
| 10982 | 10987 | const gpa = sema.gpa; |
| ... | ... | @@ -11948,19 +11953,27 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I |
| 11948 | 11953 | var buffer: Value.ToTypeBuffer = undefined; |
| 11949 | 11954 | const child_ty = child_val.toType(&buffer); |
| 11950 | 11955 | |
| 11956 | const ptr_size = size_val.toEnum(std.builtin.TypeInfo.Pointer.Size); | |
| 11957 | ||
| 11958 | var actual_sentinel: ?Value = null; | |
| 11951 | 11959 | if (!sentinel_val.isNull()) { |
| 11952 | return sema.fail(block, src, "TODO: implement zirReify for pointer with non-null sentinel", .{}); | |
| 11960 | if (ptr_size == .One or ptr_size == .C) { | |
| 11961 | return sema.fail(block, src, "sentinels are only allowed on slices and unknown-length pointers", .{}); | |
| 11962 | } | |
| 11963 | const sentinel_ptr_val = sentinel_val.castTag(.opt_payload).?.data; | |
| 11964 | const ptr_ty = try Type.ptr(sema.arena, .{ .@"addrspace" = .generic, .pointee_type = child_ty }); | |
| 11965 | actual_sentinel = (try sema.pointerDeref(block, src, sentinel_ptr_val, ptr_ty)).?; | |
| 11953 | 11966 | } |
| 11954 | 11967 | |
| 11955 | 11968 | const ty = try Type.ptr(sema.arena, .{ |
| 11956 | .size = size_val.toEnum(std.builtin.TypeInfo.Pointer.Size), | |
| 11969 | .size = ptr_size, | |
| 11957 | 11970 | .mutable = !is_const_val.toBool(), |
| 11958 | 11971 | .@"volatile" = is_volatile_val.toBool(), |
| 11959 | 11972 | .@"align" = @intCast(u8, alignment_val.toUnsignedInt()), // TODO: Validate this value. |
| 11960 | 11973 | .@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace), |
| 11961 | 11974 | .pointee_type = try child_ty.copy(sema.arena), |
| 11962 | 11975 | .@"allowzero" = is_allowzero_val.toBool(), |
| 11963 | .sentinel = null, | |
| 11976 | .sentinel = actual_sentinel, | |
| 11964 | 11977 | }); |
| 11965 | 11978 | return sema.addType(ty); |
| 11966 | 11979 | }, |
| ... | ... | @@ -12070,6 +12083,7 @@ fn zirIntToPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 12070 | 12083 | const type_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node }; |
| 12071 | 12084 | const type_res = try sema.resolveType(block, src, extra.lhs); |
| 12072 | 12085 | try sema.checkPtrType(block, type_src, type_res); |
| 12086 | _ = try sema.resolveTypeLayout(block, src, type_res.childType()); | |
| 12073 | 12087 | const ptr_align = type_res.ptrAlignment(sema.mod.getTarget()); |
| 12074 | 12088 | |
| 12075 | 12089 | if (try sema.resolveDefinedValue(block, operand_src, operand_coerced)) |val| { |
| ... | ... | @@ -17587,7 +17601,7 @@ fn resolvePeerTypes( |
| 17587 | 17601 | return chosen_ty; |
| 17588 | 17602 | } |
| 17589 | 17603 | |
| 17590 | pub fn resolveTypeLayout( | |
| 17604 | fn resolveTypeLayout( | |
| 17591 | 17605 | sema: *Sema, |
| 17592 | 17606 | block: *Block, |
| 17593 | 17607 | src: LazySrcLoc, |
| ... | ... | @@ -17660,7 +17674,7 @@ fn resolveUnionLayout( |
| 17660 | 17674 | union_obj.status = .have_layout; |
| 17661 | 17675 | } |
| 17662 | 17676 | |
| 17663 | fn resolveTypeFully( | |
| 17677 | pub fn resolveTypeFully( | |
| 17664 | 17678 | sema: *Sema, |
| 17665 | 17679 | block: *Block, |
| 17666 | 17680 | src: LazySrcLoc, |
src/codegen/llvm.zig+1-1| ... | ... | @@ -3892,7 +3892,7 @@ pub const FuncGen = struct { |
| 3892 | 3892 | return self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); |
| 3893 | 3893 | } |
| 3894 | 3894 | |
| 3895 | if (operand_ty.zigTypeTag() == .Int and inst_ty.zigTypeTag() == .Pointer) { | |
| 3895 | if (operand_ty.zigTypeTag() == .Int and inst_ty.isPtrAtRuntime()) { | |
| 3896 | 3896 | return self.builder.buildIntToPtr(operand, llvm_dest_ty, ""); |
| 3897 | 3897 | } |
| 3898 | 3898 |
src/type.zig+1-1| ... | ... | @@ -2602,7 +2602,7 @@ pub const Type = extern union { |
| 2602 | 2602 | const payload = self.castTag(.pointer).?.data; |
| 2603 | 2603 | return payload.@"allowzero"; |
| 2604 | 2604 | }, |
| 2605 | else => false, | |
| 2605 | else => return self.zigTypeTag() == .Optional, | |
| 2606 | 2606 | }; |
| 2607 | 2607 | } |
| 2608 | 2608 |
test/behavior.zig+2-2| ... | ... | @@ -125,6 +125,7 @@ test { |
| 125 | 125 | _ = @import("behavior/widening.zig"); |
| 126 | 126 | _ = @import("behavior/bugs/421.zig"); |
| 127 | 127 | _ = @import("behavior/bugs/726.zig"); |
| 128 | _ = @import("behavior/bugs/828.zig"); | |
| 128 | 129 | _ = @import("behavior/bugs/1421.zig"); |
| 129 | 130 | _ = @import("behavior/bugs/1442.zig"); |
| 130 | 131 | _ = @import("behavior/bugs/1607.zig"); |
| ... | ... | @@ -132,6 +133,7 @@ test { |
| 132 | 133 | _ = @import("behavior/bugs/3384.zig"); |
| 133 | 134 | _ = @import("behavior/bugs/3742.zig"); |
| 134 | 135 | _ = @import("behavior/bugs/5398.zig"); |
| 136 | _ = @import("behavior/bugs/5413.zig"); | |
| 135 | 137 | _ = @import("behavior/bugs/5487.zig"); |
| 136 | 138 | _ = @import("behavior/struct_contains_null_ptr_itself.zig"); |
| 137 | 139 | _ = @import("behavior/switch_prong_err_enum.zig"); |
| ... | ... | @@ -148,12 +150,10 @@ test { |
| 148 | 150 | _ = @import("behavior/await_struct.zig"); |
| 149 | 151 | _ = @import("behavior/bugs/529.zig"); |
| 150 | 152 | _ = @import("behavior/bugs/718.zig"); |
| 151 | _ = @import("behavior/bugs/828.zig"); | |
| 152 | 153 | _ = @import("behavior/bugs/920.zig"); |
| 153 | 154 | _ = @import("behavior/bugs/1120.zig"); |
| 154 | 155 | _ = @import("behavior/bugs/1851.zig"); |
| 155 | 156 | _ = @import("behavior/bugs/3779.zig"); |
| 156 | _ = @import("behavior/bugs/5413.zig"); | |
| 157 | 157 | _ = @import("behavior/bugs/6456.zig"); |
| 158 | 158 | _ = @import("behavior/bugs/6781.zig"); |
| 159 | 159 | _ = @import("behavior/bugs/7003.zig"); |
test/behavior/basic.zig+34| ... | ... | @@ -819,3 +819,37 @@ test "if expression type coercion" { |
| 819 | 819 | const x: u16 = if (cond) 1 else 0; |
| 820 | 820 | try expect(@as(u16, x) == 1); |
| 821 | 821 | } |
| 822 | ||
| 823 | test "discarding the result of various expressions" { | |
| 824 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | |
| 825 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | |
| 826 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | |
| 827 | ||
| 828 | const S = struct { | |
| 829 | fn foo() !u32 { | |
| 830 | return 1; | |
| 831 | } | |
| 832 | fn bar() ?u32 { | |
| 833 | return 1; | |
| 834 | } | |
| 835 | }; | |
| 836 | _ = S.bar() orelse { | |
| 837 | // do nothing | |
| 838 | }; | |
| 839 | _ = S.foo() catch { | |
| 840 | // do nothing | |
| 841 | }; | |
| 842 | _ = switch (1) { | |
| 843 | 1 => 1, | |
| 844 | 2 => {}, | |
| 845 | else => return, | |
| 846 | }; | |
| 847 | _ = try S.foo(); | |
| 848 | _ = if (S.bar()) |some| some else {}; | |
| 849 | _ = blk: { | |
| 850 | if (S.bar()) |some| break :blk some; | |
| 851 | break :blk; | |
| 852 | }; | |
| 853 | _ = while (S.bar()) |some| break some else {}; | |
| 854 | _ = for ("foo") |char| break char else {}; | |
| 855 | } |