| 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,7 +1318,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void { |
| 1318 | .breakpoint => try func.airBreakpoint(), | 1318 | .breakpoint => try func.airBreakpoint(), |
| 1319 | .ret_addr => try func.airRetAddr(inst), | 1319 | .ret_addr => try func.airRetAddr(inst), |
| 1320 | .frame_addr => try func.airFrameAddress(inst), | 1320 | .frame_addr => try func.airFrameAddress(inst), |
| 1321 | .fence => try func.airFence(), | 1321 | .fence => try func.airFence(inst), |
| 1322 | .cond_br => try func.airCondBr(inst), | 1322 | .cond_br => try func.airCondBr(inst), |
| 1323 | .dbg_stmt => try func.airDbgStmt(inst), | 1323 | .dbg_stmt => try func.airDbgStmt(inst), |
| 1324 | .fptrunc => try func.airFptrunc(inst), | 1324 | .fptrunc => try func.airFptrunc(inst), |
| ... | @@ -4238,9 +4238,28 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { | ... | @@ -4238,9 +4238,28 @@ fn airFrameAddress(func: *Func, inst: Air.Inst.Index) !void { |
| 4238 | return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); | 4238 | return func.finishAir(inst, dst_mcv, .{ .none, .none, .none }); |
| 4239 | } | 4239 | } |
| 4240 | 4240 | ||
| 4241 | fn airFence(func: *Func) !void { | 4241 | fn airFence(func: *Func, inst: Air.Inst.Index) !void { |
| 4242 | return func.fail("TODO implement fence() for {}", .{func.target.cpu.arch}); | 4242 | const order = func.air.instructions.items(.data)[@intFromEnum(inst)].fence; |
| 4243 | //return func.finishAirBookkeeping(); | 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 | fn airCall(func: *Func, inst: Air.Inst.Index, modifier: std.builtin.CallModifier) !void { | 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,12 +6283,13 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6264 | 6283 | ||
| 6265 | if (order == .seq_cst) { | 6284 | if (order == .seq_cst) { |
| 6266 | _ = try func.addInst(.{ | 6285 | _ = try func.addInst(.{ |
| 6267 | .tag = .fence, | 6286 | .tag = .pseudo, |
| 6268 | .ops = .fence, | 6287 | .ops = .pseudo_fence, |
| 6269 | .data = .{ | 6288 | .data = .{ |
| 6270 | .fence = .{ | 6289 | .fence = .{ |
| 6271 | .pred = .rw, | 6290 | .pred = .rw, |
| 6272 | .succ = .rw, | 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,12 +6304,13 @@ fn airAtomicLoad(func: *Func, inst: Air.Inst.Index) !void { |
| 6284 | // Make sure all previous reads happen before any reading or writing accurs. | 6304 | // Make sure all previous reads happen before any reading or writing accurs. |
| 6285 | .seq_cst, .acquire => { | 6305 | .seq_cst, .acquire => { |
| 6286 | _ = try func.addInst(.{ | 6306 | _ = try func.addInst(.{ |
| 6287 | .tag = .fence, | 6307 | .tag = .pseudo, |
| 6288 | .ops = .fence, | 6308 | .ops = .pseudo_fence, |
| 6289 | .data = .{ | 6309 | .data = .{ |
| 6290 | .fence = .{ | 6310 | .fence = .{ |
| 6291 | .pred = .r, | 6311 | .pred = .r, |
| 6292 | .succ = .rw, | 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,12 +6334,13 @@ fn airAtomicStore(func: *Func, inst: Air.Inst.Index, order: std.builtin.AtomicOr |
| 6313 | .unordered, .monotonic => {}, | 6334 | .unordered, .monotonic => {}, |
| 6314 | .release, .seq_cst => { | 6335 | .release, .seq_cst => { |
| 6315 | _ = try func.addInst(.{ | 6336 | _ = try func.addInst(.{ |
| 6316 | .tag = .fence, | 6337 | .tag = .pseudo, |
| 6317 | .ops = .fence, | 6338 | .ops = .pseudo_fence, |
| 6318 | .data = .{ | 6339 | .data = .{ |
| 6319 | .fence = .{ | 6340 | .fence = .{ |
| 6320 | .pred = .rw, | 6341 | .pred = .rw, |
| 6321 | .succ = .w, | 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,6 +45,11 @@ const AmoWidth = enum(u3) { |
| 45 | D = 0b011, | 45 | D = 0b011, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | const FenceMode = enum(u4) { | ||
| 49 | none = 0b0000, | ||
| 50 | tso = 0b1000, | ||
| 51 | }; | ||
| 52 | |||
| 48 | const Enc = struct { | 53 | const Enc = struct { |
| 49 | opcode: OpCode, | 54 | opcode: OpCode, |
| 50 | 55 | ||
| ... | @@ -58,6 +63,10 @@ const Enc = struct { | ... | @@ -58,6 +63,10 @@ const Enc = struct { |
| 58 | funct5: u5, | 63 | funct5: u5, |
| 59 | width: AmoWidth, | 64 | width: AmoWidth, |
| 60 | }, | 65 | }, |
| 66 | fence: struct { | ||
| 67 | funct3: u3, | ||
| 68 | fm: FenceMode, | ||
| 69 | }, | ||
| 61 | /// funct5 + rm + fmt | 70 | /// funct5 + rm + fmt |
| 62 | fmt: struct { | 71 | fmt: struct { |
| 63 | funct5: u5, | 72 | funct5: u5, |
| ... | @@ -210,6 +219,7 @@ pub const Mnemonic = enum { | ... | @@ -210,6 +219,7 @@ pub const Mnemonic = enum { |
| 210 | 219 | ||
| 211 | // MISC | 220 | // MISC |
| 212 | fence, | 221 | fence, |
| 222 | fencetso, | ||
| 213 | 223 | ||
| 214 | // AMO | 224 | // AMO |
| 215 | amoswapw, | 225 | amoswapw, |
| ... | @@ -406,9 +416,12 @@ pub const Mnemonic = enum { | ... | @@ -406,9 +416,12 @@ pub const Mnemonic = enum { |
| 406 | 416 | ||
| 407 | .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } }, | 417 | .unimp => .{ .opcode = .NONE, .data = .{ .f = .{ .funct3 = 0b000 } } }, |
| 408 | 418 | ||
| 419 | |||
| 409 | // MISC_MEM | 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 | // AMO | 426 | // AMO |
| 414 | 427 | ||
| ... | @@ -437,7 +450,6 @@ pub const Mnemonic = enum { | ... | @@ -437,7 +450,6 @@ pub const Mnemonic = enum { |
| 437 | .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } }, | 450 | .amomaxud => .{ .opcode = .AMO, .data = .{ .amo = .{ .width = .D, .funct5 = 0b11100 } } }, |
| 438 | 451 | ||
| 439 | 452 | ||
| 440 | |||
| 441 | // zig fmt: on | 453 | // zig fmt: on |
| 442 | }; | 454 | }; |
| 443 | } | 455 | } |
| ... | @@ -583,6 +595,7 @@ pub const InstEnc = enum { | ... | @@ -583,6 +595,7 @@ pub const InstEnc = enum { |
| 583 | => .system, | 595 | => .system, |
| 584 | 596 | ||
| 585 | .fence, | 597 | .fence, |
| 598 | .fencetso, | ||
| 586 | => .fence, | 599 | => .fence, |
| 587 | 600 | ||
| 588 | .amoswapw, | 601 | .amoswapw, |
| ... | @@ -689,7 +702,7 @@ pub const Data = union(InstEnc) { | ... | @@ -689,7 +702,7 @@ pub const Data = union(InstEnc) { |
| 689 | rs1: u5 = 0, | 702 | rs1: u5 = 0, |
| 690 | succ: u4, | 703 | succ: u4, |
| 691 | pred: u4, | 704 | pred: u4, |
| 692 | _ignored: u4 = 0, | 705 | fm: u4, |
| 693 | }, | 706 | }, |
| 694 | amo: packed struct { | 707 | amo: packed struct { |
| 695 | opcode: u7, | 708 | opcode: u7, |
| ... | @@ -711,11 +724,9 @@ pub const Data = union(InstEnc) { | ... | @@ -711,11 +724,9 @@ pub const Data = union(InstEnc) { |
| 711 | 724 | ||
| 712 | pub fn toU32(self: Data) u32 { | 725 | pub fn toU32(self: Data) u32 { |
| 713 | return switch (self) { | 726 | return switch (self) { |
| 714 | // zig fmt: off | 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), |
| 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), | ||
| 716 | inline else => |v| @bitCast(v), | 728 | inline else => |v| @bitCast(v), |
| 717 | .system => unreachable, | 729 | .system => unreachable, |
| 718 | // zig fmt: on | ||
| 719 | }; | 730 | }; |
| 720 | } | 731 | } |
| 721 | 732 | ||
| ... | @@ -869,16 +880,17 @@ pub const Data = union(InstEnc) { | ... | @@ -869,16 +880,17 @@ pub const Data = union(InstEnc) { |
| 869 | .fence => { | 880 | .fence => { |
| 870 | assert(ops.len == 2); | 881 | assert(ops.len == 2); |
| 871 | 882 | ||
| 872 | const succ = ops[0]; | 883 | const succ = ops[0].barrier; |
| 873 | const pred = ops[1]; | 884 | const pred = ops[1].barrier; |
| 874 | 885 | ||
| 875 | return .{ | 886 | return .{ |
| 876 | .fence = .{ | 887 | .fence = .{ |
| 877 | .succ = @intFromEnum(succ.barrier), | 888 | .succ = @intFromEnum(succ), |
| 878 | .pred = @intFromEnum(pred.barrier), | 889 | .pred = @intFromEnum(pred), |
| 879 | 890 | ||
| 880 | .opcode = @intFromEnum(enc.opcode), | 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,7 +903,7 @@ pub const Data = union(InstEnc) { |
| 891 | const rl = ops[3]; | 903 | const rl = ops[3]; |
| 892 | const aq = ops[4]; | 904 | const aq = ops[4]; |
| 893 | 905 | ||
| 894 | const ret: Data = .{ | 906 | return .{ |
| 895 | .amo = .{ | 907 | .amo = .{ |
| 896 | .rd = rd.reg.encodeId(), | 908 | .rd = rd.reg.encodeId(), |
| 897 | .rs1 = rs1.reg.encodeId(), | 909 | .rs1 = rs1.reg.encodeId(), |
| ... | @@ -906,9 +918,6 @@ pub const Data = union(InstEnc) { | ... | @@ -906,9 +918,6 @@ pub const Data = union(InstEnc) { |
| 906 | .funct5 = enc.data.amo.funct5, | 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 | else => std.debug.panic("TODO: construct {s}", .{@tagName(inst_enc)}), | 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,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 | else => return lower.fail("TODO lower: psuedo {s}", .{@tagName(inst.ops)}), | 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,10 +497,6 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 485 | .{ .reg = inst.data.r_type.rs1 }, | 497 | .{ .reg = inst.data.r_type.rs1 }, |
| 486 | .{ .reg = inst.data.r_type.rs2 }, | 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 | else => return lower.fail("TODO: generic lower ops {s}", .{@tagName(inst.ops)}), | 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,8 +80,6 @@ pub const Inst = struct { |
| 80 | sh, | 80 | sh, |
| 81 | sb, | 81 | sb, |
| 82 | 82 | ||
| 83 | fence, | ||
| 84 | |||
| 85 | // M extension | 83 | // M extension |
| 86 | mul, | 84 | mul, |
| 87 | mulw, | 85 | mulw, |
| ... | @@ -256,6 +254,10 @@ pub const Inst = struct { | ... | @@ -256,6 +254,10 @@ pub const Inst = struct { |
| 256 | fence: struct { | 254 | fence: struct { |
| 257 | pred: Barrier, | 255 | pred: Barrier, |
| 258 | succ: Barrier, | 256 | succ: Barrier, |
| 257 | fm: enum { | ||
| 258 | none, | ||
| 259 | tso, | ||
| 260 | }, | ||
| 259 | }, | 261 | }, |
| 260 | 262 | ||
| 261 | amo: struct { | 263 | amo: struct { |
| ... | @@ -355,7 +357,7 @@ pub const Inst = struct { | ... | @@ -355,7 +357,7 @@ pub const Inst = struct { |
| 355 | pseudo_extern_fn_reloc, | 357 | pseudo_extern_fn_reloc, |
| 356 | 358 | ||
| 357 | /// IORW, IORW | 359 | /// IORW, IORW |
| 358 | fence, | 360 | pseudo_fence, |
| 359 | 361 | ||
| 360 | /// Ordering, Src, Addr, Dest | 362 | /// Ordering, Src, Addr, Dest |
| 361 | pseudo_amo, | 363 | pseudo_amo, |
| ... | @@ -396,8 +398,8 @@ pub const FrameLoc = struct { | ... | @@ -396,8 +398,8 @@ pub const FrameLoc = struct { |
| 396 | 398 | ||
| 397 | pub const Barrier = enum(u4) { | 399 | pub const Barrier = enum(u4) { |
| 398 | // Fence | 400 | // Fence |
| 399 | r = 0b0001, | 401 | w = 0b0001, |
| 400 | w = 0b0010, | 402 | r = 0b0010, |
| 401 | rw = 0b0011, | 403 | rw = 0b0011, |
| 402 | 404 | ||
| 403 | // Amo | 405 | // Amo |
test/behavior/atomics.zig-1| ... | @@ -42,7 +42,6 @@ test "fence" { | ... | @@ -42,7 +42,6 @@ test "fence" { |
| 42 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 42 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 43 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 43 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 44 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 44 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 45 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 46 | 45 | ||
| 47 | var x: i32 = 1234; | 46 | var x: i32 = 1234; |
| 48 | @fence(.seq_cst); | 47 | @fence(.seq_cst); |
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1| ... | @@ -11,7 +11,6 @@ test { | ... | @@ -11,7 +11,6 @@ test { |
| 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 11 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 12 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 13 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; | 13 | if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest; |
| 14 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; | ||
| 15 | 14 | ||
| 16 | var val: u8 = undefined; | 15 | var val: u8 = undefined; |
| 17 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); | 16 | try testing.expectEqual({}, @atomicStore(u8, &val, 0, .unordered)); |