| ... | ... | @@ -6,6 +6,7 @@ const std = @import("std"); |
| 6 | 6 | const Mir = @import("Mir.zig"); |
| 7 | 7 | const link = @import("../../link.zig"); |
| 8 | 8 | const Module = @import("../../Module.zig"); |
| 9 | const codegen = @import("../../codegen.zig"); |
| 9 | 10 | const leb128 = std.leb; |
| 10 | 11 | |
| 11 | 12 | /// Contains our list of instructions |
| ... | ... | @@ -22,6 +23,16 @@ locals: []const u8, |
| 22 | 23 | /// The declaration that code is being generated for. |
| 23 | 24 | decl: *Module.Decl, |
| 24 | 25 | |
| 26 | // Debug information |
| 27 | /// Holds the debug information for this emission |
| 28 | dbg_output: codegen.DebugInfoOutput, |
| 29 | /// Previous debug info line |
| 30 | prev_di_line: u32, |
| 31 | /// Previous debug info column |
| 32 | prev_di_column: u32, |
| 33 | /// Previous offset relative to code section |
| 34 | prev_di_offset: u32, |
| 35 | |
| 25 | 36 | const InnerError = error{ |
| 26 | 37 | OutOfMemory, |
| 27 | 38 | EmitFail, |
| ... | ... | @@ -40,6 +51,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 40 | 51 | .block => try emit.emitBlock(tag, inst), |
| 41 | 52 | .loop => try emit.emitBlock(tag, inst), |
| 42 | 53 | |
| 54 | .dbg_line => try emit.emitDbgLine(inst), |
| 55 | .dbg_epilogue_begin => try emit.emitDbgEpilogueBegin(), |
| 56 | .dbg_prologue_end => try emit.emitDbgPrologueEnd(), |
| 57 | |
| 43 | 58 | // branch instructions |
| 44 | 59 | .br_if => try emit.emitLabel(tag, inst), |
| 45 | 60 | .br_table => try emit.emitBrTable(inst), |
| ... | ... | @@ -419,3 +434,43 @@ fn emitMemFill(emit: *Emit) !void { |
| 419 | 434 | // For now we will always emit index 0. |
| 420 | 435 | try leb128.writeULEB128(emit.code.writer(), @as(u32, 0)); |
| 421 | 436 | } |
| 437 | |
| 438 | fn emitDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 439 | const extra_index = emit.mir.instructions.items(.data)[inst].payload; |
| 440 | const dbg_line = emit.mir.extraData(Mir.DbgLineColumn, extra_index).data; |
| 441 | try emit.dbgAdvancePCAndLine(dbg_line.line, dbg_line.column); |
| 442 | } |
| 443 | |
| 444 | fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void { |
| 445 | if (emit.dbg_output != .dwarf) return; |
| 446 | |
| 447 | const dbg_line = &emit.dbg_output.dwarf.dbg_line; |
| 448 | try dbg_line.ensureUnusedCapacity(11); |
| 449 | dbg_line.appendAssumeCapacity(std.dwarf.LNS.advance_pc); |
| 450 | // TODO: This must emit a relocation to calculate the offset relative |
| 451 | // to the code section start. |
| 452 | leb128.writeULEB128(dbg_line.writer(), emit.offset() - emit.prev_di_offset) catch unreachable; |
| 453 | const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line); |
| 454 | if (delta_line != 0) { |
| 455 | dbg_line.appendAssumeCapacity(std.dwarf.LNS.advance_line); |
| 456 | leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable; |
| 457 | } |
| 458 | dbg_line.appendAssumeCapacity(std.dwarf.LNS.copy); |
| 459 | emit.prev_di_line = line; |
| 460 | emit.prev_di_column = column; |
| 461 | emit.prev_di_offset = emit.offset(); |
| 462 | } |
| 463 | |
| 464 | fn emitDbgPrologueEnd(emit: *Emit) !void { |
| 465 | if (emit.dbg_output != .dwarf) return; |
| 466 | |
| 467 | try emit.dbg_output.dwarf.dbg_line.append(std.dwarf.LNS.set_prologue_end); |
| 468 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 469 | } |
| 470 | |
| 471 | fn emitDbgEpilogueBegin(emit: *Emit) !void { |
| 472 | if (emit.dbg_output != .dwarf) return; |
| 473 | |
| 474 | try emit.dbg_output.dwarf.dbg_line.append(std.dwarf.LNS.set_epilogue_begin); |
| 475 | try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column); |
| 476 | } |