authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-02-28 13:34:21+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-28 13:09:14-07:00
log90bce11f62aa2f246b9bce5bc49069a3faf7ec9a
tree1489691423543c9d3d5c65dcefa7c8cd6ae59354
parent2682b41da54e9b652dc570140d52f85418d6b89d

stage2: implement `@frameAddress`


11 files changed, 75 insertions(+), 7 deletions(-)

src/Air.zig+5
...@@ -580,6 +580,10 @@ pub const Inst = struct {...@@ -580,6 +580,10 @@ pub const Inst = struct {
580 /// Uses the `ty_pl` field.580 /// Uses the `ty_pl` field.
581 field_parent_ptr,581 field_parent_ptr,
582582
583 /// Implements @frameAddress builtin.
584 /// Uses the `ty` field.
585 frame_address,
586
583 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {587 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
584 return switch (op) {588 return switch (op) {
585 .lt => .cmp_lt,589 .lt => .cmp_lt,
...@@ -939,6 +943,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {...@@ -939,6 +943,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
939 .ptrtoint,943 .ptrtoint,
940 .slice_len,944 .slice_len,
941 .ret_addr,945 .ret_addr,
946 .frame_address,
942 => return Type.initTag(.usize),947 => return Type.initTag(.usize),
943948
944 .bool_to_int => return Type.initTag(.u1),949 .bool_to_int => return Type.initTag(.u1),
src/Liveness.zig+1
...@@ -317,6 +317,7 @@ fn analyzeInst(...@@ -317,6 +317,7 @@ fn analyzeInst(
317 .unreach,317 .unreach,
318 .fence,318 .fence,
319 .ret_addr,319 .ret_addr,
320 .frame_address,
320 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),321 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
321322
322 .not,323 .not,
src/Sema.zig+11-7
...@@ -8078,9 +8078,10 @@ fn analyzeTupleCat(...@@ -8078,9 +8078,10 @@ fn analyzeTupleCat(
8078 if (dest_fields == 0) {8078 if (dest_fields == 0) {
8079 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));8079 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
8080 }8080 }
8081 const final_len = try sema.usizeCast(block, rhs_src, dest_fields);
80818082
8082 const types = try sema.arena.alloc(Type, dest_fields);8083 const types = try sema.arena.alloc(Type, final_len);
8083 const values = try sema.arena.alloc(Value, dest_fields);8084 const values = try sema.arena.alloc(Value, final_len);
80848085
8085 const opt_runtime_src = rs: {8086 const opt_runtime_src = rs: {
8086 var runtime_src: ?LazySrcLoc = null;8087 var runtime_src: ?LazySrcLoc = null;
...@@ -8116,7 +8117,7 @@ fn analyzeTupleCat(...@@ -8116,7 +8117,7 @@ fn analyzeTupleCat(
81168117
8117 try sema.requireRuntimeBlock(block, runtime_src);8118 try sema.requireRuntimeBlock(block, runtime_src);
81188119
8119 const element_refs = try sema.arena.alloc(Air.Inst.Ref, dest_fields);8120 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
8120 for (lhs_tuple.types) |_, i| {8121 for (lhs_tuple.types) |_, i| {
8121 const operand_src = lhs_src; // TODO better source location8122 const operand_src = lhs_src; // TODO better source location
8122 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, @intCast(u32, i), lhs_ty);8123 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, @intCast(u32, i), lhs_ty);
...@@ -8261,9 +8262,10 @@ fn analyzeTupleMul(...@@ -8261,9 +8262,10 @@ fn analyzeTupleMul(
8261 if (final_len_u64 == 0) {8262 if (final_len_u64 == 0) {
8262 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));8263 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
8263 }8264 }
8265 const final_len = try sema.usizeCast(block, rhs_src, final_len_u64);
82648266
8265 const types = try sema.arena.alloc(Type, final_len_u64);8267 const types = try sema.arena.alloc(Type, final_len);
8266 const values = try sema.arena.alloc(Value, final_len_u64);8268 const values = try sema.arena.alloc(Value, final_len);
82678269
8268 const opt_runtime_src = rs: {8270 const opt_runtime_src = rs: {
8269 var runtime_src: ?LazySrcLoc = null;8271 var runtime_src: ?LazySrcLoc = null;
...@@ -8295,7 +8297,7 @@ fn analyzeTupleMul(...@@ -8295,7 +8297,7 @@ fn analyzeTupleMul(
82958297
8296 try sema.requireRuntimeBlock(block, runtime_src);8298 try sema.requireRuntimeBlock(block, runtime_src);
82978299
8298 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len_u64);8300 const element_refs = try sema.arena.alloc(Air.Inst.Ref, final_len);
8299 for (operand_tuple.types) |_, i| {8301 for (operand_tuple.types) |_, i| {
8300 const operand_src = lhs_src; // TODO better source location8302 const operand_src = lhs_src; // TODO better source location
8301 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(u32, i), operand_ty);8303 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(u32, i), operand_ty);
...@@ -11893,7 +11895,8 @@ fn zirFrameAddress(...@@ -11893,7 +11895,8 @@ fn zirFrameAddress(
11893 extended: Zir.Inst.Extended.InstData,11895 extended: Zir.Inst.Extended.InstData,
11894) CompileError!Air.Inst.Ref {11896) CompileError!Air.Inst.Ref {
11895 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };11897 const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
11896 return sema.fail(block, src, "TODO: Sema.zirFrameAddress", .{});11898 try sema.requireFunctionBlock(block, src);
11899 return block.addTy(.frame_address, Type.@"usize");
11897}11900}
1189811901
11899fn zirAlignOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {11902fn 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...@@ -19257,6 +19260,7 @@ fn pointerDeref(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value, ptr
19257/// Used to convert a u64 value to a usize value, emitting a compile error if the number19260/// Used to convert a u64 value to a usize value, emitting a compile error if the number
19258/// is too big to fit.19261/// is too big to fit.
19259fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError!usize {19262fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError!usize {
19263 if (@bitSizeOf(u64) <= @bitSizeOf(usize)) return int;
19260 return std.math.cast(usize, int) catch |err| switch (err) {19264 return std.math.cast(usize, int) catch |err| switch (err) {
19261 error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}),19265 error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}),
19262 };19266 };
src/arch/aarch64/CodeGen.zig+9
...@@ -670,6 +670,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -670,6 +670,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
670 .wrap_optional => try self.airWrapOptional(inst),670 .wrap_optional => try self.airWrapOptional(inst),
671 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),671 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
672 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),672 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
673
674 .frame_address => try self.airFrameAddress(inst),
673 // zig fmt: on675 // zig fmt: on
674 }676 }
675677
...@@ -1517,6 +1519,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1517,6 +1519,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1517 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1519 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1518}1520}
15191521
1522fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
1523 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1524 const extra = self.air.extraData(Air.StructField, ty_pl.payload).data;
1525 _ = extra;
1526 return self.fail("TODO implement codegen airFrameAddress", .{});
1527}
1528
1520fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {1529fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1521 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1530 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1522 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});1531 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
src/arch/arm/CodeGen.zig+9
...@@ -656,6 +656,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -656,6 +656,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
656 .wrap_optional => try self.airWrapOptional(inst),656 .wrap_optional => try self.airWrapOptional(inst),
657 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),657 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
658 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),658 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
659
660 .frame_address => try self.airFrameAddress(inst),
659 // zig fmt: on661 // zig fmt: on
660 }662 }
661663
...@@ -1272,6 +1274,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1272,6 +1274,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1272 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1274 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1273}1275}
12741276
1277fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
1278 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1279 const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data;
1280 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airFrameAddress", .{});
1281 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1282}
1283
1275fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {1284fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1276 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1285 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1277 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1286 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
src/arch/riscv64/CodeGen.zig+8
...@@ -641,6 +641,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -641,6 +641,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
641 .wrap_optional => try self.airWrapOptional(inst),641 .wrap_optional => try self.airWrapOptional(inst),
642 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),642 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
643 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),643 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
644
645 .frame_address => try self.airFrameAddress(inst),
644 // zig fmt: on646 // zig fmt: on
645 }647 }
646 if (std.debug.runtime_safety) {648 if (std.debug.runtime_safety) {
...@@ -1103,6 +1105,12 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1103,6 +1105,12 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1103 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1105 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1104}1106}
11051107
1108fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
1109 _ = self;
1110 _ = inst;
1111 return self.fail("TODO implement codegen airFrameAddress", .{});
1112}
1113
1106fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {1114fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1107 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1115 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1108 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});1116 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement slice_ptr for {}", .{self.target.cpu.arch});
src/arch/wasm/CodeGen.zig+1
...@@ -1726,6 +1726,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {...@@ -1726,6 +1726,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
1726 .error_name,1726 .error_name,
1727 .errunion_payload_ptr_set,1727 .errunion_payload_ptr_set,
1728 .field_parent_ptr,1728 .field_parent_ptr,
1729 .frame_address,
17291730
1730 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/102481731 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248
1731 // is implemented in the frontend before implementing them here in the wasm backend.1732 // is implemented in the frontend before implementing them here in the wasm backend.
src/arch/x86_64/CodeGen.zig+11
...@@ -753,6 +753,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {...@@ -753,6 +753,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
753 .wrap_optional => try self.airWrapOptional(inst),753 .wrap_optional => try self.airWrapOptional(inst),
754 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),754 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
755 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),755 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
756
757 .frame_address => try self.airFrameAddress(inst),
756 // zig fmt: on758 // zig fmt: on
757 }759 }
758760
...@@ -1865,6 +1867,15 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -1865,6 +1867,15 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
1865 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });1867 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1866}1868}
18671869
1870fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
1871 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1872 const result: MCValue = if (self.liveness.isUnused(inst))
1873 .dead
1874 else
1875 return self.fail("TODO implement airFrameAddress for {}", .{self.target.cpu.arch});
1876 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
1877}
1878
1868fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {1879fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
1869 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1880 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
1870 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {1881 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
src/codegen/c.zig+7
...@@ -1757,6 +1757,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO...@@ -1757,6 +1757,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
1757 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),1757 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
1758 .wrap_errunion_err => try airWrapErrUnionErr(f, inst),1758 .wrap_errunion_err => try airWrapErrUnionErr(f, inst),
1759 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),1759 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
1760
1761 .frame_address => try airFrameAddress(f, inst),
1760 // zig fmt: on1762 // zig fmt: on
1761 };1763 };
1762 switch (result_value) {1764 switch (result_value) {
...@@ -3198,6 +3200,11 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -3198,6 +3200,11 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
3198 return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{});3200 return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{});
3199}3201}
32003202
3203fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
3204 _ = inst;
3205 return f.fail("TODO: C backend: implement airFrameAddress", .{});
3206}
3207
3201fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {3208fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
3202 if (f.liveness.isUnused(inst))3209 if (f.liveness.isUnused(inst))
3203 return CValue.none;3210 return CValue.none;
src/codegen/llvm.zig+12
...@@ -2214,6 +2214,8 @@ pub const FuncGen = struct {...@@ -2214,6 +2214,8 @@ pub const FuncGen = struct {
2214 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),2214 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
2215 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),2215 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
22162216
2217 .frame_address => try self.airFrameAddress(inst),
2218
2217 .constant => unreachable,2219 .constant => unreachable,
2218 .const_ty => unreachable,2220 .const_ty => unreachable,
2219 .unreach => self.airUnreach(inst),2221 .unreach => self.airUnreach(inst),
...@@ -3339,6 +3341,16 @@ pub const FuncGen = struct {...@@ -3339,6 +3341,16 @@ pub const FuncGen = struct {
3339 return partial;3341 return partial;
3340 }3342 }
33413343
3344 fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3345 if (self.liveness.isUnused(inst)) return null;
3346
3347 const llvm_i32 = try self.dg.llvmType(Type.initTag(.i32));
3348 const llvm_fn = self.getIntrinsic("llvm.frameaddress", &.{llvm_i32});
3349 const ptr_val = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{llvm_i32.constNull()}, 1, .Fast, .Auto, "");
3350 const llvm_usize = try self.dg.llvmType(Type.usize);
3351 return self.builder.buildPtrToInt(ptr_val, llvm_usize, "");
3352 }
3353
3342 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {3354 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
3343 if (self.liveness.isUnused(inst)) return null;3355 if (self.liveness.isUnused(inst)) return null;
33443356
src/print_air.zig+1
...@@ -177,6 +177,7 @@ const Writer = struct {...@@ -177,6 +177,7 @@ const Writer = struct {
177 .alloc,177 .alloc,
178 .ret_ptr,178 .ret_ptr,
179 .arg,179 .arg,
180 .frame_address,
180 => try w.writeTy(s, inst),181 => try w.writeTy(s, inst),
181182
182 .not,183 .not,