Commit f760272200
Changed files (3)
src
arch
src/arch/wasm/CodeGen.zig
@@ -882,6 +882,8 @@ fn genFunc(self: *Self) InnerError!void {
self.args = cc_result.args;
self.return_value = cc_result.return_value;
+ try self.addTag(.dbg_prologue_end);
+
// Generate MIR for function body
try self.genBody(self.air.getMainBody());
// In case we have a return value, but the last instruction is a noreturn (such as a while loop)
@@ -896,6 +898,8 @@ fn genFunc(self: *Self) InnerError!void {
// End of function body
try self.addTag(.end);
+ try self.addTag(.dbg_epilogue_begin);
+
// check if we have to initialize and allocate anything into the stack frame.
// If so, create enough stack space and insert the instructions at the front of the list.
if (self.stack_size > 0) {
@@ -942,6 +946,10 @@ fn genFunc(self: *Self) InnerError!void {
.code = self.code,
.locals = self.locals.items,
.decl = self.decl,
+ .dbg_output = self.debug_output,
+ .prev_di_line = 0,
+ .prev_di_column = 0,
+ .prev_di_offset = 0,
};
emit.emitMir() catch |err| switch (err) {
src/arch/wasm/Emit.zig
@@ -6,6 +6,7 @@ const std = @import("std");
const Mir = @import("Mir.zig");
const link = @import("../../link.zig");
const Module = @import("../../Module.zig");
+const codegen = @import("../../codegen.zig");
const leb128 = std.leb;
/// Contains our list of instructions
@@ -22,6 +23,16 @@ locals: []const u8,
/// The declaration that code is being generated for.
decl: *Module.Decl,
+// Debug information
+/// Holds the debug information for this emission
+dbg_output: codegen.DebugInfoOutput,
+/// Previous debug info line
+prev_di_line: u32,
+/// Previous debug info column
+prev_di_column: u32,
+/// Previous offset relative to code section
+prev_di_offset: u32,
+
const InnerError = error{
OutOfMemory,
EmitFail,
@@ -40,6 +51,10 @@ pub fn emitMir(emit: *Emit) InnerError!void {
.block => try emit.emitBlock(tag, inst),
.loop => try emit.emitBlock(tag, inst),
+ .dbg_line => try emit.emitDbgLine(inst),
+ .dbg_epilogue_begin => try emit.emitDbgEpilogueBegin(),
+ .dbg_prologue_end => try emit.emitDbgPrologueEnd(),
+
// branch instructions
.br_if => try emit.emitLabel(tag, inst),
.br_table => try emit.emitBrTable(inst),
@@ -419,3 +434,43 @@ fn emitMemFill(emit: *Emit) !void {
// For now we will always emit index 0.
try leb128.writeULEB128(emit.code.writer(), @as(u32, 0));
}
+
+fn emitDbgLine(emit: *Emit, inst: Mir.Inst.Index) !void {
+ const extra_index = emit.mir.instructions.items(.data)[inst].payload;
+ const dbg_line = emit.mir.extraData(Mir.DbgLineColumn, extra_index).data;
+ try emit.dbgAdvancePCAndLine(dbg_line.line, dbg_line.column);
+}
+
+fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) !void {
+ if (emit.dbg_output != .dwarf) return;
+
+ const dbg_line = &emit.dbg_output.dwarf.dbg_line;
+ try dbg_line.ensureUnusedCapacity(11);
+ dbg_line.appendAssumeCapacity(std.dwarf.LNS.advance_pc);
+ // TODO: This must emit a relocation to calculate the offset relative
+ // to the code section start.
+ leb128.writeULEB128(dbg_line.writer(), emit.offset() - emit.prev_di_offset) catch unreachable;
+ const delta_line = @intCast(i32, line) - @intCast(i32, emit.prev_di_line);
+ if (delta_line != 0) {
+ dbg_line.appendAssumeCapacity(std.dwarf.LNS.advance_line);
+ leb128.writeILEB128(dbg_line.writer(), delta_line) catch unreachable;
+ }
+ dbg_line.appendAssumeCapacity(std.dwarf.LNS.copy);
+ emit.prev_di_line = line;
+ emit.prev_di_column = column;
+ emit.prev_di_offset = emit.offset();
+}
+
+fn emitDbgPrologueEnd(emit: *Emit) !void {
+ if (emit.dbg_output != .dwarf) return;
+
+ try emit.dbg_output.dwarf.dbg_line.append(std.dwarf.LNS.set_prologue_end);
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
+}
+
+fn emitDbgEpilogueBegin(emit: *Emit) !void {
+ if (emit.dbg_output != .dwarf) return;
+
+ try emit.dbg_output.dwarf.dbg_line.append(std.dwarf.LNS.set_epilogue_begin);
+ try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
+}
src/arch/wasm/Mir.zig
@@ -47,6 +47,19 @@ pub const Inst = struct {
///
/// Type of the loop is given in data `block_type`
loop = 0x03,
+ /// Inserts debug information about the current line and column
+ /// of the source code
+ ///
+ /// Uses `payload` of which the payload type is `DbgLineColumn`
+ dbg_line = 0x06,
+ /// Emits epilogue begin debug information
+ ///
+ /// Uses `nop`
+ dbg_epilogue_begin = 0x07,
+ /// Emits prologue end debug information
+ ///
+ /// Uses `nop`
+ dbg_prologue_end = 0x08,
/// Represents the end of a function body or an initialization expression
///
/// Payload is `nop`
@@ -645,3 +658,9 @@ pub const Memory = struct {
pointer: u32,
offset: u32,
};
+
+/// Maps a source line with wasm bytecode
+pub const DbgLineColumn = struct {
+ line: u32,
+ column: u32,
+};