| ... | @@ -6,6 +6,7 @@ const std = @import("std"); | ... | @@ -6,6 +6,7 @@ const std = @import("std"); |
| 6 | const Mir = @import("Mir.zig"); | 6 | const Mir = @import("Mir.zig"); |
| 7 | const link = @import("../../link.zig"); | 7 | const link = @import("../../link.zig"); |
| 8 | const Module = @import("../../Module.zig"); | 8 | const Module = @import("../../Module.zig"); |
| | 9 | const codegen = @import("../../codegen.zig"); |
| 9 | const leb128 = std.leb; | 10 | const leb128 = std.leb; |
| 10 | | 11 | |
| 11 | /// Contains our list of instructions | 12 | /// Contains our list of instructions |
| ... | @@ -22,6 +23,16 @@ locals: []const u8, | ... | @@ -22,6 +23,16 @@ locals: []const u8, |
| 22 | /// The declaration that code is being generated for. | 23 | /// The declaration that code is being generated for. |
| 23 | decl: *Module.Decl, | 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 | const InnerError = error{ | 36 | const InnerError = error{ |
| 26 | OutOfMemory, | 37 | OutOfMemory, |
| 27 | EmitFail, | 38 | EmitFail, |
| ... | @@ -40,6 +51,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { | ... | @@ -40,6 +51,10 @@ pub fn emitMir(emit: *Emit) InnerError!void { |
| 40 | .block => try emit.emitBlock(tag, inst), | 51 | .block => try emit.emitBlock(tag, inst), |
| 41 | .loop => try emit.emitBlock(tag, inst), | 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 | // branch instructions | 58 | // branch instructions |
| 44 | .br_if => try emit.emitLabel(tag, inst), | 59 | .br_if => try emit.emitLabel(tag, inst), |
| 45 | .br_table => try emit.emitBrTable(inst), | 60 | .br_table => try emit.emitBrTable(inst), |
| ... | @@ -419,3 +434,43 @@ fn emitMemFill(emit: *Emit) !void { | ... | @@ -419,3 +434,43 @@ fn emitMemFill(emit: *Emit) !void { |
| 419 | // For now we will always emit index 0. | 434 | // For now we will always emit index 0. |
| 420 | try leb128.writeULEB128(emit.code.writer(), @as(u32, 0)); | 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 | } |