From ddd2ef822f99979d3ea61583a91ab236942e6367 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 18 Dec 2021 06:11:46 +0100 Subject: stage2: @returnAddress() --- src/Air.zig | 4 ++++ src/Liveness.zig | 1 + src/Sema.zig | 6 +++++- src/arch/aarch64/CodeGen.zig | 5 +++++ src/arch/arm/CodeGen.zig | 5 +++++ src/arch/riscv64/CodeGen.zig | 5 +++++ src/arch/x86_64/CodeGen.zig | 5 +++++ src/codegen/c.zig | 5 +++++ src/codegen/llvm.zig | 10 ++++++++++ src/print_air.zig | 1 + 10 files changed, 46 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Air.zig b/src/Air.zig index 72e281d03e..9e4a61b9a2 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -195,6 +195,9 @@ pub const Inst = struct { /// Lowers to a hardware trap instruction, or the next best thing. /// Result type is always void. breakpoint, + /// Yields the return address of the current function. + /// Uses the `no_op` field. + ret_addr, /// Function call. /// Result type is the return type of the function being called. /// Uses the `pl_op` field with the `Call` payload. operand is the callee. @@ -785,6 +788,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type { .ptrtoint, .slice_len, + .ret_addr, => return Type.initTag(.usize), .bool_to_int => return Type.initTag(.u1), diff --git a/src/Liveness.zig b/src/Liveness.zig index a7128e2cc2..160a2e97d3 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -281,6 +281,7 @@ fn analyzeInst( .dbg_stmt, .unreach, .fence, + .ret_addr, => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }), .not, diff --git a/src/Sema.zig b/src/Sema.zig index 9b9371c856..03ee58dc06 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8739,8 +8739,12 @@ fn zirRetAddr( block: *Block, extended: Zir.Inst.Extended.InstData, ) CompileError!Air.Inst.Ref { + const tracy = trace(@src()); + defer tracy.end(); + const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) }; - return sema.fail(block, src, "TODO: implement Sema.zirRetAddr", .{}); + try sema.requireRuntimeBlock(block, src); + return try block.addNoOp(.ret_addr); } fn zirBuiltinSrc( diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index fda673631d..1c6d54485b 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -547,6 +547,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .block => try self.airBlock(inst), .br => try self.airBr(inst), .breakpoint => try self.airBreakpoint(), + .ret_addr => try self.airRetAddr(), .fence => try self.airFence(), .call => try self.airCall(inst), .cond_br => try self.airCondBr(inst), @@ -1416,6 +1417,10 @@ fn airBreakpoint(self: *Self) !void { return self.finishAirBookkeeping(); } +fn airRetAddr(self: *Self) !void { + return self.fail("TODO implement airRetAddr for {}", .{self.target.cpu.arch}); +} + fn airFence(self: *Self) !void { return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); //return self.finishAirBookkeeping(); diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index bcc1b927e7..0039d78434 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -545,6 +545,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .block => try self.airBlock(inst), .br => try self.airBr(inst), .breakpoint => try self.airBreakpoint(), + .ret_addr => try self.airRetAddr(), .fence => try self.airFence(), .call => try self.airCall(inst), .cond_br => try self.airCondBr(inst), @@ -1850,6 +1851,10 @@ fn airBreakpoint(self: *Self) !void { return self.finishAirBookkeeping(); } +fn airRetAddr(self: *Self) !void { + return self.fail("TODO implement airRetAddr for {}", .{self.target.cpu.arch}); +} + fn airFence(self: *Self) !void { return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); //return self.finishAirBookkeeping(); diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 1d67ad0abf..51703681e9 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -526,6 +526,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .block => try self.airBlock(inst), .br => try self.airBr(inst), .breakpoint => try self.airBreakpoint(), + .ret_addr => try self.airRetAddr(), .fence => try self.airFence(), .call => try self.airCall(inst), .cond_br => try self.airCondBr(inst), @@ -1354,6 +1355,10 @@ fn airBreakpoint(self: *Self) !void { return self.finishAirBookkeeping(); } +fn airRetAddr(self: *Self) !void { + return self.fail("TODO implement airRetAddr for {}", .{self.target.cpu.arch}); +} + fn airFence(self: *Self) !void { return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); //return self.finishAirBookkeeping(); diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 8fadcdd5f5..3b40293527 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -579,6 +579,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { .block => try self.airBlock(inst), .br => try self.airBr(inst), .breakpoint => try self.airBreakpoint(), + .ret_addr => try self.airRetAddr(), .fence => try self.airFence(), .call => try self.airCall(inst), .cond_br => try self.airCondBr(inst), @@ -1839,6 +1840,10 @@ fn airBreakpoint(self: *Self) !void { return self.finishAirBookkeeping(); } +fn airRetAddr(self: *Self) !void { + return self.fail("TODO implement airRetAddr for {}", .{self.target.cpu.arch}); +} + fn airFence(self: *Self) !void { return self.fail("TODO implement fence() for {}", .{self.target.cpu.arch}); //return self.finishAirBookkeeping(); diff --git a/src/codegen/c.zig b/src/codegen/c.zig index b086d15b48..070aa0a238 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1125,6 +1125,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .arg => airArg(f), .breakpoint => try airBreakpoint(f), + .ret_addr => try airRetAddr(f), .unreach => try airUnreach(f), .fence => try airFence(f, inst), @@ -2191,6 +2192,10 @@ fn airBreakpoint(f: *Function) !CValue { return CValue.none; } +fn airRetAddr(f: *Function) !CValue { + return f.fail("TODO implement codegen for airRetAddr", .{}); +} + fn airFence(f: *Function, inst: Air.Inst.Index) !CValue { const atomic_order = f.air.instructions.items(.data)[inst].fence; const writer = f.object.writer(); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index d12dad2403..0a2b12dd1e 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1747,6 +1747,7 @@ pub const FuncGen = struct { .br => try self.airBr(inst), .switch_br => try self.airSwitchBr(inst), .breakpoint => try self.airBreakpoint(inst), + .ret_addr => try self.airRetAddr(inst), .call => try self.airCall(inst), .cond_br => try self.airCondBr(inst), .intcast => try self.airIntCast(inst), @@ -3550,6 +3551,15 @@ pub const FuncGen = struct { return null; } + fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + _ = inst; + const i32_zero = self.context.intType(32).constNull(); + const usize_llvm_ty = try self.dg.llvmType(Type.usize); + const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); + const ptr_val = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{i32_zero}, 1, .Fast, .Auto, ""); + return self.builder.buildPtrToInt(ptr_val, usize_llvm_ty, ""); + } + fn airFence(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const atomic_order = self.air.instructions.items(.data)[inst].fence; const llvm_memory_order = toLlvmAtomicOrdering(atomic_order); diff --git a/src/print_air.zig b/src/print_air.zig index e11826c874..17af7ebf62 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -159,6 +159,7 @@ const Writer = struct { .breakpoint, .unreach, + .ret_addr, => try w.writeNoOp(s, inst), .const_ty, -- cgit v1.2.3