mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
stage2: implement @frameAddress
This commit is contained in:
parent
2682b41da5
commit
90bce11f62
@ -580,6 +580,10 @@ pub const Inst = struct {
|
||||
/// Uses the `ty_pl` field.
|
||||
field_parent_ptr,
|
||||
|
||||
/// Implements @frameAddress builtin.
|
||||
/// Uses the `ty` field.
|
||||
frame_address,
|
||||
|
||||
pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
|
||||
return switch (op) {
|
||||
.lt => .cmp_lt,
|
||||
@ -939,6 +943,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
|
||||
.ptrtoint,
|
||||
.slice_len,
|
||||
.ret_addr,
|
||||
.frame_address,
|
||||
=> return Type.initTag(.usize),
|
||||
|
||||
.bool_to_int => return Type.initTag(.u1),
|
||||
|
||||
@ -317,6 +317,7 @@ fn analyzeInst(
|
||||
.unreach,
|
||||
.fence,
|
||||
.ret_addr,
|
||||
.frame_address,
|
||||
=> return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
|
||||
|
||||
.not,
|
||||
|
||||
18
src/Sema.zig
18
src/Sema.zig
@ -8078,9 +8078,10 @@ fn analyzeTupleCat(
|
||||
if (dest_fields == 0) {
|
||||
return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
|
||||
}
|
||||
const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
|
||||
|
||||
const types = try sema.arena.alloc(Type, dest_fields);
|
||||
const values = try sema.arena.alloc(Value, dest_fields);
|
||||
const types = try sema.arena.alloc(Type, final_len);
|
||||
const values = try sema.arena.alloc(Value, final_len);
|
||||
|
||||
const opt_runtime_src = rs: {
|
||||
var runtime_src: ?LazySrcLoc = null;
|
||||
@ -8116,7 +8117,7 @@ fn analyzeTupleCat(
|
||||
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
|
||||
const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_fields);
|
||||
const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
|
||||
for (lhs_tuple.types) |_, i| {
|
||||
const operand_src = lhs_src; // TODO better source location
|
||||
element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, @intCast(u32, i), lhs_ty);
|
||||
@ -8261,9 +8262,10 @@ fn analyzeTupleMul(
|
||||
if (final_len_u64 == 0) {
|
||||
return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
|
||||
}
|
||||
const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);
|
||||
|
||||
const types = try sema.arena.alloc(Type, final_len_u64);
|
||||
const values = try sema.arena.alloc(Value, final_len_u64);
|
||||
const types = try sema.arena.alloc(Type, final_len);
|
||||
const values = try sema.arena.alloc(Value, final_len);
|
||||
|
||||
const opt_runtime_src = rs: {
|
||||
var runtime_src: ?LazySrcLoc = null;
|
||||
@ -8295,7 +8297,7 @@ fn analyzeTupleMul(
|
||||
|
||||
try sema.requireRuntimeBlock(block, runtime_src);
|
||||
|
||||
const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len_u64);
|
||||
const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
|
||||
for (operand_tuple.types) |_, i| {
|
||||
const operand_src = lhs_src; // TODO better source location
|
||||
element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(u32, i), operand_ty);
|
||||
@ -11893,7 +11895,8 @@ fn zirFrameAddress(
|
||||
extended: Zir.Inst.Extended.InstData,
|
||||
) CompileError!Air.Inst.Ref {
|
||||
const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
|
||||
return sema.fail(block, src, "TODO: Sema.zirFrameAddress", .{});
|
||||
try sema.requireFunctionBlock(block, src);
|
||||
return block.addTy(.frame_address, Type.@"usize");
|
||||
}
|
||||
|
||||
fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
|
||||
@ -19257,6 +19260,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
|
||||
/// Used to convert a u64 value to a usize value, emitting a compile error if the number
|
||||
/// is too big to fit.
|
||||
fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError!usize {
|
||||
if (@bitSizeOf(u64) <= @bitSizeOf(usize)) return int;
|
||||
return std.math.cast(usize, int) catch |err| switch (err) {
|
||||
error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}),
|
||||
};
|
||||
|
||||
@ -670,6 +670,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.wrap_optional => try self.airWrapOptional(inst),
|
||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
|
||||
.frame_address => try self.airFrameAddress(inst),
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
@ -1517,6 +1519,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||
const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
|
||||
_ = extra;
|
||||
return self.fail("TODO implement codegen airFrameAddress", .{});
|
||||
}
|
||||
|
||||
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
|
||||
|
||||
@ -656,6 +656,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.wrap_optional => try self.airWrapOptional(inst),
|
||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
|
||||
.frame_address => try self.airFrameAddress(inst),
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
@ -1272,6 +1274,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
|
||||
const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airFrameAddress", .{});
|
||||
return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
|
||||
}
|
||||
|
||||
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
|
||||
@ -641,6 +641,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.wrap_optional => try self.airWrapOptional(inst),
|
||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
|
||||
.frame_address => try self.airFrameAddress(inst),
|
||||
// zig fmt: on
|
||||
}
|
||||
if (std.debug.runtime_safety) {
|
||||
@ -1103,6 +1105,12 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
|
||||
_ = self;
|
||||
_ = inst;
|
||||
return self.fail("TODO implement codegen airFrameAddress", .{});
|
||||
}
|
||||
|
||||
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
|
||||
|
||||
@ -1726,6 +1726,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
|
||||
.error_name,
|
||||
.errunion_payload_ptr_set,
|
||||
.field_parent_ptr,
|
||||
.frame_address,
|
||||
|
||||
// For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248
|
||||
// is implemented in the frontend before implementing them here in the wasm backend.
|
||||
|
||||
@ -753,6 +753,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.wrap_optional => try self.airWrapOptional(inst),
|
||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
|
||||
.frame_address => try self.airFrameAddress(inst),
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
@ -1865,6 +1867,15 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst))
|
||||
.dead
|
||||
else
|
||||
return self.fail("TODO implement airFrameAddress for {}", .{self.target.cpu.arch});
|
||||
return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
|
||||
}
|
||||
|
||||
fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_op = self.air.instructions.items(.data)[inst].ty_op;
|
||||
const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
|
||||
|
||||
@ -1757,6 +1757,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
|
||||
.wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
|
||||
.wrap_errunion_err => try airWrapErrUnionErr(f, inst),
|
||||
.errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
|
||||
|
||||
.frame_address => try airFrameAddress(f, inst),
|
||||
// zig fmt: on
|
||||
};
|
||||
switch (result_value) {
|
||||
@ -3198,6 +3200,11 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{});
|
||||
}
|
||||
|
||||
fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
_ = inst;
|
||||
return f.fail("TODO: C backend: implement airFrameAddress", .{});
|
||||
}
|
||||
|
||||
fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
if (f.liveness.isUnused(inst))
|
||||
return CValue.none;
|
||||
|
||||
@ -2214,6 +2214,8 @@ pub const FuncGen = struct {
|
||||
.wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
|
||||
.wrap_errunion_err => try self.airWrapErrUnionErr(inst),
|
||||
|
||||
.frame_address => try self.airFrameAddress(inst),
|
||||
|
||||
.constant => unreachable,
|
||||
.const_ty => unreachable,
|
||||
.unreach => self.airUnreach(inst),
|
||||
@ -3339,6 +3341,16 @@ pub const FuncGen = struct {
|
||||
return partial;
|
||||
}
|
||||
|
||||
fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
const llvm_i32 = try self.dg.llvmType(Type.initTag(.i32));
|
||||
const llvm_fn = self.getIntrinsic("llvm.frameaddress", &.{llvm_i32});
|
||||
const ptr_val = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{llvm_i32.constNull()}, 1, .Fast, .Auto, "");
|
||||
const llvm_usize = try self.dg.llvmType(Type.usize);
|
||||
return self.builder.buildPtrToInt(ptr_val, llvm_usize, "");
|
||||
}
|
||||
|
||||
fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
|
||||
if (self.liveness.isUnused(inst)) return null;
|
||||
|
||||
|
||||
@ -177,6 +177,7 @@ const Writer = struct {
|
||||
.alloc,
|
||||
.ret_ptr,
|
||||
.arg,
|
||||
.frame_address,
|
||||
=> try w.writeTy(s, inst),
|
||||
|
||||
.not,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user