authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-04-11 19:00:25-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-04-11 19:00:25-07:00
logd2d4df40746dc65802e074ab9a532cf78e698333
treeb9da84bf7a6c02d664bd2893865794debe9e9033
parentc5e662d860f7b77350a06938ca2e40993eb70a3c
parent4fe575f47bbc10ee56f47bd9e7e1b8dacd35fc41
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #8477 from joachimschmidt557/stage2-arm

stage2 codegen: Set MCValue of register arguments to their stack copies

2 files changed, 92 insertions(+), 27 deletions(-)

src/codegen.zig+53-27
...@@ -1681,22 +1681,34 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1681,22 +1681,34 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16811681
1682 switch (mcv) {1682 switch (mcv) {
1683 .register => |reg| {1683 .register => |reg| {
1684 // Copy arg to stack for better debugging1684 switch (self.debug_output) {
1685 const ty = inst.base.ty;1685 .dwarf => |dbg_out| {
1686 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {1686 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3);
1687 return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty});1687 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1688 };1688 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1689 const abi_align = ty.abiAlignment(self.target.*);1689 1, // ULEB128 dwarf expression length
1690 const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align);1690 reg.dwarfLocOp(),
1691 try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg });1691 });
1692 const adjusted_stack_offset = math.negateCast(stack_offset + abi_size) catch {1692 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len);
1693 return self.fail(inst.base.src, "Stack offset too large for arguments", .{});1693 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1694 };1694 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
16951695 },
1696 .none => {},
1697 }
1698 },
1699 .stack_offset => |offset| {
1696 switch (self.debug_output) {1700 switch (self.debug_output) {
1697 .dwarf => |dbg_out| {1701 .dwarf => |dbg_out| {
1698 switch (arch) {1702 switch (arch) {
1699 .arm, .armeb => {1703 .arm, .armeb => {
1704 const ty = inst.base.ty;
1705 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
1706 return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty});
1707 };
1708 const adjusted_stack_offset = math.negateCast(offset + abi_size) catch {
1709 return self.fail(inst.base.src, "Stack offset too large for arguments", .{});
1710 };
1711
1700 try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);1712 try dbg_out.dbg_info.append(link.File.Elf.abbrev_parameter);
17011713
1702 // Get length of the LEB128 stack offset1714 // Get length of the LEB128 stack offset
...@@ -1708,19 +1720,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1708,19 +1720,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1708 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);1720 try leb128.writeULEB128(dbg_out.dbg_info.writer(), counting_writer.bytes_written + 1);
1709 try dbg_out.dbg_info.append(DW.OP_breg11);1721 try dbg_out.dbg_info.append(DW.OP_breg11);
1710 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);1722 try leb128.writeILEB128(dbg_out.dbg_info.writer(), adjusted_stack_offset);
1723
1724 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len);
1725 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1726 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
1711 },1727 },
1712 else => {1728 else => {},
1713 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 3);
1714 dbg_out.dbg_info.appendAssumeCapacity(link.File.Elf.abbrev_parameter);
1715 dbg_out.dbg_info.appendSliceAssumeCapacity(&[2]u8{ // DW.AT_location, DW.FORM_exprloc
1716 1, // ULEB128 dwarf expression length
1717 reg.dwarfLocOp(),
1718 });
1719 },
1720 }1729 }
1721 try dbg_out.dbg_info.ensureCapacity(dbg_out.dbg_info.items.len + 5 + name_with_null.len);
1722 try self.addDbgInfoTypeReloc(inst.base.ty); // DW.AT_type, DW.FORM_ref4
1723 dbg_out.dbg_info.appendSliceAssumeCapacity(name_with_null); // DW.AT_name, DW.FORM_string
1724 },1730 },
1725 .none => {},1731 .none => {},
1726 }1732 }
...@@ -1738,19 +1744,39 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1738,19 +1744,39 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1738 }1744 }
17391745
1740 const result = self.args[arg_index];1746 const result = self.args[arg_index];
1741 try self.genArgDbgInfo(inst, result);1747 const mcv = switch (arch) {
1748 // TODO support stack-only arguments on all target architectures
1749 .arm, .armeb, .aarch64, .aarch64_32, .aarch64_be => switch (result) {
1750 // Copy registers to the stack
1751 .register => |reg| blk: {
1752 const ty = inst.base.ty;
1753 const abi_size = math.cast(u32, ty.abiSize(self.target.*)) catch {
1754 return self.fail(inst.base.src, "type '{}' too big to fit into stack frame", .{ty});
1755 };
1756 const abi_align = ty.abiAlignment(self.target.*);
1757 const stack_offset = try self.allocMem(&inst.base, abi_size, abi_align);
1758 try self.genSetStack(inst.base.src, ty, stack_offset, MCValue{ .register = reg });
1759
1760 break :blk MCValue{ .stack_offset = stack_offset };
1761 },
1762 else => result,
1763 },
1764 else => result,
1765 };
1766 try self.genArgDbgInfo(inst, mcv);
17421767
1743 if (inst.base.isUnused())1768 if (inst.base.isUnused())
1744 return MCValue.dead;1769 return MCValue.dead;
17451770
1746 switch (result) {1771 switch (mcv) {
1747 .register => |reg| {1772 .register => |reg| {
1748 try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1);1773 try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1);
1749 self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base);1774 self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base);
1750 },1775 },
1751 else => {},1776 else => {},
1752 }1777 }
1753 return result;1778
1779 return mcv;
1754 }1780 }
17551781
1756 fn genBreakpoint(self: *Self, src: LazySrcLoc) !MCValue {1782 fn genBreakpoint(self: *Self, src: LazySrcLoc) !MCValue {
...@@ -2257,7 +2283,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2257,7 +2283,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2257 const rhs = try self.resolveInst(inst.rhs);2283 const rhs = try self.resolveInst(inst.rhs);
22582284
2259 const src_mcv = rhs;2285 const src_mcv = rhs;
2260 const dst_mcv = if (lhs != .register) try self.copyToNewRegister(&inst.base, lhs) else lhs;2286 const dst_mcv = if (lhs != .register) try self.copyToNewRegister(inst.lhs, lhs) else lhs;
22612287
2262 try self.genArmBinOpCode(inst.base.src, dst_mcv.register, dst_mcv, src_mcv, .cmp_eq);2288 try self.genArmBinOpCode(inst.base.src, dst_mcv.register, dst_mcv, src_mcv, .cmp_eq);
2263 const info = inst.lhs.ty.intInfo(self.target.*);2289 const info = inst.lhs.ty.intInfo(self.target.*);
test/stage2/arm.zig+39
...@@ -419,4 +419,43 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -419,4 +419,43 @@ pub fn addCases(ctx: *TestContext) !void {
419 "",419 "",
420 );420 );
421 }421 }
422
423 {
424 var case = ctx.exe("recursive fibonacci", linux_arm);
425 case.addCompareOutput(
426 \\export fn _start() noreturn {
427 \\ assert(fib(0) == 0);
428 \\ assert(fib(1) == 1);
429 \\ assert(fib(2) == 1);
430 \\ assert(fib(3) == 2);
431 \\ assert(fib(10) == 55);
432 \\ assert(fib(20) == 6765);
433 \\ exit();
434 \\}
435 \\
436 \\fn fib(n: u32) u32 {
437 \\ if (n < 2) {
438 \\ return n;
439 \\ } else {
440 \\ return fib(n - 2) + fib(n - 1);
441 \\ }
442 \\}
443 \\
444 \\fn assert(ok: bool) void {
445 \\ if (!ok) unreachable;
446 \\}
447 \\
448 \\fn exit() noreturn {
449 \\ asm volatile ("svc #0"
450 \\ :
451 \\ : [number] "{r7}" (1),
452 \\ [arg1] "{r0}" (0)
453 \\ : "memory"
454 \\ );
455 \\ unreachable;
456 \\}
457 ,
458 "",
459 );
460 }
422}461}