authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-12-31 12:21:59+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-01-01 11:16:34+01:00
logf8163f7eaf45fa2b53a1f5ceac35088ad7d73e45
treeb6ad28892098ec62135103f177e82ea9582c55de
parentb100e2ec2a06268623b119baf584e059440cb8f0
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: implement airCall for function pointers


2 files changed, 85 insertions(+), 28 deletions(-)

src/arch/arm/CodeGen.zig+37-28
...@@ -2238,10 +2238,16 @@ fn airFence(self: *Self) !void {...@@ -2238,10 +2238,16 @@ fn airFence(self: *Self) !void {
22382238
2239fn airCall(self: *Self, inst: Air.Inst.Index) !void {2239fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2240 const pl_op = self.air.instructions.items(.data)[inst].pl_op;2240 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
2241 const fn_ty = self.air.typeOf(pl_op.operand);
2242 const callee = pl_op.operand;2241 const callee = pl_op.operand;
2243 const extra = self.air.extraData(Air.Call, pl_op.payload);2242 const extra = self.air.extraData(Air.Call, pl_op.payload);
2244 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);2243 const args = @bitCast([]const Air.Inst.Ref, self.air.extra[extra.end..][0..extra.data.args_len]);
2244 const ty = self.air.typeOf(callee);
2245
2246 const fn_ty = switch (ty.zigTypeTag()) {
2247 .Fn => ty,
2248 .Pointer => ty.childType(),
2249 else => unreachable,
2250 };
22452251
2246 var info = try self.resolveCallingConventionValues(fn_ty);2252 var info = try self.resolveCallingConventionValues(fn_ty);
2247 defer info.deinit(self);2253 defer info.deinit(self);
...@@ -2310,39 +2316,42 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {...@@ -2310,39 +2316,42 @@ fn airCall(self: *Self, inst: Air.Inst.Index) !void {
2310 unreachable;2316 unreachable;
23112317
2312 try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr });2318 try self.genSetReg(Type.initTag(.usize), .lr, .{ .memory = got_addr });
2313
2314 // TODO: add Instruction.supportedOn
2315 // function for ARM
2316 if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) {
2317 _ = try self.addInst(.{
2318 .tag = .blx,
2319 .cond = .al,
2320 .data = .{ .reg = .lr },
2321 });
2322 } else {
2323 return self.fail("TODO fix blx emulatio for ARM <v5", .{});
2324 // _ = try self.addInst(.{
2325 // .tag = .mov,
2326 // .cond = .al,
2327 // .data = .{ .rr_op = .{
2328 // .rd = .lr,
2329 // .rn = .r0,
2330 // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none),
2331 // } },
2332 // });
2333 // _ = try self.addInst(.{
2334 // .tag = .bx,
2335 // .cond = .al,
2336 // .data = .{ .reg = .lr },
2337 // });
2338 }
2339 } else if (func_value.castTag(.extern_fn)) |_| {2319 } else if (func_value.castTag(.extern_fn)) |_| {
2340 return self.fail("TODO implement calling extern functions", .{});2320 return self.fail("TODO implement calling extern functions", .{});
2341 } else {2321 } else {
2342 return self.fail("TODO implement calling bitcasted functions", .{});2322 return self.fail("TODO implement calling bitcasted functions", .{});
2343 }2323 }
2344 } else {2324 } else {
2345 return self.fail("TODO implement calling runtime known function pointer", .{});2325 assert(ty.zigTypeTag() == .Pointer);
2326 const mcv = try self.resolveInst(callee);
2327
2328 try self.genSetReg(Type.initTag(.usize), .lr, mcv);
2329 }
2330
2331 // TODO: add Instruction.supportedOn
2332 // function for ARM
2333 if (Target.arm.featureSetHas(self.target.cpu.features, .has_v5t)) {
2334 _ = try self.addInst(.{
2335 .tag = .blx,
2336 .cond = .al,
2337 .data = .{ .reg = .lr },
2338 });
2339 } else {
2340 return self.fail("TODO fix blx emulation for ARM <v5", .{});
2341 // _ = try self.addInst(.{
2342 // .tag = .mov,
2343 // .cond = .al,
2344 // .data = .{ .rr_op = .{
2345 // .rd = .lr,
2346 // .rn = .r0,
2347 // .op = Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none),
2348 // } },
2349 // });
2350 // _ = try self.addInst(.{
2351 // .tag = .bx,
2352 // .cond = .al,
2353 // .data = .{ .reg = .lr },
2354 // });
2346 }2355 }
2347 } else if (self.bin_file.cast(link.File.MachO)) |_| {2356 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2348 unreachable; // unsupported architecture for MachO2357 unreachable; // unsupported architecture for MachO
test/stage2/arm.zig+48
...@@ -704,4 +704,52 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -704,4 +704,52 @@ pub fn addCases(ctx: *TestContext) !void {
704 "",704 "",
705 );705 );
706 }706 }
707
708 {
709 var case = ctx.exe("function pointers", linux_arm);
710 case.addCompareOutput(
711 \\const PrintFn = fn () void;
712 \\
713 \\pub fn main() void {
714 \\ var printFn: PrintFn = stopSayingThat;
715 \\ var i: u32 = 0;
716 \\ while (i < 4) : (i += 1) printFn();
717 \\
718 \\ printFn = moveEveryZig;
719 \\ printFn();
720 \\}
721 \\
722 \\fn stopSayingThat() void {
723 \\ asm volatile ("svc #0"
724 \\ :
725 \\ : [number] "{r7}" (4),
726 \\ [arg1] "{r0}" (1),
727 \\ [arg2] "{r1}" (@ptrToInt("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n")),
728 \\ [arg3] "{r2}" ("Hello, my name is Inigo Montoya; you killed my father, prepare to die.\n".len),
729 \\ : "memory"
730 \\ );
731 \\ return;
732 \\}
733 \\
734 \\fn moveEveryZig() void {
735 \\ asm volatile ("svc #0"
736 \\ :
737 \\ : [number] "{r7}" (4),
738 \\ [arg1] "{r0}" (1),
739 \\ [arg2] "{r1}" (@ptrToInt("All your codebase are belong to us\n")),
740 \\ [arg3] "{r2}" ("All your codebase are belong to us\n".len),
741 \\ : "memory"
742 \\ );
743 \\ return;
744 \\}
745 ,
746 \\Hello, my name is Inigo Montoya; you killed my father, prepare to die.
747 \\Hello, my name is Inigo Montoya; you killed my father, prepare to die.
748 \\Hello, my name is Inigo Montoya; you killed my father, prepare to die.
749 \\Hello, my name is Inigo Montoya; you killed my father, prepare to die.
750 \\All your codebase are belong to us
751 \\
752 ,
753 );
754 }
707}755}