| ... | @@ -1274,7 +1274,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1274,7 +1274,7 @@ fn airSliceLen(self: *Self, inst: Air.Inst.Index) !void { |
| 1274 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { | 1274 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1275 | const operand = try self.resolveInst(ty_op.operand); | 1275 | const operand = try self.resolveInst(ty_op.operand); |
| 1276 | const dst_mcv: MCValue = switch (operand) { | 1276 | const dst_mcv: MCValue = switch (operand) { |
| 1277 | .stack_offset => |off| MCValue{ .stack_offset = off + 4 }, | 1277 | .stack_offset => |off| MCValue{ .stack_offset = off + 8 }, |
| 1278 | else => return self.fail("TODO implement slice_len for {}", .{operand}), | 1278 | else => return self.fail("TODO implement slice_len for {}", .{operand}), |
| 1279 | }; | 1279 | }; |
| 1280 | break :result dst_mcv; | 1280 | break :result dst_mcv; |
| ... | @@ -1303,10 +1303,57 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1303,10 +1303,57 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1303 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1303 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1304 | const is_volatile = false; // TODO | 1304 | const is_volatile = false; // TODO |
| 1305 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1305 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1306 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) | 1306 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { |
| 1307 | .dead | 1307 | const slice_mcv = try self.resolveInst(bin_op.lhs); |
| 1308 | else | 1308 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 1309 | return self.fail("TODO implement slice_elem_val for {}", .{self.target.cpu.arch}); | 1309 | |
| | 1310 | const elem_ty = slice_ty.childType(); |
| | 1311 | const elem_size = elem_ty.abiSize(self.target.*); |
| | 1312 | |
| | 1313 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| | 1314 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| | 1315 | |
| | 1316 | const index_ty = self.air.typeOf(bin_op.rhs); |
| | 1317 | const index_mcv: MCValue = blk: { |
| | 1318 | switch (try self.resolveInst(bin_op.rhs)) { |
| | 1319 | .register => |reg| { |
| | 1320 | if (reg.to64() != .rcx) { |
| | 1321 | try self.register_manager.getReg(.rcx, inst); |
| | 1322 | } |
| | 1323 | break :blk MCValue{ .register = .rcx }; |
| | 1324 | }, |
| | 1325 | else => return self.fail("TODO move index mcv into a register", .{}), |
| | 1326 | } |
| | 1327 | }; |
| | 1328 | |
| | 1329 | try self.genIMulOpMir(index_ty, index_mcv, .{ .immediate = elem_size }); |
| | 1330 | |
| | 1331 | const dst_mcv = blk: { |
| | 1332 | switch (slice_mcv) { |
| | 1333 | .stack_offset => |unadjusted_off| { |
| | 1334 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| | 1335 | const addr_reg = try self.register_manager.allocReg(null, &.{index_mcv.register}); |
| | 1336 | const slice_ptr_abi_size = @intCast(u32, slice_ptr_field_type.abiSize(self.target.*)); |
| | 1337 | const off = unadjusted_off + elem_size; |
| | 1338 | // lea reg, [rbp - 8 + rcx*1] |
| | 1339 | _ = try self.addInst(.{ |
| | 1340 | .tag = .lea, |
| | 1341 | .ops = (Mir.Ops{ |
| | 1342 | .reg1 = registerAlias(addr_reg, slice_ptr_abi_size), |
| | 1343 | .reg2 = .rbp, |
| | 1344 | .flags = 0b11, |
| | 1345 | }).encode(), |
| | 1346 | .data = .{ .imm = -@intCast(i32, off) }, |
| | 1347 | }); |
| | 1348 | try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type); |
| | 1349 | break :blk dst_mcv; |
| | 1350 | }, |
| | 1351 | else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}), |
| | 1352 | } |
| | 1353 | }; |
| | 1354 | |
| | 1355 | break :result dst_mcv; |
| | 1356 | }; |
| 1310 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1357 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1311 | } | 1358 | } |
| 1312 | | 1359 | |
| ... | @@ -1791,6 +1838,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! | ... | @@ -1791,6 +1838,7 @@ fn genIMulOpMir(self: *Self, dst_ty: Type, dst_mcv: MCValue, src_mcv: MCValue) ! |
| 1791 | .data = .{ .imm = @intCast(i32, imm) }, | 1838 | .data = .{ .imm = @intCast(i32, imm) }, |
| 1792 | }); | 1839 | }); |
| 1793 | } else { | 1840 | } else { |
| | 1841 | // TODO verify we don't spill and assign to the same register as dst_mcv |
| 1794 | const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv); | 1842 | const src_reg = try self.copyToTmpRegister(dst_ty, src_mcv); |
| 1795 | return self.genIMulOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg }); | 1843 | return self.genIMulOpMir(dst_ty, dst_mcv, MCValue{ .register = src_reg }); |
| 1796 | } | 1844 | } |
| ... | @@ -2906,12 +2954,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2906,12 +2954,6 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2906 | }, | 2954 | }, |
| 2907 | } | 2955 | } |
| 2908 | }, | 2956 | }, |
| 2909 | .embedded_in_code, .memory => { | | |
| 2910 | // TODO this and `.stack_offset` below need to get improved to support types greater than | | |
| 2911 | // register size, and do general memcpy | | |
| 2912 | const reg = try self.copyToTmpRegister(ty, mcv); | | |
| 2913 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | | |
| 2914 | }, | | |
| 2915 | .register => |reg| { | 2957 | .register => |reg| { |
| 2916 | if (stack_offset > math.maxInt(i32)) { | 2958 | if (stack_offset > math.maxInt(i32)) { |
| 2917 | return self.fail("stack offset too large", .{}); | 2959 | return self.fail("stack offset too large", .{}); |
| ... | @@ -2928,15 +2970,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -2928,15 +2970,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2928 | .data = .{ .imm = -@intCast(i32, adj_off) }, | 2970 | .data = .{ .imm = -@intCast(i32, adj_off) }, |
| 2929 | }); | 2971 | }); |
| 2930 | }, | 2972 | }, |
| 2931 | .stack_offset => |off| { | 2973 | .stack_offset, |
| 2932 | // TODO this and `.embedded_in_code` above need to get improved to support types greater than | 2974 | .embedded_in_code, |
| | 2975 | .memory, |
| | 2976 | => { |
| | 2977 | // TODO this needs to get improved to support types greater than |
| 2933 | // register size, and do general memcpy | 2978 | // register size, and do general memcpy |
| | 2979 | if (mcv == .stack_offset and mcv.stack_offset == stack_offset) { |
| | 2980 | // Copy stack variable to itself; nothing to do. |
| | 2981 | return; |
| | 2982 | } |
| 2934 | | 2983 | |
| 2935 | if (stack_offset == off) | 2984 | if (ty.abiSize(self.target.*) <= 8) { |
| 2936 | return; // Copy stack variable to itself; nothing to do. | 2985 | const reg = try self.copyToTmpRegister(ty, mcv); |
| | 2986 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| | 2987 | } |
| 2937 | | 2988 | |
| 2938 | const reg = try self.copyToTmpRegister(ty, mcv); | 2989 | return self.fail("TODO implement memcpy for ABI size {} > 8", .{ty.abiSize(self.target.*)}); |
| 2939 | return self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); | | |
| 2940 | }, | 2990 | }, |
| 2941 | } | 2991 | } |
| 2942 | } | 2992 | } |