@zigc/lib 0.16.0-test.1 → 0.17.0-dev.9

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 (242) 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 +2 -18
  111. package/std/os/linux/arc.zig +144 -0
  112. package/std/os/linux.zig +21 -4
  113. package/std/os/windows.zig +2 -2
  114. package/std/pdb.zig +143 -4
  115. package/std/posix.zig +6 -12
  116. package/std/priority_dequeue.zig +13 -12
  117. package/std/priority_queue.zig +5 -4
  118. package/std/process/Child.zig +1 -1
  119. package/std/process/Environ.zig +1 -1
  120. package/std/start.zig +17 -4
  121. package/std/std.zig +19 -6
  122. package/std/testing/FailingAllocator.zig +4 -4
  123. package/std/testing/Smith.zig +37 -2
  124. package/std/zig/Ast/Render.zig +186 -458
  125. package/std/zig/Ast.zig +0 -4
  126. package/std/zig/AstGen.zig +44 -7
  127. package/std/zig/AstSmith.zig +2602 -0
  128. package/std/zig/Client.zig +8 -3
  129. package/std/zig/Parse.zig +83 -74
  130. package/std/zig/Server.zig +26 -0
  131. package/std/zig/Zir.zig +17 -0
  132. package/std/zig/c_translation/helpers.zig +14 -9
  133. package/std/zig/llvm/Builder.zig +107 -48
  134. package/std/zig/system.zig +20 -4
  135. package/std/zig/tokenizer.zig +2 -1
  136. package/std/zig.zig +6 -0
  137. package/compiler/aro/aro/Driver/Filesystem.zig +0 -241
  138. package/libc/mingw/complex/cabs.c +0 -48
  139. package/libc/mingw/complex/cabsf.c +0 -48
  140. package/libc/mingw/complex/cacos.c +0 -50
  141. package/libc/mingw/complex/cacosf.c +0 -50
  142. package/libc/mingw/complex/carg.c +0 -48
  143. package/libc/mingw/complex/cargf.c +0 -48
  144. package/libc/mingw/complex/casin.c +0 -50
  145. package/libc/mingw/complex/casinf.c +0 -50
  146. package/libc/mingw/complex/catan.c +0 -50
  147. package/libc/mingw/complex/catanf.c +0 -50
  148. package/libc/mingw/complex/ccos.c +0 -50
  149. package/libc/mingw/complex/ccosf.c +0 -50
  150. package/libc/mingw/complex/cexp.c +0 -48
  151. package/libc/mingw/complex/cexpf.c +0 -48
  152. package/libc/mingw/complex/cimag.c +0 -48
  153. package/libc/mingw/complex/cimagf.c +0 -48
  154. package/libc/mingw/complex/clog.c +0 -48
  155. package/libc/mingw/complex/clog10.c +0 -49
  156. package/libc/mingw/complex/clog10f.c +0 -49
  157. package/libc/mingw/complex/clogf.c +0 -48
  158. package/libc/mingw/complex/conj.c +0 -48
  159. package/libc/mingw/complex/conjf.c +0 -48
  160. package/libc/mingw/complex/cpow.c +0 -48
  161. package/libc/mingw/complex/cpowf.c +0 -48
  162. package/libc/mingw/complex/cproj.c +0 -48
  163. package/libc/mingw/complex/cprojf.c +0 -48
  164. package/libc/mingw/complex/creal.c +0 -48
  165. package/libc/mingw/complex/crealf.c +0 -48
  166. package/libc/mingw/complex/csin.c +0 -50
  167. package/libc/mingw/complex/csinf.c +0 -50
  168. package/libc/mingw/complex/csqrt.c +0 -48
  169. package/libc/mingw/complex/csqrtf.c +0 -48
  170. package/libc/mingw/complex/ctan.c +0 -50
  171. package/libc/mingw/complex/ctanf.c +0 -50
  172. package/libc/mingw/math/arm/s_rint.c +0 -86
  173. package/libc/mingw/math/arm/s_rintf.c +0 -51
  174. package/libc/mingw/math/arm/sincos.S +0 -30
  175. package/libc/mingw/math/arm-common/sincosl.c +0 -13
  176. package/libc/mingw/math/arm64/rint.c +0 -12
  177. package/libc/mingw/math/arm64/rintf.c +0 -12
  178. package/libc/mingw/math/arm64/sincos.S +0 -32
  179. package/libc/mingw/math/bsd_private_base.h +0 -148
  180. package/libc/mingw/math/frexpf.c +0 -13
  181. package/libc/mingw/math/frexpl.c +0 -71
  182. package/libc/mingw/math/x86/acosf.c +0 -29
  183. package/libc/mingw/math/x86/atanf.c +0 -23
  184. package/libc/mingw/math/x86/atanl.c +0 -18
  185. package/libc/mingw/math/x86/cos.def.h +0 -65
  186. package/libc/mingw/math/x86/cosl.c +0 -46
  187. package/libc/mingw/math/x86/cosl_internal.S +0 -55
  188. package/libc/mingw/math/x86/ldexp.c +0 -23
  189. package/libc/mingw/math/x86/scalbn.S +0 -41
  190. package/libc/mingw/math/x86/scalbnf.S +0 -40
  191. package/libc/mingw/math/x86/sin.def.h +0 -65
  192. package/libc/mingw/math/x86/sinl.c +0 -46
  193. package/libc/mingw/math/x86/sinl_internal.S +0 -58
  194. package/libc/mingw/math/x86/tanl.S +0 -62
  195. package/libc/mingw/misc/btowc.c +0 -28
  196. package/libc/mingw/misc/wcstof.c +0 -66
  197. package/libc/mingw/misc/wcstoimax.c +0 -132
  198. package/libc/mingw/misc/wcstoumax.c +0 -126
  199. package/libc/mingw/misc/wctob.c +0 -29
  200. package/libc/mingw/misc/winbs_uint64.c +0 -6
  201. package/libc/mingw/misc/winbs_ulong.c +0 -6
  202. package/libc/mingw/misc/winbs_ushort.c +0 -6
  203. package/libc/mingw/stdio/_Exit.c +0 -10
  204. package/libc/mingw/stdio/_findfirst64i32.c +0 -21
  205. package/libc/mingw/stdio/_findnext64i32.c +0 -21
  206. package/libc/mingw/stdio/_fstat64i32.c +0 -37
  207. package/libc/mingw/stdio/_stat64i32.c +0 -37
  208. package/libc/mingw/stdio/_wfindfirst64i32.c +0 -21
  209. package/libc/mingw/stdio/_wfindnext64i32.c +0 -21
  210. package/libc/mingw/stdio/_wstat64i32.c +0 -37
  211. package/libc/musl/src/legacy/isastream.c +0 -7
  212. package/libc/musl/src/legacy/valloc.c +0 -8
  213. package/libc/musl/src/math/__cosl.c +0 -96
  214. package/libc/musl/src/math/__sinl.c +0 -78
  215. package/libc/musl/src/math/__tanl.c +0 -143
  216. package/libc/musl/src/math/aarch64/lrint.c +0 -10
  217. package/libc/musl/src/math/aarch64/lrintf.c +0 -10
  218. package/libc/musl/src/math/aarch64/rintf.c +0 -7
  219. package/libc/musl/src/math/cosl.c +0 -39
  220. package/libc/musl/src/math/fdim.c +0 -10
  221. package/libc/musl/src/math/finite.c +0 -7
  222. package/libc/musl/src/math/finitef.c +0 -7
  223. package/libc/musl/src/math/frexp.c +0 -23
  224. package/libc/musl/src/math/frexpf.c +0 -23
  225. package/libc/musl/src/math/frexpl.c +0 -29
  226. package/libc/musl/src/math/i386/lrint.c +0 -8
  227. package/libc/musl/src/math/i386/lrintf.c +0 -8
  228. package/libc/musl/src/math/i386/rintf.c +0 -7
  229. package/libc/musl/src/math/lrint.c +0 -72
  230. package/libc/musl/src/math/lrintf.c +0 -8
  231. package/libc/musl/src/math/powerpc64/lrint.c +0 -16
  232. package/libc/musl/src/math/powerpc64/lrintf.c +0 -16
  233. package/libc/musl/src/math/rintf.c +0 -30
  234. package/libc/musl/src/math/s390x/rintf.c +0 -15
  235. package/libc/musl/src/math/sincosl.c +0 -60
  236. package/libc/musl/src/math/sinl.c +0 -41
  237. package/libc/musl/src/math/tanl.c +0 -29
  238. package/libc/musl/src/math/x32/lrint.s +0 -5
  239. package/libc/musl/src/math/x32/lrintf.s +0 -5
  240. package/libc/musl/src/math/x86_64/lrint.c +0 -8
  241. package/libc/musl/src/math/x86_64/lrintf.c +0 -8
  242. package/libc/wasi/libc-bottom-half/sources/reallocarray.c +0 -14
