@zigc/lib 0.16.0-test.1 → 0.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/LICENSE +19 -0
  2. package/c/math.zig +135 -35
  3. package/c/stropts.zig +17 -0
  4. package/c.zig +1 -0
  5. package/compiler/aro/aro/Attribute/names.zig +604 -589
  6. package/compiler/aro/aro/Attribute.zig +202 -116
  7. package/compiler/aro/aro/Builtins/common.zig +874 -863
  8. package/compiler/aro/aro/Builtins/eval.zig +15 -7
  9. package/compiler/aro/aro/Builtins.zig +0 -1
  10. package/compiler/aro/aro/CodeGen.zig +3 -1
  11. package/compiler/aro/aro/Compilation.zig +120 -97
  12. package/compiler/aro/aro/Diagnostics.zig +21 -17
  13. package/compiler/aro/aro/Driver/GCCDetector.zig +635 -0
  14. package/compiler/aro/aro/Driver.zig +124 -50
  15. package/compiler/aro/aro/LangOpts.zig +12 -2
  16. package/compiler/aro/aro/Parser/Diagnostic.zig +79 -19
  17. package/compiler/aro/aro/Parser.zig +336 -142
  18. package/compiler/aro/aro/Preprocessor/Diagnostic.zig +21 -0
  19. package/compiler/aro/aro/Preprocessor.zig +127 -56
  20. package/compiler/aro/aro/Target.zig +17 -12
  21. package/compiler/aro/aro/Tokenizer.zig +31 -14
  22. package/compiler/aro/aro/Toolchain.zig +4 -7
  23. package/compiler/aro/aro/Tree.zig +178 -148
  24. package/compiler/aro/aro/TypeStore.zig +82 -24
  25. package/compiler/aro/aro/Value.zig +13 -17
  26. package/compiler/aro/aro/features.zig +1 -0
  27. package/compiler/aro/aro/pragmas/once.zig +0 -1
  28. package/compiler/aro/aro/record_layout.zig +3 -3
  29. package/compiler/aro/assembly_backend/x86_64.zig +3 -4
  30. package/compiler/aro/backend/Assembly.zig +1 -2
  31. package/compiler/aro/backend/Interner.zig +2 -2
  32. package/compiler/aro/backend/Ir.zig +100 -92
  33. package/compiler/aro/include/ptrcheck.h +49 -0
  34. package/compiler/aro/main.zig +26 -10
  35. package/compiler/build_runner.zig +1 -0
  36. package/compiler/objdump.zig +93 -0
  37. package/compiler/reduce.zig +5 -1
  38. package/compiler/resinator/compile.zig +2 -2
  39. package/compiler/resinator/main.zig +7 -1
  40. package/compiler/resinator/preprocess.zig +1 -3
  41. package/compiler/std-docs.zig +8 -1
  42. package/compiler/test_runner.zig +193 -61
  43. package/compiler/translate-c/MacroTranslator.zig +80 -11
  44. package/compiler/translate-c/PatternList.zig +1 -9
  45. package/compiler/translate-c/Scope.zig +43 -6
  46. package/compiler/translate-c/Translator.zig +364 -126
  47. package/compiler/translate-c/ast.zig +19 -11
  48. package/compiler/translate-c/main.zig +75 -16
  49. package/compiler_rt/cos.zig +141 -52
  50. package/compiler_rt/limb64.zig +266 -0
  51. package/compiler_rt/long_double.zig +37 -0
  52. package/compiler_rt/mulo.zig +6 -1
  53. package/compiler_rt/rem_pio2l.zig +173 -0
  54. package/compiler_rt/sin.zig +140 -55
  55. package/compiler_rt/sincos.zig +279 -72
  56. package/compiler_rt/tan.zig +118 -47
  57. package/compiler_rt/trig.zig +256 -6
  58. package/compiler_rt.zig +2 -0
  59. package/fuzzer.zig +855 -307
  60. package/libc/musl/src/math/pow.c +343 -0
  61. package/package.json +1 -1
  62. package/std/Build/Fuzz.zig +6 -19
  63. package/std/Build/Module.zig +1 -1
  64. package/std/Build/Step/CheckObject.zig +3 -3
  65. package/std/Build/Step/Compile.zig +18 -0
  66. package/std/Build/Step/ConfigHeader.zig +49 -33
  67. package/std/Build/Step/InstallArtifact.zig +18 -0
  68. package/std/Build/Step/Run.zig +536 -87
  69. package/std/Build/Step/TranslateC.zig +0 -6
  70. package/std/Build/Step.zig +8 -15
  71. package/std/Build/WebServer.zig +29 -17
  72. package/std/Build/abi.zig +47 -11
  73. package/std/Build.zig +17 -14
  74. package/std/Io/Dispatch.zig +2 -0
  75. package/std/Io/File/Reader.zig +3 -1
  76. package/std/Io/File.zig +1 -0
  77. package/std/Io/Kqueue.zig +2 -2
  78. package/std/Io/Threaded.zig +181 -143
  79. package/std/Io/Uring.zig +2 -1
  80. package/std/Io.zig +970 -2
  81. package/std/Target.zig +3 -2
  82. package/std/Thread.zig +8 -3
  83. package/std/array_hash_map.zig +96 -555
  84. package/std/array_list.zig +22 -31
  85. package/std/bit_set.zig +22 -6
  86. package/std/builtin/assembly.zig +68 -0
  87. package/std/c.zig +17 -17
  88. package/std/compress/flate/Compress.zig +3 -3
  89. package/std/crypto/Certificate/Bundle.zig +15 -1
  90. package/std/crypto/codecs/asn1.zig +33 -18
  91. package/std/crypto/codecs/base64_hex_ct.zig +14 -4
  92. package/std/debug/Dwarf.zig +29 -9
  93. package/std/debug/Info.zig +4 -0
  94. package/std/debug/MachOFile.zig +46 -8
  95. package/std/debug/Pdb.zig +539 -36
  96. package/std/debug/SelfInfo/Elf.zig +19 -18
  97. package/std/debug/SelfInfo/MachO.zig +18 -7
  98. package/std/debug/SelfInfo/Windows.zig +138 -36
  99. package/std/debug.zig +179 -65
  100. package/std/enums.zig +25 -19
  101. package/std/heap/ArenaAllocator.zig +145 -154
  102. package/std/heap/debug_allocator.zig +7 -7
  103. package/std/http/Client.zig +10 -6
  104. package/std/http.zig +11 -9
  105. package/std/json/Stringify.zig +3 -3
  106. package/std/json/dynamic.zig +4 -4
  107. package/std/math/big/int.zig +16 -17
  108. package/std/mem/Allocator.zig +4 -5
  109. package/std/mem.zig +48 -0
  110. package/std/os/emscripten.zig +1 -17
  111. package/std/os/linux.zig +7 -2
  112. package/std/os/windows.zig +2 -2
  113. package/std/pdb.zig +143 -4
  114. package/std/posix.zig +6 -12
  115. package/std/priority_dequeue.zig +13 -12
  116. package/std/priority_queue.zig +5 -4
  117. package/std/process/Child.zig +1 -1
  118. package/std/process/Environ.zig +1 -1
  119. package/std/start.zig +17 -4
  120. package/std/std.zig +19 -6
  121. package/std/testing/FailingAllocator.zig +4 -4
  122. package/std/testing/Smith.zig +37 -2
  123. package/std/zig/Ast/Render.zig +186 -458
  124. package/std/zig/Ast.zig +0 -4
  125. package/std/zig/AstGen.zig +44 -7
  126. package/std/zig/AstSmith.zig +2602 -0
  127. package/std/zig/Client.zig +8 -3
  128. package/std/zig/Parse.zig +83 -74
  129. package/std/zig/Server.zig +26 -0
  130. package/std/zig/Zir.zig +17 -0
  131. package/std/zig/c_translation/helpers.zig +14 -9
  132. package/std/zig/llvm/Builder.zig +107 -48
  133. package/std/zig/system.zig +20 -4
  134. package/std/zig/tokenizer.zig +2 -1
  135. package/std/zig.zig +6 -0
  136. package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
  137. package/libc/mingw/complex/cabs.c +0 -48
  138. package/libc/mingw/complex/cabsf.c +0 -48
  139. package/libc/mingw/complex/cacos.c +0 -50
  140. package/libc/mingw/complex/cacosf.c +0 -50
  141. package/libc/mingw/complex/carg.c +0 -48
  142. package/libc/mingw/complex/cargf.c +0 -48
  143. package/libc/mingw/complex/casin.c +0 -50
  144. package/libc/mingw/complex/casinf.c +0 -50
  145. package/libc/mingw/complex/catan.c +0 -50
  146. package/libc/mingw/complex/catanf.c +0 -50
  147. package/libc/mingw/complex/ccos.c +0 -50
  148. package/libc/mingw/complex/ccosf.c +0 -50
  149. package/libc/mingw/complex/cexp.c +0 -48
  150. package/libc/mingw/complex/cexpf.c +0 -48
  151. package/libc/mingw/complex/cimag.c +0 -48
  152. package/libc/mingw/complex/cimagf.c +0 -48
  153. package/libc/mingw/complex/clog.c +0 -48
  154. package/libc/mingw/complex/clog10.c +0 -49
  155. package/libc/mingw/complex/clog10f.c +0 -49
  156. package/libc/mingw/complex/clogf.c +0 -48
  157. package/libc/mingw/complex/conj.c +0 -48
  158. package/libc/mingw/complex/conjf.c +0 -48
  159. package/libc/mingw/complex/cpow.c +0 -48
  160. package/libc/mingw/complex/cpowf.c +0 -48
  161. package/libc/mingw/complex/cproj.c +0 -48
  162. package/libc/mingw/complex/cprojf.c +0 -48
  163. package/libc/mingw/complex/creal.c +0 -48
  164. package/libc/mingw/complex/crealf.c +0 -48
  165. package/libc/mingw/complex/csin.c +0 -50
  166. package/libc/mingw/complex/csinf.c +0 -50
  167. package/libc/mingw/complex/csqrt.c +0 -48
  168. package/libc/mingw/complex/csqrtf.c +0 -48
  169. package/libc/mingw/complex/ctan.c +0 -50
  170. package/libc/mingw/complex/ctanf.c +0 -50
  171. package/libc/mingw/math/arm/s_rint.c +0 -86
  172. package/libc/mingw/math/arm/s_rintf.c +0 -51
  173. package/libc/mingw/math/arm/sincos.S +0 -30
  174. package/libc/mingw/math/arm-common/sincosl.c +0 -13
  175. package/libc/mingw/math/arm64/rint.c +0 -12
  176. package/libc/mingw/math/arm64/rintf.c +0 -12
  177. package/libc/mingw/math/arm64/sincos.S +0 -32
  178. package/libc/mingw/math/bsd_private_base.h +0 -148
  179. package/libc/mingw/math/frexpf.c +0 -13
  180. package/libc/mingw/math/frexpl.c +0 -71
  181. package/libc/mingw/math/x86/acosf.c +0 -29
  182. package/libc/mingw/math/x86/atanf.c +0 -23
  183. package/libc/mingw/math/x86/atanl.c +0 -18
  184. package/libc/mingw/math/x86/cos.def.h +0 -65
  185. package/libc/mingw/math/x86/cosl.c +0 -46
  186. package/libc/mingw/math/x86/cosl_internal.S +0 -55
  187. package/libc/mingw/math/x86/ldexp.c +0 -23
  188. package/libc/mingw/math/x86/scalbn.S +0 -41
  189. package/libc/mingw/math/x86/scalbnf.S +0 -40
  190. package/libc/mingw/math/x86/sin.def.h +0 -65
  191. package/libc/mingw/math/x86/sinl.c +0 -46
  192. package/libc/mingw/math/x86/sinl_internal.S +0 -58
  193. package/libc/mingw/math/x86/tanl.S +0 -62
  194. package/libc/mingw/misc/btowc.c +0 -28
  195. package/libc/mingw/misc/wcstof.c +0 -66
  196. package/libc/mingw/misc/wcstoimax.c +0 -132
  197. package/libc/mingw/misc/wcstoumax.c +0 -126
  198. package/libc/mingw/misc/wctob.c +0 -29
  199. package/libc/mingw/misc/winbs_uint64.c +0 -6
  200. package/libc/mingw/misc/winbs_ulong.c +0 -6
  201. package/libc/mingw/misc/winbs_ushort.c +0 -6
  202. package/libc/mingw/stdio/_Exit.c +0 -10
  203. package/libc/mingw/stdio/_findfirst64i32.c +0 -21
  204. package/libc/mingw/stdio/_findnext64i32.c +0 -21
  205. package/libc/mingw/stdio/_fstat64i32.c +0 -37
  206. package/libc/mingw/stdio/_stat64i32.c +0 -37
  207. package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
  208. package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
  209. package/libc/mingw/stdio/_wstat64i32.c +0 -37
  210. package/libc/musl/src/legacy/isastream.c +0 -7
  211. package/libc/musl/src/legacy/valloc.c +0 -8
  212. package/libc/musl/src/math/__cosl.c +0 -96
  213. package/libc/musl/src/math/__sinl.c +0 -78
  214. package/libc/musl/src/math/__tanl.c +0 -143
  215. package/libc/musl/src/math/aarch64/lrint.c +0 -10
  216. package/libc/musl/src/math/aarch64/lrintf.c +0 -10
  217. package/libc/musl/src/math/aarch64/rintf.c +0 -7
  218. package/libc/musl/src/math/cosl.c +0 -39
  219. package/libc/musl/src/math/fdim.c +0 -10
  220. package/libc/musl/src/math/finite.c +0 -7
  221. package/libc/musl/src/math/finitef.c +0 -7
  222. package/libc/musl/src/math/frexp.c +0 -23
  223. package/libc/musl/src/math/frexpf.c +0 -23
  224. package/libc/musl/src/math/frexpl.c +0 -29
  225. package/libc/musl/src/math/i386/lrint.c +0 -8
  226. package/libc/musl/src/math/i386/lrintf.c +0 -8
  227. package/libc/musl/src/math/i386/rintf.c +0 -7
  228. package/libc/musl/src/math/lrint.c +0 -72
  229. package/libc/musl/src/math/lrintf.c +0 -8
  230. package/libc/musl/src/math/powerpc64/lrint.c +0 -16
  231. package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
  232. package/libc/musl/src/math/rintf.c +0 -30
  233. package/libc/musl/src/math/s390x/rintf.c +0 -15
  234. package/libc/musl/src/math/sincosl.c +0 -60
  235. package/libc/musl/src/math/sinl.c +0 -41
  236. package/libc/musl/src/math/tanl.c +0 -29
  237. package/libc/musl/src/math/x32/lrint.s +0 -5
  238. package/libc/musl/src/math/x32/lrintf.s +0 -5
  239. package/libc/musl/src/math/x86_64/lrint.c +0 -8
  240. package/libc/musl/src/math/x86_64/lrintf.c +0 -8
  241. package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
