| ... | @@ -14492,6 +14492,20 @@ fn zirBoolBr( | ... | @@ -14492,6 +14492,20 @@ fn zirBoolBr( |
| 14492 | const rhs_result = try sema.resolveBody(rhs_block, body, inst); | 14492 | const rhs_result = try sema.resolveBody(rhs_block, body, inst); |
| 14493 | _ = try rhs_block.addBr(block_inst, rhs_result); | 14493 | _ = try rhs_block.addBr(block_inst, rhs_result); |
| 14494 | | 14494 | |
| | 14495 | return finishCondBr(sema, parent_block, &child_block, &then_block, &else_block, lhs, block_inst); |
| | 14496 | } |
| | 14497 | |
| | 14498 | fn finishCondBr( |
| | 14499 | sema: *Sema, |
| | 14500 | parent_block: *Block, |
| | 14501 | child_block: *Block, |
| | 14502 | then_block: *Block, |
| | 14503 | else_block: *Block, |
| | 14504 | cond: Air.Inst.Ref, |
| | 14505 | block_inst: Air.Inst.Index, |
| | 14506 | ) !Air.Inst.Ref { |
| | 14507 | const gpa = sema.gpa; |
| | 14508 | |
| 14495 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + | 14509 | try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len + |
| 14496 | then_block.instructions.items.len + else_block.instructions.items.len + | 14510 | then_block.instructions.items.len + else_block.instructions.items.len + |
| 14497 | @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len + 1); | 14511 | @typeInfo(Air.Block).Struct.fields.len + child_block.instructions.items.len + 1); |
| ... | @@ -14504,7 +14518,7 @@ fn zirBoolBr( | ... | @@ -14504,7 +14518,7 @@ fn zirBoolBr( |
| 14504 | sema.air_extra.appendSliceAssumeCapacity(else_block.instructions.items); | 14518 | sema.air_extra.appendSliceAssumeCapacity(else_block.instructions.items); |
| 14505 | | 14519 | |
| 14506 | _ = try child_block.addInst(.{ .tag = .cond_br, .data = .{ .pl_op = .{ | 14520 | _ = try child_block.addInst(.{ .tag = .cond_br, .data = .{ .pl_op = .{ |
| 14507 | .operand = lhs, | 14521 | .operand = cond, |
| 14508 | .payload = cond_br_payload, | 14522 | .payload = cond_br_payload, |
| 14509 | } } }); | 14523 | } } }); |
| 14510 | | 14524 | |
| ... | @@ -14901,6 +14915,8 @@ fn analyzeRet( | ... | @@ -14901,6 +14915,8 @@ fn analyzeRet( |
| 14901 | uncasted_operand: Air.Inst.Ref, | 14915 | uncasted_operand: Air.Inst.Ref, |
| 14902 | src: LazySrcLoc, | 14916 | src: LazySrcLoc, |
| 14903 | ) CompileError!Zir.Inst.Index { | 14917 | ) CompileError!Zir.Inst.Index { |
| | 14918 | const gpa = sema.gpa; |
| | 14919 | |
| 14904 | // Special case for returning an error to an inferred error set; we need to | 14920 | // Special case for returning an error to an inferred error set; we need to |
| 14905 | // add the error tag to the inferred error set of the in-scope function, so | 14921 | // add the error tag to the inferred error set of the in-scope function, so |
| 14906 | // that the coercion below works correctly. | 14922 | // that the coercion below works correctly. |
| ... | @@ -14918,11 +14934,13 @@ fn analyzeRet( | ... | @@ -14918,11 +14934,13 @@ fn analyzeRet( |
| 14918 | return error.ComptimeReturn; | 14934 | return error.ComptimeReturn; |
| 14919 | } | 14935 | } |
| 14920 | // We are inlining a function call; rewrite the `ret` as a `break`. | 14936 | // We are inlining a function call; rewrite the `ret` as a `break`. |
| 14921 | try inlining.merges.results.append(sema.gpa, operand); | 14937 | try inlining.merges.results.append(gpa, operand); |
| 14922 | _ = try block.addBr(inlining.merges.block_inst, operand); | 14938 | _ = try block.addBr(inlining.merges.block_inst, operand); |
| 14923 | return always_noreturn; | 14939 | return always_noreturn; |
| 14924 | } | 14940 | } |
| 14925 | | 14941 | |
| | 14942 | try sema.resolveTypeLayout(block, src, sema.fn_ret_ty); |
| | 14943 | |
| 14926 | // TODO implement this feature in all the backends and then delete this check. | 14944 | // TODO implement this feature in all the backends and then delete this check. |
| 14927 | const backend_supports_error_return_tracing = | 14945 | const backend_supports_error_return_tracing = |
| 14928 | sema.mod.comp.bin_file.options.use_llvm; | 14946 | sema.mod.comp.bin_file.options.use_llvm; |
| ... | @@ -14931,19 +14949,52 @@ fn analyzeRet( | ... | @@ -14931,19 +14949,52 @@ fn analyzeRet( |
| 14931 | sema.mod.comp.bin_file.options.error_return_tracing and | 14949 | sema.mod.comp.bin_file.options.error_return_tracing and |
| 14932 | backend_supports_error_return_tracing) | 14950 | backend_supports_error_return_tracing) |
| 14933 | ret_err: { | 14951 | ret_err: { |
| 14934 | if (try sema.resolveMaybeUndefVal(block, src, operand)) |ret_val| { | 14952 | // Avoid adding a frame to the error return trace in case the value is comptime-known |
| 14935 | if (ret_val.tag() != .@"error") break :ret_err; | 14953 | // to be not an error. |
| 14936 | } | 14954 | const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, src, operand); |
| 14937 | const return_err_fn = try sema.getBuiltin(block, src, "returnError"); | 14955 | const need_check = switch (is_non_err) { |
| | 14956 | .bool_true => break :ret_err, |
| | 14957 | .bool_false => false, |
| | 14958 | else => true, |
| | 14959 | }; |
| | 14960 | |
| 14938 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); | 14961 | const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); |
| 14939 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); | 14962 | const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); |
| 14940 | const ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty); | 14963 | const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty); |
| 14941 | const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); | 14964 | const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty); |
| | 14965 | const return_err_fn = try sema.getBuiltin(block, src, "returnError"); |
| 14942 | const args: [1]Air.Inst.Ref = .{err_return_trace}; | 14966 | const args: [1]Air.Inst.Ref = .{err_return_trace}; |
| | 14967 | |
| | 14968 | if (!need_check) { |
| | 14969 | _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null); |
| | 14970 | break :ret_err; |
| | 14971 | } |
| | 14972 | |
| | 14973 | const block_inst = @intCast(Air.Inst.Index, sema.air_instructions.len); |
| | 14974 | try sema.air_instructions.append(gpa, .{ |
| | 14975 | .tag = .block, |
| | 14976 | .data = .{ .ty_pl = .{ |
| | 14977 | .ty = .void_type, |
| | 14978 | .payload = undefined, |
| | 14979 | } }, |
| | 14980 | }); |
| | 14981 | |
| | 14982 | var child_block = block.makeSubBlock(); |
| | 14983 | defer child_block.instructions.deinit(gpa); |
| | 14984 | |
| | 14985 | var then_block = child_block.makeSubBlock(); |
| | 14986 | defer then_block.instructions.deinit(gpa); |
| | 14987 | _ = try then_block.addUnOp(.ret, operand); |
| | 14988 | |
| | 14989 | var else_block = child_block.makeSubBlock(); |
| | 14990 | defer else_block.instructions.deinit(gpa); |
| 14943 | _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null); | 14991 | _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null); |
| | 14992 | _ = try else_block.addUnOp(.ret, operand); |
| | 14993 | |
| | 14994 | _ = try finishCondBr(sema, block, &child_block, &then_block, &else_block, is_non_err, block_inst); |
| | 14995 | return always_noreturn; |
| 14944 | } | 14996 | } |
| 14945 | | 14997 | |
| 14946 | try sema.resolveTypeLayout(block, src, sema.fn_ret_ty); | | |
| 14947 | _ = try block.addUnOp(.ret, operand); | 14998 | _ = try block.addUnOp(.ret, operand); |
| 14948 | return always_noreturn; | 14999 | return always_noreturn; |
| 14949 | } | 15000 | } |
| ... | @@ -25436,10 +25487,16 @@ fn analyzeIsNonErrComptimeOnly( | ... | @@ -25436,10 +25487,16 @@ fn analyzeIsNonErrComptimeOnly( |
| 25436 | assert(ot == .ErrorUnion); | 25487 | assert(ot == .ErrorUnion); |
| 25437 | | 25488 | |
| 25438 | if (Air.refToIndex(operand)) |operand_inst| { | 25489 | if (Air.refToIndex(operand)) |operand_inst| { |
| 25439 | const air_tags = sema.air_instructions.items(.tag); | 25490 | switch (sema.air_instructions.items(.tag)[operand_inst]) { |
| 25440 | if (air_tags[operand_inst] == .wrap_errunion_payload) { | 25491 | .wrap_errunion_payload => return Air.Inst.Ref.bool_true, |
| 25441 | return Air.Inst.Ref.bool_true; | 25492 | .wrap_errunion_err => return Air.Inst.Ref.bool_false, |
| | 25493 | else => {}, |
| 25442 | } | 25494 | } |
| | 25495 | } else if (operand == .undef) { |
| | 25496 | return sema.addConstUndef(Type.bool); |
| | 25497 | } else { |
| | 25498 | // None of the ref tags can be errors. |
| | 25499 | return Air.Inst.Ref.bool_true; |
| 25443 | } | 25500 | } |
| 25444 | | 25501 | |
| 25445 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, src, operand); | 25502 | const maybe_operand_val = try sema.resolveMaybeUndefVal(block, src, operand); |