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 {
580580 /// Uses the `ty_pl` field.
581581 field_parent_ptr,
582582
583 /// Implements @frameAddress builtin.
584 /// Uses the `ty` field.
585 frame_address,
586
583587 pub fn fromCmpOp(op: std.math.CompareOperator) Tag {
584588 return switch (op) {
585589 .lt => .cmp_lt,
......@@ -939,6 +943,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
939943 .ptrtoint,
940944 .slice_len,
941945 .ret_addr,
946 .frame_address,
942947 => return Type.initTag(.usize),
943948
944949 .bool_to_int => return Type.initTag(.u1),
src/Liveness.zig+1
......@@ -317,6 +317,7 @@ fn analyzeInst(
317317 .unreach,
318318 .fence,
319319 .ret_addr,
320 .frame_address,
320321 => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }),
321322
322323 .not,
src/Sema.zig+11-7
......@@ -8078,9 +8078,10 @@ fn analyzeTupleCat(
80788078 if (dest_fields == 0) {
80798079 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
80808080 }
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 values = try sema.arena.alloc(Value, dest_fields);
8083 const types = try sema.arena.alloc(Type, final_len);
8084 const values = try sema.arena.alloc(Value, final_len);
80848085
80858086 const opt_runtime_src = rs: {
80868087 var runtime_src: ?LazySrcLoc = null;
......@@ -8116,7 +8117,7 @@ fn analyzeTupleCat(
81168117
81178118 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);
81208121 for (lhs_tuple.types) |_, i| {
81218122 const operand_src = lhs_src; // TODO better source location
81228123 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, lhs, @intCast(u32, i), lhs_ty);
......@@ -8261,9 +8262,10 @@ fn analyzeTupleMul(
82618262 if (final_len_u64 == 0) {
82628263 return sema.addConstant(Type.initTag(.empty_struct_literal), Value.initTag(.empty_struct_value));
82638264 }
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);
8266 const values = try sema.arena.alloc(Value, final_len_u64);
8267 const types = try sema.arena.alloc(Type, final_len);
8268 const values = try sema.arena.alloc(Value, final_len);
82678269
82688270 const opt_runtime_src = rs: {
82698271 var runtime_src: ?LazySrcLoc = null;
......@@ -8295,7 +8297,7 @@ fn analyzeTupleMul(
82958297
82968298 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);
82998301 for (operand_tuple.types) |_, i| {
83008302 const operand_src = lhs_src; // TODO better source location
83018303 element_refs[i] = try sema.tupleFieldValByIndex(block, operand_src, operand, @intCast(u32, i), operand_ty);
......@@ -11893,7 +11895,8 @@ fn zirFrameAddress(
1189311895 extended: Zir.Inst.Extended.InstData,
1189411896) CompileError!Air.Inst.Ref {
1189511897 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");
1189711900}
1189811901
1189911902fn 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
1925719260/// Used to convert a u64 value to a usize value, emitting a compile error if the number
1925819261/// is too big to fit.
1925919262fn usizeCast(sema: *Sema, block: *Block, src: LazySrcLoc, int: u64) CompileError!usize {
19263 if (@bitSizeOf(u64) <= @bitSizeOf(usize)) return int;
1926019264 return std.math.cast(usize, int) catch |err| switch (err) {
1926119265 error.Overflow => return sema.fail(block, src, "expression produces integer value {d} which is too big for this compiler implementation to handle", .{int}),
1926219266 };
src/arch/aarch64/CodeGen.zig+9
......@@ -670,6 +670,8 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
670670 .wrap_optional => try self.airWrapOptional(inst),
671671 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
672672 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
673
674 .frame_address => try self.airFrameAddress(inst),
673675 // zig fmt: on
674676 }
675677
......@@ -1517,6 +1519,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
15171519 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
15181520}
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
15201529fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
15211530 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
15221531 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 {
656656 .wrap_optional => try self.airWrapOptional(inst),
657657 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
658658 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
659
660 .frame_address => try self.airFrameAddress(inst),
659661 // zig fmt: on
660662 }
661663
......@@ -1272,6 +1274,13 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
12721274 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
12731275}
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
12751284fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
12761285 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
12771286 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 {
641641 .wrap_optional => try self.airWrapOptional(inst),
642642 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
643643 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
644
645 .frame_address => try self.airFrameAddress(inst),
644646 // zig fmt: on
645647 }
646648 if (std.debug.runtime_safety) {
......@@ -1103,6 +1105,12 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
11031105 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
11041106}
11051107
1108fn airFrameAddress(self: *Self, inst: Air.Inst.Index) !void {
1109 _ = self;
1110 _ = inst;
1111 return self.fail("TODO implement codegen airFrameAddress", .{});
1112}
1113
11061114fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
11071115 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
11081116 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 {
17261726 .error_name,
17271727 .errunion_payload_ptr_set,
17281728 .field_parent_ptr,
1729 .frame_address,
17291730
17301731 // For these 4, probably best to wait until https://github.com/ziglang/zig/issues/10248
17311732 // 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 {
753753 .wrap_optional => try self.airWrapOptional(inst),
754754 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
755755 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
756
757 .frame_address => try self.airFrameAddress(inst),
756758 // zig fmt: on
757759 }
758760
......@@ -1865,6 +1867,15 @@ fn airWrapErrUnionErr(self: *Self, inst: Air.Inst.Index) !void {
18651867 return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
18661868}
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
18681879fn airSlicePtr(self: *Self, inst: Air.Inst.Index) !void {
18691880 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
18701881 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
17571757 .wrap_errunion_payload => try airWrapErrUnionPay(f, inst),
17581758 .wrap_errunion_err => try airWrapErrUnionErr(f, inst),
17591759 .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst),
1760
1761 .frame_address => try airFrameAddress(f, inst),
17601762 // zig fmt: on
17611763 };
17621764 switch (result_value) {
......@@ -3198,6 +3200,11 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue {
31983200 return f.fail("TODO: C backend: implement airErrUnionPayloadPtrSet", .{});
31993201}
32003202
3203fn airFrameAddress(f: *Function, inst: Air.Inst.Index) !CValue {
3204 _ = inst;
3205 return f.fail("TODO: C backend: implement airFrameAddress", .{});
3206}
3207
32013208fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue {
32023209 if (f.liveness.isUnused(inst))
32033210 return CValue.none;
src/codegen/llvm.zig+12
......@@ -2214,6 +2214,8 @@ pub const FuncGen = struct {
22142214 .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst),
22152215 .wrap_errunion_err => try self.airWrapErrUnionErr(inst),
22162216
2217 .frame_address => try self.airFrameAddress(inst),
2218
22172219 .constant => unreachable,
22182220 .const_ty => unreachable,
22192221 .unreach => self.airUnreach(inst),
......@@ -3339,6 +3341,16 @@ pub const FuncGen = struct {
33393341 return partial;
33403342 }
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
33423354 fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
33433355 if (self.liveness.isUnused(inst)) return null;
33443356
src/print_air.zig+1
......@@ -177,6 +177,7 @@ const Writer = struct {
177177 .alloc,
178178 .ret_ptr,
179179 .arg,
180 .frame_address,
180181 => try w.writeTy(s, inst),
181182
182183 .not,