| ... | @@ -596,10 +596,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -596,10 +596,11 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 596 | .array_to_slice => try self.airArrayToSlice(inst), | 596 | .array_to_slice => try self.airArrayToSlice(inst), |
| 597 | .int_to_float => try self.airIntToFloat(inst), | 597 | .int_to_float => try self.airIntToFloat(inst), |
| 598 | .float_to_int => try self.airFloatToInt(inst), | 598 | .float_to_int => try self.airFloatToInt(inst), |
| 599 | .cmpxchg_strong => @panic("TODO try self.airCmpxchg(inst)"), | 599 | .cmpxchg_strong, |
| 600 | .cmpxchg_weak => @panic("TODO try self.airCmpxchg(inst)"), | 600 | .cmpxchg_weak, |
| 601 | .atomic_rmw => @panic("TODO try self.airAtomicRmw(inst)"), | 601 | => try self.airCmpxchg(inst), |
| 602 | .atomic_load => @panic("TODO try self.airAtomicLoad(inst)"), | 602 | .atomic_rmw => try self.airAtomicRmw(inst), |
| | 603 | .atomic_load => try self.airAtomicLoad(inst), |
| 603 | .memcpy => @panic("TODO try self.airMemcpy(inst)"), | 604 | .memcpy => @panic("TODO try self.airMemcpy(inst)"), |
| 604 | .memset => try self.airMemset(inst), | 605 | .memset => try self.airMemset(inst), |
| 605 | .set_union_tag => try self.airSetUnionTag(inst), | 606 | .set_union_tag => try self.airSetUnionTag(inst), |
| ... | @@ -1023,6 +1024,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1023,6 +1024,22 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1023 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); | 1024 | return self.finishAir(inst, mcv, .{ .none, .none, .none }); |
| 1024 | } | 1025 | } |
| 1025 | | 1026 | |
| | 1027 | fn airAtomicLoad(self: *Self, inst: Air.Inst.Index) !void { |
| | 1028 | _ = self.air.instructions.items(.data)[inst].atomic_load; |
| | 1029 | |
| | 1030 | return self.fail("TODO implement airAtomicLoad for {}", .{ |
| | 1031 | self.target.cpu.arch, |
| | 1032 | }); |
| | 1033 | } |
| | 1034 | |
| | 1035 | fn airAtomicRmw(self: *Self, inst: Air.Inst.Index) !void { |
| | 1036 | _ = self.air.instructions.items(.data)[inst].pl_op; |
| | 1037 | |
| | 1038 | return self.fail("TODO implement airAtomicRmw for {}", .{ |
| | 1039 | self.target.cpu.arch, |
| | 1040 | }); |
| | 1041 | } |
| | 1042 | |
| 1026 | fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { | 1043 | fn airBinOp(self: *Self, inst: Air.Inst.Index, tag: Air.Inst.Tag) !void { |
| 1027 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1044 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1028 | const lhs = try self.resolveInst(bin_op.lhs); | 1045 | const lhs = try self.resolveInst(bin_op.lhs); |
| ... | @@ -1332,6 +1349,16 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1332,6 +1349,16 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1332 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 1349 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 1333 | } | 1350 | } |
| 1334 | | 1351 | |
| | 1352 | fn airCmpxchg(self: *Self, inst: Air.Inst.Index) !void { |
| | 1353 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| | 1354 | const extra = self.air.extraData(Air.Block, ty_pl.payload); |
| | 1355 | _ = extra; |
| | 1356 | |
| | 1357 | return self.fail("TODO implement airCmpxchg for {}", .{ |
| | 1358 | self.target.cpu.arch, |
| | 1359 | }); |
| | 1360 | } |
| | 1361 | |
| 1335 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | 1362 | fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1336 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 1363 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |
| 1337 | const condition = try self.resolveInst(pl_op.operand); | 1364 | const condition = try self.resolveInst(pl_op.operand); |
| ... | @@ -1416,6 +1443,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1416,6 +1443,7 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void { |
| 1416 | const else_value = else_values[else_idx]; | 1443 | const else_value = else_values[else_idx]; |
| 1417 | const canon_mcv = if (saved_then_branch.inst_table.fetchSwapRemove(else_key)) |then_entry| blk: { | 1444 | const canon_mcv = if (saved_then_branch.inst_table.fetchSwapRemove(else_key)) |then_entry| blk: { |
| 1418 | // The instruction's MCValue is overridden in both branches. | 1445 | // The instruction's MCValue is overridden in both branches. |
| | 1446 | log.debug("condBr put branch table (key = %{d}, value = {})", .{ else_key, then_entry.value }); |
| 1419 | parent_branch.inst_table.putAssumeCapacity(else_key, then_entry.value); | 1447 | parent_branch.inst_table.putAssumeCapacity(else_key, then_entry.value); |
| 1420 | if (else_value == .dead) { | 1448 | if (else_value == .dead) { |
| 1421 | assert(then_entry.value == .dead); | 1449 | assert(then_entry.value == .dead); |
| ... | @@ -2908,7 +2936,18 @@ fn binOpImmediate( | ... | @@ -2908,7 +2936,18 @@ fn binOpImmediate( |
| 2908 | | 2936 | |
| 2909 | const reg = try self.register_manager.allocReg(track_inst, gp); | 2937 | const reg = try self.register_manager.allocReg(track_inst, gp); |
| 2910 | | 2938 | |
| 2911 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 2939 | if (track_inst) |inst| { |
| | 2940 | const mcv = .{ .register = reg }; |
| | 2941 | log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv }); |
| | 2942 | branch.inst_table.putAssumeCapacity(inst, mcv); |
| | 2943 | |
| | 2944 | // If we're moving a condition flag MCV to register, |
| | 2945 | // mark it as free. |
| | 2946 | if (lhs == .condition_flags) { |
| | 2947 | assert(self.condition_flags_inst.? == inst); |
| | 2948 | self.condition_flags_inst = null; |
| | 2949 | } |
| | 2950 | } |
| 2912 | | 2951 | |
| 2913 | break :blk reg; | 2952 | break :blk reg; |
| 2914 | }; | 2953 | }; |
| ... | @@ -3035,7 +3074,18 @@ fn binOpRegister( | ... | @@ -3035,7 +3074,18 @@ fn binOpRegister( |
| 3035 | } else null; | 3074 | } else null; |
| 3036 | | 3075 | |
| 3037 | const reg = try self.register_manager.allocReg(track_inst, gp); | 3076 | const reg = try self.register_manager.allocReg(track_inst, gp); |
| 3038 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 3077 | if (track_inst) |inst| { |
| | 3078 | const mcv = .{ .register = reg }; |
| | 3079 | log.debug("binOpRegister move lhs %{d} to register: {} -> {}", .{ inst, lhs, mcv }); |
| | 3080 | branch.inst_table.putAssumeCapacity(inst, mcv); |
| | 3081 | |
| | 3082 | // If we're moving a condition flag MCV to register, |
| | 3083 | // mark it as free. |
| | 3084 | if (lhs == .condition_flags) { |
| | 3085 | assert(self.condition_flags_inst.? == inst); |
| | 3086 | self.condition_flags_inst = null; |
| | 3087 | } |
| | 3088 | } |
| 3039 | | 3089 | |
| 3040 | break :blk reg; | 3090 | break :blk reg; |
| 3041 | }; | 3091 | }; |
| ... | @@ -3048,7 +3098,18 @@ fn binOpRegister( | ... | @@ -3048,7 +3098,18 @@ fn binOpRegister( |
| 3048 | } else null; | 3098 | } else null; |
| 3049 | | 3099 | |
| 3050 | const reg = try self.register_manager.allocReg(track_inst, gp); | 3100 | const reg = try self.register_manager.allocReg(track_inst, gp); |
| 3051 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 3101 | if (track_inst) |inst| { |
| | 3102 | const mcv = .{ .register = reg }; |
| | 3103 | log.debug("binOpRegister move rhs %{d} to register: {} -> {}", .{ inst, rhs, mcv }); |
| | 3104 | branch.inst_table.putAssumeCapacity(inst, mcv); |
| | 3105 | |
| | 3106 | // If we're moving a condition flag MCV to register, |
| | 3107 | // mark it as free. |
| | 3108 | if (rhs == .condition_flags) { |
| | 3109 | assert(self.condition_flags_inst.? == inst); |
| | 3110 | self.condition_flags_inst = null; |
| | 3111 | } |
| | 3112 | } |
| 3052 | | 3113 | |
| 3053 | break :blk reg; | 3114 | break :blk reg; |
| 3054 | }; | 3115 | }; |
| ... | @@ -3867,6 +3928,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { | ... | @@ -3867,6 +3928,7 @@ fn getResolvedInstValue(self: *Self, inst: Air.Inst.Index) MCValue { |
| 3867 | while (true) { | 3928 | while (true) { |
| 3868 | i -= 1; | 3929 | i -= 1; |
| 3869 | if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| { | 3930 | if (self.branch_stack.items[i].inst_table.get(inst)) |mcv| { |
| | 3931 | log.debug("getResolvedInstValue %{} => {}", .{ inst, mcv }); |
| 3870 | assert(mcv != .dead); | 3932 | assert(mcv != .dead); |
| 3871 | return mcv; | 3933 | return mcv; |
| 3872 | } | 3934 | } |
| ... | @@ -4082,6 +4144,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { | ... | @@ -4082,6 +4144,7 @@ fn processDeath(self: *Self, inst: Air.Inst.Index) void { |
| 4082 | const prev_value = self.getResolvedInstValue(inst); | 4144 | const prev_value = self.getResolvedInstValue(inst); |
| 4083 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; | 4145 | const branch = &self.branch_stack.items[self.branch_stack.items.len - 1]; |
| 4084 | branch.inst_table.putAssumeCapacity(inst, .dead); | 4146 | branch.inst_table.putAssumeCapacity(inst, .dead); |
| | 4147 | log.debug("%{} death: {} -> .dead", .{ inst, prev_value }); |
| 4085 | switch (prev_value) { | 4148 | switch (prev_value) { |
| 4086 | .register => |reg| { | 4149 | .register => |reg| { |
| 4087 | self.register_manager.freeReg(reg); | 4150 | self.register_manager.freeReg(reg); |