@@ -14888,10 +14888,83 @@ fn zirRetLoad(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Zir
14888
14888
const operand = try sema.analyzeLoad(block, src, ret_ptr, src);
14889
14889
return sema.analyzeRet(block, operand, src);
14890
14890
}
14891
+
14892
+ if (sema.wantErrorReturnTracing()) {
14893
+ const is_non_err = try sema.analyzePtrIsNonErr(block, src, ret_ptr);
14894
+ return retWithErrTracing(sema, block, src, is_non_err, .ret_load, ret_ptr);
14895
+ }
14896
+
14891
14897
_ = try block.addUnOp(.ret_load, ret_ptr);
14892
14898
return always_noreturn;
14893
14899
}
14894
14900
14901
+ fn retWithErrTracing(
14902
+ sema: *Sema,
14903
+ block: *Block,
14904
+ src: LazySrcLoc,
14905
+ is_non_err: Air.Inst.Ref,
14906
+ ret_tag: Air.Inst.Tag,
14907
+ operand: Air.Inst.Ref,
14908
+ ) CompileError!Zir.Inst.Index {
14909
+ const need_check = switch (is_non_err) {
14910
+ .bool_true => {
14911
+ _ = try block.addUnOp(ret_tag, operand);
14912
+ return always_noreturn;
14913
+ },
14914
+ .bool_false => false,
14915
+ else => true,
14916
+ };
14917
+ const gpa = sema.gpa;
14918
+ const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
14919
+ const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
14920
+ const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, stack_trace_ty);
14921
+ const err_return_trace = try block.addTy(.err_return_trace, ptr_stack_trace_ty);
14922
+ const return_err_fn = try sema.getBuiltin(block, src, "returnError");
14923
+ const args: [1]Air.Inst.Ref = .{err_return_trace};
14924
+
14925
+ if (!need_check) {
14926
+ _ = try sema.analyzeCall(block, return_err_fn, src, src, .never_inline, false, &args, null);
14927
+ _ = try block.addUnOp(ret_tag, operand);
14928
+ return always_noreturn;
14929
+ }
14930
+
14931
+ var then_block = block.makeSubBlock();
14932
+ defer then_block.instructions.deinit(gpa);
14933
+ _ = try then_block.addUnOp(ret_tag, operand);
14934
+
14935
+ var else_block = block.makeSubBlock();
14936
+ defer else_block.instructions.deinit(gpa);
14937
+ _ = try sema.analyzeCall(&else_block, return_err_fn, src, src, .never_inline, false, &args, null);
14938
+ _ = try else_block.addUnOp(ret_tag, operand);
14939
+
14940
+ try sema.air_extra.ensureUnusedCapacity(gpa, @typeInfo(Air.CondBr).Struct.fields.len +
14941
+ then_block.instructions.items.len + else_block.instructions.items.len +
14942
+ @typeInfo(Air.Block).Struct.fields.len + 1);
14943
+
14944
+ const cond_br_payload = sema.addExtraAssumeCapacity(Air.CondBr{
14945
+ .then_body_len = @intCast(u32, then_block.instructions.items.len),
14946
+ .else_body_len = @intCast(u32, else_block.instructions.items.len),
14947
+ });
14948
+ sema.air_extra.appendSliceAssumeCapacity(then_block.instructions.items);
14949
+ sema.air_extra.appendSliceAssumeCapacity(else_block.instructions.items);
14950
+
14951
+ _ = try block.addInst(.{ .tag = .cond_br, .data = .{ .pl_op = .{
14952
+ .operand = is_non_err,
14953
+ .payload = cond_br_payload,
14954
+ } } });
14955
+
14956
+ return always_noreturn;
14957
+ }
14958
+
14959
+ fn wantErrorReturnTracing(sema: *Sema) bool {
14960
+ // TODO implement this feature in all the backends and then delete this check.
14961
+ const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm;
14962
+
14963
+ return sema.fn_ret_ty.isError() and
14964
+ sema.mod.comp.bin_file.options.error_return_tracing and
14965
+ backend_supports_error_return_tracing;
14966
+ }
14967
+
14895
14968
fn addToInferredErrorSet(sema: *Sema, uncasted_operand: Air.Inst.Ref) !void {
14896
14969
assert(sema.fn_ret_ty.zigTypeTag() == .ErrorUnion);
14897
14970
@@ -14915,8 +14988,6 @@ fn analyzeRet(
14915
14988
uncasted_operand: Air.Inst.Ref,
14916
14989
src: LazySrcLoc,
14917
14990
) CompileError!Zir.Inst.Index {
14918
- const gpa = sema.gpa;
14919
-
14920
14991
// Special case for returning an error to an inferred error set; we need to
14921
14992
// add the error tag to the inferred error set of the in-scope function, so
14922
14993
// that the coercion below works correctly.
@@ -14934,65 +15005,18 @@ fn analyzeRet(
14934
15005
return error.ComptimeReturn;
14935
15006
}
14936
15007
// We are inlining a function call; rewrite the `ret` as a `break`.
14937
- try inlining.merges.results.append(gpa, operand);
15008
+ try inlining.merges.results.append(sema. gpa, operand);
14938
15009
_ = try block.addBr(inlining.merges.block_inst, operand);
14939
15010
return always_noreturn;
14940
15011
}
14941
15012
14942
15013
try sema.resolveTypeLayout(block, src, sema.fn_ret_ty);
14943
15014
14944
- // TODO implement this feature in all the backends and then delete this check.
14945
- const backend_supports_error_return_tracing =
14946
- sema.mod.comp.bin_file.options.use_llvm;
14947
-
14948
- if (sema.fn_ret_ty.isError() and
14949
- sema.mod.comp.bin_file.options.error_return_tracing and
14950
- backend_supports_error_return_tracing)
14951
- ret_err: {
15015
+ if (sema.wantErrorReturnTracing()) {
14952
15016
// Avoid adding a frame to the error return trace in case the value is comptime-known
14953
15017
// to be not an error.
14954
- const is_non_err = try sema.analyzeIsNonErrComptimeOnly(block, src, operand);
14955
- const need_check = switch (is_non_err) {
14956
- .bool_true => break :ret_err,
14957
- .bool_false => false,
14958
- else => true,
14959
- };
14960
-
14961
- const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace");
14962
- const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty);
14963
- const ptr_stack_trace_ty = try Type.Tag.single_mut_pointer.create(sema.arena, 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");
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);
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;
15018
+ const is_non_err = try sema.analyzeIsNonErr(block, src, operand);
15019
+ return retWithErrTracing(sema, block, src, is_non_err, .ret, operand);
14996
15020
}
14997
15021
14998
15022
_ = try block.addUnOp(.ret, operand);
@@ -25474,6 +25498,27 @@ fn analyzeIsNull(
25474
25498
return block.addUnOp(air_tag, operand);
25475
25499
}
25476
25500
25501
+ fn analyzePtrIsNonErrComptimeOnly(
25502
+ sema: *Sema,
25503
+ block: *Block,
25504
+ src: LazySrcLoc,
25505
+ operand: Air.Inst.Ref,
25506
+ ) CompileError!Air.Inst.Ref {
25507
+ const ptr_ty = sema.typeOf(operand);
25508
+ assert(ptr_ty.zigTypeTag() == .Pointer);
25509
+ const child_ty = ptr_ty.childType();
25510
+
25511
+ const child_tag = child_ty.zigTypeTag();
25512
+ if (child_tag != .ErrorSet and child_tag != .ErrorUnion) return Air.Inst.Ref.bool_true;
25513
+ if (child_tag == .ErrorSet) return Air.Inst.Ref.bool_false;
25514
+ assert(child_tag == .ErrorUnion);
25515
+
25516
+ _ = block;
25517
+ _ = src;
25518
+
25519
+ return Air.Inst.Ref.none;
25520
+ }
25521
+
25477
25522
fn analyzeIsNonErrComptimeOnly(
25478
25523
sema: *Sema,
25479
25524
block: *Block,
@@ -25572,6 +25617,21 @@ fn analyzeIsNonErr(
25572
25617
}
25573
25618
}
25574
25619
25620
+ fn analyzePtrIsNonErr(
25621
+ sema: *Sema,
25622
+ block: *Block,
25623
+ src: LazySrcLoc,
25624
+ operand: Air.Inst.Ref,
25625
+ ) CompileError!Air.Inst.Ref {
25626
+ const result = try sema.analyzePtrIsNonErrComptimeOnly(block, src, operand);
25627
+ if (result == .none) {
25628
+ try sema.requireRuntimeBlock(block, src, null);
25629
+ return block.addUnOp(.is_non_err_ptr, operand);
25630
+ } else {
25631
+ return result;
25632
+ }
25633
+ }
25634
+
25575
25635
fn analyzeSlice(
25576
25636
sema: *Sema,
25577
25637
block: *Block,
0 commit comments