aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjoachimschmidt557 <joachim.schmidt557@outlook.com>2021-12-31 12:21:59 +0100
committerjoachimschmidt557 <joachim.schmidt557@outlook.com>2022-01-01 11:16:34 +0100
commitf8163f7eaf45fa2b53a1f5ceac35088ad7d73e45 (patch)
treeb6ad28892098ec62135103f177e82ea9582c55de /src
parentb100e2ec2a06268623b119baf584e059440cb8f0 (diff)
downloadzig-f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45.tar.gz
zig-f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45.zip
stage2 ARM: implement airCall for function pointers
Diffstat (limited to 'src')
-rw-r--r--src/arch/arm/CodeGen.zig65
1 files changed, 37 insertions, 28 deletions
diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig
index 7765064634..a607ce54fd 100644
--- 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