aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authormlugg <mlugg@mlugg.co.uk>2024-02-13 02:36:13 +0000
committermlugg <mlugg@mlugg.co.uk>2024-02-16 11:26:34 +0000
commit10784c7fc8d419fff943994f1aa5a454d4e43391 (patch)
treef58674fe9b481693abbba790f95491e950681ef8 /src/Sema.zig
parent434537213e406191959818f573b24ca45c1b0e45 (diff)
downloadzig-10784c7fc8d419fff943994f1aa5a454d4e43391.tar.gz
zig-10784c7fc8d419fff943994f1aa5a454d4e43391.zip
AstGen: migrate `ty` result locations to `coerced_ty`
In most cases where AstGen is coercing to a fixed type (such as `u29`, `type`, `std.builtin.CallingConvention) we do not necessarily require an explicit coercion instruction. Instead, Sema knows the type that is required, and can perform the coercion after the fact. This means we can use the `coerced_ty` result location kind, saving unnecessary coercion instructions and therefore ZIR bytes. This required a few enhancements to Sema to introduce missing coercions.
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig84
1 files changed, 58 insertions, 26 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index e0ff94ec83..3465f923a8 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -10487,7 +10487,8 @@ fn zirElemValNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const array = try sema.resolveInst(extra.lhs);
- const elem_index = try sema.resolveInst(extra.rhs);
+ const uncoerced_elem_index = try sema.resolveInst(extra.rhs);
+ const elem_index = try sema.coerce(block, Type.usize, uncoerced_elem_index, elem_index_src);
return sema.elemVal(block, src, array, elem_index, elem_index_src, true);
}
@@ -10539,7 +10540,8 @@ fn zirElemPtrNode(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
const elem_index_src: LazySrcLoc = .{ .node_offset_array_access_index = inst_data.src_node };
const extra = sema.code.extraData(Zir.Inst.Bin, inst_data.payload_index).data;
const array_ptr = try sema.resolveInst(extra.lhs);
- const elem_index = try sema.resolveInst(extra.rhs);
+ const uncoerced_elem_index = try sema.resolveInst(extra.rhs);
+ const elem_index = try sema.coerce(block, Type.usize, uncoerced_elem_index, elem_index_src);
return sema.elemPtr(block, src, array_ptr, elem_index, elem_index_src, false, true);
}
@@ -18722,11 +18724,13 @@ fn zirBoolBr(
const inst_data = datas[@intFromEnum(inst)].pl_node;
const extra = sema.code.extraData(Zir.Inst.BoolBr, inst_data.payload_index);
- const lhs = try sema.resolveInst(extra.data.lhs);
+ const uncoerced_lhs = try sema.resolveInst(extra.data.lhs);
const body = sema.code.bodySlice(extra.end, extra.data.body_len);
const lhs_src: LazySrcLoc = .{ .node_offset_bin_lhs = inst_data.src_node };
const rhs_src: LazySrcLoc = .{ .node_offset_bin_rhs = inst_data.src_node };
+ const lhs = try sema.coerce(parent_block, Type.bool, uncoerced_lhs, lhs_src);
+
if (try sema.resolveDefinedValue(parent_block, lhs_src, lhs)) |lhs_val| {
if (is_bool_or and lhs_val.toBool()) {
return .bool_true;
@@ -18736,7 +18740,11 @@ fn zirBoolBr(
// comptime-known left-hand side. No need for a block here; the result
// is simply the rhs expression. Here we rely on there only being 1
// break instruction (`break_inline`).
- return sema.resolveBody(parent_block, body, inst);
+ const rhs_result = try sema.resolveBody(parent_block, body, inst);
+ if (sema.typeOf(rhs_result).isNoReturn(mod)) {
+ return rhs_result;
+ }
+ return sema.coerce(parent_block, Type.bool, rhs_result, rhs_src);
}
const block_inst: Air.Inst.Index = @enumFromInt(sema.air_instructions.len);
@@ -18767,13 +18775,16 @@ fn zirBoolBr(
_ = try lhs_block.addBr(block_inst, lhs_result);
const rhs_result = try sema.resolveBody(rhs_block, body, inst);
- if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
- _ = try rhs_block.addBr(block_inst, rhs_result);
- }
+ const rhs_noret = sema.typeOf(rhs_result).isNoReturn(mod);
+ const coerced_rhs_result = if (!rhs_noret) rhs: {
+ const coerced_result = try sema.coerce(rhs_block, Type.bool, rhs_result, rhs_src);
+ _ = try rhs_block.addBr(block_inst, coerced_result);
+ break :rhs coerced_result;
+ } else rhs_result;
const result = sema.finishCondBr(parent_block, &child_block, &then_block, &else_block, lhs, block_inst);
- if (!sema.typeOf(rhs_result).isNoReturn(mod)) {
- if (try sema.resolveDefinedValue(rhs_block, rhs_src, rhs_result)) |rhs_val| {
+ if (!rhs_noret) {
+ if (try sema.resolveDefinedValue(rhs_block, rhs_src, coerced_rhs_result)) |rhs_val| {
if (is_bool_or and rhs_val.toBool()) {
return .bool_true;
} else if (!is_bool_or and !rhs_val.toBool()) {
@@ -20750,8 +20761,9 @@ fn zirIntFromBool(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError
fn zirErrorName(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
- const operand = try sema.resolveInst(inst_data.operand);
const operand_src: LazySrcLoc = .{ .node_offset_builtin_call_arg0 = inst_data.src_node };
+ const uncoerced_operand = try sema.resolveInst(inst_data.operand);
+ const operand = try sema.coerce(block, Type.anyerror, uncoerced_operand, operand_src);
if (try sema.resolveDefinedValue(block, operand_src, operand)) |val| {
const err_name = sema.mod.intern_pool.indexToKey(val.toIntern()).err.name;
@@ -25375,15 +25387,21 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_align_ref) blk: {
const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const align_tv = sema.resolveInstConst(block, align_src, align_ref, .{
+ const uncoerced_align = sema.resolveInst(align_ref) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const coerced_align = sema.coerce(block, Type.u29, uncoerced_align, align_src) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const align_val = sema.resolveConstDefinedValue(block, align_src, coerced_align, .{
.needed_comptime_reason = "alignment must be comptime-known",
}) catch |err| switch (err) {
- error.GenericPoison => {
- break :blk null;
- },
+ error.GenericPoison => break :blk null,
else => |e| return e,
};
- const alignment = try sema.validateAlignAllowZero(block, align_src, try align_tv.val.toUnsignedIntAdvanced(sema));
+ const alignment = try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntAdvanced(sema));
const default = target_util.defaultFunctionAlignment(target);
break :blk if (alignment == default) .none else alignment;
} else .none;
@@ -25394,7 +25412,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
const body = sema.code.bodySlice(extra_index, body_len);
extra_index += body.len;
- const addrspace_ty = try sema.getBuiltinType("AddressSpace");
+ const addrspace_ty = Type.fromInterned(.address_space_type);
const val = try sema.resolveGenericBody(block, addrspace_src, body, inst, addrspace_ty, .{
.needed_comptime_reason = "addrspace must be comptime-known",
});
@@ -25405,15 +25423,22 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_addrspace_ref) blk: {
const addrspace_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const addrspace_tv = sema.resolveInstConst(block, addrspace_src, addrspace_ref, .{
+ const addrspace_ty = Type.fromInterned(.address_space_type);
+ const uncoerced_addrspace = sema.resolveInst(addrspace_ref) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const coerced_addrspace = sema.coerce(block, addrspace_ty, uncoerced_addrspace, addrspace_src) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const addrspace_val = sema.resolveConstDefinedValue(block, addrspace_src, coerced_addrspace, .{
.needed_comptime_reason = "addrspace must be comptime-known",
}) catch |err| switch (err) {
- error.GenericPoison => {
- break :blk null;
- },
+ error.GenericPoison => break :blk null,
else => |e| return e,
};
- break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_tv.val);
+ break :blk mod.toEnum(std.builtin.AddressSpace, addrspace_val);
} else target_util.defaultAddressSpace(target, .function);
const section: Section = if (extra.data.bits.has_section_body) blk: {
@@ -25461,15 +25486,22 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
} else if (extra.data.bits.has_cc_ref) blk: {
const cc_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
extra_index += 1;
- const cc_tv = sema.resolveInstConst(block, cc_src, cc_ref, .{
+ const cc_ty = Type.fromInterned(.calling_convention_type);
+ const uncoerced_cc = sema.resolveInst(cc_ref) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const coerced_cc = sema.coerce(block, cc_ty, uncoerced_cc, cc_src) catch |err| switch (err) {
+ error.GenericPoison => break :blk null,
+ else => |e| return e,
+ };
+ const cc_val = sema.resolveConstDefinedValue(block, cc_src, coerced_cc, .{
.needed_comptime_reason = "calling convention must be comptime-known",
}) catch |err| switch (err) {
- error.GenericPoison => {
- break :blk null;
- },
+ error.GenericPoison => break :blk null,
else => |e| return e,
};
- break :blk mod.toEnum(std.builtin.CallingConvention, cc_tv.val);
+ break :blk mod.toEnum(std.builtin.CallingConvention, cc_val);
} else if (sema.owner_decl.is_exported and has_body)
.C
else