authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-10-16 18:32:02+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2020-10-25 12:51:19+01:00
log7d14426da49fcb42b69d41a36935cf65ad70c697
tree3796759fce8718de1f205c918fba1581e2647c8d
parent0e16328636c29b4d82331744cfa1eaad1b7a8507

stage2 ARM: enable backpatching return statement


2 files changed, 48 insertions(+), 15 deletions(-)

src/codegen.zig+38-9
...@@ -587,11 +587,36 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -587,11 +587,36 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
587587
588 try self.dbgSetEpilogueBegin();588 try self.dbgSetEpilogueBegin();
589589
590 // exitlude jumps
591 if (self.exitlude_jump_relocs.items.len == 1) {
592 // There is only one relocation. Hence,
593 // this relocation must be at the end of
594 // the code. Therefore, we can just delete
595 // the space initially reserved for the
596 // jump
597 self.code.items.len -= 4;
598 } else for (self.exitlude_jump_relocs.items) |jmp_reloc| {
599 const amt = self.code.items.len - (jmp_reloc + 4);
600 if (amt == 0) {
601 // This return is at the end of the
602 // code block. We can't just delete
603 // the space because there may be
604 // other jumps we already relocated to
605 // the address. Instead, insert a nop
606 mem.writeIntLittle(u32, self.code.items[jmp_reloc..][0..4], Instruction.nop().toU32());
607 } else {
608 if (math.cast(i26, amt)) |offset| {
609 mem.writeIntLittle(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(.al, offset).toU32());
610 } else |err| {
611 return self.fail(self.src, "exitlude jump is too large", .{});
612 }
613 }
614 }
615
590 // mov sp, fp616 // mov sp, fp
591 // pop {fp, pc}617 // pop {fp, pc}
592 // TODO: return by jumping to this code, use relocations618 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32());
593 // mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32());619 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.pop(.al, .{ .fp, .pc }).toU32());
594 // mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.pop(.al, .{ .fp, .pc }).toU32());
595 } else {620 } else {
596 try self.dbgSetPrologueEnd();621 try self.dbgSetPrologueEnd();
597 try self.genBody(self.mod_fn.analysis.success);622 try self.genBody(self.mod_fn.analysis.success);
...@@ -1661,12 +1686,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1661,12 +1686,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1661 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.zero, 0, .ra).toU32());1686 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.zero, 0, .ra).toU32());
1662 },1687 },
1663 .arm => {1688 .arm => {
1664 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .sp, Instruction.Operand.reg(.fp, Instruction.Operand.Shift.none)).toU32());1689 // Just add space for an instruction, patch this later
1665 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.pop(.al, .{ .fp, .pc }).toU32());1690 try self.code.resize(self.code.items.len + 4);
1666 // TODO: jump to the end with relocation1691 try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
1667 // // Just add space for an instruction, patch this later
1668 // try self.code.resize(self.code.items.len + 4);
1669 // try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
1670 },1692 },
1671 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),1693 else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
1672 }1694 }
...@@ -1932,6 +1954,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1932,6 +1954,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1932 mem.writeIntLittle(i32, self.code.addManyAsArrayAssumeCapacity(4), delta);1954 mem.writeIntLittle(i32, self.code.addManyAsArrayAssumeCapacity(4), delta);
1933 }1955 }
1934 },1956 },
1957 .arm => {
1958 if (math.cast(i26, @intCast(i32, index) - @intCast(i32, self.code.items.len))) |delta| {
1959 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.b(.al, delta).toU32());
1960 } else |err| {
1961 return self.fail(src, "TODO: enable larger branch offset", .{});
1962 }
1963 },
1935 else => return self.fail(src, "TODO implement jump for {}", .{self.target.cpu.arch}),1964 else => return self.fail(src, "TODO implement jump for {}", .{self.target.cpu.arch}),
1936 }1965 }
1937 }1966 }
src/codegen/arm.zig+10-6
...@@ -575,12 +575,12 @@ pub const Instruction = union(enum) {...@@ -575,12 +575,12 @@ pub const Instruction = union(enum) {
575 };575 };
576 }576 }
577577
578 fn branch(cond: Condition, offset: i24, link: u1) Instruction {578 fn branch(cond: Condition, offset: i26, link: u1) Instruction {
579 return Instruction{579 return Instruction{
580 .Branch = .{580 .Branch = .{
581 .cond = @enumToInt(cond),581 .cond = @enumToInt(cond),
582 .link = link,582 .link = link,
583 .offset = @bitCast(u24, offset),583 .offset = @bitCast(u24, @intCast(i24, offset >> 2)),
584 },584 },
585 };585 };
586 }586 }
...@@ -895,11 +895,11 @@ pub const Instruction = union(enum) {...@@ -895,11 +895,11 @@ pub const Instruction = union(enum) {
895895
896 // Branch896 // Branch
897897
898 pub fn b(cond: Condition, offset: i24) Instruction {898 pub fn b(cond: Condition, offset: i26) Instruction {
899 return branch(cond, offset, 0);899 return branch(cond, offset, 0);
900 }900 }
901901
902 pub fn bl(cond: Condition, offset: i24) Instruction {902 pub fn bl(cond: Condition, offset: i26) Instruction {
903 return branch(cond, offset, 1);903 return branch(cond, offset, 1);
904 }904 }
905905
...@@ -929,6 +929,10 @@ pub const Instruction = union(enum) {...@@ -929,6 +929,10 @@ pub const Instruction = union(enum) {
929929
930 // Aliases930 // Aliases
931931
932 pub fn nop() Instruction {
933 return mov(.al, .r0, Instruction.Operand.reg(.r0, Instruction.Operand.Shift.none));
934 }
935
932 pub fn pop(cond: Condition, args: anytype) Instruction {936 pub fn pop(cond: Condition, args: anytype) Instruction {
933 if (@typeInfo(@TypeOf(args)) != .Struct) {937 if (@typeInfo(@TypeOf(args)) != .Struct) {
934 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));938 @compileError("Expected tuple or struct argument, found " ++ @typeName(@TypeOf(args)));
...@@ -1025,11 +1029,11 @@ test "serialize instructions" {...@@ -1025,11 +1029,11 @@ test "serialize instructions" {
1025 },1029 },
1026 .{ // b #121030 .{ // b #12
1027 .inst = Instruction.b(.al, 12),1031 .inst = Instruction.b(.al, 12),
1028 .expected = 0b1110_101_0_0000_0000_0000_0000_0000_1100,1032 .expected = 0b1110_101_0_0000_0000_0000_0000_0000_0011,
1029 },1033 },
1030 .{ // bl #-41034 .{ // bl #-4
1031 .inst = Instruction.bl(.al, -4),1035 .inst = Instruction.bl(.al, -4),
1032 .expected = 0b1110_101_1_1111_1111_1111_1111_1111_1100,1036 .expected = 0b1110_101_1_1111_1111_1111_1111_1111_1111,
1033 },1037 },
1034 .{ // bx lr1038 .{ // bx lr
1035 .inst = Instruction.bx(.al, .lr),1039 .inst = Instruction.bx(.al, .lr),