package/std/debug.zig CHANGED
@@ -13,7 +13,6 @@ const windows = std.os.windows;
13
13
  const builtin = @import("builtin");
14
14
  const native_arch = builtin.cpu.arch;
15
15
  const native_os = builtin.os.tag;
16
- const StackTrace = std.builtin.StackTrace;
17
16
 
18
17
  const root = @import("root");
19
18
 
@@ -39,8 +38,8 @@ pub const cpu_context = @import("debug/cpu_context.zig");
39
38
  /// pub const init: SelfInfo;
40
39
  /// pub fn deinit(si: *SelfInfo, io: Io) void;
41
40
  ///
42
- /// /// Returns the symbol and source location of the instruction at `address`.
43
- /// pub fn getSymbol(si: *SelfInfo, io: Io, address: usize) SelfInfoError!Symbol;
41
+ /// /// Appends the symbols for the instruction at `address` to `symbols`.
42
+ /// pub fn getSymbols(si: *SelfInfo, io: Io, symbol_allocator: Allocator, text_arena: Allocator, address: usize, include_inline_callers: bool, symbols: *std.ArrayList(Symbol)) SelfInfoError!void;
44
43
  /// /// Returns a name for the "module" (e.g. shared library or executable image) containing `address`.
45
44
  /// pub fn getModuleName(si: *SelfInfo, io: Io, address: usize) SelfInfoError![]const u8;
