authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-15 16:42:26+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-03-16 09:34:26+02:00
log03438118369605df178f4bfdb5b1a8ad6a349be7
tree27ea1fa1f07ebc7f704f7d00331e08896a0354d9
parent0f112b9f6d390ad4c95b7bf214a8243ad9e3b9a7

Sema: emit dbg_func around inline calls


11 files changed, 134 insertions(+), 2 deletions(-)

src/Air.zig+4-1
......@@ -7,7 +7,6 @@ const std = @import("std");
77const builtin = @import("builtin");
88const Value = @import("value.zig").Value;
99const Type = @import("type.zig").Type;
10const Module = @import("Module.zig");
1110const assert = std.debug.assert;
1211const Air = @This();
1312
......@@ -327,6 +326,9 @@ pub const Inst = struct {
327326 /// Result type is always void.
328327 /// Uses the `dbg_stmt` field.
329328 dbg_stmt,
329 /// Marks change of source function. Emitted around an inline call.
330 /// Uses `ty_pl` with the payload being the index of a Value.Function in air.values.
331 dbg_func,
330332 /// Marks the beginning of a local variable. The operand is a pointer pointing
331333 /// to the storage for the variable. The local may be a const or a var.
332334 /// Result type is always void.
......@@ -971,6 +973,7 @@ pub fn typeOfIndex(air: Air, inst: Air.Inst.Index) Type {
971973
972974 .breakpoint,
973975 .dbg_stmt,
976 .dbg_func,
974977 .dbg_var_ptr,
975978 .dbg_var_val,
976979 .store,
src/Liveness.zig+1
......@@ -314,6 +314,7 @@ fn analyzeInst(
314314 .const_ty,
315315 .breakpoint,
316316 .dbg_stmt,
317 .dbg_func,
317318 .unreach,
318319 .fence,
319320 .ret_addr,
src/Sema.zig+32
......@@ -4639,6 +4639,10 @@ fn analyzeCall(
46394639 // comptime state.
46404640 var should_memoize = true;
46414641
4642 var new_fn_info = module_fn.owner_decl.ty.fnInfo();
4643 new_fn_info.param_types = try sema.arena.alloc(Type, new_fn_info.param_types.len);
4644 new_fn_info.comptime_params = (try sema.arena.alloc(bool, new_fn_info.param_types.len)).ptr;
4645
46424646 // This will have return instructions analyzed as break instructions to
46434647 // the block_inst above. Here we are performing "comptime/inline semantic analysis"
46444648 // for a function body, which means we must map the parameter ZIR instructions to
......@@ -4658,6 +4662,7 @@ fn analyzeCall(
46584662 const param_body = sema.code.extra[extra.end..][0..extra.data.body_len];
46594663 const param_ty_inst = try sema.resolveBody(&child_block, param_body, inst);
46604664 const param_ty = try sema.analyzeAsType(&child_block, param_src, param_ty_inst);
4665 new_fn_info.param_types[arg_i] = param_ty;
46614666 const arg_src = call_src; // TODO: better source location
46624667 const casted_arg = try sema.coerce(&child_block, param_ty, uncasted_args[arg_i], arg_src);
46634668 try sema.inst_map.putNoClobber(gpa, inst, casted_arg);
......@@ -4685,6 +4690,7 @@ fn analyzeCall(
46854690 .param_anytype, .param_anytype_comptime => {
46864691 // No coercion needed.
46874692 const uncasted_arg = uncasted_args[arg_i];
4693 new_fn_info.param_types[arg_i] = sema.typeOf(uncasted_arg);
46884694 try sema.inst_map.putNoClobber(gpa, inst, uncasted_arg);
46894695
46904696 if (is_comptime_call) {
......@@ -4735,6 +4741,7 @@ fn analyzeCall(
47354741 }
47364742 break :blk bare_return_type;
47374743 };
4744 new_fn_info.return_type = fn_ret_ty;
47384745 const parent_fn_ret_ty = sema.fn_ret_ty;
47394746 sema.fn_ret_ty = fn_ret_ty;
47404747 defer sema.fn_ret_ty = parent_fn_ret_ty;
......@@ -4757,6 +4764,9 @@ fn analyzeCall(
47574764 }
47584765 }
47594766
4767 const new_func_resolved_ty = try Type.Tag.function.create(sema.arena, new_fn_info);
4768 if (!is_comptime_call) try sema.emitDbgFunc(block, parent_func.?, module_fn, new_func_resolved_ty);
4769
47604770 const result = result: {
47614771 sema.analyzeBody(&child_block, fn_info.body) catch |err| switch (err) {
47624772 error.ComptimeReturn => break :result inlining.comptime_result,
......@@ -4771,6 +4781,8 @@ fn analyzeCall(
47714781 break :result try sema.analyzeBlockBody(block, call_src, &child_block, merges);
47724782 };
47734783
4784 if (!is_comptime_call) try sema.emitDbgFunc(block, module_fn, parent_func.?, parent_func.?.owner_decl.ty);
4785
47744786 if (should_memoize and is_comptime_call) {
47754787 const result_val = try sema.resolveConstMaybeUndefVal(block, call_src, result);
47764788
......@@ -5175,6 +5187,26 @@ fn instantiateGenericCall(
51755187 return func_inst;
51765188}
51775189
5190fn emitDbgFunc(
5191 sema: *Sema,
5192 block: *Block,
5193 old_func: *Module.Fn,
5194 new_func: *Module.Fn,
5195 new_func_ty: Type,
5196) CompileError!void {
5197 // No change of file; no dbg_func needed.
5198 if (old_func == new_func) return;
5199
5200 try sema.air_values.append(sema.gpa, try Value.Tag.function.create(sema.arena, new_func));
5201 _ = try block.addInst(.{
5202 .tag = .dbg_func,
5203 .data = .{ .ty_pl = .{
5204 .ty = try sema.addType(new_func_ty),
5205 .payload = @intCast(u32, sema.air_values.items.len - 1),
5206 } },
5207 });
5208}
5209
51785210fn zirIntType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
51795211 _ = block;
51805212 const tracy = trace(@src());
src/arch/aarch64/CodeGen.zig+9
......@@ -598,6 +598,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
598598 .fence => try self.airFence(),
599599 .cond_br => try self.airCondBr(inst),
600600 .dbg_stmt => try self.airDbgStmt(inst),
601 .dbg_func => try self.airDbgFunc(inst),
601602 .fptrunc => try self.airFptrunc(inst),
602603 .fpext => try self.airFpext(inst),
603604 .intcast => try self.airIntCast(inst),
......@@ -2715,6 +2716,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
27152716 return self.finishAirBookkeeping();
27162717}
27172718
2719fn airDbgFunc(self: *Self, inst: Air.Inst.Index) !void {
2720 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2721 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
2722 // TODO emit debug info for function change
2723 _ = function;
2724 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2725}
2726
27182727fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
27192728 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
27202729 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/arm/CodeGen.zig+9
......@@ -595,6 +595,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
595595 .fence => try self.airFence(),
596596 .cond_br => try self.airCondBr(inst),
597597 .dbg_stmt => try self.airDbgStmt(inst),
598 .dbg_func => try self.airDbgFunc(inst),
598599 .fptrunc => try self.airFptrunc(inst),
599600 .fpext => try self.airFpext(inst),
600601 .intcast => try self.airIntCast(inst),
......@@ -2835,6 +2836,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
28352836 return self.finishAirBookkeeping();
28362837}
28372838
2839fn airDbgFunc(self: *Self, inst: Air.Inst.Index) !void {
2840 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
2841 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
2842 // TODO emit debug info for function change
2843 _ = function;
2844 return self.finishAir(inst, .dead, .{ .none, .none, .none });
2845}
2846
28382847fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
28392848 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
28402849 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/riscv64/CodeGen.zig+9
......@@ -562,6 +562,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
562562 .fence => try self.airFence(),
563563 .cond_br => try self.airCondBr(inst),
564564 .dbg_stmt => try self.airDbgStmt(inst),
565 .dbg_func => try self.airDbgFunc(inst),
565566 .fptrunc => try self.airFptrunc(inst),
566567 .fpext => try self.airFpext(inst),
567568 .intcast => try self.airIntCast(inst),
......@@ -1640,6 +1641,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
16401641 return self.finishAirBookkeeping();
16411642}
16421643
1644fn airDbgFunc(self: *Self, inst: Air.Inst.Index) !void {
1645 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
1646 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
1647 // TODO emit debug info for function change
1648 _ = function;
1649 return self.finishAir(inst, .dead, .{ .none, .none, .none });
1650}
1651
16431652fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
16441653 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
16451654 const name = self.air.nullTerminatedString(pl_op.payload);
src/arch/wasm/CodeGen.zig+1
......@@ -1227,6 +1227,7 @@ fn genInst(self: *Self, inst: Air.Inst.Index) !WValue {
12271227
12281228 // TODO
12291229 .dbg_stmt,
1230 .dbg_func,
12301231 .dbg_var_ptr,
12311232 .dbg_var_val,
12321233 => WValue.none,
src/arch/x86_64/CodeGen.zig+9
......@@ -679,6 +679,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
679679 .fence => try self.airFence(),
680680 .cond_br => try self.airCondBr(inst),
681681 .dbg_stmt => try self.airDbgStmt(inst),
682 .dbg_func => try self.airDbgFunc(inst),
682683 .fptrunc => try self.airFptrunc(inst),
683684 .fpext => try self.airFpext(inst),
684685 .intcast => try self.airIntCast(inst),
......@@ -3670,6 +3671,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
36703671 return self.finishAirBookkeeping();
36713672}
36723673
3674fn airDbgFunc(self: *Self, inst: Air.Inst.Index) !void {
3675 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
3676 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
3677 // TODO emit debug info for function change
3678 _ = function;
3679 return self.finishAir(inst, .dead, .{ .none, .none, .none });
3680}
3681
36733682fn airDbgVar(self: *Self, inst: Air.Inst.Index) !void {
36743683 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
36753684 const name = self.air.nullTerminatedString(pl_op.payload);
src/codegen/c.zig+9
......@@ -1687,6 +1687,7 @@ fn genBody(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail, OutO
16871687 .block => try airBlock(f, inst),
16881688 .bitcast => try airBitcast(f, inst),
16891689 .dbg_stmt => try airDbgStmt(f, inst),
1690 .dbg_func => try airDbgFunc(f, inst),
16901691 .intcast => try airIntCast(f, inst),
16911692 .trunc => try airTrunc(f, inst),
16921693 .bool_to_int => try airBoolToInt(f, inst),
......@@ -2660,6 +2661,14 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
26602661 return CValue.none;
26612662}
26622663
2664fn airDbgFunc(f: *Function, inst: Air.Inst.Index) !CValue {
2665 const ty_pl = f.air.instructions.items(.data)[inst].ty_pl;
2666 const writer = f.object.writer();
2667 const function = f.air.values[ty_pl.payload].castTag(.function).?.data;
2668 try writer.print("/* dbg func:{s} */\n", .{function.owner_decl.name});
2669 return CValue.none;
2670}
2671
26632672fn airDbgVar(f: *Function, inst: Air.Inst.Index) !CValue {
26642673 const pl_op = f.air.instructions.items(.data)[inst].pl_op;
26652674 const name = f.air.nullTerminatedString(pl_op.payload);
src/codegen/llvm.zig+44-1
......@@ -1754,11 +1754,14 @@ pub const DeclGen = struct {
17541754 /// Note that this can be called before the function's semantic analysis has
17551755 /// completed, so if any attributes rely on that, they must be done in updateFunc, not here.
17561756 fn resolveLlvmFunction(dg: *DeclGen, decl: *Module.Decl) !*const llvm.Value {
1757 return dg.resolveLlvmFunctionExtra(decl, decl.ty);
1758 }
1759
1760 fn resolveLlvmFunctionExtra(dg: *DeclGen, decl: *Module.Decl, zig_fn_type: Type) !*const llvm.Value {
17571761 const gop = try dg.object.decl_map.getOrPut(dg.gpa, decl);
17581762 if (gop.found_existing) return gop.value_ptr.*;
17591763
17601764 assert(decl.has_tv);
1761 const zig_fn_type = decl.ty;
17621765 const fn_info = zig_fn_type.fnInfo();
17631766 const target = dg.module.getTarget();
17641767 const sret = firstParamSRet(fn_info, target);
......@@ -3460,6 +3463,7 @@ pub const FuncGen = struct {
34603463 .const_ty => unreachable,
34613464 .unreach => self.airUnreach(inst),
34623465 .dbg_stmt => self.airDbgStmt(inst),
3466 .dbg_func => try self.airDbgFunc(inst),
34633467 .dbg_var_ptr => try self.airDbgVarPtr(inst),
34643468 .dbg_var_val => try self.airDbgVarVal(inst),
34653469 // zig fmt: on
......@@ -4181,6 +4185,45 @@ pub const FuncGen = struct {
41814185 return null;
41824186 }
41834187
4188 fn airDbgFunc(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
4189 const dib = self.dg.object.di_builder orelse return null;
4190 const ty_pl = self.air.instructions.items(.data)[inst].ty_pl;
4191
4192 const function = self.air.values[ty_pl.payload].castTag(.function).?.data;
4193 const decl = function.owner_decl;
4194 const fn_ty = try self.air.getRefType(ty_pl.ty).copy(self.dg.object.type_map_arena.allocator());
4195 const llvm_func = try self.dg.resolveLlvmFunctionExtra(decl, fn_ty);
4196 const fn_info = fn_ty.fnInfo();
4197 const di_file = try self.dg.object.getDIFile(self.gpa, decl.src_namespace.file_scope);
4198
4199 const line_number = decl.src_line + 1;
4200 const is_internal_linkage = !self.dg.module.decl_exports.contains(decl);
4201 const noret_bit: c_uint = if (fn_info.return_type.isNoReturn())
4202 llvm.DIFlags.NoReturn
4203 else
4204 0;
4205 const subprogram = dib.createFunction(
4206 di_file.toScope(),
4207 decl.name,
4208 llvm_func.getValueName(),
4209 di_file,
4210 line_number,
4211 try self.dg.lowerDebugType(fn_ty),
4212 is_internal_linkage,
4213 true, // is definition
4214 line_number + function.lbrace_line, // scope line
4215 llvm.DIFlags.StaticMember | noret_bit,
4216 self.dg.module.comp.bin_file.options.optimize_mode != .Debug,
4217 null, // decl_subprogram
4218 );
4219 try self.dg.object.di_map.put(self.gpa, decl, subprogram.toNode());
4220
4221 llvm_func.fnSetSubprogram(subprogram);
4222
4223 self.di_scope = subprogram.toScope();
4224 return null;
4225 }
4226
41844227 fn airDbgVarPtr(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
41854228 const dib = self.dg.object.di_builder orelse return null;
41864229 const pl_op = self.air.instructions.items(.data)[inst].pl_op;
src/print_air.zig+7
......@@ -242,6 +242,7 @@ const Writer = struct {
242242 .constant => try w.writeConstant(s, inst),
243243 .assembly => try w.writeAssembly(s, inst),
244244 .dbg_stmt => try w.writeDbgStmt(s, inst),
245 .dbg_func => try w.writeDbgFunc(s, inst),
245246 .aggregate_init => try w.writeAggregateInit(s, inst),
246247 .union_init => try w.writeUnionInit(s, inst),
247248 .br => try w.writeBr(s, inst),
......@@ -552,6 +553,12 @@ const Writer = struct {
552553 try s.print("{d}:{d}", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 });
553554 }
554555
556 fn writeDbgFunc(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
557 const ty_pl = w.air.instructions.items(.data)[inst].ty_pl;
558 const function = w.air.values[ty_pl.payload].castTag(.function).?.data;
559 try s.print("{s}", .{function.owner_decl.name});
560 }
561
555562 fn writeDbgVar(w: *Writer, s: anytype, inst: Air.Inst.Index) @TypeOf(s).Error!void {
556563 const pl_op = w.air.instructions.items(.data)[inst].pl_op;
557564 try w.writeOperand(s, inst, 0, pl_op.operand);