motiejus/zig

fork of https://codeberg.org/ziglang/zig
git clone https://git.jakstys.lt/motiejus/zig.git
Log | Tree | Refs | README | LICENSE

commit f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45 (tree)
parent b100e2ec2a06268623b119baf584e059440cb8f0
Author: joachimschmidt557 <joachim.schmidt557@outlook.com>
Date:   Fri, 31 Dec 2021 12:21:59 +0100

stage2 ARM: implement airCall for function pointers

Diffstat:
Msrc/arch/arm/CodeGen.zig | 65+++++++++++++++++++++++++++++++++++++----------------------------
Mtest/stage2/arm.zig | 48++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 85 insertions(+), 28 deletions(-)

diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig @@ -2238,10 +2238,16 @@ fn airFence(self: *Self) !void { fn airCall(self: *Self, inst: Air.Inst.Index) !void { const pl_op = self.air.instructions.items(.data)[inst].pl_op; - const fn_ty = self.air.typeOf(pl_op.operand); const callee = pl_op.operand; const extra = self.air.extraData(Air.Call, pl_op.payload); const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]); + const ty = self.air.typeOf(callee); + + const fn_ty = switch (ty.zigTypeTag()) { + .Fn => ty, + .Pointer => ty.childType(), + else => unreachable, + }; var info = try self.resolveCallingConventionValues(fn_ty); defer info.deinit(self); @@ -2310,39 +2316,42 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void { unreachable; try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr }); - - // TODO: add Instruction.supportedOn - // function for ARM - if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { - _ = try self.addInst(.{ - .tag = .blx, - .cond = .al, - .data = .{ .reg = .lr }, - }); - } else { - return self.fail("TODO fix blx emulatio for ARM <v5", .{}); - // _ = try self.addInst(.{ - // .tag = .mov, - // .cond = .al, - // .data = .{ .rr_op = .{ - // .rd = .lr, - // .rn = .r0, - // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none), - // } }, - // }); - // _ = try self.addInst(.{ - // .tag = .bx, - // .cond = .al, - // .data = .{ .reg = .lr }, - // }); - } } else if (func_value.castTag(.extern_fn)) |_| { return self.fail("TODO implement calling extern functions", .{}); } else { return self.fail("TODO implement calling bitcasted functions", .{}); } } else { - return self.fail("TODO implement calling runtime known function pointer", .{}); + assert(ty.zigTypeTag() == .Pointer); + const mcv = try self.resolveInst(callee); + + try self.genSetReg(Type.initTag(.usize), .lr, mcv); + } + + // TODO: add Instruction.supportedOn + // function for ARM + if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) { + _ = try self.addInst(.{ + .tag = .blx, + .cond = .al, + .data = .{ .reg = .lr }, + }); + } else { + return self.fail("TODO fix blx emulation for ARM <v5", .{}); + // _ = try self.addInst(.{ + // .tag = .mov, + // .cond = .al, + // .data = .{ .rr_op = .{ + // .rd = .lr, + // .rn = .r0, + // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none), + // } }, + // }); + // _ = try self.addInst(.{ + // .tag = .bx, + // .cond = .al, + // .data = .{ .reg = .lr }, + // }); } } else if (self.bin_file.cast(link.File.MachO)) |_| { unreachable; // unsupported architecture for MachO diff --git a/test/stage2/arm.zig b/test/stage2/arm.zig @@ -704,4 +704,52 @@ pub fn addCases(ctx: *TestContext) !void { "", ); } + + { + var case = ctx.exe("function pointers", linux_arm); + case.addCompareOutput( + \\const PrintFn = fn () void; + \\ + \\pub fn main() void { + \\ var printFn: PrintFn = stopSayingThat; + \\ var i: u32 = 0; + \\ while (i < 4) : (i += 1) printFn(); + \\ + \\ printFn = moveEveryZig; + \\ printFn(); + \\} + \\ + \\fn stopSayingThat() void { + \\ asm volatile ("svc #0" + \\ : + \\ : [number] "{r7}" (4), + \\ [arg1] "{r0}" (1), + \\ [arg2] "{r1}" (@ptrToInt("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n")), + \\ [arg3] "{r2}" ("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n".len), + \\ : "memory" + \\ ); + \\ return; + \\} + \\ + \\fn moveEveryZig() void { + \\ asm volatile ("svc #0" + \\ : + \\ : [number] "{r7}" (4), + \\ [arg1] "{r0}" (1), + \\ [arg2] "{r1}" (@ptrToInt("All your codebase are belong to us\n")), + \\ [arg3] "{r2}" ("All your codebase are belong to us\n".len), + \\ : "memory" + \\ ); + \\ return; + \\} + , + \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. + \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. + \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. + \\Hello, my name is Inigo Montoya; you killed my father, prepare to die. + \\All your codebase are belong to us + \\ + , + ); + } }