| author | |
| committer | |
| log | 8d30fc45c424ed1aaf9067436a64b0744619c250 |
| tree | 69d6d86af25281f7d999990629305da76ff9913b |
| parent | 9766b68c475438e24885dd75cf137d51e72ccfa3 |
| signature |
we can run `std.debug.print` now, with both run-time strings and integers!22 files changed, 129 insertions(+), 151 deletions(-)
lib/compiler/test_runner.zig+9-7| ... | ... | @@ -271,6 +271,7 @@ pub fn mainSimple() anyerror!void { |
| 271 | 271 | }; |
| 272 | 272 | // is the backend capable of using std.fmt.format to print a summary at the end? |
| 273 | 273 | const print_summary = switch (builtin.zig_backend) { |
| 274 | .stage2_riscv64 => true, | |
| 274 | 275 | else => false, |
| 275 | 276 | }; |
| 276 | 277 | |
| ... | ... | @@ -282,11 +283,13 @@ pub fn mainSimple() anyerror!void { |
| 282 | 283 | const stderr = if (comptime enable_print) std.io.getStdErr() else {}; |
| 283 | 284 | |
| 284 | 285 | for (builtin.test_functions) |test_fn| { |
| 285 | if (enable_print) { | |
| 286 | stderr.writeAll(test_fn.name) catch {}; | |
| 287 | stderr.writeAll("... ") catch {}; | |
| 288 | } | |
| 289 | test_fn.func() catch |err| { | |
| 286 | if (test_fn.func()) |_| { | |
| 287 | if (enable_print) { | |
| 288 | stderr.writeAll(test_fn.name) catch {}; | |
| 289 | stderr.writeAll("... ") catch {}; | |
| 290 | stderr.writeAll("PASS\n") catch {}; | |
| 291 | } | |
| 292 | } else |err| if (enable_print) { | |
| 290 | 293 | if (enable_print) { |
| 291 | 294 | stderr.writeAll(test_fn.name) catch {}; |
| 292 | 295 | stderr.writeAll("... ") catch {}; |
| ... | ... | @@ -300,8 +303,7 @@ pub fn mainSimple() anyerror!void { |
| 300 | 303 | if (enable_print) stderr.writeAll("SKIP\n") catch {}; |
| 301 | 304 | skipped += 1; |
| 302 | 305 | continue; |
| 303 | }; | |
| 304 | if (enable_print) stderr.writeAll("PASS\n") catch {}; | |
| 306 | } | |
| 305 | 307 | passed += 1; |
| 306 | 308 | } |
| 307 | 309 | if (enable_print and print_summary) { |
lib/std/builtin.zig+1-8| ... | ... | @@ -775,14 +775,7 @@ pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr |
| 775 | 775 | } |
| 776 | 776 | |
| 777 | 777 | if (builtin.zig_backend == .stage2_riscv64) { |
| 778 | asm volatile ("ecall" | |
| 779 | : | |
| 780 | : [number] "{a7}" (64), | |
| 781 | [arg1] "{a0}" (1), | |
| 782 | [arg2] "{a1}" (@intFromPtr(msg.ptr)), | |
| 783 | [arg3] "{a2}" (msg.len), | |
| 784 | : "memory" | |
| 785 | ); | |
| 778 | std.debug.print("panic: {s}\n", .{msg}); | |
| 786 | 779 | std.posix.exit(127); |
| 787 | 780 | } |
| 788 | 781 |
src/Package/Module.zig+1-1| ... | ... | @@ -159,7 +159,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Package.Module { |
| 159 | 159 | |
| 160 | 160 | if (options.inherited.single_threaded) |x| break :b x; |
| 161 | 161 | if (options.parent) |p| break :b p.single_threaded; |
| 162 | break :b target_util.defaultSingleThreaded(target); | |
| 162 | break :b target_util.defaultSingleThreaded(target, zig_backend); | |
| 163 | 163 | }; |
| 164 | 164 | |
| 165 | 165 | const error_tracing = b: { |
src/arch/riscv64/CodeGen.zig+110-106| ... | ... | @@ -51,7 +51,6 @@ const InnerError = CodeGenError || error{OutOfRegisters}; |
| 51 | 51 | pt: Zcu.PerThread, |
| 52 | 52 | air: Air, |
| 53 | 53 | liveness: Liveness, |
| 54 | zcu: *Zcu, | |
| 55 | 54 | bin_file: *link.File, |
| 56 | 55 | gpa: Allocator, |
| 57 | 56 | |
| ... | ... | @@ -264,13 +263,13 @@ const MCValue = union(enum) { |
| 264 | 263 | .register_pair, |
| 265 | 264 | .memory, |
| 266 | 265 | .indirect, |
| 267 | .load_frame, | |
| 268 | 266 | .load_symbol, |
| 269 | 267 | .lea_symbol, |
| 270 | 268 | => switch (off) { |
| 271 | 269 | 0 => mcv, |
| 272 | else => unreachable, // not offsettable | |
| 270 | else => unreachable, | |
| 273 | 271 | }, |
| 272 | .load_frame => |frame| .{ .load_frame = .{ .index = frame.index, .off = frame.off + off } }, | |
| 274 | 273 | .immediate => |imm| .{ .immediate = @bitCast(@as(i64, @bitCast(imm)) +% off) }, |
| 275 | 274 | .register => |reg| .{ .register_offset = .{ .reg = reg, .off = off } }, |
| 276 | 275 | .register_offset => |reg_off| .{ .register_offset = .{ .reg = reg_off.reg, .off = reg_off.off + off } }, |
| ... | ... | @@ -737,7 +736,6 @@ pub fn generate( |
| 737 | 736 | .air = air, |
| 738 | 737 | .pt = pt, |
| 739 | 738 | .mod = mod, |
| 740 | .zcu = zcu, | |
| 741 | 739 | .bin_file = bin_file, |
| 742 | 740 | .liveness = liveness, |
| 743 | 741 | .target = target, |
| ... | ... | @@ -946,7 +944,7 @@ fn formatDecl( |
| 946 | 944 | } |
| 947 | 945 | fn fmtDecl(func: *Func, decl_index: InternPool.DeclIndex) std.fmt.Formatter(formatDecl) { |
| 948 | 946 | return .{ .data = .{ |
| 949 | .zcu = func.zcu, | |
| 947 | .zcu = func.pt.zcu, | |
| 950 | 948 | .decl_index = decl_index, |
| 951 | 949 | } }; |
| 952 | 950 | } |
| ... | ... | @@ -1325,6 +1323,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1325 | 1323 | .mul, |
| 1326 | 1324 | .mul_wrap, |
| 1327 | 1325 | .div_trunc, |
| 1326 | .rem, | |
| 1328 | 1327 | |
| 1329 | 1328 | .shl, .shl_exact, |
| 1330 | 1329 | .shr, .shr_exact, |
| ... | ... | @@ -1344,7 +1343,6 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1344 | 1343 | .ptr_add, |
| 1345 | 1344 | .ptr_sub => try func.airPtrArithmetic(inst, tag), |
| 1346 | 1345 | |
| 1347 | .rem, | |
| 1348 | 1346 | .mod, |
| 1349 | 1347 | .div_float, |
| 1350 | 1348 | .div_floor, |
| ... | ... | @@ -2151,11 +2149,16 @@ fn airTrunc(func: *Func, inst: Air.Inst.Index) !void { |
| 2151 | 2149 | const ty_op = func.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; |
| 2152 | 2150 | if (func.liveness.isUnused(inst)) |
| 2153 | 2151 | return func.finishAir(inst, .unreach, .{ ty_op.operand, .none, .none }); |
| 2154 | ||
| 2152 | // we assume no zeroext in the "Zig ABI", so it's fine to just not truncate it. | |
| 2155 | 2153 | const operand = try func.resolveInst(ty_op.operand); |
| 2156 | _ = operand; | |
| 2157 | return func.fail("TODO implement trunc for {}", .{func.target.cpu.arch}); | |
| 2158 | // return func.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | |
| 2154 | ||
| 2155 | // we can do it just to be safe, but this shouldn't be needed for no-runtime safety modes | |
| 2156 | switch (operand) { | |
| 2157 | .register => |reg| try func.truncateRegister(func.typeOf(ty_op.operand), reg), | |
| 2158 | else => {}, | |
| 2159 | } | |
| 2160 | ||
| 2161 | return func.finishAir(inst, operand, .{ ty_op.operand, .none, .none }); | |
| 2159 | 2162 | } |
| 2160 | 2163 | |
| 2161 | 2164 | fn airIntFromBool(func: *Func, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -2305,10 +2308,7 @@ fn binOp( |
| 2305 | 2308 | 80, 128 => true, |
| 2306 | 2309 | else => unreachable, |
| 2307 | 2310 | }; |
| 2308 | switch (air_tag) { | |
| 2309 | .rem, .mod => {}, | |
| 2310 | else => if (!type_needs_libcall) break :libcall, | |
| 2311 | } | |
| 2311 | if (!type_needs_libcall) break :libcall; | |
| 2312 | 2312 | return func.fail("binOp libcall runtime-float ops", .{}); |
| 2313 | 2313 | } |
| 2314 | 2314 | |
| ... | ... | @@ -2384,6 +2384,7 @@ fn genBinOp( |
| 2384 | 2384 | .sub_wrap, |
| 2385 | 2385 | .mul, |
| 2386 | 2386 | .mul_wrap, |
| 2387 | .rem, | |
| 2387 | 2388 | => { |
| 2388 | 2389 | if (!math.isPowerOfTwo(bit_size)) |
| 2389 | 2390 | return func.fail( |
| ... | ... | @@ -2391,6 +2392,15 @@ fn genBinOp( |
| 2391 | 2392 | .{ @tagName(tag), bit_size }, |
| 2392 | 2393 | ); |
| 2393 | 2394 | |
| 2395 | switch (tag) { | |
| 2396 | .rem, | |
| 2397 | => { | |
| 2398 | try func.truncateRegister(lhs_ty, lhs_reg); | |
| 2399 | try func.truncateRegister(rhs_ty, rhs_reg); | |
| 2400 | }, | |
| 2401 | else => {}, | |
| 2402 | } | |
| 2403 | ||
| 2394 | 2404 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 2395 | 2405 | .Int => { |
| 2396 | 2406 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| ... | ... | @@ -2409,6 +2419,10 @@ fn genBinOp( |
| 2409 | 2419 | 32 => .mulw, |
| 2410 | 2420 | else => unreachable, |
| 2411 | 2421 | }, |
| 2422 | .rem => switch (bit_size) { | |
| 2423 | 64 => if (is_unsigned) .remu else .rem, | |
| 2424 | else => if (is_unsigned) .remuw else .remu, | |
| 2425 | }, | |
| 2412 | 2426 | else => unreachable, |
| 2413 | 2427 | }; |
| 2414 | 2428 | |
| ... | ... | @@ -2423,14 +2437,6 @@ fn genBinOp( |
| 2423 | 2437 | }, |
| 2424 | 2438 | }, |
| 2425 | 2439 | }); |
| 2426 | ||
| 2427 | // truncate when the instruction is larger than the bit size. | |
| 2428 | switch (bit_size) { | |
| 2429 | 8, 16 => try func.truncateRegister(lhs_ty, dst_reg), | |
| 2430 | 32 => {}, // addw/subw affects the first 32-bits | |
| 2431 | 64 => {}, // add/sub affects the entire register | |
| 2432 | else => unreachable, | |
| 2433 | } | |
| 2434 | 2440 | }, |
| 2435 | 2441 | .Float => { |
| 2436 | 2442 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| ... | ... | @@ -2627,23 +2633,17 @@ fn genBinOp( |
| 2627 | 2633 | .shl, |
| 2628 | 2634 | .shl_exact, |
| 2629 | 2635 | => { |
| 2630 | if (!math.isPowerOfTwo(bit_size)) | |
| 2631 | return func.fail( | |
| 2632 | "TODO: genBinOp {s} non-pow 2, found {}", | |
| 2633 | .{ @tagName(tag), bit_size }, | |
| 2634 | ); | |
| 2635 | ||
| 2636 | // it's important that the shift amount is exact | |
| 2636 | if (bit_size > 64) return func.fail("TODO: genBinOp shift > 64 bits, {}", .{bit_size}); | |
| 2637 | 2637 | try func.truncateRegister(rhs_ty, rhs_reg); |
| 2638 | 2638 | |
| 2639 | 2639 | const mir_tag: Mir.Inst.Tag = switch (tag) { |
| 2640 | 2640 | .shl, .shl_exact => switch (bit_size) { |
| 2641 | 8, 16, 64 => .sll, | |
| 2641 | 1...31, 33...64 => .sll, | |
| 2642 | 2642 | 32 => .sllw, |
| 2643 | 2643 | else => unreachable, |
| 2644 | 2644 | }, |
| 2645 | 2645 | .shr, .shr_exact => switch (bit_size) { |
| 2646 | 8, 16, 64 => .srl, | |
| 2646 | 1...31, 33...64 => .srl, | |
| 2647 | 2647 | 32 => .srlw, |
| 2648 | 2648 | else => unreachable, |
| 2649 | 2649 | }, |
| ... | ... | @@ -2659,13 +2659,6 @@ fn genBinOp( |
| 2659 | 2659 | .rs2 = rhs_reg, |
| 2660 | 2660 | } }, |
| 2661 | 2661 | }); |
| 2662 | ||
| 2663 | switch (bit_size) { | |
| 2664 | 8, 16 => try func.truncateRegister(lhs_ty, dst_reg), | |
| 2665 | 32 => {}, | |
| 2666 | 64 => {}, | |
| 2667 | else => unreachable, | |
| 2668 | } | |
| 2669 | 2662 | }, |
| 2670 | 2663 | |
| 2671 | 2664 | // TODO: move the isel logic out of lower and into here. |
| ... | ... | @@ -2810,10 +2803,6 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 2810 | 2803 | if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { |
| 2811 | 2804 | const add_result = try func.binOp(null, .add, extra.lhs, extra.rhs); |
| 2812 | 2805 | |
| 2813 | const add_result_reg = try func.copyToTmpRegister(ty, add_result); | |
| 2814 | const add_result_reg_lock = func.register_manager.lockRegAssumeUnused(add_result_reg); | |
| 2815 | defer func.register_manager.unlockReg(add_result_reg_lock); | |
| 2816 | ||
| 2817 | 2806 | try func.genSetMem( |
| 2818 | 2807 | .{ .frame = offset.index }, |
| 2819 | 2808 | offset.off + @as(i32, @intCast(tuple_ty.structFieldOffset(0, pt))), |
| ... | ... | @@ -2821,14 +2810,21 @@ fn airAddWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 2821 | 2810 | add_result, |
| 2822 | 2811 | ); |
| 2823 | 2812 | |
| 2813 | const trunc_reg = try func.copyToTmpRegister(ty, add_result); | |
| 2814 | const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg); | |
| 2815 | defer func.register_manager.unlockReg(trunc_reg_lock); | |
| 2816 | ||
| 2824 | 2817 | const overflow_reg, const overflow_lock = try func.allocReg(.int); |
| 2825 | 2818 | defer func.register_manager.unlockReg(overflow_lock); |
| 2826 | 2819 | |
| 2820 | // if the result isn't equal after truncating it to the given type, | |
| 2821 | // an overflow must have happened. | |
| 2822 | try func.truncateRegister(func.typeOf(extra.lhs), trunc_reg); | |
| 2827 | 2823 | try func.genBinOp( |
| 2828 | 2824 | .cmp_neq, |
| 2829 | .{ .register = add_result_reg }, | |
| 2825 | add_result, | |
| 2830 | 2826 | ty, |
| 2831 | .{ .register = add_result_reg }, | |
| 2827 | .{ .register = trunc_reg }, | |
| 2832 | 2828 | ty, |
| 2833 | 2829 | overflow_reg, |
| 2834 | 2830 | ); |
| ... | ... | @@ -3022,61 +3018,34 @@ fn airMulWithOverflow(func: *Func, inst: Air.Inst.Index) !void { |
| 3022 | 3018 | switch (lhs_ty.zigTypeTag(zcu)) { |
| 3023 | 3019 | else => |x| return func.fail("TODO: airMulWithOverflow {s}", .{@tagName(x)}), |
| 3024 | 3020 | .Int => { |
| 3025 | assert(lhs_ty.eql(rhs_ty, zcu)); | |
| 3026 | const int_info = lhs_ty.intInfo(zcu); | |
| 3027 | switch (int_info.bits) { | |
| 3028 | 1...32 => { | |
| 3029 | if (int_info.bits >= 8 and math.isPowerOfTwo(int_info.bits)) { | |
| 3030 | if (int_info.signedness == .unsigned) { | |
| 3031 | switch (int_info.bits) { | |
| 3032 | 1...8 => { | |
| 3033 | const max_val = std.math.pow(u16, 2, int_info.bits) - 1; | |
| 3034 | ||
| 3035 | const add_reg, const add_lock = try func.promoteReg(lhs_ty, lhs); | |
| 3036 | defer if (add_lock) |lock| func.register_manager.unlockReg(lock); | |
| 3037 | ||
| 3038 | const overflow_reg, const overflow_lock = try func.allocReg(.int); | |
| 3039 | defer func.register_manager.unlockReg(overflow_lock); | |
| 3040 | ||
| 3041 | _ = try func.addInst(.{ | |
| 3042 | .tag = .andi, | |
| 3043 | .ops = .rri, | |
| 3044 | .data = .{ .i_type = .{ | |
| 3045 | .rd = overflow_reg, | |
| 3046 | .rs1 = add_reg, | |
| 3047 | .imm12 = Immediate.s(max_val), | |
| 3048 | } }, | |
| 3049 | }); | |
| 3050 | ||
| 3051 | try func.genBinOp( | |
| 3052 | .cmp_neq, | |
| 3053 | .{ .register = overflow_reg }, | |
| 3054 | lhs_ty, | |
| 3055 | .{ .register = add_reg }, | |
| 3056 | lhs_ty, | |
| 3057 | overflow_reg, | |
| 3058 | ); | |
| 3059 | ||
| 3060 | try func.genCopy( | |
| 3061 | lhs_ty, | |
| 3062 | result_mcv.offset(overflow_off), | |
| 3063 | .{ .register = overflow_reg }, | |
| 3064 | ); | |
| 3065 | ||
| 3066 | break :result result_mcv; | |
| 3067 | }, | |
| 3068 | ||
| 3069 | else => return func.fail("TODO: airMulWithOverflow check for size {d}", .{int_info.bits}), | |
| 3070 | } | |
| 3071 | } else { | |
| 3072 | return func.fail("TODO: airMulWithOverflow calculate carry for signed addition", .{}); | |
| 3073 | } | |
| 3074 | } else { | |
| 3075 | return func.fail("TODO: airMulWithOverflow with < 8 bits or non-pow of 2", .{}); | |
| 3076 | } | |
| 3077 | }, | |
| 3078 | else => return func.fail("TODO: airMulWithOverflow larger than 32-bit mul", .{}), | |
| 3079 | } | |
| 3021 | if (std.debug.runtime_safety) assert(lhs_ty.eql(rhs_ty, zcu)); | |
| 3022 | ||
| 3023 | const trunc_reg = try func.copyToTmpRegister(lhs_ty, .{ .register = dest_reg }); | |
| 3024 | const trunc_reg_lock = func.register_manager.lockRegAssumeUnused(trunc_reg); | |
| 3025 | defer func.register_manager.unlockReg(trunc_reg_lock); | |
| 3026 | ||
| 3027 | const overflow_reg, const overflow_lock = try func.allocReg(.int); | |
| 3028 | defer func.register_manager.unlockReg(overflow_lock); | |
| 3029 | ||
| 3030 | // if the result isn't equal after truncating it to the given type, | |
| 3031 | // an overflow must have happened. | |
| 3032 | try func.truncateRegister(func.typeOf(extra.lhs), trunc_reg); | |
| 3033 | try func.genBinOp( | |
| 3034 | .cmp_neq, | |
| 3035 | .{ .register = dest_reg }, | |
| 3036 | lhs_ty, | |
| 3037 | .{ .register = trunc_reg }, | |
| 3038 | rhs_ty, | |
| 3039 | overflow_reg, | |
| 3040 | ); | |
| 3041 | ||
| 3042 | try func.genCopy( | |
| 3043 | lhs_ty, | |
| 3044 | result_mcv.offset(overflow_off), | |
| 3045 | .{ .register = overflow_reg }, | |
| 3046 | ); | |
| 3047 | ||
| 3048 | break :result result_mcv; | |
| 3080 | 3049 | }, |
| 3081 | 3050 | } |
| 3082 | 3051 | }; |
| ... | ... | @@ -3317,7 +3286,17 @@ fn airWrapOptional(func: *Func, inst: Air.Inst.Index) !void { |
| 3317 | 3286 | Type.u8, |
| 3318 | 3287 | .{ .immediate = 1 }, |
| 3319 | 3288 | ), |
| 3320 | .register => return func.fail("TODO: airWrapOption opt_mcv register", .{}), | |
| 3289 | ||
| 3290 | .register => |opt_reg| { | |
| 3291 | try func.genBinOp( | |
| 3292 | .shl, | |
| 3293 | .{ .immediate = 1 }, | |
| 3294 | Type.u64, | |
| 3295 | .{ .immediate = 32 }, | |
| 3296 | Type.u64, | |
| 3297 | opt_reg, | |
| 3298 | ); | |
| 3299 | }, | |
| 3321 | 3300 | else => unreachable, |
| 3322 | 3301 | } |
| 3323 | 3302 | } |
| ... | ... | @@ -4059,7 +4038,7 @@ fn airLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 4059 | 4038 | const elem_size = elem_ty.abiSize(pt); |
| 4060 | 4039 | |
| 4061 | 4040 | const dst_mcv: MCValue = blk: { |
| 4062 | // Pointer is 8 bytes, and if the element is more than that, we cannot reuse it. | |
| 4041 | // "ptr" is 8 bytes, and if the element is more than that, we cannot reuse it. | |
| 4063 | 4042 | if (elem_size <= 8 and func.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 4064 | 4043 | // The MCValue that holds the pointer can be re-used as the value. |
| 4065 | 4044 | break :blk ptr; |
| ... | ... | @@ -4970,7 +4949,7 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 4970 | 4949 | .lea_symbol, |
| 4971 | 4950 | .reserved_frame, |
| 4972 | 4951 | .air_ref, |
| 4973 | => return func.fail("TODO: hmm {}", .{opt_mcv}), | |
| 4952 | => unreachable, | |
| 4974 | 4953 | |
| 4975 | 4954 | .register => |opt_reg| { |
| 4976 | 4955 | if (some_info.off == 0) { |
| ... | ... | @@ -4993,9 +4972,27 @@ fn isNull(func: *Func, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 4993 | 4972 | return return_mcv; |
| 4994 | 4973 | } |
| 4995 | 4974 | assert(some_info.ty.ip_index == .bool_type); |
| 4996 | const opt_abi_size: u32 = @intCast(opt_ty.abiSize(pt)); | |
| 4997 | _ = opt_abi_size; | |
| 4998 | return func.fail("TODO: isNull some_info.off != 0 register", .{}); | |
| 4975 | const bit_offset: u7 = @intCast(some_info.off * 8); | |
| 4976 | ||
| 4977 | try func.genBinOp( | |
| 4978 | .shr, | |
| 4979 | .{ .register = opt_reg }, | |
| 4980 | Type.u64, | |
| 4981 | .{ .immediate = bit_offset }, | |
| 4982 | Type.u8, | |
| 4983 | return_reg, | |
| 4984 | ); | |
| 4985 | try func.truncateRegister(Type.u8, return_reg); | |
| 4986 | try func.genBinOp( | |
| 4987 | .cmp_eq, | |
| 4988 | .{ .register = return_reg }, | |
| 4989 | Type.u64, | |
| 4990 | .{ .immediate = 0 }, | |
| 4991 | Type.u8, | |
| 4992 | return_reg, | |
| 4993 | ); | |
| 4994 | ||
| 4995 | return return_mcv; | |
| 4999 | 4996 | }, |
| 5000 | 4997 | |
| 5001 | 4998 | .load_frame => { |
| ... | ... | @@ -6556,7 +6553,8 @@ fn airAtomicRmw(func: *Func, inst: Air.Inst.Index) !void { |
| 6556 | 6553 | } |
| 6557 | 6554 | |
| 6558 | 6555 | fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6559 | const zcu = func.pt.zcu; | |
| 6556 | const pt = func.pt; | |
| 6557 | const zcu = pt.zcu; | |
| 6560 | 6558 | const atomic_load = func.air.instructions.items(.data)[@intFromEnum(inst)].atomic_load; |
| 6561 | 6559 | const order: std.builtin.AtomicOrder = atomic_load.order; |
| 6562 | 6560 | |
| ... | ... | @@ -6564,6 +6562,9 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6564 | 6562 | const elem_ty = ptr_ty.childType(zcu); |
| 6565 | 6563 | const ptr_mcv = try func.resolveInst(atomic_load.ptr); |
| 6566 | 6564 | |
| 6565 | const bit_size = elem_ty.bitSize(pt); | |
| 6566 | if (bit_size > 64) return func.fail("TODO: airAtomicStore > 64 bits", .{}); | |
| 6567 | ||
| 6567 | 6568 | const result_mcv = try func.allocRegOrMem(elem_ty, inst, true); |
| 6568 | 6569 | assert(result_mcv == .register); // should be less than 8 bytes |
| 6569 | 6570 | |
| ... | ... | @@ -6616,6 +6617,9 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 6616 | 6617 | const val_ty = func.typeOf(bin_op.rhs); |
| 6617 | 6618 | const val_mcv = try func.resolveInst(bin_op.rhs); |
| 6618 | 6619 | |
| 6620 | const bit_size = val_ty.bitSize(func.pt); | |
| 6621 | if (bit_size > 64) return func.fail("TODO: airAtomicStore > 64 bits", .{}); | |
| 6622 | ||
| 6619 | 6623 | switch (order) { |
| 6620 | 6624 | .unordered, .monotonic => {}, |
| 6621 | 6625 | .release, .seq_cst => { |
src/target.zig+2-1| ... | ... | @@ -60,9 +60,10 @@ pub fn alwaysSingleThreaded(target: std.Target) bool { |
| 60 | 60 | return false; |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | pub fn defaultSingleThreaded(target: std.Target) bool { | |
| 63 | pub fn defaultSingleThreaded(target: std.Target, backend: std.builtin.CompilerBackend) bool { | |
| 64 | 64 | switch (target.cpu.arch) { |
| 65 | 65 | .wasm32, .wasm64 => return true, |
| 66 | .riscv64 => if (backend == .stage2_riscv64) return true, | |
| 66 | 67 | else => {}, |
| 67 | 68 | } |
| 68 | 69 | switch (target.os.tag) { |
test/behavior/align.zig-1| ... | ... | @@ -16,7 +16,6 @@ test "global variable alignment" { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | test "large alignment of local constant" { |
| 19 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO | |
| 20 | 19 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 21 | 20 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 22 | 21 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; // flaky |
test/behavior/basic.zig-2| ... | ... | @@ -16,8 +16,6 @@ test "empty function with comments" { |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | test "truncate" { |
| 19 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 20 | ||
| 21 | 19 | try expect(testTruncate(0x10fd) == 0xfd); |
| 22 | 20 | comptime assert(testTruncate(0x10fd) == 0xfd); |
| 23 | 21 | } |
test/behavior/call.zig-1| ... | ... | @@ -441,7 +441,6 @@ test "non-anytype generic parameters provide result type" { |
| 441 | 441 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 442 | 442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 443 | 443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 444 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 445 | 444 | |
| 446 | 445 | const S = struct { |
| 447 | 446 | fn f(comptime T: type, y: T) !void { |
test/behavior/cast.zig-2| ... | ... | @@ -1845,7 +1845,6 @@ test "peer type resolution: three-way resolution combines error set and optional |
| 1845 | 1845 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1846 | 1846 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1847 | 1847 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1848 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1849 | 1848 | |
| 1850 | 1849 | const E = error{Foo}; |
| 1851 | 1850 | var a: E = error.Foo; |
| ... | ... | @@ -1960,7 +1959,6 @@ test "peer type resolution: vector and tuple" { |
| 1960 | 1959 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1961 | 1960 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1962 | 1961 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1963 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1964 | 1962 | |
| 1965 | 1963 | var vec: @Vector(3, i32) = .{ 1, 2, 3 }; |
| 1966 | 1964 | _ = &vec; |
test/behavior/destructure.zig-2| ... | ... | @@ -23,8 +23,6 @@ test "simple destructure" { |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | 25 | test "destructure with comptime syntax" { |
| 26 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 27 | ||
| 28 | 26 | const S = struct { |
| 29 | 27 | fn doTheTest() !void { |
| 30 | 28 | { |
test/behavior/enum.zig-1| ... | ... | @@ -1076,7 +1076,6 @@ test "enum literal casting to optional" { |
| 1076 | 1076 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1077 | 1077 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1078 | 1078 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1079 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1080 | 1079 | |
| 1081 | 1080 | var bar: ?Bar = undefined; |
| 1082 | 1081 | bar = .B; |
test/behavior/fn.zig-1| ... | ... | @@ -181,7 +181,6 @@ test "function with complex callconv and return type expressions" { |
| 181 | 181 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 182 | 182 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 183 | 183 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 184 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 185 | 184 | |
| 186 | 185 | try expect(fComplexCallconvRet(3).x == 9); |
| 187 | 186 | } |
test/behavior/for.zig-2| ... | ... | @@ -112,7 +112,6 @@ test "for with null and T peer types and inferred result location type" { |
| 112 | 112 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 113 | 113 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 114 | 114 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 115 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 116 | 115 | |
| 117 | 116 | const S = struct { |
| 118 | 117 | fn doTheTest(slice: []const u8) !void { |
| ... | ... | @@ -228,7 +227,6 @@ test "else continue outer for" { |
| 228 | 227 | |
| 229 | 228 | test "for loop with else branch" { |
| 230 | 229 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 231 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 232 | 230 | |
| 233 | 231 | { |
| 234 | 232 | var x = [_]u32{ 1, 2 }; |
test/behavior/if.zig-3| ... | ... | @@ -82,7 +82,6 @@ test "const result loc, runtime if cond, else unreachable" { |
| 82 | 82 | test "if copies its payload" { |
| 83 | 83 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 84 | 84 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 85 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 86 | 85 | |
| 87 | 86 | const S = struct { |
| 88 | 87 | fn doTheTest() !void { |
| ... | ... | @@ -147,8 +146,6 @@ test "if-else expression with runtime condition result location is inferred opti |
| 147 | 146 | } |
| 148 | 147 | |
| 149 | 148 | test "result location with inferred type ends up being pointer to comptime_int" { |
| 150 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 151 | ||
| 152 | 149 | var a: ?u32 = 1234; |
| 153 | 150 | var b: u32 = 2000; |
| 154 | 151 | _ = .{ &a, &b }; |
test/behavior/math.zig+6-3| ... | ... | @@ -689,6 +689,8 @@ fn testSignedWrappingEval(x: i32) !void { |
| 689 | 689 | } |
| 690 | 690 | |
| 691 | 691 | test "signed negation wrapping" { |
| 692 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 693 | ||
| 692 | 694 | try testSignedNegationWrappingEval(minInt(i16)); |
| 693 | 695 | try comptime testSignedNegationWrappingEval(minInt(i16)); |
| 694 | 696 | } |
| ... | ... | @@ -699,6 +701,8 @@ fn testSignedNegationWrappingEval(x: i16) !void { |
| 699 | 701 | } |
| 700 | 702 | |
| 701 | 703 | test "unsigned negation wrapping" { |
| 704 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 705 | ||
| 702 | 706 | try testUnsignedNegationWrappingEval(1); |
| 703 | 707 | try comptime testUnsignedNegationWrappingEval(1); |
| 704 | 708 | } |
| ... | ... | @@ -725,7 +729,6 @@ fn negateWrap(comptime T: type, x: T) T { |
| 725 | 729 | test "unsigned 64-bit division" { |
| 726 | 730 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 727 | 731 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 728 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 729 | 732 | |
| 730 | 733 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isMIPS()) { |
| 731 | 734 | // https://github.com/ziglang/zig/issues/16846 |
| ... | ... | @@ -838,7 +841,6 @@ test "@addWithOverflow" { |
| 838 | 841 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 839 | 842 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 840 | 843 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 841 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 842 | 844 | |
| 843 | 845 | try testAddWithOverflow(u8, 250, 100, 94, 1); |
| 844 | 846 | try testAddWithOverflow(u8, 100, 150, 250, 0); |
| ... | ... | @@ -927,7 +929,6 @@ fn testMulWithOverflow(comptime T: type, a: T, b: T, mul: T, bit: u1) !void { |
| 927 | 929 | test "basic @mulWithOverflow" { |
| 928 | 930 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 929 | 931 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 930 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 931 | 932 | |
| 932 | 933 | try testMulWithOverflow(u8, 86, 3, 2, 1); |
| 933 | 934 | try testMulWithOverflow(u8, 85, 3, 255, 0); |
| ... | ... | @@ -1330,6 +1331,8 @@ test "quad hex float literal parsing accurate" { |
| 1330 | 1331 | } |
| 1331 | 1332 | |
| 1332 | 1333 | test "truncating shift left" { |
| 1334 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1335 | ||
| 1333 | 1336 | try testShlTrunc(maxInt(u16)); |
| 1334 | 1337 | try comptime testShlTrunc(maxInt(u16)); |
| 1335 | 1338 | } |
test/behavior/null.zig-1| ... | ... | @@ -188,7 +188,6 @@ test "unwrap optional which is field of global var" { |
| 188 | 188 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 189 | 189 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 190 | 190 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 191 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 192 | 191 | |
| 193 | 192 | struct_with_optional.field = null; |
| 194 | 193 | if (struct_with_optional.field) |payload| { |
test/behavior/optional.zig-3| ... | ... | @@ -134,7 +134,6 @@ test "nested optional field in struct" { |
| 134 | 134 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 135 | 135 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 136 | 136 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 137 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 138 | 137 | |
| 139 | 138 | const S2 = struct { |
| 140 | 139 | y: u8, |
| ... | ... | @@ -287,7 +286,6 @@ test "nested orelse" { |
| 287 | 286 | test "self-referential struct through a slice of optional" { |
| 288 | 287 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 289 | 288 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 290 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 291 | 289 | |
| 292 | 290 | const S = struct { |
| 293 | 291 | const Node = struct { |
| ... | ... | @@ -566,7 +564,6 @@ test "Optional slice passed to function" { |
| 566 | 564 | test "peer type resolution in nested if expressions" { |
| 567 | 565 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 568 | 566 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 569 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 570 | 567 | |
| 571 | 568 | const Thing = struct { n: i32 }; |
| 572 | 569 | var a = false; |
test/behavior/packed-struct.zig-1| ... | ... | @@ -1096,7 +1096,6 @@ test "packed struct used as part of anon decl name" { |
| 1096 | 1096 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1097 | 1097 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1098 | 1098 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 1099 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1100 | 1099 | |
| 1101 | 1100 | const S = packed struct { a: u0 = 0 }; |
| 1102 | 1101 | var a: u8 = 0; |
test/behavior/struct.zig-1| ... | ... | @@ -1573,7 +1573,6 @@ test "no dependency loop on optional field wrapped in generic function" { |
| 1573 | 1573 | test "optional field init with tuple" { |
| 1574 | 1574 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1575 | 1575 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1576 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 1577 | 1576 | |
| 1578 | 1577 | const S = struct { |
| 1579 | 1578 | a: ?struct { b: u32 }, |
test/behavior/switch.zig-1| ... | ... | @@ -516,7 +516,6 @@ test "switch with null and T peer types and inferred result location type" { |
| 516 | 516 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 517 | 517 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 518 | 518 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 519 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 520 | 519 | |
| 521 | 520 | const S = struct { |
| 522 | 521 | fn doTheTest(c: u8) !void { |
test/behavior/threadlocal.zig-2| ... | ... | @@ -6,7 +6,6 @@ test "thread local variable" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 7 | 7 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 8 | 8 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 9 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 10 | 9 | if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) { |
| 11 | 10 | .x86_64, .x86 => {}, |
| 12 | 11 | else => return error.SkipZigTest, |
| ... | ... | @@ -47,7 +46,6 @@ test "reference a global threadlocal variable" { |
| 47 | 46 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 48 | 47 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 49 | 48 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 50 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 51 | 49 | if (builtin.zig_backend == .stage2_llvm) switch (builtin.cpu.arch) { |
| 52 | 50 | .x86_64, .x86 => {}, |
| 53 | 51 | else => return error.SkipZigTest, |
test/behavior/while.zig-1| ... | ... | @@ -106,7 +106,6 @@ fn testBreakOuter() void { |
| 106 | 106 | test "while copies its payload" { |
| 107 | 107 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 108 | 108 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 109 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 110 | 109 | |
| 111 | 110 | const S = struct { |
| 112 | 111 | fn doTheTest() !void { |