stage2 aarch64: add basic function pro/epilogue

Fix typo in `nop` implementation.
Simplify `aarch64` macOS tests.
This commit is contained in:
Jakub Konka 2021-01-17 11:26:02 +01:00
parent e292f33de7
commit b25cf7db02
3 changed files with 88 additions and 81 deletions

View File

@ -637,6 +637,67 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
try self.dbgSetEpilogueBegin();
}
},
.aarch64, .aarch64_be, .aarch64_32 => {
const cc = self.fn_type.fnCallingConvention();
if (cc != .Naked) {
// TODO Finish function prologue and epilogue for aarch64.
// Reserve the stack for local variables, etc.
// stp fp, lr, [sp, #-16]!
writeInt(u32, try self.code.addManyAsArray(4), Instruction.stp(
.x29,
.x30,
Register.sp,
Instruction.LoadStorePairOffset.pre_index(-16),
).toU32());
try self.dbgSetPrologueEnd();
try self.genBody(self.mod_fn.body);
try self.dbgSetEpilogueBegin();
// exitlude jumps
if (self.exitlude_jump_relocs.items.len == 1) {
// There is only one relocation. Hence,
// this relocation must be at the end of
// the code. Therefore, we can just delete
// the space initially reserved for the
// jump
self.code.items.len -= 4;
} else for (self.exitlude_jump_relocs.items) |jmp_reloc| {
const amt = @intCast(i32, self.code.items.len) - @intCast(i32, jmp_reloc + 8);
if (amt == -4) {
// This return is at the end of the
// code block. We can't just delete
// the space because there may be
// other jumps we already relocated to
// the address. Instead, insert a nop
writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.nop().toU32());
} else {
if (math.cast(i28, amt)) |offset| {
writeInt(u32, self.code.items[jmp_reloc..][0..4], Instruction.b(offset).toU32());
} else |err| {
return self.failSymbol("exitlude jump is too large", .{});
}
}
}
// ldp fp, lr, [sp], #16
writeInt(u32, try self.code.addManyAsArray(4), Instruction.ldp(
.x29,
.x30,
Register.sp,
Instruction.LoadStorePairOffset.post_index(16),
).toU32());
// ret lr
writeInt(u32, try self.code.addManyAsArray(4), Instruction.ret(null).toU32());
} else {
try self.dbgSetPrologueEnd();
try self.genBody(self.mod_fn.body);
try self.dbgSetEpilogueBegin();
}
},
else => {
try self.dbgSetPrologueEnd();
try self.genBody(self.mod_fn.body);
@ -1962,8 +2023,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
},
.aarch64 => {
// TODO: relocations
writeInt(u32, try self.code.addManyAsArray(4), Instruction.ret(null).toU32());
// Just add space for an instruction, patch this later
try self.code.resize(self.code.items.len + 4);
try self.exitlude_jump_relocs.append(self.gpa, self.code.items.len - 4);
},
else => return self.fail(src, "TODO implement return for {}", .{self.target.cpu.arch}),
}

View File

@ -814,7 +814,7 @@ pub const Instruction = union(enum) {
// Nop
pub fn nop() Instruction {
return Instruction{ .NoOperation = {} };
return Instruction{ .NoOperation = .{} };
}
// Logical (shifted register)

View File

@ -17,97 +17,60 @@ pub fn addCases(ctx: *TestContext) !void {
// Regular old hello world
case.addCompareOutput(
\\extern "c" fn write(usize, usize, usize) void;
\\extern "c" fn exit(usize) noreturn;
\\
\\export fn _start() noreturn {
\\ print();
\\
\\ exit();
\\ exit(0);
\\}
\\
\\fn print() void {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (4),
\\ [arg1] "{x0}" (1),
\\ [arg2] "{x1}" (@ptrToInt("Hello, World!\n")),
\\ [arg3] "{x2}" (14)
\\ : "memory"
\\ );
\\ return;
\\}
\\
\\fn exit() noreturn {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (1),
\\ [arg1] "{x0}" (0)
\\ : "memory"
\\ );
\\ unreachable;
\\ const msg = @ptrToInt("Hello, World!\n");
\\ const len = 14;
\\ write(1, msg, len);
\\}
,
"Hello, World!\n",
);
// Now change the message only
case.addCompareOutput(
\\extern "c" fn write(usize, usize, usize) void;
\\extern "c" fn exit(usize) noreturn;
\\
\\export fn _start() noreturn {
\\ print();
\\
\\ exit();
\\ exit(0);
\\}
\\
\\fn print() void {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (4),
\\ [arg1] "{x0}" (1),
\\ [arg2] "{x1}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
\\ [arg3] "{x2}" (104)
\\ : "memory"
\\ );
\\ return;
\\}
\\
\\fn exit() noreturn {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (1),
\\ [arg1] "{x0}" (0)
\\ : "memory"
\\ );
\\ unreachable;
\\ const msg = @ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n");
\\ const len = 104;
\\ write(1, msg, len);
\\}
,
"What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
);
// Now we print it twice.
case.addCompareOutput(
\\extern "c" fn write(usize, usize, usize) void;
\\extern "c" fn exit(usize) noreturn;
\\
\\export fn _start() noreturn {
\\ print();
\\ print();
\\
\\ exit();
\\ exit(0);
\\}
\\
\\fn print() void {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (4),
\\ [arg1] "{x0}" (1),
\\ [arg2] "{x1}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
\\ [arg3] "{x2}" (104)
\\ : "memory"
\\ );
\\ return;
\\}
\\
\\fn exit() noreturn {
\\ asm volatile ("svc #0x80"
\\ :
\\ : [number] "{x16}" (1),
\\ [arg1] "{x0}" (0)
\\ : "memory"
\\ );
\\ unreachable;
\\ const msg = @ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n");
\\ const len = 104;
\\ write(1, msg, len);
\\}
,
\\What is up? This is a longer message that will force the data to be relocated in virtual address space.
@ -200,24 +163,6 @@ pub fn addCases(ctx: *TestContext) !void {
);
}
{
var case = ctx.exe("hello world linked to libc", macos_aarch64);
// TODO rewrite this test once we handle more int conversions and return args.
case.addCompareOutput(
\\extern "c" fn write(usize, usize, usize) void;
\\extern "c" fn exit(usize) noreturn;
\\
\\export fn _start() noreturn {
\\ write(1, @ptrToInt("Hello,"), 6);
\\ write(1, @ptrToInt(" World!\n,"), 8);
\\ exit(0);
\\}
,
"Hello, World!\n",
);
}
{
var case = ctx.exe("only libc exit", macos_aarch64);