diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-02-28 13:34:21 +0200 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-02-28 13:09:14 -0700 |
| commit | 90bce11f62aa2f246b9bce5bc49069a3faf7ec9a (patch) | |
| tree | 1489691423543c9d3d5c65dcefa7c8cd6ae59354 | |
| parent | 2682b41da54e9b652dc570140d52f85418d6b89d (diff) | |
| download | zig-90bce11f62aa2f246b9bce5bc49069a3faf7ec9a.tar.gz zig-90bce11f62aa2f246b9bce5bc49069a3faf7ec9a.zip | |
stage2: implement `@frameAddress`
| -rw-r--r-- | src/Air.zig | 5 | ||||
| -rw-r--r-- | src/Liveness.zig | 1 | ||||
| -rw-r--r-- | src/Sema.zig | 18 | ||||
| -rw-r--r-- | src/arch/aarch64/CodeGen.zig | 9 | ||||
| -rw-r--r-- | src/arch/arm/CodeGen.zig | 9 | ||||
| -rw-r--r-- | src/arch/riscv64/CodeGen.zig | 8 | ||||
| -rw-r--r-- | src/arch/wasm/CodeGen.zig | 1 | ||||
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 11 | ||||
| -rw-r--r-- | src/codegen/c.zig | 7 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 12 | ||||
| -rw-r--r-- | src/print_air.zig | 1 |
11 files changed, 75 insertions, 7 deletions
diff --git a/src/Air.zig b/src/Air.zig index 5c8873a199..90d61dfa03 100644 --- a/src/Air.zig +++ b/src/Air.zig @@ -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), diff --git a/src/Liveness.zig b/src/Liveness.zig index 1fd6cd91ee..ac34bc4e02 100644 --- a/src/Liveness.zig +++ b/src/Liveness.zig @@ -317,6 +317,7 @@ fn analyzeInst( .unreach, .fence, .ret_addr, + .frame_address, => return trackOperands(a, new_set, inst, main_tomb, .{ .none, .none, .none }), .not, diff --git a/src/Sema.zig b/src/Sema.zig index 8711b56b2d..de69cbe5da 100644 --- a/src/Sema.zig +++ b/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}), }; diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index c9413975e3..b58bad7a3c 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -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}); diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index 6cd4a1fd9f..1776196828 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -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: { diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index c654ea625d..ac5d914af1 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -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}); diff --git a/src/arch/wasm/CodeGen.zig b/src/arch/wasm/CodeGen.zig index e2e6b00e84..69a70d0d53 100644 --- a/src/arch/wasm/CodeGen.zig +++ b/src/arch/wasm/CodeGen.zig @@ -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. diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 45d9767320..3a6541ccd5 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -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: { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index f09acaa47c..331673cc55 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -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; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index e349f0186e..6f2cc9bbd0 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -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; diff --git a/src/print_air.zig b/src/print_air.zig index 4609c4d148..5c6fdf4759 100644 --- a/src/print_air.zig +++ b/src/print_air.zig @@ -177,6 +177,7 @@ const Writer = struct { .alloc, .ret_ptr, .arg, + .frame_address, => try w.writeTy(s, inst), .not, |
