authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-18 16:30:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-18 18:55:02+01:00
log8201939d7f57d5332d209dd7fb728eafe5a8b882
tree6a0ad47edace2ca4645defee791473f5a31efba4
parent8c233687b4b0fdad725bf81b204dde7ccba45f56

stage2: implement airArrayElemVal


2 files changed, 95 insertions(+), 57 deletions(-)

src/arch/x86_64/CodeGen.zig+94-54
...@@ -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}
13311331
1332fn 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
1332fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {1339fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1333 const is_volatile = false; // TODO1340 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);
13441349 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,
13531358 .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, offset1374 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 {
13991389
1400fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {1390fn 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 .dead1393 const array_ty = self.air.typeOf(bin_op.lhs);
1404 else1394 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}
14081431
...@@ -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 {
1419fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {1442fn 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 .dead1446 const ptr_ty = self.air.typeOf(extra.lhs);
1424 else1447 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}
14281468
...@@ -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 });
test/behavior/array.zig+1-3
...@@ -75,8 +75,6 @@ test "array literal with inferred length" {...@@ -75,8 +75,6 @@ test "array literal with inferred length" {
75}75}
7676
77test "array dot len const expr" {77test "array dot len const expr" {
78 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
79
80 try expect(comptime x: {78 try expect(comptime x: {
81 break :x some_array.len == 4;79 break :x some_array.len == 4;
82 });80 });
...@@ -166,7 +164,7 @@ test "nested arrays" {...@@ -166,7 +164,7 @@ test "nested arrays" {
166}164}
167165
168test "implicit comptime in array type size" {166test "implicit comptime in array type size" {
169 if (builtin.zig_backend == .stage2_x86_64 or builtin.zig_backend == .stage2_arm) return error.SkipZigTest;167 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
170168
171 var arr: [plusOne(10)]bool = undefined;169 var arr: [plusOne(10)]bool = undefined;
172 try expect(arr.len == 11);170 try expect(arr.len == 11);