| ... | @@ -1329,59 +1329,49 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1329,59 +1329,49 @@ fn airPtrSlicePtrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1329 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 1329 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| 1330 | } | 1330 | } |
| 1331 | | 1331 | |
| | 1332 | fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Register { |
| | 1333 | const reg = try self.register_manager.allocReg(null, &.{}); |
| | 1334 | try self.genSetReg(index_ty, reg, index); |
| | 1335 | try self.genIMulOpMir(index_ty, .{ .register = reg }, .{ .immediate = elem_size }); |
| | 1336 | return reg; |
| | 1337 | } |
| | 1338 | |
| 1332 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1339 | fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1333 | const is_volatile = false; // TODO | 1340 | const is_volatile = false; // TODO |
| 1334 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1341 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1335 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { | 1342 | const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { |
| 1336 | const slice_mcv = try self.resolveInst(bin_op.lhs); | 1343 | const slice_mcv = try self.resolveInst(bin_op.lhs); |
| 1337 | const slice_ty = self.air.typeOf(bin_op.lhs); | 1344 | const slice_ty = self.air.typeOf(bin_op.lhs); |
| 1338 | | | |
| 1339 | const elem_ty = slice_ty.childType(); | 1345 | const elem_ty = slice_ty.childType(); |
| 1340 | const elem_size = elem_ty.abiSize(self.target.*); | 1346 | const elem_size = elem_ty.abiSize(self.target.*); |
| 1341 | | | |
| 1342 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; | 1347 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 1343 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); | 1348 | const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf); |
| 1344 | | 1349 | const index_ty = self.air.typeOf(bin_op.rhs); |
| 1345 | const offset_reg = blk: { | 1350 | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 1346 | const index_ty = self.air.typeOf(bin_op.rhs); | 1351 | const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size); |
| 1347 | const index_mcv = try self.resolveInst(bin_op.rhs); | 1352 | const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg}); |
| 1348 | const offset_reg = try self.register_manager.allocReg(null, &.{}); | 1353 | switch (slice_mcv) { |
| 1349 | try self.genSetReg(index_ty, offset_reg, index_mcv); | 1354 | .stack_offset => |off| { |
| 1350 | try self.genIMulOpMir(index_ty, .{ .register = offset_reg }, .{ .immediate = elem_size }); | 1355 | // mov reg, [rbp - 8] |
| 1351 | break :blk offset_reg; | 1356 | _ = try self.addInst(.{ |
| 1352 | }; | 1357 | .tag = .mov, |
| 1353 | | 1358 | .ops = (Mir.Ops{ |
| 1354 | const dst_mcv = blk: { | 1359 | .reg1 = addr_reg.to64(), |
| 1355 | switch (slice_mcv) { | 1360 | .reg2 = .rbp, |
| 1356 | .stack_offset => |off| { | 1361 | .flags = 0b01, |
| 1357 | const dst_mcv = try self.allocRegOrMem(inst, false); | 1362 | }).encode(), |
| 1358 | const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg}); | 1363 | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) }, |
| 1359 | // mov reg, [rbp - 8] | 1364 | }); |
| 1360 | _ = try self.addInst(.{ | 1365 | }, |
| 1361 | .tag = .mov, | 1366 | else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}), |
| 1362 | .ops = (Mir.Ops{ | 1367 | } |
| 1363 | .reg1 = addr_reg.to64(), | 1368 | // TODO we could allocate register here, but need to except addr register and potentially |
| 1364 | .reg2 = .rbp, | 1369 | // offset register. |
| 1365 | .flags = 0b01, | 1370 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| 1366 | }).encode(), | 1371 | try self.genBinMathOpMir(.add, slice_ptr_field_type, .unsigned, .{ .register = addr_reg.to64() }, .{ |
| 1367 | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + 16)) }, | 1372 | .register = offset_reg.to64(), |
| 1368 | }); | 1373 | }); |
| 1369 | // add addr, offset | 1374 | try self.load(dst_mcv, .{ .register = addr_reg.to64() }, slice_ptr_field_type); |
| 1370 | _ = try self.addInst(.{ | | |
| 1371 | .tag = .add, | | |
| 1372 | .ops = (Mir.Ops{ | | |
| 1373 | .reg1 = addr_reg.to64(), | | |
| 1374 | .reg2 = offset_reg.to64(), | | |
| 1375 | }).encode(), | | |
| 1376 | .data = undefined, | | |
| 1377 | }); | | |
| 1378 | try self.load(dst_mcv, .{ .register = addr_reg }, slice_ptr_field_type); | | |
| 1379 | break :blk dst_mcv; | | |
| 1380 | }, | | |
| 1381 | else => return self.fail("TODO implement slice_elem_val when slice is {}", .{slice_mcv}), | | |
| 1382 | } | | |
| 1383 | }; | | |
| 1384 | | | |
| 1385 | break :result dst_mcv; | 1375 | break :result dst_mcv; |
| 1386 | }; | 1376 | }; |
| 1387 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1377 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| ... | @@ -1399,10 +1389,43 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1399,10 +1389,43 @@ fn airSliceElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1399 | | 1389 | |
| 1400 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | 1390 | fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1401 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 1391 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 1402 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1392 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1403 | .dead | 1393 | const array_ty = self.air.typeOf(bin_op.lhs); |
| 1404 | else | 1394 | const array = try self.resolveInst(bin_op.lhs); |
| 1405 | return self.fail("TODO implement array_elem_val for {}", .{self.target.cpu.arch}); | 1395 | const array_abi_size = array_ty.abiSize(self.target.*); |
| | 1396 | const elem_ty = array_ty.childType(); |
| | 1397 | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| | 1398 | const index_ty = self.air.typeOf(bin_op.rhs); |
| | 1399 | const index = try self.resolveInst(bin_op.rhs); |
| | 1400 | const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size); |
| | 1401 | const addr_reg = try self.register_manager.allocReg(null, &.{offset_reg}); |
| | 1402 | switch (array) { |
| | 1403 | .stack_offset => |off| { |
| | 1404 | // lea reg, [rbp] |
| | 1405 | _ = try self.addInst(.{ |
| | 1406 | .tag = .lea, |
| | 1407 | .ops = (Mir.Ops{ |
| | 1408 | .reg1 = addr_reg.to64(), |
| | 1409 | .reg2 = .rbp, |
| | 1410 | }).encode(), |
| | 1411 | .data = .{ .imm = @bitCast(u32, -@intCast(i32, off + array_abi_size)) }, |
| | 1412 | }); |
| | 1413 | }, |
| | 1414 | else => return self.fail("TODO implement array_elem_val when array is {}", .{array}), |
| | 1415 | } |
| | 1416 | // TODO we could allocate register here, but need to except addr register and potentially |
| | 1417 | // offset register. |
| | 1418 | const dst_mcv = try self.allocRegOrMem(inst, false); |
| | 1419 | try self.genBinMathOpMir( |
| | 1420 | .add, |
| | 1421 | array_ty, |
| | 1422 | .unsigned, |
| | 1423 | .{ .register = addr_reg.to64() }, |
| | 1424 | .{ .register = offset_reg.to64() }, |
| | 1425 | ); |
| | 1426 | try self.load(dst_mcv, .{ .register = addr_reg.to64() }, array_ty); |
| | 1427 | break :result dst_mcv; |
| | 1428 | }; |
| 1406 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); | 1429 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 1407 | } | 1430 | } |
| 1408 | | 1431 | |
| ... | @@ -1419,10 +1442,27 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1419,10 +1442,27 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 1419 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { | 1442 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 1420 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 1443 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 1421 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; | 1444 | const extra = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 1422 | const result: MCValue = if (self.liveness.isUnused(inst)) | 1445 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: { |
| 1423 | .dead | 1446 | const ptr_ty = self.air.typeOf(extra.lhs); |
| 1424 | else | 1447 | const ptr = try self.resolveInst(extra.lhs); |
| 1425 | return self.fail("TODO implement ptr_elem_ptr for {}", .{self.target.cpu.arch}); | 1448 | const elem_ty = ptr_ty.elemType2(); |
| | 1449 | const elem_abi_size = elem_ty.abiSize(self.target.*); |
| | 1450 | const index_ty = self.air.typeOf(extra.rhs); |
| | 1451 | const index = try self.resolveInst(extra.rhs); |
| | 1452 | const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size); |
| | 1453 | const dst_mcv = blk: { |
| | 1454 | switch (ptr) { |
| | 1455 | .ptr_stack_offset => { |
| | 1456 | const reg = try self.register_manager.allocReg(inst, &.{offset_reg}); |
| | 1457 | try self.genSetReg(ptr_ty, reg, ptr); |
| | 1458 | break :blk .{ .register = reg }; |
| | 1459 | }, |
| | 1460 | else => return self.fail("TODO implement ptr_elem_ptr when ptr is {}", .{ptr}), |
| | 1461 | } |
| | 1462 | }; |
| | 1463 | try self.genBinMathOpMir(.add, ptr_ty, .unsigned, dst_mcv, .{ .register = offset_reg }); |
| | 1464 | break :result dst_mcv; |
| | 1465 | }; |
| 1426 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); | 1466 | return self.finishAir(inst, result, .{ extra.lhs, extra.rhs, .none }); |
| 1427 | } | 1467 | } |
| 1428 | | 1468 | |
| ... | @@ -3742,12 +3782,12 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3742,12 +3782,12 @@ fn airArrayToSlice(self: *Self, inst: Air.Inst.Index) !void { |
| 3742 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 3782 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 3743 | const ptr_ty = self.air.typeOf(ty_op.operand); | 3783 | const ptr_ty = self.air.typeOf(ty_op.operand); |
| 3744 | const ptr = try self.resolveInst(ty_op.operand); | 3784 | const ptr = try self.resolveInst(ty_op.operand); |
| | 3785 | const array_ty = ptr_ty.childType(); |
| | 3786 | const array_len = array_ty.arrayLenIncludingSentinel(); |
| 3745 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { | 3787 | const result: MCValue = if (self.liveness.isUnused(inst)) .dead else blk: { |
| 3746 | const stack_offset = try self.allocMem(inst, 16, 16); | 3788 | const stack_offset = try self.allocMem(inst, 16, 16); |
| 3747 | const array_ty = ptr_ty.childType(); | | |
| 3748 | const array_len = array_ty.arrayLenIncludingSentinel(); | | |
| 3749 | try self.genSetStack(ptr_ty, stack_offset + 8, ptr); | 3789 | try self.genSetStack(ptr_ty, stack_offset + 8, ptr); |
| 3750 | try self.genSetStack(Type.initTag(.u64), stack_offset + 16, .{ .immediate = array_len }); | 3790 | try self.genSetStack(Type.initTag(.u64), stack_offset, .{ .immediate = array_len }); |
| 3751 | break :blk .{ .stack_offset = stack_offset }; | 3791 | break :blk .{ .stack_offset = stack_offset }; |
| 3752 | }; | 3792 | }; |
| 3753 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 3793 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |