| author | |
| committer | |
| log | 3e73f37d0a371276c534240ee2d26cbf4b3a0033 |
| tree | b0736a37d79066c8cb0649107fcb14db3ef260e7 |
| parent | 7a02878f4e1ff18275e61db7450fb3e12ee1926e |
| signature |
6 files changed, 75 insertions(+), 36 deletions(-)
src/arch/riscv64/CodeGen.zig+32-10| ... | ... | @@ -1318,7 +1318,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1318 | 1318 | .breakpoint => try func.airBreakpoint(), |
| 1319 | 1319 | .ret_addr => try func.airRetAddr(inst), |
| 1320 | 1320 | .frame_addr => try func.airFrameAddress(inst), |
| 1321 | .fence => try func.airFence(), | |
| 1321 | .fence => try func.airFence(inst), | |
| 1322 | 1322 | .cond_br => try func.airCondBr(inst), |
| 1323 | 1323 | .dbg_stmt => try func.airDbgStmt(inst), |
| 1324 | 1324 | .fptrunc => try func.airFptrunc(inst), |
| ... | ... | @@ -4238,9 +4238,28 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { |
| 4238 | 4238 | return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 4239 | 4239 | } |
| 4240 | 4240 | |
| 4241 | fn airFence(func: *Func) !void { | |
| 4242 | return func.fail("TODO implement fence() for {}", .{func.target.cpu.arch}); | |
| 4243 | //return func.finishAirBookkeeping(); | |
| 4241 | fn airFence(func: *Func, inst: Air.Inst.Index) !void { | |
| 4242 | const order = func.air.instructions.items(.data)[@intFromEnum(inst)].fence; | |
| 4243 | const pred: Mir.Barrier, const succ: Mir.Barrier = switch (order) { | |
| 4244 | .unordered, .monotonic => unreachable, | |
| 4245 | .acquire => .{ .r, .rw }, | |
| 4246 | .release => .{ .rw, .r }, | |
| 4247 | .acq_rel => .{ .rw, .rw }, | |
| 4248 | .seq_cst => .{ .rw, .rw }, | |
| 4249 | }; | |
| 4250 | ||
| 4251 | _ = try func.addInst(.{ | |
| 4252 | .tag = .pseudo, | |
| 4253 | .ops = .pseudo_fence, | |
| 4254 | .data = .{ | |
| 4255 | .fence = .{ | |
| 4256 | .pred = pred, | |
| 4257 | .succ = succ, | |
| 4258 | .fm = if (order == .acq_rel) .tso else .none, | |
| 4259 | }, | |
| 4260 | }, | |
| 4261 | }); | |
| 4262 | return func.finishAirBookkeeping(); | |
| 4244 | 4263 | } |
| 4245 | 4264 | |
| 4246 | 4265 | fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { |
| ... | ... | @@ -6264,12 +6283,13 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6264 | 6283 | |
| 6265 | 6284 | if (order == .seq_cst) { |
| 6266 | 6285 | _ = try func.addInst(.{ |
| 6267 | .tag = .fence, | |
| 6268 | .ops = .fence, | |
| 6286 | .tag = .pseudo, | |
| 6287 | .ops = .pseudo_fence, | |
| 6269 | 6288 | .data = .{ |
| 6270 | 6289 | .fence = .{ |
| 6271 | 6290 | .pred = .rw, |
| 6272 | 6291 | .succ = .rw, |
| 6292 | .fm = .none, | |
| 6273 | 6293 | }, |
| 6274 | 6294 | }, |
| 6275 | 6295 | }); |
| ... | ... | @@ -6284,12 +6304,13 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6284 | 6304 | // Make sure all previous reads happen before any reading or writing accurs. |
| 6285 | 6305 | .seq_cst, .acquire => { |
| 6286 | 6306 | _ = try func.addInst(.{ |
| 6287 | .tag = .fence, | |
| 6288 | .ops = .fence, | |
| 6307 | .tag = .pseudo, | |
| 6308 | .ops = .pseudo_fence, | |
| 6289 | 6309 | .data = .{ |
| 6290 | 6310 | .fence = .{ |
| 6291 | 6311 | .pred = .r, |
| 6292 | 6312 | .succ = .rw, |
| 6313 | .fm = .none, | |
| 6293 | 6314 | }, |
| 6294 | 6315 | }, |
| 6295 | 6316 | }); |
| ... | ... | @@ -6313,12 +6334,13 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 6313 | 6334 | .unordered, .monotonic => {}, |
| 6314 | 6335 | .release, .seq_cst => { |
| 6315 | 6336 | _ = try func.addInst(.{ |
| 6316 | .tag = .fence, | |
| 6317 | .ops = .fence, | |
| 6337 | .tag = .pseudo, | |
| 6338 | .ops = .pseudo_fence, | |
| 6318 | 6339 | .data = .{ |
| 6319 | 6340 | .fence = .{ |
| 6320 | 6341 | .pred = .rw, |
| 6321 | 6342 | .succ = .w, |
| 6343 | .fm = .none, | |
| 6322 | 6344 | }, |
| 6323 | 6345 | }, |
| 6324 | 6346 | }); |
src/arch/riscv64/Encoding.zig+24-15| ... | ... | @@ -45,6 +45,11 @@ const AmoWidth = enum(u3) { |
| 45 | 45 | D = 0b011, |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | const FenceMode = enum(u4) { | |
| 49 | none = 0b0000, | |
| 50 | tso = 0b1000, | |
| 51 | }; | |
| 52 | ||
| 48 | 53 | const Enc = struct { |
| 49 | 54 | opcode: OpCode, |
| 50 | 55 | |
| ... | ... | @@ -58,6 +63,10 @@ const Enc = struct { |
| 58 | 63 | funct5: u5, |
| 59 | 64 | width: AmoWidth, |
| 60 | 65 | }, |
| 66 | fence: struct { | |
| 67 | funct3: u3, | |
| 68 | fm: FenceMode, | |
| 69 | }, | |
| 61 | 70 | /// funct5 + rm + fmt |
| 62 | 71 | fmt: struct { |
| 63 | 72 | funct5: u5, |
| ... | ... | @@ -210,6 +219,7 @@ pub const Mnemonic = enum { |
| 210 | 219 | |
| 211 | 220 | // MISC |
| 212 | 221 | fence, |
| 222 | fencetso, | |
| 213 | 223 | |
| 214 | 224 | // AMO |
| 215 | 225 | amoswapw, |
| ... | ... | @@ -406,9 +416,12 @@ pub const Mnemonic = enum { |
| 406 | 416 | |
| 407 | 417 | .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } }, |
| 408 | 418 | |
| 419 | ||
| 409 | 420 | // MISC_MEM |
| 410 | 421 | |
| 411 | .fence => .{ .opcode = .MISC_MEM, .data = .{ .f = .{ .funct3 = 0b000 } } }, | |
| 422 | .fence => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .none } } }, | |
| 423 | .fencetso => .{ .opcode = .MISC_MEM, .data = .{ .fence = .{ .funct3 = 0b000, .fm = .tso } } }, | |
| 424 | ||
| 412 | 425 | |
| 413 | 426 | // AMO |
| 414 | 427 | |
| ... | ... | @@ -437,7 +450,6 @@ pub const Mnemonic = enum { |
| 437 | 450 | .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } }, |
| 438 | 451 | |
| 439 | 452 | |
| 440 | ||
| 441 | 453 | // zig fmt: on |
| 442 | 454 | }; |
| 443 | 455 | } |
| ... | ... | @@ -583,6 +595,7 @@ pub const InstEnc = enum { |
| 583 | 595 | => .system, |
| 584 | 596 | |
| 585 | 597 | .fence, |
| 598 | .fencetso, | |
| 586 | 599 | => .fence, |
| 587 | 600 | |
| 588 | 601 | .amoswapw, |
| ... | ... | @@ -689,7 +702,7 @@ pub const Data = union(InstEnc) { |
| 689 | 702 | rs1: u5 = 0, |
| 690 | 703 | succ: u4, |
| 691 | 704 | pred: u4, |
| 692 | _ignored: u4 = 0, | |
| 705 | fm: u4, | |
| 693 | 706 | }, |
| 694 | 707 | amo: packed struct { |
| 695 | 708 | opcode: u7, |
| ... | ... | @@ -711,11 +724,9 @@ pub const Data = union(InstEnc) { |
| 711 | 724 | |
| 712 | 725 | pub fn toU32(self: Data) u32 { |
| 713 | 726 | return switch (self) { |
| 714 | // zig fmt: off | |
| 715 | .B => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.imm11)) << 7) + (@as(u32, @intCast(v.imm1_4)) << 8) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.rs2)) << 20) + (@as(u32, @intCast(v.imm5_10)) << 25) + (@as(u32, @intCast(v.imm12)) << 31), | |
| 727 | .fence => |v| @as(u32, @intCast(v.opcode)) + (@as(u32, @intCast(v.rd)) << 7) + (@as(u32, @intCast(v.funct3)) << 12) + (@as(u32, @intCast(v.rs1)) << 15) + (@as(u32, @intCast(v.succ)) << 20) + (@as(u32, @intCast(v.pred)) << 24) + (@as(u32, @intCast(v.fm)) << 28), | |
| 716 | 728 | inline else => |v| @bitCast(v), |
| 717 | 729 | .system => unreachable, |
| 718 | // zig fmt: on | |
| 719 | 730 | }; |
| 720 | 731 | } |
| 721 | 732 | |
| ... | ... | @@ -869,16 +880,17 @@ pub const Data = union(InstEnc) { |
| 869 | 880 | .fence => { |
| 870 | 881 | assert(ops.len == 2); |
| 871 | 882 | |
| 872 | const succ = ops[0]; | |
| 873 | const pred = ops[1]; | |
| 883 | const succ = ops[0].barrier; | |
| 884 | const pred = ops[1].barrier; | |
| 874 | 885 | |
| 875 | 886 | return .{ |
| 876 | 887 | .fence = .{ |
| 877 | .succ = @intFromEnum(succ.barrier), | |
| 878 | .pred = @intFromEnum(pred.barrier), | |
| 888 | .succ = @intFromEnum(succ), | |
| 889 | .pred = @intFromEnum(pred), | |
| 879 | 890 | |
| 880 | 891 | .opcode = @intFromEnum(enc.opcode), |
| 881 | .funct3 = enc.data.f.funct3, | |
| 892 | .funct3 = enc.data.fence.funct3, | |
| 893 | .fm = @intFromEnum(enc.data.fence.fm), | |
| 882 | 894 | }, |
| 883 | 895 | }; |
| 884 | 896 | }, |
| ... | ... | @@ -891,7 +903,7 @@ pub const Data = union(InstEnc) { |
| 891 | 903 | const rl = ops[3]; |
| 892 | 904 | const aq = ops[4]; |
| 893 | 905 | |
| 894 | const ret: Data = .{ | |
| 906 | return .{ | |
| 895 | 907 | .amo = .{ |
| 896 | 908 | .rd = rd.reg.encodeId(), |
| 897 | 909 | .rs1 = rs1.reg.encodeId(), |
| ... | ... | @@ -906,9 +918,6 @@ pub const Data = union(InstEnc) { |
| 906 | 918 | .funct5 = enc.data.amo.funct5, |
| 907 | 919 | }, |
| 908 | 920 | }; |
| 909 | ||
| 910 | std.debug.print("ret: {}, {}", .{ ret.amo.rl, rl.barrier == .rl }); | |
| 911 | return ret; | |
| 912 | 921 | }, |
| 913 | 922 | |
| 914 | 923 | else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}), |
src/arch/riscv64/Lower.zig+12-4| ... | ... | @@ -443,6 +443,18 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index, options: struct { |
| 443 | 443 | }); |
| 444 | 444 | }, |
| 445 | 445 | |
| 446 | .pseudo_fence => { | |
| 447 | const fence = inst.data.fence; | |
| 448 | ||
| 449 | try lower.emit(switch (fence.fm) { | |
| 450 | .tso => .fencetso, | |
| 451 | .none => .fence, | |
| 452 | }, &.{ | |
| 453 | .{ .barrier = fence.succ }, | |
| 454 | .{ .barrier = fence.pred }, | |
| 455 | }); | |
| 456 | }, | |
| 457 | ||
| 446 | 458 | else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}), |
| 447 | 459 | }, |
| 448 | 460 | } |
| ... | ... | @@ -485,10 +497,6 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 485 | 497 | .{ .reg = inst.data.r_type.rs1 }, |
| 486 | 498 | .{ .reg = inst.data.r_type.rs2 }, |
| 487 | 499 | }, |
| 488 | .fence => &.{ | |
| 489 | .{ .barrier = inst.data.fence.succ }, | |
| 490 | .{ .barrier = inst.data.fence.pred }, | |
| 491 | }, | |
| 492 | 500 | else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}), |
| 493 | 501 | }); |
| 494 | 502 | } |
src/arch/riscv64/Mir.zig+7-5| ... | ... | @@ -80,8 +80,6 @@ pub const Inst = struct { |
| 80 | 80 | sh, |
| 81 | 81 | sb, |
| 82 | 82 | |
| 83 | fence, | |
| 84 | ||
| 85 | 83 | // M extension |
| 86 | 84 | mul, |
| 87 | 85 | mulw, |
| ... | ... | @@ -256,6 +254,10 @@ pub const Inst = struct { |
| 256 | 254 | fence: struct { |
| 257 | 255 | pred: Barrier, |
| 258 | 256 | succ: Barrier, |
| 257 | fm: enum { | |
| 258 | none, | |
| 259 | tso, | |
| 260 | }, | |
| 259 | 261 | }, |
| 260 | 262 | |
| 261 | 263 | amo: struct { |
| ... | ... | @@ -355,7 +357,7 @@ pub const Inst = struct { |
| 355 | 357 | pseudo_extern_fn_reloc, |
| 356 | 358 | |
| 357 | 359 | /// IORW, IORW |
| 358 | fence, | |
| 360 | pseudo_fence, | |
| 359 | 361 | |
| 360 | 362 | /// Ordering, Src, Addr, Dest |
| 361 | 363 | pseudo_amo, |
| ... | ... | @@ -396,8 +398,8 @@ pub const FrameLoc = struct { |
| 396 | 398 | |
| 397 | 399 | pub const Barrier = enum(u4) { |
| 398 | 400 | // Fence |
| 399 | r = 0b0001, | |
| 400 | w = 0b0010, | |
| 401 | w = 0b0001, | |
| 402 | r = 0b0010, | |
| 401 | 403 | rw = 0b0011, |
| 402 | 404 | |
| 403 | 405 | // Amo |
test/behavior/atomics.zig-1| ... | ... | @@ -42,7 +42,6 @@ test "fence" { |
| 42 | 42 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 43 | 43 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 44 | 44 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 45 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 46 | 45 | |
| 47 | 46 | var x: i32 = 1234; |
| 48 | 47 | @fence(.seq_cst); |
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1| ... | ... | @@ -11,7 +11,6 @@ test { |
| 11 | 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 12 | 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 13 | 13 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 14 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | |
| 15 | 14 | |
| 16 | 15 | var val: u8 = undefined; |
| 17 | 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); |