mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 23:53:15 +00:00
stage2 aarch64: add basic function pro/epilogue
Fix typo in `nop` implementation. Simplify `aarch64` macOS tests.
This commit is contained in:
parent
e292f33de7
commit
b25cf7db02
@ -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}),
|
||||
}
|
||||
|
||||
@ -814,7 +814,7 @@ pub const Instruction = union(enum) {
|
||||
// Nop
|
||||
|
||||
pub fn nop() Instruction {
|
||||
return Instruction{ .NoOperation = {} };
|
||||
return Instruction{ .NoOperation = .{} };
|
||||
}
|
||||
|
||||
// Logical (shifted register)
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user