ERR/E3.0 (slice 3b): comptime trace resolution
#run failures now print the same `func at file:line:col` trace as runtime, resolved in-process via the interpreter's IR/source tables. - Read-side context-split op `.trace_resolve` (mirror of .trace_frame), lowered from a name-recognized `__trace_resolve_frame(u64) -> Frame`. - emit_llvm: inttoptr the operand to *Frame + load (the value .trace_frame stamped in). - interp: unpack (func_id << 32 | span.start); resolve func/file from module.functions and line/col via SourceLoc.compute over a new source_map (setSourceMap wired at every production interp site). - trace.sx: frame_at -> u64; to_string routes each frame through __trace_resolve_frame, so one source works in both machines. Compiled path behavior unchanged (243/244/247 identical; it now loads via the op). New examples/253-comptime-trace.sx exercises the comptime path. Gates: zig build, zig build test, run_examples.sh -> 291 passed.
This commit is contained in:
@@ -8554,6 +8554,7 @@ pub const Lowering = struct {
|
||||
|
||||
var interp = interp_mod.Interpreter.init(self.module, self.alloc);
|
||||
defer interp.deinit();
|
||||
if (self.diagnostics) |d| if (d.import_sources) |sm| interp.setSourceMap(sm);
|
||||
|
||||
const result = interp.call(ct_func_id, &.{}) catch return null;
|
||||
|
||||
@@ -10345,6 +10346,18 @@ pub const Lowering = struct {
|
||||
// chain at comptime, no-op in compiled code (ERR E4.1).
|
||||
return self.builder.emit(.{ .interp_print_frames = {} }, .void);
|
||||
}
|
||||
if (std.mem.eql(u8, name, "__trace_resolve_frame")) {
|
||||
// Backs `trace.sx`'s formatter: a raw trace-buffer u64 → a `Frame`.
|
||||
// Compiled code reinterprets the operand as `*Frame` and loads it;
|
||||
// the interp unpacks (func_id, span.start) and resolves (ERR E3.0
|
||||
// slice 3b). Result type is the `Frame` struct from trace.sx.
|
||||
const frame_ty = self.module.types.findByName(self.module.types.internString("Frame")) orelse {
|
||||
if (self.diagnostics) |d| d.addFmt(.err, null, "`__trace_resolve_frame` needs `Frame` (from trace.sx) in scope", .{});
|
||||
return self.builder.constInt(0, .void);
|
||||
};
|
||||
const arg = self.lowerExpr(c.args[0]);
|
||||
return self.builder.emit(.{ .trace_resolve = .{ .operand = arg } }, frame_ty);
|
||||
}
|
||||
if (std.mem.eql(u8, name, "error_tag_name")) {
|
||||
// error_tag_name(e) → look the error-set value's runtime tag id up
|
||||
// in the always-linked tag-name table. The value IS its u32 tag id.
|
||||
@@ -13981,6 +13994,8 @@ pub const Lowering = struct {
|
||||
if (std.mem.eql(u8, bare_name, "error_tag_name")) return .string;
|
||||
if (std.mem.eql(u8, bare_name, "is_comptime")) return .bool;
|
||||
if (std.mem.eql(u8, bare_name, "__interp_print_frames")) return .void;
|
||||
if (std.mem.eql(u8, bare_name, "__trace_resolve_frame"))
|
||||
return self.module.types.findByName(self.module.types.internString("Frame")) orelse .unresolved;
|
||||
if (std.mem.eql(u8, bare_name, "is_flags")) return .bool;
|
||||
if (std.mem.eql(u8, bare_name, "type_of")) return .any;
|
||||
if (std.mem.eql(u8, bare_name, "field_value")) return .any;
|
||||
|
||||
Reference in New Issue
Block a user