| ... | @@ -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, |
| ... | @@ -53047,7 +53067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -53047,7 +53067,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 53047 | }), | 53067 | }), |
| 53048 | else => |e| return e, | 53068 | else => |e| return e, |
| 53049 | }; | 53069 | }; |
| 53050 | try res[0].withOverflow(&res[1], cg); | 53070 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 53051 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 53071 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 53052 | }, | 53072 | }, |
| 53053 | .sub_with_overflow => |air_tag| { | 53073 | .sub_with_overflow => |air_tag| { |
| ... | @@ -53952,7 +53972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -53952,7 +53972,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 53952 | }), | 53972 | }), |
| 53953 | else => |e| return e, | 53973 | else => |e| return e, |
| 53954 | }; | 53974 | }; |
| 53955 | try res[0].withOverflow(&res[1], cg); | 53975 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 53956 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 53976 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 53957 | }, | 53977 | }, |
| 53958 | .mul_with_overflow => |air_tag| { | 53978 | .mul_with_overflow => |air_tag| { |
| ... | @@ -57549,7 +57569,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -57549,7 +57569,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 57549 | }), | 57569 | }), |
| 57550 | else => |e| return e, | 57570 | else => |e| return e, |
| 57551 | }; | 57571 | }; |
| 57552 | try res[0].withOverflow(&res[1], cg); | 57572 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 57553 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 57573 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 57554 | }, | 57574 | }, |
| 57555 | .shl_with_overflow => |air_tag| { | 57575 | .shl_with_overflow => |air_tag| { |
| ... | @@ -60894,7 +60914,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -60894,7 +60914,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 60894 | }), | 60914 | }), |
| 60895 | else => |e| return e, | 60915 | else => |e| return e, |
| 60896 | }; | 60916 | }; |
| 60897 | try res[0].withOverflow(&res[1], cg); | 60917 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| 60898 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 60918 | try res[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 60899 | }, | 60919 | }, |
| 60900 | .alloc => { | 60920 | .alloc => { |
| ... | @@ -104070,7 +104090,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -104070,7 +104090,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 104070 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; | 104090 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; |
| 104071 | const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data; | 104091 | const bin_op = cg.air.extraData(Air.Bin, ty_pl.payload).data; |
| 104072 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); | 104092 | var ops = try cg.tempsFromOperands(inst, .{ bin_op.lhs, bin_op.rhs }); |
| 104073 | try ops[0].toPair(&ops[1], cg); | 104093 | try ops[0].toPair(&ops[1], ty_pl.ty, cg); |
| 104074 | try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); | 104094 | try ops[0].finish(inst, &.{ bin_op.lhs, bin_op.rhs }, &ops, cg); |
| 104075 | }, | 104095 | }, |
| 104076 | .slice_len => { | 104096 | .slice_len => { |
| ... | @@ -104487,7 +104507,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -104487,7 +104507,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 104487 | var len = try cg.tempInit(.usize, .{ | 104507 | var len = try cg.tempInit(.usize, .{ |
| 104488 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), | 104508 | .immediate = cg.typeOf(ty_op.operand).childType(zcu).arrayLen(zcu), |
| 104489 | }); | 104509 | }); |
| 104490 | try ops[0].toPair(&len, cg); | 104510 | try ops[0].toPair(&len, ty_op.ty, cg); |
| 104491 | try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg); | 104511 | try ops[0].finish(inst, &.{ty_op.operand}, &ops, cg); |
| 104492 | }, | 104512 | }, |
| 104493 | .int_from_float, .int_from_float_optimized => |air_tag| { | 104513 | .int_from_float, .int_from_float_optimized => |air_tag| { |
| ... | @@ -171079,7 +171099,113 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -171079,7 +171099,113 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171079 | }; | 171099 | }; |
| 171080 | for (ops) |op| try op.die(cg); | 171100 | for (ops) |op| try op.die(cg); |
| 171081 | }, | 171101 | }, |
| 171082 | .cmpxchg_weak, .cmpxchg_strong => try cg.airCmpxchg(inst), | 171102 | .cmpxchg_weak, .cmpxchg_strong => |air_tag| { |
| | 171103 | const ty_pl = air_datas[@backingInt(inst)].ty_pl; |
| | 171104 | const extra = cg.air.extraData(Air.Cmpxchg, ty_pl.payload).data; |
| | 171105 | var ops = try cg.tempsFromOperands(inst, .{ extra.ptr, extra.expected_value, extra.new_value }); |
| | 171106 | var res: [2]Temp = undefined; |
| | 171107 | (if (ty_pl.ty.optionalReprIsPayload(zcu)) |
| | 171108 | cg.select(res[0..1], &.{ty_pl.ty}, &ops, comptime &.{.{ |
| | 171109 | .required_features = .{ .@"64bit", .cmov, null, null }, |
| | 171110 | .src_constraints = .{ .any, .{ .size = .qword }, .{ .size = .qword } }, |
| | 171111 | .patterns = &.{ |
| | 171112 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 171113 | }, |
| | 171114 | .extra_temps = .{ |
| | 171115 | .{ .type = .usize, .kind = .{ .rc = .general_purpose } }, |
| | 171116 | .unused, |
| | 171117 | .unused, |
| | 171118 | .unused, |
| | 171119 | .unused, |
| | 171120 | .unused, |
| | 171121 | .unused, |
| | 171122 | .unused, |
| | 171123 | .unused, |
| | 171124 | .unused, |
| | 171125 | .unused, |
| | 171126 | }, |
| | 171127 | .dst_temps = .{ .{ .ref = .src1 }, .unused }, |
| | 171128 | .clobbers = .{ .eflags = true }, |
| | 171129 | .each = .{ .once = &.{ |
| | 171130 | .{ ._, ._, .xor, .tmp0d, .tmp0d, ._, ._ }, |
| | 171131 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0q), .src2q, ._, ._ }, |
| | 171132 | .{ ._, ._e, .cmov, .dst0q, .tmp0q, ._, ._ }, |
| | 171133 | } }, |
| | 171134 | }}) |
| | 171135 | else |
| | 171136 | cg.select(&res, &.{ ty_pl.ty.childType(zcu), .u1 }, &ops, comptime &.{ .{ |
| | 171137 | .required_features = .{ .@"64bit", null, null, null }, |
| | 171138 | .src_constraints = .{ .any, .{ .int = .byte }, .{ .int = .byte } }, |
| | 171139 | .patterns = &.{ |
| | 171140 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 171141 | }, |
| | 171142 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 171143 | .clobbers = .{ .eflags = true }, |
| | 171144 | .each = .{ .once = &.{ |
| | 171145 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0b), .src2b, ._, ._ }, |
| | 171146 | } }, |
| | 171147 | }, .{ |
| | 171148 | .required_features = .{ .@"64bit", null, null, null }, |
| | 171149 | .src_constraints = .{ .any, .{ .int = .word }, .{ .int = .word } }, |
| | 171150 | .patterns = &.{ |
| | 171151 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 171152 | }, |
| | 171153 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 171154 | .clobbers = .{ .eflags = true }, |
| | 171155 | .each = .{ .once = &.{ |
| | 171156 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0w), .src2w, ._, ._ }, |
| | 171157 | } }, |
| | 171158 | }, .{ |
| | 171159 | .required_features = .{ .@"64bit", null, null, null }, |
| | 171160 | .src_constraints = .{ .any, .{ .int = .dword }, .{ .int = .dword } }, |
| | 171161 | .patterns = &.{ |
| | 171162 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 171163 | }, |
| | 171164 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 171165 | .clobbers = .{ .eflags = true }, |
| | 171166 | .each = .{ .once = &.{ |
| | 171167 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0d), .src2d, ._, ._ }, |
| | 171168 | } }, |
| | 171169 | }, .{ |
| | 171170 | .required_features = .{ .@"64bit", null, null, null }, |
| | 171171 | .src_constraints = .{ .any, .{ .int = .qword }, .{ .int = .qword } }, |
| | 171172 | .patterns = &.{ |
| | 171173 | .{ .src = .{ .to_gpr, .{ .to_reg = .rax }, .to_gpr } }, |
| | 171174 | }, |
| | 171175 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 171176 | .clobbers = .{ .eflags = true }, |
| | 171177 | .each = .{ .once = &.{ |
| | 171178 | .{ ._, .@"lock _", .cmpxchg, .lea(.src0q), .src2q, ._, ._ }, |
| | 171179 | } }, |
| | 171180 | }, .{ |
| | 171181 | .required_features = .{ .@"64bit", .cx16, null, null }, |
| | 171182 | .src_constraints = .{ .any, .{ .int = .xword }, .{ .int = .xword } }, |
| | 171183 | .patterns = &.{.{ |
| | 171184 | .src = .{ |
| | 171185 | .to_gpr, |
| | 171186 | .{ .to_reg_pair = .{ .rax, .rdx } }, |
| | 171187 | .{ .to_reg_pair = .{ .rbx, .rcx } }, |
| | 171188 | }, |
| | 171189 | }}, |
| | 171190 | .dst_temps = .{ .{ .ref = .src1 }, .{ .cc = .ne } }, |
| | 171191 | .clobbers = .{ .eflags = true }, |
| | 171192 | .each = .{ .once = &.{ |
| | 171193 | .{ ._, .@"lock _16b", .cmpxchg, .lea(.src0x), ._, ._, ._ }, |
| | 171194 | } }, |
| | 171195 | } })) catch |err| switch (err) { |
| | 171196 | error.SelectFailed => return cg.fail("failed to select {s} {f} {f} {f} {f}", .{ |
| | 171197 | @tagName(air_tag), |
| | 171198 | ty_pl.ty.fmt(zcu), |
| | 171199 | ops[0].tracking(cg), |
| | 171200 | ops[1].tracking(cg), |
| | 171201 | ops[2].tracking(cg), |
| | 171202 | }), |
| | 171203 | else => |e| return e, |
| | 171204 | }; |
| | 171205 | if (!ty_pl.ty.optionalReprIsPayload(zcu)) |
| | 171206 | try res[0].withOverflow(&res[1], ty_pl.ty, cg); |
| | 171207 | try res[0].finish(inst, &.{ extra.ptr, extra.expected_value, extra.new_value }, &ops, cg); |
| | 171208 | }, |
| 171083 | .atomic_load => try cg.airAtomicLoad(inst), | 171209 | .atomic_load => try cg.airAtomicLoad(inst), |
| 171084 | .atomic_store_unordered => try cg.airAtomicStore(inst, .unordered), | 171210 | .atomic_store_unordered => try cg.airAtomicStore(inst, .unordered), |
| 171085 | .atomic_store_monotonic => try cg.airAtomicStore(inst, .monotonic), | 171211 | .atomic_store_monotonic => try cg.airAtomicStore(inst, .monotonic), |
| ... | @@ -171421,7 +171547,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -171421,7 +171547,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171421 | }), | 171547 | }), |
| 171422 | else => |e| return e, | 171548 | else => |e| return e, |
| 171423 | }; | 171549 | }; |
| 171424 | if (res[0].tracking(cg).short != .register_pair) try ops[0].toPair(&res[0], cg); | 171550 | if (res[0].tracking(cg).short != .register_pair) try ops[0].toPair(&res[0], .slice_const_u8_sentinel_0, cg); |
| 171425 | try res[0].finish(inst, &.{un_op}, &ops, cg); | 171551 | try res[0].finish(inst, &.{un_op}, &ops, cg); |
| 171426 | }, | 171552 | }, |
| 171427 | .error_name => |air_tag| { | 171553 | .error_name => |air_tag| { |
| ... | @@ -171524,7 +171650,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -171524,7 +171650,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 171524 | else => |e| return e, | 171650 | else => |e| return e, |
| 171525 | }; | 171651 | }; |
| 171526 | const orig_res = res; | 171652 | const orig_res = res; |
| 171527 | try res[0].toPair(&res[1], cg); | 171653 | try res[0].toPair(&res[1], .slice_const_u8_sentinel_0, cg); |
| 171528 | for (&ops) |*op| for (orig_res) |orig_r| { | 171654 | for (&ops) |*op| for (orig_res) |orig_r| { |
| 171529 | if (op.index != orig_r.index) continue; | 171655 | if (op.index != orig_r.index) continue; |
| 171530 | op.* = res[0]; | 171656 | op.* = res[0]; |
| ... | @@ -174108,7 +174234,10 @@ fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void { | ... | @@ -174108,7 +174234,10 @@ fn getValue(self: *CodeGen, value: MCValue, inst: ?Air.Inst.Index) !void { |
| 174108 | for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst); | 174234 | for (value.getRegs()) |reg| try self.register_manager.getReg(reg, inst); |
| 174109 | switch (value) { | 174235 | switch (value) { |
| 174110 | else => {}, | 174236 | else => {}, |
| 174111 | .eflags, .register_overflow => self.eflags_inst = inst, | 174237 | .eflags, |
| | 174238 | .register_overflow, |
| | 174239 | .register_pair_overflow, |
| | 174240 | => self.eflags_inst = inst, |
| 174112 | } | 174241 | } |
| 174113 | } | 174242 | } |
| 174114 | | 174243 | |
| ... | @@ -174136,6 +174265,10 @@ fn freeValue(self: *CodeGen, value: MCValue, comptime opts: FreeOptions) !void { | ... | @@ -174136,6 +174265,10 @@ fn freeValue(self: *CodeGen, value: MCValue, comptime opts: FreeOptions) !void { |
| 174136 | try self.freeReg(reg_ov.reg, opts); | 174265 | try self.freeReg(reg_ov.reg, opts); |
| 174137 | self.eflags_inst = null; | 174266 | self.eflags_inst = null; |
| 174138 | }, | 174267 | }, |
| | 174268 | .register_pair_overflow => |rpo| { |
| | 174269 | for (rpo.pair) |r| try self.freeReg(r, opts); |
| | 174270 | self.eflags_inst = null; |
| | 174271 | }, |
| 174139 | .register_mask => |reg_mask| try self.freeReg(reg_mask.reg, opts), | 174272 | .register_mask => |reg_mask| try self.freeReg(reg_mask.reg, opts), |
| 174140 | .eflags => self.eflags_inst = null, | 174273 | .eflags => self.eflags_inst = null, |
| 174141 | else => {}, // TODO process stack allocation death | 174274 | else => {}, // TODO process stack allocation death |
| ... | @@ -174678,7 +174811,12 @@ fn reuseOperandAdvanced( | ... | @@ -174678,7 +174811,12 @@ fn reuseOperandAdvanced( |
| 174678 | return false; | 174811 | return false; |
| 174679 | | 174812 | |
| 174680 | switch (mcv) { | 174813 | switch (mcv) { |
| 174681 | .register, .register_pair, .register_overflow, .register_mask => for (mcv.getRegs()) |reg| { | 174814 | .register, |
| | 174815 | .register_pair, |
| | 174816 | .register_overflow, |
| | 174817 | .register_pair_overflow, |
| | 174818 | .register_mask, |
| | 174819 | => for (mcv.getRegs()) |reg| { |
| 174682 | // If it's in the registers table, need to associate the register(s) with the | 174820 | // If it's in the registers table, need to associate the register(s) with the |
| 174683 | // new instruction. | 174821 | // new instruction. |
| 174684 | if (maybe_tracked_inst) |tracked_inst| { | 174822 | if (maybe_tracked_inst) |tracked_inst| { |
| ... | @@ -174693,7 +174831,10 @@ fn reuseOperandAdvanced( | ... | @@ -174693,7 +174831,10 @@ fn reuseOperandAdvanced( |
| 174693 | else => return false, | 174831 | else => return false, |
| 174694 | } | 174832 | } |
| 174695 | switch (mcv) { | 174833 | switch (mcv) { |
| 174696 | .eflags, .register_overflow => self.eflags_inst = maybe_tracked_inst, | 174834 | .eflags, |
| | 174835 | .register_overflow, |
| | 174836 | .register_pair_overflow, |
| | 174837 | => self.eflags_inst = maybe_tracked_inst, |
| 174697 | else => {}, | 174838 | else => {}, |
| 174698 | } | 174839 | } |
| 174699 | | 174840 | |
| ... | @@ -174720,6 +174861,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE | ... | @@ -174720,6 +174861,7 @@ fn load(self: *CodeGen, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerE |
| 174720 | .register_triple, | 174861 | .register_triple, |
| 174721 | .register_quadruple, | 174862 | .register_quadruple, |
| 174722 | .register_overflow, | 174863 | .register_overflow, |
| | 174864 | .register_pair_overflow, |
| 174723 | .register_mask, | 174865 | .register_mask, |
| 174724 | .indirect_load_frame, | 174866 | .indirect_load_frame, |
| 174725 | .indirect_mask, | 174867 | .indirect_mask, |
| ... | @@ -174779,6 +174921,7 @@ fn store( | ... | @@ -174779,6 +174921,7 @@ fn store( |
| 174779 | .register_triple, | 174921 | .register_triple, |
| 174780 | .register_quadruple, | 174922 | .register_quadruple, |
| 174781 | .register_overflow, | 174923 | .register_overflow, |
| | 174924 | .register_pair_overflow, |
| 174782 | .register_mask, | 174925 | .register_mask, |
| 174783 | .indirect_load_frame, | 174926 | .indirect_load_frame, |
| 174784 | .indirect_mask, | 174927 | .indirect_mask, |
| ... | @@ -174830,6 +174973,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: | ... | @@ -174830,6 +174973,7 @@ fn genUnOpMir(self: *CodeGen, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: |
| 174830 | .register_offset, | 174973 | .register_offset, |
| 174831 | .eflags, | 174974 | .eflags, |
| 174832 | .register_overflow, | 174975 | .register_overflow, |
| | 174976 | .register_pair_overflow, |
| 174833 | .register_mask, | 174977 | .register_mask, |
| 174834 | .indirect_load_frame, | 174978 | .indirect_load_frame, |
| 174835 | .indirect_mask, | 174979 | .indirect_mask, |
| ... | @@ -175526,6 +175670,7 @@ fn genBinOpMir( | ... | @@ -175526,6 +175670,7 @@ fn genBinOpMir( |
| 175526 | .immediate, | 175670 | .immediate, |
| 175527 | .eflags, | 175671 | .eflags, |
| 175528 | .register_overflow, | 175672 | .register_overflow, |
| | 175673 | .register_pair_overflow, |
| 175529 | .register_mask, | 175674 | .register_mask, |
| 175530 | .lea_frame, | 175675 | .lea_frame, |
| 175531 | .lea_nav, | 175676 | .lea_nav, |
| ... | @@ -175574,6 +175719,7 @@ fn genBinOpMir( | ... | @@ -175574,6 +175719,7 @@ fn genBinOpMir( |
| 175574 | .dead, | 175719 | .dead, |
| 175575 | .undef, | 175720 | .undef, |
| 175576 | .register_overflow, | 175721 | .register_overflow, |
| | 175722 | .register_pair_overflow, |
| 175577 | .register_mask, | 175723 | .register_mask, |
| 175578 | .indirect_load_frame, | 175724 | .indirect_load_frame, |
| 175579 | .indirect_mask, | 175725 | .indirect_mask, |
| ... | @@ -175752,6 +175898,7 @@ fn genBinOpMir( | ... | @@ -175752,6 +175898,7 @@ fn genBinOpMir( |
| 175752 | .dead, | 175898 | .dead, |
| 175753 | .undef, | 175899 | .undef, |
| 175754 | .register_overflow, | 175900 | .register_overflow, |
| | 175901 | .register_pair_overflow, |
| 175755 | .register_mask, | 175902 | .register_mask, |
| 175756 | .indirect_load_frame, | 175903 | .indirect_load_frame, |
| 175757 | .indirect_mask, | 175904 | .indirect_mask, |
| ... | @@ -175862,6 +176009,7 @@ fn genBinOpMir( | ... | @@ -175862,6 +176009,7 @@ fn genBinOpMir( |
| 175862 | .dead, | 176009 | .dead, |
| 175863 | .undef, | 176010 | .undef, |
| 175864 | .register_overflow, | 176011 | .register_overflow, |
| | 176012 | .register_pair_overflow, |
| 175865 | .register_mask, | 176013 | .register_mask, |
| 175866 | .indirect_load_frame, | 176014 | .indirect_load_frame, |
| 175867 | .indirect_mask, | 176015 | .indirect_mask, |
| ... | @@ -178971,6 +179119,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -178971,6 +179119,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 178971 | .immediate, | 179119 | .immediate, |
| 178972 | .eflags, | 179120 | .eflags, |
| 178973 | .register_overflow, | 179121 | .register_overflow, |
| | 179122 | .register_pair_overflow, |
| 178974 | .register_mask, | 179123 | .register_mask, |
| 178975 | .indirect_load_frame, | 179124 | .indirect_load_frame, |
| 178976 | .indirect_mask, | 179125 | .indirect_mask, |
| ... | @@ -178995,6 +179144,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C | ... | @@ -178995,6 +179144,7 @@ fn genCopy(self: *CodeGen, ty: Type, dst_mcv: MCValue, src_mcv: MCValue, opts: C |
| 178995 | .dead, | 179144 | .dead, |
| 178996 | .undef, | 179145 | .undef, |
| 178997 | .register_overflow, | 179146 | .register_overflow, |
| | 179147 | .register_pair_overflow, |
| 178998 | .register_tee, | 179148 | .register_tee, |
| 178999 | .elementwise_gpr, | 179149 | .elementwise_gpr, |
| 179000 | .elementwise_sse, | 179150 | .elementwise_sse, |
| ... | @@ -179198,6 +179348,7 @@ fn genSetReg( | ... | @@ -179198,6 +179348,7 @@ fn genSetReg( |
| 179198 | .ywordwise_sse, | 179348 | .ywordwise_sse, |
| 179199 | .zwordwise_sse, | 179349 | .zwordwise_sse, |
| 179200 | .reserved_frame, | 179350 | .reserved_frame, |
| | 179351 | .register_pair_overflow, |
| 179201 | => unreachable, | 179352 | => unreachable, |
| 179202 | .undef => if (opts.safety) switch (dst_reg.class()) { | 179353 | .undef => if (opts.safety) switch (dst_reg.class()) { |
| 179203 | .general_purpose, .gphi => switch (abi_size) { | 179354 | .general_purpose, .gphi => switch (abi_size) { |
| ... | @@ -180001,6 +180152,23 @@ fn genSetMem( | ... | @@ -180001,6 +180152,23 @@ fn genSetMem( |
| 180001 | @tagName(src_mcv), ty.fmt(zcu), | 180152 | @tagName(src_mcv), ty.fmt(zcu), |
| 180002 | }), | 180153 | }), |
| 180003 | }, | 180154 | }, |
| | 180155 | .register_pair_overflow => |rpo| switch (ty.zigTypeTag(zcu)) { |
| | 180156 | .optional => { |
| | 180157 | assert(!ty.optionalReprIsPayload(zcu)); |
| | 180158 | const child_ty = ty.optionalChild(zcu); |
| | 180159 | try cg.genSetMem(base, disp, child_ty, .{ .register_pair = rpo.pair }, opts); |
| | 180160 | try cg.genSetMem( |
| | 180161 | base, |
| | 180162 | disp + @as(i32, @intCast(child_ty.abiSize(zcu))), |
| | 180163 | .bool, |
| | 180164 | .{ .eflags = rpo.eflags }, |
| | 180165 | opts, |
| | 180166 | ); |
| | 180167 | }, |
| | 180168 | else => return cg.fail("TODO implement genSetMem for {s} of {f}", .{ |
| | 180169 | @tagName(src_mcv), ty.fmt(zcu), |
| | 180170 | }), |
| | 180171 | }, |
| 180004 | .register_offset => |reg_off| { | 180172 | .register_offset => |reg_off| { |
| 180005 | const src_reg = cg.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) { | 180173 | const src_reg = cg.copyToTmpRegister(ty, src_mcv) catch |err| switch (err) { |
| 180006 | error.OutOfRegisters => { | 180174 | error.OutOfRegisters => { |
| ... | @@ -180335,111 +180503,6 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { | ... | @@ -180335,111 +180503,6 @@ fn airBitCast(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 180335 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 180503 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 180336 | } | 180504 | } |
| 180337 | | 180505 | |
| 180338 | fn airCmpxchg(self: *CodeGen, inst: Air.Inst.Index) !void { | | |
| 180339 | const pt = self.pt; | | |
| 180340 | const zcu = pt.zcu; | | |
| 180341 | const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | | |
| 180342 | const extra = self.air.extraData(Air.Cmpxchg, ty_pl.payload).data; | | |
| 180343 | | | |
| 180344 | const dst_ty = self.typeOfIndex(inst); | | |
| 180345 | const ptr_ty = self.typeOf(extra.ptr); | | |
| 180346 | const val_ty = self.typeOf(extra.expected_value); | | |
| 180347 | const val_abi_size: u32 = @intCast(val_ty.abiSize(zcu)); | | |
| 180348 | | | |
| 180349 | try self.spillRegisters(&.{ .rax, .rdx, .rbx, .rcx }); | | |
| 180350 | const regs_lock = self.register_manager.lockRegsAssumeUnused(4, .{ .rax, .rdx, .rbx, .rcx }); | | |
| 180351 | defer for (regs_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180352 | | | |
| 180353 | const exp_mcv = try self.resolveInst(extra.expected_value); | | |
| 180354 | if (val_abi_size > 8) { | | |
| 180355 | const exp_addr_mcv: MCValue = switch (exp_mcv) { | | |
| 180356 | .memory, .indirect, .load_frame => exp_mcv.address(), | | |
| 180357 | else => .{ .register = try self.copyToTmpRegister(.usize, exp_mcv.address()) }, | | |
| 180358 | }; | | |
| 180359 | const exp_addr_lock = | | |
| 180360 | if (exp_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | | |
| 180361 | defer if (exp_addr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180362 | | | |
| 180363 | try self.genSetReg(.rax, .usize, exp_addr_mcv.deref(), .{}); | | |
| 180364 | try self.genSetReg(.rdx, .usize, exp_addr_mcv.offset(8).deref(), .{}); | | |
| 180365 | } else try self.genSetReg(.rax, val_ty, exp_mcv, .{}); | | |
| 180366 | | | |
| 180367 | const new_mcv = try self.resolveInst(extra.new_value); | | |
| 180368 | const new_reg = if (val_abi_size > 8) new: { | | |
| 180369 | const new_addr_mcv: MCValue = switch (new_mcv) { | | |
| 180370 | .memory, .indirect, .load_frame => new_mcv.address(), | | |
| 180371 | else => .{ .register = try self.copyToTmpRegister(.usize, new_mcv.address()) }, | | |
| 180372 | }; | | |
| 180373 | const new_addr_lock = | | |
| 180374 | if (new_addr_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | | |
| 180375 | defer if (new_addr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180376 | | | |
| 180377 | try self.genSetReg(.rbx, .usize, new_addr_mcv.deref(), .{}); | | |
| 180378 | try self.genSetReg(.rcx, .usize, new_addr_mcv.offset(8).deref(), .{}); | | |
| 180379 | break :new null; | | |
| 180380 | } else try self.copyToTmpRegister(val_ty, new_mcv); | | |
| 180381 | const new_lock = if (new_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; | | |
| 180382 | defer if (new_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180383 | | | |
| 180384 | const ptr_mcv = try self.resolveInst(extra.ptr); | | |
| 180385 | const mem_size: Memory.Size = .fromSize(val_abi_size); | | |
| 180386 | const ptr_mem: Memory = switch (ptr_mcv) { | | |
| 180387 | .immediate, .register, .register_offset, .lea_frame => try ptr_mcv.deref().mem(self, .{ .size = mem_size }), | | |
| 180388 | else => .{ | | |
| 180389 | .base = .{ .reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv) }, | | |
| 180390 | .mod = .{ .rm = .{ .size = mem_size } }, | | |
| 180391 | }, | | |
| 180392 | }; | | |
| 180393 | switch (ptr_mem.mod) { | | |
| 180394 | .rm => {}, | | |
| 180395 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | | |
| 180396 | } | | |
| 180397 | const ptr_lock = switch (ptr_mem.base) { | | |
| 180398 | .none, .frame, .nav, .uav => null, | | |
| 180399 | .reg => |reg| self.register_manager.lockReg(reg), | | |
| 180400 | .table, .rip_inst, .lazy_sym, .extern_func => unreachable, | | |
| 180401 | }; | | |
| 180402 | defer if (ptr_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180403 | | | |
| 180404 | try self.spillEflagsIfOccupied(); | | |
| 180405 | const null_reg = if (dst_ty.optionalReprIsPayload(zcu) and !self.liveness.isUnused(inst)) null_reg: { | | |
| 180406 | const null_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); | | |
| 180407 | try self.asmRegisterRegister(.{ ._, .xor }, null_reg.to32(), null_reg.to32()); | | |
| 180408 | break :null_reg null_reg; | | |
| 180409 | } else null; | | |
| 180410 | const null_lock = if (null_reg) |reg| self.register_manager.lockRegAssumeUnused(reg) else null; | | |
| 180411 | defer if (null_lock) |lock| self.register_manager.unlockReg(lock); | | |
| 180412 | | | |
| 180413 | if (val_abi_size <= 8) try self.asmMemoryRegister( | | |
| 180414 | .{ .@"lock _", .cmpxchg }, | | |
| 180415 | ptr_mem, | | |
| 180416 | registerAlias(new_reg.?, val_abi_size), | | |
| 180417 | ) else try self.asmMemory(.{ .@"lock _16b", .cmpxchg }, ptr_mem); | | |
| 180418 | | | |
| 180419 | const result: MCValue = result: { | | |
| 180420 | if (self.liveness.isUnused(inst)) break :result .unreach; | | |
| 180421 | | | |
| 180422 | if (null_reg) |reg| try self.asmCmovccRegisterRegister( | | |
| 180423 | .e, | | |
| 180424 | registerAlias(.rax, val_abi_size), | | |
| 180425 | registerAlias(reg, val_abi_size), | | |
| 180426 | ); | | |
| 180427 | | | |
| 180428 | if (val_abi_size <= 8) { | | |
| 180429 | if (null_reg) |_| break :result .{ .register = .rax }; | | |
| 180430 | self.eflags_inst = inst; | | |
| 180431 | break :result .{ .register_overflow = .{ .reg = .rax, .eflags = .ne } }; | | |
| 180432 | } | | |
| 180433 | | | |
| 180434 | const dst_mcv = try self.allocRegOrMem(inst, false); | | |
| 180435 | try self.genCopy(.usize, dst_mcv, .{ .register = .rax }, .{}); | | |
| 180436 | try self.genCopy(.usize, dst_mcv.address().offset(8).deref(), .{ .register = .rdx }, .{}); | | |
| 180437 | if (null_reg == null) try self.genCopy(.bool, dst_mcv.address().offset(16).deref(), .{ .eflags = .ne }, .{}); | | |
| 180438 | break :result dst_mcv; | | |
| 180439 | }; | | |
| 180440 | return self.finishAir(inst, result, .{ extra.ptr, extra.expected_value, extra.new_value }); | | |
| 180441 | } | | |
| 180442 | | | |
| 180443 | fn atomicOp( | 180506 | fn atomicOp( |
| 180444 | self: *CodeGen, | 180507 | self: *CodeGen, |
| 180445 | ptr_mcv: MCValue, | 180508 | ptr_mcv: MCValue, |
| ... | @@ -180475,7 +180538,7 @@ fn atomicOp( | ... | @@ -180475,7 +180538,7 @@ fn atomicOp( |
| 180475 | }; | 180538 | }; |
| 180476 | switch (ptr_mem.mod) { | 180539 | switch (ptr_mem.mod) { |
| 180477 | .rm => {}, | 180540 | .rm => {}, |
| 180478 | .off => return self.fail("TODO airCmpxchg with {s}", .{@tagName(ptr_mcv)}), | 180541 | .off => return self.fail("TODO atomicOp with {s}", .{@tagName(ptr_mcv)}), |
| 180479 | } | 180542 | } |
| 180480 | const mem_lock = switch (ptr_mem.base) { | 180543 | const mem_lock = switch (ptr_mem.base) { |
| 180481 | .none, .frame, .nav, .uav => null, | 180544 | .none, .frame, .nav, .uav => null, |
| ... | @@ -182855,6 +182918,7 @@ const Temp = struct { | ... | @@ -182855,6 +182918,7 @@ const Temp = struct { |
| 182855 | .register_triple, | 182918 | .register_triple, |
| 182856 | .register_quadruple, | 182919 | .register_quadruple, |
| 182857 | .register_overflow, | 182920 | .register_overflow, |
| | 182921 | .register_pair_overflow, |
| 182858 | => true, | 182922 | => true, |
| 182859 | .load_frame => |frame_addr| !frame_addr.index.isNamed(), | 182923 | .load_frame => |frame_addr| !frame_addr.index.isNamed(), |
| 182860 | }, | 182924 | }, |
| ... | @@ -183235,7 +183299,7 @@ const Temp = struct { | ... | @@ -183235,7 +183299,7 @@ const Temp = struct { |
| 183235 | return true; | 183299 | return true; |
| 183236 | } | 183300 | } |
| 183237 | | 183301 | |
| 183238 | fn toPair(first_temp: *Temp, second_temp: *Temp, cg: *CodeGen) InnerError!void { | 183302 | fn toPair(first_temp: *Temp, second_temp: *Temp, result_ty: Type, cg: *CodeGen) InnerError!void { |
| 183239 | while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| { | 183303 | while (true) for ([_]*Temp{ first_temp, second_temp }) |part_temp| { |
| 183240 | if (try part_temp.toRegClass(true, .general_purpose, cg)) break; | 183304 | if (try part_temp.toRegClass(true, .general_purpose, cg)) break; |
| 183241 | } else break; | 183305 | } else break; |
| ... | @@ -183250,13 +183314,13 @@ const Temp = struct { | ... | @@ -183250,13 +183314,13 @@ const Temp = struct { |
| 183250 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); | 183314 | assert(cg.reuseTemp(result_temp.index, first_temp.index, first_temp_tracking)); |
| 183251 | assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); | 183315 | assert(cg.reuseTemp(result_temp.index, second_temp.index, second_temp_tracking)); |
| 183252 | result_temp_index.tracking(cg).* = .init(result); | 183316 | result_temp_index.tracking(cg).* = .init(result); |
| 183253 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 183317 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 183254 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 183318 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 183255 | first_temp.* = result_temp; | 183319 | first_temp.* = result_temp; |
| 183256 | second_temp.* = result_temp; | 183320 | second_temp.* = result_temp; |
| 183257 | } | 183321 | } |
| 183258 | | 183322 | |
| 183259 | fn withOverflow(temp: *Temp, overflow_temp: *Temp, cg: *CodeGen) InnerError!void { | 183323 | fn withOverflow(temp: *Temp, overflow_temp: *Temp, result_ty: Type, cg: *CodeGen) InnerError!void { |
| 183260 | const temp_index = temp.unwrap(cg).temp; | 183324 | const temp_index = temp.unwrap(cg).temp; |
| 183261 | const temp_tracking = temp_index.tracking(cg); | 183325 | const temp_tracking = temp_index.tracking(cg); |
| 183262 | const overflow_temp_tracking = overflow_temp.unwrap(cg).temp.tracking(cg); | 183326 | const overflow_temp_tracking = overflow_temp.unwrap(cg).temp.tracking(cg); |
| ... | @@ -183268,7 +183332,7 @@ const Temp = struct { | ... | @@ -183268,7 +183332,7 @@ const Temp = struct { |
| 183268 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); | 183332 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| 183269 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); | 183333 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| 183270 | result_temp_index.tracking(cg).* = .init(.{ .register_overflow = .{ .reg = reg, .eflags = overflow_cc } }); | 183334 | result_temp_index.tracking(cg).* = .init(.{ .register_overflow = .{ .reg = reg, .eflags = overflow_cc } }); |
| 183271 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 183335 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 183272 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 183336 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 183273 | temp.* = result_temp; | 183337 | temp.* = result_temp; |
| 183274 | overflow_temp.* = result_temp; | 183338 | overflow_temp.* = result_temp; |
| ... | @@ -183280,7 +183344,22 @@ const Temp = struct { | ... | @@ -183280,7 +183344,22 @@ const Temp = struct { |
| 183280 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); | 183344 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| 183281 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); | 183345 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| 183282 | result_temp_index.tracking(cg).* = .init(.{ .register_pair = .{ reg, overflow_reg } }); | 183346 | result_temp_index.tracking(cg).* = .init(.{ .register_pair = .{ reg, overflow_reg } }); |
| 183283 | cg.temp_type[@backingInt(result_temp_index)] = .slice_const_u8; | 183347 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| | 183348 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| | 183349 | temp.* = result_temp; |
| | 183350 | overflow_temp.* = result_temp; |
| | 183351 | return; |
| | 183352 | }, |
| | 183353 | else => {}, |
| | 183354 | }, |
| | 183355 | .register_pair => |pair| switch (overflow_temp_tracking.short) { |
| | 183356 | .eflags => |overflow_cc| { |
| | 183357 | const result_temp_index = cg.next_temp_index; |
| | 183358 | const result_temp: Temp = .{ .index = result_temp_index.toIndex() }; |
| | 183359 | assert(cg.reuseTemp(result_temp.index, temp.index, temp_tracking)); |
| | 183360 | assert(cg.reuseTemp(result_temp.index, overflow_temp.index, overflow_temp_tracking)); |
| | 183361 | result_temp_index.tracking(cg).* = .init(.{ .register_pair_overflow = .{ .pair = pair, .eflags = overflow_cc } }); |
| | 183362 | cg.temp_type[@backingInt(result_temp_index)] = result_ty; |
| 183284 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); | 183363 | cg.next_temp_index = @fromBackingInt(@intCast(@backingInt(result_temp_index) + 1)); |
| 183285 | temp.* = result_temp; | 183364 | temp.* = result_temp; |
| 183286 | overflow_temp.* = result_temp; | 183365 | overflow_temp.* = result_temp; |
| ... | @@ -183320,6 +183399,7 @@ const Temp = struct { | ... | @@ -183320,6 +183399,7 @@ const Temp = struct { |
| 183320 | .register_triple, | 183399 | .register_triple, |
| 183321 | .register_quadruple, | 183400 | .register_quadruple, |
| 183322 | .register_overflow, | 183401 | .register_overflow, |
| | 183402 | .register_pair_overflow, |
| 183323 | .register_mask, | 183403 | .register_mask, |
| 183324 | .indirect_load_frame, | 183404 | .indirect_load_frame, |
| 183325 | .indirect_mask, | 183405 | .indirect_mask, |
| ... | @@ -189802,6 +189882,7 @@ const Temp = struct { | ... | @@ -189802,6 +189882,7 @@ const Temp = struct { |
| 189802 | .register_quadruple, | 189882 | .register_quadruple, |
| 189803 | .register_offset, | 189883 | .register_offset, |
| 189804 | .register_overflow, | 189884 | .register_overflow, |
| | 189885 | .register_pair_overflow, |
| 189805 | .register_mask, | 189886 | .register_mask, |
| 189806 | .memory, | 189887 | .memory, |
| 189807 | .indirect, | 189888 | .indirect, |
| ... | @@ -189920,6 +190001,7 @@ fn reuseTemp( | ... | @@ -189920,6 +190001,7 @@ fn reuseTemp( |
| 189920 | .register_pair, | 190001 | .register_pair, |
| 189921 | .register_offset, | 190002 | .register_offset, |
| 189922 | .register_overflow, | 190003 | .register_overflow, |
| | 190004 | .register_pair_overflow, |
| 189923 | .register_mask, | 190005 | .register_mask, |
| 189924 | .indirect, | 190006 | .indirect, |
| 189925 | => for (tracking.short.getRegs()) |tracked_reg| { | 190007 | => for (tracking.short.getRegs()) |tracked_reg| { |
| ... | @@ -189931,7 +190013,10 @@ fn reuseTemp( | ... | @@ -189931,7 +190013,10 @@ fn reuseTemp( |
| 189931 | else => {}, | 190013 | else => {}, |
| 189932 | } | 190014 | } |
| 189933 | switch (tracking.short) { | 190015 | switch (tracking.short) { |
| 189934 | .eflags, .register_overflow => cg.eflags_inst = new_inst, | 190016 | .eflags, |
| | 190017 | .register_overflow, |
| | 190018 | .register_pair_overflow, |
| | 190019 | => cg.eflags_inst = new_inst, |
| 189935 | else => {}, | 190020 | else => {}, |
| 189936 | } | 190021 | } |
| 189937 | tracking.reuse(cg, new_inst, old_inst); | 190022 | tracking.reuse(cg, new_inst, old_inst); |
| ... | @@ -192514,7 +192599,13 @@ const Select = struct { | ... | @@ -192514,7 +192599,13 @@ const Select = struct { |
| 192514 | } }, | 192599 | } }, |
| 192515 | .eflags => unreachable, | 192600 | .eflags => unreachable, |
| 192516 | .register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) }, | 192601 | .register => |reg| .{ .reg = s.lowerReg(reg.toSize(op.flags.base.size, s.cg.target)) }, |
| 192517 | .register_pair, .register_triple, .register_quadruple, .register_offset, .register_overflow => unreachable, | 192602 | .register_pair, |
| | 192603 | .register_triple, |
| | 192604 | .register_quadruple, |
| | 192605 | .register_offset, |
| | 192606 | .register_overflow, |
| | 192607 | .register_pair_overflow, |
| | 192608 | => unreachable, |
| 192518 | .register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) }, | 192609 | .register_mask => |reg_mask| .{ .reg = s.lowerReg(reg_mask.reg.toSize(op.flags.base.size, s.cg.target)) }, |
| 192519 | .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } }, | 192610 | .lea_nav => |nav| .{ .imm = .{ .nav = .{ .index = nav } } }, |
| 192520 | .lea_uav => |uav| .{ .imm = .{ .uav = uav } }, | 192611 | .lea_uav => |uav| .{ .imm = .{ .uav = uav } }, |