Commit 7774287fdc

mlugg <mlugg@mlugg.co.uk>
2025-01-23 05:48:01
tests: enable stack trace tests for x86_64-selfhosted
Allows the stack trace tests to be additionally compiled and run with `.use_llvm = false, .use_lld = false` depending on the host target. This is currently enabled for x86_64 targets emitting ELF. Self-hosted backends emit slightly different DWARF info to the LLVM backend, so the checking logic (and the tests themselves) had to be tweaked slightly to support both backends at once.
1 parent d916954
test/src/check-stack-trace.zig
@@ -58,14 +58,23 @@ pub fn main() !void {
             try buf.appendSlice(line[pos + 1 .. marks[2] + delims[2].len]);
             try buf.appendSlice(" [address]");
             if (optimize_mode == .Debug) {
-                // On certain platforms (windows) or possibly depending on how we choose to link main
-                // the object file extension may be present so we simply strip any extension.
-                if (mem.indexOfScalar(u8, line[marks[4]..marks[5]], '.')) |idot| {
-                    try buf.appendSlice(line[marks[3] .. marks[4] + idot]);
-                    try buf.appendSlice(line[marks[5]..]);
+                try buf.appendSlice(line[marks[3] .. marks[4] + delims[4].len]);
+
+                const file_name = line[marks[4] + delims[4].len .. marks[5]];
+                // The LLVM backend currently uses the object file name in the debug info here.
+                // This actually violates the DWARF specification (DWARF5 § 3.1.1, lines 24-27).
+                // The self-hosted backend uses the root Zig source file of the module (in compilance with the spec).
+                if (std.mem.eql(u8, file_name, "test") or
+                    std.mem.eql(u8, file_name, "test.exe.obj") or
+                    std.mem.endsWith(u8, file_name, ".zig"))
+                {
+                    try buf.appendSlice("[main_file]");
                 } else {
-                    try buf.appendSlice(line[marks[3]..]);
+                    // Something unexpected; include it verbatim.
+                    try buf.appendSlice(file_name);
                 }
+
+                try buf.appendSlice(line[marks[5]..]);
             } else {
                 try buf.appendSlice(line[marks[3] .. marks[3] + delims[3].len]);
                 try buf.appendSlice("[function]");
test/src/StackTrace.zig
@@ -21,17 +21,34 @@ const Config = struct {
 };
 
 pub fn addCase(self: *StackTrace, config: Config) void {
+    self.addCaseInner(config, true);
+    if (shouldTestNonLlvm(self.b.graph.host.result)) {
+        self.addCaseInner(config, false);
+    }
+}
+
+fn addCaseInner(self: *StackTrace, config: Config, use_llvm: bool) void {
     if (config.Debug) |per_mode|
-        self.addExpect(config.name, config.source, .Debug, per_mode);
+        self.addExpect(config.name, config.source, .Debug, use_llvm, per_mode);
 
     if (config.ReleaseSmall) |per_mode|
-        self.addExpect(config.name, config.source, .ReleaseSmall, per_mode);
+        self.addExpect(config.name, config.source, .ReleaseSmall, use_llvm, per_mode);
 
     if (config.ReleaseFast) |per_mode|
-        self.addExpect(config.name, config.source, .ReleaseFast, per_mode);
+        self.addExpect(config.name, config.source, .ReleaseFast, use_llvm, per_mode);
 
     if (config.ReleaseSafe) |per_mode|
-        self.addExpect(config.name, config.source, .ReleaseSafe, per_mode);
+        self.addExpect(config.name, config.source, .ReleaseSafe, use_llvm, per_mode);
+}
+
+fn shouldTestNonLlvm(target: std.Target) bool {
+    return switch (target.cpu.arch) {
+        .x86_64 => switch (target.ofmt) {
+            .elf => true,
+            else => false,
+        },
+        else => false,
+    };
 }
 
 fn addExpect(
@@ -39,13 +56,14 @@ fn addExpect(
     name: []const u8,
     source: []const u8,
     optimize_mode: OptimizeMode,
+    use_llvm: bool,
     mode_config: Config.PerMode,
 ) void {
     for (mode_config.exclude_os) |tag| if (tag == builtin.os.tag) return;
 
     const b = self.b;
-    const annotated_case_name = b.fmt("check {s} ({s})", .{
-        name, @tagName(optimize_mode),
+    const annotated_case_name = b.fmt("check {s} ({s} {s})", .{
+        name, @tagName(optimize_mode), if (use_llvm) "llvm" else "selfhosted",
     });
     for (self.test_filters) |test_filter| {
         if (mem.indexOf(u8, annotated_case_name, test_filter)) |_| break;
@@ -61,6 +79,7 @@ fn addExpect(
             .target = b.graph.host,
             .error_tracing = mode_config.error_tracing,
         }),
+        .use_llvm = use_llvm,
     });
 
     const run = b.addRunArtifact(exe);
test/stack_traces.zig
@@ -13,7 +13,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TheSkyIsFalling
-            \\source.zig:2:5: [address] in main (test)
+            \\source.zig:2:5: [address] in main ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
             \\
@@ -61,10 +61,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TheSkyIsFalling
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:6:5: [address] in main (test)
+            \\source.zig:6:5: [address] in main ([main_file])
             \\    try foo();
             \\    ^
             \\
@@ -120,7 +120,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: UnrelatedError
-            \\source.zig:13:5: [address] in main (test)
+            \\source.zig:13:5: [address] in main ([main_file])
             \\    return error.UnrelatedError;
             \\    ^
             \\
@@ -172,7 +172,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: UnrelatedError
-            \\source.zig:10:5: [address] in main (test)
+            \\source.zig:10:5: [address] in main ([main_file])
             \\    return error.UnrelatedError;
             \\    ^
             \\
@@ -224,10 +224,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TheSkyIsFalling
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:10:5: [address] in main (test)
+            \\source.zig:10:5: [address] in main ([main_file])
             \\    try foo();
             \\    ^
             \\
@@ -284,7 +284,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: BadTime
-            \\source.zig:12:5: [address] in main (test)
+            \\source.zig:12:5: [address] in main ([main_file])
             \\    return error.BadTime;
             \\    ^
             \\
@@ -332,10 +332,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: AndMyCarIsOutOfGas
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:6:5: [address] in main (test)
+            \\source.zig:6:5: [address] in main ([main_file])
             \\    return foo() catch error.AndMyCarIsOutOfGas;
             \\    ^
             \\
@@ -391,7 +391,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: SomethingUnrelatedWentWrong
-            \\source.zig:11:5: [address] in main (test)
+            \\source.zig:11:5: [address] in main ([main_file])
             \\    return error.SomethingUnrelatedWentWrong;
             \\    ^
             \\
@@ -456,13 +456,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: StillUnresolved
-            \\source.zig:1:18: [address] in foo (test)
+            \\source.zig:1:18: [address] in foo ([main_file])
             \\fn foo() !void { return error.TheSkyIsFalling; }
             \\                 ^
-            \\source.zig:2:18: [address] in bar (test)
+            \\source.zig:2:18: [address] in bar ([main_file])
             \\fn bar() !void { return error.InternalError; }
             \\                 ^
-            \\source.zig:23:5: [address] in main (test)
+            \\source.zig:23:5: [address] in main ([main_file])
             \\    return error.StillUnresolved;
             \\    ^
             \\
@@ -527,13 +527,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TestExpectedError
-            \\source.zig:9:18: [address] in foo (test)
+            \\source.zig:9:18: [address] in foo ([main_file])
             \\fn foo() !void { return error.Foo; }
             \\                 ^
-            \\source.zig:5:5: [address] in expectError (test)
+            \\source.zig:5:5: [address] in expectError ([main_file])
             \\    return error.TestExpectedError;
             \\    ^
-            \\source.zig:17:5: [address] in main (test)
+            \\source.zig:17:5: [address] in main ([main_file])
             \\    try expectError(error.Bar, foo());
             \\    ^
             \\
@@ -592,13 +592,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: AndMyCarIsOutOfGas
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:6:5: [address] in bar (test)
+            \\source.zig:6:5: [address] in bar ([main_file])
             \\    return error.AndMyCarIsOutOfGas;
             \\    ^
-            \\source.zig:11:9: [address] in main (test)
+            \\source.zig:11:9: [address] in main ([main_file])
             \\        try bar();
             \\        ^
             \\
@@ -657,13 +657,13 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: AndMyCarIsOutOfGas
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:6:5: [address] in bar (test)
+            \\source.zig:6:5: [address] in bar ([main_file])
             \\    return error.AndMyCarIsOutOfGas;
             \\    ^
-            \\source.zig:11:9: [address] in main (test)
+            \\source.zig:11:9: [address] in main ([main_file])
             \\        try bar();
             \\        ^
             \\
@@ -724,16 +724,16 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TheSkyIsFalling
-            \\source.zig:10:5: [address] in make_error (test)
+            \\source.zig:10:5: [address] in make_error ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
-            \\source.zig:6:5: [address] in bar (test)
+            \\source.zig:6:5: [address] in bar ([main_file])
             \\    return make_error();
             \\    ^
-            \\source.zig:2:5: [address] in foo (test)
+            \\source.zig:2:5: [address] in foo ([main_file])
             \\    try bar();
             \\    ^
-            \\source.zig:14:5: [address] in main (test)
+            \\source.zig:14:5: [address] in main ([main_file])
             \\    try foo();
             \\    ^
             \\
@@ -797,10 +797,10 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
                 .windows, // TODO intermittent failures
             },
             .expect =
-            \\source.zig:7:8: [address] in foo (test)
+            \\source.zig:7:8: [address] in foo ([main_file])
             \\    bar();
             \\       ^
-            \\source.zig:10:8: [address] in main (test)
+            \\source.zig:10:8: [address] in main ([main_file])
             \\    foo();
             \\       ^
             \\
@@ -829,7 +829,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
         .Debug = .{
             .expect =
             \\error: TheSkyIsFalling
-            \\source.zig:3:5: [address] in main (test)
+            \\source.zig:3:5: [address] in main ([main_file])
             \\    return error.TheSkyIsFalling;
             \\    ^
             \\