diff options
| author | mlugg <mlugg@mlugg.co.uk> | 2024-02-13 02:36:13 +0000 |
|---|---|---|
| committer | mlugg <mlugg@mlugg.co.uk> | 2024-02-16 11:26:34 +0000 |
| commit | 10784c7fc8d419fff943994f1aa5a454d4e43391 (patch) | |
| tree | f58674fe9b481693abbba790f95491e950681ef8 | |
| parent | 434537213e406191959818f573b24ca45c1b0e45 (diff) | |
| download | zig-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.
| -rw-r--r-- | src/AstGen.zig | 117 | ||||
| -rw-r--r-- | src/Sema.zig | 84 |
2 files changed, 114 insertions, 87 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig index 0117f0ac26..4b9efa0408 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -360,16 +360,11 @@ const ResultInfo = struct { }; }; -/// TODO: modify Sema to remove in favour of `coerced_align_ri` -const align_ri: ResultInfo = .{ .rl = .{ .ty = .u29_type } }; const coerced_align_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .u29_type } }; -/// TODO: modify Sema to remove in favour of `coerced_addrspace_ri` -const addrspace_ri: ResultInfo = .{ .rl = .{ .ty = .address_space_type } }; const coerced_addrspace_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .address_space_type } }; const coerced_linksection_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }; -const bool_ri: ResultInfo = .{ .rl = .{ .ty = .bool_type } }; -const type_ri: ResultInfo = .{ .rl = .{ .ty = .type_type } }; const coerced_type_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .type_type } }; +const coerced_bool_ri: ResultInfo = .{ .rl = .{ .coerced_ty = .bool_type } }; fn typeExpr(gz: *GenZir, scope: *Scope, type_node: Ast.Node.Index) InnerError!Zir.Inst.Ref { return comptimeExpr(gz, scope, coerced_type_ri, type_node); @@ -786,7 +781,7 @@ fn expr(gz: *GenZir, scope: *Scope, ri: ResultInfo, node: Ast.Node.Index) InnerE .bool_and => return boolBinOp(gz, scope, ri, node, .bool_br_and), .bool_or => return boolBinOp(gz, scope, ri, node, .bool_br_or), - .bool_not => return simpleUnOp(gz, scope, ri, node, bool_ri, node_datas[node].lhs, .bool_not), + .bool_not => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, node_datas[node].lhs, .bool_not), .bit_not => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, node_datas[node].lhs, .bit_not), .negation => return negation(gz, scope, ri, node), @@ -1372,7 +1367,7 @@ fn fnProtoExpr( }; const align_ref: Zir.Inst.Ref = if (fn_proto.ast.align_expr == 0) .none else inst: { - break :inst try expr(&block_scope, scope, align_ri, fn_proto.ast.align_expr); + break :inst try expr(&block_scope, scope, coerced_align_ri, fn_proto.ast.align_expr); }; if (fn_proto.ast.addrspace_expr != 0) { @@ -1387,7 +1382,7 @@ fn fnProtoExpr( try expr( &block_scope, scope, - .{ .rl = .{ .ty = .calling_convention_type } }, + .{ .rl = .{ .coerced_ty = .calling_convention_type } }, fn_proto.ast.callconv_expr, ) else @@ -3136,7 +3131,7 @@ fn varDecl( } const align_inst: Zir.Inst.Ref = if (var_decl.ast.align_node != 0) - try expr(gz, scope, align_ri, var_decl.ast.align_node) + try expr(gz, scope, coerced_align_ri, var_decl.ast.align_node) else .none; @@ -3505,7 +3500,7 @@ fn assignDestructureMaybeDecls( const this_lhs_comptime = is_comptime or (is_const and rhs_is_comptime); const align_inst: Zir.Inst.Ref = if (full.ast.align_node != 0) - try expr(gz, scope, align_ri, full.ast.align_node) + try expr(gz, scope, coerced_align_ri, full.ast.align_node) else .none; @@ -3783,7 +3778,7 @@ fn ptrType( gz.astgen.source_line = source_line; gz.astgen.source_column = source_column; - addrspace_ref = try expr(gz, scope, addrspace_ri, ptr_info.ast.addrspace_node); + addrspace_ref = try expr(gz, scope, coerced_addrspace_ri, ptr_info.ast.addrspace_node); trailing_count += 1; } if (ptr_info.ast.align_node != 0) { @@ -4176,7 +4171,7 @@ fn fnDecl( var addrspace_gz = decl_gz.makeSubBlock(params_scope); defer addrspace_gz.unstack(); const addrspace_ref: Zir.Inst.Ref = if (fn_proto.ast.addrspace_expr == 0) .none else inst: { - const inst = try expr(&decl_gz, params_scope, addrspace_ri, fn_proto.ast.addrspace_expr); + const inst = try expr(&decl_gz, params_scope, coerced_addrspace_ri, fn_proto.ast.addrspace_expr); if (addrspace_gz.instructionsSlice().len == 0) { // In this case we will send a len=0 body which can be encoded more efficiently. break :inst inst; @@ -4431,7 +4426,7 @@ fn globalVarDecl( try expr( &block_scope, &block_scope.base, - .{ .rl = .{ .ty = .type_type } }, + coerced_type_ri, var_decl.ast.type_node, ) else @@ -5254,7 +5249,7 @@ fn unionDeclInner( return astgen.failNode(member_node, "union field missing type", .{}); } if (have_align) { - const align_inst = try expr(&block_scope, &block_scope.base, .{ .rl = .{ .ty = .u32_type } }, member.ast.align_expr); + const align_inst = try expr(&block_scope, &block_scope.base, coerced_align_ri, member.ast.align_expr); wip_members.appendToField(@intFromEnum(align_inst)); any_aligned_fields = true; } @@ -5522,7 +5517,7 @@ fn containerDecl( namespace.base.tag = .enum_namespace; const arg_inst: Zir.Inst.Ref = if (container_decl.ast.arg != 0) - try comptimeExpr(&block_scope, &namespace.base, .{ .rl = .{ .ty = .type_type } }, container_decl.ast.arg) + try comptimeExpr(&block_scope, &namespace.base, coerced_type_ri, container_decl.ast.arg) else .none; @@ -6079,7 +6074,7 @@ fn arrayAccess( const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); - const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs); + const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); try emitDbgStmt(gz, cursor); return gz.addPlNode(.elem_ptr_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }); @@ -6089,7 +6084,7 @@ fn arrayAccess( const cursor = maybeAdvanceSourceCursorToMainToken(gz, node); - const rhs = try expr(gz, scope, .{ .rl = .{ .ty = .usize_type } }, node_datas[node].rhs); + const rhs = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .usize_type } }, node_datas[node].rhs); try emitDbgStmt(gz, cursor); return rvalue(gz, ri, try gz.addPlNode(.elem_val_node, node, Zir.Inst.Bin{ .lhs = lhs, .rhs = rhs }), node); @@ -6157,12 +6152,12 @@ fn boolBinOp( const tree = astgen.tree; const node_datas = tree.nodes.items(.data); - const lhs = try expr(gz, scope, bool_ri, node_datas[node].lhs); + const lhs = try expr(gz, scope, coerced_bool_ri, node_datas[node].lhs); const bool_br = (try gz.addPlNodePayloadIndex(zir_tag, node, undefined)).toIndex().?; var rhs_scope = gz.makeSubBlock(scope); defer rhs_scope.unstack(); - const rhs = try expr(&rhs_scope, &rhs_scope.base, bool_ri, node_datas[node].rhs); + const rhs = try expr(&rhs_scope, &rhs_scope.base, coerced_bool_ri, node_datas[node].rhs); if (!gz.refIsNoReturn(rhs)) { _ = try rhs_scope.addBreakWithSrcNode(.break_inline, bool_br, rhs, node_datas[node].rhs); } @@ -6230,7 +6225,7 @@ fn ifExpr( .bool_bit = try block_scope.addUnNode(tag, optional, if_full.ast.cond_expr), }; } else { - const cond = try expr(&block_scope, &block_scope.base, bool_ri, if_full.ast.cond_expr); + const cond = try expr(&block_scope, &block_scope.base, coerced_bool_ri, if_full.ast.cond_expr); break :c .{ .inst = cond, .bool_bit = cond, @@ -6476,7 +6471,7 @@ fn whileExpr( .bool_bit = try cond_scope.addUnNode(tag, optional, while_full.ast.cond_expr), }; } else { - const cond = try expr(&cond_scope, &cond_scope.base, bool_ri, while_full.ast.cond_expr); + const cond = try expr(&cond_scope, &cond_scope.base, coerced_bool_ri, while_full.ast.cond_expr); break :c .{ .inst = cond, .bool_bit = cond, @@ -8052,7 +8047,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref .rl = .{ .ptr = .{ .inst = try gz.addNode(.ret_ptr, node) } }, .ctx = .@"return", } else .{ - .rl = .{ .ty = astgen.fn_ret_ty }, + .rl = .{ .coerced_ty = astgen.fn_ret_ty }, .ctx = .@"return", }; const prev_anon_name_strategy = gz.anon_name_strategy; @@ -8688,7 +8683,7 @@ fn unionInit( params: []const Ast.Node.Index, ) InnerError!Zir.Inst.Ref { const union_type = try typeExpr(gz, scope, params[0]); - const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]); const field_type = try gz.addPlNode(.field_type_ref, node, Zir.Inst.FieldTypeRef{ .container_type = union_type, .field_name = field_name, @@ -9001,12 +8996,12 @@ fn builtinCall( if (ri.rl == .ref or ri.rl == .ref_coerced_ty) { return gz.addPlNode(.field_ptr_named, node, Zir.Inst.FieldNamed{ .lhs = try expr(gz, scope, .{ .rl = .ref }, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]), }); } const result = try gz.addPlNode(.field_val_named, node, Zir.Inst.FieldNamed{ .lhs = try expr(gz, scope, .{ .rl = .none }, params[0]), - .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]), + .field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]), }); return rvalue(gz, ri, result, node); }, @@ -9133,7 +9128,7 @@ fn builtinCall( return rvalue(gz, ri, .void_value, node); }, .set_align_stack => { - const order = try expr(gz, scope, align_ri, params[0]); + const order = try expr(gz, scope, coerced_align_ri, params[0]); _ = try gz.addExtendedPayload(.set_align_stack, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = order, @@ -9175,32 +9170,32 @@ fn builtinCall( .bit_size_of => return simpleUnOpType(gz, scope, ri, node, params[0], .bit_size_of), .align_of => return simpleUnOpType(gz, scope, ri, node, params[0], .align_of), - .int_from_ptr => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_ptr), - .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .compile_error), - .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota), - .int_from_enum => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_enum), - .int_from_bool => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_bool), - .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .embed_file), - .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .anyerror_type } }, params[0], .error_name), - .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, bool_ri, params[0], .set_runtime_safety), - .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), - .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), - .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos), - .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan), - .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp), - .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2), - .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), - .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), - .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), - .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs), - .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), - .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), - .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), - .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round), - .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), - .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), - .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), - .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size), + .int_from_ptr => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_ptr), + .compile_error => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .compile_error), + .set_eval_branch_quota => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .u32_type } }, params[0], .set_eval_branch_quota), + .int_from_enum => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_enum), + .int_from_bool => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .int_from_bool), + .embed_file => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .embed_file), + .error_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .anyerror_type } }, params[0], .error_name), + .set_runtime_safety => return simpleUnOp(gz, scope, ri, node, coerced_bool_ri, params[0], .set_runtime_safety), + .sqrt => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sqrt), + .sin => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .sin), + .cos => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .cos), + .tan => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tan), + .exp => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp), + .exp2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .exp2), + .log => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log), + .log2 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log2), + .log10 => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .log10), + .abs => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .abs), + .floor => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .floor), + .ceil => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .ceil), + .trunc => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .trunc), + .round => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .round), + .tag_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .tag_name), + .type_name => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .type_name), + .Frame => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_type), + .frame_size => return simpleUnOp(gz, scope, ri, node, .{ .rl = .none }, params[0], .frame_size), .int_from_float => return typeCast(gz, scope, ri, node, params[0], .int_from_float, builtin_name), .float_from_int => return typeCast(gz, scope, ri, node, params[0], .float_from_int, builtin_name), @@ -9238,7 +9233,7 @@ fn builtinCall( }, .panic => { try emitDbgNode(gz, node); - return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0], .panic); + return simpleUnOp(gz, scope, ri, node, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0], .panic); }, .trap => { try emitDbgNode(gz, node); @@ -9327,7 +9322,7 @@ fn builtinCall( }, .c_define => { if (!gz.c_import) return gz.astgen.failNode(node, "C define valid only inside C import block", .{}); - const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[0]); + const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[0]); const value = try comptimeExpr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addExtendedPayload(.c_define, Zir.Inst.BinNode{ .node = gz.nodeIndexToRelative(node), @@ -9348,7 +9343,7 @@ fn builtinCall( return rvalue(gz, ri, result, node); }, .reduce => { - const op = try expr(gz, scope, .{ .rl = .{ .ty = .reduce_op_type } }, params[0]); + const op = try expr(gz, scope, .{ .rl = .{ .coerced_ty = .reduce_op_type } }, params[0]); const scalar = try expr(gz, scope, .{ .rl = .none }, params[1]); const result = try gz.addPlNode(.reduce, node, Zir.Inst.Bin{ .lhs = op, @@ -9424,7 +9419,7 @@ fn builtinCall( }, .field_parent_ptr => { const parent_type = try typeExpr(gz, scope, params[0]); - const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, params[1]); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, params[1]); const result = try gz.addPlNode(.field_parent_ptr, node, Zir.Inst.FieldParentPtr{ .parent_type = parent_type, .field_name = field_name, @@ -9561,7 +9556,7 @@ fn hasDeclOrField( tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const container_type = try typeExpr(gz, scope, lhs_node); - const name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node); + const name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node); const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = container_type, .rhs = name, @@ -9711,7 +9706,7 @@ fn simpleCBuiltin( ) InnerError!Zir.Inst.Ref { const name: []const u8 = if (tag == .c_undef) "C undef" else "C include"; if (!gz.c_import) return gz.astgen.failNode(node, "{s} valid only inside C import block", .{name}); - const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, operand_node); + const operand = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, operand_node); _ = try gz.addExtendedPayload(tag, Zir.Inst.UnNode{ .node = gz.nodeIndexToRelative(node), .operand = operand, @@ -9729,7 +9724,7 @@ fn offsetOf( tag: Zir.Inst.Tag, ) InnerError!Zir.Inst.Ref { const type_inst = try typeExpr(gz, scope, lhs_node); - const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .ty = .slice_const_u8_type } }, rhs_node); + const field_name = try comptimeExpr(gz, scope, .{ .rl = .{ .coerced_ty = .slice_const_u8_type } }, rhs_node); const result = try gz.addPlNode(tag, node, Zir.Inst.Bin{ .lhs = type_inst, .rhs = field_name, @@ -13148,7 +13143,7 @@ const GenZir = struct { fn addRet(gz: *GenZir, ri: ResultInfo, operand: Zir.Inst.Ref, node: Ast.Node.Index) !void { switch (ri.rl) { .ptr => |ptr_res| _ = try gz.addUnNode(.ret_load, ptr_res.inst, node), - .ty => _ = try gz.addUnNode(.ret_node, operand, node), + .coerced_ty => _ = try gz.addUnNode(.ret_node, operand, node), else => unreachable, } } 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 |
