addEnsureResult
Function parameters
Parameters
- gz:*GenZir
- maybe_unused_result:Zir.Inst.Ref
- statement:Ast.Node.Index
Functions in this namespace
Functions
Source
Implementation
fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: Ast.Node.Index) InnerError!Ast.Node.OptionalIndex {
var noreturn_src_node: Ast.Node.OptionalIndex = .none;
const elide_check = if (maybe_unused_result.toIndex()) |inst| b: {
// Note that this array becomes invalid after appending more items to it
// in the above while loop.
const zir_tags = gz.astgen.instructions.items(.tag);
switch (zir_tags[@intFromEnum(inst)]) {
// For some instructions, modify the zir data
// so we can avoid a separate ensure_result_used instruction.
.call, .field_call => {
const break_extra = gz.astgen.instructions.items(.data)[@intFromEnum(inst)].pl_node.payload_index;
comptime assert(std.meta.fieldIndex(Zir.Inst.Call, "flags") ==
std.meta.fieldIndex(Zir.Inst.FieldCall, "flags"));
const flags: *Zir.Inst.Call.Flags = @ptrCast(&gz.astgen.extra.items[
break_extra + std.meta.fieldIndex(Zir.Inst.Call, "flags").?
]);
flags.ensure_result_used = true;
break :b true;
},
.builtin_call => {
const break_extra = gz.astgen.instructions.items(.data)[@intFromEnum(inst)].pl_node.payload_index;
const flags: *Zir.Inst.BuiltinCall.Flags = @ptrCast(&gz.astgen.extra.items[
break_extra + std.meta.fieldIndex(Zir.Inst.BuiltinCall, "flags").?
]);
flags.ensure_result_used = true;
break :b true;
},
// ZIR instructions that might be a type other than `noreturn` or `void`.
.add,
.addwrap,
.add_sat,
.add_unsafe,
.param,
.param_comptime,
.param_anytype,
.param_anytype_comptime,
.alloc,
.alloc_mut,
.alloc_comptime_mut,
.alloc_inferred,
.alloc_inferred_mut,
.alloc_inferred_comptime,
.alloc_inferred_comptime_mut,
.make_ptr_const,
.array_cat,
.array_mul,
.array_type,
.array_type_sentinel,
.elem_type,
.indexable_ptr_elem_type,
.splat_op_result_ty,
.vector_type,
.indexable_ptr_len,
.anyframe_type,
.as_node,
.as_shift_operand,
.bit_and,
.bitcast,
.bit_or,
.block,
.block_comptime,
.block_inline,
.declaration,
.suspend_block,
.loop,
.bool_br_and,
.bool_br_or,
.bool_not,
.cmp_lt,
.cmp_lte,
.cmp_eq,
.cmp_gte,
.cmp_gt,
.cmp_neq,
.decl_ref,
.decl_val,
.load,
.div,
.elem_ptr,
.elem_val,
.elem_ptr_node,
.elem_val_node,
.elem_val_imm,
.field_ptr,
.field_val,
.field_ptr_named,
.field_val_named,
.func,
.func_inferred,
.func_fancy,
.int,
.int_big,
.float,
.float128,
.int_type,
.is_non_null,
.is_non_null_ptr,
.is_non_err,
.is_non_err_ptr,
.ret_is_non_err,
.mod_rem,
.mul,
.mulwrap,
.mul_sat,
.ref,
.shl,
.shl_sat,
.shr,
.str,
.sub,
.subwrap,
.sub_sat,
.negate,
.negate_wrap,
.typeof,
.typeof_builtin,
.xor,
.optional_type,
.optional_payload_safe,
.optional_payload_unsafe,
.optional_payload_safe_ptr,
.optional_payload_unsafe_ptr,
.err_union_payload_unsafe,
.err_union_payload_unsafe_ptr,
.err_union_code,
.err_union_code_ptr,
.ptr_type,
.enum_literal,
.decl_literal,
.decl_literal_no_coerce,
.merge_error_sets,
.error_union_type,
.bit_not,
.error_value,
.slice_start,
.slice_end,
.slice_sentinel,
.slice_length,
.slice_sentinel_ty,
.import,
.switch_block,
.switch_block_ref,
.switch_block_err_union,
.union_init,
.field_type_ref,
.error_set_decl,
.enum_from_int,
.int_from_enum,
.type_info,
.size_of,
.bit_size_of,
.typeof_log2_int_type,
.int_from_ptr,
.align_of,
.int_from_bool,
.embed_file,
.error_name,
.sqrt,
.sin,
.cos,
.tan,
.exp,
.exp2,
.log,
.log2,
.log10,
.abs,
.floor,
.ceil,
.trunc,
.round,
.tag_name,
.type_name,
.frame_type,
.int_from_float,
.float_from_int,
.ptr_from_int,
.float_cast,
.int_cast,
.ptr_cast,
.truncate,
.has_decl,
.has_field,
.clz,
.ctz,
.pop_count,
.byte_swap,
.bit_reverse,
.div_exact,
.div_floor,
.div_trunc,
.mod,
.rem,
.shl_exact,
.shr_exact,
.bit_offset_of,
.offset_of,
.splat,
.reduce,
.shuffle,
.atomic_load,
.atomic_rmw,
.mul_add,
.max,
.min,
.c_import,
.@"resume",
.ret_err_value_code,
.ret_ptr,
.ret_type,
.for_len,
.@"try",
.try_ptr,
.opt_eu_base_ptr_init,
.coerce_ptr_elem_ty,
.struct_init_empty,
.struct_init_empty_result,
.struct_init_empty_ref_result,
.struct_init_anon,
.struct_init,
.struct_init_ref,
.struct_init_field_type,
.struct_init_field_ptr,
.array_init_anon,
.array_init,
.array_init_ref,
.validate_array_init_ref_ty,
.array_init_elem_type,
.array_init_elem_ptr,
=> break :b false,
.extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) {
.breakpoint,
.disable_instrumentation,
.disable_intrinsics,
.set_float_mode,
.branch_hint,
=> break :b true,
else => break :b false,
},
// ZIR instructions that are always `noreturn`.
.@"break",
.break_inline,
.condbr,
.condbr_inline,
.compile_error,
.ret_node,
.ret_load,
.ret_implicit,
.ret_err_value,
.@"unreachable",
.repeat,
.repeat_inline,
.panic,
.trap,
.check_comptime_control_flow,
.switch_continue,
=> {
noreturn_src_node = statement.toOptional();
break :b true;
},
// ZIR instructions that are always `void`.
.dbg_stmt,
.dbg_var_ptr,
.dbg_var_val,
.ensure_result_used,
.ensure_result_non_error,
.ensure_err_union_payload_void,
.@"export",
.set_eval_branch_quota,
.atomic_store,
.store_node,
.store_to_inferred_ptr,
.resolve_inferred_alloc,
.set_runtime_safety,
.memcpy,
.memset,
.memmove,
.validate_deref,
.validate_destructure,
.save_err_ret_index,
.restore_err_ret_index_unconditional,
.restore_err_ret_index_fn_entry,
.validate_struct_init_ty,
.validate_struct_init_result_ty,
.validate_ptr_struct_init,
.validate_array_init_ty,
.validate_array_init_result_ty,
.validate_ptr_array_init,
.validate_ref_ty,
.validate_const,
=> break :b true,
.@"defer" => unreachable,
.defer_err_code => unreachable,
}
} else switch (maybe_unused_result) {
.none => unreachable,
.unreachable_value => b: {
noreturn_src_node = statement.toOptional();
break :b true;
},
.void_value => true,
else => false,
};
if (!elide_check) {
_ = try gz.addUnNode(.ensure_result_used, maybe_unused_result, statement);
}
return noreturn_src_node;
}