ERR/E3.0 (slice 1): thread source spans into IR instructions
Foundation for DWARF line-info (E3.0). The `Inst.span` field existed but was
never populated — `emit()` always passed the empty `{0,0}` default, so every
instruction had no source location (the lone reader, the interp's comptime
bail-offset, was always 0).
- Builder gains a `current_span`; `emit`/`emitVoid` stamp it onto each
instruction.
- `lowerExpr` / `lowerStmt` set `current_span` from the AST node's span on
entry and restore it on exit (save/restore), so a parent's later emits keep
the parent's span after a child lowers; the empty default is skipped so
synthetic nodes don't reset a meaningful enclosing span.
Behavior-neutral: codegen never reads spans, and the only consumer (the interp
bail-offset) merely gains real offsets. 290 examples pass unchanged, no `.ir`
snapshot drift. New unit test asserts an emitted `add` carries its `a + b` span.
Next (slice 2): bind `llvm-c/DebugInfo.h`, emit DICompileUnit / DISubprogram /
DIFile / DILocation from these spans, gate on debug/trace mode.
This commit is contained in:
@@ -253,6 +253,12 @@ pub const Builder = struct {
|
||||
current_block: ?BlockId = null,
|
||||
/// Running instruction counter within the current function (for Ref assignment).
|
||||
inst_counter: u32 = 0,
|
||||
/// Source span stamped onto every instruction emitted via `emit`/`emitVoid`
|
||||
/// (ERR E3.0). Lowering sets it (save/restore) at each AST node so the IR
|
||||
/// carries per-instruction locations for DWARF `.debug_line` + comptime
|
||||
/// frame resolution. Defaults empty for instructions emitted outside a
|
||||
/// node context (synthetic prologue/epilogue, etc.).
|
||||
current_span: Span = .{},
|
||||
|
||||
pub fn init(module: *Module) Builder {
|
||||
return .{ .module = module };
|
||||
@@ -344,7 +350,7 @@ pub const Builder = struct {
|
||||
// ── Emit helpers ────────────────────────────────────────────────
|
||||
|
||||
pub fn emit(self: *Builder, op: Op, ty: TypeId) Ref {
|
||||
return self.emitSpan(op, ty, .{});
|
||||
return self.emitSpan(op, ty, self.current_span);
|
||||
}
|
||||
|
||||
fn emitSpan(self: *Builder, op: Op, ty: TypeId, span: Span) Ref {
|
||||
@@ -359,7 +365,7 @@ pub const Builder = struct {
|
||||
pub fn emitVoid(self: *Builder, op: Op, ty: TypeId) void {
|
||||
const block = self.currentBlock();
|
||||
self.inst_counter += 1;
|
||||
block.insts.append(self.module.alloc, .{ .op = op, .ty = ty }) catch unreachable;
|
||||
block.insts.append(self.module.alloc, .{ .op = op, .ty = ty, .span = self.current_span }) catch unreachable;
|
||||
}
|
||||
|
||||
// ── Constants ───────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user