authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-02 21:28:06-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-02 21:28:06-07:00
log659603c6211e5628db0ab0dd9b1e8454ed1b69c6
treeb289d736f4ac0956dec00b72ca6e1ac0af4c9855
parent42d331b58aa874420d2515071e94f046adaf0689

codegen: emit .debug_line ops for IR instructions


7 files changed, 159 insertions(+), 66 deletions(-)

lib/std/zig.zig+9
...@@ -43,6 +43,15 @@ pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usi...@@ -43,6 +43,15 @@ pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usi
43 return .{ .line = line, .column = column };43 return .{ .line = line, .column = column };
44}44}
4545
46pub fn lineDelta(source: []const u8, start: usize, end: usize) usize {
47 var line: usize = 0;
48 for (source[start..end]) |byte| switch (byte) {
49 '\n' => line += 1,
50 else => continue,
51 };
52 return line;
53}
54
46/// Returns the standard file system basename of a binary generated by the Zig compiler.55/// Returns the standard file system basename of a binary generated by the Zig compiler.
47pub fn binNameAlloc(56pub fn binNameAlloc(
48 allocator: *std.mem.Allocator,57 allocator: *std.mem.Allocator,
src-self-hosted/astgen.zig+2-1
...@@ -120,6 +120,8 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block...@@ -120,6 +120,8 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
120120
121 var scope = parent_scope;121 var scope = parent_scope;
122 for (block_node.statements()) |statement| {122 for (block_node.statements()) |statement| {
123 const src = scope.tree().token_locs[statement.firstToken()].start;
124 _ = try addZIRNoOp(mod, scope, src, .dbg_stmt);
123 switch (statement.tag) {125 switch (statement.tag) {
124 .VarDecl => {126 .VarDecl => {
125 const var_decl_node = statement.castTag(.VarDecl).?;127 const var_decl_node = statement.castTag(.VarDecl).?;
...@@ -146,7 +148,6 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block...@@ -146,7 +148,6 @@ pub fn blockExpr(mod: *Module, parent_scope: *Scope, block_node: *ast.Node.Block
146 else => {148 else => {
147 const possibly_unused_result = try expr(mod, scope, .none, statement);149 const possibly_unused_result = try expr(mod, scope, .none, statement);
148 if (!possibly_unused_result.tag.isNoReturn()) {150 if (!possibly_unused_result.tag.isNoReturn()) {
149 const src = scope.tree().token_locs[statement.firstToken()].start;
150 _ = try addZIRUnOp(mod, scope, src, .ensure_result_used, possibly_unused_result);151 _ = try addZIRUnOp(mod, scope, src, .ensure_result_used, possibly_unused_result);
151 }152 }
152 },153 },
src-self-hosted/codegen.zig+128-61
...@@ -12,6 +12,11 @@ const ErrorMsg = Module.ErrorMsg;...@@ -12,6 +12,11 @@ const ErrorMsg = Module.ErrorMsg;
12const Target = std.Target;12const Target = std.Target;
13const Allocator = mem.Allocator;13const Allocator = mem.Allocator;
14const trace = @import("tracy.zig").trace;14const trace = @import("tracy.zig").trace;
15const DW = std.dwarf;
16const leb128 = std.debug.leb;
17
18// TODO Turn back on zig fmt when https://github.com/ziglang/zig/issues/5948 is implemented.
19// zig fmt: off
1520
16/// The codegen-related data that is stored in `ir.Inst.Block` instructions.21/// The codegen-related data that is stored in `ir.Inst.Block` instructions.
17pub const BlockData = struct {22pub const BlockData = struct {
...@@ -52,57 +57,57 @@ pub fn generateSymbol(...@@ -52,57 +57,57 @@ pub fn generateSymbol(
52 switch (typed_value.ty.zigTypeTag()) {57 switch (typed_value.ty.zigTypeTag()) {
53 .Fn => {58 .Fn => {
54 switch (bin_file.base.options.target.cpu.arch) {59 switch (bin_file.base.options.target.cpu.arch) {
55 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code),60 //.arm => return Function(.arm).generateSymbol(bin_file, src, typed_value, code, dbg_line),
56 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code),61 //.armeb => return Function(.armeb).generateSymbol(bin_file, src, typed_value, code, dbg_line),
57 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code),62 //.aarch64 => return Function(.aarch64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
58 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code),63 //.aarch64_be => return Function(.aarch64_be).generateSymbol(bin_file, src, typed_value, code, dbg_line),
59 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code),64 //.aarch64_32 => return Function(.aarch64_32).generateSymbol(bin_file, src, typed_value, code, dbg_line),
60 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code),65 //.arc => return Function(.arc).generateSymbol(bin_file, src, typed_value, code, dbg_line),
61 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code),66 //.avr => return Function(.avr).generateSymbol(bin_file, src, typed_value, code, dbg_line),
62 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code),67 //.bpfel => return Function(.bpfel).generateSymbol(bin_file, src, typed_value, code, dbg_line),
63 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code),68 //.bpfeb => return Function(.bpfeb).generateSymbol(bin_file, src, typed_value, code, dbg_line),
64 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code),69 //.hexagon => return Function(.hexagon).generateSymbol(bin_file, src, typed_value, code, dbg_line),
65 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code),70 //.mips => return Function(.mips).generateSymbol(bin_file, src, typed_value, code, dbg_line),
66 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code),71 //.mipsel => return Function(.mipsel).generateSymbol(bin_file, src, typed_value, code, dbg_line),
67 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code),72 //.mips64 => return Function(.mips64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
68 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code),73 //.mips64el => return Function(.mips64el).generateSymbol(bin_file, src, typed_value, code, dbg_line),
69 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code),74 //.msp430 => return Function(.msp430).generateSymbol(bin_file, src, typed_value, code, dbg_line),
70 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code),75 //.powerpc => return Function(.powerpc).generateSymbol(bin_file, src, typed_value, code, dbg_line),
71 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code),76 //.powerpc64 => return Function(.powerpc64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
72 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code),77 //.powerpc64le => return Function(.powerpc64le).generateSymbol(bin_file, src, typed_value, code, dbg_line),
73 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code),78 //.r600 => return Function(.r600).generateSymbol(bin_file, src, typed_value, code, dbg_line),
74 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code),79 //.amdgcn => return Function(.amdgcn).generateSymbol(bin_file, src, typed_value, code, dbg_line),
75 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code),80 //.riscv32 => return Function(.riscv32).generateSymbol(bin_file, src, typed_value, code, dbg_line),
76 //.riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code),81 //.riscv64 => return Function(.riscv64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
77 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code),82 //.sparc => return Function(.sparc).generateSymbol(bin_file, src, typed_value, code, dbg_line),
78 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code),83 //.sparcv9 => return Function(.sparcv9).generateSymbol(bin_file, src, typed_value, code, dbg_line),
79 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code),84 //.sparcel => return Function(.sparcel).generateSymbol(bin_file, src, typed_value, code, dbg_line),
80 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code),85 //.s390x => return Function(.s390x).generateSymbol(bin_file, src, typed_value, code, dbg_line),
81 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code),86 //.tce => return Function(.tce).generateSymbol(bin_file, src, typed_value, code, dbg_line),
82 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code),87 //.tcele => return Function(.tcele).generateSymbol(bin_file, src, typed_value, code, dbg_line),
83 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code),88 //.thumb => return Function(.thumb).generateSymbol(bin_file, src, typed_value, code, dbg_line),
84 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code),89 //.thumbeb => return Function(.thumbeb).generateSymbol(bin_file, src, typed_value, code, dbg_line),
85 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code),90 //.i386 => return Function(.i386).generateSymbol(bin_file, src, typed_value, code, dbg_line),
86 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code),91 .x86_64 => return Function(.x86_64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
87 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code),92 //.xcore => return Function(.xcore).generateSymbol(bin_file, src, typed_value, code, dbg_line),
88 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code),93 //.nvptx => return Function(.nvptx).generateSymbol(bin_file, src, typed_value, code, dbg_line),
89 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code),94 //.nvptx64 => return Function(.nvptx64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
90 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code),95 //.le32 => return Function(.le32).generateSymbol(bin_file, src, typed_value, code, dbg_line),
91 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code),96 //.le64 => return Function(.le64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
92 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code),97 //.amdil => return Function(.amdil).generateSymbol(bin_file, src, typed_value, code, dbg_line),
93 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code),98 //.amdil64 => return Function(.amdil64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
94 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code),99 //.hsail => return Function(.hsail).generateSymbol(bin_file, src, typed_value, code, dbg_line),
95 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code),100 //.hsail64 => return Function(.hsail64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
96 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code),101 //.spir => return Function(.spir).generateSymbol(bin_file, src, typed_value, code, dbg_line),
97 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code),102 //.spir64 => return Function(.spir64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
98 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code),103 //.kalimba => return Function(.kalimba).generateSymbol(bin_file, src, typed_value, code, dbg_line),
99 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code),104 //.shave => return Function(.shave).generateSymbol(bin_file, src, typed_value, code, dbg_line),
100 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code),105 //.lanai => return Function(.lanai).generateSymbol(bin_file, src, typed_value, code, dbg_line),
101 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code),106 //.wasm32 => return Function(.wasm32).generateSymbol(bin_file, src, typed_value, code, dbg_line),
102 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code),107 //.wasm64 => return Function(.wasm64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
103 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code),108 //.renderscript32 => return Function(.renderscript32).generateSymbol(bin_file, src, typed_value, code, dbg_line),
104 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code),109 //.renderscript64 => return Function(.renderscript64).generateSymbol(bin_file, src, typed_value, code, dbg_line),
105 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code),110 //.ve => return Function(.ve).generateSymbol(bin_file, src, typed_value, code, dbg_line),
106 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),111 else => @panic("Backend architectures that don't have good support yet are commented out, to improve compilation performance. If you are interested in one of these other backends feel free to uncomment them. Eventually these will be completed, but stage1 is slow and a memory hog."),
107 }112 }
108 },113 },
...@@ -207,6 +212,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -207,6 +212,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
207 target: *const std.Target,212 target: *const std.Target,
208 mod_fn: *const Module.Fn,213 mod_fn: *const Module.Fn,
209 code: *std.ArrayList(u8),214 code: *std.ArrayList(u8),
215 dbg_line: *std.ArrayList(u8),
210 err_msg: ?*ErrorMsg,216 err_msg: ?*ErrorMsg,
211 args: []MCValue,217 args: []MCValue,
212 ret_mcv: MCValue,218 ret_mcv: MCValue,
...@@ -215,6 +221,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -215,6 +221,15 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
215 src: usize,221 src: usize,
216 stack_align: u32,222 stack_align: u32,
217223
224 /// Byte offset within the source file.
225 prev_di_src: usize,
226 /// Relative to the beginning of `code`.
227 prev_di_pc: usize,
228 /// Used to find newlines and count line deltas.
229 source: []const u8,
230 /// Byte offset within the source file of the ending curly.
231 rbrace_src: usize,
232
218 /// The value is an offset into the `Function` `code` from the beginning.233 /// The value is an offset into the `Function` `code` from the beginning.
219 /// To perform the reloc, write 32-bit signed little-endian integer234 /// To perform the reloc, write 32-bit signed little-endian integer
220 /// which is a relative jump, based on the address following the reloc.235 /// which is a relative jump, based on the address following the reloc.
...@@ -366,6 +381,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -366,6 +381,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
366 src: usize,381 src: usize,
367 typed_value: TypedValue,382 typed_value: TypedValue,
368 code: *std.ArrayList(u8),383 code: *std.ArrayList(u8),
384 dbg_line: *std.ArrayList(u8),
369 ) GenerateSymbolError!Result {385 ) GenerateSymbolError!Result {
370 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;386 const module_fn = typed_value.val.cast(Value.Payload.Function).?.func;
371387
...@@ -380,12 +396,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -380,12 +396,20 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
380 const branch = try branch_stack.addOne();396 const branch = try branch_stack.addOne();
381 branch.* = .{};397 branch.* = .{};
382398
399 const scope_file = module_fn.owner_decl.scope.cast(Module.Scope.File).?;
400 const tree = scope_file.contents.tree;
401 const fn_proto = tree.root_node.decls()[module_fn.owner_decl.src_index].castTag(.FnProto).?;
402 const block = fn_proto.body().?.castTag(.Block).?;
403 const lbrace_src = tree.token_locs[block.lbrace].start;
404 const rbrace_src = tree.token_locs[block.rbrace].start;
405
383 var function = Self{406 var function = Self{
384 .gpa = bin_file.allocator,407 .gpa = bin_file.allocator,
385 .target = &bin_file.base.options.target,408 .target = &bin_file.base.options.target,
386 .bin_file = bin_file,409 .bin_file = bin_file,
387 .mod_fn = module_fn,410 .mod_fn = module_fn,
388 .code = code,411 .code = code,
412 .dbg_line = dbg_line,
389 .err_msg = null,413 .err_msg = null,
390 .args = undefined, // populated after `resolveCallingConventionValues`414 .args = undefined, // populated after `resolveCallingConventionValues`
391 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`415 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
...@@ -394,6 +418,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -394,6 +418,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
394 .branch_stack = &branch_stack,418 .branch_stack = &branch_stack,
395 .src = src,419 .src = src,
396 .stack_align = undefined,420 .stack_align = undefined,
421 .prev_di_pc = 0,
422 .prev_di_src = lbrace_src,
423 .rbrace_src = rbrace_src,
424 .source = tree.source,
397 };425 };
398 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);426 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
399427
...@@ -432,21 +460,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -432,21 +460,16 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
432 // TODO During semantic analysis, check if there are no function calls. If there460 // TODO During semantic analysis, check if there are no function calls. If there
433 // are none, here we can omit the part where we subtract and then add rsp.461 // are none, here we can omit the part where we subtract and then add rsp.
434 self.code.appendSliceAssumeCapacity(&[_]u8{462 self.code.appendSliceAssumeCapacity(&[_]u8{
435 // push rbp463 0x55, // push rbp
436 0x55,464 0x48, 0x89, 0xe5, // mov rbp, rsp
437 // mov rbp, rsp465 0x48, 0x81, 0xec, // sub rsp, imm32 (with reloc)
438 0x48,
439 0x89,
440 0xe5,
441 // sub rsp, imm32 (with reloc)
442 0x48,
443 0x81,
444 0xec,
445 });466 });
446 const reloc_index = self.code.items.len;467 const reloc_index = self.code.items.len;
447 self.code.items.len += 4;468 self.code.items.len += 4;
448469
470 try self.dbgSetPrologueEnd();
449 try self.genBody(self.mod_fn.analysis.success);471 try self.genBody(self.mod_fn.analysis.success);
472 try self.dbgSetEpilogueBegin();
450473
451 const stack_end = self.branch_stack.items[0].max_end_stack;474 const stack_end = self.branch_stack.items[0].max_end_stack;
452 if (stack_end > math.maxInt(i32))475 if (stack_end > math.maxInt(i32))
...@@ -486,13 +509,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -486,13 +509,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
486 0xc3, // ret509 0xc3, // ret
487 });510 });
488 } else {511 } else {
512 try self.dbgSetPrologueEnd();
489 try self.genBody(self.mod_fn.analysis.success);513 try self.genBody(self.mod_fn.analysis.success);
514 try self.dbgSetEpilogueBegin();
490 }515 }
491 },516 },
492 else => {517 else => {
518 try self.dbgSetPrologueEnd();
493 try self.genBody(self.mod_fn.analysis.success);519 try self.genBody(self.mod_fn.analysis.success);
520 try self.dbgSetEpilogueBegin();
494 },521 },
495 }522 }
523 // Drop them off at the rbrace.
524 try self.dbgAdvancePCAndLine(self.rbrace_src);
496 }525 }
497526
498 fn genBody(self: *Self, body: ir.Body) InnerError!void {527 fn genBody(self: *Self, body: ir.Body) InnerError!void {
...@@ -509,6 +538,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -509,6 +538,38 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
509 }538 }
510 }539 }
511540
541 fn dbgSetPrologueEnd(self: *Self) InnerError!void {
542 try self.dbg_line.append(DW.LNS_set_prologue_end);
543 try self.dbgAdvancePCAndLine(self.prev_di_src);
544 }
545
546 fn dbgSetEpilogueBegin(self: *Self) InnerError!void {
547 try self.dbg_line.append(DW.LNS_set_epilogue_begin);
548 try self.dbgAdvancePCAndLine(self.prev_di_src);
549 }
550
551 fn dbgAdvancePCAndLine(self: *Self, src: usize) InnerError!void {
552 // TODO Look into improving the performance here by adding a token-index-to-line
553 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
554 // this involves scanning over the source code for newlines
555 // (but only from the previous byte offset to the new one).
556 const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, src);
557 const delta_pc = self.code.items.len - self.prev_di_pc;
558 self.prev_di_src = src;
559 self.prev_di_pc = self.code.items.len;
560 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit
561 // single-byte opcodes that add different numbers to both the PC and the line number
562 // at the same time.
563 try self.dbg_line.ensureCapacity(self.dbg_line.items.len + 11);
564 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);
565 leb128.writeULEB128(self.dbg_line.writer(), delta_pc) catch unreachable;
566 if (delta_line != 0) {
567 self.dbg_line.appendAssumeCapacity(DW.LNS_advance_line);
568 leb128.writeULEB128(self.dbg_line.writer(), delta_line) catch unreachable;
569 }
570 self.dbg_line.appendAssumeCapacity(DW.LNS_copy);
571 }
572
512 fn processDeath(self: *Self, inst: *ir.Inst) void {573 fn processDeath(self: *Self, inst: *ir.Inst) void {
513 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];574 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
514 const entry = branch.inst_table.getEntry(inst) orelse return;575 const entry = branch.inst_table.getEntry(inst) orelse return;
...@@ -544,6 +605,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -544,6 +605,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
544 .cmp_neq => return self.genCmp(inst.castTag(.cmp_neq).?, .neq),605 .cmp_neq => return self.genCmp(inst.castTag(.cmp_neq).?, .neq),
545 .condbr => return self.genCondBr(inst.castTag(.condbr).?),606 .condbr => return self.genCondBr(inst.castTag(.condbr).?),
546 .constant => unreachable, // excluded from function bodies607 .constant => unreachable, // excluded from function bodies
608 .dbg_stmt => return self.genDbgStmt(inst.castTag(.dbg_stmt).?),
547 .floatcast => return self.genFloatCast(inst.castTag(.floatcast).?),609 .floatcast => return self.genFloatCast(inst.castTag(.floatcast).?),
548 .intcast => return self.genIntCast(inst.castTag(.intcast).?),610 .intcast => return self.genIntCast(inst.castTag(.intcast).?),
549 .isnonnull => return self.genIsNonNull(inst.castTag(.isnonnull).?),611 .isnonnull => return self.genIsNonNull(inst.castTag(.isnonnull).?),
...@@ -1107,6 +1169,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -1107,6 +1169,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1107 }1169 }
1108 }1170 }
11091171
1172 fn genDbgStmt(self: *Self, inst: *ir.Inst.NoOp) !MCValue {
1173 try self.dbgAdvancePCAndLine(inst.base.src);
1174 return MCValue.none;
1175 }
1176
1110 fn genCondBr(self: *Self, inst: *ir.Inst.CondBr) !MCValue {1177 fn genCondBr(self: *Self, inst: *ir.Inst.CondBr) !MCValue {
1111 switch (arch) {1178 switch (arch) {
1112 .x86_64 => {1179 .x86_64 => {
src-self-hosted/ir.zig+2
...@@ -65,6 +65,7 @@ pub const Inst = struct {...@@ -65,6 +65,7 @@ pub const Inst = struct {
65 cmp_neq,65 cmp_neq,
66 condbr,66 condbr,
67 constant,67 constant,
68 dbg_stmt,
68 isnonnull,69 isnonnull,
69 isnull,70 isnull,
70 /// Read a value from a pointer.71 /// Read a value from a pointer.
...@@ -88,6 +89,7 @@ pub const Inst = struct {...@@ -88,6 +89,7 @@ pub const Inst = struct {
88 .unreach,89 .unreach,
89 .arg,90 .arg,
90 .breakpoint,91 .breakpoint,
92 .dbg_stmt,
91 => NoOp,93 => NoOp,
9294
93 .ref,95 .ref,
src-self-hosted/link.zig+7-4
...@@ -2024,9 +2024,9 @@ pub const File = struct {...@@ -2024,9 +2024,9 @@ pub const File = struct {
2024 // line number of the open curly from the beginning of the file.2024 // line number of the open curly from the beginning of the file.
2025 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;2025 const fn_proto = file_ast_decls[decl.src_index].castTag(.FnProto).?;
2026 const block = fn_proto.body().?.castTag(.Block).?;2026 const block = fn_proto.body().?.castTag(.Block).?;
2027 const loc = tree.tokenLocation(0, block.lbrace);2027 const line_delta = std.zig.lineDelta(tree.source, 0, tree.token_locs[block.lbrace].start);
2028 // No need to add one; this is a delta from DWARF's starting line number (1).2028 // No need to add one; this is a delta from DWARF's starting line number (1).
2029 break :blk @intCast(u28, loc.line);2029 break :blk @intCast(u28, line_delta);
2030 } else {2030 } else {
2031 const prev_src_fn = src_file.fns.entries.items[src_fn_index - 1].key;2031 const prev_src_fn = src_file.fns.entries.items[src_fn_index - 1].key;
2032 const mod_fn = @fieldParentPtr(Module.Fn, "link", prev_src_fn);2032 const mod_fn = @fieldParentPtr(Module.Fn, "link", prev_src_fn);
...@@ -2035,9 +2035,12 @@ pub const File = struct {...@@ -2035,9 +2035,12 @@ pub const File = struct {
2035 const prev_block = prev_fn_proto.body().?.castTag(.Block).?;2035 const prev_block = prev_fn_proto.body().?.castTag(.Block).?;
2036 const this_block = this_fn_proto.body().?.castTag(.Block).?;2036 const this_block = this_fn_proto.body().?.castTag(.Block).?;
2037 // Find the difference between prev decl end curly and this decl begin curly.2037 // Find the difference between prev decl end curly and this decl begin curly.
2038 const loc = tree.tokenLocation(tree.token_locs[prev_block.rbrace].start, this_block.lbrace);2038 const line_delta = std.zig.lineDelta(tree.source,
2039 tree.token_locs[prev_block.rbrace].start,
2040 tree.token_locs[this_block.lbrace].start,
2041 );
2039 // No need to add one; this is a delta from the previous line number.2042 // No need to add one; this is a delta from the previous line number.
2040 break :blk @intCast(u28, loc.line);2043 break :blk @intCast(u28, line_delta);
2041 }2044 }
2042 };2045 };
20432046
src-self-hosted/zir.zig+5
...@@ -107,6 +107,8 @@ pub const Inst = struct {...@@ -107,6 +107,8 @@ pub const Inst = struct {
107 condbr,107 condbr,
108 /// Special case, has no textual representation.108 /// Special case, has no textual representation.
109 @"const",109 @"const",
110 /// Declares the beginning of a statement. Used for debug info.
111 dbg_stmt,
110 /// Represents a pointer to a global decl by name.112 /// Represents a pointer to a global decl by name.
111 declref,113 declref,
112 /// Represents a pointer to a global decl by string name.114 /// Represents a pointer to a global decl by string name.
...@@ -211,6 +213,7 @@ pub const Inst = struct {...@@ -211,6 +213,7 @@ pub const Inst = struct {
211 return switch (tag) {213 return switch (tag) {
212 .arg,214 .arg,
213 .breakpoint,215 .breakpoint,
216 .dbg_stmt,
214 .returnvoid,217 .returnvoid,
215 .alloc_inferred,218 .alloc_inferred,
216 .ret_ptr,219 .ret_ptr,
...@@ -324,6 +327,7 @@ pub const Inst = struct {...@@ -324,6 +327,7 @@ pub const Inst = struct {
324 .coerce_result_block_ptr,327 .coerce_result_block_ptr,
325 .coerce_to_ptr_elem,328 .coerce_to_ptr_elem,
326 .@"const",329 .@"const",
330 .dbg_stmt,
327 .declref,331 .declref,
328 .declref_str,332 .declref_str,
329 .declval,333 .declval,
...@@ -1843,6 +1847,7 @@ const EmitZIR = struct {...@@ -1843,6 +1847,7 @@ const EmitZIR = struct {
1843 .breakpoint => try self.emitNoOp(inst.src, .breakpoint),1847 .breakpoint => try self.emitNoOp(inst.src, .breakpoint),
1844 .unreach => try self.emitNoOp(inst.src, .@"unreachable"),1848 .unreach => try self.emitNoOp(inst.src, .@"unreachable"),
1845 .retvoid => try self.emitNoOp(inst.src, .returnvoid),1849 .retvoid => try self.emitNoOp(inst.src, .returnvoid),
1850 .dbg_stmt => try self.emitNoOp(inst.src, .dbg_stmt),
18461851
1847 .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot),1852 .not => try self.emitUnOp(inst.src, new_body, inst.castTag(.not).?, .boolnot),
1848 .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"),1853 .ret => try self.emitUnOp(inst.src, new_body, inst.castTag(.ret).?, .@"return"),
src-self-hosted/zir_sema.zig+6
...@@ -41,6 +41,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -41,6 +41,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
41 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),41 .coerce_to_ptr_elem => return analyzeInstCoerceToPtrElem(mod, scope, old_inst.castTag(.coerce_to_ptr_elem).?),
42 .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),42 .compileerror => return analyzeInstCompileError(mod, scope, old_inst.castTag(.compileerror).?),
43 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),43 .@"const" => return analyzeInstConst(mod, scope, old_inst.castTag(.@"const").?),
44 .dbg_stmt => return analyzeInstDbgStmt(mod, scope, old_inst.castTag(.dbg_stmt).?),
44 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),45 .declref => return analyzeInstDeclRef(mod, scope, old_inst.castTag(.declref).?),
45 .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?),46 .declref_str => return analyzeInstDeclRefStr(mod, scope, old_inst.castTag(.declref_str).?),
46 .declval => return analyzeInstDeclVal(mod, scope, old_inst.castTag(.declval).?),47 .declval => return analyzeInstDeclVal(mod, scope, old_inst.castTag(.declval).?),
...@@ -487,6 +488,11 @@ fn analyzeInstBreakVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid)...@@ -487,6 +488,11 @@ fn analyzeInstBreakVoid(mod: *Module, scope: *Scope, inst: *zir.Inst.BreakVoid)
487 return analyzeBreak(mod, scope, inst.base.src, block, void_inst);488 return analyzeBreak(mod, scope, inst.base.src, block, void_inst);
488}489}
489490
491fn analyzeInstDbgStmt(mod: *Module, scope: *Scope, inst: *zir.Inst.NoOp) InnerError!*Inst {
492 const b = try mod.requireRuntimeBlock(scope, inst.base.src);
493 return mod.addNoOp(b, inst.base.src, Type.initTag(.void), .dbg_stmt);
494}
495
490fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {496fn analyzeInstDeclRefStr(mod: *Module, scope: *Scope, inst: *zir.Inst.DeclRefStr) InnerError!*Inst {
491 const decl_name = try resolveConstString(mod, scope, inst.positionals.name);497 const decl_name = try resolveConstString(mod, scope, inst.positionals.name);
492 return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);498 return mod.analyzeDeclRefByName(scope, inst.base.src, decl_name);