aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Air.zig4
-rw-r--r--src/Liveness.zig1
-rw-r--r--src/Sema.zig6
-rw-r--r--src/arch/aarch64/CodeGen.zig5
-rw-r--r--src/arch/arm/CodeGen.zig5
-rw-r--r--src/arch/riscv64/CodeGen.zig5
-rw-r--r--src/arch/x86_64/CodeGen.zig5
-rw-r--r--src/codegen/c.zig5
-rw-r--r--src/codegen/llvm.zig10
-rw-r--r--src/print_air.zig1
10 files changed, 46 insertions, 1 deletions
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,