| ... | @@ -210,6 +210,8 @@ pub const MCValue = union(enum) { | ... | @@ -210,6 +210,8 @@ pub const MCValue = union(enum) { |
| 210 | register_offset: bits.RegisterOffset, | 210 | register_offset: bits.RegisterOffset, |
| 211 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register. | 211 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored in the GP register. |
| 212 | register_overflow: struct { reg: Register, eflags: Condition }, | 212 | register_overflow: struct { reg: Register, eflags: Condition }, |
| | 213 | /// The value is a tuple { wrapped, overflow } where wrapped value is stored across two registers. |
| | 214 | register_pair_overflow: struct { pair: [2]Register, eflags: Condition }, |
| 213 | /// The value is a bool vector stored in a vector register with a different scalar type. | 215 | /// The value is a bool vector stored in a vector register with a different scalar type. |
| 214 | register_mask: Mask, | 216 | register_mask: Mask, |
| 215 | /// The value is in memory at a hard-coded address. | 217 | /// The value is in memory at a hard-coded address. |
| ... | @@ -265,6 +267,7 @@ pub const MCValue = union(enum) { | ... | @@ -265,6 +267,7 @@ pub const MCValue = union(enum) { |
| 265 | .register_mask, | 267 | .register_mask, |
| 266 | .eflags, | 268 | .eflags, |
| 267 | .register_overflow, | 269 | .register_overflow, |
| | 270 | .register_pair_overflow, |
| 268 | .indirect_load_frame, | 271 | .indirect_load_frame, |
| 269 | .lea_frame, | 272 | .lea_frame, |
| 270 | .lea_nav, | 273 | .lea_nav, |
| ... | @@ -363,6 +366,7 @@ pub const MCValue = union(enum) { | ... | @@ -363,6 +366,7 @@ pub const MCValue = union(enum) { |
| 363 | .indirect, | 366 | .indirect, |
| 364 | .indirect_mask, | 367 | .indirect_mask, |
| 365 | => |*pl| (&pl.reg)[0..1], | 368 | => |*pl| (&pl.reg)[0..1], |
| | 369 | .register_pair_overflow => |*rpo| &rpo.pair, |
| 366 | else => &.{}, | 370 | else => &.{}, |
| 367 | }; | 371 | }; |
| 368 | } | 372 | } |
| ... | @@ -371,6 +375,7 @@ pub const MCValue = union(enum) { | ... | @@ -371,6 +375,7 @@ pub const MCValue = union(enum) { |
| 371 | return switch (mcv) { | 375 | return switch (mcv) { |
| 372 | .eflags => |cc| cc, | 376 | .eflags => |cc| cc, |
| 373 | .register_overflow => |reg_ov| reg_ov.eflags, | 377 | .register_overflow => |reg_ov| reg_ov.eflags, |
| | 378 | .register_pair_overflow => |rpo| rpo.eflags, |
| 374 | else => null, | 379 | else => null, |
| 375 | }; | 380 | }; |
| 376 | } | 381 | } |
| ... | @@ -396,6 +401,7 @@ pub const MCValue = union(enum) { | ... | @@ -396,6 +401,7 @@ pub const MCValue = union(enum) { |
| 396 | .register_quadruple, | 401 | .register_quadruple, |
| 397 | .register_offset, | 402 | .register_offset, |
| 398 | .register_overflow, | 403 | .register_overflow, |
| | 404 | .register_pair_overflow, |
| 399 | .register_mask, | 405 | .register_mask, |
| 400 | .indirect_mask, | 406 | .indirect_mask, |
| 401 | .lea_frame, | 407 | .lea_frame, |
| ... | @@ -437,6 +443,7 @@ pub const MCValue = union(enum) { | ... | @@ -437,6 +443,7 @@ pub const MCValue = union(enum) { |
| 437 | .register_triple, | 443 | .register_triple, |
| 438 | .register_quadruple, | 444 | .register_quadruple, |
| 439 | .register_overflow, | 445 | .register_overflow, |
| | 446 | .register_pair_overflow, |
| 440 | .register_mask, | 447 | .register_mask, |
| 441 | .memory, | 448 | .memory, |
| 442 | .indirect, | 449 | .indirect, |
| ... | @@ -487,6 +494,7 @@ pub const MCValue = union(enum) { | ... | @@ -487,6 +494,7 @@ pub const MCValue = union(enum) { |
| 487 | .register_triple, | 494 | .register_triple, |
| 488 | .register_quadruple, | 495 | .register_quadruple, |
| 489 | .register_overflow, | 496 | .register_overflow, |
| | 497 | .register_pair_overflow, |
| 490 | .register_mask, | 498 | .register_mask, |
| 491 | .memory, | 499 | .memory, |
| 492 | .indirect, | 500 | .indirect, |
| ... | @@ -530,6 +538,7 @@ pub const MCValue = union(enum) { | ... | @@ -530,6 +538,7 @@ pub const MCValue = union(enum) { |
| 530 | .register_quadruple, | 538 | .register_quadruple, |
| 531 | .register_offset, | 539 | .register_offset, |
| 532 | .register_overflow, | 540 | .register_overflow, |
| | 541 | .register_pair_overflow, |
| 533 | .register_mask, | 542 | .register_mask, |
| 534 | .indirect_load_frame, | 543 | .indirect_load_frame, |
| 535 | .lea_frame, | 544 | .lea_frame, |
| ... | @@ -604,6 +613,11 @@ pub const MCValue = union(enum) { | ... | @@ -604,6 +613,11 @@ pub const MCValue = union(enum) { |
| 604 | @tagName(pl.eflags), | 613 | @tagName(pl.eflags), |
| 605 | @tagName(pl.reg), | 614 | @tagName(pl.reg), |
| 606 | }), | 615 | }), |
| | 616 | .register_pair_overflow => |pl| try w.print("{t}:({t}:{t})", .{ |
| | 617 | pl.eflags, |
| | 618 | pl.pair[0], |
| | 619 | pl.pair[1], |
| | 620 | }), |
| 607 | .register_mask => |pl| try w.print("mask({s},{f}):{s}{s}", .{ | 621 | .register_mask => |pl| try w.print("mask({s},{f}):{s}{s}", .{ |
| 608 | @tagName(pl.info.kind), | 622 | @tagName(pl.info.kind), |
| 609 | pl.info.scalar, | 623 | pl.info.scalar, |
| ... | @@ -693,6 +707,7 @@ const InstTracking = struct { | ... | @@ -693,6 +707,7 @@ const InstTracking = struct { |
| 693 | .register_quadruple, | 707 | .register_quadruple, |
| 694 | .register_offset, | 708 | .register_offset, |
| 695 | .register_overflow, | 709 | .register_overflow, |
| | 710 | .register_pair_overflow, |
| 696 | .register_mask, | 711 | .register_mask, |
| 697 | .indirect, | 712 | .indirect, |
| 698 | .indirect_mask, | 713 | .indirect_mask, |
| ... | @@ -750,6 +765,10 @@ const InstTracking = struct { | ... | @@ -750,6 +765,10 @@ const InstTracking = struct { |
| 750 | function.register_manager.freeReg(reg_ov.reg); | 765 | function.register_manager.freeReg(reg_ov.reg); |
| 751 | function.eflags_inst = null; | 766 | function.eflags_inst = null; |
| 752 | }, | 767 | }, |
| | 768 | .register_pair_overflow => |rpo| { |
| | 769 | for (rpo.pair) |r| function.register_manager.freeReg(r); |
| | 770 | function.eflags_inst = null; |
| | 771 | }, |
| 753 | .register_mask => |reg_mask| function.register_manager.freeReg(reg_mask.reg), | 772 | .register_mask => |reg_mask| function.register_manager.freeReg(reg_mask.reg), |
| 754 | .eflags => function.eflags_inst = null, | 773 | .eflags => function.eflags_inst = null, |
| 755 | else => {}, // TODO process stack allocation death | 774 | else => {}, // TODO process stack allocation death |
| ... | @@ -793,6 +812,7 @@ const InstTracking = struct { | ... | @@ -793,6 +812,7 @@ const InstTracking = struct { |
| 793 | .register_quadruple, | 812 | .register_quadruple, |
| 794 | .register_offset, | 813 | .register_offset, |
| 795 | .register_overflow, | 814 | .register_overflow, |
| | 815 | .register_pair_overflow, |
| 796 | .register_mask, | 816 | .register_mask, |
| 797 | .indirect, | 817 | .indirect, |
| 798 | .indirect_mask, | 818 | .indirect_mask, |
| ... | @@ -51941,7 +51961,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -51941,7 +51961,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 51941 | }), | 51961 | }), |
| 51942 | else => |e| return e, | 51962 | else => |e| return e, |
| 51943 | }; | 51963 | }; |
| 51944 | try res[0].withOverflow(&res[1], cg); | 51964 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 51945 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 51965 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 51946 | }, | 51966 | }, |
| 51947 | .sub_with_overflow => |air_tag| { | 51967 | .sub_with_overflow => |air_tag| { |
| ... | @@ -52846,7 +52866,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -52846,7 +52866,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52846 | }), | 52866 | }), |
| 52847 | else => |e| return e, | 52867 | else => |e| return e, |
| 52848 | }; | 52868 | }; |
| 52849 | try res[0].withOverflow(&res[1], cg); | 52869 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 52850 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 52870 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 52851 | }, | 52871 | }, |
| 52852 | .mul_with_overflow => |air_tag| { | 52872 | .mul_with_overflow => |air_tag| { |
| ... | @@ -56443,7 +56463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -56443,7 +56463,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 56443 | }), | 56463 | }), |
| 56444 | else => |e| return e, | 56464 | else => |e| return e, |
| 56445 | }; | 56465 | }; |
| 56446 | try res[0].withOverflow(&res[1], cg); | 56466 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 56447 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 56467 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 56448 | }, | 56468 | }, |
| 56449 | .shl_with_overflow => |air_tag| { | 56469 | .shl_with_overflow => |air_tag| { |
| ... | @@ -59788,7 +59808,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -59788,7 +59808,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 59788 | }), | 59808 | }), |
| 59789 | else => |e| return e, | 59809 | else => |e| return e, |
| 59790 | }; | 59810 | }; |
| 59791 | try res[0].withOverflow(&res[1], cg); | 59811 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 59792 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 59812 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 59793 | }, | 59813 | }, |
| 59794 | .alloc => { | 59814 | .alloc => { |
| ... | @@ -103057,7 +103077,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -103057,7 +103077,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103057 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; | 103077 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; |
| 103058 | const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data; | 103078 | const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 103059 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); | 103079 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 103060 | try ops[0].toPair(&ops[1], cg); | 103080 | try ops[0].toPair(&ops[1], ty_pl.ty, cg); |
| 103061 | try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 103081 | try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 103062 | }, | 103082 | }, |
| 103063 | .slice_len => { | 103083 | .slice_len => { |
| ... | @@ -103474,7 +103494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -103474,7 +103494,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 103474 | var len = try cg.tempInit(.usize, .{ | 103494 | var len = try cg.tempInit(.usize, .{ |
| 103475 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), | 103495 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), |
| 103476 | }); | 103496 | }); |
| 103477 | try ops[0].toPair(&len, cg); | 103497 | try ops[0].toPair(&len, ty_op.ty, cg); |
| 103478 | try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg); | 103498 | try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg); |
| 103479 | }, | 103499 | }, |
| 103480 | .int_from_float, .int_from_float_optimized => |air_tag| { | 103500 | .int_from_float, .int_from_float_optimized => |air_tag| { |
| ... | @@ -170236,7 +170256,113 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -170236,7 +170256,113 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 170236 | }; | 170256 | }; |
| 170237 | for (ops) |op| try op.die(cg); | 170257 | for (ops) |op| try op.die(cg); |
| 170238 | }, | 170258 | }, |
| 170239 | .cmpxchg_weak, .cmpxchg_strong => try cg.airCmpxchg(inst), | 170259 | .cmpxchg_weak, .cmpxchg_strong => |air_tag| { |
| | 170260 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; |
| | 170261 | const extra = cg.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| | 170262 | var ops = try cg.tempsFromOperands(inst, .{ extra.ptr, extra.expected_value, extra.new_value }); |
| | 170263 | var res: [2]Temp = undefined; |
| | 170264 | (if (ty_pl.ty.optionalReprIsPayload(zcu)) |
| | 170265 | cg.select(res[0..1], &.{ty_pl.ty}, &ops, comptime &.{.{ |
| | 170266 | .required_features = .{ .@"64bit", .cmov, null, null }, |
| | 170267 | .src_constraints = .{ .any, .{ .size = .qword }, .{ .size = .qword } }, |
| | 170268 | .patterns = &.{ |
| | 170269 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 170270 | }, |
| | 170271 | .extra_temps = .{ |
| | 170272 | .{ .type = .usize, .kind = .{ .rc = .general_purpose } }, |
| | 170273 | .unused, |
| | 170274 | .unused, |
| | 170275 | .unused, |
| | 170276 | .unused, |
| | 170277 | .unused, |
| | 170278 | .unused, |
| | 170279 | .unused, |
| | 170280 | .unused, |
| | 170281 | .unused, |
| | 170282 | .unused, |
| | 170283 | }, |
| | 170284 | .dst_temps = .{ .{ .ref = .src1 }, .unused }, |
| | 170285 | .clobbers = .{ .eflags = true }, |
| | 170286 | .each = .{ .once = &.{ |
| | 170287 | .{ ._, ._, .xor, .tmp0d, .tmp0d, ._, ._ }, |
| | 170288 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0q), .src2q, ._, ._ }, |
| | 170289 | .{ ._, ._e, .cmov, .dst0q, .tmp0q, ._, ._ }, |
| | 170290 | } }, |
| | 170291 | }}) |
| | 170292 | else |
| | 170293 | cg.select(&res, &.{ ty_pl.ty.childType(zcu), .u1 }, &ops, comptime &.{ .{ |
| | 170294 | .required_features = .{ .@"64bit", null, null, null }, |
| | 170295 | .src_constraints = .{ .any, .{ .int = .byte }, .{ .int = .byte } }, |
| | 170296 | .patterns = &.{ |
| | 170297 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 170298 | }, |
| | 170299 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 170300 | .clobbers = .{ .eflags = true }, |
| | 170301 | .each = .{ .once = &.{ |
| | 170302 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0b), .src2b, ._, ._ }, |
| | 170303 | } }, |
| | 170304 | }, .{ |
| | 170305 | .required_features = .{ .@"64bit", null, null, null }, |
| | 170306 | .src_constraints = .{ .any, .{ .int = .word }, .{ .int = .word } }, |
| | 170307 | .patterns = &.{ |
| | 170308 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 170309 | }, |
| | 170310 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 170311 | .clobbers = .{ .eflags = true }, |
| | 170312 | .each = .{ .once = &.{ |
| | 170313 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0w), .src2w, ._, ._ }, |
| | 170314 | } }, |
| | 170315 | }, .{ |
| | 170316 | .required_features = .{ .@"64bit", null, null, null }, |
| | 170317 | .src_constraints = .{ .any, .{ .int = .dword }, .{ .int = .dword } }, |
| | 170318 | .patterns = &.{ |
| | 170319 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 170320 | }, |
| | 170321 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 170322 | .clobbers = .{ .eflags = true }, |
| | 170323 | .each = .{ .once = &.{ |
| | 170324 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0d), .src2d, ._, ._ }, |
| | 170325 | } }, |
| | 170326 | }, .{ |
| | 170327 | .required_features = .{ .@"64bit", null, null, null }, |
| | 170328 | .src_constraints = .{ .any, .{ .int = .qword }, .{ .int = .qword } }, |
| | 170329 | .patterns = &.{ |
| | 170330 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 170331 | }, |
| | 170332 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 170333 | .clobbers = .{ .eflags = true }, |
| | 170334 | .each = .{ .once = &.{ |
| | 170335 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0q), .src2q, ._, ._ }, |
| | 170336 | } }, |
| | 170337 | }, .{ |
| | 170338 | .required_features = .{ .@"64bit", .cx16, null, null }, |
| | 170339 | .src_constraints = .{ .any, .{ .int = .xword }, .{ .int = .xword } }, |
| | 170340 | .patterns = &.{.{ |
| | 170341 | .src = .{ |
| | 170342 | .to_gpr, |
| | 170343 | .{ .to_reg_pair = .{ .rax, .rdx } }, |
| | 170344 | .{ .to_reg_pair = .{ .rbx, .rcx } }, |
| | 170345 | }, |
| | 170346 | }}, |
| | 170347 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 170348 | .clobbers = .{ .eflags = true }, |
| | 170349 | .each = .{ .once = &.{ |
| | 170350 | .{ ._, .@"lock _16b", .cmpxchg, .lea(.src0x), ._, ._, ._ }, |
| | 170351 | } }, |
| | 170352 | } })) catch |err| switch (err) { |
| | 170353 | error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{ |
| | 170354 | @tagName(air_tag), |
| | 170355 | ty_pl.ty.fmt(zcu), |
| | 170356 | ops[0].tracking(cg), |
| | 170357 | ops[1].tracking(cg), |
| | 170358 | ops[2].tracking(cg), |
| | 170359 | }), |
| | 170360 | else => |e| return e, |
| | 170361 | }; |
| | 170362 | if (!ty_pl.ty.optionalReprIsPayload(zcu)) |
| | 170363 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| | 170364 | try res[0].finish(inst, &.{ extra.ptr, extra.expected_value, extra.new_value }, &ops, cg); |
| | 170365 | }, |
| 170240 | .atomic_load => try cg.airAtomicLoad(inst), | 170366 | .atomic_load => try cg.airAtomicLoad(inst), |
| 170241 | .atomic_store_unordered => try cg.airAtomicStore(inst, .unordered), | 170367 | .atomic_store_unordered => try cg.airAtomicStore(inst, .unordered), |
| 170242 | .atomic_store_monotonic => try cg.airAtomicStore(inst, .monotonic), | 170368 | .atomic_store_monotonic => try cg.airAtomicStore(inst, .monotonic), |
| ... | @@ -170578,7 +170704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -170578,7 +170704,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 170578 | }), | 170704 | }), |
| 170579 | else => |e| return e, | 170705 | else => |e| return e, |
| 170580 | }; | 170706 | }; |
| 170581 | if (res[0].tracking(cg).short != .register_pair) try ops[0].toPair(&res[0], cg); | 170707 | if (res[0].tracking(cg).short != .register_pair) try ops[0].toPair(&res[0], .slice_const_u8_sentinel_0, cg); |
| 170582 | try res[0].finish(inst, &.{un_op}, &ops, cg); | 170708 | try res[0].finish(inst, &.{un_op}, &ops, cg); |
| 170583 | }, | 170709 | }, |
| 170584 | .error_name => |air_tag| { | 170710 | .error_name => |air_tag| { |
| ... | @@ -170681,7 +170807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -170681,7 +170807,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 170681 | else => |e| return e, | 170807 | else => |e| return e, |
| 170682 | }; | 170808 | }; |
| 170683 | const orig_res = res; | 170809 | const orig_res = res; |
| 170684 | try res[0].toPair(&res[1], cg); | 170810 | try res[0].toPair(&res[1], .slice_const_u8_sentinel_0, cg); |
| 170685 | for (&ops) |*op| for (orig_res) |orig_r| { | 170811 | for (&ops) |*op| for (orig_res) |orig_r| { |
| 170686 | if (op.index != orig_r.index) continue; | 170812 | if (op.index != orig_r.index) continue; |
| 170687 | op.* = res[0]; | 170813 | op.* = res[0]; |
| ... | @@ -173190,7 +173316,10 @@ fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void { | ... | @@ -173190,7 +173316,10 @@ fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void { |
| 173190 | for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst); | 173316 | for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst); |
| 173191 | switch (value) { | 173317 | switch (value) { |
| 173192 | else => {}, | 173318 | else => {}, |
| 173193 | .eflags, .register_overflow => self.eflags_inst = inst, | 173319 | .eflags, |
| | 173320 | .register_overflow, |
| | 173321 | .register_pair_overflow, |
| | 173322 | => self.eflags_inst = inst, |
| 173194 | } | 173323 | } |
| 173195 | } | 173324 | } |
| 173196 | | 173325 | |
| ... | @@ -173218,6 +173347,10 @@ fn freeValue(self: *CodeGen, value: MCValue, comptime opts: FreeOptions) !void { | ... | @@ -173218,6 +173347,10 @@ fn freeValue(self: *CodeGen, value: MCValue, comptime opts: FreeOptions) !void { |
| 173218 | try self.freeReg(reg_ov.reg, opts); | 173347 | try self.freeReg(reg_ov.reg, opts); |
| 173219 | self.eflags_inst = null; | 173348 | self.eflags_inst = null; |
| 173220 | }, | 173349 | }, |
| | 173350 | .register_pair_overflow => |rpo| { |
| | 173351 | for (rpo.pair) |r| try self.freeReg(r, opts); |
| | 173352 | self.eflags_inst = null; |
| | 173353 | }, |
| 173221 | .register_mask => |reg_mask| try self.freeReg(reg_mask.reg, opts), | 173354 | .register_mask => |reg_mask| try self.freeReg(reg_mask.reg, opts), |
| 173222 | .eflags => self.eflags_inst = null, | 173355 | .eflags => self.eflags_inst = null, |
| 173223 | else => {}, // TODO process stack allocation death | 173356 | else => {}, // TODO process stack allocation death |
| ... | @@ -173760,7 +173893,12 @@ fn reuseOperandAdvanced( | ... | @@ -173760,7 +173893,12 @@ fn reuseOperandAdvanced( |
| 173760 | return false; | 173893 | return false; |
| 173761 | | 173894 | |
| 173762 | switch (mcv) { | 173895 | switch (mcv) { |
| 173763 | .register, .register_pair, .register_overflow, .register_mask => for (mcv.getRegs()) |reg| { | 173896 | .register, |
| | 173897 | .register_pair, |
| | 173898 | .register_overflow, |
| | 173899 | .register_pair_overflow, |
| | 173900 | .register_mask, |
| | 173901 | => for (mcv.getRegs()) |reg| { |
| 173764 | // If it's in the registers table, need to associate the register(s) with the | 173902 | // If it's in the registers table, need to associate the register(s) with the |
| 173765 | // new instruction. | 173903 | // new instruction. |
| 173766 | if (maybe_tracked_inst) |tracked_inst| { | 173904 | if (maybe_tracked_inst) |tracked_inst| { |
| ... | @@ -173775,7 +173913,10 @@ fn reuseOperandAdvanced( | ... | @@ -173775,7 +173913,10 @@ fn reuseOperandAdvanced( |
| 173775 | else => return false, | 173913 | else => return false, |
| 173776 | } | 173914 | } |
| 173777 | switch (mcv) { | 173915 | switch (mcv) { |
| 173778 | .eflags, .register_overflow => self.eflags_inst = maybe_tracked_inst, | 173916 | .eflags, |
| | 173917 | .register_overflow, |
| | 173918 | .register_pair_overflow, |
| | 173919 | => self.eflags_inst = maybe_tracked_inst, |
| 173779 | else => {}, | 173920 | else => {}, |
| 173780 | } | 173921 | } |
| 173781 | | 173922 | |
| ... | @@ -173802,6 +173943,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE | ... | @@ -173802,6 +173943,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 173802 | .register_triple, | 173943 | .register_triple, |
| 173803 | .register_quadruple, | 173944 | .register_quadruple, |
| 173804 | .register_overflow, | 173945 | .register_overflow, |
| | 173946 | .register_pair_overflow, |
| 173805 | .register_mask, | 173947 | .register_mask, |
| 173806 | .indirect_load_frame, | 173948 | .indirect_load_frame, |
| 173807 | .indirect_mask, | 173949 | .indirect_mask, |
| ... | @@ -173861,6 +174003,7 @@ fn store( | ... | @@ -173861,6 +174003,7 @@ fn store( |
| 173861 | .register_triple, | 174003 | .register_triple, |
| 173862 | .register_quadruple, | 174004 | .register_quadruple, |
| 173863 | .register_overflow, | 174005 | .register_overflow, |
| | 174006 | .register_pair_overflow, |
| 173864 | .register_mask, | 174007 | .register_mask, |
| 173865 | .indirect_load_frame, | 174008 | .indirect_load_frame, |
| 173866 | .indirect_mask, | 174009 | .indirect_mask, |
| ... | @@ -173912,6 +174055,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: | ... | @@ -173912,6 +174055,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 173912 | .register_offset, | 174055 | .register_offset, |
| 173913 | .eflags, | 174056 | .eflags, |
| 173914 | .register_overflow, | 174057 | .register_overflow, |
| | 174058 | .register_pair_overflow, |
| 173915 | .register_mask, | 174059 | .register_mask, |
| 173916 | .indirect_load_frame, | 174060 | .indirect_load_frame, |
| 173917 | .indirect_mask, | 174061 | .indirect_mask, |
| ... | @@ -174608,6 +174752,7 @@ fn genBinOpMir( | ... | @@ -174608,6 +174752,7 @@ fn genBinOpMir( |
| 174608 | .immediate, | 174752 | .immediate, |
| 174609 | .eflags, | 174753 | .eflags, |
| 174610 | .register_overflow, | 174754 | .register_overflow, |
| | 174755 | .register_pair_overflow, |
| 174611 | .register_mask, | 174756 | .register_mask, |
| 174612 | .lea_frame, | 174757 | .lea_frame, |
| 174613 | .lea_nav, | 174758 | .lea_nav, |
| ... | @@ -174656,6 +174801,7 @@ fn genBinOpMir( | ... | @@ -174656,6 +174801,7 @@ fn genBinOpMir( |
| 174656 | .dead, | 174801 | .dead, |
| 174657 | .undef, | 174802 | .undef, |
| 174658 | .register_overflow, | 174803 | .register_overflow, |
| | 174804 | .register_pair_overflow, |
| 174659 | .register_mask, | 174805 | .register_mask, |
| 174660 | .indirect_load_frame, | 174806 | .indirect_load_frame, |
| 174661 | .indirect_mask, | 174807 | .indirect_mask, |
| ... | @@ -174834,6 +174980,7 @@ fn genBinOpMir( | ... | @@ -174834,6 +174980,7 @@ fn genBinOpMir( |
| 174834 | .dead, | 174980 | .dead, |
| 174835 | .undef, | 174981 | .undef, |
| 174836 | .register_overflow, | 174982 | .register_overflow, |
| | 174983 | .register_pair_overflow, |
| 174837 | .register_mask, | 174984 | .register_mask, |
| 174838 | .indirect_load_frame, | 174985 | .indirect_load_frame, |
| 174839 | .indirect_mask, | 174986 | .indirect_mask, |
| ... | @@ -174944,6 +175091,7 @@ fn genBinOpMir( | ... | @@ -174944,6 +175091,7 @@ fn genBinOpMir( |
| 174944 | .dead, | 175091 | .dead, |
| 174945 | .undef, | 175092 | .undef, |
| 174946 | .register_overflow, | 175093 | .register_overflow, |
| | 175094 | .register_pair_overflow, |
| 174947 | .register_mask, | 175095 | .register_mask, |
| 174948 | .indirect_load_frame, | 175096 | .indirect_load_frame, |
| 174949 | .indirect_mask, | 175097 | .indirect_mask, |
| ... | @@ -178053,6 +178201,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -178053,6 +178201,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 178053 | .immediate, | 178201 | .immediate, |
| 178054 | .eflags, | 178202 | .eflags, |
| 178055 | .register_overflow, | 178203 | .register_overflow, |
| | 178204 | .register_pair_overflow, |
| 178056 | .register_mask, | 178205 | .register_mask, |
| 178057 | .indirect_load_frame, | 178206 | .indirect_load_frame, |
| 178058 | .indirect_mask, | 178207 | .indirect_mask, |
| ... | @@ -178077,6 +178226,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -178077,6 +178226,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 178077 | .dead, | 178226 | .dead, |
| 178078 | .undef, | 178227 | .undef, |
| 178079 | .register_overflow, | 178228 | .register_overflow, |
| | 178229 | .register_pair_overflow, |
| 178080 | .register_tee, | 178230 | .register_tee, |
| 178081 | .elementwise_gpr, | 178231 | .elementwise_gpr, |
| 178082 | .elementwise_sse, | 178232 | .elementwise_sse, |
| ... | @@ -178280,6 +178430,7 @@ fn genSetReg( | ... | @@ -178280,6 +178430,7 @@ fn genSetReg( |
| 178280 | .ywordwise_sse, | 178430 | .ywordwise_sse, |
| 178281 | .zwordwise_sse, | 178431 | .zwordwise_sse, |
| 178282 | .reserved_frame, | 178432 | .reserved_frame, |
| | 178433 | .register_pair_overflow, |
| 178283 | => unreachable, | 178434 | => unreachable, |
| 178284 | .undef => if (opts.safety) switch (dst_reg.class()) { | 178435 | .undef => if (opts.safety) switch (dst_reg.class()) { |
| 178285 | .general_purpose, .gphi => switch (abi_size) { | 178436 | .general_purpose, .gphi => switch (abi_size) { |
| ... | @@ -179083,6 +179234,23 @@ fn genSetMem( | ... | @@ -179083,6 +179234,23 @@ fn genSetMem( |
| 179083 | @tagName(src_mcv), ty.fmt(zcu), | 179234 | @tagName(src_mcv), ty.fmt(zcu), |
| 179084 | }), | 179235 | }), |
| 179085 | }, | 179236 | }, |
| | 179237 | .register_pair_overflow => |rpo| switch (ty.zigTypeTag(zcu)) { |
| | 179238 | .optional => { |
| | 179239 | assert(!ty.optionalReprIsPayload(zcu)); |
| | 179240 | const child_ty = ty.optionalChild(zcu); |
| | 179241 | try cg.genSetMem(base, disp, child_ty, .{ .register_pair = rpo.pair }, opts); |
| | 179242 | try cg.genSetMem( |
| | 179243 | base, |
| | 179244 | disp + @as(i32, @intCast(child_ty.abiSize(zcu))), |
| | 179245 | .bool, |
| | 179246 | .{ .eflags = rpo.eflags }, |
| | 179247 | opts, |
| | 179248 | ); |
| | 179249 | }, |
| | 179250 | else => return cg.fail("TODO implement genSetMem for {s} of {f}", .{ |
| | 179251 | @tagName(src_mcv), ty.fmt(zcu), |
| | 179252 | }), |
| | 179253 | }, |
| 179086 | .register_offset => |reg_off| { | 179254 | .register_offset => |reg_off| { |
| 179087 | const src_reg = cg.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) { | 179255 | const src_reg = cg.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) { |
| 179088 | error.OutOfRegisters => { | 179256 | error.OutOfRegisters => { |
| ... | @@ -179417,111 +179585,6 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -179417,111 +179585,6 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 179417 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 179585 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 179418 | } | 179586 | } |
| 179419 | | 179587 | |
| 179420 | fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { | | |
| 179421 | const pt = self.pt; | | |
| 179422 | const zcu = pt.zcu; | | |
| 179423 | const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | | |
| 179424 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | | |
| 179425 | | | |
| 179426 | const dst_ty = self.typeOfIndex(inst); | | |
| 179427 | const ptr_ty = self.typeOf(extra.ptr); | | |
| 179428 | const val_ty = self.typeOf(extra.expected_value); | | |
| 179429 | const val_abi_size: u32 = @intCast(val_ty.abiSize(zcu)); | | |
| 179430 | | | |
| 179431 | try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx }); | | |
| 179432 | const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx }); | | |
| 179433 | defer for (regs_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179434 | | | |
| 179435 | const exp_mcv = try self.resolveInst(extra.expected_value); | | |
| 179436 | if (val_abi_size > 8) { | | |
| 179437 | const exp_addr_mcv: MCValue = switch (exp_mcv) { | | |
| 179438 | .memory, .indirect, .load_frame => exp_mcv.address(), | | |
| 179439 | else => .{ .register = try self.copyToTmpRegister(.usize, exp_mcv.address()) }, | | |
| 179440 | }; | | |
| 179441 | const exp_addr_lock = | | |
| 179442 | if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | | |
| 179443 | defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179444 | | | |
| 179445 | try self.genSetReg(.rax, .usize, exp_addr_mcv.deref(), .{}); | | |
| 179446 | try self.genSetReg(.rdx, .usize, exp_addr_mcv.offset(8).deref(), .{}); | | |
| 179447 | } else try self.genSetReg(.rax, val_ty, exp_mcv, .{}); | | |
| 179448 | | | |
| 179449 | const new_mcv = try self.resolveInst(extra.new_value); | | |
| 179450 | const new_reg = if (val_abi_size > 8) new: { | | |
| 179451 | const new_addr_mcv: MCValue = switch (new_mcv) { | | |
| 179452 | .memory, .indirect, .load_frame => new_mcv.address(), | | |
| 179453 | else => .{ .register = try self.copyToTmpRegister(.usize, new_mcv.address()) }, | | |
| 179454 | }; | | |
| 179455 | const new_addr_lock = | | |
| 179456 | if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | | |
| 179457 | defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179458 | | | |
| 179459 | try self.genSetReg(.rbx, .usize, new_addr_mcv.deref(), .{}); | | |
| 179460 | try self.genSetReg(.rcx, .usize, new_addr_mcv.offset(8).deref(), .{}); | | |
| 179461 | break :new null; | | |
| 179462 | } else try self.copyToTmpRegister(val_ty, new_mcv); | | |
| 179463 | const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; | | |
| 179464 | defer if (new_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179465 | | | |
| 179466 | const ptr_mcv = try self.resolveInst(extra.ptr); | | |
| 179467 | const mem_size: Memory.Size = .fromSize(val_abi_size); | | |
| 179468 | const ptr_mem: Memory = switch (ptr_mcv) { | | |
| 179469 | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, .{ .size = mem_size }), | | |
| 179470 | else => .{ | | |
| 179471 | .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) }, | | |
| 179472 | .mod = .{ .rm = .{ .size = mem_size } }, | | |
| 179473 | }, | | |
| 179474 | }; | | |
| 179475 | switch (ptr_mem.mod) { | | |
| 179476 | .rm => {}, | | |
| 179477 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | | |
| 179478 | } | | |
| 179479 | const ptr_lock = switch (ptr_mem.base) { | | |
| 179480 | .none, .frame, .nav, .uav => null, | | |
| 179481 | .reg => |reg| self.register_manager.lockReg(reg), | | |
| 179482 | .table, .rip_inst, .lazy_sym, .extern_func => unreachable, | | |
| 179483 | }; | | |
| 179484 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179485 | | | |
| 179486 | try self.spillEflagsIfOccupied(); | | |
| 179487 | const null_reg = if (dst_ty.optionalReprIsPayload(zcu) and !self.liveness.isUnused(inst)) null_reg: { | | |
| 179488 | const null_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); | | |
| 179489 | try self.asmRegisterRegister(.{ ._, .xor }, null_reg.to32(), null_reg.to32()); | | |
| 179490 | break :null_reg null_reg; | | |
| 179491 | } else null; | | |
| 179492 | const null_lock = if (null_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; | | |
| 179493 | defer if (null_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 179494 | | | |
| 179495 | if (val_abi_size <= 8) try self.asmMemoryRegister( | | |
| 179496 | .{ .@"lock _", .cmpxchg }, | | |
| 179497 | ptr_mem, | | |
| 179498 | registerAlias(new_reg.?, val_abi_size), | | |
| 179499 | ) else try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem); | | |
| 179500 | | | |
| 179501 | const result: MCValue = result: { | | |
| 179502 | if (self.liveness.isUnused(inst)) break :result .unreach; | | |
| 179503 | | | |
| 179504 | if (null_reg) |reg| try self.asmCmovccRegisterRegister( | | |
| 179505 | .e, | | |
| 179506 | registerAlias(.rax, val_abi_size), | | |
| 179507 | registerAlias(reg, val_abi_size), | | |
| 179508 | ); | | |
| 179509 | | | |
| 179510 | if (val_abi_size <= 8) { | | |
| 179511 | if (null_reg) |_| break :result .{ .register = .rax }; | | |
| 179512 | self.eflags_inst = inst; | | |
| 179513 | break :result .{ .register_overflow = .{ .reg = .rax, .eflags = .ne } }; | | |
| 179514 | } | | |
| 179515 | | | |
| 179516 | const dst_mcv = try self.allocRegOrMem(inst, false); | | |
| 179517 | try self.genCopy(.usize, dst_mcv, .{ .register = .rax }, .{}); | | |
| 179518 | try self.genCopy(.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{}); | | |
| 179519 | if (null_reg == null) try self.genCopy(.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{}); | | |
| 179520 | break :result dst_mcv; | | |
| 179521 | }; | | |
| 179522 | return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value }); | | |
| 179523 | } | | |
| 179524 | | | |
| 179525 | fn atomicOp( | 179588 | fn atomicOp( |
| 179526 | self: *CodeGen, | 179589 | self: *CodeGen, |
| 179527 | ptr_mcv: MCValue, | 179590 | ptr_mcv: MCValue, |
| ... | @@ -179557,7 +179620,7 @@ fn atomicOp( | ... | @@ -179557,7 +179620,7 @@ fn atomicOp( |
| 179557 | }; | 179620 | }; |
| 179558 | switch (ptr_mem.mod) { | 179621 | switch (ptr_mem.mod) { |
| 179559 | .rm => {}, | 179622 | .rm => {}, |
| 179560 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | 179623 | .off => return self.fail("TODO atomicOp with {s}", .{@tagName(ptr_mcv)}), |
| 179561 | } | 179624 | } |
| 179562 | const mem_lock = switch (ptr_mem.base) { | 179625 | const mem_lock = switch (ptr_mem.base) { |
| 179563 | .none, .frame, .nav, .uav => null, | 179626 | .none, .frame, .nav, .uav => null, |
| ... | @@ -181936,6 +181999,7 @@ const Temp = struct { | ... | @@ -181936,6 +181999,7 @@ const Temp = struct { |
| 181936 | .register_triple, | 181999 | .register_triple, |
| 181937 | .register_quadruple, | 182000 | .register_quadruple, |
| 181938 | .register_overflow, | 182001 | .register_overflow, |
| | 182002 | .register_pair_overflow, |
| 181939 | => true, | 182003 | => true, |
| 181940 | .load_frame => |frame_addr| !frame_addr.index.isNamed(), | 182004 | .load_frame => |frame_addr| !frame_addr.index.isNamed(), |
| 181941 | }, | 182005 | }, |
| ... | @@ -182316,7 +182380,7 @@ const Temp = struct { | ... | @@ -182316,7 +182380,7 @@ const Temp = struct { |
| 182316 | return true; | 182380 | return true; |
| 182317 | } | 182381 | } |
| 182318 | | 182382 | |
| 182319 | fn toPair(first_temp: *Temp, second_temp: *Temp, cg: *CodeGen) InnerError!void { | 182383 | fn toPair(first_temp: *Temp, second_temp: *Temp, result_ty: Type, cg: *CodeGen) InnerError!void { |
| 182320 | while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| { | 182384 | while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| { |
| 182321 | if (try part_temp.toRegClass(true, .general_purpose, cg)) break; | 182385 | if (try part_temp.toRegClass(true, .general_purpose, cg)) break; |
| 182322 | } else break; | 182386 | } else break; |
| ... | @@ -182331,13 +182395,13 @@ const Temp = struct { | ... | @@ -182331,13 +182395,13 @@ const Temp = struct { |
| 182331 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); | 182395 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); |
| 182332 | assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); | 182396 | assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); |
| 182333 | result_temp_index.tracking(cg).* = .init(result); | 182397 | result_temp_index.tracking(cg).* = .init(result); |
| 182334 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 182398 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 182335 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 182399 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 182336 | first_temp.* = result_temp; | 182400 | first_temp.* = result_temp; |
| 182337 | second_temp.* = result_temp; | 182401 | second_temp.* = result_temp; |
| 182338 | } | 182402 | } |
| 182339 | | 182403 | |
| 182340 | fn withOverflow(temp: *Temp, overflow_temp: *Temp, cg: *CodeGen) InnerError!void { | 182404 | fn withOverflow(temp: *Temp, overflow_temp: *Temp, result_ty: Type, cg: *CodeGen) InnerError!void { |
| 182341 | const temp_index = temp.unwrap(cg).temp; | 182405 | const temp_index = temp.unwrap(cg).temp; |
| 182342 | const temp_tracking = temp_index.tracking(cg); | 182406 | const temp_tracking = temp_index.tracking(cg); |
| 182343 | const overflow_temp_tracking = overflow_temp.unwrap(cg).temp.tracking(cg); | 182407 | const overflow_temp_tracking = overflow_temp.unwrap(cg).temp.tracking(cg); |
| ... | @@ -182349,7 +182413,7 @@ const Temp = struct { | ... | @@ -182349,7 +182413,7 @@ const Temp = struct { |
| 182349 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); | 182413 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| 182350 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); | 182414 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| 182351 | result_temp_index.tracking(cg).* = .init(.{ .register_overflow = .{ .reg = reg, .eflags = overflow_cc } }); | 182415 | result_temp_index.tracking(cg).* = .init(.{ .register_overflow = .{ .reg = reg, .eflags = overflow_cc } }); |
| 182352 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 182416 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 182353 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 182417 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 182354 | temp.* = result_temp; | 182418 | temp.* = result_temp; |
| 182355 | overflow_temp.* = result_temp; | 182419 | overflow_temp.* = result_temp; |
| ... | @@ -182361,7 +182425,22 @@ const Temp = struct { | ... | @@ -182361,7 +182425,22 @@ const Temp = struct { |
| 182361 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); | 182425 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| 182362 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); | 182426 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| 182363 | result_temp_index.tracking(cg).* = .init(.{ .register_pair = .{ reg, overflow_reg } }); | 182427 | result_temp_index.tracking(cg).* = .init(.{ .register_pair = .{ reg, overflow_reg } }); |
| 182364 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 182428 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| | 182429 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| | 182430 | temp.* = result_temp; |
| | 182431 | overflow_temp.* = result_temp; |
| | 182432 | return; |
| | 182433 | }, |
| | 182434 | else => {}, |
| | 182435 | }, |
| | 182436 | .register_pair => |pair| switch (overflow_temp_tracking.short) { |
| | 182437 | .eflags => |overflow_cc| { |
| | 182438 | const result_temp_index = cg.next_temp_index; |
| | 182439 | const result_temp: Temp = .{ .index = result_temp_index.toIndex() }; |
| | 182440 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| | 182441 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| | 182442 | result_temp_index.tracking(cg).* = .init(.{ .register_pair_overflow = .{ .pair = pair, .eflags = overflow_cc } }); |
| | 182443 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 182365 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 182444 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 182366 | temp.* = result_temp; | 182445 | temp.* = result_temp; |
| 182367 | overflow_temp.* = result_temp; | 182446 | overflow_temp.* = result_temp; |
| ... | @@ -182401,6 +182480,7 @@ const Temp = struct { | ... | @@ -182401,6 +182480,7 @@ const Temp = struct { |
| 182401 | .register_triple, | 182480 | .register_triple, |
| 182402 | .register_quadruple, | 182481 | .register_quadruple, |
| 182403 | .register_overflow, | 182482 | .register_overflow, |
| | 182483 | .register_pair_overflow, |
| 182404 | .register_mask, | 182484 | .register_mask, |
| 182405 | .indirect_load_frame, | 182485 | .indirect_load_frame, |
| 182406 | .indirect_mask, | 182486 | .indirect_mask, |
| ... | @@ -188883,6 +188963,7 @@ const Temp = struct { | ... | @@ -188883,6 +188963,7 @@ const Temp = struct { |
| 188883 | .register_quadruple, | 188963 | .register_quadruple, |
| 188884 | .register_offset, | 188964 | .register_offset, |
| 188885 | .register_overflow, | 188965 | .register_overflow, |
| | 188966 | .register_pair_overflow, |
| 188886 | .register_mask, | 188967 | .register_mask, |
| 188887 | .memory, | 188968 | .memory, |
| 188888 | .indirect, | 188969 | .indirect, |
| ... | @@ -189001,6 +189082,7 @@ fn reuseTemp( | ... | @@ -189001,6 +189082,7 @@ fn reuseTemp( |
| 189001 | .register_pair, | 189082 | .register_pair, |
| 189002 | .register_offset, | 189083 | .register_offset, |
| 189003 | .register_overflow, | 189084 | .register_overflow, |
| | 189085 | .register_pair_overflow, |
| 189004 | .register_mask, | 189086 | .register_mask, |
| 189005 | .indirect, | 189087 | .indirect, |
| 189006 | => for (tracking.short.getRegs()) |tracked_reg| { | 189088 | => for (tracking.short.getRegs()) |tracked_reg| { |
| ... | @@ -189012,7 +189094,10 @@ fn reuseTemp( | ... | @@ -189012,7 +189094,10 @@ fn reuseTemp( |
| 189012 | else => {}, | 189094 | else => {}, |
| 189013 | } | 189095 | } |
| 189014 | switch (tracking.short) { | 189096 | switch (tracking.short) { |
| 189015 | .eflags, .register_overflow => cg.eflags_inst = new_inst, | 189097 | .eflags, |
| | 189098 | .register_overflow, |
| | 189099 | .register_pair_overflow, |
| | 189100 | => cg.eflags_inst = new_inst, |
| 189016 | else => {}, | 189101 | else => {}, |
| 189017 | } | 189102 | } |
| 189018 | tracking.reuse(cg, new_inst, old_inst); | 189103 | tracking.reuse(cg, new_inst, old_inst); |
| ... | @@ -191592,7 +191677,13 @@ const Select = struct { | ... | @@ -191592,7 +191677,13 @@ const Select = struct { |
| 191592 | } }, | 191677 | } }, |
| 191593 | .eflags => unreachable, | 191678 | .eflags => unreachable, |
| 191594 | .register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) }, | 191679 | .register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) }, |
| 191595 | .register_pair, .register_triple, .register_quadruple, .register_offset, .register_overflow => unreachable, | 191680 | .register_pair, |
| | 191681 | .register_triple, |
| | 191682 | .register_quadruple, |
| | 191683 | .register_offset, |
| | 191684 | .register_overflow, |
| | 191685 | .register_pair_overflow, |
| | 191686 | => unreachable, |
| 191596 | .register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) }, | 191687 | .register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) }, |
| 191597 | .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } }, | 191688 | .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } }, |
| 191598 | .lea_uav => |uav| .{ .imm = .{ .uav = uav } }, | 191689 | .lea_uav => |uav| .{ .imm = .{ .uav = uav } }, |