46
45
  /// pub fn getModuleSlide(si: *SelfInfo, io: Io, address: usize) SelfInfoError!usize;
@@ -563,7 +562,7 @@ pub fn defaultPanic(msg: []const u8, first_trace_addr: ?usize) noreturn {
563
562
 
564
563
  if (@errorReturnTrace()) |t| if (t.index > 0) {
565
564
  writer.writeAll("error return context:\n") catch break :trace;
566
- writeStackTrace(t, stderr) catch break :trace;
565
+ writeErrorReturnTrace(t, stderr) catch break :trace;
567
566
  writer.writeAll("\nstack trace:\n") catch break :trace;
568
567
  };
569
568
  writeCurrentStackTrace(.{
@@ -602,6 +601,35 @@ fn waitForOtherThreadToFinishPanicking() void {
602
601
  }
603
602
  }
604
603
 
604
+ pub const StackTrace = struct {
605
+ /// Each element is the "return address" of a function call, meaning the instruction address
606
+ /// which control flow will return to when the function returns.
607
+ ///
608
+ /// The first slice element corresponds to the innermost stack frame, and the last element to
609
+ /// the outermost.
610
+ ///
611
+ /// Inlined function calls do not have meaningful return addresses and are therefore not
612
+ /// included in this slice. Instead, when printing the stack trace, the source locations of
613
+ /// inline calls should be read from debug information and the corresponding "inline frames"
614
+ /// printed in the appropriate locations.
615
+ return_addresses: []usize,
616
+ /// Indicates whether any stack frames were omitted from `return_addresses`.
617
+ skipped: SkippedAddresses,
618
+ };
619
+
620
+ /// Indicates how many addresses were skipped in a trace.
621
+ pub const SkippedAddresses = enum(usize) {
622
+ /// No addresses were omitted: `return_addresses` contains all stack frames, including the
623
+ /// outermost.
624
+ none = 0,
625
+ /// It is not known whether any frames were omitted.
626
+ unknown = std.math.maxInt(usize),
627
+ /// The full stack trace was available, but some frames are not included in
628
+ /// `return_addresses` due to buffer size limitations. The enum value is the exact number of
629
+ /// addresses which were omitted.
630
+ _,
631
+ };
632
+
605
633
  pub const StackUnwindOptions = struct {
606
634
  /// If not `null`, we will ignore all frames up until this return address. This is typically
607
635
  /// used to omit intermediate handling code (for instance, a panic handler and its machinery)
@@ -621,7 +649,10 @@ pub const StackUnwindOptions = struct {
621
649
  ///
622
650
  /// See `writeCurrentStackTrace` to immediately print the trace instead of capturing it.
623
651
  pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf: []usize) StackTrace {
624
- const empty_trace: StackTrace = .{ .index = 0, .instruction_addresses = &.{} };
652
+ const empty_trace: StackTrace = .{
653
+ .return_addresses = &.{},
654
+ .skipped = .none,
655
+ };
625
656
  if (!std.options.allow_stack_tracing) return empty_trace;
626
657
  var it: StackIterator = .init(options.context);
627
658
  defer it.deinit();
@@ -632,17 +663,17 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
632
663
  var total_frames: usize = 0;
633
664
  var index: usize = 0;
634
665
  var wait_for = options.first_address;
635
- // Ideally, we would iterate the whole stack so that the `index` in the returned trace was
666
+ // Ideally, we would iterate the whole stack so that the `index - min(buf.len, index)` would be
636
667
  // indicative of how many frames were skipped. However, this has a significant runtime cost
637
668
  // in some cases, so at least for now, we don't do that.
638
- while (index < addr_buf.len) switch (it.next(io)) {
639
- .switch_to_fp => if (!it.stratOk(options.allow_unsafe_unwind)) break,
640
- .end => break,
669
+ const skipped: SkippedAddresses = while (index < addr_buf.len) switch (it.next(io)) {
670
+ .switch_to_fp => if (!it.stratOk(options.allow_unsafe_unwind)) break .unknown,
671
+ .end => break .none,
641
672
  .frame => |ret_addr| {
642
673
  if (total_frames > 10_000) {
643
674
  // Limit the number of frames in case of (e.g.) broken debug information which is
644
675
  // getting unwinding stuck in a loop.
645
- break;
676
+ break .unknown;
646
677
  }
647
678
  total_frames += 1;
648
679
  if (wait_for) |target| {
@@ -652,10 +683,10 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
652
683
  addr_buf[index] = ret_addr;
653
684
  index += 1;
654
685
  },
655
- };
686
+ } else .unknown;
656
687
  return .{
657
- .index = index,
658
- .instruction_addresses = addr_buf[0..index],
688
+ .return_addresses = addr_buf[0..index],
689
+ .skipped = skipped,
659
690
  };
660
691
  }
661
692
  /// Write the current stack trace to `writer`, annotated with source locations.
@@ -663,6 +694,10 @@ pub noinline fn captureCurrentStackTrace(options: StackUnwindOptions, addr_buf:
663
694
  /// See `captureCurrentStackTrace` to capture the trace addresses into a buffer instead of printing.
664
695
  pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Terminal) Writer.Error!void {
665
696
  const writer = t.writer;
697
+
698
+ var text_arena: std.heap.ArenaAllocator = .init(getDebugInfoAllocator());
699
+ defer text_arena.deinit();
700
+
666
701
  if (!std.options.allow_stack_tracing) {
667
702
  t.setColor(.dim) catch {};
668
703
  try writer.print("Cannot print stack trace: stack tracing is disabled\n", .{});
@@ -740,7 +775,10 @@ pub noinline fn writeCurrentStackTrace(options: StackUnwindOptions, t: Io.Termin
740
775
  }
741
776
  // `ret_addr` is the return address, which is *after* the function call.
742
777
  // Subtract 1 to get an address *in* the function call for a better source location.
743
- try printSourceAtAddress(io, di, t, ret_addr -| StackIterator.ra_call_offset);
778
+ try printSourceAtAddress(io, &text_arena, di, t, .{
779
+ .address = ret_addr -| StackIterator.ra_call_offset,
780
+ .resolve_inline_callers = true,
781
+ });
744
782
  printed_any_frame = true;
745
783
  },
746
784
  };
@@ -773,8 +811,29 @@ pub const FormatStackTrace = struct {
773
811
  }
774
812
  };
775
813
 
814
+ /// Write a previously captured error return trace to `writer`, annotated with source locations.
815
+ pub fn writeErrorReturnTrace(et: *const std.builtin.StackTrace, t: Io.Terminal) Writer.Error!void {
816
+ // We take the slice by value, preventing the length from being mutated if an error occurs while
817
+ // writing the stack trace.
818
+ const len = @min(et.instruction_addresses.len, et.index);
819
+ const skipped = et.index - len;
820
+ try writeTrace(et.instruction_addresses[0..len], @enumFromInt(skipped), t, false);
821
+ }
822
+
776
823
  /// Write a previously captured stack trace to `writer`, annotated with source locations.
777
824
  pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void {
825
+ try writeTrace(st.return_addresses, st.skipped, t, true);
826
+ }
827
+
828
+ fn writeTrace(
829
+ addresses: []const usize,
830
+ skipped: SkippedAddresses,
831
+ t: Io.Terminal,
832
+ resolve_inline_callers: bool,
833
+ ) Writer.Error!void {
834
+ var text_arena: std.heap.ArenaAllocator = .init(getDebugInfoAllocator());
835
+ defer text_arena.deinit();
836
+
778
837
  const writer = t.writer;
779
838
  if (!std.options.allow_stack_tracing) {
780
839
  t.setColor(.dim) catch {};
@@ -783,10 +842,7 @@ pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void
783
842
  return;
784
843
  }
785
844
 
786
- // Fetch `st.index` straight away. Aside from avoiding redundant loads, this prevents issues if
787
- // `st` is `@errorReturnTrace()` and errors are encountered while writing the stack trace.
788
- const n_frames = st.index;
789
- if (n_frames == 0) return writer.writeAll("(empty stack trace)\n");
845
+ if (addresses.len == 0) return writer.writeAll("(empty stack trace)\n");
790
846
  const di = getSelfDebugInfo() catch |err| switch (err) {
791
847
  error.UnsupportedTarget => {
792
848
  t.setColor(.dim) catch {};
@@ -796,16 +852,26 @@ pub fn writeStackTrace(st: *const StackTrace, t: Io.Terminal) Writer.Error!void
796
852
  },
797
853
  };
798
854
  const io = std.Options.debug_io;
799
- const captured_frames = @min(n_frames, st.instruction_addresses.len);
800
- for (st.instruction_addresses[0..captured_frames]) |ret_addr| {
801
- // `ret_addr` is the return address, which is *after* the function call.
855
+ for (addresses) |addr| {
856
+ // `addr` is the return address, which is *after* the function call.
802
857
  // Subtract 1 to get an address *in* the function call for a better source location.
803
- try printSourceAtAddress(io, di, t, ret_addr -| StackIterator.ra_call_offset);
858
+ try printSourceAtAddress(io, &text_arena, di, t, .{
859
+ .address = addr -| StackIterator.ra_call_offset,
860
+ .resolve_inline_callers = resolve_inline_callers,
861
+ });
804
862
  }
805
- if (n_frames > captured_frames) {
806
- t.setColor(.bold) catch {};
807
- try writer.print("({d} additional stack frames skipped...)\n", .{n_frames - captured_frames});
808
- t.setColor(.reset) catch {};
863
+ switch (skipped) {
864
+ .none => {},
865
+ .unknown => {
866
+ t.setColor(.bold) catch {};
867
+ try writer.writeAll("(additional stack frames may have been skipped...)\n");
868
+ t.setColor(.reset) catch {};
869
+ },
870
+ else => |n| {
871
+ t.setColor(.bold) catch {};
872
+ try writer.print("({d} additional stack frames skipped due to buffer size limitations...)\n", .{n});
873
+ t.setColor(.reset) catch {};
874
+ },
809
875
  }
810
876
  }
811
877
  /// A thin wrapper around `writeStackTrace` which writes to stderr and ignores write errors.
@@ -817,6 +883,15 @@ pub fn dumpStackTrace(st: *const StackTrace) void {
817
883
  };
818
884
  }
819
885
 
886
+ /// A thin wrapper around `writeErrorReturnTrace` which writes to stderr and ignores write errors.
887
+ pub fn dumpErrorReturnTrace(et: *const std.builtin.StackTrace) void {
888
+ const stderr = lockStderr(&.{}).terminal();
889
+ defer unlockStderr();
890
+ writeErrorReturnTrace(et, stderr) catch |err| switch (err) {
891
+ error.WriteFailed => {},
892
+ };
893
+ }
894
+
820
895
  const StackIterator = union(enum) {
821
896
  /// We will first report the current PC of this `CpuContextPtr`, then we will switch to a
822
897
  /// different strategy to actually unwind.
@@ -1106,48 +1181,77 @@ pub inline fn stripInstructionPtrAuthCode(ptr: usize) usize {
1106
1181
  return ptr;
1107
1182
  }
1108
1183
 
1109
- fn printSourceAtAddress(io: Io, debug_info: *SelfInfo, t: Io.Terminal, address: usize) Writer.Error!void {
1110
- const symbol: Symbol = debug_info.getSymbol(io, address) catch |err| switch (err) {
1111
- error.MissingDebugInfo,
1112
- error.UnsupportedDebugInfo,
1113
- error.InvalidDebugInfo,
1114
- => .unknown,
1115
- error.ReadFailed, error.Unexpected, error.Canceled => s: {
1116
- t.setColor(.dim) catch {};
1117
- try t.writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{});
1118
- t.setColor(.reset) catch {};
1119
- break :s .unknown;
1120
- },
1121
- error.OutOfMemory => s: {
1122
- t.setColor(.dim) catch {};
1123
- try t.writer.print("Ran out of memory loading debug info, trace may be incomplete\n\n", .{});
1124
- t.setColor(.reset) catch {};
1125
- break :s .unknown;
1126
- },
1127
- };
1128
- defer if (symbol.source_location) |sl| getDebugInfoAllocator().free(sl.file_name);
1129
- return printLineInfo(
1184
+ const PrintSourceAddressOptions = struct {
1185
+ address: usize,
1186
+ resolve_inline_callers: bool,
1187
+ };
1188
+
1189
+ fn printSourceAtAddress(
1190
+ io: Io,
1191
+ text_arena: *std.heap.ArenaAllocator,
1192
+ debug_info: *SelfInfo,
1193
+ t: Io.Terminal,
1194
+ options: PrintSourceAddressOptions,
1195
+ ) Writer.Error!void {
1196
+ defer _ = text_arena.reset(.retain_capacity);
1197
+
1198
+ // Initialize the symbol array with space for at least one element, allocating this on the stack
1199
+ // in the common case where only one element is needed
1200
+ var symbol_fallback_allocator = std.heap.stackFallback(@sizeOf(Symbol) + @alignOf(Symbol) - 1, getDebugInfoAllocator());
1201
+ const symbol_allocator = symbol_fallback_allocator.get();
1202
+ var symbols = std.ArrayList(Symbol).initCapacity(symbol_allocator, 1) catch unreachable;
1203
+ defer symbols.deinit(symbol_allocator);
1204
+
1205
+ debug_info.getSymbols(
1130
1206
  io,
1131
- t,
1132
- symbol.source_location,
1133
- address,
1134
- symbol.name orelse "???",
1135
- symbol.compile_unit_name orelse debug_info.getModuleName(io, address) catch "???",
1136
- );
1207
+ symbol_allocator,
1208
+ text_arena.allocator(),
1209
+ options.address,
1210
+ options.resolve_inline_callers,
1211
+ &symbols,
1212
+ ) catch |err| {
1213
+ t.setColor(.dim) catch {};
1214
+ defer t.setColor(.reset) catch {};
1215
+ switch (err) {
1216
+ error.MissingDebugInfo,
1217
+ error.UnsupportedDebugInfo,
1218
+ error.InvalidDebugInfo,
1219
+ => {},
1220
+ error.ReadFailed, error.Unexpected, error.Canceled => {
1221
+ try t.writer.print("Failed to read debug info from filesystem, trace may be incomplete\n\n", .{});
1222
+ },
1223
+ error.OutOfMemory => {
1224
+ t.setColor(.dim) catch {};
1225
+ try t.writer.print("Ran out of memory loading debug info, trace may be incomplete\n\n", .{});
1226
+ t.setColor(.reset) catch {};
1227
+ },
1228
+ }
1229
+ };
1230
+
1231
+ // If we failed to write any symbols, at least write the unknown symbol. Can't fail since we
1232
+ // initialized with a capacity of 1.
1233
+ if (symbols.items.len == 0) symbols.appendAssumeCapacity(.unknown);
1234
+
1235
+ for (symbols.items) |symbol| {
1236
+ try printLineInfo(io, t, debug_info, options.address, symbol);
1237
+ }
1137
1238
  }
1138
1239
  fn printLineInfo(
1139
1240
  io: Io,
1140
1241
  t: Io.Terminal,
1141
- source_location: ?SourceLocation,
1242
+ debug_info: *SelfInfo,
1142
1243
  address: usize,
1143
- symbol_name: []const u8,
1144
- compile_unit_name: []const u8,
1244
+ symbol: Symbol,
1145
1245
  ) Writer.Error!void {
1146
1246
  const writer = t.writer;
1147
1247
  t.setColor(.bold) catch {};
1148
1248
 
1149
- if (source_location) |*sl| {
1150
- try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
1249
+ if (symbol.source_location) |*sl| {
1250
+ if (sl.column == 0) {
1251
+ try writer.print("{s}:{d}", .{ sl.file_name, sl.line });
1252
+ } else {
1253
+ try writer.print("{s}:{d}:{d}", .{ sl.file_name, sl.line, sl.column });
1254
+ }
1151
1255
  } else {
1152
1256
  try writer.writeAll("???:?:?");
1153
1257
  }
@@ -1155,12 +1259,16 @@ fn printLineInfo(
1155
1259
  t.setColor(.reset) catch {};
1156
1260
  try writer.writeAll(": ");
1157
1261
  t.setColor(.dim) catch {};
1158
- try writer.print("0x{x} in {s} ({s})", .{ address, symbol_name, compile_unit_name });
1262
+ try writer.print("0x{x} in {s} ({s})", .{
1263
+ address,
1264
+ symbol.name orelse "???",
1265
+ symbol.compile_unit_name orelse debug_info.getModuleName(io, address) catch "???",
1266
+ });
1159
1267
  t.setColor(.reset) catch {};
1160
1268
  try writer.writeAll("\n");
1161
1269
 
1162
1270
  // Show the matching source code line if possible
1163
- if (source_location) |sl| {
1271
+ if (symbol.source_location) |sl| {
1164
1272
  if (printLineFromFile(io, writer, sl)) {
1165
1273
  if (sl.column > 0) {
1166
1274
  // The caret already takes one char
@@ -1599,7 +1707,12 @@ test "manage resources correctly" {
1599
1707
  var di: SelfInfo = .init;
1600
1708
  defer di.deinit(io);
1601
1709
  const t: Io.Terminal = .{ .writer = &discarding.writer, .mode = .no_color };
1602
- try printSourceAtAddress(io, &di, t, S.showMyTrace());
1710
+ var text_arena: std.heap.ArenaAllocator = .init(std.testing.allocator);
1711
+ defer text_arena.deinit();
1712
+ try printSourceAtAddress(io, &text_arena, &di, t, .{
1713
+ .address = S.showMyTrace(),
1714
+ .resolve_inline_callers = true,
1715
+ });
1603
1716
  }
1604
1717
 
1605
1718
  /// This API helps you track where a value originated and where it was mutated,
@@ -1648,8 +1761,8 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1648
1761
  t.notes[t.index] = note;
1649
1762
  const addrs = &t.addrs[t.index];
1650
1763
  const st = captureCurrentStackTrace(.{ .first_address = addr }, addrs);
1651
- if (st.index < addrs.len) {
1652
- @memset(addrs[st.index..], 0); // zero unused frames to indicate end of trace
1764
+ if (st.return_addresses.len < addrs.len) {
1765
+ @memset(addrs[st.return_addresses.len..], 0); // zero unused frames to indicate end of trace
1653
1766
  }
1654
1767
  }
1655
1768
  // Keep counting even if the end is reached so that the
@@ -1667,9 +1780,10 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
1667
1780
  stderr.writer.print("{s}:\n", .{t.notes[i]}) catch return;
1668
1781
  var frames_array_mutable = frames_array;
1669
1782
  const frames = mem.sliceTo(frames_array_mutable[0..], 0);
1783
+ const len = @min(t.index, frames.len);
1670
1784
  const stack_trace: StackTrace = .{
1671
- .index = frames.len,
1672
- .instruction_addresses = frames,
1785
+ .return_addresses = frames[0..len],
1786
+ .skipped = if (len < frames.len) .none else .unknown,
1673
1787
  };
1674
1788
  writeStackTrace(&stack_trace, stderr) catch return;
1675
1789
  }
package/std/enums.zig CHANGED
@@ -252,7 +252,7 @@ pub fn EnumSet(comptime E: type) type {
252
252
  /// The maximum number of items in this set.
253
253
  pub const len = Indexer.count;
254
254
 
255
- bits: BitSet = BitSet.initEmpty(),
255
+ bits: BitSet = .empty,
256
256
 
257
257
  /// Initializes the set using a struct of bools
258
258
  pub fn init(init_values: EnumFieldStruct(E, bool, false)) Self {
@@ -278,19 +278,27 @@ pub fn EnumSet(comptime E: type) type {
278
278
  return result;
279
279
  }
280
280
 
281
+ /// A set containing no keys.
282
+ pub const empty: Self = .{ .bits = .empty };
283
+
284
+ /// A set containing all possible keys.
285
+ pub const full: Self = .{ .bits = .full };
286
+
287
+ /// Deprecated: use `.empty`.
281
288
  /// Returns a set containing no keys.
282
289
  pub fn initEmpty() Self {
283
- return .{ .bits = BitSet.initEmpty() };
290
+ return .empty;
284
291
  }
285
292
 
293
+ /// Deprecated: use `.full`.
286
294
  /// Returns a set containing all possible keys.
287
295
  pub fn initFull() Self {
288
- return .{ .bits = BitSet.initFull() };
296
+ return .full;
289
297
  }
290
298
 
291
299
  /// Returns a set containing multiple keys.
292
300
  pub fn initMany(keys: []const Key) Self {
293
- var set = initEmpty();
301
+ var set: Self = .empty;
294
302
  for (keys) |key| set.insert(key);
295
303
  return set;
296
304
  }
@@ -440,7 +448,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
440
448
  const BitSet = std.StaticBitSet(Indexer.count);
441
449
 
442
450
  /// Bits determining whether items are in the map
443
- bits: BitSet = BitSet.initEmpty(),
451
+ bits: BitSet = .empty,
444
452
  /// Values of items in the map. If the associated
445
453
  /// bit is zero, the value is undefined.
446
454
  values: [Indexer.count]Value = undefined,
@@ -475,7 +483,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
475
483
  /// Consider using EnumArray instead if the map will remain full.
476
484
  pub fn initFull(value: Value) Self {
477
485
  var result: Self = .{
478
- .bits = Self.BitSet.initFull(),
486
+ .bits = .full,
479
487
  .values = undefined,
480
488
  };
481
489
  @memset(&result.values, value);
@@ -493,7 +501,7 @@ pub fn EnumMap(comptime E: type, comptime V: type) type {
493
501
  pub fn initFullWithDefault(comptime default: ?Value, init_values: EnumFieldStruct(E, Value, default)) Self {
494
502
  @setEvalBranchQuota(2 * @typeInfo(E).@"enum".fields.len);
495
503
  var result: Self = .{
496
- .bits = Self.BitSet.initFull(),
504
+ .bits = .full,
497
505
  .values = undefined,
498
506
  };
499
507
  inline for (0..Self.len) |i| {
@@ -687,16 +695,14 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
687
695
  return self;
688
696
  }
689
697
 
690
- /// Initializes the multiset with a count of zero.
691
- pub fn initEmpty() Self {
692
- return initWithCount(0);
693
- }
698
+ /// A multiset with a count of zero.
699
+ pub const empty: Self = .initWithCount(0);
694
700
 
695
701
  /// Initializes the multiset with all keys at the
696
702
  /// same count.
697
703
  pub fn initWithCount(comptime c: CountSize) Self {
698
704
  return .{
699
- .counts = EnumArray(E, CountSize).initDefault(c, .{}),
705
+ .counts = .initDefault(c, .{}),
700
706
  };
701
707
  }
702
708
 
@@ -855,7 +861,7 @@ pub fn BoundedEnumMultiset(comptime E: type, comptime CountSize: type) type {
855
861
  test EnumMultiset {
856
862
  const Ball = enum { red, green, blue };
857
863
 
858
- const empty = EnumMultiset(Ball).initEmpty();
864
+ const empty = EnumMultiset(Ball).empty;
859
865
  const r0_g1_b2 = EnumMultiset(Ball).init(.{
860
866
  .red = 0,
861
867
  .green = 1,
@@ -1162,8 +1168,8 @@ pub fn EnumArray(comptime E: type, comptime V: type) type {
1162
1168
  test "pure EnumSet fns" {
1163
1169
  const Suit = enum { spades, hearts, clubs, diamonds };
1164
1170
 
1165
- const empty = EnumSet(Suit).initEmpty();
1166
- const full = EnumSet(Suit).initFull();
1171
+ const empty = EnumSet(Suit).empty;
1172
+ const full = EnumSet(Suit).full;
1167
1173
  const black = EnumSet(Suit).initMany(&[_]Suit{ .spades, .clubs });
1168
1174
  const red = EnumSet(Suit).initMany(&[_]Suit{ .hearts, .diamonds });
1169
1175
 
@@ -1224,8 +1230,8 @@ test "pure EnumSet fns" {
1224
1230
 
1225
1231
  test "EnumSet empty" {
1226
1232
  const E = enum {};
1227
- const empty = EnumSet(E).initEmpty();
1228
- const full = EnumSet(E).initFull();
1233
+ const empty = EnumSet(E).empty;
1234
+ const full = EnumSet(E).full;
1229
1235
 
1230
1236
  try std.testing.expect(empty.eql(full));
1231
1237
  try std.testing.expect(empty.complement().eql(full));
@@ -1236,13 +1242,13 @@ test "EnumSet empty" {
1236
1242
  test "EnumSet const iterator" {
1237
1243
  const Direction = enum { up, down, left, right };
1238
1244
  const diag_move = init: {
1239
- var move = EnumSet(Direction).initEmpty();
1245
+ var move = EnumSet(Direction).empty;
1240
1246
  move.insert(.right);
1241
1247
  move.insert(.up);
1242
1248
  break :init move;
1243
1249
  };
1244
1250
 
1245
- var result = EnumSet(Direction).initEmpty();
1251
+ var result = EnumSet(Direction).empty;
1246
1252
  var it = diag_move.iterator();
1247
1253
  while (it.next()) |dir| {
1248
1254
  result.insert(dir);