diff options
| author | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2021-12-31 12:21:59 +0100 |
|---|---|---|
| committer | joachimschmidt557 <joachim.schmidt557@outlook.com> | 2022-01-01 11:16:34 +0100 |
| commit | f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45 (patch) | |
| tree | b6ad28892098ec62135103f177e82ea9582c55de /src | |
| parent | b100e2ec2a06268623b119baf584e059440cb8f0 (diff) | |
| download | zig-f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45.tar.gz zig-f8163f7eaf45fa2b53a1f5ceac35088ad7d73e45.zip | |
stage2 ARM: implement airCall for function pointers
Diffstat (limited to 'src')
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 65 |
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 |