@@ -143,7 +143,13 @@ pub fn main(init: std.process.Init.Minimal) !void {
143
143
  if (!zig_integration) io.unlockStderr();
144
144
  }
145
145
 
146
- var comp = aro.Compilation.init(aro_arena, aro_arena, io, &diagnostics, Io.Dir.cwd());
146
+ var comp = try aro.Compilation.init(.{
147
+ .gpa = aro_arena,
148
+ .arena = aro_arena,
149
+ .io = io,
150
+ .diagnostics = &diagnostics,
151
+ .environ_map = &environ_map,
152
+ });
147
153
  defer comp.deinit();
148
154
 
149
155
  var argv: std.ArrayList([]const u8) = .empty;
@@ -14,8 +14,6 @@ pub fn preprocess(
14
14
  argv: []const []const u8,
15
15
  maybe_dependencies: ?*Dependencies,
16
16
  ) PreprocessError!void {
17
- try comp.addDefaultPragmaHandlers();
18
-
19
17
  var driver: aro.Driver = .{ .comp = comp, .diagnostics = comp.diagnostics, .aro_name = "arocc" };
20
18
  defer driver.deinit();
21
19
 
@@ -47,7 +45,7 @@ pub fn preprocess(
47
45
  if (hasAnyErrors(comp)) return error.GeneratedSourceError;
48
46
 
49
47
  comp.generated_buf.items.len = 0;
50
- var pp = aro.Preprocessor.initDefault(comp) catch |err| switch (err) {
48
+ var pp = aro.Preprocessor.init(comp, .{ .base_file = source.id }) catch |err| switch (err) {
51
49
  error.FatalError => return error.GeneratedSourceError,
52
50
  error.OutOfMemory => |e| return e,
53
51
  };
@@ -423,7 +423,14 @@ fn buildWasmBinary(
423
423
  );
424
424
  return error.WasmCompilationFailed;
425
425
  },
426
- .stopped, .unknown => {
426
+ .stopped => |sig| {
427
+ std.log.err(
428
+ "the following command stopped unexpectedly with signal {t}:\n{s}",
429
+ .{ sig, try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items) },
430
+ );
431
+ return error.WasmCompilationFailed;
432
+ },
433
+ .unknown => {
427
434
  std.log.err(
428
435
  "the following command terminated unexpectedly:\n{s}",
429
436
  .{try std.Build.Step.allocPrintCmd(arena, .inherit, null, argv.items)},
@@ -6,6 +6,7 @@ const Io = std.Io;
6
6
  const fatal = std.process.fatal;
7
7
  const testing = std.testing;
8
8
  const assert = std.debug.assert;
9
+ const panic = std.debug.panic;
9
10
  const fuzz_abi = std.Build.abi.fuzz;
10
11
 
11
12
  pub const std_options: std.Options = .{
@@ -17,6 +18,8 @@ var fba: std.heap.FixedBufferAllocator = .init(&fba_buffer);
17
18
  var fba_buffer: [8192]u8 = undefined;
18
19
  var stdin_buffer: [4096]u8 = undefined;
19
20
  var stdout_buffer: [4096]u8 = undefined;
21
+ var stdin_reader: Io.File.Reader = undefined;
22
+ var stdout_writer: Io.File.Writer = undefined;
20
23
  const runner_threaded_io: Io = Io.Threaded.global_single_threaded.io();
21
24
 
22
25
  /// Keep in sync with logic in `std.Build.addRunArtifact` which decides whether
@@ -38,10 +41,10 @@ pub fn main(init: std.process.Init.Minimal) void {
38
41
  }
39
42
 
40
43
  if (need_simple) {
41
- return mainSimple() catch |err| std.debug.panic("test failure: {t}", .{err});
44
+ return mainSimple() catch |err| panic("test failure: {t}", .{err});
42
45
  }
43
46
 
44
- const args = init.args.toSlice(fba.allocator()) catch |err| std.debug.panic("unable to parse command line args: {t}", .{err});
47
+ const args = init.args.toSlice(fba.allocator()) catch |err| panic("unable to parse command line args: {t}", .{err});
45
48
 
46
49
  var listen = false;
47
50
  var opt_cache_dir: ?[]const u8 = null;
@@ -55,7 +58,7 @@ pub fn main(init: std.process.Init.Minimal) void {
55
58
  } else if (std.mem.startsWith(u8, arg, "--cache-dir")) {
56
59
  opt_cache_dir = arg["--cache-dir=".len..];
57
60
  } else {
58
- std.debug.panic("unrecognized command line argument: {s}", .{arg});
61
+ panic("unrecognized command line argument: {s}", .{arg});
59
62
  }
60
63
  }
61
64
 
@@ -65,7 +68,7 @@ pub fn main(init: std.process.Init.Minimal) void {
65
68
  }
66
69
 
67
70
  if (listen) {
68
- return mainServer(init) catch |err| std.debug.panic("internal test runner failure: {t}", .{err});
71
+ return mainServer(init) catch |err| panic("internal test runner failure: {t}", .{err});
69
72
  } else {
70
73
  return mainTerminal(init);
71
74
  }
@@ -73,24 +76,14 @@ pub fn main(init: std.process.Init.Minimal) void {
73
76
 
74
77
  fn mainServer(init: std.process.Init.Minimal) !void {
75
78
  @disableInstrumentation();
76
- var stdin_reader = Io.File.stdin().readerStreaming(runner_threaded_io, &stdin_buffer);
77
- var stdout_writer = Io.File.stdout().writerStreaming(runner_threaded_io, &stdout_buffer);
79
+ stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer);
80
+ stdout_writer = .initStreaming(.stdout(), runner_threaded_io, &stdout_buffer);
78
81
  var server = try std.zig.Server.init(.{
79
82
  .in = &stdin_reader.interface,
80
83
  .out = &stdout_writer.interface,
81
84
  .zig_version = builtin.zig_version_string,
82
85
  });
83
86
 
84
- if (builtin.fuzz) {
85
- const coverage = fuzz_abi.fuzzer_coverage();
86
- try server.serveCoverageIdMessage(
87
- coverage.id,
88
- coverage.runs,
89
- coverage.unique,
90
- coverage.seen,
91
- );
92
- }
93
-
94
87
  while (true) {
95
88
  const hdr = try server.receiveMessage();
96
89
  switch (hdr.tag) {
@@ -151,7 +144,7 @@ fn mainServer(init: std.process.Init.Minimal) !void {
151
144
  error.SkipZigTest => .skip,
152
145
  else => s: {
153
146
  if (@errorReturnTrace()) |trace| {
154
- std.debug.dumpStackTrace(trace);
147
+ std.debug.dumpErrorReturnTrace(trace);
155
148
  }
156
149
  break :s .fail;
157
150
  },
@@ -180,48 +173,75 @@ fn mainServer(init: std.process.Init.Minimal) !void {
180
173
  // since they are not present.
181
174
  if (!builtin.fuzz) unreachable;
182
175
 
183
- const index: u32 = @intCast(index: {
184
- testing.allocator_instance = .{};
185
- defer if (testing.allocator_instance.deinit() == .leak) {
186
- @panic("internal test runner memory leak");
187
- };
188
-
189
- const name_len = try server.receiveBody_u32();
190
- const name = try server.in.readAlloc(testing.allocator, @intCast(name_len));
191
- defer testing.allocator.free(name);
192
- for (0.., builtin.test_functions) |i, test_fn| {
193
- if (std.mem.eql(u8, name, test_fn.name)) {
194
- break :index i;
195
- }
196
- } else {
197
- std.debug.panic("fuzz test {s} no longer exists", .{name});
198
- }
176
+ var gpa_instance: std.heap.DebugAllocator(.{}) = .init;
177
+ defer if (gpa_instance.deinit() == .leak) {
178
+ @panic("internal test runner memory leak");
179
+ };
180
+ const gpa = gpa_instance.allocator();
181
+ var io_instance: Io.Threaded = .init(gpa, .{
182
+ .argv0 = .init(init.args),
183
+ .environ = init.environ,
199
184
  });
185
+ defer io_instance.deinit();
186
+ const io = io_instance.io();
187
+
200
188
  const mode: fuzz_abi.LimitKind = @enumFromInt(try server.receiveBody_u8());
201
189
  const amount_or_instance = try server.receiveBody_u64();
190
+ const main_instance = mode == .iterations or amount_or_instance == 0;
191
+
192
+ if (main_instance) {
193
+ const coverage = fuzz_abi.fuzzer_coverage();
194
+ try server.serveCoverageIdMessage(
195
+ coverage.id,
196
+ coverage.runs,
197
+ coverage.unique,
198
+ coverage.seen,
199
+ );
200
+ }
202
201
 
203
- const test_fn = builtin.test_functions[index];
204
- const entry_addr = @intFromPtr(test_fn.func);
202
+ const n_tests: u32 = try server.receiveBody_u32();
203
+ const test_indexes = try gpa.alloc(u32, n_tests);
204
+ defer gpa.free(test_indexes);
205
+ fuzz_runner = .{
206
+ .indexes = test_indexes,
207
+ .server = &server,
208
+ .gpa = gpa,
209
+ .io = io,
210
+ .input_poller = undefined,
211
+ };
205
212
 
206
- try server.serveU64Message(.fuzz_start_addr, fuzz_abi.fuzzer_unslide_address(entry_addr));
207
- defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1);
208
- is_fuzz_test = false;
209
- fuzz_test_index = index;
210
- fuzz_mode = mode;
211
- fuzz_amount_or_instance = amount_or_instance;
213
+ {
214
+ var large_name_buf: std.ArrayList(u8) = .empty;
215
+ defer large_name_buf.deinit(gpa);
216
+ for (test_indexes) |*i| {
217
+ const name_len = try server.receiveBody_u32();
218
+ const name = if (name_len <= server.in.buffer.len)
219
+ try server.in.take(name_len)
220
+ else large_name: {
221
+ try large_name_buf.resize(gpa, name_len);
222
+ try server.in.readSliceAll(large_name_buf.items);
223
+ break :large_name large_name_buf.items;
224
+ };
225
+
226
+ for (0.., builtin.test_functions) |test_i, test_fn| {
227
+ if (std.mem.eql(u8, name, test_fn.name)) {
228
+ i.* = @intCast(test_i);
229
+ break;
230
+ }
231
+ } else {
232
+ panic("fuzz test {s} no longer exists", .{name});
233
+ }
212
234
 
213
- test_fn.func() catch |err| switch (err) {
214
- error.SkipZigTest => return,
215
- else => {
216
- if (@errorReturnTrace()) |trace| {
217
- std.debug.dumpStackTrace(trace);
235
+ if (main_instance) {
236
+ const relocated_entry_addr = @intFromPtr(builtin.test_functions[i.*].func);
237
+ const entry_addr = fuzz_abi.fuzzer_unslide_address(relocated_entry_addr);
238
+ try server.serveU64Message(.fuzz_start_addr, entry_addr);
218
239
  }
219
- std.debug.print("failed with error.{t}\n", .{err});
220
- std.process.exit(1);
221
- },
222
- };
223
- if (!is_fuzz_test) @panic("missed call to std.testing.fuzz");
224
- if (log_err_count != 0) @panic("error logs detected");
240
+ }
241
+ }
242
+
243
+ fuzz_abi.fuzzer_main(n_tests, testing.random_seed, mode, amount_or_instance);
244
+
225
245
  assert(mode != .forever);
226
246
  std.process.exit(0);
227
247
  },
@@ -292,7 +312,7 @@ fn mainTerminal(init: std.process.Init.Minimal) void {
292
312
  std.debug.print("FAIL ({t})\n", .{err});
293
313
  }
294
314
  if (@errorReturnTrace()) |trace| {
295
- std.debug.dumpStackTrace(trace);
315
+ std.debug.dumpErrorReturnTrace(trace);
296
316
  }
297
317
  test_node.end();
298
318
  },
@@ -382,16 +402,126 @@ pub fn mainSimple() anyerror!void {
382
402
  passed += 1;
383
403
  }
384
404
  if (enable_print) {
385
- var stdout_writer = stdout.writer(runner_threaded_io, &.{});
386
- stdout_writer.interface.print("{} passed, {} skipped, {} failed\n", .{ passed, skipped, failed }) catch {};
405
+ var unbuffered_stdout_writer = stdout.writer(runner_threaded_io, &.{});
406
+ unbuffered_stdout_writer.interface.print(
407
+ "{} passed, {} skipped, {} failed\n",
408
+ .{ passed, skipped, failed },
409
+ ) catch {};
387
410
  }
388
411
  if (failed != 0) std.process.exit(1);
389
412
  }
390
413
 
391
414
  var is_fuzz_test: bool = undefined;
392
- var fuzz_test_index: u32 = undefined;
393
- var fuzz_mode: fuzz_abi.LimitKind = undefined;
394
- var fuzz_amount_or_instance: u64 = undefined;
415
+ var fuzz_runner: if (builtin.fuzz) struct {
416
+ indexes: []u32,
417
+ server: *std.zig.Server,
418
+ gpa: std.mem.Allocator,
419
+ io: Io,
420
+ input_poller: Io.Future(Io.Cancelable!void),
421
+
422
+ comptime {
423
+ assert(builtin.fuzz); // `fuzz_runner` was analyzed in non-fuzzing compilation
424
+ }
425
+
426
+ export fn runner_test_run(i: u32) void {
427
+ @disableInstrumentation();
428
+
429
+ fuzz_runner.server.serveU32Message(.fuzz_test_change, i) catch |e| switch (e) {
430
+ error.WriteFailed => panic("failed to write to stdout: {t}", .{stdout_writer.err.?}),
431
+ };
432
+
433
+ testing.allocator_instance = .{};
434
+ defer if (testing.allocator_instance.deinit() == .leak) std.process.exit(1);
435
+ is_fuzz_test = false;
436
+
437
+ builtin.test_functions[fuzz_runner.indexes[i]].func() catch |err| switch (err) {
438
+ error.SkipZigTest => return,
439
+ else => {
440
+ if (@errorReturnTrace()) |trace| {
441
+ std.debug.dumpErrorReturnTrace(trace);
442
+ }
443
+ std.debug.print("failed with error.{t}\n", .{err});
444
+ std.process.exit(1);
445
+ },
446
+ };
447
+
448
+ if (!is_fuzz_test) @panic("missed call to std.testing.fuzz");
449
+ if (log_err_count != 0) @panic("error logs detected");
450
+ }
451
+
452
+ export fn runner_test_name(i: u32) fuzz_abi.Slice {
453
+ @disableInstrumentation();
454
+ return .fromSlice(builtin.test_functions[fuzz_runner.indexes[i]].name);
455
+ }
456
+
457
+ export fn runner_broadcast_input(test_i: u32, bytes_slice: fuzz_abi.Slice) void {
458
+ @disableInstrumentation();
459
+ const bytes = bytes_slice.toSlice();
460
+ fuzz_runner.server.serveBroadcastFuzzInputMessage(test_i, bytes) catch |e| switch (e) {
461
+ error.WriteFailed => panic("failed to write to stdout: {t}", .{stdout_writer.err.?}),
462
+ };
463
+ }
464
+
465
+ export fn runner_start_input_poller() void {
466
+ @disableInstrumentation();
467
+ const future = fuzz_runner.io.concurrent(inputPoller, .{}) catch |e| switch (e) {
468
+ error.ConcurrencyUnavailable => @panic("failed to spawn concurrent fuzz input poller"),
469
+ };
470
+ fuzz_runner.input_poller = future;
471
+ }
472
+
473
+ export fn runner_stop_input_poller() void {
474
+ @disableInstrumentation();
475
+ assert(fuzz_runner.input_poller.cancel(fuzz_runner.io) == error.Canceled);
476
+ }
477
+
478
+ export fn runner_futex_wait(ptr: *const u32, expected: u32) bool {
479
+ @disableInstrumentation();
480
+ return fuzz_runner.io.futexWait(u32, ptr, expected) == error.Canceled;
481
+ }
482
+
483
+ export fn runner_futex_wake(ptr: *const u32, waiters: u32) void {
484
+ @disableInstrumentation();
485
+ fuzz_runner.io.futexWake(u32, ptr, waiters);
486
+ }
487
+
488
+ fn inputPoller() Io.Cancelable!void {
489
+ @disableInstrumentation();
490
+ switch (inputPollerInner()) {
491
+ error.Canceled => return error.Canceled,
492
+ error.ReadFailed => {
493
+ if (stdin_reader.err.? == error.Canceled) return error.Canceled;
494
+ panic("failed to read from stdin: {t}", .{stdin_reader.err.?});
495
+ },
496
+ error.EndOfStream => @panic("unexpected end of stdin"),
497
+ }
498
+ }
499
+
500
+ fn inputPollerInner() (Io.Cancelable || Io.Reader.Error) {
501
+ @disableInstrumentation();
502
+ const server = fuzz_runner.server;
503
+ var large_bytes_list: std.ArrayList(u8) = .empty;
504
+ defer large_bytes_list.deinit(fuzz_runner.gpa);
505
+ while (true) {
506
+ const hdr = try server.receiveMessage();
507
+ if (hdr.tag != .new_fuzz_input) {
508
+ panic("unexpected message: {x}\n", .{@intFromEnum(hdr.tag)});
509
+ }
510
+ const test_i = try server.receiveBody_u32();
511
+ const input_len = hdr.bytes_len - 4;
512
+ const bytes = if (input_len <= server.in.buffer.len)
513
+ try server.in.take(input_len)
514
+ else bytes: {
515
+ large_bytes_list.resize(fuzz_runner.gpa, @intCast(input_len)) catch @panic("OOM");
516
+ try server.in.readSliceAll(large_bytes_list.items);
517
+ break :bytes large_bytes_list.items;
518
+ };
519
+ if (fuzz_abi.fuzzer_receive_input(test_i, .fromSlice(bytes))) {
520
+ return error.Canceled;
521
+ }
522
+ }
523
+ }
524
+ } else void = undefined;
395
525
 
396
526
  pub fn fuzz(
397
527
  context: anytype,
@@ -448,16 +578,18 @@ pub fn fuzz(
448
578
  return false;
449
579
  }
450
580
  };
581
+
451
582
  if (builtin.fuzz) {
583
+ // Preserve the calling test's allocator state
452
584
  const prev_allocator_state = testing.allocator_instance;
453
585
  testing.allocator_instance = .{};
454
586
  defer testing.allocator_instance = prev_allocator_state;
455
- global.ctx = context;
456
587
 
457
- fuzz_abi.fuzzer_set_test(&global.test_one, .fromSlice(builtin.test_functions[fuzz_test_index].name));
588
+ global.ctx = context;
589
+ fuzz_abi.fuzzer_set_test(&global.test_one);
458
590
  for (options.corpus) |elem|
459
591
  fuzz_abi.fuzzer_new_input(.fromSlice(elem));
460
- fuzz_abi.fuzzer_main(fuzz_mode, fuzz_amount_or_instance);
592
+ fuzz_abi.fuzzer_start_test();
461
593
  return;
462
594
  }
463
595
 
@@ -266,7 +266,8 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
266
266
  const lit_bytes = mt.tokSlice();
267
267
  mt.i += 1;
268
268
 
269
- var bytes = try std.ArrayList(u8).initCapacity(arena, lit_bytes.len + 3);
269
+ // +3 for prefix and +2 for suffix
270
+ var bytes = try std.ArrayList(u8).initCapacity(arena, lit_bytes.len + 3 + 2);
270
271
 
271
272
  const prefix = aro.Tree.Token.NumberPrefix.fromString(lit_bytes);
272
273
  switch (prefix) {
@@ -350,13 +351,21 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode {
350
351
  if (is_float) {
351
352
  const type_node = try ZigTag.type.create(arena, switch (suffix) {
352
353
  .F16 => "f16",
353
- .F => "f32",
354
- .None => "f64",
355
- .L => "c_longdouble",
354
+ .F, .F32 => "f32",
355
+ .None, .F32x, .F64 => "f64",
356
+ .L, .F64x => "c_longdouble",
356
357
  .W => "f80",
357
358
  .Q, .F128 => "f128",
358
- else => unreachable,
359
+ else => {
360
+ try mt.fail("TODO: float literal suffix: '{s}'", .{suffix_str});
361
+ return error.ParseError;
362
+ },
359
363
  });
364
+ if (bytes.getLast() == '.') {
365
+ bytes.appendAssumeCapacity('0');
366
+ } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) {
367
+ bytes.appendSliceAssumeCapacity(".0");
368
+ }
360
369
  const rhs = try ZigTag.float_literal.create(arena, bytes.items);
361
370
  return ZigTag.as.create(arena, .{ .lhs = type_node, .rhs = rhs });
362
371
  } else {
@@ -582,6 +591,7 @@ fn escapeUnprintables(mt: *MacroTranslator) ![]const u8 {
582
591
 
583
592
  fn parseCPrimaryExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
584
593
  const arena = mt.t.arena;
594
+ const gpa = mt.t.gpa;
585
595
  const tok = mt.peek();
586
596
  switch (tok) {
587
597
  .char_literal,
@@ -646,6 +656,51 @@ fn parseCPrimaryExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
646
656
  }
647
657
  return identifier;
648
658
  },
659
+ .keyword_generic => {
660
+ mt.i += 1;
661
+
662
+ try mt.expect(.l_paren);
663
+ const param = try mt.parseCCondExpr(scope);
664
+ const typeof_param = try ZigTag.typeof.create(arena, param);
665
+ try mt.expect(.comma);
666
+
667
+ var cases: std.ArrayList(ZigNode) = .empty;
668
+ defer cases.deinit(gpa);
669
+ var has_default = false;
670
+ while (true) {
671
+ const case = if (mt.eat(.keyword_default)) blk: {
672
+ has_default = true;
673
+ try mt.expect(.colon);
674
+ const expr = try mt.parseCCondExpr(scope);
675
+ break :blk try ZigTag.switch_else.create(arena, expr);
676
+ } else blk: {
677
+ const case_type = try mt.parseCTypeName(scope) orelse {
678
+ try mt.fail("unable to translate C expr: expected type instead got '{s}'", .{mt.peek().symbol()});
679
+ return error.ParseError;
680
+ };
681
+ try mt.expect(.colon);
682
+ const expr = try mt.parseCCondExpr(scope);
683
+ break :blk try ZigTag.switch_prong.create(arena, .{
684
+ .cases = try arena.dupe(ZigNode, &.{case_type}),
685
+ .cond = expr,
686
+ });
687
+ };
688
+ try cases.append(gpa, case);
689
+ if (!mt.eat(.comma)) break;
690
+ }
691
+ try mt.expect(.r_paren);
692
+
693
+ if (!has_default) try cases.append(gpa, try ZigTag.switch_else.create(
694
+ arena,
695
+ try ZigTag.@"comptime".create(arena, ZigTag.@"unreachable".init()),
696
+ ));
697
+
698
+ const sw = try ZigTag.@"switch".create(arena, .{
699
+ .cond = typeof_param,
700
+ .cases = try arena.dupe(ZigNode, cases.items),
701
+ });
702
+ return sw;
703
+ },
649
704
  else => {},
650
705
  }
651
706
 
@@ -678,8 +733,10 @@ fn macroIntToBool(mt: *MacroTranslator, node: ZigNode) !ZigNode {
678
733
  }
679
734
 
680
735
  fn parseCCondExpr(mt: *MacroTranslator, scope: *Scope) ParseError!ZigNode {
681
- const node = try mt.parseCOrExpr(scope);
682
- if (!mt.eat(.question_mark)) return node;
736
+ const condition = try mt.parseCOrExpr(scope);
737
+ if (!mt.eat(.question_mark)) return condition;
738
+ const bool_ty = try ZigTag.type.create(mt.t.arena, "bool");
739
+ const node = try mt.t.createHelperCallNode(.cast, &.{ bool_ty, condition });
683
740
 
684
741
  const then_body = try mt.parseCOrExpr(scope);
685
742
  try mt.expect(.colon);
@@ -1135,6 +1192,8 @@ fn parseCPostfixExpr(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNode) P
1135
1192
  .string_literal_utf_8,
1136
1193
  .string_literal_utf_32,
1137
1194
  .string_literal_wide,
1195
+ .macro_param,
1196
+ .macro_param_no_expand,
1138
1197
  => {},
1139
1198
  .identifier, .extended_identifier => {
1140
1199
  if (mt.t.global_scope.blank_macros.contains(mt.tokSlice())) {
@@ -1160,8 +1219,13 @@ fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNo
1160
1219
  mt.i += 1;
1161
1220
  const tok = mt.tokens[mt.i];
1162
1221
  if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
1163
- try mt.fail("unable to translate C expr: field access using macro parameter", .{});
1164
- return error.ParseError;
1222
+ const param = mt.macro.params[tok.end];
1223
+ mt.i += 1;
1224
+
1225
+ const mangled_name = scope.getAlias(param) orelse param;
1226
+ const field_name = try ZigTag.identifier.create(arena, mangled_name);
1227
+ node = try ZigTag.field_builtin.create(arena, .{ .lhs = node, .rhs = field_name });
1228
+ continue;
1165
1229
  }
1166
1230
  const field_name = mt.tokSlice();
1167
1231
  try mt.expect(.identifier);
@@ -1172,8 +1236,13 @@ fn parseCPostfixExprInner(mt: *MacroTranslator, scope: *Scope, type_name: ?ZigNo
1172
1236
  mt.i += 1;
1173
1237
  const tok = mt.tokens[mt.i];
1174
1238
  if (tok.id == .macro_param or tok.id == .macro_param_no_expand) {
1175
- try mt.fail("unable to translate C expr: field access using macro parameter", .{});
1176
- return error.ParseError;
1239
+ const param = mt.macro.params[tok.end];
1240
+ mt.i += 1;
1241
+
1242
+ const mangled_name = scope.getAlias(param) orelse param;
1243
+ const field_name = try ZigTag.identifier.create(arena, mangled_name);
1244
+ node = try ZigTag.field_builtin.create(arena, .{ .lhs = node, .rhs = field_name });
1245
+ continue;
1177
1246
  }
1178
1247
  const field_name = mt.tokSlice();
1179
1248
  try mt.expect(.identifier);
@@ -65,10 +65,7 @@ const templates = [_]Template{
65
65
  .{ "CAST_OR_CALL(X, Y) ((X)(Y))", .CAST_OR_CALL },
66
66
 
67
67
  .{
68
- \\wl_container_of(ptr, sample, member) \
69
- \\(__typeof__(sample))((char *)(ptr) - \
70
- \\ offsetof(__typeof__(*sample), member))
71
- ,
68
+ "wl_container_of(ptr, sample, member) (__typeof__(sample))((char *)(ptr) - offsetof(__typeof__(*sample), member))",
72
69
  .WL_CONTAINER_OF,
73
70
  },
74
71
 
@@ -267,11 +264,6 @@ test "Macro matching" {
267
264
  try helper.checkMacro(allocator, pattern_list, "BAR(Z) (Z ## LL)", .LL_SUFFIX);
268
265
  try helper.checkMacro(allocator, pattern_list, "BAR(Z) (Z ## UL)", .UL_SUFFIX);
269
266
  try helper.checkMacro(allocator, pattern_list, "BAR(Z) (Z ## ULL)", .ULL_SUFFIX);
270
- try helper.checkMacro(allocator, pattern_list,
271
- \\container_of(a, b, c) \
272
- \\(__typeof__(b))((char *)(a) - \
273
- \\ offsetof(__typeof__(*b), c))
274
- , .WL_CONTAINER_OF);
275
267
 
276
268
  try helper.checkMacro(allocator, pattern_list, "NO_MATCH(X, Y) (X + Y)", null);
277
269
  try helper.checkMacro(allocator, pattern_list, "CAST_OR_CALL(X, Y) (X)(Y)", .CAST_OR_CALL);
@@ -18,7 +18,22 @@ pub const ContainerMemberFns = struct {
18
18
  container_decl_ptr: *ast.Node,
19
19
  member_fns: std.ArrayList(*ast.Payload.Func) = .empty,
20
20
  };
21
- pub const ContainerMemberFnsHashMap = std.AutoArrayHashMapUnmanaged(aro.QualType, ContainerMemberFns);
21
+ pub const ContainerMemberFnsHashMap = std.ArrayHashMapUnmanaged(
22
+ aro.QualType,
23
+ ContainerMemberFns,
24
+ struct {
25
+ pub fn hash(self: @This(), key: aro.QualType) u32 {
26
+ const auto_hash = std.array_hash_map.getAutoHashFn(aro.QualType, @This());
27
+ return auto_hash(self, key.unqualified());
28
+ }
29
+
30
+ pub fn eql(self: @This(), a: aro.QualType, b: aro.QualType, b_index: usize) bool {
31
+ const auto_eql = std.array_hash_map.getAutoEqlFn(aro.QualType, @This());
32
+ return auto_eql(self, a.unqualified(), b.unqualified(), b_index);
33
+ }
34
+ },
35
+ false,
36
+ );
22
37
 
23
38
  id: Id,
24
39
  parent: ?*Scope,
@@ -254,7 +269,12 @@ pub const Root = struct {
254
269
 
255
270
  var member_names: std.StringArrayHashMapUnmanaged(void) = .empty;
256
271
  defer member_names.deinit(gpa);
257
- for (root.container_member_fns_map.values()) |members| {
272
+ for (root.container_member_fns_map.keys(), root.container_member_fns_map.values()) |container_qt, members| {
273
+ // Get the container name
274
+ const container_name = root.translator.unnamed_typedefs.get(container_qt) orelse
275
+ container_qt.getRecord(root.translator.comp).?.name.lookup(root.translator.comp);
276
+ std.debug.assert(container_name.len > 0);
277
+
258
278
  member_names.clearRetainingCapacity();
259
279
  const decls_ptr = switch (members.container_decl_ptr.tag()) {
260
280
  .@"struct", .@"union" => blk_record: {
@@ -274,7 +294,7 @@ pub const Root = struct {
274
294
  members.container_decl_ptr.* = container_decl;
275
295
  break :blk_opaque &container_decl.castTag(.@"opaque").?.data.decls;
276
296
  },
277
- else => return,
297
+ else => continue,
278
298
  };
279
299
 
280
300
  const old_decls = decls_ptr.*;
@@ -299,9 +319,26 @@ pub const Root = struct {
299
319
 
300
320
  for (members.member_fns.items) |func| {
301
321
  const func_name = func.data.name.?;
302
- const func_name_trimmed = std.mem.trimEnd(u8, func_name, "_");
303
- const last_idx = std.mem.findLast(u8, func_name_trimmed, "_") orelse continue;
304
- const func_name_alias = func_name[last_idx + 1 ..];
322
+ const func_name_alias = blk: {
323
+ // Try multiple candidate prefixes to extract the alias
324
+ // 1. typedef struct { ... } foo; -> foo_get_bar() extracts "get_bar"
325
+ // 2. typedef struct _foo foo; -> foo_get_bar() extracts "get_bar"
326
+ const container_name_trimmed = std.mem.trimStart(u8, container_name, "_");
327
+ const suffix = std.mem.cutPrefix(u8, func_name, container_name_trimmed);
328
+ // Check suffix starts with '_' to avoid invalid aliases like "1_get_bar" from foo1_get_bar()
329
+ if (suffix) |alias| if (alias.len > 0 and alias[0] == '_') {
330
+ const alias_trimmed = std.mem.trimStart(u8, alias, "_");
331
+ if (alias_trimmed.len > 0) break :blk alias_trimmed;
332
+ };
333
+
334
+ // Doesn't match any prefix - fallback to trimming trailing underscores and using last segment
335
+ const func_name_trimmed = std.mem.trimEnd(u8, func_name, "_");
336
+ const last_idx = std.mem.findLast(u8, func_name_trimmed, "_") orelse continue;
337
+ break :blk func_name[last_idx + 1 ..];
338
+ };
339
+
340
+ // Skip if the alias conflicts with an existing type
341
+ if (root.contains(func_name_alias)) continue;
305
342
  const member_name_slot = try member_names.getOrPutValue(gpa, func_name_alias, {});
306
343
  if (member_name_slot.found_existing) continue;
307
344
  func_ref_vars[count] = try ast.Node.Tag.pub_var_simple.create(arena, .{