From eee8fffec70b1d3e2900970dbe836e346e499231 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 22 Apr 2022 21:30:54 +0300 Subject: stage2: implement error return traces --- src/codegen/c.zig | 34 +++++++++++++++++++++ src/codegen/llvm.zig | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 116 insertions(+), 2 deletions(-) (limited to 'src/codegen') diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 998271cd7f..c3ca79dabe 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -1911,6 +1911,8 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO .wrap_errunion_payload => try airWrapErrUnionPay(f, inst), .wrap_errunion_err => try airWrapErrUnionErr(f, inst), .errunion_payload_ptr_set => try airErrUnionPayloadPtrSet(f, inst), + .err_return_trace => try airErrReturnTrace(f, inst), + .set_err_return_trace => try airSetErrReturnTrace(f, inst), .wasm_memory_size => try airWasmMemorySize(f, inst), .wasm_memory_grow => try airWasmMemoryGrow(f, inst), @@ -3447,6 +3449,38 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { return local; } +fn airErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; + + const un_op = f.air.instructions.items(.data)[inst].un_op; + const writer = f.object.writer(); + const inst_ty = f.air.typeOfIndex(inst); + const operand = try f.resolveInst(un_op); + const local = try f.allocLocal(inst_ty, .Const); + + try writer.writeAll(" = "); + + _ = operand; + _ = local; + return f.fail("TODO: C backend: implement airErrReturnTrace", .{}); +} + +fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { + if (f.liveness.isUnused(inst)) return CValue.none; + + const un_op = f.air.instructions.items(.data)[inst].un_op; + const writer = f.object.writer(); + const inst_ty = f.air.typeOfIndex(inst); + const operand = try f.resolveInst(un_op); + const local = try f.allocLocal(inst_ty, .Const); + + try writer.writeAll(" = "); + + _ = operand; + _ = local; + return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{}); +} + fn airWrapErrUnionPay(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 7392b2068b..dfb0f8f03b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -636,10 +636,18 @@ pub const Object = struct { const ret_ptr = if (sret) llvm_func.getParam(0) else null; const gpa = dg.gpa; + const err_return_tracing = fn_info.return_type.isError() and + dg.module.comp.bin_file.options.error_return_tracing; + + const err_ret_trace = if (err_return_tracing) + llvm_func.getParam(@boolToInt(ret_ptr != null)) + else + null; + var args = std.ArrayList(*const llvm.Value).init(gpa); defer args.deinit(); - const param_offset: c_uint = @boolToInt(ret_ptr != null); + const param_offset = @as(c_uint, @boolToInt(ret_ptr != null)) + @boolToInt(err_return_tracing); for (fn_info.param_types) |param_ty| { if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; @@ -711,6 +719,7 @@ pub const Object = struct { .base_line = dg.decl.src_line, .prev_dbg_line = 0, .prev_dbg_column = 0, + .err_ret_trace = err_ret_trace, }; defer fg.deinit(); @@ -1755,6 +1764,17 @@ pub const Object = struct { try param_di_types.append(try o.lowerDebugType(Type.void, .full)); } + if (fn_info.return_type.isError() and + o.module.comp.bin_file.options.error_return_tracing) + { + var ptr_ty_payload: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = o.getStackTraceType(), + }; + const ptr_ty = Type.initPayload(&ptr_ty_payload.base); + try param_di_types.append(try o.lowerDebugType(ptr_ty, .full)); + } + for (fn_info.param_types) |param_ty| { if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; @@ -1824,6 +1844,27 @@ pub const Object = struct { "", // unique id ); } + + fn getStackTraceType(o: *Object) Type { + const mod = o.module; + + const std_pkg = mod.main_pkg.table.get("std").?; + const std_file = (mod.importPkg(std_pkg) catch unreachable).file; + + const builtin_str: []const u8 = "builtin"; + const std_namespace = mod.declPtr(std_file.root_decl.unwrap().?).src_namespace; + const builtin_decl = std_namespace.decls + .getKeyAdapted(builtin_str, Module.DeclAdapter{ .mod = mod }).?; + + const stack_trace_str: []const u8 = "StackTrace"; + // buffer is only used for int_type, `builtin` is a struct. + const builtin_ty = mod.declPtr(builtin_decl).val.toType(undefined); + const builtin_namespace = builtin_ty.getNamespace().?; + const stack_trace_decl = builtin_namespace.decls + .getKeyAdapted(stack_trace_str, Module.DeclAdapter{ .mod = mod }).?; + + return mod.declPtr(stack_trace_decl).val.toType(undefined); + } }; pub const DeclGen = struct { @@ -1976,8 +2017,15 @@ pub const DeclGen = struct { llvm_fn.addSretAttr(0, raw_llvm_ret_ty); } + const err_return_tracing = fn_info.return_type.isError() and + dg.module.comp.bin_file.options.error_return_tracing; + + if (err_return_tracing) { + dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull"); + } + // Set parameter attributes. - var llvm_param_i: c_uint = @boolToInt(sret); + var llvm_param_i: c_uint = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing); for (fn_info.param_types) |param_ty| { if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; @@ -2435,6 +2483,17 @@ pub const DeclGen = struct { try llvm_params.append(llvm_sret_ty.pointerType(0)); } + if (fn_info.return_type.isError() and + dg.module.comp.bin_file.options.error_return_tracing) + { + var ptr_ty_payload: Type.Payload.ElemType = .{ + .base = .{ .tag = .single_mut_pointer }, + .data = dg.object.getStackTraceType(), + }; + const ptr_ty = Type.initPayload(&ptr_ty_payload.base); + try llvm_params.append(try lowerFnParamTy(dg, fn_info.cc, ptr_ty)); + } + for (fn_info.param_types) |param_ty| { if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; @@ -3449,6 +3508,8 @@ pub const FuncGen = struct { llvm_func: *const llvm.Value, + err_ret_trace: ?*const llvm.Value = null, + /// This data structure is used to implement breaking to blocks. blocks: std.AutoHashMapUnmanaged(Air.Inst.Index, struct { parent_bb: *const llvm.BasicBlock, @@ -3678,6 +3739,8 @@ pub const FuncGen = struct { .unwrap_errunion_err => try self.airErrUnionErr(inst, false), .unwrap_errunion_err_ptr => try self.airErrUnionErr(inst, true), .errunion_payload_ptr_set => try self.airErrUnionPayloadPtrSet(inst), + .err_return_trace => try self.airErrReturnTrace(inst), + .set_err_return_trace => try self.airSetErrReturnTrace(inst), .wrap_optional => try self.airWrapOptional(inst), .wrap_errunion_payload => try self.airWrapErrUnionPayload(inst), @@ -3732,6 +3795,12 @@ pub const FuncGen = struct { break :blk ret_ptr; }; + if (fn_info.return_type.isError() and + self.dg.module.comp.bin_file.options.error_return_tracing) + { + try llvm_args.append(self.err_ret_trace.?); + } + for (args) |arg| { const param_ty = self.air.typeOf(arg); if (!param_ty.hasRuntimeBitsIgnoreComptime()) continue; @@ -5149,6 +5218,17 @@ pub const FuncGen = struct { return self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); } + fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { + return self.err_ret_trace.?; + } + + fn airSetErrReturnTrace(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { + const un_op = self.air.instructions.items(.data)[inst].un_op; + const operand = try self.resolveInst(un_op); + self.err_ret_trace = operand; + return null; + } + fn airWrapOptional(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { if (self.liveness.isUnused(inst)) return null; -- cgit v1.2.3 From 66c3988e5eebd423844d5dd20c762d6fefe20adf Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Fri, 22 Apr 2022 23:10:02 +0300 Subject: stage2: disable error return tracing on unsupported targets --- lib/test_runner.zig | 4 ++-- src/Sema.zig | 20 ++++++++++++++++++-- src/arch/aarch64/CodeGen.zig | 12 ++++-------- src/arch/arm/CodeGen.zig | 12 ++++-------- src/arch/riscv64/CodeGen.zig | 12 ++++-------- src/arch/x86_64/CodeGen.zig | 12 ++++-------- src/codegen/c.zig | 24 +----------------------- src/codegen/llvm.zig | 10 +++++----- 8 files changed, 42 insertions(+), 64 deletions(-) (limited to 'src/codegen') diff --git a/lib/test_runner.zig b/lib/test_runner.zig index 4b6c80ac66..5ae05464f2 100644 --- a/lib/test_runner.zig +++ b/lib/test_runner.zig @@ -92,9 +92,9 @@ pub fn main() void { fail_count += 1; progress.log("FAIL ({s})\n", .{@errorName(err)}); if (!have_tty) std.debug.print("FAIL ({s})\n", .{@errorName(err)}); - if (builtin.zig_backend != .stage2_llvm) if (@errorReturnTrace()) |trace| { + if (@errorReturnTrace()) |trace| { std.debug.dumpStackTrace(trace.*); - }; + } test_node.end(); }, } diff --git a/src/Sema.zig b/src/Sema.zig index ab2a59f44a..1801806084 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1412,6 +1412,12 @@ fn analyzeAsType( } pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { + const backend_supports_error_return_tracing = false; + if (!backend_supports_error_return_tracing) { + // TODO implement this feature in all the backends and then delete this branch + return; + } + var err_trace_block = block.makeSubBlock(); err_trace_block.is_comptime = false; defer err_trace_block.instructions.deinit(sema.gpa); @@ -12655,7 +12661,12 @@ fn analyzeRet( return always_noreturn; } - if (sema.fn_ret_ty.isError() and sema.mod.comp.bin_file.options.error_return_tracing) { + // TODO implement this feature in all the backends and then delete this check. + const backend_supports_error_return_tracing = false; + + if (sema.fn_ret_ty.isError() and sema.mod.comp.bin_file.options.error_return_tracing and + backend_supports_error_return_tracing) + { const return_err_fn = try sema.getBuiltin(block, src, "returnError"); const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); @@ -13397,9 +13408,14 @@ fn zirErrorReturnTrace( const unresolved_stack_trace_ty = try sema.getBuiltinType(block, src, "StackTrace"); const stack_trace_ty = try sema.resolveTypeFields(block, src, unresolved_stack_trace_ty); const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty); + + // TODO implement this feature in all the backends and then delete this check. + const backend_supports_error_return_tracing = false; + if (sema.owner_func != null and sema.owner_func.?.calls_or_awaits_errorable_fn and - sema.mod.comp.bin_file.options.error_return_tracing) + sema.mod.comp.bin_file.options.error_return_tracing and + backend_supports_error_return_tracing) { return block.addTy(.err_return_trace, opt_ptr_stack_trace_ty); } diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index 56b7b87499..95a29b840e 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -2333,21 +2333,17 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; + _ = inst; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + return self.finishAir(inst, result, .{ .none, .none, .none }); } fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + _ = inst; + return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { diff --git a/src/arch/arm/CodeGen.zig b/src/arch/arm/CodeGen.zig index f09b37ee69..0154548911 100644 --- a/src/arch/arm/CodeGen.zig +++ b/src/arch/arm/CodeGen.zig @@ -1846,21 +1846,17 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; + _ = inst; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + return self.finishAir(inst, result, .{ .none, .none, .none }); } fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + _ = inst; + return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); } /// T to E!T diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 6d813cfbbb..22c97b9aec 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1270,21 +1270,17 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; + _ = inst; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + return self.finishAir(inst, result, .{ .none, .none, .none }); } fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + _ = inst; + return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 31ecc58c66..bb3ebec5db 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -1858,21 +1858,17 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { } fn airErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; + _ = inst; const result: MCValue = if (self.liveness.isUnused(inst)) .dead else return self.fail("TODO implement airErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + return self.finishAir(inst, result, .{ .none, .none, .none }); } fn airSetErrReturnTrace(self: *Self, inst: Air.Inst.Index) !void { - const ty_op = self.air.instructions.items(.data)[inst].ty_op; - const result: MCValue = if (self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); - return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); + _ = inst; + return self.fail("TODO implement airSetErrReturnTrace for {}", .{self.target.cpu.arch}); } fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void { diff --git a/src/codegen/c.zig b/src/codegen/c.zig index c3ca79dabe..92770168f4 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -3451,33 +3451,11 @@ fn airErrUnionPayloadPtrSet(f: *Function, inst: Air.Inst.Index) !CValue { fn airErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { if (f.liveness.isUnused(inst)) return CValue.none; - - const un_op = f.air.instructions.items(.data)[inst].un_op; - const writer = f.object.writer(); - const inst_ty = f.air.typeOfIndex(inst); - const operand = try f.resolveInst(un_op); - const local = try f.allocLocal(inst_ty, .Const); - - try writer.writeAll(" = "); - - _ = operand; - _ = local; return f.fail("TODO: C backend: implement airErrReturnTrace", .{}); } fn airSetErrReturnTrace(f: *Function, inst: Air.Inst.Index) !CValue { - if (f.liveness.isUnused(inst)) return CValue.none; - - const un_op = f.air.instructions.items(.data)[inst].un_op; - const writer = f.object.writer(); - const inst_ty = f.air.typeOfIndex(inst); - const operand = try f.resolveInst(un_op); - const local = try f.allocLocal(inst_ty, .Const); - - try writer.writeAll(" = "); - - _ = operand; - _ = local; + _ = inst; return f.fail("TODO: C backend: implement airSetErrReturnTrace", .{}); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index dfb0f8f03b..f6bb989f37 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -637,7 +637,7 @@ pub const Object = struct { const gpa = dg.gpa; const err_return_tracing = fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing; + dg.module.comp.bin_file.options.error_return_tracing and false; const err_ret_trace = if (err_return_tracing) llvm_func.getParam(@boolToInt(ret_ptr != null)) @@ -1765,7 +1765,7 @@ pub const Object = struct { } if (fn_info.return_type.isError() and - o.module.comp.bin_file.options.error_return_tracing) + o.module.comp.bin_file.options.error_return_tracing and false) { var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, @@ -2018,7 +2018,7 @@ pub const DeclGen = struct { } const err_return_tracing = fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing; + dg.module.comp.bin_file.options.error_return_tracing and false; if (err_return_tracing) { dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull"); @@ -2484,7 +2484,7 @@ pub const DeclGen = struct { } if (fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing) + dg.module.comp.bin_file.options.error_return_tracing and false) { var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, @@ -3796,7 +3796,7 @@ pub const FuncGen = struct { }; if (fn_info.return_type.isError() and - self.dg.module.comp.bin_file.options.error_return_tracing) + self.dg.module.comp.bin_file.options.error_return_tracing and false) { try llvm_args.append(self.err_ret_trace.?); } -- cgit v1.2.3 From 53a5aee3b3684a03c91236702c9304dce21279e2 Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 23 Apr 2022 09:38:38 +0300 Subject: stage2: enable error return tracing on llvm backend --- src/Compilation.zig | 3 ++- src/Sema.zig | 22 +++++++++++----------- src/codegen/llvm.zig | 13 ++++++++----- 3 files changed, 21 insertions(+), 17 deletions(-) (limited to 'src/codegen') diff --git a/src/Compilation.zig b/src/Compilation.zig index 407c753193..687b0a6dc6 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1457,7 +1457,8 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { errdefer if (module) |zm| zm.deinit(); const error_return_tracing = !strip and switch (options.optimize_mode) { - .Debug, .ReleaseSafe => true, + .Debug, .ReleaseSafe => (!options.target.isWasm() or options.target.os.tag == .emscripten) and + !options.target.cpu.arch.isBpf(), .ReleaseFast, .ReleaseSmall => false, }; diff --git a/src/Sema.zig b/src/Sema.zig index 1801806084..86f06c3ad3 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -1412,7 +1412,8 @@ fn analyzeAsType( } pub fn setupErrorReturnTrace(sema: *Sema, block: *Block, last_arg_index: usize) !void { - const backend_supports_error_return_tracing = false; + const backend_supports_error_return_tracing = + sema.mod.comp.bin_file.options.use_llvm; if (!backend_supports_error_return_tracing) { // TODO implement this feature in all the backends and then delete this branch return; @@ -5275,10 +5276,6 @@ fn analyzeCall( try sema.queueFullTypeResolution(func_ty_info.return_type); if (sema.owner_func != null and func_ty_info.return_type.isError()) { - if (!sema.owner_func.?.calls_or_awaits_errorable_fn) { - // Ensure the type exists so that backends can assume that. - _ = try sema.getBuiltinType(block, call_src, "StackTrace"); - } sema.owner_func.?.calls_or_awaits_errorable_fn = true; } @@ -5692,10 +5689,6 @@ fn instantiateGenericCall( } if (sema.owner_func != null and new_fn_info.return_type.isError()) { - if (!sema.owner_func.?.calls_or_awaits_errorable_fn) { - // Ensure the type exists so that backends can assume that. - _ = try sema.getBuiltinType(block, call_src, "StackTrace"); - } sema.owner_func.?.calls_or_awaits_errorable_fn = true; } @@ -12662,7 +12655,8 @@ fn analyzeRet( } // TODO implement this feature in all the backends and then delete this check. - const backend_supports_error_return_tracing = false; + const backend_supports_error_return_tracing = + sema.mod.comp.bin_file.options.use_llvm; if (sema.fn_ret_ty.isError() and sema.mod.comp.bin_file.options.error_return_tracing and backend_supports_error_return_tracing) @@ -13410,7 +13404,8 @@ fn zirErrorReturnTrace( const opt_ptr_stack_trace_ty = try Type.Tag.optional_single_mut_pointer.create(sema.arena, stack_trace_ty); // TODO implement this feature in all the backends and then delete this check. - const backend_supports_error_return_tracing = false; + const backend_supports_error_return_tracing = + sema.mod.comp.bin_file.options.use_llvm; if (sema.owner_func != null and sema.owner_func.?.calls_or_awaits_errorable_fn and @@ -21966,6 +21961,11 @@ pub fn resolveFnTypes( ) CompileError!void { try sema.resolveTypeFully(block, src, fn_info.return_type); + if (sema.mod.comp.bin_file.options.error_return_tracing and fn_info.return_type.isError()) { + // Ensure the type exists so that backends can assume that. + _ = try sema.getBuiltinType(block, src, "StackTrace"); + } + for (fn_info.param_types) |param_ty| { try sema.resolveTypeFully(block, src, param_ty); } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index f6bb989f37..9998f1d40f 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -637,7 +637,7 @@ pub const Object = struct { const gpa = dg.gpa; const err_return_tracing = fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing and false; + dg.module.comp.bin_file.options.error_return_tracing; const err_ret_trace = if (err_return_tracing) llvm_func.getParam(@boolToInt(ret_ptr != null)) @@ -698,6 +698,9 @@ pub const Object = struct { const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file.?, line_number, 1); di_scope = lexical_block.toScope(); + + // Setup a debug location in case there is a call to `returnError` before a `.dbg_stmt`. + builder.setCurrentDebugLocation(line_number + func.lbrace_line, func.lbrace_column, di_scope.?, null); } var fg: FuncGen = .{ @@ -1765,7 +1768,7 @@ pub const Object = struct { } if (fn_info.return_type.isError() and - o.module.comp.bin_file.options.error_return_tracing and false) + o.module.comp.bin_file.options.error_return_tracing) { var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, @@ -2018,7 +2021,7 @@ pub const DeclGen = struct { } const err_return_tracing = fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing and false; + dg.module.comp.bin_file.options.error_return_tracing; if (err_return_tracing) { dg.addArgAttr(llvm_fn, @boolToInt(sret), "nonnull"); @@ -2484,7 +2487,7 @@ pub const DeclGen = struct { } if (fn_info.return_type.isError() and - dg.module.comp.bin_file.options.error_return_tracing and false) + dg.module.comp.bin_file.options.error_return_tracing) { var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, @@ -3796,7 +3799,7 @@ pub const FuncGen = struct { }; if (fn_info.return_type.isError() and - self.dg.module.comp.bin_file.options.error_return_tracing and false) + self.dg.module.comp.bin_file.options.error_return_tracing) { try llvm_args.append(self.err_ret_trace.?); } -- cgit v1.2.3 From e369752430a1b3a50e57e11b9f0682d026c62feb Mon Sep 17 00:00:00 2001 From: Veikka Tuominen Date: Sat, 23 Apr 2022 14:48:16 +0300 Subject: Sema: do not call `returnError` when returning payload of error union --- src/Module.zig | 2 +- src/Sema.zig | 3 ++- src/codegen/llvm.zig | 3 --- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src/codegen') diff --git a/src/Module.zig b/src/Module.zig index cb38ddba45..11549ccda6 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -4839,7 +4839,7 @@ pub fn analyzeFnBody(mod: *Module, func: *Fn, arena: Allocator) SemaError!Air { }; defer sema.deinit(); - // reset in case case calls to errorable functions are removed. + // reset in case calls to errorable functions are removed. func.calls_or_awaits_errorable_fn = false; // First few indexes of extra are reserved and set at the end. diff --git a/src/Sema.zig b/src/Sema.zig index 86f06c3ad3..a7dd905dd6 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -12658,7 +12658,8 @@ fn analyzeRet( const backend_supports_error_return_tracing = sema.mod.comp.bin_file.options.use_llvm; - if (sema.fn_ret_ty.isError() and sema.mod.comp.bin_file.options.error_return_tracing and + if ((sema.fn_ret_ty.zigTypeTag() == .ErrorSet or sema.typeOf(uncasted_operand).zigTypeTag() == .ErrorUnion) and + sema.mod.comp.bin_file.options.error_return_tracing and backend_supports_error_return_tracing) { const return_err_fn = try sema.getBuiltin(block, src, "returnError"); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 9998f1d40f..dfb0f8f03b 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -698,9 +698,6 @@ pub const Object = struct { const lexical_block = dib.createLexicalBlock(subprogram.toScope(), di_file.?, line_number, 1); di_scope = lexical_block.toScope(); - - // Setup a debug location in case there is a call to `returnError` before a `.dbg_stmt`. - builder.setCurrentDebugLocation(line_number + func.lbrace_line, func.lbrace_column, di_scope.?, null); } var fg: FuncGen = .{ -- cgit v1.2.3