authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-29 02:28:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-07-29 02:29:37-07:00
log8899e6e334758f2e101399075d0456195035c372
tree5ae6f6dd8afba7cacd3d5b1532d4c25b3661189d
parent606f157a6b6001b2623d28275a892c1a8ee3a646

stage2: codegen: fix off-by-one stack variable offsets


1 files changed, 14 insertions(+), 8 deletions(-)

src-self-hosted/codegen.zig+14-8
...@@ -1346,11 +1346,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1346,11 +1346,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1346 return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{});1346 return self.fail(src, "TODO implement set stack variable with compare flags value (signed)", .{});
1347 },1347 },
1348 .immediate => |x_big| {1348 .immediate => |x_big| {
1349 if (stack_offset > 128) {1349 const abi_size = ty.abiSize(self.target.*);
1350 const adj_off = stack_offset + abi_size;
1351 if (adj_off > 128) {
1350 return self.fail(src, "TODO implement set stack variable with large stack offset", .{});1352 return self.fail(src, "TODO implement set stack variable with large stack offset", .{});
1351 }1353 }
1352 try self.code.ensureCapacity(self.code.items.len + 8);1354 try self.code.ensureCapacity(self.code.items.len + 8);
1353 switch (ty.abiSize(self.target.*)) {1355 switch (abi_size) {
1354 1 => {1356 1 => {
1355 return self.fail(src, "TODO implement set abi_size=1 stack variable with immediate", .{});1357 return self.fail(src, "TODO implement set abi_size=1 stack variable with immediate", .{});
1356 },1358 },
...@@ -1361,7 +1363,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1361,7 +1363,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1361 const x = @intCast(u32, x_big);1363 const x = @intCast(u32, x_big);
1362 // We have a positive stack offset value but we want a twos complement negative1364 // We have a positive stack offset value but we want a twos complement negative
1363 // offset from rbp, which is at the top of the stack frame.1365 // offset from rbp, which is at the top of the stack frame.
1364 const negative_offset = @intCast(i8, -@intCast(i32, stack_offset));1366 const negative_offset = @intCast(i8, -@intCast(i32, adj_off));
1365 const twos_comp = @bitCast(u8, negative_offset);1367 const twos_comp = @bitCast(u8, negative_offset);
1366 // mov DWORD PTR [rbp+offset], immediate1368 // mov DWORD PTR [rbp+offset], immediate
1367 self.code.appendSliceAssumeCapacity(&[_]u8{ 0xc7, 0x45, twos_comp });1369 self.code.appendSliceAssumeCapacity(&[_]u8{ 0xc7, 0x45, twos_comp });
...@@ -1382,19 +1384,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1382,19 +1384,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1382 return self.fail(src, "TODO implement set stack variable from embedded_in_code", .{});1384 return self.fail(src, "TODO implement set stack variable from embedded_in_code", .{});
1383 },1385 },
1384 .register => |reg| {1386 .register => |reg| {
1387 const abi_size = ty.abiSize(self.target.*);
1388 const adj_off = stack_offset + abi_size;
1385 try self.code.ensureCapacity(self.code.items.len + 7);1389 try self.code.ensureCapacity(self.code.items.len + 7);
1386 self.rex(.{ .w = reg.size() == 64, .b = reg.isExtended() });1390 self.rex(.{ .w = reg.size() == 64, .b = reg.isExtended() });
1387 const reg_id: u8 = @truncate(u3, reg.id());1391 const reg_id: u8 = @truncate(u3, reg.id());
1388 if (stack_offset <= 128) {1392 if (adj_off <= 128) {
1389 // example: 48 89 55 7f mov QWORD PTR [rbp+0x7f],rdx1393 // example: 48 89 55 7f mov QWORD PTR [rbp+0x7f],rdx
1390 const RM = @as(u8, 0b01_000_101) | (reg_id << 3);1394 const RM = @as(u8, 0b01_000_101) | (reg_id << 3);
1391 const negative_offset = @intCast(i8, -@intCast(i32, stack_offset));1395 const negative_offset = @intCast(i8, -@intCast(i32, adj_off));
1392 const twos_comp = @bitCast(u8, negative_offset);1396 const twos_comp = @bitCast(u8, negative_offset);
1393 self.code.appendSliceAssumeCapacity(&[_]u8{ 0x89, RM, twos_comp });1397 self.code.appendSliceAssumeCapacity(&[_]u8{ 0x89, RM, twos_comp });
1394 } else if (stack_offset <= 2147483648) {1398 } else if (adj_off <= 2147483648) {
1395 // example: 48 89 95 80 00 00 00 mov QWORD PTR [rbp+0x80],rdx1399 // example: 48 89 95 80 00 00 00 mov QWORD PTR [rbp+0x80],rdx
1396 const RM = @as(u8, 0b10_000_101) | (reg_id << 3);1400 const RM = @as(u8, 0b10_000_101) | (reg_id << 3);
1397 const negative_offset = @intCast(i32, -@intCast(i33, stack_offset));1401 const negative_offset = @intCast(i32, -@intCast(i33, adj_off));
1398 const twos_comp = @bitCast(u32, negative_offset);1402 const twos_comp = @bitCast(u32, negative_offset);
1399 self.code.appendSliceAssumeCapacity(&[_]u8{ 0x89, RM });1403 self.code.appendSliceAssumeCapacity(&[_]u8{ 0x89, RM });
1400 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), twos_comp);1404 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), twos_comp);
...@@ -1605,8 +1609,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1605,8 +1609,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1605 }1609 }
1606 }1610 }
1607 },1611 },
1608 .stack_offset => |off| {1612 .stack_offset => |unadjusted_off| {
1609 try self.code.ensureCapacity(self.code.items.len + 7);1613 try self.code.ensureCapacity(self.code.items.len + 7);
1614 const size_bytes = @divExact(reg.size(), 8);
1615 const off = unadjusted_off + size_bytes;
1610 self.rex(.{ .w = reg.size() == 64, .r = reg.isExtended() });1616 self.rex(.{ .w = reg.size() == 64, .r = reg.isExtended() });
1611 const reg_id: u8 = @truncate(u3, reg.id());1617 const reg_id: u8 = @truncate(u3, reg.id());
1612 if (off <= 128) {1618 if (off <= 128) {