From d25d71ff316bc2b0b28eaad7b42e9c19e8baa2d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Thu, 10 Oct 2024 17:30:09 +0200 Subject: [PATCH 1/2] update zig sources to 0.14.0-dev.1876+41dbd0d0d --- README.md | 2 +- build | 2 +- build.bat | 2 +- zig/CMakeLists.txt | 6 +- zig/README.md | 2 +- zig/bootstrap.c | 4 +- zig/build.zig | 4 + zig/doc/langref.html.in | 34 +- zig/lib/compiler/aro/aro/Compilation.zig | 2 +- zig/lib/compiler/aro/aro/target.zig | 23 +- zig/lib/compiler/fmt.zig | 1 + zig/lib/compiler/objcopy.zig | 343 ++- zig/lib/compiler_rt/aulldiv.zig | 3 +- zig/lib/compiler_rt/aullrem.zig | 3 +- zig/lib/compiler_rt/common.zig | 26 +- zig/lib/compiler_rt/emutls.zig | 2 +- zig/lib/compiler_rt/fixdfdi.zig | 5 + zig/lib/compiler_rt/fixsfdi.zig | 5 + zig/lib/compiler_rt/fixunsdfdi.zig | 5 + zig/lib/compiler_rt/fixunssfdi.zig | 5 + zig/lib/compiler_rt/floatdidf.zig | 5 + zig/lib/compiler_rt/floatdisf.zig | 5 + zig/lib/compiler_rt/floatundidf.zig | 5 + zig/lib/compiler_rt/floatundisf.zig | 5 + zig/lib/libc/glibc/abilists | Bin 274738 -> 246035 bytes zig/lib/libc/glibc/sysdeps/mips/mips32/crtn.S | 6 +- .../libc/glibc/sysdeps/mips/mips64/n32/crtn.S | 6 +- .../libc/glibc/sysdeps/mips/mips64/n64/crtn.S | 6 +- zig/lib/libc/glibc/sysdeps/unix/mips/sysdep.h | 3 +- .../loongarch64-linux-gnusf/bits/endianness.h | 11 + .../loongarch64-linux-gnusf/bits/fcntl.h | 61 + .../loongarch64-linux-gnusf/bits/fenv.h | 90 + .../loongarch64-linux-gnusf/bits/hwcap.h | 38 + .../loongarch64-linux-gnusf/bits/link.h | 76 + .../bits/link_lavcurrent.h | 25 + .../bits/long-double.h | 21 + .../loongarch64-linux-gnusf/bits/procfs.h | 52 + .../bits/pthread_stack_min.h | 20 + .../loongarch64-linux-gnusf/bits/setjmp.h | 42 + .../loongarch64-linux-gnusf/bits/shmlba.h | 24 + .../loongarch64-linux-gnusf/bits/sigstack.h | 32 + .../bits/struct_stat.h | 127 ++ .../loongarch64-linux-gnusf/bits/timesize.h | 20 + .../loongarch64-linux-gnusf/bits/wordsize.h | 19 + .../loongarch64-linux-gnusf/fpu_control.h | 119 ++ .../gnu/lib-names-lp64s.h | 27 + .../loongarch64-linux-gnusf/gnu/lib-names.h | 16 + .../loongarch64-linux-gnusf/gnu/stubs-lp64s.h | 38 + .../loongarch64-linux-gnusf/gnu/stubs.h | 12 + .../include/loongarch64-linux-gnusf/ieee754.h | 170 ++ .../include/loongarch64-linux-gnusf/sys/asm.h | 78 + .../loongarch64-linux-gnusf/sys/ucontext.h | 64 + .../loongarch64-linux-gnusf/sys/user.h | 42 + zig/lib/libc/musl/crt/arm/crti.s | 2 + zig/lib/libc/musl/crt/mips/crtn.s | 6 +- zig/lib/libc/musl/crt/mips64/crtn.s | 6 +- zig/lib/libunwind/src/gcc_personality_v0.c | 36 +- zig/lib/std/Build.zig | 213 +- zig/lib/std/Build/Cache.zig | 7 + zig/lib/std/Build/Cache/Path.zig | 24 +- zig/lib/std/Build/Module.zig | 69 +- zig/lib/std/Build/Step/CheckObject.zig | 44 +- zig/lib/std/Build/Step/Compile.zig | 12 + zig/lib/std/Build/Step/ObjCopy.zig | 80 + zig/lib/std/Build/Step/TranslateC.zig | 49 +- zig/lib/std/Build/Watch.zig | 7 +- zig/lib/std/Target.zig | 662 ++++-- zig/lib/std/Target/Query.zig | 2 +- zig/lib/std/Target/aarch64.zig | 86 +- zig/lib/std/Target/arm.zig | 1 - zig/lib/std/Target/lanai.zig | 37 + zig/lib/std/Target/propeller.zig | 20 + zig/lib/std/Target/xcore.zig | 37 + zig/lib/std/Thread.zig | 77 + zig/lib/std/Thread/Futex.zig | 21 +- zig/lib/std/Thread/ResetEvent.zig | 8 +- zig/lib/std/Thread/WaitGroup.zig | 3 +- zig/lib/std/atomic.zig | 48 +- zig/lib/std/bit_set.zig | 3 - zig/lib/std/builtin.zig | 243 +-- zig/lib/std/c.zig | 99 +- zig/lib/std/c/darwin.zig | 3 +- zig/lib/std/crypto/tls.zig | 4 +- zig/lib/std/crypto/tls/Client.zig | 14 +- zig/lib/std/debug.zig | 168 +- zig/lib/std/debug/FormattedPanic.zig | 45 + zig/lib/std/debug/SimplePanic.zig | 86 + zig/lib/std/elf.zig | 112 +- zig/lib/std/fmt.zig | 12 +- zig/lib/std/fs/Dir.zig | 7 + zig/lib/std/fs/test.zig | 30 + zig/lib/std/heap.zig | 2 - zig/lib/std/http/test.zig | 5 + zig/lib/std/io.zig | 192 +- zig/lib/std/io/Reader/test.zig | 3 +- zig/lib/std/io/buffered_reader.zig | 72 +- zig/lib/std/math/float.zig | 3 - zig/lib/std/math/gcd.zig | 59 +- zig/lib/std/math/isnan.zig | 8 +- zig/lib/std/mem.zig | 4 - zig/lib/std/meta.zig | 11 +- zig/lib/std/os/linux.zig | 115 +- zig/lib/std/os/linux/IoUring.zig | 8 +- .../std/os/linux/{arm64.zig => aarch64.zig} | 0 .../std/os/linux/{arm-eabi.zig => arm.zig} | 0 zig/lib/std/os/linux/hexagon.zig | 254 +++ .../std/os/linux/{start_pie.zig => pie.zig} | 0 zig/lib/std/os/linux/powerpc64.zig | 10 +- zig/lib/std/os/linux/s390x.zig | 276 +++ zig/lib/std/os/linux/syscalls.zig | 4 +- zig/lib/std/os/linux/thumb.zig | 2 +- zig/lib/std/os/linux/tls.zig | 14 +- zig/lib/std/os/uefi/pool_allocator.zig | 7 +- zig/lib/std/os/wasi.zig | 42 + zig/lib/std/os/windows.zig | 3 + zig/lib/std/os/windows/tls.zig | 2 +- zig/lib/std/posix.zig | 25 +- zig/lib/std/posix/test.zig | 5 + zig/lib/std/process/Child.zig | 4 +- zig/lib/std/sort.zig | 37 +- zig/lib/std/start.zig | 6 +- zig/lib/std/tar.zig | 1 + zig/lib/std/tar/writer.zig | 10 +- zig/lib/std/time.zig | 82 +- zig/lib/std/zig.zig | 1 - zig/lib/std/zig/AstGen.zig | 19 +- zig/lib/std/zig/AstRlAnnotate.zig | 1 - zig/lib/std/zig/BuiltinFn.zig | 8 - zig/lib/std/zig/LibCDirs.zig | 21 +- zig/lib/std/zig/LibCInstallation.zig | 332 ++- zig/lib/std/zig/Zir.zig | 18 +- zig/lib/std/zig/system.zig | 19 +- zig/lib/std/zig/target.zig | 1 + zig/lib/std/zig/tokenizer.zig | 3 + zig/lib/tsan/builtins/assembly.h | 293 +++ zig/lib/tsan/interception/interception.h | 29 +- .../tsan/interception/interception_linux.h | 16 +- .../tsan/interception/interception_win.cpp | 83 +- .../sanitizer_common/sanitizer_allocator.cpp | 10 +- .../sanitizer_allocator_interface.h | 2 + .../sanitizer_allocator_primary32.h | 2 +- .../sanitizer_allocator_primary64.h | 16 +- zig/lib/tsan/sanitizer_common/sanitizer_asm.h | 43 +- .../tsan/sanitizer_common/sanitizer_atomic.h | 14 +- .../sanitizer_common/sanitizer_atomic_clang.h | 85 +- .../sanitizer_atomic_clang_mips.h | 117 -- .../sanitizer_atomic_clang_other.h | 85 - .../sanitizer_atomic_clang_x86.h | 113 - .../sanitizer_common/sanitizer_atomic_msvc.h | 8 +- .../sanitizer_common/sanitizer_bitvector.h | 8 +- .../sanitizer_chained_origin_depot.cpp | 6 +- .../sanitizer_chained_origin_depot.h | 4 +- .../sanitizer_common/sanitizer_common.cpp | 20 +- .../tsan/sanitizer_common/sanitizer_common.h | 45 +- .../sanitizer_common_interceptors.inc | 203 +- .../sanitizer_common_interceptors_format.inc | 15 +- .../sanitizer_common_interface.inc | 1 + .../sanitizer_common_interface_posix.inc | 1 + .../sanitizer_common_libcdep.cpp | 10 +- .../sanitizer_common_syscalls.inc | 35 + .../tsan/sanitizer_common/sanitizer_dl.cpp | 37 + zig/lib/tsan/sanitizer_common/sanitizer_dl.h | 26 + .../tsan/sanitizer_common/sanitizer_file.cpp | 4 +- .../tsan/sanitizer_common/sanitizer_file.h | 2 +- .../sanitizer_flag_parser.cpp | 7 +- .../sanitizer_common/sanitizer_flag_parser.h | 4 +- .../tsan/sanitizer_common/sanitizer_flags.cpp | 4 +- .../tsan/sanitizer_common/sanitizer_flags.inc | 13 + .../sanitizer_common/sanitizer_flat_map.h | 4 + .../tsan/sanitizer_common/sanitizer_freebsd.h | 137 -- .../sanitizer_common/sanitizer_fuchsia.cpp | 107 +- .../tsan/sanitizer_common/sanitizer_hash.h | 2 +- .../sanitizer_internal_defs.h | 34 +- .../tsan/sanitizer_common/sanitizer_libc.cpp | 16 + .../tsan/sanitizer_common/sanitizer_libc.h | 3 +- .../sanitizer_common/sanitizer_libignore.cpp | 4 +- .../tsan/sanitizer_common/sanitizer_linux.cpp | 1842 +++++++++-------- .../tsan/sanitizer_common/sanitizer_linux.h | 114 +- .../sanitizer_linux_libcdep.cpp | 483 ++--- .../sanitizer_common/sanitizer_linux_s390.cpp | 164 +- .../tsan/sanitizer_common/sanitizer_mac.cpp | 8 +- .../sanitizer_common/sanitizer_mallinfo.h | 4 + .../sanitizer_common/sanitizer_malloc_mac.inc | 2 +- .../tsan/sanitizer_common/sanitizer_mutex.cpp | 6 +- .../sanitizer_placement_new.h | 4 +- .../sanitizer_common/sanitizer_platform.h | 24 +- .../sanitizer_platform_interceptors.h | 16 +- .../sanitizer_platform_limits_freebsd.cpp | 2 + .../sanitizer_platform_limits_freebsd.h | 24 +- .../sanitizer_platform_limits_openbsd.cpp | 0 .../sanitizer_platform_limits_openbsd.h | 0 .../sanitizer_platform_limits_posix.h | 1 + .../tsan/sanitizer_common/sanitizer_posix.cpp | 12 +- .../tsan/sanitizer_common/sanitizer_posix.h | 28 +- .../sanitizer_posix_libcdep.cpp | 33 +- .../sanitizer_common/sanitizer_printf.cpp | 11 +- .../sanitizer_procmaps_bsd.cpp | 47 +- .../sanitizer_procmaps_common.cpp | 2 +- .../tsan/sanitizer_common/sanitizer_ptrauth.h | 46 +- .../sanitizer_redefine_builtins.h | 16 +- .../sanitizer_common/sanitizer_ring_buffer.h | 4 +- .../sanitizer_stack_store.cpp | 9 +- .../sanitizer_common/sanitizer_stackdepot.cpp | 8 +- .../sanitizer_common/sanitizer_stackdepot.h | 4 +- .../sanitizer_stackdepotbase.h | 31 +- .../sanitizer_stacktrace_libcdep.cpp | 42 +- .../sanitizer_stacktrace_printer.cpp | 133 +- .../sanitizer_stacktrace_printer.h | 143 +- .../sanitizer_stacktrace_sparc.cpp | 11 +- .../sanitizer_stoptheworld_linux_libcdep.cpp | 10 +- .../sanitizer_stoptheworld_netbsd_libcdep.cpp | 4 +- .../sanitizer_suppressions.cpp | 7 +- .../sanitizer_common/sanitizer_symbolizer.cpp | 5 +- .../sanitizer_common/sanitizer_symbolizer.h | 27 +- .../sanitizer_symbolizer_internal.h | 9 + .../sanitizer_symbolizer_libbacktrace.cpp | 2 +- .../sanitizer_symbolizer_libcdep.cpp | 20 +- .../sanitizer_symbolizer_mac.cpp | 5 +- .../sanitizer_symbolizer_markup.cpp | 228 +- .../sanitizer_symbolizer_markup.h | 79 + ...> sanitizer_symbolizer_markup_constants.h} | 19 +- .../sanitizer_symbolizer_markup_fuchsia.cpp | 85 + .../sanitizer_symbolizer_posix_libcdep.cpp | 67 +- .../sanitizer_symbolizer_report.cpp | 80 +- .../sanitizer_symbolizer_report_fuchsia.cpp | 33 + .../sanitizer_symbolizer_win.cpp | 6 +- .../sanitizer_syscall_linux_hexagon.inc | 131 ++ .../sanitizer_syscall_linux_loongarch64.inc | 171 ++ .../sanitizer_syscall_linux_riscv64.inc | 174 ++ .../sanitizer_thread_arg_retval.cpp | 23 +- .../sanitizer_thread_arg_retval.h | 1 + .../sanitizer_tls_get_addr.cpp | 15 +- .../sanitizer_unwind_fuchsia.cpp | 66 + .../sanitizer_common/sanitizer_unwind_win.cpp | 7 + .../tsan/sanitizer_common/sanitizer_win.cpp | 25 +- zig/lib/tsan/tsan_debugging.cpp | 4 +- zig/lib/tsan/tsan_defs.h | 2 +- zig/lib/tsan/tsan_dispatch_defs.h | 7 - zig/lib/tsan/tsan_interceptors_posix.cpp | 135 +- zig/lib/tsan/tsan_interface.h | 8 + zig/lib/tsan/tsan_interface_ann.cpp | 24 +- zig/lib/tsan/tsan_interface_atomic.cpp | 24 + zig/lib/tsan/tsan_mman.cpp | 29 +- zig/lib/tsan/tsan_mman.h | 4 +- zig/lib/tsan/tsan_platform.h | 151 +- zig/lib/tsan/tsan_platform_linux.cpp | 220 +- zig/lib/tsan/tsan_platform_mac.cpp | 9 +- zig/lib/tsan/tsan_platform_posix.cpp | 43 +- zig/lib/tsan/tsan_preinit.cpp | 10 +- zig/lib/tsan/tsan_report.cpp | 38 +- zig/lib/tsan/tsan_report.h | 3 +- zig/lib/tsan/tsan_rtl.cpp | 24 +- zig/lib/tsan/tsan_rtl.h | 12 +- zig/lib/tsan/tsan_rtl_aarch64.S | 7 + zig/lib/tsan/tsan_rtl_access.cpp | 22 +- zig/lib/tsan/tsan_rtl_loongarch64.S | 196 ++ zig/lib/tsan/tsan_rtl_mutex.cpp | 2 +- zig/lib/tsan/tsan_rtl_riscv64.S | 203 ++ zig/lib/tsan/tsan_rtl_s390x.S | 49 + zig/lib/tsan/tsan_rtl_thread.cpp | 10 +- zig/lib/tsan/tsan_suppressions.cpp | 3 +- zig/lib/tsan/tsan_vector_clock.h | 2 +- zig/lib/zig.h | 60 +- zig/src/Air.zig | 7 - zig/src/Air/types_resolved.zig | 1 - zig/src/Compilation.zig | 185 +- zig/src/Compilation/Config.zig | 2 +- zig/src/InternPool.zig | 34 +- zig/src/Liveness.zig | 3 - zig/src/Liveness/Verify.zig | 1 - zig/src/Package/Manifest.zig | 7 + zig/src/Sema.zig | 775 +++---- zig/src/Sema/bitcast.zig | 12 +- zig/src/Type.zig | 6 +- zig/src/Value.zig | 12 +- zig/src/Zcu.zig | 23 +- zig/src/Zcu/PerThread.zig | 96 +- zig/src/arch/aarch64/CodeGen.zig | 6 - zig/src/arch/aarch64/Mir.zig | 2 +- zig/src/arch/arm/CodeGen.zig | 6 - zig/src/arch/mips/abi.zig | 2 - zig/src/arch/riscv64/CodeGen.zig | 21 - zig/src/arch/sparc64/CodeGen.zig | 24 - zig/src/arch/wasm/CodeGen.zig | 65 +- zig/src/arch/x86_64/CodeGen.zig | 101 +- zig/src/arch/x86_64/Emit.zig | 24 + zig/src/arch/x86_64/Lower.zig | 2 + zig/src/arch/x86_64/Mir.zig | 4 + zig/src/arch/x86_64/encoder.zig | 8 +- zig/src/clang.zig | 2 +- zig/src/codegen/c.zig | 12 - zig/src/codegen/llvm.zig | 131 +- zig/src/codegen/spirv.zig | 3 + zig/src/crash_report.zig | 21 +- zig/src/glibc.zig | 81 +- zig/src/libcxx.zig | 2 +- zig/src/libtsan.zig | 16 +- zig/src/libunwind.zig | 4 + zig/src/link.zig | 32 +- zig/src/link/C.zig | 3 +- zig/src/link/Coff.zig | 1 - zig/src/link/Coff/lld.zig | 53 +- zig/src/link/Dwarf.zig | 194 +- zig/src/link/Elf.zig | 1411 ++++++------- zig/src/link/Elf/Archive.zig | 23 +- zig/src/link/Elf/Atom.zig | 41 +- zig/src/link/Elf/AtomList.zig | 43 +- zig/src/link/Elf/LdScript.zig | 38 +- zig/src/link/Elf/LinkerDefined.zig | 10 +- zig/src/link/Elf/Object.zig | 145 +- zig/src/link/Elf/SharedObject.zig | 34 +- zig/src/link/Elf/Symbol.zig | 16 +- zig/src/link/Elf/ZigObject.zig | 296 ++- zig/src/link/Elf/file.zig | 52 +- zig/src/link/Elf/merge_section.zig | 4 + zig/src/link/Elf/relocatable.zig | 146 +- zig/src/link/Elf/synthetic_sections.zig | 29 +- zig/src/link/MachO.zig | 368 ++-- zig/src/link/MachO/Archive.zig | 16 +- zig/src/link/MachO/Atom.zig | 4 +- zig/src/link/MachO/Dylib.zig | 11 +- zig/src/link/MachO/InternalObject.zig | 44 +- zig/src/link/MachO/Object.zig | 63 +- zig/src/link/MachO/ZigObject.zig | 4 +- zig/src/link/MachO/file.zig | 11 +- zig/src/link/MachO/load_commands.zig | 5 +- zig/src/link/MachO/relocatable.zig | 40 +- zig/src/link/NvPtx.zig | 1 - zig/src/link/Plan9.zig | 1 - zig/src/link/SpirV.zig | 1 - zig/src/link/StringTable.zig | 2 +- zig/src/link/Wasm.zig | 60 +- zig/src/main.zig | 82 +- zig/src/mingw.zig | 42 +- zig/src/musl.zig | 4 +- zig/src/mutable_value.zig | 4 +- zig/src/print_air.zig | 7 - zig/src/print_zir.zig | 3 +- zig/src/target.zig | 44 +- zig/src/wasi_libc.zig | 14 +- zig/test/behavior/array.zig | 67 + zig/test/behavior/atomics.zig | 10 - zig/test/behavior/basic.zig | 1 + zig/test/behavior/bitcast.zig | 3 - ...n_functions_returning_void_or_noreturn.zig | 1 - zig/test/behavior/export_keyword.zig | 13 + zig/test/behavior/math.zig | 6 - zig/test/behavior/union.zig | 1 + zig/test/behavior/var_args.zig | 5 + ...ray slice sentinel mismatch non-scalar.zig | 13 + ...orderings_of_fence_Acquire_or_stricter.zig | 9 - .../comptime_var_referenced_at_runtime.zig | 20 + .../comptime_var_referenced_by_decl.zig | 7 + .../destructure_error_union.zig | 15 + .../compile_errors/minmax_missing_args.zig | 9 + .../compile_errors/splat_bad_result_type.zig | 7 + .../splat_result_type_non_vector.zig | 9 - zig/test/cases/errdefer_discard.zig | 7 + zig/test/cases/exit.zig | 2 +- ...ray slice sentinel mismatch non-scalar.zig | 21 - zig/test/incremental/add_decl | 4 +- zig/test/incremental/add_decl_namespaced | 4 +- zig/test/incremental/delete_comptime_decls | 4 +- zig/test/incremental/hello | 4 +- zig/test/incremental/modify_inline_fn | 4 +- zig/test/incremental/move_src | 4 +- zig/test/incremental/remove_enum_field | 4 +- .../incremental/type_becomes_comptime_only | 4 +- zig/test/incremental/unreferenced_error | 4 +- zig/test/link/elf.zig | 16 +- zig/test/link/link.zig | 2 +- zig/test/link/macho.zig | 26 + zig/test/llvm_targets.zig | 343 ++- zig/test/src/Debugger.zig | 485 +++-- zig/test/standalone/empty_env/build.zig | 7 + zig/test/tests.zig | 76 + zig/tools/generate_linux_syscalls.zig | 2 + zig/tools/incr-check.zig | 427 ++-- zig/tools/lldb_pretty_printers.py | 13 +- zig/tools/process_headers.zig | 5 + zig/tools/update_cpu_features.zig | 36 +- 381 files changed, 13437 insertions(+), 6724 deletions(-) create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/endianness.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/fcntl.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/fenv.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/hwcap.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/link.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/link_lavcurrent.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/long-double.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/procfs.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/pthread_stack_min.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/setjmp.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/shmlba.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/sigstack.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/struct_stat.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/timesize.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/bits/wordsize.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/fpu_control.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names-lp64s.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs-lp64s.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/ieee754.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/sys/asm.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/sys/ucontext.h create mode 100644 zig/lib/libc/include/loongarch64-linux-gnusf/sys/user.h create mode 100644 zig/lib/std/Target/lanai.zig create mode 100644 zig/lib/std/Target/propeller.zig create mode 100644 zig/lib/std/Target/xcore.zig create mode 100644 zig/lib/std/debug/FormattedPanic.zig create mode 100644 zig/lib/std/debug/SimplePanic.zig rename zig/lib/std/os/linux/{arm64.zig => aarch64.zig} (100%) rename zig/lib/std/os/linux/{arm-eabi.zig => arm.zig} (100%) create mode 100644 zig/lib/std/os/linux/hexagon.zig rename zig/lib/std/os/linux/{start_pie.zig => pie.zig} (100%) create mode 100644 zig/lib/std/os/linux/s390x.zig create mode 100644 zig/lib/tsan/builtins/assembly.h delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_atomic_clang_mips.h delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_atomic_clang_other.h delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_atomic_clang_x86.h create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_dl.cpp create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_dl.h delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_freebsd.h delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.cpp delete mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_platform_limits_openbsd.h create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_symbolizer_markup.h rename zig/lib/tsan/sanitizer_common/{sanitizer_symbolizer_fuchsia.h => sanitizer_symbolizer_markup_constants.h} (69%) create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_symbolizer_markup_fuchsia.cpp create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_symbolizer_report_fuchsia.cpp create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_syscall_linux_hexagon.inc create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_syscall_linux_loongarch64.inc create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_syscall_linux_riscv64.inc create mode 100644 zig/lib/tsan/sanitizer_common/sanitizer_unwind_fuchsia.cpp create mode 100644 zig/lib/tsan/tsan_rtl_loongarch64.S create mode 100644 zig/lib/tsan/tsan_rtl_riscv64.S create mode 100644 zig/lib/tsan/tsan_rtl_s390x.S create mode 100644 zig/test/cases/compile_errors/array slice sentinel mismatch non-scalar.zig delete mode 100644 zig/test/cases/compile_errors/atomic_orderings_of_fence_Acquire_or_stricter.zig create mode 100644 zig/test/cases/compile_errors/destructure_error_union.zig create mode 100644 zig/test/cases/compile_errors/minmax_missing_args.zig create mode 100644 zig/test/cases/compile_errors/splat_bad_result_type.zig delete mode 100644 zig/test/cases/compile_errors/splat_result_type_non_vector.zig create mode 100644 zig/test/cases/errdefer_discard.zig delete mode 100644 zig/test/cases/safety/array slice sentinel mismatch non-scalar.zig diff --git a/README.md b/README.md index 70f12ae933..f1e0009a79 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ to find and inspect the patch diffs. * LLVM, LLD, Clang 19.1.0 * zlib 1.3.1 * zstd 1.5.2 - * zig 0.14.0-dev.1622+2ac543388 + * zig 0.14.0-dev.1876+41dbd0d0d For other versions, check the git tags of this repository. diff --git a/build b/build index cc5bd56008..b1c233233a 100755 --- a/build +++ b/build @@ -7,7 +7,7 @@ TARGET="$1" # Example: riscv64-linux-gnu MCPU="$2" # Examples: `baseline`, `native`, `generic+v7a`, or `arm1176jzf_s` ROOTDIR="$(pwd)" -ZIG_VERSION="0.14.0-dev.1622+2ac543388" +ZIG_VERSION="0.14.0-dev.1876+41dbd0d0d" TARGET_OS_AND_ABI=${TARGET#*-} # Example: linux-gnu diff --git a/build.bat b/build.bat index 609d7ce87f..331bd1d043 100644 --- a/build.bat +++ b/build.bat @@ -35,7 +35,7 @@ if "%VSCMD_ARG_HOST_ARCH%"=="x86" set OUTDIR=out-win-x86 set ROOTDIR=%~dp0 set "ROOTDIR_CMAKE=%ROOTDIR:\=/%" -set ZIG_VERSION="0.14.0-dev.1622+2ac543388" +set ZIG_VERSION="0.14.0-dev.1876+41dbd0d0d" set JOBS_ARG= pushd %ROOTDIR% diff --git a/zig/CMakeLists.txt b/zig/CMakeLists.txt index d7dfbfce81..e71f799b54 100644 --- a/zig/CMakeLists.txt +++ b/zig/CMakeLists.txt @@ -125,8 +125,8 @@ check_pie_supported( OUTPUT_VARIABLE ZIG_PIE_SUPPORTED_BY_CMAKE LANGUAGES C CXX ) -if(ZIG_PIE AND NOT ZIG_PIE_SUPPORTED_BY_CMAKE) - message(SEND_ERROR "ZIG_PIE was requested but CMake does not support it for \"zigcpp\" target") +if(ZIG_PIE AND NOT CMAKE_CXX_LINK_PIE_SUPPORTED) + message(SEND_ERROR "ZIG_PIE was requested but CMake does not support it for \"zigcpp\" target: ${ZIG_PIE_SUPPORTED_BY_CMAKE}") endif() @@ -894,9 +894,7 @@ set(BUILD_COMPILER_RT_ARGS --name compiler_rt -femit-bin="${ZIG_COMPILER_RT_C_SOURCE}" -target "${ZIG_HOST_TARGET_TRIPLE}" - --dep "build_options" "-Mroot=lib/compiler_rt.zig" - "-Mbuild_options=${ZIG_CONFIG_ZIG_OUT}" ) add_custom_command( diff --git a/zig/README.md b/zig/README.md index 865bd178b3..818a7d67f8 100644 --- a/zig/README.md +++ b/zig/README.md @@ -47,7 +47,7 @@ Ensure you have the required dependencies: * CMake >= 3.15 * System C/C++ Toolchain - * LLVM, Clang, LLD development libraries == 18.x + * LLVM, Clang, LLD development libraries == 19.x Then it is the standard CMake build process: diff --git a/zig/bootstrap.c b/zig/bootstrap.c index a373522de4..f341740a0e 100644 --- a/zig/bootstrap.c +++ b/zig/bootstrap.c @@ -123,7 +123,7 @@ int main(int argc, char **argv) { if (f == NULL) panic("unable to open config.zig for writing"); - const char *zig_version = "0.14.0-dev.1622+2ac543388"; + const char *zig_version = "0.14.0-dev.1876+41dbd0d0d"; int written = fprintf(f, "pub const have_llvm = false;\n" @@ -170,9 +170,7 @@ int main(int argc, char **argv) { "-ofmt=c", "-OReleaseSmall", "--name", "compiler_rt", "-femit-bin=compiler_rt.c", "-target", host_triple, - "--dep", "build_options", "-Mroot=lib/compiler_rt.zig", - "-Mbuild_options=config.zig", NULL, }; print_and_run(child_argv); diff --git a/zig/build.zig b/zig/build.zig index 731b825c07..a5f4cd5675 100644 --- a/zig/build.zig +++ b/zig/build.zig @@ -577,6 +577,10 @@ pub fn build(b: *std.Build) !void { } else { update_mingw_step.dependOn(&b.addFail("The -Dmingw-src=... option is required for this step").step); } + + const test_incremental_step = b.step("test-incremental", "Run the incremental compilation test cases"); + try tests.addIncrementalTests(b, test_incremental_step); + test_step.dependOn(test_incremental_step); } fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { diff --git a/zig/doc/langref.html.in b/zig/doc/langref.html.in index 9f12829349..54b923d0d9 100644 --- a/zig/doc/langref.html.in +++ b/zig/doc/langref.html.in @@ -4218,11 +4218,10 @@ pub fn print(self: *Writer, arg0: []const u8, arg1: i32) !void { {#header_close#} {#header_open|Atomics#} -

TODO: @fence()

TODO: @atomic rmw

TODO: builtin atomic memory ordering enum

- {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} + {#see_also|@atomicLoad|@atomicStore|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} {#header_close#} @@ -4307,7 +4306,7 @@ comptime { an integer or an enum.

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

- {#see_also|@atomicStore|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} + {#see_also|@atomicStore|@atomicRmw||@cmpxchgWeak|@cmpxchgStrong#} {#header_close#} {#header_open|@atomicRmw#} @@ -4322,7 +4321,7 @@ comptime {

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

{#syntax#}AtomicRmwOp{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicRmwOp{#endsyntax#}.

- {#see_also|@atomicStore|@atomicLoad|@fence|@cmpxchgWeak|@cmpxchgStrong#} + {#see_also|@atomicStore|@atomicLoad|@cmpxchgWeak|@cmpxchgStrong#} {#header_close#} {#header_open|@atomicStore#} @@ -4335,7 +4334,7 @@ comptime { an integer or an enum.

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

- {#see_also|@atomicLoad|@atomicRmw|@fence|@cmpxchgWeak|@cmpxchgStrong#} + {#see_also|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} {#header_close#} {#header_open|@bitCast#} @@ -4568,7 +4567,7 @@ comptime {

{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

- {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@fence|@cmpxchgWeak#} + {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgWeak#} {#header_close#} {#header_open|@cmpxchgWeak#} @@ -4600,7 +4599,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val

{#syntax#}@typeInfo(@TypeOf(ptr)).pointer.alignment{#endsyntax#} must be {#syntax#}>= @sizeOf(T).{#endsyntax#}

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

- {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@fence|@cmpxchgStrong#} + {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgStrong#} {#header_close#} {#header_open|@compileError#} @@ -4766,10 +4765,10 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val Converts an integer into an {#link|enum#} value. The return type is the inferred result type.

- Attempting to convert an integer with no corresponding value in the enum invokes + Attempting to convert an integer with no corresponding value in the enum invokes safety-checked {#link|Undefined Behavior#}. Note that a {#link|non-exhaustive enum|Non-exhaustive enum#} has corresponding values for all - integers in the enum's integer tag type: the {#syntax#}_{#endsyntax#} value represents all + integers in the enum's integer tag type: the {#syntax#}_{#endsyntax#} value represents all the remaining unnamed integers in the enum's tag type.

{#see_also|@intFromEnum#} @@ -4857,15 +4856,6 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val {#see_also|@export#} {#header_close#} - {#header_open|@fence#} -
{#syntax#}@fence(order: AtomicOrder) void{#endsyntax#}
-

- The {#syntax#}fence{#endsyntax#} function is used to introduce happens-before edges between operations. -

-

{#syntax#}AtomicOrder{#endsyntax#} can be found with {#syntax#}@import("std").builtin.AtomicOrder{#endsyntax#}.

- {#see_also|@atomicStore|@atomicLoad|@atomicRmw|@cmpxchgWeak|@cmpxchgStrong#} - {#header_close#} - {#header_open|@field#}
{#syntax#}@field(lhs: anytype, comptime field_name: []const u8) (field){#endsyntax#}

Performs field access by a compile-time string. Works on both fields and declarations. @@ -6241,11 +6231,13 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val

  • Are you linking libc? In this case, {#syntax#}std.heap.c_allocator{#endsyntax#} is likely the right choice, at least for your main allocator.
  • +
  • + Need to use the same allocator in multiple threads? Use one of your choice + wrapped around {#syntax#}std.heap.ThreadSafeAllocator{#endsyntax#} +
  • Is the maximum number of bytes that you will need bounded by a number known at - {#link|comptime#}? In this case, use {#syntax#}std.heap.FixedBufferAllocator{#endsyntax#} or - {#syntax#}std.heap.ThreadSafeFixedBufferAllocator{#endsyntax#} depending on whether you need - thread-safety or not. + {#link|comptime#}? In this case, use {#syntax#}std.heap.FixedBufferAllocator{#endsyntax#}.
  • Is your program a command line application which runs from start to end without any fundamental diff --git a/zig/lib/compiler/aro/aro/Compilation.zig b/zig/lib/compiler/aro/aro/Compilation.zig index 22ca9c00ed..414cdb45f0 100644 --- a/zig/lib/compiler/aro/aro/Compilation.zig +++ b/zig/lib/compiler/aro/aro/Compilation.zig @@ -308,7 +308,7 @@ fn generateSystemDefines(comp: *Compilation, w: anytype) !void { ), else => {}, } - if (comp.target.abi == .android) { + if (comp.target.isAndroid()) { try w.writeAll("#define __ANDROID__ 1\n"); } diff --git a/zig/lib/compiler/aro/aro/target.zig b/zig/lib/compiler/aro/aro/target.zig index b84788429a..c07935a420 100644 --- a/zig/lib/compiler/aro/aro/target.zig +++ b/zig/lib/compiler/aro/aro/target.zig @@ -482,7 +482,6 @@ pub fn get32BitArchVariant(target: std.Target) ?std.Target { .spirv, .spirv32, .loongarch32, - .dxil, .xtensa, => {}, // Already 32 bit @@ -509,7 +508,6 @@ pub fn get64BitArchVariant(target: std.Target) ?std.Target { .arc, .avr, .csky, - .dxil, .hexagon, .kalimba, .lanai, @@ -578,7 +576,6 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { .bpfel => "bpfel", .bpfeb => "bpfeb", .csky => "csky", - .dxil => "dxil", .hexagon => "hexagon", .loongarch32 => "loongarch32", .loongarch64 => "loongarch64", @@ -655,7 +652,6 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { .tvos => "tvos", .watchos => "watchos", .driverkit => "driverkit", - .shadermodel => "shadermodel", .visionos => "xros", .serenity => "serenity", .bridgeos => "bridgeos", @@ -693,6 +689,7 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { .eabi => "eabi", .eabihf => "eabihf", .android => "android", + .androideabi => "androideabi", .musl => "musl", .musleabi => "musleabi", .musleabihf => "musleabihf", @@ -702,22 +699,8 @@ pub fn toLLVMTriple(target: std.Target, buf: []u8) []const u8 { .cygnus => "cygnus", .simulator => "simulator", .macabi => "macabi", - .pixel => "pixel", - .vertex => "vertex", - .geometry => "geometry", - .hull => "hull", - .domain => "domain", - .compute => "compute", - .library => "library", - .raygeneration => "raygeneration", - .intersection => "intersection", - .anyhit => "anyhit", - .closesthit => "closesthit", - .miss => "miss", - .callable => "callable", - .mesh => "mesh", - .amplification => "amplification", - .ohos => "openhos", + .ohos => "ohos", + .ohoseabi => "ohoseabi", }; writer.writeAll(llvm_abi) catch unreachable; return stream.getWritten(); diff --git a/zig/lib/compiler/fmt.zig b/zig/lib/compiler/fmt.zig index c747addd72..5a4f112c34 100644 --- a/zig/lib/compiler/fmt.zig +++ b/zig/lib/compiler/fmt.zig @@ -207,6 +207,7 @@ const FmtError = error{ LockViolation, NetNameDeleted, InvalidArgument, + ProcessNotFound, } || fs.File.OpenError; fn fmtPath(fmt: *Fmt, file_path: []const u8, check_mode: bool, dir: fs.Dir, sub_path: []const u8) FmtError!void { diff --git a/zig/lib/compiler/objcopy.zig b/zig/lib/compiler/objcopy.zig index ac609c94e5..9794671e6f 100644 --- a/zig/lib/compiler/objcopy.zig +++ b/zig/lib/compiler/objcopy.zig @@ -40,6 +40,9 @@ fn cmdObjCopy( var only_keep_debug: bool = false; var compress_debug_sections: bool = false; var listen = false; + var add_section: ?AddSection = null; + var set_section_alignment: ?SetSectionAlignment = null; + var set_section_flags: ?SetSectionFlags = null; while (i < args.len) : (i += 1) { const arg = args[i]; if (!mem.startsWith(u8, arg, "-")) { @@ -104,6 +107,37 @@ fn cmdObjCopy( i += 1; if (i >= args.len) fatal("expected another argument after '{s}'", .{arg}); opt_extract = args[i]; + } else if (mem.eql(u8, arg, "--set-section-alignment")) { + i += 1; + if (i >= args.len) fatal("expected section name and alignment arguments after '{s}'", .{arg}); + + if (splitOption(args[i])) |split| { + const alignment = std.fmt.parseInt(u32, split.second, 10) catch |err| { + fatal("unable to parse alignment number: '{s}': {s}", .{ split.second, @errorName(err) }); + }; + if (!std.math.isPowerOfTwo(alignment)) fatal("alignment must be a power of two", .{}); + set_section_alignment = .{ .section_name = split.first, .alignment = alignment }; + } else { + fatal("unrecognized argument: '{s}', expecting =", .{args[i]}); + } + } else if (mem.eql(u8, arg, "--set-section-flags")) { + i += 1; + if (i >= args.len) fatal("expected section name and filename arguments after '{s}'", .{arg}); + + if (splitOption(args[i])) |split| { + set_section_flags = .{ .section_name = split.first, .flags = parseSectionFlags(split.second) }; + } else { + fatal("unrecognized argument: '{s}', expecting =", .{args[i]}); + } + } else if (mem.eql(u8, arg, "--add-section")) { + i += 1; + if (i >= args.len) fatal("expected section name and filename arguments after '{s}'", .{arg}); + + if (splitOption(args[i])) |split| { + add_section = .{ .section_name = split.first, .file_path = split.second }; + } else { + fatal("unrecognized argument: '{s}', expecting =", .{args[i]}); + } } else { fatal("unrecognized argument: '{s}'", .{arg}); } @@ -151,6 +185,12 @@ fn cmdObjCopy( fatal("zig objcopy: ELF to RAW or HEX copying does not support --strip", .{}); if (opt_extract != null) fatal("zig objcopy: ELF to RAW or HEX copying does not support --extract-to", .{}); + if (add_section != null) + fatal("zig objcopy: ELF to RAW or HEX copying does not support --add-section", .{}); + if (set_section_alignment != null) + fatal("zig objcopy: ELF to RAW or HEX copying does not support --set_section_alignment", .{}); + if (set_section_flags != null) + fatal("zig objcopy: ELF to RAW or HEX copying does not support --set_section_flags", .{}); try emitElf(arena, in_file, out_file, elf_hdr, .{ .ofmt = out_fmt, @@ -175,6 +215,9 @@ fn cmdObjCopy( .add_debuglink = opt_add_debuglink, .extract_to = opt_extract, .compress_debug = compress_debug_sections, + .add_section = add_section, + .set_section_alignment = set_section_alignment, + .set_section_flags = set_section_flags, }); return std.process.cleanExit(); }, @@ -217,18 +260,21 @@ const usage = \\Usage: zig objcopy [options] input output \\ \\Options: - \\ -h, --help Print this help and exit - \\ --output-target= Format of the output file - \\ -O Alias for --output-target - \\ --only-section=
    Remove all but
    - \\ -j Alias for --only-section - \\ --pad-to Pad the last section up to address - \\ --strip-debug, -g Remove all debug sections from the output. - \\ --strip-all, -S Remove all debug sections and symbol table from the output. - \\ --only-keep-debug Strip a file, removing contents of any sections that would not be stripped by --strip-debug and leaving the debugging sections intact. - \\ --add-gnu-debuglink= Creates a .gnu_debuglink section which contains a reference to and adds it to the output file. - \\ --extract-to Extract the removed sections into , and add a .gnu-debuglink section. - \\ --compress-debug-sections Compress DWARF debug sections with zlib + \\ -h, --help Print this help and exit + \\ --output-target= Format of the output file + \\ -O Alias for --output-target + \\ --only-section=
    Remove all but
    + \\ -j Alias for --only-section + \\ --pad-to Pad the last section up to address + \\ --strip-debug, -g Remove all debug sections from the output. + \\ --strip-all, -S Remove all debug sections and symbol table from the output. + \\ --only-keep-debug Strip a file, removing contents of any sections that would not be stripped by --strip-debug and leaving the debugging sections intact. + \\ --add-gnu-debuglink= Creates a .gnu_debuglink section which contains a reference to and adds it to the output file. + \\ --extract-to Extract the removed sections into , and add a .gnu-debuglink section. + \\ --compress-debug-sections Compress DWARF debug sections with zlib + \\ --set-section-alignment = Set alignment of section to bytes. Must be a power of two. + \\ --set-section-flags = Set flags of section to represented as a comma separated set of flags. + \\ --add-section = Add file content from with the a new section named . \\ ; @@ -236,6 +282,24 @@ pub const EmitRawElfOptions = struct { ofmt: std.Target.ObjectFormat, only_section: ?[]const u8 = null, pad_to: ?u64 = null, + add_section: ?AddSection = null, + set_section_alignment: ?SetSectionAlignment = null, + set_section_flags: ?SetSectionFlags = null, +}; + +const AddSection = struct { + section_name: []const u8, + file_path: []const u8, +}; + +const SetSectionAlignment = struct { + section_name: []const u8, + alignment: u32, +}; + +const SetSectionFlags = struct { + section_name: []const u8, + flags: SectionFlags, }; fn emitElf( @@ -392,7 +456,7 @@ const BinaryElfOutput = struct { if (phdr.p_type == elf.PT_LOAD) { const newSegment = try allocator.create(BinaryElfSegment); - newSegment.physicalAddress = if (phdr.p_paddr != 0) phdr.p_paddr else phdr.p_vaddr; + newSegment.physicalAddress = phdr.p_paddr; newSegment.virtualAddress = phdr.p_vaddr; newSegment.fileSize = @intCast(phdr.p_filesz); newSegment.elfOffset = phdr.p_offset; @@ -678,6 +742,9 @@ const StripElfOptions = struct { strip_debug: bool = false, only_keep_debug: bool = false, compress_debug: bool = false, + add_section: ?AddSection, + set_section_alignment: ?SetSectionAlignment, + set_section_flags: ?SetSectionFlags, }; fn stripElf( @@ -721,6 +788,14 @@ fn stripElf( var elf_file = try ElfFile(is_64).parse(allocator, in_file, elf_hdr); defer elf_file.deinit(); + if (options.add_section) |user_section| { + for (elf_file.sections) |section| { + if (std.mem.eql(u8, section.name, user_section.section_name)) { + fatal("zig objcopy: unable to add section '{s}'. Section already exists in input", .{user_section.section_name}); + } + } + } + if (filter_complement) |flt| { // write the .dbg file and close it, so it can be read back to compute the debuglink checksum. const path = options.extract_to.?; @@ -733,7 +808,14 @@ fn stripElf( } const debuglink: ?DebugLink = if (debuglink_path) |path| ElfFileHelper.createDebugLink(path) else null; - try elf_file.emit(allocator, out_file, in_file, .{ .section_filter = filter, .debuglink = debuglink, .compress_debug = options.compress_debug }); + try elf_file.emit(allocator, out_file, in_file, .{ + .section_filter = filter, + .debuglink = debuglink, + .compress_debug = options.compress_debug, + .add_section = options.add_section, + .set_section_alignment = options.set_section_alignment, + .set_section_flags = options.set_section_flags, + }); }, } } @@ -786,7 +868,7 @@ fn ElfFile(comptime is_64: bool) type { // program header: list of segments const program_segments = blk: { if (@sizeOf(Elf_Phdr) != header.phentsize) - fatal("zig objcopy: unsuported ELF file, unexpected phentsize ({d})", .{header.phentsize}); + fatal("zig objcopy: unsupported ELF file, unexpected phentsize ({d})", .{header.phentsize}); const program_header = try allocator.alloc(Elf_Phdr, header.phnum); const bytes_read = try in_file.preadAll(std.mem.sliceAsBytes(program_header), header.phoff); @@ -798,7 +880,7 @@ fn ElfFile(comptime is_64: bool) type { // section header const sections = blk: { if (@sizeOf(Elf_Shdr) != header.shentsize) - fatal("zig objcopy: unsuported ELF file, unexpected shentsize ({d})", .{header.shentsize}); + fatal("zig objcopy: unsupported ELF file, unexpected shentsize ({d})", .{header.shentsize}); const section_header = try allocator.alloc(Section, header.shnum); @@ -896,6 +978,9 @@ fn ElfFile(comptime is_64: bool) type { section_filter: Filter = .all, debuglink: ?DebugLink = null, compress_debug: bool = false, + add_section: ?AddSection = null, + set_section_alignment: ?SetSectionAlignment = null, + set_section_flags: ?SetSectionFlags = null, }; fn emit(self: *const Self, gpa: Allocator, out_file: File, in_file: File, options: EmitElfOptions) !void { var arena = std.heap.ArenaAllocator.init(gpa); @@ -934,6 +1019,10 @@ fn ElfFile(comptime is_64: bool) type { if (options.debuglink != null) next_idx += 1; + if (options.add_section != null) { + next_idx += 1; + } + break :blk next_idx; }; @@ -959,6 +1048,28 @@ fn ElfFile(comptime is_64: bool) type { break :blk new_offset; }; + // add user section to the string table if needed + const user_section_name: u32 = blk: { + if (options.add_section == null) break :blk elf.SHN_UNDEF; + if (self.raw_elf_header.e_shstrndx == elf.SHN_UNDEF) + fatal("zig objcopy: no strtab, cannot add the user section", .{}); // TODO add the section if needed? + + const strtab = &self.sections[self.raw_elf_header.e_shstrndx]; + const update = §ions_update[self.raw_elf_header.e_shstrndx]; + + const name = options.add_section.?.section_name; + const new_offset: u32 = @intCast(strtab.payload.?.len); + const buf = try allocator.alignedAlloc(u8, section_memory_align, new_offset + name.len + 1); + @memcpy(buf[0..new_offset], strtab.payload.?); + @memcpy(buf[new_offset..][0..name.len], name); + buf[new_offset + name.len] = 0; + + assert(update.action == .keep); + update.payload = buf; + + break :blk new_offset; + }; + // maybe compress .debug sections if (options.compress_debug) { for (self.sections[1..], sections_update[1..]) |section, *update| { @@ -1018,7 +1129,7 @@ fn ElfFile(comptime is_64: bool) type { if (section.section.sh_type == elf.SHT_NOBITS) continue; if (section.section.sh_offset < offset) { - fatal("zig objcopy: unsuported ELF file", .{}); + fatal("zig objcopy: unsupported ELF file", .{}); } offset = section.section.sh_offset; } @@ -1134,10 +1245,100 @@ fn ElfFile(comptime is_64: bool) type { eof_offset += @as(Elf_OffSize, @intCast(payload.len)); } + // --add-section + if (options.add_section) |add_section| { + var section_file = fs.cwd().openFile(add_section.file_path, .{}) catch |err| + fatal("unable to open '{s}': {s}", .{ add_section.file_path, @errorName(err) }); + defer section_file.close(); + + const payload = try section_file.readToEndAlloc(arena.allocator(), std.math.maxInt(usize)); + + dest_sections[dest_section_idx] = Elf_Shdr{ + .sh_name = user_section_name, + .sh_type = elf.SHT_PROGBITS, + .sh_flags = 0, + .sh_addr = 0, + .sh_offset = eof_offset, + .sh_size = @intCast(payload.len), + .sh_link = elf.SHN_UNDEF, + .sh_info = elf.SHN_UNDEF, + .sh_addralign = 4, + .sh_entsize = 0, + }; + dest_section_idx += 1; + + cmdbuf.appendAssumeCapacity(.{ .write_data = .{ .data = payload, .out_offset = eof_offset } }); + eof_offset += @as(Elf_OffSize, @intCast(payload.len)); + } + assert(dest_section_idx == new_shnum); break :blk dest_sections; }; + // --set-section-alignment: overwrite alignment + if (options.set_section_alignment) |set_align| { + if (self.raw_elf_header.e_shstrndx == elf.SHN_UNDEF) + fatal("zig objcopy: no strtab, cannot add the user section", .{}); // TODO add the section if needed? + + const strtab = §ions_update[self.raw_elf_header.e_shstrndx]; + for (updated_section_header) |*section| { + const section_name = std.mem.span(@as([*:0]const u8, @ptrCast(&strtab.payload.?[section.sh_name]))); + if (std.mem.eql(u8, section_name, set_align.section_name)) { + section.sh_addralign = set_align.alignment; + break; + } + } else std.log.warn("Skipping --set-section-alignment. Section '{s}' not found", .{set_align.section_name}); + } + + // --set-section-flags: overwrite flags + if (options.set_section_flags) |set_flags| { + if (self.raw_elf_header.e_shstrndx == elf.SHN_UNDEF) + fatal("zig objcopy: no strtab, cannot add the user section", .{}); // TODO add the section if needed? + + const strtab = §ions_update[self.raw_elf_header.e_shstrndx]; + for (updated_section_header) |*section| { + const section_name = std.mem.span(@as([*:0]const u8, @ptrCast(&strtab.payload.?[section.sh_name]))); + if (std.mem.eql(u8, section_name, set_flags.section_name)) { + section.sh_flags = std.elf.SHF_WRITE; // default is writable cleared by "readonly" + const f = set_flags.flags; + + // Supporting a subset of GNU and LLVM objcopy for ELF only + // GNU: + // alloc: add SHF_ALLOC + // contents: if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing + // load: if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) + // noload: not ELF relevant + // readonly: clear default SHF_WRITE flag + // code: add SHF_EXECINSTR + // data: not ELF relevant + // rom: ignored + // exclude: add SHF_EXCLUDE + // share: not ELF relevant + // debug: not ELF relevant + // large: add SHF_X86_64_LARGE. Fatal error if target is not x86_64 + if (f.alloc) section.sh_flags |= std.elf.SHF_ALLOC; + if (f.contents or f.load) { + if (section.sh_type == std.elf.SHT_NOBITS) section.sh_type = std.elf.SHT_PROGBITS; + } + if (f.readonly) section.sh_flags &= ~@as(@TypeOf(section.sh_type), std.elf.SHF_WRITE); + if (f.code) section.sh_flags |= std.elf.SHF_EXECINSTR; + if (f.exclude) section.sh_flags |= std.elf.SHF_EXCLUDE; + if (f.large) { + if (updated_elf_header.e_machine != std.elf.EM.X86_64) + fatal("zig objcopy: 'large' section flag is only supported on x86_64 targets", .{}); + section.sh_flags |= std.elf.SHF_X86_64_LARGE; + } + + // LLVM: + // merge: add SHF_MERGE + // strings: add SHF_STRINGS + if (f.merge) section.sh_flags |= std.elf.SHF_MERGE; + if (f.strings) section.sh_flags |= std.elf.SHF_STRINGS; + break; + } + } else std.log.warn("Skipping --set-section-flags. Section '{s}' not found", .{set_flags.section_name}); + } + // write the section header at the tail { const offset = std.mem.alignForward(Elf_OffSize, eof_offset, @alignOf(Elf_Shdr)); @@ -1361,3 +1562,111 @@ const ElfFileHelper = struct { return hasher.final(); } }; + +const SectionFlags = packed struct { + alloc: bool = false, + contents: bool = false, + load: bool = false, + noload: bool = false, + readonly: bool = false, + code: bool = false, + data: bool = false, + rom: bool = false, + exclude: bool = false, + shared: bool = false, + debug: bool = false, + large: bool = false, + merge: bool = false, + strings: bool = false, +}; + +fn parseSectionFlags(comma_separated_flags: []const u8) SectionFlags { + const P = struct { + fn parse(flags: *SectionFlags, string: []const u8) void { + if (string.len == 0) return; + + if (std.mem.eql(u8, string, "alloc")) { + flags.alloc = true; + } else if (std.mem.eql(u8, string, "contents")) { + flags.contents = true; + } else if (std.mem.eql(u8, string, "load")) { + flags.load = true; + } else if (std.mem.eql(u8, string, "noload")) { + flags.noload = true; + } else if (std.mem.eql(u8, string, "readonly")) { + flags.readonly = true; + } else if (std.mem.eql(u8, string, "code")) { + flags.code = true; + } else if (std.mem.eql(u8, string, "data")) { + flags.data = true; + } else if (std.mem.eql(u8, string, "rom")) { + flags.rom = true; + } else if (std.mem.eql(u8, string, "exclude")) { + flags.exclude = true; + } else if (std.mem.eql(u8, string, "shared")) { + flags.shared = true; + } else if (std.mem.eql(u8, string, "debug")) { + flags.debug = true; + } else if (std.mem.eql(u8, string, "large")) { + flags.large = true; + } else if (std.mem.eql(u8, string, "merge")) { + flags.merge = true; + } else if (std.mem.eql(u8, string, "strings")) { + flags.strings = true; + } else { + std.log.warn("Skipping unrecognized section flag '{s}'", .{string}); + } + } + }; + + var flags = SectionFlags{}; + var offset: usize = 0; + for (comma_separated_flags, 0..) |c, i| { + if (c == ',') { + defer offset = i + 1; + const string = comma_separated_flags[offset..i]; + P.parse(&flags, string); + } + } + P.parse(&flags, comma_separated_flags[offset..]); + return flags; +} + +test "Parse section flags" { + const F = SectionFlags; + try std.testing.expectEqual(F{}, parseSectionFlags("")); + try std.testing.expectEqual(F{}, parseSectionFlags(",")); + try std.testing.expectEqual(F{}, parseSectionFlags("abc")); + try std.testing.expectEqual(F{ .alloc = true }, parseSectionFlags("alloc")); + try std.testing.expectEqual(F{ .data = true }, parseSectionFlags("data,")); + try std.testing.expectEqual(F{ .alloc = true, .code = true }, parseSectionFlags("alloc,code")); + try std.testing.expectEqual(F{ .alloc = true, .code = true }, parseSectionFlags("alloc,code,not_supported")); +} + +const SplitResult = struct { first: []const u8, second: []const u8 }; + +fn splitOption(option: []const u8) ?SplitResult { + const separator = '='; + if (option.len < 3) return null; // minimum "a=b" + for (1..option.len - 1) |i| { + if (option[i] == separator) return .{ + .first = option[0..i], + .second = option[i + 1 ..], + }; + } + return null; +} + +test "Split option" { + { + const split = splitOption(".abc=123"); + try std.testing.expect(split != null); + try std.testing.expectEqualStrings(".abc", split.?.first); + try std.testing.expectEqualStrings("123", split.?.second); + } + + try std.testing.expectEqual(null, splitOption("")); + try std.testing.expectEqual(null, splitOption("=abc")); + try std.testing.expectEqual(null, splitOption("abc=")); + try std.testing.expectEqual(null, splitOption("abc")); +} diff --git a/zig/lib/compiler_rt/aulldiv.zig b/zig/lib/compiler_rt/aulldiv.zig index 21ec61722b..6d822b7b86 100644 --- a/zig/lib/compiler_rt/aulldiv.zig +++ b/zig/lib/compiler_rt/aulldiv.zig @@ -1,13 +1,14 @@ const std = @import("std"); const builtin = @import("builtin"); const arch = builtin.cpu.arch; +const os = builtin.os.tag; const abi = builtin.abi; const common = @import("common.zig"); pub const panic = common.panic; comptime { - if (arch == .x86 and abi == .msvc and builtin.zig_backend != .stage2_c) { + if (arch == .x86 and os == .windows and (abi == .msvc or abi == .itanium) and builtin.zig_backend != .stage2_c) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins @export(&_alldiv, .{ .name = "\x01__alldiv", .linkage = common.linkage, .visibility = common.visibility }); @export(&_aulldiv, .{ .name = "\x01__aulldiv", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/zig/lib/compiler_rt/aullrem.zig b/zig/lib/compiler_rt/aullrem.zig index c1578aeb8b..5c4d0588f7 100644 --- a/zig/lib/compiler_rt/aullrem.zig +++ b/zig/lib/compiler_rt/aullrem.zig @@ -1,13 +1,14 @@ const std = @import("std"); const builtin = @import("builtin"); const arch = builtin.cpu.arch; +const os = builtin.os.tag; const abi = builtin.abi; const common = @import("common.zig"); pub const panic = common.panic; comptime { - if (arch == .x86 and abi == .msvc and builtin.zig_backend != .stage2_c) { + if (arch == .x86 and os == .windows and (abi == .msvc or abi == .itanium) and builtin.zig_backend != .stage2_c) { // Don't let LLVM apply the stdcall name mangling on those MSVC builtins @export(&_allrem, .{ .name = "\x01__allrem", .linkage = common.linkage, .visibility = common.visibility }); @export(&_aullrem, .{ .name = "\x01__aullrem", .linkage = common.linkage, .visibility = common.visibility }); diff --git a/zig/lib/compiler_rt/common.zig b/zig/lib/compiler_rt/common.zig index 1dfd4be07f..786dc7303a 100644 --- a/zig/lib/compiler_rt/common.zig +++ b/zig/lib/compiler_rt/common.zig @@ -1,8 +1,14 @@ const std = @import("std"); const builtin = @import("builtin"); const native_endian = builtin.cpu.arch.endian(); +const ofmt_c = builtin.object_format == .c; -pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) .internal else .weak; +pub const linkage: std.builtin.GlobalLinkage = if (builtin.is_test) + .internal +else if (ofmt_c) + .strong +else + .weak; /// Determines the symbol's visibility to other objects. /// For WebAssembly this allows the symbol to be resolved to other modules, but will not /// export it to the host runtime. @@ -16,19 +22,22 @@ pub const want_aeabi = switch (builtin.abi) { .gnueabi, .gnueabihf, .android, + .androideabi, => switch (builtin.cpu.arch) { .arm, .armeb, .thumb, .thumbeb => true, else => false, }, else => false, }; +pub const want_mingw_arm_abi = builtin.cpu.arch.isArmOrThumb() and builtin.target.isMinGW(); + pub const want_ppc_abi = builtin.cpu.arch.isPowerPC(); pub const want_float_exceptions = !builtin.cpu.arch.isWasm(); // Libcalls that involve u128 on Windows x86-64 are expected by LLVM to use the // calling convention of @Vector(2, u64), rather than what's standard. -pub const want_windows_v2u64_abi = builtin.os.tag == .windows and builtin.cpu.arch == .x86_64 and @import("builtin").object_format != .c; +pub const want_windows_v2u64_abi = builtin.os.tag == .windows and builtin.cpu.arch == .x86_64 and !ofmt_c; /// This governs whether to use these symbol names for f16/f32 conversions /// rather than the standard names: @@ -67,13 +76,14 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) { pub const want_sparc_abi = builtin.cpu.arch.isSPARC(); -// Avoid dragging in the runtime safety mechanisms into this .o file, -// unless we're trying to test compiler-rt. -pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { - _ = error_return_trace; +// Avoid dragging in the runtime safety mechanisms into this .o file, unless +// we're trying to test compiler-rt. +pub const Panic = if (builtin.is_test) std.debug.FormattedPanic else struct {}; + +/// To be deleted after zig1.wasm is updated. +pub fn panic(msg: []const u8, error_return_trace: ?*std.builtin.StackTrace, ret_addr: ?usize) noreturn { if (builtin.is_test) { - @branchHint(.cold); - std.debug.panic("{s}", .{msg}); + std.debug.defaultPanic(msg, error_return_trace, ret_addr orelse @returnAddress()); } else { unreachable; } diff --git a/zig/lib/compiler_rt/emutls.zig b/zig/lib/compiler_rt/emutls.zig index 55927b8b37..b0244a14f5 100644 --- a/zig/lib/compiler_rt/emutls.zig +++ b/zig/lib/compiler_rt/emutls.zig @@ -18,7 +18,7 @@ const gcc_word = usize; pub const panic = common.panic; comptime { - if (builtin.link_libc and (builtin.abi == .android or builtin.os.tag == .openbsd)) { + if (builtin.link_libc and (builtin.abi.isAndroid() or builtin.os.tag == .openbsd)) { @export(&__emutls_get_address, .{ .name = "__emutls_get_address", .linkage = common.linkage, .visibility = common.visibility }); } } diff --git a/zig/lib/compiler_rt/fixdfdi.zig b/zig/lib/compiler_rt/fixdfdi.zig index 78744b145d..b9bc5797b9 100644 --- a/zig/lib/compiler_rt/fixdfdi.zig +++ b/zig/lib/compiler_rt/fixdfdi.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_d2lz, .{ .name = "__aeabi_d2lz", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__fixdfdi, .{ .name = "__fixdfdi", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__fixdfdi, .{ .name = "__dtoi64", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/fixsfdi.zig b/zig/lib/compiler_rt/fixsfdi.zig index c75e401475..192614bd79 100644 --- a/zig/lib/compiler_rt/fixsfdi.zig +++ b/zig/lib/compiler_rt/fixsfdi.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_f2lz, .{ .name = "__aeabi_f2lz", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__fixsfdi, .{ .name = "__fixsfdi", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__fixsfdi, .{ .name = "__stoi64", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/fixunsdfdi.zig b/zig/lib/compiler_rt/fixunsdfdi.zig index 68a0c44ff9..86a4fa9de1 100644 --- a/zig/lib/compiler_rt/fixunsdfdi.zig +++ b/zig/lib/compiler_rt/fixunsdfdi.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_d2ulz, .{ .name = "__aeabi_d2ulz", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__fixunsdfdi, .{ .name = "__fixunsdfdi", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__fixunsdfdi, .{ .name = "__dtou64", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/fixunssfdi.zig b/zig/lib/compiler_rt/fixunssfdi.zig index 9157a71e2f..81d1c77f06 100644 --- a/zig/lib/compiler_rt/fixunssfdi.zig +++ b/zig/lib/compiler_rt/fixunssfdi.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const intFromFloat = @import("./int_from_float.zig").intFromFloat; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_f2ulz, .{ .name = "__aeabi_f2ulz", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__fixunssfdi, .{ .name = "__fixunssfdi", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__fixunssfdi, .{ .name = "__stou64", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/floatdidf.zig b/zig/lib/compiler_rt/floatdidf.zig index 393fa95c19..fc145e836d 100644 --- a/zig/lib/compiler_rt/floatdidf.zig +++ b/zig/lib/compiler_rt/floatdidf.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_l2d, .{ .name = "__aeabi_l2d", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__floatdidf, .{ .name = "__floatdidf", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__floatdidf, .{ .name = "__i64tod", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/floatdisf.zig b/zig/lib/compiler_rt/floatdisf.zig index 4f3b42ef79..d1c9515f9a 100644 --- a/zig/lib/compiler_rt/floatdisf.zig +++ b/zig/lib/compiler_rt/floatdisf.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_l2f, .{ .name = "__aeabi_l2f", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__floatdisf, .{ .name = "__floatdisf", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__floatdisf, .{ .name = "__i64tos", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/floatundidf.zig b/zig/lib/compiler_rt/floatundidf.zig index 5cb1de0d35..3448f0cf20 100644 --- a/zig/lib/compiler_rt/floatundidf.zig +++ b/zig/lib/compiler_rt/floatundidf.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_ul2d, .{ .name = "__aeabi_ul2d", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__floatundidf, .{ .name = "__floatundidf", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__floatundidf, .{ .name = "__u64tod", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/compiler_rt/floatundisf.zig b/zig/lib/compiler_rt/floatundisf.zig index 17f9148575..9054982b54 100644 --- a/zig/lib/compiler_rt/floatundisf.zig +++ b/zig/lib/compiler_rt/floatundisf.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const common = @import("./common.zig"); const floatFromInt = @import("./float_from_int.zig").floatFromInt; @@ -8,6 +9,10 @@ comptime { @export(&__aeabi_ul2f, .{ .name = "__aeabi_ul2f", .linkage = common.linkage, .visibility = common.visibility }); } else { @export(&__floatundisf, .{ .name = "__floatundisf", .linkage = common.linkage, .visibility = common.visibility }); + + if (common.want_mingw_arm_abi) { + @export(&__floatundisf, .{ .name = "__u64tos", .linkage = common.linkage, .visibility = common.visibility }); + } } } diff --git a/zig/lib/libc/glibc/abilists b/zig/lib/libc/glibc/abilists index 4e617973270d8c6fd227a4d35865cd7aa9a4bc07..3aed1e0f930ed2e4e9f6d558c1a42a9ec24eff14 100644 GIT binary patch literal 246035 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]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
    <~5mJ_7`sobhc~{x%AeZ)0+uoMP{iot^?Mq` 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

    qj8jSzG6B>IRl=gVhIAJ0bGKUOMtjK)`3 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 literal 274738 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 Lgc4wDeE -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 addiu $sp,$sp,32 .set macro .set reorder @@ -51,7 +52,8 @@ lw $31,28($sp) .set noreorder .set nomacro - j $31 + /* zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 addiu $sp,$sp,32 .set macro .set reorder diff --git a/zig/lib/libc/glibc/sysdeps/mips/mips64/n32/crtn.S b/zig/lib/libc/glibc/sysdeps/mips/mips64/n32/crtn.S index 633d79cfad..f9a6c7ee4c 100644 --- a/zig/lib/libc/glibc/sysdeps/mips/mips64/n32/crtn.S +++ b/zig/lib/libc/glibc/sysdeps/mips/mips64/n32/crtn.S @@ -43,7 +43,8 @@ ld $28,0($sp) .set noreorder .set nomacro - j $31 + /* zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 addiu $sp,$sp,16 .set macro .set reorder @@ -53,7 +54,8 @@ ld $28,0($sp) .set noreorder .set nomacro - j $31 + /* zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 addiu $sp,$sp,16 .set macro .set reorder diff --git a/zig/lib/libc/glibc/sysdeps/mips/mips64/n64/crtn.S b/zig/lib/libc/glibc/sysdeps/mips/mips64/n64/crtn.S index 99ed1e3263..2722b2812c 100644 --- a/zig/lib/libc/glibc/sysdeps/mips/mips64/n64/crtn.S +++ b/zig/lib/libc/glibc/sysdeps/mips/mips64/n64/crtn.S @@ -43,7 +43,8 @@ ld $28,0($sp) .set noreorder .set nomacro - j $31 + /* zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 daddiu $sp,$sp,16 .set macro .set reorder @@ -53,7 +54,8 @@ ld $28,0($sp) .set noreorder .set nomacro - j $31 + /* zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 */ + jr $31 daddiu $sp,$sp,16 .set macro .set reorder diff --git a/zig/lib/libc/glibc/sysdeps/unix/mips/sysdep.h b/zig/lib/libc/glibc/sysdeps/unix/mips/sysdep.h index d1e0460260..54e92b26d0 100644 --- a/zig/lib/libc/glibc/sysdeps/unix/mips/sysdep.h +++ b/zig/lib/libc/glibc/sysdeps/unix/mips/sysdep.h @@ -39,7 +39,8 @@ .end function; \ .size function,.-function -#define ret j ra ; nop +// zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 +#define ret jr ra ; nop #undef PSEUDO_END #define PSEUDO_END(sym) cfi_endproc; .end sym; .size sym,.-sym diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/endianness.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/endianness.h new file mode 100644 index 0000000000..989463fb5d --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/endianness.h @@ -0,0 +1,11 @@ +#ifndef _BITS_ENDIANNESS_H +#define _BITS_ENDIANNESS_H 1 + +#ifndef _BITS_ENDIAN_H +#error "Never use directly; include instead." +#endif + +/* LoongArch is little-endian. */ +#define __BYTE_ORDER __LITTLE_ENDIAN + +#endif /* bits/endianness.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fcntl.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fcntl.h new file mode 100644 index 0000000000..bbbde65d43 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fcntl.h @@ -0,0 +1,61 @@ +/* O_*, F_*, FD_* bit values for the generic Linux/LoongArch ABI. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _FCNTL_H +#error "Never use directly; include instead." +#endif + +#include + +/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as + non-64-bit versions. It will need to be revised for 128-bit. */ +#if __WORDSIZE == 64 +#define __O_LARGEFILE 0 + +#define F_GETLK64 5 /* Get record locking info. */ +#define F_SETLK64 6 /* Set record locking info (non-blocking). */ +#define F_SETLKW64 7 /* Set record locking info (blocking). */ +#endif + +struct flock +{ + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ +#ifndef __USE_FILE_OFFSET64 + __off_t l_start; /* Offset where the lock begins. */ + __off_t l_len; /* Size of the locked area; zero means until EOF. */ +#else + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ +#endif + __pid_t l_pid; /* Process holding the lock. */ +}; + +#ifdef __USE_LARGEFILE64 +struct flock64 +{ + short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */ + short int l_whence; /* Where `l_start' is relative to (like `lseek'). */ + __off64_t l_start; /* Offset where the lock begins. */ + __off64_t l_len; /* Size of the locked area; zero means until EOF. */ + __pid_t l_pid; /* Process holding the lock. */ +}; +#endif + +/* Include generic Linux declarations. */ +#include \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fenv.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fenv.h new file mode 100644 index 0000000000..92dc84011a --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/fenv.h @@ -0,0 +1,90 @@ +/* Floating point environment. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _FENV_H +#error "Never use directly; include instead." +#endif + +/* Define bits representing the exception. We use the bit positions + of the appropriate bits in the FPU control word. */ +enum +{ + FE_INEXACT = +#define FE_INEXACT 0x010000 + FE_INEXACT, + FE_UNDERFLOW = +#define FE_UNDERFLOW 0x020000 + FE_UNDERFLOW, + FE_OVERFLOW = +#define FE_OVERFLOW 0x040000 + FE_OVERFLOW, + FE_DIVBYZERO = +#define FE_DIVBYZERO 0x080000 + FE_DIVBYZERO, + FE_INVALID = +#define FE_INVALID 0x100000 + FE_INVALID, +}; + +#define FE_ALL_EXCEPT \ + (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID) + +/* The LoongArch FPU supports all of the four defined rounding modes. We + use again the bit positions in the FPU control word as the values + for the appropriate macros. */ +enum +{ + FE_TONEAREST = +#define FE_TONEAREST 0x000 + FE_TONEAREST, + FE_TOWARDZERO = +#define FE_TOWARDZERO 0x100 + FE_TOWARDZERO, + FE_UPWARD = +#define FE_UPWARD 0x200 + FE_UPWARD, + FE_DOWNWARD = +#define FE_DOWNWARD 0x300 + FE_DOWNWARD +}; + +/* Type representing exception flags. */ +typedef unsigned int fexcept_t; + +/* Type representing floating-point environment. This function corresponds + to the layout of the block written by the `fstenv'. */ +typedef struct +{ + unsigned int __fp_control_register; +} fenv_t; + +/* If the default argument is used we use this value. */ +#define FE_DFL_ENV ((const fenv_t *) -1) + +#ifdef __USE_GNU +/* Floating-point environment where none of the exception is masked. */ +#define FE_NOMASK_ENV ((const fenv_t *) -257) +#endif + +#if __GLIBC_USE (IEC_60559_BFP_EXT_C23) +/* Type representing floating-point control modes. */ +typedef unsigned int femode_t; + +/* Default floating-point control modes. */ +#define FE_DFL_MODE ((const femode_t *) -1L) +#endif \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/hwcap.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/hwcap.h new file mode 100644 index 0000000000..3b3d1ad463 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/hwcap.h @@ -0,0 +1,38 @@ +/* Defines for bits in AT_HWCAP. LoongArch64 Linux version. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#if !defined (_SYS_AUXV_H) +# error "Never include directly; use instead." +#endif + +/* The following must match the kernel's . */ +/* HWCAP flags */ +#define HWCAP_LOONGARCH_CPUCFG (1 << 0) +#define HWCAP_LOONGARCH_LAM (1 << 1) +#define HWCAP_LOONGARCH_UAL (1 << 2) +#define HWCAP_LOONGARCH_FPU (1 << 3) +#define HWCAP_LOONGARCH_LSX (1 << 4) +#define HWCAP_LOONGARCH_LASX (1 << 5) +#define HWCAP_LOONGARCH_CRC32 (1 << 6) +#define HWCAP_LOONGARCH_COMPLEX (1 << 7) +#define HWCAP_LOONGARCH_CRYPTO (1 << 8) +#define HWCAP_LOONGARCH_LVZ (1 << 9) +#define HWCAP_LOONGARCH_LBT_X86 (1 << 10) +#define HWCAP_LOONGARCH_LBT_ARM (1 << 11) +#define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) +#define HWCAP_LOONGARCH_PTW (1 << 13) \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link.h new file mode 100644 index 0000000000..821a54fe54 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link.h @@ -0,0 +1,76 @@ +/* Machine-specific declarations for dynamic linker interface. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _LINK_H +#error "Never include directly; use instead." +#endif + +#ifndef __loongarch_soft_float +typedef float La_loongarch_vr + __attribute__ ((__vector_size__ (16), __aligned__ (16))); +typedef float La_loongarch_xr + __attribute__ ((__vector_size__ (32), __aligned__ (16))); + +typedef union +{ + double fpreg[4]; + La_loongarch_vr vr[2]; + La_loongarch_xr xr[1]; +} La_loongarch_vector __attribute__ ((__aligned__ (16))); +#endif + +typedef struct La_loongarch_regs +{ + unsigned long int lr_reg[8]; /* a0 - a7 */ +#ifndef __loongarch_soft_float + La_loongarch_vector lr_vec[8]; /* fa0 - fa7 or vr0 - vr7 or xr0 - xr7*/ +#endif + unsigned long int lr_ra; + unsigned long int lr_sp; +} La_loongarch_regs; + +/* Return values for calls from PLT on LoongArch. */ +typedef struct La_loongarch_retval +{ + unsigned long int lrv_a0; + unsigned long int lrv_a1; +#ifndef __loongarch_soft_float + La_loongarch_vector lrv_vec0; + La_loongarch_vector lrv_vec1; +#endif +} La_loongarch_retval; + +__BEGIN_DECLS + +extern ElfW (Addr) la_loongarch_gnu_pltenter (ElfW (Sym) *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + La_loongarch_regs *__regs, + unsigned int *__flags, + const char *__symname, + long int *__framesizep); +extern unsigned int la_loongarch_gnu_pltexit (ElfW (Sym) *__sym, + unsigned int __ndx, + uintptr_t *__refcook, + uintptr_t *__defcook, + const La_loongarch_regs *__inregs, + La_loongarch_retval *__outregs, + const char *__symname); + +__END_DECLS \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link_lavcurrent.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link_lavcurrent.h new file mode 100644 index 0000000000..36d637cd1f --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/link_lavcurrent.h @@ -0,0 +1,25 @@ +/* Data structure for communication from the run-time dynamic linker for + loaded ELF shared objects. LAV_CURRENT definition. + Copyright (C) 2023-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _LINK_H +# error "Never include directly; use instead." +#endif + +/* Version numbers for la_version handshake interface. */ +#define LAV_CURRENT 3 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/long-double.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/long-double.h new file mode 100644 index 0000000000..a83f6c746f --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/long-double.h @@ -0,0 +1,21 @@ +/* Properties of long double type. ldbl-128 version. + Copyright (C) 2016-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* long double is distinct from double, so there is nothing to + define here. */ +#define __LDOUBLE_REDIRECTS_TO_FLOAT128_ABI 0 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/procfs.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/procfs.h new file mode 100644 index 0000000000..4371fd0a8f --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/procfs.h @@ -0,0 +1,52 @@ +/* Types for registers for sys/procfs.h. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _SYS_PROCFS_H +# error "Never include directly; use instead." +#endif + +/* Type for a general-purpose register. */ +typedef __uint64_t elf_greg_t; + +/* And the whole bunch of them. We could have used `struct + pt_regs' directly in the typedef, but tradition says that + the register set is an array, which does have some peculiar + semantics, so leave it that way. */ +#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof (elf_greg_t)) +typedef elf_greg_t elf_gregset_t[ELF_NGREG]; + +#define ELF_NFPREG 34 /* 32 FPRs + 8-byte byte-vec for fcc + 4-byte FCR */ +typedef union +{ + double d; + float f; +} elf_fpreg_t; +typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; + +typedef union +{ + double d[2]; + float f[4]; +} __attribute__ ((__aligned__ (16))) elf_lsxregset_t[32]; + +typedef union +{ + double d[4]; + float f[8]; +} __attribute__ ((__aligned__ (32))) elf_lasxregset_t[32]; \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/pthread_stack_min.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/pthread_stack_min.h new file mode 100644 index 0000000000..4a05d0d8a5 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/pthread_stack_min.h @@ -0,0 +1,20 @@ +/* Definition of PTHREAD_STACK_MIN. LoongArch Linux version. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +/* Minimum size for a thread. At least two pages with 64k pages. */ +#define PTHREAD_STACK_MIN 131072 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/setjmp.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/setjmp.h new file mode 100644 index 0000000000..59214222c8 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/setjmp.h @@ -0,0 +1,42 @@ +/* Define the machine-dependent type `jmp_buf'. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _LOONGARCH_BITS_SETJMP_H +#define _LOONGARCH_BITS_SETJMP_H + +typedef struct __jmp_buf_internal_tag +{ + /* Program counter. */ + long int __pc; + /* Stack pointer. */ + long int __sp; + /* Reserved */ + long int __x; + /* Frame pointer. */ + long int __fp; + /* Callee-saved registers. */ + long int __regs[9]; + +#ifndef __loongarch_soft_float + /* Callee-saved floating point registers. */ + double __fpregs[8]; +#endif + +} __jmp_buf[1]; + +#endif /* _LOONGARCH_BITS_SETJMP_H */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/shmlba.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/shmlba.h new file mode 100644 index 0000000000..166f19c016 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/shmlba.h @@ -0,0 +1,24 @@ +/* Define SHMLBA. LoongArch version. + Copyright (C) 2023-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_SHM_H +# error "Never use directly; include instead." +#endif + +/* Segment low boundary address multiple. */ +#define SHMLBA 0x10000 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/sigstack.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/sigstack.h new file mode 100644 index 0000000000..af2933a8ce --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/sigstack.h @@ -0,0 +1,32 @@ +/* sigstack, sigaltstack definitions. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _BITS_SIGSTACK_H +#define _BITS_SIGSTACK_H 1 + +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H +# error "Never include this file directly. Use instead" +#endif + +/* Minimum stack size for a signal handler. */ +#define MINSIGSTKSZ 4096 + +/* System default stack size. */ +#define SIGSTKSZ 16384 + +#endif /* bits/sigstack.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/struct_stat.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/struct_stat.h new file mode 100644 index 0000000000..c8e2d78b57 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/struct_stat.h @@ -0,0 +1,127 @@ +/* Definition for struct stat. + Copyright (C) 2020-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#if !defined _SYS_STAT_H && !defined _FCNTL_H +# error "Never include directly; use instead." +#endif + +#ifndef _BITS_STRUCT_STAT_H +#define _BITS_STRUCT_STAT_H 1 + +#include +#include + +#if defined __USE_FILE_OFFSET64 +# define __field64(type, type64, name) type64 name +#elif __WORDSIZE == 64 || defined __INO_T_MATCHES_INO64_T +# if defined __INO_T_MATCHES_INO64_T && !defined __OFF_T_MATCHES_OFF64_T +# error "ino_t and off_t must both be the same type" +# endif +# define __field64(type, type64, name) type name +#elif __BYTE_ORDER == __LITTLE_ENDIAN +# define __field64(type, type64, name) \ + type name __attribute__((__aligned__ (__alignof__ (type64)))); int __##name##_pad +#else +# define __field64(type, type64, name) \ + int __##name##_pad __attribute__((__aligned__ (__alignof__ (type64)))); type name +#endif + +struct stat + { + __dev_t st_dev; /* Device. */ + __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __dev_t __pad1; + __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ +#ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +# define st_atime st_atim.tv_sec /* Backward compatibility. */ +# define st_mtime st_mtim.tv_sec +# define st_ctime st_ctim.tv_sec +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + int __glibc_reserved[2]; + }; + +#undef __field64 + +#ifdef __USE_LARGEFILE64 +struct stat64 + { + __dev_t st_dev; /* Device. */ + __ino64_t st_ino; /* File serial number. */ + __mode_t st_mode; /* File mode. */ + __nlink_t st_nlink; /* Link count. */ + __uid_t st_uid; /* User ID of the file's owner. */ + __gid_t st_gid; /* Group ID of the file's group.*/ + __dev_t st_rdev; /* Device number, if device. */ + __dev_t __pad1; + __off64_t st_size; /* Size of file, in bytes. */ + __blksize_t st_blksize; /* Optimal block size for I/O. */ + int __pad2; + __blkcnt64_t st_blocks; /* Nr. 512-byte blocks allocated. */ +#ifdef __USE_XOPEN2K8 + /* Nanosecond resolution timestamps are stored in a format + equivalent to 'struct timespec'. This is the type used + whenever possible but the Unix namespace rules do not allow the + identifier 'timespec' to appear in the header. + Therefore we have to handle the use of this header in strictly + standard-compliant sources special. */ + struct timespec st_atim; /* Time of last access. */ + struct timespec st_mtim; /* Time of last modification. */ + struct timespec st_ctim; /* Time of last status change. */ +#else + __time_t st_atime; /* Time of last access. */ + unsigned long int st_atimensec; /* Nscecs of last access. */ + __time_t st_mtime; /* Time of last modification. */ + unsigned long int st_mtimensec; /* Nsecs of last modification. */ + __time_t st_ctime; /* Time of last status change. */ + unsigned long int st_ctimensec; /* Nsecs of last status change. */ +#endif + int __glibc_reserved[2]; + }; +#endif + +/* Tell code we have these members. */ +#define _STATBUF_ST_BLKSIZE +#define _STATBUF_ST_RDEV +/* Nanosecond resolution time values are supported. */ +#define _STATBUF_ST_NSEC + +#endif /* _BITS_STRUCT_STAT_H */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/timesize.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/timesize.h new file mode 100644 index 0000000000..17f828ecfe --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/timesize.h @@ -0,0 +1,20 @@ +/* Bit size of the time_t type at glibc build time, general case. + Copyright (C) 2018-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Size in bits of the 'time_t' type of the default ABI. */ +#define __TIMESIZE 64 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/bits/wordsize.h b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/wordsize.h new file mode 100644 index 0000000000..98996fdf03 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/bits/wordsize.h @@ -0,0 +1,19 @@ +/* Copyright (C) 1999-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define __WORDSIZE 64 +#define __WORDSIZE_TIME64_COMPAT32 0 \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/fpu_control.h b/zig/lib/libc/include/loongarch64-linux-gnusf/fpu_control.h new file mode 100644 index 0000000000..d52d6d51cc --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/fpu_control.h @@ -0,0 +1,119 @@ +/* FPU control word bits. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _FPU_CONTROL_H +#define _FPU_CONTROL_H + +/* LoongArch FPU floating point control register bits. + * + * 31-29 -> reserved (read as 0, can not changed by software) + * 28 -> cause bit for invalid exception + * 27 -> cause bit for division by zero exception + * 26 -> cause bit for overflow exception + * 25 -> cause bit for underflow exception + * 24 -> cause bit for inexact exception + * 23-21 -> reserved (read as 0, can not changed by software) + * 20 -> flag invalid exception + * 19 -> flag division by zero exception + * 18 -> flag overflow exception + * 17 -> flag underflow exception + * 16 -> flag inexact exception + * 9-8 -> rounding control + * 7-5 -> reserved (read as 0, can not changed by software) + * 4 -> enable exception for invalid exception + * 3 -> enable exception for division by zero exception + * 2 -> enable exception for overflow exception + * 1 -> enable exception for underflow exception + * 0 -> enable exception for inexact exception + * + * + * Rounding Control: + * 00 - rounding ties to even (RNE) + * 01 - rounding toward zero (RZ) + * 10 - rounding (up) toward plus infinity (RP) + * 11 - rounding (down) toward minus infinity (RM) + */ + +#include + +#ifdef __loongarch_soft_float + +#define _FPU_RESERVED 0xffffffff +#define _FPU_DEFAULT 0x00000000 +typedef unsigned int fpu_control_t; +#define _FPU_GETCW(cw) (cw) = 0 +#define _FPU_SETCW(cw) (void) (cw) +extern fpu_control_t __fpu_control; + +#else /* __loongarch_soft_float */ + +/* Masks for interrupts. */ +#define _FPU_MASK_V 0x10 /* Invalid operation */ +#define _FPU_MASK_Z 0x08 /* Division by zero */ +#define _FPU_MASK_O 0x04 /* Overflow */ +#define _FPU_MASK_U 0x02 /* Underflow */ +#define _FPU_MASK_I 0x01 /* Inexact operation */ + +/* Flush denormalized numbers to zero. */ +#define _FPU_FLUSH_TZ 0x1000000 + +/* Rounding control. */ +#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */ +#define _FPU_RC_ZERO 0x100 +#define _FPU_RC_UP 0x200 +#define _FPU_RC_DOWN 0x300 +/* Mask for rounding control. */ +#define _FPU_RC_MASK 0x300 + +#define _FPU_RESERVED 0x0 + +#define _FPU_DEFAULT 0x0 +#define _FPU_IEEE 0x1F + +/* Type of the control word. */ +typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__))); + +/* Macros for accessing the hardware control word. */ +extern fpu_control_t __loongarch_fpu_getcw (void) __THROW; +extern void __loongarch_fpu_setcw (fpu_control_t) __THROW; +#define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw)) +#define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $fcsr0,%0" : : "r"(cw)) + +/* Default control word set at startup. */ +extern fpu_control_t __fpu_control; + +# define _FCLASS_SNAN (1 << 0) +# define _FCLASS_QNAN (1 << 1) +# define _FCLASS_MINF (1 << 2) +# define _FCLASS_MNORM (1 << 3) +# define _FCLASS_MSUBNORM (1 << 4) +# define _FCLASS_MZERO (1 << 5) +# define _FCLASS_PINF (1 << 6) +# define _FCLASS_PNORM (1 << 7) +# define _FCLASS_PSUBNORM (1 << 8) +# define _FCLASS_PZERO (1 << 9) + +# define _FCLASS_ZERO (_FCLASS_MZERO | _FCLASS_PZERO) +# define _FCLASS_SUBNORM (_FCLASS_MSUBNORM | _FCLASS_PSUBNORM) +# define _FCLASS_NORM (_FCLASS_MNORM | _FCLASS_PNORM) +# define _FCLASS_INF (_FCLASS_MINF | _FCLASS_PINF) +# define _FCLASS_NAN (_FCLASS_SNAN | _FCLASS_QNAN) + +#endif /* __loongarch_soft_float */ + +#endif /* fpu_control.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names-lp64s.h b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names-lp64s.h new file mode 100644 index 0000000000..7c8b796194 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names-lp64s.h @@ -0,0 +1,27 @@ +/* This file is automatically generated. */ +#ifndef __GNU_LIB_NAMES_H +# error "Never use directly; include instead." +#endif + +#define LD_LINUX_LOONGARCH_LP64S_SO "ld-linux-loongarch-lp64s.so.1" +#define LD_SO "ld-linux-loongarch-lp64s.so.1" +#define LIBANL_SO "libanl.so.1" +#define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" +#define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" +#define LIBC_SO "libc.so.6" +#define LIBDL_SO "libdl.so.2" +#define LIBGCC_S_SO "libgcc_s.so.1" +#define LIBMVEC_SO "libmvec.so.1" +#define LIBM_SO "libm.so.6" +#define LIBNSL_SO "libnsl.so.1" +#define LIBNSS_COMPAT_SO "libnss_compat.so.2" +#define LIBNSS_DB_SO "libnss_db.so.2" +#define LIBNSS_DNS_SO "libnss_dns.so.2" +#define LIBNSS_FILES_SO "libnss_files.so.2" +#define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" +#define LIBNSS_LDAP_SO "libnss_ldap.so.2" +#define LIBPTHREAD_SO "libpthread.so.0" +#define LIBRESOLV_SO "libresolv.so.2" +#define LIBRT_SO "librt.so.1" +#define LIBTHREAD_DB_SO "libthread_db.so.1" +#define LIBUTIL_SO "libutil.so.1" \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names.h b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names.h new file mode 100644 index 0000000000..c3eba41e09 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/lib-names.h @@ -0,0 +1,16 @@ +/* This file is automatically generated. + It defines macros to allow user program to find the shared + library files which come as part of GNU libc. */ +#ifndef __GNU_LIB_NAMES_H +#define __GNU_LIB_NAMES_H 1 + +#include + +#if __WORDSIZE == 64 && defined __loongarch_soft_float +# include +#endif +#if __WORDSIZE == 64 && defined __loongarch_double_float +# include +#endif + +#endif /* gnu/lib-names.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs-lp64s.h b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs-lp64s.h new file mode 100644 index 0000000000..6ce02418e6 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs-lp64s.h @@ -0,0 +1,38 @@ +/* This file is automatically generated. + It defines a symbol `__stub_FUNCTION' for each function + in the C library which is a stub, meaning it will fail + every time called, usually setting errno to ENOSYS. */ + +#ifdef _LIBC + #error Applications may not define the macro _LIBC +#endif + +#define __stub___compat_bdflush +#define __stub___compat_create_module +#define __stub___compat_get_kernel_syms +#define __stub___compat_query_module +#define __stub___compat_uselib +#define __stub_chflags +#define __stub_fchflags +#define __stub_feclearexcept +#define __stub_fedisableexcept +#define __stub_feenableexcept +#define __stub_fegetenv +#define __stub_fegetexcept +#define __stub_fegetexceptflag +#define __stub_fegetmode +#define __stub_fegetround +#define __stub_feholdexcept +#define __stub_feraiseexcept +#define __stub_fesetenv +#define __stub_fesetexcept +#define __stub_fesetexceptflag +#define __stub_fesetmode +#define __stub_fesetround +#define __stub_fetestexcept +#define __stub_feupdateenv +#define __stub_gtty +#define __stub_revoke +#define __stub_setlogin +#define __stub_sigreturn +#define __stub_stty \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs.h b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs.h new file mode 100644 index 0000000000..ea3f10c421 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/gnu/stubs.h @@ -0,0 +1,12 @@ +/* This file is automatically generated. + This file selects the right generated file of `__stub_FUNCTION' macros + based on the architecture being compiled for. */ + +#include + +#if __WORDSIZE == 64 && defined __loongarch_soft_float +# include +#endif +#if __WORDSIZE == 64 && defined __loongarch_double_float +# include +#endif \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/ieee754.h b/zig/lib/libc/include/loongarch64-linux-gnusf/ieee754.h new file mode 100644 index 0000000000..b1e2ec7dc6 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/ieee754.h @@ -0,0 +1,170 @@ +/* Copyright (C) 1992-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _IEEE754_H +#define _IEEE754_H 1 + +#include + +#include + +__BEGIN_DECLS + +union ieee754_float + { + float f; + + /* This is the IEEE 754 single-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int mantissa:23; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:23; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:8; + unsigned int quiet_nan:1; + unsigned int mantissa:22; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned int mantissa:22; + unsigned int quiet_nan:1; + unsigned int exponent:8; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee_nan; + }; + +#define IEEE754_FLOAT_BIAS 0x7f /* Added to exponent. */ + + +union ieee754_double + { + double d; + + /* This is the IEEE 754 double-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:20; + unsigned int mantissa1:32; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:20; + unsigned int exponent:11; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:11; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:19; + unsigned int mantissa1:32; +#else + /* Together these comprise the mantissa. */ + unsigned int mantissa1:32; + unsigned int mantissa0:19; + unsigned int quiet_nan:1; + unsigned int exponent:11; + unsigned int negative:1; +#endif + } ieee_nan; + }; + +#define IEEE754_DOUBLE_BIAS 0x3ff /* Added to exponent. */ + + +union ieee854_long_double + { + long double d; + + /* This is the IEEE 854 quad-precision format. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:16; + unsigned int mantissa1:32; + unsigned int mantissa2:32; + unsigned int mantissa3:32; +#endif /* Big endian. */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* Together these comprise the mantissa. */ + unsigned int mantissa3:32; + unsigned int mantissa2:32; + unsigned int mantissa1:32; + unsigned int mantissa0:16; + unsigned int exponent:15; + unsigned int negative:1; +#endif /* Little endian. */ + } ieee; + + /* This format makes it easier to see if a NaN is a signalling NaN. */ + struct + { +#if __BYTE_ORDER == __BIG_ENDIAN + unsigned int negative:1; + unsigned int exponent:15; + unsigned int quiet_nan:1; + /* Together these comprise the mantissa. */ + unsigned int mantissa0:15; + unsigned int mantissa1:32; + unsigned int mantissa2:32; + unsigned int mantissa3:32; +#else + /* Together these comprise the mantissa. */ + unsigned int mantissa3:32; + unsigned int mantissa2:32; + unsigned int mantissa1:32; + unsigned int mantissa0:15; + unsigned int quiet_nan:1; + unsigned int exponent:15; + unsigned int negative:1; +#endif + } ieee_nan; + }; + +#define IEEE854_LONG_DOUBLE_BIAS 0x3fff /* Added to exponent. */ + +__END_DECLS + +#endif /* ieee754.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/sys/asm.h b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/asm.h new file mode 100644 index 0000000000..282831f10d --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/asm.h @@ -0,0 +1,78 @@ +/* Miscellaneous macros. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +#ifndef _SYS_ASM_H +#define _SYS_ASM_H + +#include +#include + +/* Macros to handle different pointer/register sizes for 32/64-bit code. */ +#define SZREG 8 +#define SZFREG 8 +#define SZVREG 16 +#define SZXREG 32 +#define REG_L ld.d +#define REG_S st.d +#define SRLI srli.d +#define SLLI slli.d +#define ADDI addi.d +#define ADD add.d +#define SUB sub.d +#define BSTRINS bstrins.d +#define LI li.d +#define FREG_L fld.d +#define FREG_S fst.d + +/* Declare leaf routine. + The usage of macro LEAF/ENTRY is as follows: + 1. LEAF(fcn) -- the align value of fcn is .align 3 (default value) + 2. LEAF(fcn, 6) -- the align value of fcn is .align 6 +*/ +#define LEAF_IMPL(symbol, aln, ...) \ + .text; \ + .globl symbol; \ + .align aln; \ + .type symbol, @function; \ +symbol: \ + cfi_startproc; + + +#define LEAF(...) LEAF_IMPL(__VA_ARGS__, 3) +#define ENTRY(...) LEAF(__VA_ARGS__) + +#define LEAF_NO_ALIGN(symbol) \ + .text; \ + .globl symbol; \ + .type symbol, @function; \ +symbol: \ + cfi_startproc; + +#define ENTRY_NO_ALIGN(symbol) LEAF_NO_ALIGN(symbol) + + +/* Mark end of function. */ +#undef END +#define END(function) \ + cfi_endproc; \ + .size function, .- function; + +/* Stack alignment. */ +#define ALMASK ~15 + +#endif /* sys/asm.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/sys/ucontext.h b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/ucontext.h new file mode 100644 index 0000000000..5db0d1e09e --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/ucontext.h @@ -0,0 +1,64 @@ +/* struct ucontext definition. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library. If not, see + . */ + +/* Don't rely on this, the interface is currently messed up and may need to + be broken to be fixed. */ +#ifndef _SYS_UCONTEXT_H +#define _SYS_UCONTEXT_H 1 + +#include + +#include +#include + +#ifdef __USE_MISC +#define LARCH_NGREG 32 + +#define LARCH_REG_RA 1 +#define LARCH_REG_SP 3 +#define LARCH_REG_S0 23 +#define LARCH_REG_S1 24 +#define LARCH_REG_A0 4 +#define LARCH_REG_S2 25 +#define LARCH_REG_NARGS 8 + +typedef unsigned long int greg_t; +/* Container for all general registers. */ +typedef greg_t gregset_t[32]; +#endif + +typedef struct mcontext_t +{ + unsigned long long __pc; + unsigned long long __gregs[32]; + unsigned int __flags; + unsigned long long __extcontext[0] __attribute__((__aligned__(16))); +} mcontext_t; + +/* Userlevel context. */ +typedef struct ucontext_t +{ + unsigned long int __uc_flags; + struct ucontext_t *uc_link; + stack_t uc_stack; + sigset_t uc_sigmask; + mcontext_t uc_mcontext; +} ucontext_t; + +#endif /* sys/ucontext.h */ \ No newline at end of file diff --git a/zig/lib/libc/include/loongarch64-linux-gnusf/sys/user.h b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/user.h new file mode 100644 index 0000000000..5dff8a5443 --- /dev/null +++ b/zig/lib/libc/include/loongarch64-linux-gnusf/sys/user.h @@ -0,0 +1,42 @@ +/* struct user_regs_struct definition for LoongArch. + Copyright (C) 2022-2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _SYS_USER_H +#define _SYS_USER_H 1 + +#include + +struct user_regs_struct +{ + /* Saved main processor registers. */ + uint64_t regs[32]; + + /* Saved special registers. */ + uint64_t orig_a0; + uint64_t csr_era; + uint64_t csr_badv; + uint64_t reserved[10]; +}; + +struct user_fp_struct { + uint64_t fpr[32]; + uint64_t fcc; + uint32_t fcsr; +}; + +#endif /* _SYS_USER_H */ \ No newline at end of file diff --git a/zig/lib/libc/musl/crt/arm/crti.s b/zig/lib/libc/musl/crt/arm/crti.s index 18dc1e4197..cccda3eaef 100644 --- a/zig/lib/libc/musl/crt/arm/crti.s +++ b/zig/lib/libc/musl/crt/arm/crti.s @@ -3,11 +3,13 @@ .section .init .global _init .type _init,%function +.align 2 _init: push {r0,lr} .section .fini .global _fini .type _fini,%function +.align 2 _fini: push {r0,lr} diff --git a/zig/lib/libc/musl/crt/mips/crtn.s b/zig/lib/libc/musl/crt/mips/crtn.s index 506a04b78c..5146d83a0e 100644 --- a/zig/lib/libc/musl/crt/mips/crtn.s +++ b/zig/lib/libc/musl/crt/mips/crtn.s @@ -3,11 +3,13 @@ .section .init lw $gp,24($sp) lw $ra,28($sp) - j $ra + # zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 + jr $ra addu $sp,$sp,32 .section .fini lw $gp,24($sp) lw $ra,28($sp) - j $ra + # zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 + jr $ra addu $sp,$sp,32 diff --git a/zig/lib/libc/musl/crt/mips64/crtn.s b/zig/lib/libc/musl/crt/mips64/crtn.s index f3930b2406..dc4dbb03ad 100644 --- a/zig/lib/libc/musl/crt/mips64/crtn.s +++ b/zig/lib/libc/musl/crt/mips64/crtn.s @@ -3,11 +3,13 @@ .section .init ld $gp,16($sp) ld $ra,24($sp) - j $ra + # zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 + jr $ra daddu $sp,$sp,32 .section .fini ld $gp,16($sp) ld $ra,24($sp) - j $ra + # zig patch: j -> jr for https://github.com/ziglang/zig/issues/21315 + jr $ra daddu $sp,$sp,32 diff --git a/zig/lib/libunwind/src/gcc_personality_v0.c b/zig/lib/libunwind/src/gcc_personality_v0.c index c946497d75..1d9c7f4d17 100644 --- a/zig/lib/libunwind/src/gcc_personality_v0.c +++ b/zig/lib/libunwind/src/gcc_personality_v0.c @@ -20,6 +20,15 @@ #include +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) +#include +#include + +EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, + PDISPATCHER_CONTEXT, + _Unwind_Personality_Fn); +#endif + // Pointer encodings documented at: // http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html @@ -43,9 +52,9 @@ #define DW_EH_PE_indirect 0x80 // gcc extension // read a uleb128 encoded value and advance pointer -static uintptr_t readULEB128(const uint8_t **data) { - uintptr_t result = 0; - uintptr_t shift = 0; +static size_t readULEB128(const uint8_t **data) { + size_t result = 0; + size_t shift = 0; unsigned char byte; const uint8_t *p = *data; do { @@ -133,7 +142,7 @@ static uintptr_t readEncodedPointer(const uint8_t **data, uint8_t encoding) { } #if defined(__arm__) && !defined(__USING_SJLJ_EXCEPTIONS__) && \ - !defined(__ARM_DWARF_EH__) + !defined(__ARM_DWARF_EH__) && !defined(__SEH__) #define USING_ARM_EHABI 1 _Unwind_Reason_Code __gnu_unwind_frame(struct _Unwind_Exception *, struct _Unwind_Context *); @@ -168,6 +177,10 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_sj0( COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( _Unwind_State state, struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) +#elif defined(__SEH__) +static _Unwind_Reason_Code __gcc_personality_imp( + int version, _Unwind_Action actions, uint64_t exceptionClass, + struct _Unwind_Exception *exceptionObject, struct _Unwind_Context *context) #else COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( int version, _Unwind_Action actions, uint64_t exceptionClass, @@ -205,14 +218,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( } // Walk call-site table looking for range that includes current PC. uint8_t callSiteEncoding = *lsda++; - uint32_t callSiteTableLength = readULEB128(&lsda); + size_t callSiteTableLength = readULEB128(&lsda); const uint8_t *callSiteTableStart = lsda; const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; const uint8_t *p = callSiteTableStart; while (p < callSiteTableEnd) { uintptr_t start = readEncodedPointer(&p, callSiteEncoding); - uintptr_t length = readEncodedPointer(&p, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&p, callSiteEncoding); + size_t length = readEncodedPointer(&p, callSiteEncoding); + size_t landingPad = readEncodedPointer(&p, callSiteEncoding); readULEB128(&p); // action value not used for C code if (landingPad == 0) continue; // no landing pad for this entry @@ -232,3 +245,12 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( // No landing pad found, continue unwinding. return continueUnwind(exceptionObject, context); } + +#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) +COMPILER_RT_ABI EXCEPTION_DISPOSITION +__gcc_personality_seh0(PEXCEPTION_RECORD ms_exc, void *this_frame, + PCONTEXT ms_orig_context, PDISPATCHER_CONTEXT ms_disp) { + return _GCC_specific_handler(ms_exc, this_frame, ms_orig_context, ms_disp, + __gcc_personality_imp); +} +#endif diff --git a/zig/lib/std/Build.zig b/zig/lib/std/Build.zig index dbd96441b1..988a72c129 100644 --- a/zig/lib/std/Build.zig +++ b/zig/lib/std/Build.zig @@ -90,9 +90,6 @@ modules: std.StringArrayHashMap(*Module), named_writefiles: std.StringArrayHashMap(*Step.WriteFile), named_lazy_paths: std.StringArrayHashMap(LazyPath), -/// A map from build root dirs to the corresponding `*Dependency`. This is shared with all child -/// `Build`s. -initialized_deps: *InitializedDepMap, /// The hash of this instance's package. `""` means that this is the root package. pkg_hash: []const u8, /// A mapping from dependency names to package hashes. @@ -125,6 +122,7 @@ pub const Graph = struct { host: ResolvedTarget, incremental: ?bool = null, random_seed: u32 = 0, + dependency_cache: InitializedDepMap = .empty, }; const AvailableDeps = []const struct { []const u8, []const u8 }; @@ -144,7 +142,7 @@ const SystemLibraryMode = enum { declared_enabled, }; -const InitializedDepMap = std.HashMap(InitializedDepKey, *Dependency, InitializedDepContext, std.hash_map.default_max_load_percentage); +const InitializedDepMap = std.HashMapUnmanaged(InitializedDepKey, *Dependency, InitializedDepContext, std.hash_map.default_max_load_percentage); const InitializedDepKey = struct { build_root_string: []const u8, user_input_options: UserInputOptionsMap, @@ -219,6 +217,8 @@ const UserValue = union(enum) { scalar: []const u8, list: ArrayList([]const u8), map: StringHashMap(*const UserValue), + lazy_path: LazyPath, + lazy_path_list: ArrayList(LazyPath), }; const TypeId = enum { @@ -230,6 +230,8 @@ const TypeId = enum { string, list, build_id, + lazy_path, + lazy_path_list, }; const TopLevelStep = struct { @@ -252,8 +254,6 @@ pub fn create( available_deps: AvailableDeps, ) !*Build { const arena = graph.arena; - const initialized_deps = try arena.create(InitializedDepMap); - initialized_deps.* = InitializedDepMap.initContext(arena, .{ .allocator = arena }); const b = try arena.create(Build); b.* = .{ @@ -304,7 +304,6 @@ pub fn create( .modules = .init(arena), .named_writefiles = .init(arena), .named_lazy_paths = .init(arena), - .initialized_deps = initialized_deps, .pkg_hash = "", .available_deps = available_deps, .release_mode = .off, @@ -398,7 +397,6 @@ fn createChildOnly( .modules = .init(allocator), .named_writefiles = .init(allocator), .named_lazy_paths = .init(allocator), - .initialized_deps = parent.initialized_deps, .pkg_hash = pkg_hash, .available_deps = pkg_deps, .release_mode = parent.release_mode, @@ -439,6 +437,22 @@ fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOption .used = false, }) catch @panic("OOM"); }, + LazyPath => { + user_input_options.put(field.name, .{ + .name = field.name, + .value = .{ .lazy_path = v.dupeInner(allocator) }, + .used = false, + }) catch @panic("OOM"); + }, + []const LazyPath => { + var list = ArrayList(LazyPath).initCapacity(allocator, v.len) catch @panic("OOM"); + for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(allocator)); + user_input_options.put(field.name, .{ + .name = field.name, + .value = .{ .lazy_path_list = list }, + .used = false, + }) catch @panic("OOM"); + }, []const u8 => { user_input_options.put(field.name, .{ .name = field.name, @@ -498,6 +512,8 @@ const OrderedUserValue = union(enum) { scalar: []const u8, list: ArrayList([]const u8), map: ArrayList(Pair), + lazy_path: LazyPath, + lazy_path_list: ArrayList(LazyPath), const Pair = struct { name: []const u8, @@ -508,6 +524,7 @@ const OrderedUserValue = union(enum) { }; fn hash(val: OrderedUserValue, hasher: *std.hash.Wyhash) void { + hasher.update(&std.mem.toBytes(std.meta.activeTag(val))); switch (val) { .flag => {}, .scalar => |scalar| hasher.update(scalar), @@ -518,6 +535,31 @@ const OrderedUserValue = union(enum) { hasher.update(map_entry.name); map_entry.value.hash(hasher); }, + .lazy_path => |lp| hashLazyPath(lp, hasher), + .lazy_path_list => |lp_list| for (lp_list.items) |lp| { + hashLazyPath(lp, hasher); + }, + } + } + + fn hashLazyPath(lp: LazyPath, hasher: *std.hash.Wyhash) void { + switch (lp) { + .src_path => |sp| { + hasher.update(sp.owner.pkg_hash); + hasher.update(sp.sub_path); + }, + .generated => |gen| { + hasher.update(gen.file.step.owner.pkg_hash); + hasher.update(std.mem.asBytes(&gen.up)); + hasher.update(gen.sub_path); + }, + .cwd_relative => |rel_path| { + hasher.update(rel_path); + }, + .dependency => |dep| { + hasher.update(dep.dependency.builder.pkg_hash); + hasher.update(dep.sub_path); + }, } } @@ -541,6 +583,8 @@ const OrderedUserValue = union(enum) { .scalar => |scalar| .{ .scalar = scalar }, .list => |list| .{ .list = list }, .map => |map| .{ .map = OrderedUserValue.mapFromUnordered(allocator, map) }, + .lazy_path => |lp| .{ .lazy_path = lp }, + .lazy_path_list => |list| .{ .lazy_path_list = list }, }; } }; @@ -1029,7 +1073,11 @@ pub fn addConfigHeader( /// Allocator.dupe without the need to handle out of memory. pub fn dupe(b: *Build, bytes: []const u8) []u8 { - return b.allocator.dupe(u8, bytes) catch @panic("OOM"); + return dupeInner(b.allocator, bytes); +} + +pub fn dupeInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 { + return allocator.dupe(u8, bytes) catch @panic("OOM"); } /// Duplicates an array of strings without the need to handle out of memory. @@ -1041,7 +1089,11 @@ pub fn dupeStrings(b: *Build, strings: []const []const u8) [][]u8 { /// Duplicates a path and converts all slashes to the OS's canonical path separator. pub fn dupePath(b: *Build, bytes: []const u8) []u8 { - const the_copy = b.dupe(bytes); + return dupePathInner(b.allocator, bytes); +} + +fn dupePathInner(allocator: std.mem.Allocator, bytes: []const u8) []u8 { + const the_copy = dupeInner(allocator, bytes); for (the_copy) |*byte| { switch (byte.*) { '/', '\\' => byte.* = fs.path.sep, @@ -1155,7 +1207,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw return null; } }, - .list, .map => { + .list, .map, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be a boolean, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1164,7 +1216,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, }, .int => switch (option_ptr.value) { - .flag, .list, .map => { + .flag, .list, .map, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be an integer, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1188,7 +1240,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, }, .float => switch (option_ptr.value) { - .flag, .map, .list => { + .flag, .map, .list, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be a float, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1205,7 +1257,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, }, .@"enum" => switch (option_ptr.value) { - .flag, .map, .list => { + .flag, .map, .list, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be an enum, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1223,7 +1275,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, }, .string => switch (option_ptr.value) { - .flag, .list, .map => { + .flag, .list, .map, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be a string, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1233,7 +1285,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw .scalar => |s| return s, }, .build_id => switch (option_ptr.value) { - .flag, .map, .list => { + .flag, .map, .list, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be an enum, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1251,7 +1303,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, }, .list => switch (option_ptr.value) { - .flag, .map => { + .flag, .map, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be a list, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1264,7 +1316,7 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw .list => |lst| return lst.items, }, .enum_list => switch (option_ptr.value) { - .flag, .map => { + .flag, .map, .lazy_path, .lazy_path_list => { log.err("Expected -D{s} to be a list, but received a {s}.", .{ name, @tagName(option_ptr.value), }); @@ -1282,19 +1334,48 @@ pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw }, .list => |lst| { const Child = @typeInfo(T).pointer.child; - var new_list = b.allocator.alloc(Child, lst.items.len) catch @panic("OOM"); - for (lst.items, 0..) |str, i| { - const value = std.meta.stringToEnum(Child, str) orelse { + const new_list = b.allocator.alloc(Child, lst.items.len) catch @panic("OOM"); + for (new_list, lst.items) |*new_item, str| { + new_item.* = std.meta.stringToEnum(Child, str) orelse { log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(Child) }); b.markInvalidUserInput(); b.allocator.free(new_list); return null; }; - new_list[i] = value; } return new_list; }, }, + .lazy_path => switch (option_ptr.value) { + .scalar => |s| return .{ .cwd_relative = s }, + .lazy_path => |lp| return lp, + .flag, .map, .list, .lazy_path_list => { + log.err("Expected -D{s} to be a path, but received a {s}.", .{ + name, @tagName(option_ptr.value), + }); + b.markInvalidUserInput(); + return null; + }, + }, + .lazy_path_list => switch (option_ptr.value) { + .scalar => |s| return b.allocator.dupe(LazyPath, &[_]LazyPath{.{ .cwd_relative = s }}) catch @panic("OOM"), + .lazy_path => |lp| return b.allocator.dupe(LazyPath, &[_]LazyPath{lp}) catch @panic("OOM"), + .list => |lst| { + const new_list = b.allocator.alloc(LazyPath, lst.items.len) catch @panic("OOM"); + for (new_list, lst.items) |*new_item, str| { + new_item.* = .{ .cwd_relative = str }; + } + return new_list; + }, + .lazy_path_list => |lp_list| return lp_list.items, + .flag, .map => { + log.err("Expected -D{s} to be a path, but received a {s}.", .{ + name, @tagName(option_ptr.value), + }); + b.markInvalidUserInput(); + return null; + }, + }, } } @@ -1514,6 +1595,10 @@ pub fn addUserInputOption(b: *Build, name_raw: []const u8, value_raw: []const u8 log.warn("TODO maps as command line arguments is not implemented yet.", .{}); return true; }, + .lazy_path, .lazy_path_list => { + log.warn("the lazy path value type isn't added from the CLI, but somehow '{s}' is a .{}", .{ name, std.zig.fmtId(@tagName(gop.value_ptr.value)) }); + return true; + }, } return false; } @@ -1536,10 +1621,15 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool { log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, s }); return true; }, - .list, .map => { + .list, .map, .lazy_path_list => { log.err("Flag '-D{s}' conflicts with multiple options of the same name.", .{name}); return true; }, + .lazy_path => |lp| { + log.err("Flag '-D{s}' conflicts with option '-D{s}={s}'.", .{ name, name, lp.getDisplayName() }); + return true; + }, + .flag => {}, } return false; @@ -1548,6 +1638,7 @@ pub fn addUserInputFlag(b: *Build, name_raw: []const u8) !bool { fn typeToEnum(comptime T: type) TypeId { return switch (T) { std.zig.BuildId => .build_id, + LazyPath => .lazy_path, else => return switch (@typeInfo(T)) { .int => .int, .float => .float, @@ -1556,6 +1647,7 @@ fn typeToEnum(comptime T: type) TypeId { .pointer => |pointer| switch (pointer.child) { u8 => .string, []const u8 => .list, + LazyPath => .lazy_path_list, else => switch (@typeInfo(pointer.child)) { .@"enum" => .enum_list, else => @compileError("Unsupported type: " ++ @typeName(T)), @@ -2071,22 +2163,17 @@ pub fn dependencyFromBuildZig( } fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { + if (std.meta.activeTag(lhs) != rhs) return false; switch (lhs) { .flag => {}, .scalar => |lhs_scalar| { - const rhs_scalar = switch (rhs) { - .scalar => |scalar| scalar, - else => return false, - }; + const rhs_scalar = rhs.scalar; if (!std.mem.eql(u8, lhs_scalar, rhs_scalar)) return false; }, .list => |lhs_list| { - const rhs_list = switch (rhs) { - .list => |list| list, - else => return false, - }; + const rhs_list = rhs.list; if (lhs_list.items.len != rhs_list.items.len) return false; @@ -2097,10 +2184,7 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { } }, .map => |lhs_map| { - const rhs_map = switch (rhs) { - .map => |map| map, - else => return false, - }; + const rhs_map = rhs.map; if (lhs_map.count() != rhs_map.count()) return false; @@ -2112,11 +2196,54 @@ fn userValuesAreSame(lhs: UserValue, rhs: UserValue) bool { return false; } }, + .lazy_path => |lhs_lp| { + const rhs_lp = rhs.lazy_path; + return userLazyPathsAreTheSame(lhs_lp, rhs_lp); + }, + .lazy_path_list => |lhs_lp_list| { + const rhs_lp_list = rhs.lazy_path_list; + if (lhs_lp_list.items.len != rhs_lp_list.items.len) return false; + for (lhs_lp_list.items, rhs_lp_list.items) |lhs_lp, rhs_lp| { + if (!userLazyPathsAreTheSame(lhs_lp, rhs_lp)) return false; + } + return true; + }, } return true; } +fn userLazyPathsAreTheSame(lhs_lp: LazyPath, rhs_lp: LazyPath) bool { + if (std.meta.activeTag(lhs_lp) != rhs_lp) return false; + switch (lhs_lp) { + .src_path => |lhs_sp| { + const rhs_sp = rhs_lp.src_path; + + if (lhs_sp.owner != rhs_sp.owner) return false; + if (std.mem.eql(u8, lhs_sp.sub_path, rhs_sp.sub_path)) return false; + }, + .generated => |lhs_gen| { + const rhs_gen = rhs_lp.generated; + + if (lhs_gen.file != rhs_gen.file) return false; + if (lhs_gen.up != rhs_gen.up) return false; + if (std.mem.eql(u8, lhs_gen.sub_path, rhs_gen.sub_path)) return false; + }, + .cwd_relative => |lhs_rel_path| { + const rhs_rel_path = rhs_lp.cwd_relative; + + if (!std.mem.eql(u8, lhs_rel_path, rhs_rel_path)) return false; + }, + .dependency => |lhs_dep| { + const rhs_dep = rhs_lp.dependency; + + if (lhs_dep.dependency != rhs_dep.dependency) return false; + if (!std.mem.eql(u8, lhs_dep.sub_path, rhs_dep.sub_path)) return false; + }, + } + return true; +} + fn dependencyInner( b: *Build, name: []const u8, @@ -2127,10 +2254,10 @@ fn dependencyInner( args: anytype, ) *Dependency { const user_input_options = userInputOptionsFromArgs(b.allocator, args); - if (b.initialized_deps.get(.{ + if (b.graph.dependency_cache.getContext(.{ .build_root_string = build_root_string, .user_input_options = user_input_options, - })) |dep| + }, .{ .allocator = b.graph.arena })) |dep| return dep; const build_root: std.Build.Cache.Directory = .{ @@ -2155,10 +2282,10 @@ fn dependencyInner( const dep = b.allocator.create(Dependency) catch @panic("OOM"); dep.* = .{ .builder = sub_builder }; - b.initialized_deps.put(.{ + b.graph.dependency_cache.putContext(b.graph.arena, .{ .build_root_string = build_root_string, .user_input_options = user_input_options, - }, dep) catch @panic("OOM"); + }, dep, .{ .allocator = b.graph.arena }) catch @panic("OOM"); return dep; } @@ -2441,16 +2568,20 @@ pub const LazyPath = union(enum) { /// The `b` parameter is only used for its allocator. All *Build instances /// share the same allocator. pub fn dupe(lazy_path: LazyPath, b: *Build) LazyPath { + return lazy_path.dupeInner(b.allocator); + } + + fn dupeInner(lazy_path: LazyPath, allocator: std.mem.Allocator) LazyPath { return switch (lazy_path) { .src_path => |sp| .{ .src_path = .{ .owner = sp.owner, .sub_path = sp.owner.dupePath(sp.sub_path), } }, - .cwd_relative => |p| .{ .cwd_relative = b.dupePath(p) }, + .cwd_relative => |p| .{ .cwd_relative = dupePathInner(allocator, p) }, .generated => |gen| .{ .generated = .{ .file = gen.file, .up = gen.up, - .sub_path = b.dupePath(gen.sub_path), + .sub_path = dupePathInner(allocator, gen.sub_path), } }, .dependency => |dep| .{ .dependency = dep }, }; diff --git a/zig/lib/std/Build/Cache.zig b/zig/lib/std/Build/Cache.zig index 93908807eb..53f1dcff29 100644 --- a/zig/lib/std/Build/Cache.zig +++ b/zig/lib/std/Build/Cache.zig @@ -398,12 +398,19 @@ pub const Manifest = struct { return gop.index; } + /// Deprecated, use `addOptionalFilePath`. pub fn addOptionalFile(self: *Manifest, optional_file_path: ?[]const u8) !void { self.hash.add(optional_file_path != null); const file_path = optional_file_path orelse return; _ = try self.addFile(file_path, null); } + pub fn addOptionalFilePath(self: *Manifest, optional_file_path: ?Path) !void { + self.hash.add(optional_file_path != null); + const file_path = optional_file_path orelse return; + _ = try self.addFilePath(file_path, null); + } + pub fn addListOfFiles(self: *Manifest, list_of_files: []const []const u8) !void { self.hash.add(list_of_files.len); for (list_of_files) |file_path| { diff --git a/zig/lib/std/Build/Cache/Path.zig b/zig/lib/std/Build/Cache/Path.zig index ee0666b70a..a14c6cd7a4 100644 --- a/zig/lib/std/Build/Cache/Path.zig +++ b/zig/lib/std/Build/Cache/Path.zig @@ -11,7 +11,11 @@ pub fn clone(p: Path, arena: Allocator) Allocator.Error!Path { } pub fn cwd() Path { - return .{ .root_dir = Cache.Directory.cwd() }; + return initCwd(""); +} + +pub fn initCwd(sub_path: []const u8) Path { + return .{ .root_dir = Cache.Directory.cwd(), .sub_path = sub_path }; } pub fn join(p: Path, arena: Allocator, sub_path: []const u8) Allocator.Error!Path { @@ -126,6 +130,14 @@ pub fn makePath(p: Path, sub_path: []const u8) !void { return p.root_dir.handle.makePath(joined_path); } +pub fn toString(p: Path, allocator: Allocator) Allocator.Error![]u8 { + return std.fmt.allocPrint(allocator, "{}", .{p}); +} + +pub fn toStringZ(p: Path, allocator: Allocator) Allocator.Error![:0]u8 { + return std.fmt.allocPrintZ(allocator, "{}", .{p}); +} + pub fn format( self: Path, comptime fmt_string: []const u8, @@ -137,7 +149,7 @@ pub fn format( const stringEscape = std.zig.stringEscape; const f = switch (fmt_string[0]) { 'q' => "", - '\'' => '\'', + '\'' => "\'", else => @compileError("unsupported format string: " ++ fmt_string), }; if (self.root_dir.path) |p| { @@ -182,6 +194,14 @@ pub fn subPathOrDot(self: Path) []const u8 { return if (self.sub_path.len == 0) "." else self.sub_path; } +pub fn stem(p: Path) []const u8 { + return fs.path.stem(p.sub_path); +} + +pub fn basename(p: Path) []const u8 { + return fs.path.basename(p.sub_path); +} + /// Useful to make `Path` a key in `std.ArrayHashMap`. pub const TableAdapter = struct { pub const Hash = std.hash.Wyhash; diff --git a/zig/lib/std/Build/Module.zig b/zig/lib/std/Build/Module.zig index 635e6cc334..253945b3d7 100644 --- a/zig/lib/std/Build/Module.zig +++ b/zig/lib/std/Build/Module.zig @@ -135,6 +135,44 @@ pub const IncludeDir = union(enum) { framework_path_system: LazyPath, other_step: *Step.Compile, config_header_step: *Step.ConfigHeader, + + pub fn appendZigProcessFlags( + include_dir: IncludeDir, + b: *std.Build, + zig_args: *std.ArrayList([]const u8), + asking_step: ?*Step, + ) !void { + switch (include_dir) { + .path => |include_path| { + try zig_args.appendSlice(&.{ "-I", include_path.getPath2(b, asking_step) }); + }, + .path_system => |include_path| { + try zig_args.appendSlice(&.{ "-isystem", include_path.getPath2(b, asking_step) }); + }, + .path_after => |include_path| { + try zig_args.appendSlice(&.{ "-idirafter", include_path.getPath2(b, asking_step) }); + }, + .framework_path => |include_path| { + try zig_args.appendSlice(&.{ "-F", include_path.getPath2(b, asking_step) }); + }, + .framework_path_system => |include_path| { + try zig_args.appendSlice(&.{ "-iframework", include_path.getPath2(b, asking_step) }); + }, + .other_step => |other| { + if (other.generated_h) |header| { + try zig_args.appendSlice(&.{ "-isystem", std.fs.path.dirname(header.getPath()).? }); + } + if (other.installed_headers_include_tree) |include_tree| { + try zig_args.appendSlice(&.{ "-I", include_tree.generated_directory.getPath() }); + } + }, + .config_header_step => |config_header| { + const full_file_path = config_header.output_file.getPath(); + const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len]; + try zig_args.appendSlice(&.{ "-I", header_dir_path }); + }, + } + } }; pub const LinkFrameworkOptions = struct { @@ -690,36 +728,7 @@ pub fn appendZigProcessFlags( } for (m.include_dirs.items) |include_dir| { - switch (include_dir) { - .path => |include_path| { - try zig_args.appendSlice(&.{ "-I", include_path.getPath2(b, asking_step) }); - }, - .path_system => |include_path| { - try zig_args.appendSlice(&.{ "-isystem", include_path.getPath2(b, asking_step) }); - }, - .path_after => |include_path| { - try zig_args.appendSlice(&.{ "-idirafter", include_path.getPath2(b, asking_step) }); - }, - .framework_path => |include_path| { - try zig_args.appendSlice(&.{ "-F", include_path.getPath2(b, asking_step) }); - }, - .framework_path_system => |include_path| { - try zig_args.appendSlice(&.{ "-iframework", include_path.getPath2(b, asking_step) }); - }, - .other_step => |other| { - if (other.generated_h) |header| { - try zig_args.appendSlice(&.{ "-isystem", std.fs.path.dirname(header.getPath()).? }); - } - if (other.installed_headers_include_tree) |include_tree| { - try zig_args.appendSlice(&.{ "-I", include_tree.generated_directory.getPath() }); - } - }, - .config_header_step => |config_header| { - const full_file_path = config_header.output_file.getPath(); - const header_dir_path = full_file_path[0 .. full_file_path.len - config_header.include_path.len]; - try zig_args.appendSlice(&.{ "-I", header_dir_path }); - }, - } + try include_dir.appendZigProcessFlags(b, zig_args, asking_step); } try zig_args.appendSlice(m.c_macros.items); diff --git a/zig/lib/std/Build/Step/CheckObject.zig b/zig/lib/std/Build/Step/CheckObject.zig index 54f7bc7412..00ea5013de 100644 --- a/zig/lib/std/Build/Step/CheckObject.zig +++ b/zig/lib/std/Build/Step/CheckObject.zig @@ -557,15 +557,15 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { const check_object: *CheckObject = @fieldParentPtr("step", step); try step.singleUnchangingWatchInput(check_object.source); - const src_path = check_object.source.getPath2(b, step); - const contents = fs.cwd().readFileAllocOptions( + const src_path = check_object.source.getPath3(b, step); + const contents = src_path.root_dir.handle.readFileAllocOptions( gpa, - src_path, + src_path.sub_path, check_object.max_bytes, null, @alignOf(u64), null, - ) catch |err| return step.fail("unable to read '{s}': {s}", .{ src_path, @errorName(err) }); + ) catch |err| return step.fail("unable to read '{'}': {s}", .{ src_path, @errorName(err) }); var vars = std.StringHashMap(u64).init(gpa); for (check_object.checks.items) |chk| { @@ -640,8 +640,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { \\{s} \\========= but parsed file does not contain it: ======= \\{s} - \\====================================================== - , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); + \\========= file path: ================================= + \\{} + , .{ + fmtMessageString(chk.kind, act.phrase.resolve(b, step)), + fmtMessageString(chk.kind, output), + src_path, + }); } }, @@ -655,8 +660,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { \\*{s}* \\========= but parsed file does not contain it: ======= \\{s} - \\====================================================== - , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); + \\========= file path: ================================= + \\{} + , .{ + fmtMessageString(chk.kind, act.phrase.resolve(b, step)), + fmtMessageString(chk.kind, output), + src_path, + }); } }, @@ -669,8 +679,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { \\{s} \\========= but parsed file does contain it: ======== \\{s} - \\=================================================== - , .{ fmtMessageString(chk.kind, act.phrase.resolve(b, step)), fmtMessageString(chk.kind, output) }); + \\========= file path: ============================== + \\{} + , .{ + fmtMessageString(chk.kind, act.phrase.resolve(b, step)), + fmtMessageString(chk.kind, output), + src_path, + }); } }, @@ -684,8 +699,13 @@ fn make(step: *Step, make_options: Step.MakeOptions) !void { \\{s} \\========= but parsed file does not contain it: ======= \\{s} - \\====================================================== - , .{ act.phrase.resolve(b, step), fmtMessageString(chk.kind, output) }); + \\========= file path: ============================== + \\{} + , .{ + act.phrase.resolve(b, step), + fmtMessageString(chk.kind, output), + src_path, + }); } }, diff --git a/zig/lib/std/Build/Step/Compile.zig b/zig/lib/std/Build/Step/Compile.zig index 0f0b5d3201..a977dc3056 100644 --- a/zig/lib/std/Build/Step/Compile.zig +++ b/zig/lib/std/Build/Step/Compile.zig @@ -235,6 +235,7 @@ sanitize_coverage_trace_pc_guard: ?bool = null, pub const ExpectedCompileErrors = union(enum) { contains: []const u8, exact: []const []const u8, + starts_with: []const u8, }; pub const Entry = union(enum) { @@ -1958,6 +1959,17 @@ fn checkCompileErrors(compile: *Compile) !void { // TODO merge this with the testing.expectEqualStrings logic, and also CheckFile switch (expect_errors) { + .starts_with => |expect_starts_with| { + if (std.mem.startsWith(u8, actual_stderr, expect_starts_with)) return; + return compile.step.fail( + \\ + \\========= should start with: ============ + \\{s} + \\========= but not found: ================ + \\{s} + \\========================================= + , .{ expect_starts_with, actual_stderr }); + }, .contains => |expect_line| { while (actual_line_it.next()) |actual_line| { if (!matchCompileError(actual_line, expect_line)) continue; diff --git a/zig/lib/std/Build/Step/ObjCopy.zig b/zig/lib/std/Build/Step/ObjCopy.zig index 6ed23d3fb4..8f0f62e222 100644 --- a/zig/lib/std/Build/Step/ObjCopy.zig +++ b/zig/lib/std/Build/Step/ObjCopy.zig @@ -26,6 +26,50 @@ pub const Strip = enum { debug_and_symbols, }; +pub const SectionFlags = packed struct { + /// add SHF_ALLOC + alloc: bool = false, + + /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing + contents: bool = false, + + /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents) + load: bool = false, + + /// readonly: clear default SHF_WRITE flag + readonly: bool = false, + + /// add SHF_EXECINSTR + code: bool = false, + + /// add SHF_EXCLUDE + exclude: bool = false, + + /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64 + large: bool = false, + + /// add SHF_MERGE + merge: bool = false, + + /// add SHF_STRINGS + strings: bool = false, +}; + +pub const AddSection = struct { + section_name: []const u8, + file_path: std.Build.LazyPath, +}; + +pub const SetSectionAlignment = struct { + section_name: []const u8, + alignment: u32, +}; + +pub const SetSectionFlags = struct { + section_name: []const u8, + flags: SectionFlags, +}; + step: Step, input_file: std.Build.LazyPath, basename: []const u8, @@ -38,6 +82,10 @@ pad_to: ?u64, strip: Strip, compress_debug: bool, +add_section: ?AddSection, +set_section_alignment: ?SetSectionAlignment, +set_section_flags: ?SetSectionFlags, + pub const Options = struct { basename: ?[]const u8 = null, format: ?RawFormat = null, @@ -51,6 +99,10 @@ pub const Options = struct { /// note: the `basename` is baked into the elf file to specify the link to the separate debug file. /// see https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html extract_to_separate_file: bool = false, + + add_section: ?AddSection = null, + set_section_alignment: ?SetSectionAlignment = null, + set_section_flags: ?SetSectionFlags = null, }; pub fn create( @@ -75,6 +127,9 @@ pub fn create( .pad_to = options.pad_to, .strip = options.strip, .compress_debug = options.compress_debug, + .add_section = options.add_section, + .set_section_alignment = options.set_section_alignment, + .set_section_flags = options.set_section_flags, }; input_file.addStepDependencies(&objcopy.step); return objcopy; @@ -155,6 +210,31 @@ fn make(step: *Step, options: Step.MakeOptions) !void { if (objcopy.output_file_debug != null) { try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})}); } + if (objcopy.add_section) |section| { + try argv.append("--add-section"); + try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath(b) })}); + } + if (objcopy.set_section_alignment) |set_align| { + try argv.append("--set-section-alignment"); + try argv.appendSlice(&.{b.fmt("{s}={d}", .{ set_align.section_name, set_align.alignment })}); + } + if (objcopy.set_section_flags) |set_flags| { + const f = set_flags.flags; + // trailing comma is allowed + try argv.append("--set-section-flags"); + try argv.appendSlice(&.{b.fmt("{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{ + set_flags.section_name, + if (f.alloc) "alloc," else "", + if (f.contents) "contents," else "", + if (f.load) "load," else "", + if (f.readonly) "readonly," else "", + if (f.code) "code," else "", + if (f.exclude) "exclude," else "", + if (f.large) "large," else "", + if (f.merge) "merge," else "", + if (f.strings) "strings," else "", + })}); + } try argv.appendSlice(&.{ full_src_path, full_dest_path }); diff --git a/zig/lib/std/Build/Step/TranslateC.zig b/zig/lib/std/Build/Step/TranslateC.zig index 9ef5f7acdf..13f4375999 100644 --- a/zig/lib/std/Build/Step/TranslateC.zig +++ b/zig/lib/std/Build/Step/TranslateC.zig @@ -1,5 +1,6 @@ const std = @import("std"); const Step = std.Build.Step; +const LazyPath = std.Build.LazyPath; const fs = std.fs; const mem = std.mem; @@ -9,7 +10,7 @@ pub const base_id: Step.Id = .translate_c; step: Step, source: std.Build.LazyPath, -include_dirs: std.ArrayList([]const u8), +include_dirs: std.ArrayList(std.Build.Module.IncludeDir), c_macros: std.ArrayList([]const u8), out_basename: []const u8, target: std.Build.ResolvedTarget, @@ -37,7 +38,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC { .makeFn = make, }), .source = source, - .include_dirs = std.ArrayList([]const u8).init(owner.allocator), + .include_dirs = std.ArrayList(std.Build.Module.IncludeDir).init(owner.allocator), .c_macros = std.ArrayList([]const u8).init(owner.allocator), .out_basename = undefined, .target = options.target, @@ -95,8 +96,45 @@ pub fn createModule(translate_c: *TranslateC) *std.Build.Module { }); } -pub fn addIncludeDir(translate_c: *TranslateC, include_dir: []const u8) void { - translate_c.include_dirs.append(translate_c.step.owner.dupePath(include_dir)) catch @panic("OOM"); +pub fn addAfterIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { + const b = translate_c.step.owner; + translate_c.include_dirs.append(.{ .path_after = lazy_path.dupe(b) }) catch + @panic("OOM"); + lazy_path.addStepDependencies(&translate_c.step); +} + +pub fn addSystemIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { + const b = translate_c.step.owner; + translate_c.include_dirs.append(.{ .path_system = lazy_path.dupe(b) }) catch + @panic("OOM"); + lazy_path.addStepDependencies(&translate_c.step); +} + +pub fn addIncludePath(translate_c: *TranslateC, lazy_path: LazyPath) void { + const b = translate_c.step.owner; + translate_c.include_dirs.append(.{ .path = lazy_path.dupe(b) }) catch + @panic("OOM"); + lazy_path.addStepDependencies(&translate_c.step); +} + +pub fn addConfigHeader(translate_c: *TranslateC, config_header: *Step.ConfigHeader) void { + translate_c.include_dirs.append(.{ .config_header_step = config_header }) catch + @panic("OOM"); + translate_c.step.dependOn(&config_header.step); +} + +pub fn addSystemFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void { + const b = translate_c.step.owner; + translate_c.include_dirs.append(.{ .framework_path_system = directory_path.dupe(b) }) catch + @panic("OOM"); + directory_path.addStepDependencies(&translate_c.step); +} + +pub fn addFrameworkPath(translate_c: *TranslateC, directory_path: LazyPath) void { + const b = translate_c.step.owner; + translate_c.include_dirs.append(.{ .framework_path = directory_path.dupe(b) }) catch + @panic("OOM"); + directory_path.addStepDependencies(&translate_c.step); } pub fn addCheckFile(translate_c: *TranslateC, expected_matches: []const []const u8) *Step.CheckFile { @@ -147,8 +185,7 @@ fn make(step: *Step, options: Step.MakeOptions) !void { } for (translate_c.include_dirs.items) |include_dir| { - try argv_list.append("-I"); - try argv_list.append(include_dir); + try include_dir.appendZigProcessFlags(b, &argv_list, step); } for (translate_c.c_macros.items) |c_macro| { diff --git a/zig/lib/std/Build/Watch.zig b/zig/lib/std/Build/Watch.zig index c1a9e80b8e..c8f6c0d64f 100644 --- a/zig/lib/std/Build/Watch.zig +++ b/zig/lib/std/Build/Watch.zig @@ -516,7 +516,7 @@ const Os = switch (builtin.os.tag) { pub fn init() !Watch { switch (builtin.os.tag) { .linux => { - const fan_fd = try std.posix.fanotify_init(.{ + const fan_fd = std.posix.fanotify_init(.{ .CLASS = .NOTIF, .CLOEXEC = true, .NONBLOCK = true, @@ -524,7 +524,10 @@ pub fn init() !Watch { .REPORT_DIR_FID = true, .REPORT_FID = true, .REPORT_TARGET_FID = true, - }, 0); + }, 0) catch |err| switch (err) { + error.UnsupportedFlags => fatal("fanotify_init failed due to old kernel; requires 5.17+", .{}), + else => |e| return e, + }; return .{ .dir_table = .{}, .os = switch (builtin.os.tag) { diff --git a/zig/lib/std/Target.zig b/zig/lib/std/Target.zig index 58fbaab8b1..efe8ad4809 100644 --- a/zig/lib/std/Target.zig +++ b/zig/lib/std/Target.zig @@ -66,13 +66,13 @@ pub const Os = struct { nvcl, opencl, opengl, - shadermodel, vulkan, // LLVM tags deliberately omitted: // - darwin // - kfreebsd // - nacl + // - shadermodel pub inline fn isDarwin(tag: Tag) bool { return switch (tag) { @@ -113,7 +113,7 @@ pub const Os = struct { pub fn staticLibSuffix(tag: Tag, abi: Abi) [:0]const u8 { return switch (abi) { - .msvc => ".lib", + .msvc, .itanium => ".lib", else => switch (tag) { .windows, .uefi => ".lib", else => ".a", @@ -138,7 +138,7 @@ pub const Os = struct { pub fn libPrefix(tag: Os.Tag, abi: Abi) [:0]const u8 { return switch (abi) { - .msvc => "", + .msvc, .itanium => "", else => switch (tag) { .windows, .uefi => "", else => "lib", @@ -178,7 +178,6 @@ pub const Os = struct { .hermit, .hurd, .emscripten, - .shadermodel, .uefi, .opencl, // TODO: OpenCL versions .opengl, // TODO: GLSL versions @@ -189,7 +188,9 @@ pub const Os = struct { .other, => .none, - .bridgeos, + // This should use semver once we determine the version history. + .bridgeos => .none, + .driverkit, .freebsd, .macos, @@ -408,7 +409,6 @@ pub const Os = struct { .hermit, .hurd, .emscripten, - .shadermodel, .uefi, .opencl, // TODO: OpenCL versions .opengl, // TODO: GLSL versions @@ -613,7 +613,6 @@ pub const Os = struct { .hurd, .wasi, .emscripten, - .shadermodel, .uefi, .opencl, .opengl, @@ -633,6 +632,7 @@ pub const avr = @import("Target/avr.zig"); pub const bpf = @import("Target/bpf.zig"); pub const csky = @import("Target/csky.zig"); pub const hexagon = @import("Target/hexagon.zig"); +pub const lanai = @import("Target/lanai.zig"); pub const loongarch = @import("Target/loongarch.zig"); pub const m68k = @import("Target/m68k.zig"); pub const mips = @import("Target/mips.zig"); @@ -646,7 +646,9 @@ pub const s390x = @import("Target/s390x.zig"); pub const ve = @import("Target/ve.zig"); pub const wasm = @import("Target/wasm.zig"); pub const x86 = @import("Target/x86.zig"); +pub const xcore = @import("Target/xcore.zig"); pub const xtensa = @import("Target/xtensa.zig"); +pub const propeller = @import("Target/propeller.zig"); pub const Abi = enum { none, @@ -664,6 +666,7 @@ pub const Abi = enum { eabihf, ilp32, android, + androideabi, musl, musleabi, musleabihf, @@ -673,75 +676,136 @@ pub const Abi = enum { cygnus, simulator, macabi, - pixel, - vertex, - geometry, - hull, - domain, - compute, - library, - raygeneration, - intersection, - anyhit, - closesthit, - miss, - callable, - mesh, - amplification, ohos, + ohoseabi, // LLVM tags deliberately omitted: - // - gnuf64 + // - amplification + // - anyhit + // - callable + // - closesthit + // - compute // - coreclr + // - domain + // - geometry + // - gnuf64 + // - hull + // - intersection + // - library + // - mesh + // - miss + // - pixel + // - raygeneration + // - vertex pub fn default(arch: Cpu.Arch, os: Os) Abi { return if (arch.isWasm()) .musl else switch (os.tag) { .freestanding, - .dragonfly, - .ps3, - .zos, - .rtems, - .aix, - .cuda, - .nvcl, - .amdhsa, - .ps4, - .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, .other, - => .eabi, - .openbsd, - .freebsd, - .fuchsia, - .netbsd, - .hurd, - .haiku, - .windows, - => .gnu, - .uefi => .msvc, + => switch (arch) { + // Soft float is usually a sane default for freestanding. + .arm, + .armeb, + .thumb, + .thumbeb, + .csky, + .mips, + .mipsel, + .powerpc, + .powerpcle, + => .eabi, + else => .none, + }, + .aix, + => if (arch == .powerpc) .eabihf else .none, .linux, .wasi, .emscripten, => .musl, - .bridgeos, - .opencl, - .opengl, - .vulkan, - .plan9, // TODO specify abi - .macos, + .rtems, + => switch (arch) { + .arm, + .armeb, + .thumb, + .thumbeb, + .mips, + .mipsel, + => .eabi, + .powerpc, + => .eabihf, + else => .none, + }, + .hurd, + .windows, + => .gnu, + .freebsd, + => switch (arch) { + .arm, + .armeb, + .thumb, + .thumbeb, + .powerpc, + => .eabihf, + .mips, + .mipsel, + => .eabi, + else => .none, + }, + .netbsd, + => switch (arch) { + .arm, + .armeb, + .thumb, + .thumbeb, + .powerpc, + => .eabihf, + .mips, + .mipsel, + => .eabi, + else => .none, + }, + .openbsd, + => switch (arch) { + .arm, + .thumb, + => .eabi, + .powerpc, + => .eabihf, + else => .none, + }, .ios, + => if (arch == .x86_64) .macabi else .none, .tvos, - .watchos, .visionos, + => if (arch == .x86_64) .simulator else .none, + .uefi, + => .msvc, + .contiki, + .elfiamcu, + .fuchsia, + .hermit, + .haiku, + .plan9, + .serenity, + .zos, + .dragonfly, + .bridgeos, .driverkit, - .shadermodel, - .solaris, + .macos, + .watchos, .illumos, - .serenity, + .solaris, + .ps3, + .ps4, + .ps5, + .amdhsa, + .amdpal, + .cuda, + .mesa3d, + .nvcl, + .opencl, + .opengl, + .vulkan, => .none, }; } @@ -764,19 +828,37 @@ pub const Abi = enum { pub inline fn isMusl(abi: Abi) bool { return switch (abi) { - .musl, .musleabi, .musleabihf, .muslx32 => true, - .ohos => true, + .musl, + .musleabi, + .musleabihf, + .muslx32, + => true, + else => abi.isOpenHarmony(), + }; + } + + pub inline fn isOpenHarmony(abi: Abi) bool { + return switch (abi) { + .ohos, .ohoseabi => true, + else => false, + }; + } + + pub inline fn isAndroid(abi: Abi) bool { + return switch (abi) { + .android, .androideabi => true, else => false, }; } pub inline fn floatAbi(abi: Abi) FloatAbi { return switch (abi) { + .androideabi, .eabi, .gnueabi, .musleabi, .gnusf, - .ohos, + .ohoseabi, => .soft, else => .hard, }; @@ -788,8 +870,6 @@ pub const ObjectFormat = enum { c, /// The Common Object File Format used by Windows and UEFI. coff, - /// The DirectX Container format containing either DXIL or DXBC. - dxcontainer, /// The Executable and Linkable Format used by many Unixes. elf, /// The Generalized Object File Format used by z/OS. @@ -811,11 +891,13 @@ pub const ObjectFormat = enum { /// The eXtended Common Object File Format used by AIX. xcoff, + // LLVM tags deliberately omitted: + // - dxcontainer + pub fn fileExt(of: ObjectFormat, arch: Cpu.Arch) [:0]const u8 { return switch (of) { .c => ".c", .coff => ".obj", - .dxcontainer => ".dxil", .elf, .goff, .macho, .wasm, .xcoff => ".o", .hex => ".ihex", .nvptx => ".ptx", @@ -833,7 +915,6 @@ pub const ObjectFormat = enum { .uefi, .windows => .coff, .zos => .goff, else => switch (arch) { - .dxil => .dxcontainer, .nvptx, .nvptx64 => .nvptx, .spirv, .spirv32, .spirv64 => .spirv, .wasm32, .wasm64 => .wasm, @@ -848,7 +929,7 @@ pub fn toElfMachine(target: Target) std.elf.EM { return switch (target.cpu.arch) { .amdgcn => .AMDGPU, - .arc => .ARC_COMPACT2, + .arc => .ARC_COMPACT, .arm, .armeb, .thumb, .thumbeb => .ARM, .aarch64, .aarch64_be => .AARCH64, .avr => .AVR, @@ -868,18 +949,20 @@ pub fn toElfMachine(target: Target) std.elf.EM { .sparc => if (Target.sparc.featureSetHas(target.cpu.features, .v9)) .SPARC32PLUS else .SPARC, .sparc64 => .SPARCV9, .spu_2 => .SPU_2, + .ve => .VE, .x86 => .@"386", .x86_64 => .X86_64, .xcore => .XCORE, .xtensa => .XTENSA, - .dxil, + .propeller1 => .PROPELLER, + .propeller2 => .PROPELLER2, + .nvptx, .nvptx64, .spirv, .spirv32, .spirv64, - .ve, .wasm32, .wasm64, => .NONE, @@ -907,7 +990,6 @@ pub fn toCoffMachine(target: Target) std.coff.MachineType { .bpfel, .bpfeb, .csky, - .dxil, .hexagon, .kalimba, .lanai, @@ -935,6 +1017,8 @@ pub fn toCoffMachine(target: Target) std.coff.MachineType { .wasm64, .xcore, .xtensa, + .propeller1, + .propeller2, => .UNKNOWN, }; } @@ -1133,7 +1217,6 @@ pub const Cpu = struct { bpfel, bpfeb, csky, - dxil, hexagon, kalimba, lanai, @@ -1151,6 +1234,8 @@ pub const Cpu = struct { powerpcle, powerpc64, powerpc64le, + propeller1, + propeller2, riscv32, riscv64, s390x, @@ -1172,6 +1257,7 @@ pub const Cpu = struct { // - aarch64_32 // - amdil // - amdil64 + // - dxil // - le32 // - le64 // - r600 @@ -1303,6 +1389,14 @@ pub const Cpu = struct { }; } + /// Returns if the architecture is a Parallax propeller architecture. + pub inline fn isPropeller(arch: Arch) bool { + return switch (arch) { + .propeller1, .propeller2 => true, + else => false, + }; + } + pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model { for (arch.allCpuModels()) |cpu| { if (std.mem.eql(u8, cpu_name, cpu.name)) { @@ -1344,10 +1438,11 @@ pub const Cpu = struct { .spirv, .spirv32, .spirv64, - .dxil, .loongarch32, .loongarch64, .arc, + .propeller1, + .propeller2, => .little, .armeb, @@ -1380,6 +1475,10 @@ pub const Cpu = struct { .input, .output, .uniform => is_spirv, // TODO this should also check how many flash banks the cpu has .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, + + // Propeller address spaces: + .cog, .hub => arch.isPropeller(), + .lut => (arch == .propeller2), }; } @@ -1400,6 +1499,7 @@ pub const Cpu = struct { .nvptx, .nvptx64 => "nvptx", .wasm32, .wasm64 => "wasm", .spirv, .spirv32, .spirv64 => "spirv", + .propeller1, .propeller2 => "propeller", else => @tagName(arch), }; } @@ -1414,6 +1514,7 @@ pub const Cpu = struct { .bpfel, .bpfeb => &bpf.all_features, .csky => &csky.all_features, .hexagon => &hexagon.all_features, + .lanai => &lanai.all_features, .loongarch32, .loongarch64 => &loongarch.all_features, .m68k => &m68k.all_features, .mips, .mipsel, .mips64, .mips64el => &mips.all_features, @@ -1425,6 +1526,7 @@ pub const Cpu = struct { .spirv, .spirv32, .spirv64 => &spirv.all_features, .s390x => &s390x.all_features, .x86, .x86_64 => &x86.all_features, + .xcore => &xcore.all_features, .xtensa => &xtensa.all_features, .nvptx, .nvptx64 => &nvptx.all_features, .ve => &ve.all_features, @@ -1444,6 +1546,7 @@ pub const Cpu = struct { .bpfel, .bpfeb => comptime allCpusFromDecls(bpf.cpu), .csky => comptime allCpusFromDecls(csky.cpu), .hexagon => comptime allCpusFromDecls(hexagon.cpu), + .lanai => comptime allCpusFromDecls(lanai.cpu), .loongarch32, .loongarch64 => comptime allCpusFromDecls(loongarch.cpu), .m68k => comptime allCpusFromDecls(m68k.cpu), .mips, .mipsel, .mips64, .mips64el => comptime allCpusFromDecls(mips.cpu), @@ -1455,6 +1558,7 @@ pub const Cpu = struct { .spirv, .spirv32, .spirv64 => comptime allCpusFromDecls(spirv.cpu), .s390x => comptime allCpusFromDecls(s390x.cpu), .x86, .x86_64 => comptime allCpusFromDecls(x86.cpu), + .xcore => comptime allCpusFromDecls(xcore.cpu), .xtensa => comptime allCpusFromDecls(xtensa.cpu), .nvptx, .nvptx64 => comptime allCpusFromDecls(nvptx.cpu), .ve => comptime allCpusFromDecls(ve.cpu), @@ -1524,11 +1628,14 @@ pub const Cpu = struct { }; }; return switch (arch) { + .arc => &arc.cpu.generic, .arm, .armeb, .thumb, .thumbeb => &arm.cpu.generic, .aarch64, .aarch64_be => &aarch64.cpu.generic, .avr => &avr.cpu.avr2, .bpfel, .bpfeb => &bpf.cpu.generic, + .csky => &csky.cpu.generic, .hexagon => &hexagon.cpu.generic, + .lanai => &lanai.cpu.generic, .loongarch32 => &loongarch.cpu.generic_la32, .loongarch64 => &loongarch.cpu.generic_la64, .m68k => &m68k.cpu.generic, @@ -1539,6 +1646,8 @@ pub const Cpu = struct { .powerpcle => &powerpc.cpu.ppc, .powerpc64 => &powerpc.cpu.ppc64, .powerpc64le => &powerpc.cpu.ppc64le, + .propeller1 => &propeller.cpu.generic, + .propeller2 => &propeller.cpu.generic, .amdgcn => &amdgpu.cpu.generic, .riscv32 => &riscv.cpu.generic_rv32, .riscv64 => &riscv.cpu.generic_rv64, @@ -1551,8 +1660,12 @@ pub const Cpu = struct { .nvptx, .nvptx64 => &nvptx.cpu.sm_20, .ve => &ve.cpu.generic, .wasm32, .wasm64 => &wasm.cpu.generic, + .xcore => &xcore.cpu.generic, + .xtensa => &xtensa.cpu.generic, - else => &S.generic_model, + .kalimba, + .spu_2, + => &S.generic_model, }; } @@ -1621,7 +1734,7 @@ pub inline fn isMusl(target: Target) bool { } pub inline fn isAndroid(target: Target) bool { - return target.abi == .android; + return target.abi.isAndroid(); } pub inline fn isWasm(target: Target) bool { @@ -1727,156 +1840,332 @@ pub const DynamicLinker = struct { return std.mem.eql(u8, lhs.buffer[0..lhs.len], rhs.buffer[0..rhs.len]); } - pub fn standard(cpu: Cpu, os_tag: Os.Tag, abi: Abi) DynamicLinker { - return if (abi == .android) initFmt("/system/bin/linker{s}", .{ - if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else "", - }) catch unreachable else if (abi.isMusl()) return initFmt("/lib/ld-musl-{s}{s}.so.1", .{ - @tagName(switch (cpu.arch) { - .thumb => .arm, - .thumbeb => .armeb, - else => cpu.arch, - }), - if (cpu.arch.isArmOrThumb() and abi.floatAbi() == .hard) "hf" else "", - }) catch unreachable else switch (os_tag) { - .freebsd => init("/libexec/ld-elf.so.1"), - .netbsd => init("/libexec/ld.elf_so"), - .openbsd => init("/usr/libexec/ld.so"), - .dragonfly => init("/libexec/ld-elf.so.2"), - .solaris, .illumos => init("/lib/64/ld.so.1"), - .linux => switch (cpu.arch) { - .x86, - .sparc, - => init("/lib/ld-linux.so.2"), + pub fn standard(cpu: Cpu, os: Os, abi: Abi) DynamicLinker { + return switch (os.tag) { + .fuchsia => init("ld.so.1"), // Fuchsia is unusual in that `DT_INTERP` is just a basename. + + .haiku => init("/system/runtime_loader"), + + .hurd => switch (cpu.arch) { + .aarch64, + .aarch64_be, + => |arch| initFmt("/lib/ld-{s}{s}.so.1", .{ + @tagName(arch), + if (abi == .gnuilp32) "_ilp32" else "", + }), - .aarch64 => init("/lib/ld-linux-aarch64.so.1"), - .aarch64_be => init("/lib/ld-linux-aarch64_be.so.1"), + .x86 => init("/lib/ld.so.1"), + .x86_64 => initFmt("/lib/ld-{s}.so.1", .{if (abi == .gnux32) "x32" else "x86-64"}), + // These are unsupported by Hurd/glibc. + .amdgcn, + .arc, .arm, .armeb, .thumb, .thumbeb, - => initFmt("/lib/ld-linux{s}.so.3", .{switch (abi.floatAbi()) { - .hard => "-armhf", - else => "", - }}) catch unreachable, - - .loongarch64 => init("/lib64/ld-linux-loongarch-lp64d.so.1"), - + .avr, + .bpfel, + .bpfeb, + .csky, + .hexagon, + .kalimba, + .lanai, + .loongarch32, + .loongarch64, + .m68k, .mips, .mipsel, .mips64, .mips64el, - => initFmt("/lib{s}/{s}", .{ - switch (abi) { - .gnuabin32, .gnux32 => "32", - .gnuabi64 => "64", - else => "", - }, - if (mips.featureSetHas(cpu.features, .nan2008)) - "ld-linux-mipsn8.so.1" - else - "ld.so.1", - }) catch unreachable, - - .powerpc, .powerpcle => init("/lib/ld.so.1"), - .powerpc64, .powerpc64le => init("/lib64/ld64.so.2"), - .s390x => init("/lib64/ld64.so.1"), - .sparc64 => init("/lib64/ld-linux.so.2"), - .x86_64 => init(switch (abi) { - .gnux32 => "/libx32/ld-linux-x32.so.2", - else => "/lib64/ld-linux-x86-64.so.2", - }), - - .riscv32 => init("/lib/ld-linux-riscv32-ilp32d.so.1"), - .riscv64 => init("/lib/ld-linux-riscv64-lp64d.so.1"), - - // Architectures in this list have been verified as not having a standard - // dynamic linker path. - .wasm32, - .wasm64, - .bpfel, - .bpfeb, + .msp430, .nvptx, .nvptx64, - .spu_2, - .avr, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, + .propeller1, + .propeller2, + .riscv32, + .riscv64, + .s390x, + .sparc, + .sparc64, .spirv, .spirv32, .spirv64, - => none, - - // TODO go over each item in this list and either move it to the above list, or - // implement the standard dynamic linker path code for it. - .arc, - .csky, - .hexagon, - .m68k, - .msp430, - .amdgcn, - .xcore, - .kalimba, - .lanai, + .spu_2, .ve, - .dxil, - .loongarch32, + .wasm32, + .wasm64, + .xcore, .xtensa, => none, }, + .linux => if (abi.isAndroid()) + initFmt("/system/bin/linker{s}", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64" else ""}) + else if (abi.isMusl()) + switch (cpu.arch) { + .arm, + .armeb, + .thumb, + .thumbeb, + .aarch64, + .aarch64_be, + .loongarch64, + .m68k, + .powerpc, + .powerpc64, + .powerpc64le, + .riscv32, + .riscv64, + .s390x, + .x86, + .x86_64, + => |arch| initFmt("/lib/ld-musl-{s}{s}.so.1", .{ + switch (arch) { + .thumb => "arm", + .thumbeb => "armeb", + .x86 => "i386", + .x86_64 => if (abi == .muslx32) "x32" else "x86_64", + else => @tagName(arch), + }, + switch (arch) { + .arm, .armeb, .thumb, .thumbeb => if (abi.floatAbi() == .hard) "hf" else "", + .aarch64, .aarch64_be => if (abi == .gnuilp32) "_ilp32" else "", + .riscv32, .riscv64 => if (std.Target.riscv.featureSetHas(cpu.features, .d)) + "" + else if (std.Target.riscv.featureSetHas(cpu.features, .f)) + "-sp" + else + "-sf", + else => if (abi.floatAbi() == .soft) "-sf" else "", + }, + }), + + // The naming scheme for MIPS is a bit irregular. + .mips, + .mipsel, + .mips64, + .mips64el, + => |arch| initFmt("/lib/ld-musl-mips{s}{s}{s}{s}.so.1", .{ + if (arch.isMIPS64()) "64" else "", // TODO: `n32` ABI support in LLVM 20. + if (mips.featureSetHas(cpu.features, if (arch.isMIPS64()) .mips64r6 else .mips32r6)) "r6" else "", + if (arch.endian() == .little) "el" else "", + if (abi.floatAbi() == .soft) "-sf" else "", + }), + + // These are unsupported by musl. + .amdgcn, + .arc, + .avr, + .csky, + .bpfel, + .bpfeb, + .hexagon, + .kalimba, + .lanai, + .loongarch32, + .msp430, + .nvptx, + .nvptx64, + .powerpcle, + .propeller1, + .propeller2, + .sparc, + .sparc64, + .spirv, + .spirv32, + .spirv64, + .spu_2, + .ve, + .wasm32, + .wasm64, + .xcore, + .xtensa, + => none, + } + else if (abi.isGnu()) + switch (cpu.arch) { + // TODO: `eb` architecture support. + // TODO: `700` ABI support. + .arc => init("/lib/ld-linux-arc.so.2"), + + // TODO: OABI support (`/lib/ld-linux.so.2`). + .arm, + .armeb, + .thumb, + .thumbeb, + => initFmt("/lib/ld-linux{s}.so.3", .{if (abi.floatAbi() == .hard) "-armhf" else ""}), + + .aarch64, + .aarch64_be, + => |arch| initFmt("/lib/ld-linux-{s}{s}.so.1", .{ + @tagName(arch), + if (abi == .gnuilp32) "_ilp32" else "", + }), + + // TODO: `-be` architecture support. + .csky => initFmt("/lib/ld-linux-cskyv2{s}.so.1", .{if (abi.floatAbi() == .hard) "-hf" else ""}), + + .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) { + .gnuf32 => "lp64f", + .gnusf => "lp64s", + else => "lp64d", + }}), + + .m68k => init("/lib/ld.so.1"), + + .mips, + .mipsel, + .mips64, + .mips64el, + => initFmt("/lib{s}/ld{s}.so.1", .{ + switch (abi) { + .gnuabin32 => "32", + .gnuabi64 => "64", + else => "", + }, + if (mips.featureSetHas(cpu.features, .nan2008)) "-linux-mipsn8" else "", + }), + + .powerpc => init("/lib/ld.so.1"), + // TODO: ELFv2 ABI opt-in support. + .powerpc64 => init("/lib64/ld64.so.1"), + .powerpc64le => init("/lib64/ld64.so.2"), + + .riscv32, + .riscv64, + => |arch| initFmt("/lib/ld-linux-{s}-{s}{s}.so.1", .{ + @tagName(arch), + switch (arch) { + .riscv32 => "ilp32", + .riscv64 => "lp64", + else => unreachable, + }, + if (riscv.featureSetHas(cpu.features, .d)) + "d" + else if (riscv.featureSetHas(cpu.features, .f)) + "f" + else + "", + }), + + .s390x => init("/lib/ld64.so.1"), + + .sparc => init("/lib/ld-linux.so.2"), + .sparc64 => init("/lib64/ld-linux.so.2"), + + .x86 => init("/lib/ld-linux.so.2"), + .x86_64 => init(if (abi == .gnux32) "/libx32/ld-linux-x32.so.2" else "/lib64/ld-linux-x86-64.so.2"), + + .xtensa => init("/lib/ld.so.1"), + + // These are unsupported by glibc. + .amdgcn, + .avr, + .bpfeb, + .bpfel, + .hexagon, + .kalimba, + .lanai, + .loongarch32, + .msp430, + .nvptx, + .nvptx64, + .powerpcle, + .propeller1, + .propeller2, + .spirv, + .spirv32, + .spirv64, + .spu_2, + .ve, + .wasm32, + .wasm64, + .xcore, + => none, + } + else + none, // Not a known Linux libc. + + .serenity => init("/usr/lib/Loader.so"), + + .dragonfly => initFmt("{s}/libexec/ld-elf.so.2", .{ + if (os.version_range.semver.isAtLeast(.{ .major = 3, .minor = 8, .patch = 0 }) orelse false) + "" + else + "/usr", + }), + + .freebsd => initFmt("{s}/libexec/ld-elf.so.1", .{ + if (os.version_range.semver.isAtLeast(.{ .major = 6, .minor = 0, .patch = 0 }) orelse false) + "" + else + "/usr", + }), + + .netbsd => init("/libexec/ld.elf_so"), + + .openbsd => init("/usr/libexec/ld.so"), + .bridgeos, .driverkit, .ios, - .tvos, - .watchos, .macos, + .tvos, .visionos, + .watchos, => init("/usr/lib/dyld"), - .serenity => init("/usr/lib/Loader.so"), + .illumos, + .solaris, + => initFmt("/lib/{s}ld.so.1", .{if (ptrBitWidth_cpu_abi(cpu, abi) == 64) "64/" else ""}), // Operating systems in this list have been verified as not having a standard // dynamic linker path. .freestanding, + .other, + + .contiki, + .elfiamcu, + .hermit, + + .aix, + .plan9, + .rtems, + .zos, + .uefi, .windows, + .emscripten, .wasi, + + .amdhsa, + .amdpal, + .cuda, + .mesa3d, + .nvcl, .opencl, .opengl, .vulkan, - .other, - .plan9, => none, - // TODO revisit when multi-arch for Haiku is available - .haiku => init("/system/runtime_loader"), - // TODO go over each item in this list and either move it to the above list, or // implement the standard dynamic linker path code for it. - .fuchsia, .ps3, - .zos, - .rtems, - .aix, - .cuda, - .nvcl, - .amdhsa, .ps4, .ps5, - .elfiamcu, - .mesa3d, - .contiki, - .amdpal, - .hermit, - .hurd, - .shadermodel, => none, - }; + } catch unreachable; } }; pub fn standardDynamicLinkerPath(target: Target) DynamicLinker { - return DynamicLinker.standard(target.cpu, target.os.tag, target.abi); + return DynamicLinker.standard(target.cpu, target.os, target.abi); } pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { @@ -1913,8 +2202,9 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 { .sparc, .spirv32, .loongarch32, - .dxil, .xtensa, + .propeller1, + .propeller2, => 32, .aarch64, @@ -2363,7 +2653,6 @@ pub fn cTypeBitSize(target: Target, c_type: CType) u16 { .hermit, .hurd, .opengl, - .shadermodel, => @panic("TODO specify the C integer and float type sizes for this OS"), } } @@ -2397,6 +2686,7 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 { .eabi, .eabihf, .android, + .androideabi, .musleabi, .musleabihf, => 8, @@ -2408,18 +2698,18 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 { }, .msp430, - .avr, => 2, .arc, .csky, .x86, .xcore, - .dxil, .loongarch32, .kalimba, .spu_2, .xtensa, + .propeller1, + .propeller2, => 4, .amdgcn, @@ -2456,6 +2746,9 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 { .wasm32, .wasm64, => 16, + + .avr, + => unreachable, // Handled above. }), ); } @@ -2470,6 +2763,7 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { .eabi, .eabihf, .android, + .androideabi, .musleabi, .musleabihf, => {}, @@ -2489,12 +2783,7 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { .longdouble => return 4, else => {}, }, - .avr => switch (c_type) { - .char, .int, .uint, .long, .ulong, .float, .longdouble => return 1, - .short, .ushort => return 2, - .double => return 4, - .longlong, .ulonglong => return 8, - }, + .avr => return 1, .x86 => switch (target.os.tag) { .windows, .uefi => switch (c_type) { .longdouble => switch (target.abi) { @@ -2519,17 +2808,17 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { .csky, .xcore, - .dxil, .loongarch32, .kalimba, .spu_2, .xtensa, + .propeller1, + .propeller2, => 4, .arc, .arm, .armeb, - .avr, .thumb, .thumbeb, .amdgcn, @@ -2567,6 +2856,9 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 { .wasm32, .wasm64, => 16, + + .avr, + => unreachable, // Handled above. }), ); } diff --git a/zig/lib/std/Target/Query.zig b/zig/lib/std/Target/Query.zig index f18d211853..e22fbcbf53 100644 --- a/zig/lib/std/Target/Query.zig +++ b/zig/lib/std/Target/Query.zig @@ -374,7 +374,7 @@ pub fn canDetectLibC(self: Query) bool { if (self.isNativeOs()) return true; if (self.os_tag) |os| { if (builtin.os.tag == .macos and os.isDarwin()) return true; - if (os == .linux and self.abi == .android) return true; + if (os == .linux and self.abi.isAndroid()) return true; } return false; } diff --git a/zig/lib/std/Target/aarch64.zig b/zig/lib/std/Target/aarch64.zig index ac7dba124e..8b501e2dc2 100644 --- a/zig/lib/std/Target/aarch64.zig +++ b/zig/lib/std/Target/aarch64.zig @@ -1373,6 +1373,7 @@ pub const all_features = blk: { .llvm_name = "v8.3a", .description = "Support ARM v8.3a architecture", .dependencies = featureSet(&[_]Feature{ + .ccidx, .complxnum, .jsconv, .pauth, @@ -1409,6 +1410,7 @@ pub const all_features = blk: { .predres, .sb, .specrestrict, + .ssbs, .v8_4a, }), }; @@ -1470,18 +1472,26 @@ pub const all_features = blk: { .llvm_name = "v8r", .description = "Support ARM v8r architecture", .dependencies = featureSet(&[_]Feature{ + .ccidx, .ccpp, + .complxnum, .contextidr_el2, .crc, .dit, + .dotprod, .flagm, + .fp16fml, + .jsconv, .lse, .pan_rwv, .pauth, .ras, .rcpc_immo, + .rdm, + .sb, .sel2, .specrestrict, + .ssbs, .tlb_rmi, .tracev8_4, .uaops, @@ -1491,6 +1501,7 @@ pub const all_features = blk: { .llvm_name = "v9.1a", .description = "Support ARM v9.1a architecture", .dependencies = featureSet(&[_]Feature{ + .rme, .v8_6a, .v9a, }), @@ -1499,6 +1510,7 @@ pub const all_features = blk: { .llvm_name = "v9.2a", .description = "Support ARM v9.2a architecture", .dependencies = featureSet(&[_]Feature{ + .mec, .v8_7a, .v9_1a, }), @@ -1524,6 +1536,8 @@ pub const all_features = blk: { .description = "Support ARM v9.5a architecture", .dependencies = featureSet(&[_]Feature{ .cpa, + .faminmax, + .lut, .v9_4a, }), }; @@ -1531,6 +1545,7 @@ pub const all_features = blk: { .llvm_name = "v9a", .description = "Support ARM v9a architecture", .dependencies = featureSet(&[_]Feature{ + .sve2, .v8_5a, }), }; @@ -1607,7 +1622,6 @@ pub const cpu = struct { .aggressive_fma, .alu_lsl_fast, .arith_bcc_fusion, - .ccidx, .cmp_bcc_fusion, .fullfp16, .fuse_address, @@ -1618,7 +1632,6 @@ pub const cpu = struct { .perfmon, .rand, .sha3, - .ssbs, .store_pair_suppress, .stp_aligned_only, .use_postra_scheduler, @@ -1633,7 +1646,6 @@ pub const cpu = struct { .aggressive_fma, .alu_lsl_fast, .arith_bcc_fusion, - .ccidx, .cmp_bcc_fusion, .fullfp16, .fuse_address, @@ -1647,7 +1659,6 @@ pub const cpu = struct { .rand, .sha3, .sm4, - .ssbs, .store_pair_suppress, .stp_aligned_only, .use_postra_scheduler, @@ -1662,7 +1673,6 @@ pub const cpu = struct { .aggressive_fma, .alu_lsl_fast, .arith_bcc_fusion, - .ccidx, .cmp_bcc_fusion, .cssc, .enable_select_opt, @@ -1678,7 +1688,6 @@ pub const cpu = struct { .rand, .sha3, .sm4, - .ssbs, .store_pair_suppress, .stp_aligned_only, .use_postra_scheduler, @@ -1819,7 +1828,6 @@ pub const cpu = struct { .fuse_literals, .perfmon, .sha3, - .ssbs, .store_pair_suppress, .v8_6a, .zcm, @@ -1846,7 +1854,6 @@ pub const cpu = struct { .hcx, .perfmon, .sha3, - .ssbs, .store_pair_suppress, .v8_6a, .zcm, @@ -1873,7 +1880,6 @@ pub const cpu = struct { .hcx, .perfmon, .sha3, - .ssbs, .store_pair_suppress, .v8_6a, .zcm, @@ -1990,7 +1996,6 @@ pub const cpu = struct { .fuse_literals, .perfmon, .sha3, - .ssbs, .store_pair_suppress, .v8_6a, .zcm, @@ -2017,7 +2022,6 @@ pub const cpu = struct { .hcx, .perfmon, .sha3, - .ssbs, .store_pair_suppress, .v8_6a, .zcm, @@ -2106,7 +2110,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -2116,7 +2119,6 @@ pub const cpu = struct { .mte, .perfmon, .predictable_select_expensive, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2149,7 +2151,6 @@ pub const cpu = struct { .llvm_name = "cortex-a510", .features = featureSet(&[_]Feature{ .bf16, - .ccidx, .ete, .fp16fml, .fuse_adrp_add, @@ -2157,7 +2158,6 @@ pub const cpu = struct { .i8mm, .mte, .perfmon, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2167,14 +2167,12 @@ pub const cpu = struct { .name = "cortex_a520", .llvm_name = "cortex-a520", .features = featureSet(&[_]Feature{ - .ccidx, .ete, .fp16fml, .fuse_adrp_add, .fuse_aes, .mte, .perfmon, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2184,14 +2182,12 @@ pub const cpu = struct { .name = "cortex_a520ae", .llvm_name = "cortex-a520ae", .features = featureSet(&[_]Feature{ - .ccidx, .ete, .fp16fml, .fuse_adrp_add, .fuse_aes, .mte, .perfmon, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2294,7 +2290,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2305,7 +2300,6 @@ pub const cpu = struct { .mte, .perfmon, .predictable_select_expensive, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2317,7 +2311,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2329,7 +2322,6 @@ pub const cpu = struct { .perfmon, .predictable_select_expensive, .spe, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2357,7 +2349,6 @@ pub const cpu = struct { .llvm_name = "cortex-a720", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2369,7 +2360,6 @@ pub const cpu = struct { .predictable_select_expensive, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2380,7 +2370,6 @@ pub const cpu = struct { .llvm_name = "cortex-a720ae", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2392,7 +2381,6 @@ pub const cpu = struct { .predictable_select_expensive, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2403,7 +2391,6 @@ pub const cpu = struct { .llvm_name = "cortex-a725", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2415,7 +2402,6 @@ pub const cpu = struct { .predictable_select_expensive, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2592,15 +2578,8 @@ pub const cpu = struct { .llvm_name = "cortex-r82", .features = featureSet(&[_]Feature{ .ccdp, - .complxnum, - .dotprod, - .fp16fml, - .jsconv, .perfmon, .predres, - .rdm, - .sb, - .ssbs, .use_postra_scheduler, .v8r, }), @@ -2610,15 +2589,8 @@ pub const cpu = struct { .llvm_name = "cortex-r82ae", .features = featureSet(&[_]Feature{ .ccdp, - .complxnum, - .dotprod, - .fp16fml, - .jsconv, .perfmon, .predres, - .rdm, - .sb, - .ssbs, .use_postra_scheduler, .v8r, }), @@ -2678,7 +2650,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2689,7 +2660,6 @@ pub const cpu = struct { .mte, .perfmon, .predictable_select_expensive, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2701,7 +2671,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -2712,7 +2681,6 @@ pub const cpu = struct { .perfmon, .predictable_select_expensive, .spe, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -2723,7 +2691,6 @@ pub const cpu = struct { .llvm_name = "cortex-x4", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -2734,7 +2701,6 @@ pub const cpu = struct { .predictable_select_expensive, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2745,7 +2711,6 @@ pub const cpu = struct { .llvm_name = "cortex-x925", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -2756,7 +2721,6 @@ pub const cpu = struct { .predictable_select_expensive, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -2935,7 +2899,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -2948,7 +2911,6 @@ pub const cpu = struct { .predictable_select_expensive, .rand, .spe, - .ssbs, .sve2_bitperm, .use_fixed_over_scalable_if_equal_cost, .use_postra_scheduler, @@ -2979,7 +2941,6 @@ pub const cpu = struct { .alu_lsl_fast, .bf16, .ccdp, - .ccidx, .enable_select_opt, .fp16fml, .fuse_adrp_add, @@ -3042,7 +3003,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -3052,7 +3012,6 @@ pub const cpu = struct { .mte, .perfmon, .predictable_select_expensive, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9a, @@ -3063,7 +3022,6 @@ pub const cpu = struct { .llvm_name = "neoverse-n3", .features = featureSet(&[_]Feature{ .alu_lsl_fast, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -3075,7 +3033,6 @@ pub const cpu = struct { .rand, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -3090,7 +3047,6 @@ pub const cpu = struct { .alu_lsl_fast, .bf16, .ccdp, - .ccidx, .enable_select_opt, .fp16fml, .fuse_adrp_add, @@ -3115,7 +3071,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .bf16, - .ccidx, .cmp_bcc_fusion, .enable_select_opt, .ete, @@ -3128,7 +3083,6 @@ pub const cpu = struct { .predictable_select_expensive, .rand, .spe, - .ssbs, .sve2_bitperm, .use_fixed_over_scalable_if_equal_cost, .use_postra_scheduler, @@ -3141,7 +3095,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .brbe, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -3152,10 +3105,8 @@ pub const cpu = struct { .perfmon, .predictable_select_expensive, .rand, - .rme, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -3167,7 +3118,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .alu_lsl_fast, .brbe, - .ccidx, .enable_select_opt, .ete, .fp16fml, @@ -3178,10 +3128,8 @@ pub const cpu = struct { .perfmon, .predictable_select_expensive, .rand, - .rme, .spe, .spe_eef, - .ssbs, .sve2_bitperm, .use_postra_scheduler, .v9_2a, @@ -3192,7 +3140,6 @@ pub const cpu = struct { .llvm_name = "oryon-1", .features = featureSet(&[_]Feature{ .aes, - .ccidx, .enable_select_opt, .fp16fml, .fuse_address, @@ -3204,7 +3151,6 @@ pub const cpu = struct { .sha3, .sm4, .spe, - .ssbs, .use_postra_scheduler, .v8_6a, }), @@ -3215,7 +3161,6 @@ pub const cpu = struct { .features = featureSet(&[_]Feature{ .aes, .alu_lsl_fast, - .ccidx, .perfmon, .predictable_select_expensive, .sha2, @@ -3262,7 +3207,6 @@ pub const cpu = struct { .aggressive_fma, .arith_bcc_fusion, .balance_fp_ops, - .ccidx, .perfmon, .predictable_select_expensive, .sha2, diff --git a/zig/lib/std/Target/arm.zig b/zig/lib/std/Target/arm.zig index aa0e1e4603..9e4e72a05a 100644 --- a/zig/lib/std/Target/arm.zig +++ b/zig/lib/std/Target/arm.zig @@ -2254,7 +2254,6 @@ pub const cpu = struct { .llvm_name = "cortex-m85", .features = featureSet(&[_]Feature{ .dsp, - .trustzone, .use_misched, .v8_1m_main, }), diff --git a/zig/lib/std/Target/lanai.zig b/zig/lib/std/Target/lanai.zig new file mode 100644 index 0000000000..041934b6d4 --- /dev/null +++ b/zig/lib/std/Target/lanai.zig @@ -0,0 +1,37 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum {}; + +pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; +pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).@"enum".fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.@"enum".fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const v11 = CpuModel{ + .name = "v11", + .llvm_name = "v11", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/zig/lib/std/Target/propeller.zig b/zig/lib/std/Target/propeller.zig new file mode 100644 index 0000000000..929e3ff74c --- /dev/null +++ b/zig/lib/std/Target/propeller.zig @@ -0,0 +1,20 @@ +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum {}; + +pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; +pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll; + +pub const all_features: [0]CpuFeature = .{}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = null, + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/zig/lib/std/Target/xcore.zig b/zig/lib/std/Target/xcore.zig new file mode 100644 index 0000000000..4069620849 --- /dev/null +++ b/zig/lib/std/Target/xcore.zig @@ -0,0 +1,37 @@ +//! This file is auto-generated by tools/update_cpu_features.zig. + +const std = @import("../std.zig"); +const CpuFeature = std.Target.Cpu.Feature; +const CpuModel = std.Target.Cpu.Model; + +pub const Feature = enum {}; + +pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet; +pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas; +pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny; +pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll; + +pub const all_features = blk: { + const len = @typeInfo(Feature).@"enum".fields.len; + std.debug.assert(len <= CpuFeature.Set.needed_bit_count); + var result: [len]CpuFeature = undefined; + const ti = @typeInfo(Feature); + for (&result, 0..) |*elem, i| { + elem.index = i; + elem.name = ti.@"enum".fields[i].name; + } + break :blk result; +}; + +pub const cpu = struct { + pub const generic = CpuModel{ + .name = "generic", + .llvm_name = "generic", + .features = featureSet(&[_]Feature{}), + }; + pub const xs1b_generic = CpuModel{ + .name = "xs1b_generic", + .llvm_name = "xs1b-generic", + .features = featureSet(&[_]Feature{}), + }; +}; diff --git a/zig/lib/std/Thread.zig b/zig/lib/std/Thread.zig index 446b629cc6..a5c03138f7 100644 --- a/zig/lib/std/Thread.zig +++ b/zig/lib/std/Thread.zig @@ -22,6 +22,83 @@ pub const WaitGroup = @import("Thread/WaitGroup.zig"); pub const use_pthreads = native_os != .windows and native_os != .wasi and builtin.link_libc; +/// Spurious wakeups are possible and no precision of timing is guaranteed. +pub fn sleep(nanoseconds: u64) void { + if (builtin.os.tag == .windows) { + const big_ms_from_ns = nanoseconds / std.time.ns_per_ms; + const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD); + windows.kernel32.Sleep(ms); + return; + } + + if (builtin.os.tag == .wasi) { + const w = std.os.wasi; + const userdata: w.userdata_t = 0x0123_45678; + const clock: w.subscription_clock_t = .{ + .id = .MONOTONIC, + .timeout = nanoseconds, + .precision = 0, + .flags = 0, + }; + const in: w.subscription_t = .{ + .userdata = userdata, + .u = .{ + .tag = .CLOCK, + .u = .{ .clock = clock }, + }, + }; + + var event: w.event_t = undefined; + var nevents: usize = undefined; + _ = w.poll_oneoff(&in, &event, 1, &nevents); + return; + } + + if (builtin.os.tag == .uefi) { + const boot_services = std.os.uefi.system_table.boot_services.?; + const us_from_ns = nanoseconds / std.time.ns_per_us; + const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize); + _ = boot_services.stall(us); + return; + } + + const s = nanoseconds / std.time.ns_per_s; + const ns = nanoseconds % std.time.ns_per_s; + + // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around + // since Linux 2.6 and glibc 2.1 anyway. + if (builtin.os.tag == .linux) { + const linux = std.os.linux; + + var req: linux.timespec = .{ + .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t), + .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t), + }; + var rem: linux.timespec = undefined; + + while (true) { + switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) { + .SUCCESS => return, + .INTR => { + req = rem; + continue; + }, + .FAULT, + .INVAL, + .OPNOTSUPP, + => unreachable, + else => return, + } + } + } + + posix.nanosleep(s, ns); +} + +test sleep { + sleep(1); +} + const Thread = @This(); const Impl = if (native_os == .windows) WindowsThreadImpl diff --git a/zig/lib/std/Thread/Futex.zig b/zig/lib/std/Thread/Futex.zig index fe22fa2011..da3fb916c6 100644 --- a/zig/lib/std/Thread/Futex.zig +++ b/zig/lib/std/Thread/Futex.zig @@ -794,9 +794,8 @@ const PosixImpl = struct { // - T1: bumps pending waiters (was reordered after the ptr == expect check) // - T1: goes to sleep and misses both the ptr change and T2's wake up // - // seq_cst as Acquire barrier to ensure the announcement happens before the ptr check below. - // seq_cst as shared modification order to form a happens-before edge with the fence(.seq_cst)+load() in wake(). - var pending = bucket.pending.fetchAdd(1, .seq_cst); + // acquire barrier to ensure the announcement happens before the ptr check below. + var pending = bucket.pending.fetchAdd(1, .acquire); assert(pending < std.math.maxInt(usize)); // If the wait gets cancelled, remove the pending count we previously added. @@ -858,15 +857,8 @@ const PosixImpl = struct { // // What we really want here is a Release load, but that doesn't exist under the C11 memory model. // We could instead do `bucket.pending.fetchAdd(0, Release) == 0` which achieves effectively the same thing, - // but the RMW operation unconditionally marks the cache-line as modified for others causing unnecessary fetching/contention. - // - // Instead we opt to do a full-fence + load instead which avoids taking ownership of the cache-line. - // fence(seq_cst) effectively converts the ptr update to seq_cst and the pending load to seq_cst: creating a Store-Load barrier. - // - // The pending count increment in wait() must also now use seq_cst for the update + this pending load - // to be in the same modification order as our load isn't using release/acquire to guarantee it. - bucket.pending.fence(.seq_cst); - if (bucket.pending.load(.monotonic) == 0) { + // LLVM lowers the fetchAdd(0, .release) into an mfence+load which avoids gaining ownership of the cache-line. + if (bucket.pending.fetchAdd(0, .release) == 0) { return; } @@ -979,15 +971,14 @@ test "broadcasting" { fn wait(self: *@This()) !void { // Decrement the counter. // Release ensures stuff before this barrier.wait() happens before the last one. - const count = self.count.fetchSub(1, .release); + // Acquire for the last counter ensures stuff before previous barrier.wait()s happened before it. + const count = self.count.fetchSub(1, .acq_rel); try testing.expect(count <= num_threads); try testing.expect(count > 0); // First counter to reach zero wakes all other threads. - // Acquire for the last counter ensures stuff before previous barrier.wait()s happened before it. // Release on futex update ensures stuff before all barrier.wait()'s happens before they all return. if (count - 1 == 0) { - _ = self.count.load(.acquire); // TODO: could be fence(acquire) if not for TSAN self.futex.store(1, .release); Futex.wake(&self.futex, num_threads - 1); return; diff --git a/zig/lib/std/Thread/ResetEvent.zig b/zig/lib/std/Thread/ResetEvent.zig index cbc5a2a31c..47a9b0c038 100644 --- a/zig/lib/std/Thread/ResetEvent.zig +++ b/zig/lib/std/Thread/ResetEvent.zig @@ -112,9 +112,9 @@ const FutexImpl = struct { // Try to set the state from `unset` to `waiting` to indicate // to the set() thread that others are blocked on the ResetEvent. // We avoid using any strict barriers until the end when we know the ResetEvent is set. - var state = self.state.load(.monotonic); + var state = self.state.load(.acquire); if (state == unset) { - state = self.state.cmpxchgStrong(state, waiting, .monotonic, .monotonic) orelse waiting; + state = self.state.cmpxchgStrong(state, waiting, .acquire, .acquire) orelse waiting; } // Wait until the ResetEvent is set since the state is waiting. @@ -124,7 +124,7 @@ const FutexImpl = struct { const wait_result = futex_deadline.wait(&self.state, waiting); // Check if the ResetEvent was set before possibly reporting error.Timeout below. - state = self.state.load(.monotonic); + state = self.state.load(.acquire); if (state != waiting) { break; } @@ -133,9 +133,7 @@ const FutexImpl = struct { } } - // Acquire barrier ensures memory accesses before set() happen before we return. assert(state == is_set); - self.state.fence(.acquire); } fn set(self: *Impl) void { diff --git a/zig/lib/std/Thread/WaitGroup.zig b/zig/lib/std/Thread/WaitGroup.zig index cff474c863..bdc49587bf 100644 --- a/zig/lib/std/Thread/WaitGroup.zig +++ b/zig/lib/std/Thread/WaitGroup.zig @@ -15,11 +15,10 @@ pub fn start(self: *WaitGroup) void { } pub fn finish(self: *WaitGroup) void { - const state = self.state.fetchSub(one_pending, .release); + const state = self.state.fetchSub(one_pending, .acq_rel); assert((state / one_pending) > 0); if (state == (one_pending | is_waiting)) { - self.state.fence(.acquire); self.event.set(); } } diff --git a/zig/lib/std/atomic.zig b/zig/lib/std/atomic.zig index 0f25bd448a..e1a6767590 100644 --- a/zig/lib/std/atomic.zig +++ b/zig/lib/std/atomic.zig @@ -10,31 +10,7 @@ pub fn Value(comptime T: type) type { return .{ .raw = value }; } - /// Perform an atomic fence which uses the atomic value as a hint for - /// the modification order. Use this when you want to imply a fence on - /// an atomic variable without necessarily performing a memory access. - pub inline fn fence(self: *Self, comptime order: AtomicOrder) void { - // LLVM's ThreadSanitizer doesn't support the normal fences so we specialize for it. - if (builtin.sanitize_thread) { - const tsan = struct { - extern "c" fn __tsan_acquire(addr: *anyopaque) void; - extern "c" fn __tsan_release(addr: *anyopaque) void; - }; - - const addr: *anyopaque = self; - return switch (order) { - .unordered, .monotonic => @compileError(@tagName(order) ++ " only applies to atomic loads and stores"), - .acquire => tsan.__tsan_acquire(addr), - .release => tsan.__tsan_release(addr), - .acq_rel, .seq_cst => { - tsan.__tsan_acquire(addr); - tsan.__tsan_release(addr); - }, - }; - } - - return @fence(order); - } + pub const fence = @compileError("@fence is deprecated, use other atomics to establish ordering"); pub inline fn load(self: *const Self, comptime order: AtomicOrder) T { return @atomicLoad(T, &self.raw, order); @@ -148,21 +124,19 @@ test Value { const RefCount = @This(); fn ref(rc: *RefCount) void { - // No ordering necessary; just updating a counter. + // no synchronization necessary; just updating a counter. _ = rc.count.fetchAdd(1, .monotonic); } fn unref(rc: *RefCount) void { - // Release ensures code before unref() happens-before the + // release ensures code before unref() happens-before the // count is decremented as dropFn could be called by then. if (rc.count.fetchSub(1, .release) == 1) { - // acquire ensures count decrement and code before - // previous unrefs()s happens-before we call dropFn - // below. - // Another alternative is to use .acq_rel on the - // fetchSub count decrement but it's extra barrier in - // possibly hot path. - rc.count.fence(.acquire); + // seeing 1 in the counter means that other unref()s have happened, + // but it doesn't mean that uses before each unref() are visible. + // The load acquires the release-sequence created by previous unref()s + // in order to ensure visibility of uses before dropping. + _ = rc.count.load(.acquire); (rc.dropFn)(rc); } } @@ -459,18 +433,20 @@ pub const cache_line = switch (builtin.cpu.arch) { .powerpc64le, => 128, + // https://github.com/llvm/llvm-project/blob/e379094328e49731a606304f7e3559d4f1fa96f9/clang/lib/Basic/Targets/Hexagon.h#L145-L151 + .hexagon, + => if (std.Target.hexagon.featureSetHas(builtin.target.cpu.features, .v73)) 64 else 32, + // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7 - // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/hexagon/include/asm/cache.h#L13 // - https://github.com/torvalds/linux/blob/3a7e02c040b130b5545e4b115aada7bacd80a2b6/arch/sparc/include/asm/cache.h#L14 .arm, .armeb, .thumb, .thumbeb, - .hexagon, .mips, .mipsel, .mips64, diff --git a/zig/lib/std/bit_set.zig b/zig/lib/std/bit_set.zig index 1e2a0179ef..7ff97cfa9d 100644 --- a/zig/lib/std/bit_set.zig +++ b/zig/lib/std/bit_set.zig @@ -1043,10 +1043,7 @@ pub const DynamicBitSet = struct { /// The integer type used to shift a mask in this bit set pub const ShiftInt = std.math.Log2Int(MaskInt); - /// The allocator used by this bit set allocator: Allocator, - - /// The number of valid items in this bit set unmanaged: DynamicBitSetUnmanaged = .{}, /// Creates a bit set with no elements present. diff --git a/zig/lib/std/builtin.zig b/zig/lib/std/builtin.zig index ccd46d874d..628b736d82 100644 --- a/zig/lib/std/builtin.zig +++ b/zig/lib/std/builtin.zig @@ -236,6 +236,17 @@ pub const AddressSpace = enum(u5) { flash3, flash4, flash5, + + // Propeller address spaces. + + /// This address space only addresses the cog-local ram. + cog, + + /// This address space only addresses shared hub ram. + hub, + + /// This address space only addresses the "lookup" ram + lut, }; /// This data structure is used by the Zig language code generation and @@ -609,6 +620,7 @@ pub const VaList = switch (builtin.cpu.arch) { .avr => *anyopaque, .bpfel, .bpfeb => *anyopaque, .hexagon => if (builtin.target.isMusl()) VaListHexagon else *u8, + .loongarch32, .loongarch64 => *anyopaque, .mips, .mipsel, .mips64, .mips64el => *anyopaque, .riscv32, .riscv64 => *anyopaque, .powerpc, .powerpcle => switch (builtin.os.tag) { @@ -761,201 +773,54 @@ pub const TestFn = struct { func: *const fn () anyerror!void, }; -/// This function type is used by the Zig language code generation and -/// therefore must be kept in sync with the compiler implementation. +/// Deprecated, use the `Panic` namespace instead. +/// To be deleted after 0.14.0 is released. pub const PanicFn = fn ([]const u8, ?*StackTrace, ?usize) noreturn; - -/// This function is used by the Zig language code generation and -/// therefore must be kept in sync with the compiler implementation. -pub const panic: PanicFn = if (@hasDecl(root, "panic")) - root.panic -else if (@hasDecl(root, "os") and @hasDecl(root.os, "panic")) - root.os.panic +/// Deprecated, use the `Panic` namespace instead. +/// To be deleted after 0.14.0 is released. +pub const panic: PanicFn = Panic.call; + +/// This namespace is used by the Zig compiler to emit various kinds of safety +/// panics. These can be overridden by making a public `Panic` namespace in the +/// root source file. +pub const Panic: type = if (@hasDecl(root, "Panic")) + root.Panic +else if (@hasDecl(root, "panic")) // Deprecated, use `Panic` instead. + DeprecatedPanic +else if (builtin.zig_backend == .stage2_riscv64) + std.debug.SimplePanic // https://github.com/ziglang/zig/issues/21519 else - default_panic; - -/// This function is used by the Zig language code generation and -/// therefore must be kept in sync with the compiler implementation. -pub fn default_panic(msg: []const u8, error_return_trace: ?*StackTrace, ret_addr: ?usize) noreturn { - @branchHint(.cold); - - // For backends that cannot handle the language features depended on by the - // default panic handler, we have a simpler panic handler: - if (builtin.zig_backend == .stage2_wasm or - builtin.zig_backend == .stage2_arm or - builtin.zig_backend == .stage2_aarch64 or - builtin.zig_backend == .stage2_x86 or - (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or - builtin.zig_backend == .stage2_sparc64 or - builtin.zig_backend == .stage2_spirv64) - { - while (true) { - @breakpoint(); - } - } - - if (builtin.zig_backend == .stage2_riscv64) { - std.debug.print("panic: {s}\n", .{msg}); - @breakpoint(); - std.posix.exit(127); - } - - switch (builtin.os.tag) { - .freestanding => { - while (true) { - @breakpoint(); - } - }, - .wasi => { - std.debug.print("{s}", .{msg}); - std.posix.abort(); - }, - .uefi => { - const uefi = std.os.uefi; - - const Formatter = struct { - pub fn fmt(exit_msg: []const u8, out: []u16) ![:0]u16 { - var u8_buf: [256]u8 = undefined; - const slice = try std.fmt.bufPrint(&u8_buf, "err: {s}\r\n", .{exit_msg}); - // We pass len - 1 because we need to add a null terminator after - const len = try std.unicode.utf8ToUtf16Le(out[0 .. out.len - 1], slice); - - out[len] = 0; - - return out[0..len :0]; - } - }; - - const ExitData = struct { - pub fn create_exit_data(exit_msg: [:0]u16, exit_size: *usize) ![*:0]u16 { - // Need boot services for pool allocation - if (uefi.system_table.boot_services == null) { - return error.BootServicesUnavailable; - } - - // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220) - const exit_data: []u16 = try uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1); - - @memcpy(exit_data[0 .. exit_msg.len + 1], exit_msg[0 .. exit_msg.len + 1]); - exit_size.* = exit_msg.len + 1; - - return @as([*:0]u16, @ptrCast(exit_data.ptr)); - } - }; - - var buf: [256]u16 = undefined; - const utf16 = Formatter.fmt(msg, &buf) catch null; - - var exit_size: usize = 0; - const exit_data = if (utf16) |u| - ExitData.create_exit_data(u, &exit_size) catch null - else - null; - - if (utf16) |str| { - // Output to both std_err and con_out, as std_err is easier - // to read in stuff like QEMU at times, but, unlike con_out, - // isn't visible on actual hardware if directly booted into - inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| { - if (o) |out| { - _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red); - _ = out.outputString(str); - _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white); - } - } - } - - if (uefi.system_table.boot_services) |bs| { - _ = bs.exit(uefi.handle, .Aborted, exit_size, exit_data); - } - - // Didn't have boot_services, just fallback to whatever. - std.posix.abort(); - }, - .cuda, .amdhsa => std.posix.abort(), - .plan9 => { - var status: [std.os.plan9.ERRMAX]u8 = undefined; - const len = @min(msg.len, status.len - 1); - @memcpy(status[0..len], msg[0..len]); - status[len] = 0; - std.os.plan9.exits(status[0..len :0]); - }, - else => { - const first_trace_addr = ret_addr orelse @returnAddress(); - std.debug.panicImpl(error_return_trace, first_trace_addr, msg); - }, - } -} - -pub fn checkNonScalarSentinel(expected: anytype, actual: @TypeOf(expected)) void { - if (!std.meta.eql(expected, actual)) { - panicSentinelMismatch(expected, actual); - } -} - -pub fn panicSentinelMismatch(expected: anytype, actual: @TypeOf(expected)) noreturn { - @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ expected, actual }); -} - -pub fn panicUnwrapError(st: ?*StackTrace, err: anyerror) noreturn { - @branchHint(.cold); - std.debug.panicExtra(st, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); -} - -pub fn panicOutOfBounds(index: usize, len: usize) noreturn { - @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); -} - -pub fn panicStartGreaterThanEnd(start: usize, end: usize) noreturn { - @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); -} - -pub fn panicInactiveUnionField(active: anytype, wanted: @TypeOf(active)) noreturn { - @branchHint(.cold); - std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ @tagName(wanted), @tagName(active) }); -} - -pub const panic_messages = struct { - pub const unreach = "reached unreachable code"; - pub const unwrap_null = "attempt to use null value"; - pub const cast_to_null = "cast causes pointer to be null"; - pub const incorrect_alignment = "incorrect alignment"; - pub const invalid_error_code = "invalid error code"; - pub const cast_truncated_data = "integer cast truncated bits"; - pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer"; - pub const integer_overflow = "integer overflow"; - pub const shl_overflow = "left shift overflowed bits"; - pub const shr_overflow = "right shift overflowed bits"; - pub const divide_by_zero = "division by zero"; - pub const exact_division_remainder = "exact division produced remainder"; - pub const inactive_union_field = "access of inactive union field"; - pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds"; - pub const corrupt_switch = "switch on corrupt value"; - pub const shift_rhs_too_big = "shift amount is greater than the type size"; - pub const invalid_enum_value = "invalid enum value"; - pub const sentinel_mismatch = "sentinel mismatch"; - pub const unwrap_error = "attempt to unwrap error"; - pub const index_out_of_bounds = "index out of bounds"; - pub const start_index_greater_than_end = "start index is larger than end index"; - pub const for_len_mismatch = "for loop over objects with non-equal lengths"; - pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths"; - pub const memcpy_alias = "@memcpy arguments alias"; - pub const noreturn_returned = "'noreturn' function returned"; -}; + std.debug.FormattedPanic; + +/// To be deleted after 0.14.0 is released. +const DeprecatedPanic = struct { + pub const call = root.panic; + pub const sentinelMismatch = std.debug.FormattedPanic.sentinelMismatch; + pub const unwrapError = std.debug.FormattedPanic.unwrapError; + pub const outOfBounds = std.debug.FormattedPanic.outOfBounds; + pub const startGreaterThanEnd = std.debug.FormattedPanic.startGreaterThanEnd; + pub const inactiveUnionField = std.debug.FormattedPanic.inactiveUnionField; + pub const messages = std.debug.FormattedPanic.messages; +}; + +/// To be deleted after zig1.wasm is updated. +pub const panicSentinelMismatch = Panic.sentinelMismatch; +/// To be deleted after zig1.wasm is updated. +pub const panicUnwrapError = Panic.unwrapError; +/// To be deleted after zig1.wasm is updated. +pub const panicOutOfBounds = Panic.outOfBounds; +/// To be deleted after zig1.wasm is updated. +pub const panicStartGreaterThanEnd = Panic.startGreaterThanEnd; +/// To be deleted after zig1.wasm is updated. +pub const panicInactiveUnionField = Panic.inactiveUnionField; +/// To be deleted after zig1.wasm is updated. +pub const panic_messages = Panic.messages; pub noinline fn returnError(st: *StackTrace) void { - @branchHint(.cold); + @branchHint(.unlikely); @setRuntimeSafety(false); - addErrRetTraceAddr(st, @returnAddress()); -} - -pub inline fn addErrRetTraceAddr(st: *StackTrace, addr: usize) void { if (st.index < st.instruction_addresses.len) - st.instruction_addresses[st.index] = addr; - + st.instruction_addresses[st.index] = @returnAddress(); st.index += 1; } diff --git a/zig/lib/std/c.zig b/zig/lib/std/c.zig index 12524667d2..d28f5b0ac4 100644 --- a/zig/lib/std/c.zig +++ b/zig/lib/std/c.zig @@ -134,7 +134,7 @@ pub const mode_t = switch (native_os) { .linux => linux.mode_t, .emscripten => emscripten.mode_t, .openbsd, .haiku, .netbsd, .solaris, .illumos, .wasi => u32, - .freebsd, .macos, .ios, .tvos, .watchos, .visionos => u16, + .freebsd, .macos, .ios, .tvos, .watchos, .visionos, .dragonfly => u16, else => u0, }; @@ -2753,6 +2753,19 @@ pub const Sigaction = switch (native_os) { restorer: ?*const fn () callconv(.C) void = null, __resv: [1]c_int = .{0}, }, + .s390x => if (builtin.abi == .gnu) extern struct { + pub const handler_fn = *align(1) const fn (i32) callconv(.C) void; + pub const sigaction_fn = *const fn (i32, *const siginfo_t, ?*anyopaque) callconv(.C) void; + + handler: extern union { + handler: ?handler_fn, + sigaction: ?sigaction_fn, + }, + __glibc_reserved0: c_int = 0, + flags: c_uint, + restorer: ?*const fn () callconv(.C) void = null, + mask: sigset_t, + } else linux.Sigaction, else => linux.Sigaction, }, .emscripten => emscripten.Sigaction, @@ -3137,6 +3150,72 @@ pub const T = switch (native_os) { pub const IOCUCNTL = 0x80047466; pub const IOCXMTFRAME = 0x80087444; }, + .dragonfly => struct { + pub const IOCMODG = 0x40047403; + pub const IOCMODS = 0x80047404; + pub const IOCM_LE = 0x00000001; + pub const IOCM_DTR = 0x00000002; + pub const IOCM_RTS = 0x00000004; + pub const IOCM_ST = 0x00000008; + pub const IOCM_SR = 0x00000010; + pub const IOCM_CTS = 0x00000020; + pub const IOCM_CAR = 0x00000040; + pub const IOCM_CD = 0x00000040; + pub const IOCM_RNG = 0x00000080; + pub const IOCM_RI = 0x00000080; + pub const IOCM_DSR = 0x00000100; + pub const IOCEXCL = 0x2000740d; + pub const IOCNXCL = 0x2000740e; + pub const IOCFLUSH = 0x80047410; + pub const IOCGETA = 0x402c7413; + pub const IOCSETA = 0x802c7414; + pub const IOCSETAW = 0x802c7415; + pub const IOCSETAF = 0x802c7416; + pub const IOCGETD = 0x4004741a; + pub const IOCSETD = 0x8004741b; + pub const IOCSBRK = 0x2000747b; + pub const IOCCBRK = 0x2000747a; + pub const IOCSDTR = 0x20007479; + pub const IOCCDTR = 0x20007478; + pub const IOCGPGRP = 0x40047477; + pub const IOCSPGRP = 0x80047476; + pub const IOCOUTQ = 0x40047473; + pub const IOCSTI = 0x80017472; + pub const IOCNOTTY = 0x20007471; + pub const IOCPKT = 0x80047470; + pub const IOCPKT_DATA = 0x00000000; + pub const IOCPKT_FLUSHREAD = 0x00000001; + pub const IOCPKT_FLUSHWRITE = 0x00000002; + pub const IOCPKT_STOP = 0x00000004; + pub const IOCPKT_START = 0x00000008; + pub const IOCPKT_NOSTOP = 0x00000010; + pub const IOCPKT_DOSTOP = 0x00000020; + pub const IOCPKT_IOCTL = 0x00000040; + pub const IOCSTOP = 0x2000746f; + pub const IOCSTART = 0x2000746e; + pub const IOCMSET = 0x8004746d; + pub const IOCMBIS = 0x8004746c; + pub const IOCMBIC = 0x8004746b; + pub const IOCMGET = 0x4004746a; + pub const IOCREMOTE = 0x80047469; + pub const IOCGWINSZ = 0x40087468; + pub const IOCSWINSZ = 0x80087467; + pub const IOCUCNTL = 0x80047466; + pub const IOCSTAT = 0x20007465; + pub const IOCGSID = 0x40047463; + pub const IOCCONS = 0x80047462; + pub const IOCSCTTY = 0x20007461; + pub const IOCEXT = 0x80047460; + pub const IOCSIG = 0x2000745f; + pub const IOCDRAIN = 0x2000745e; + pub const IOCMSDTRWAIT = 0x8004745b; + pub const IOCMGDTRWAIT = 0x4004745a; + pub const IOCTIMESTAMP = 0x40107459; + pub const IOCDCDTIMESTAMP = 0x40107458; + pub const IOCSDRAINWAIT = 0x80047457; + pub const IOCGDRAINWAIT = 0x40047456; + pub const IOCISPTMASTER = 0x20007455; + }, else => void, }; pub const IOCPARM_MASK = switch (native_os) { @@ -5946,7 +6025,7 @@ pub const PR = switch (native_os) { }; pub const _errno = switch (native_os) { .linux => switch (native_abi) { - .android => private.__errno, + .android, .androideabi => private.__errno, else => private.__errno_location, }, .emscripten => private.__errno_location, @@ -6389,14 +6468,14 @@ pub const Stat = switch (native_os) { return self.ctim; } } else extern struct { - dev: dev_t, + dev: u32, __pad0: [3]u32, ino: ino_t, mode: mode_t, nlink: nlink_t, uid: uid_t, gid: gid_t, - rdev: dev_t, + rdev: u32, __pad1: [3]u32, size: off_t, atim: timespec, @@ -6754,7 +6833,7 @@ pub const pthread_mutex_t = switch (native_os) { .mips64, .powerpc64, .powerpc64le, .sparc64 => 40, else => if (@sizeOf(usize) == 8) 40 else 24, }, - .android => if (@sizeOf(usize) == 8) 40 else 4, + .android, .androideabi => if (@sizeOf(usize) == 8) 40 else 4, else => @compileError("unsupported ABI"), }; }, @@ -6848,7 +6927,7 @@ pub const pthread_cond_t = switch (native_os) { pub const pthread_rwlock_t = switch (native_os) { .linux => switch (native_abi) { - .android => switch (@sizeOf(usize)) { + .android, .androideabi => switch (@sizeOf(usize)) { 4 => extern struct { data: [40]u8 align(@alignOf(usize)) = [_]u8{0} ** 40, }, @@ -9450,7 +9529,7 @@ pub extern "c" fn pthread_rwlock_unlock(rwl: *pthread_rwlock_t) callconv(.C) E; pub const pthread_t = *opaque {}; pub const FILE = opaque {}; -pub extern "c" fn dlopen(path: [*:0]const u8, mode: RTLD) ?*anyopaque; +pub extern "c" fn dlopen(path: ?[*:0]const u8, mode: RTLD) ?*anyopaque; pub extern "c" fn dlclose(handle: *anyopaque) c_int; pub extern "c" fn dlsym(handle: ?*anyopaque, symbol: [*:0]const u8) ?*anyopaque; pub extern "c" fn dlerror() ?[*:0]u8; @@ -9506,7 +9585,7 @@ else if (native_os == .linux and builtin.target.isMusl()) else private.getcontext; -pub const max_align_t = if (native_abi == .msvc) +pub const max_align_t = if (native_abi == .msvc or native_abi == .itanium) f64 else if (builtin.target.isDarwin()) c_longdouble @@ -9796,6 +9875,10 @@ pub const _ksiginfo = netbsd._ksiginfo; pub const _lwp_self = netbsd._lwp_self; pub const lwpid_t = netbsd.lwpid_t; +pub const lwp_gettid = dragonfly.lwp_gettid; +pub const umtx_sleep = dragonfly.umtx_sleep; +pub const umtx_wakeup = dragonfly.umtx_wakeup; + /// External definitions shared by two or more operating systems. const private = struct { extern "c" fn close(fd: fd_t) c_int; diff --git a/zig/lib/std/c/darwin.zig b/zig/lib/std/c/darwin.zig index 60a349868e..573f29150d 100644 --- a/zig/lib/std/c/darwin.zig +++ b/zig/lib/std/c/darwin.zig @@ -10,7 +10,7 @@ const mode_t = std.c.mode_t; const off_t = std.c.off_t; const pid_t = std.c.pid_t; const pthread_attr_t = std.c.pthread_attr_t; -const sigset_t = std.c.segset_t; +const sigset_t = std.c.sigset_t; const timespec = std.c.timespec; const sf_hdtr = std.c.sf_hdtr; @@ -23,6 +23,7 @@ pub const mach_port_t = c_uint; pub const THREAD_STATE_NONE = switch (native_arch) { .aarch64 => 5, .x86_64 => 13, + else => @compileError("unsupported arch"), }; pub const EXC = enum(exception_type_t) { diff --git a/zig/lib/std/crypto/tls.zig b/zig/lib/std/crypto/tls.zig index b3d0dcb59f..fb1b550e42 100644 --- a/zig/lib/std/crypto/tls.zig +++ b/zig/lib/std/crypto/tls.zig @@ -279,8 +279,8 @@ pub const NamedGroup = enum(u16) { ffdhe8192 = 0x0104, // Hybrid post-quantum key agreements - x25519_kyber512d00 = 0xFE30, - x25519_kyber768d00 = 0x6399, + secp256r1_ml_kem256 = 0x11EB, + x25519_ml_kem768 = 0x11EC, _, }; diff --git a/zig/lib/std/crypto/tls/Client.zig b/zig/lib/std/crypto/tls/Client.zig index 452ef5d0c5..84dbb2167a 100644 --- a/zig/lib/std/crypto/tls/Client.zig +++ b/zig/lib/std/crypto/tls/Client.zig @@ -158,7 +158,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In // Only possible to happen if the private key is all zeroes. error.IdentityElement => return error.InsufficientEntropy, }; - const kyber768_kp = crypto.kem.kyber_d00.Kyber768.KeyPair.create(null) catch {}; + const ml_kem768_kp = crypto.kem.ml_kem.MLKem768.KeyPair.create(null) catch {}; const extensions_payload = tls.extension(.supported_versions, [_]u8{ @@ -172,7 +172,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In .rsa_pss_rsae_sha512, .ed25519, })) ++ tls.extension(.supported_groups, enum_array(tls.NamedGroup, &.{ - .x25519_kyber768d00, + .x25519_ml_kem768, .secp256r1, .x25519, })) ++ tls.extension( @@ -181,8 +181,8 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In array(1, x25519_kp.public_key) ++ int2(@intFromEnum(tls.NamedGroup.secp256r1)) ++ array(1, secp256r1_kp.public_key.toUncompressedSec1()) ++ - int2(@intFromEnum(tls.NamedGroup.x25519_kyber768d00)) ++ - array(1, x25519_kp.public_key ++ kyber768_kp.public_key.toBytes())), + int2(@intFromEnum(tls.NamedGroup.x25519_ml_kem768)) ++ + array(1, x25519_kp.public_key ++ ml_kem768_kp.public_key.toBytes())), ) ++ int2(@intFromEnum(tls.ExtensionType.server_name)) ++ int2(host_len + 5) ++ // byte length of this extension payload @@ -298,9 +298,9 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In const key_size = extd.decode(u16); try extd.ensure(key_size); switch (named_group) { - .x25519_kyber768d00 => { + .x25519_ml_kem768 => { const xksl = crypto.dh.X25519.public_length; - const hksl = xksl + crypto.kem.kyber_d00.Kyber768.ciphertext_length; + const hksl = xksl + crypto.kem.ml_kem.MLKem768.ciphertext_length; if (key_size != hksl) return error.TlsIllegalParameter; const server_ks = extd.array(hksl); @@ -308,7 +308,7 @@ pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) In shared_key = &((crypto.dh.X25519.scalarmult( x25519_kp.secret_key, server_ks[0..xksl].*, - ) catch return error.TlsDecryptFailure) ++ (kyber768_kp.secret_key.decaps( + ) catch return error.TlsDecryptFailure) ++ (ml_kem768_kp.secret_key.decaps( server_ks[xksl..hksl], ) catch return error.TlsDecryptFailure)); }, diff --git a/zig/lib/std/debug.zig b/zig/lib/std/debug.zig index fd6676504f..23b005ad49 100644 --- a/zig/lib/std/debug.zig +++ b/zig/lib/std/debug.zig @@ -21,6 +21,9 @@ pub const SelfInfo = @import("debug/SelfInfo.zig"); pub const Info = @import("debug/Info.zig"); pub const Coverage = @import("debug/Coverage.zig"); +pub const FormattedPanic = @import("debug/FormattedPanic.zig"); +pub const SimplePanic = @import("debug/SimplePanic.zig"); + /// Unresolved source locations can be represented with a single `usize` that /// corresponds to a virtual memory address of the program counter. Combined /// with debug information, those values can be converted into a resolved @@ -58,6 +61,7 @@ pub const sys_can_stack_trace = switch (builtin.cpu.arch) { .mipsel, .mips64, .mips64el, + .s390x, => false, // `@returnAddress()` in LLVM 10 gives @@ -408,14 +412,21 @@ pub fn assertReadable(slice: []const volatile u8) void { for (slice) |*byte| _ = byte.*; } +/// By including a call to this function, the caller gains an error return trace +/// secret parameter, making `@errorReturnTrace()` more useful. This is not +/// necessary if the function already contains a call to an errorable function +/// elsewhere. +pub fn errorReturnTraceHelper() anyerror!void {} + +/// Equivalent to `@panic` but with a formatted message. pub fn panic(comptime format: []const u8, args: anytype) noreturn { @branchHint(.cold); - + errorReturnTraceHelper() catch unreachable; panicExtra(@errorReturnTrace(), @returnAddress(), format, args); } -/// `panicExtra` is useful when you want to print out an `@errorReturnTrace` -/// and also print out some values. +/// Equivalent to `@panic` but with a formatted message, and with an explicitly +/// provided `@errorReturnTrace` and return address. pub fn panicExtra( trace: ?*std.builtin.StackTrace, ret_addr: ?usize, @@ -436,7 +447,7 @@ pub fn panicExtra( break :blk &buf; }, }; - std.builtin.panic(msg, trace, ret_addr); + std.builtin.Panic.call(msg, trace, ret_addr); } /// Non-zero whenever the program triggered a panic. @@ -447,11 +458,70 @@ var panicking = std.atomic.Value(u8).init(0); /// This is used to catch and handle panics triggered by the panic handler. threadlocal var panic_stage: usize = 0; -// `panicImpl` could be useful in implementing a custom panic handler which -// calls the default handler (on supported platforms) -pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize, msg: []const u8) noreturn { +/// Dumps a stack trace to standard error, then aborts. +pub fn defaultPanic( + msg: []const u8, + error_return_trace: ?*const std.builtin.StackTrace, + first_trace_addr: ?usize, +) noreturn { @branchHint(.cold); + // For backends that cannot handle the language features depended on by the + // default panic handler, we have a simpler panic handler: + if (builtin.zig_backend == .stage2_wasm or + builtin.zig_backend == .stage2_arm or + builtin.zig_backend == .stage2_aarch64 or + builtin.zig_backend == .stage2_x86 or + (builtin.zig_backend == .stage2_x86_64 and (builtin.target.ofmt != .elf and builtin.target.ofmt != .macho)) or + builtin.zig_backend == .stage2_sparc64 or + builtin.zig_backend == .stage2_spirv64) + { + @trap(); + } + + switch (builtin.os.tag) { + .freestanding => { + @trap(); + }, + .uefi => { + const uefi = std.os.uefi; + + var utf16_buffer: [1000]u16 = undefined; + const len_minus_3 = std.unicode.utf8ToUtf16Le(&utf16_buffer, msg) catch 0; + utf16_buffer[len_minus_3..][0..3].* = .{ '\r', '\n', 0 }; + const len = len_minus_3 + 3; + const exit_msg = utf16_buffer[0 .. len - 1 :0]; + + // Output to both std_err and con_out, as std_err is easier + // to read in stuff like QEMU at times, but, unlike con_out, + // isn't visible on actual hardware if directly booted into + inline for ([_]?*uefi.protocol.SimpleTextOutput{ uefi.system_table.std_err, uefi.system_table.con_out }) |o| { + if (o) |out| { + _ = out.setAttribute(uefi.protocol.SimpleTextOutput.red); + _ = out.outputString(exit_msg); + _ = out.setAttribute(uefi.protocol.SimpleTextOutput.white); + } + } + + if (uefi.system_table.boot_services) |bs| { + // ExitData buffer must be allocated using boot_services.allocatePool (spec: page 220) + const exit_data: []u16 = uefi.raw_pool_allocator.alloc(u16, exit_msg.len + 1) catch @trap(); + @memcpy(exit_data, exit_msg[0..exit_data.len]); // Includes null terminator. + _ = bs.exit(uefi.handle, .Aborted, exit_data.len, exit_data.ptr); + } + @trap(); + }, + .cuda, .amdhsa => std.posix.abort(), + .plan9 => { + var status: [std.os.plan9.ERRMAX]u8 = undefined; + const len = @min(msg.len, status.len - 1); + @memcpy(status[0..len], msg[0..len]); + status[len] = 0; + std.os.plan9.exits(status[0..len :0]); + }, + else => {}, + } + if (enable_segfault_handler) { // If a segfault happens while panicking, we want it to actually segfault, not trigger // the handler. @@ -465,7 +535,6 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize _ = panicking.fetchAdd(1, .seq_cst); - // Make sure to release the mutex when done { lockStdErr(); defer unlockStdErr(); @@ -478,10 +547,9 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize stderr.print("thread {} panic: ", .{current_thread_id}) catch posix.abort(); } stderr.print("{s}\n", .{msg}) catch posix.abort(); - if (trace) |t| { - dumpStackTrace(t.*); - } - dumpCurrentStackTrace(first_trace_addr); + + if (error_return_trace) |t| dumpStackTrace(t.*); + dumpCurrentStackTrace(first_trace_addr orelse @returnAddress()); } waitForOtherThreadToFinishPanicking(); @@ -489,15 +557,12 @@ pub fn panicImpl(trace: ?*const std.builtin.StackTrace, first_trace_addr: ?usize 1 => { panic_stage = 2; - // A panic happened while trying to print a previous panic message, - // we're still holding the mutex but that's fine as we're going to - // call abort() - const stderr = io.getStdErr().writer(); - stderr.print("Panicked during a panic. Aborting.\n", .{}) catch posix.abort(); - }, - else => { - // Panicked while printing "Panicked during a panic." + // A panic happened while trying to print a previous panic message. + // We're still holding the mutex but that's fine as we're going to + // call abort(). + io.getStdErr().writeAll("aborting due to recursive panic\n") catch {}; }, + else => {}, // Panicked while printing the recursive panic message. }; posix.abort(); @@ -1157,7 +1222,7 @@ pub const default_enable_segfault_handler = runtime_safety and have_segfault_han pub fn maybeEnableSegfaultHandler() void { if (enable_segfault_handler) { - std.debug.attachSegfaultHandler(); + attachSegfaultHandler(); } } @@ -1289,46 +1354,29 @@ fn handleSegfaultWindows(info: *windows.EXCEPTION_POINTERS) callconv(windows.WIN } } -fn handleSegfaultWindowsExtra( - info: *windows.EXCEPTION_POINTERS, - msg: u8, - label: ?[]const u8, -) noreturn { - const exception_address = @intFromPtr(info.ExceptionRecord.ExceptionAddress); - if (windows.CONTEXT != void) { - nosuspend switch (panic_stage) { - 0 => { - panic_stage = 1; - _ = panicking.fetchAdd(1, .seq_cst); - - { - lockStdErr(); - defer unlockStdErr(); - - dumpSegfaultInfoWindows(info, msg, label); - } +fn handleSegfaultWindowsExtra(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) noreturn { + comptime assert(windows.CONTEXT != void); + nosuspend switch (panic_stage) { + 0 => { + panic_stage = 1; + _ = panicking.fetchAdd(1, .seq_cst); + + { + lockStdErr(); + defer unlockStdErr(); - waitForOtherThreadToFinishPanicking(); - }, - else => { - // panic mutex already locked dumpSegfaultInfoWindows(info, msg, label); - }, - }; - posix.abort(); - } else { - switch (msg) { - 0 => panicImpl(null, exception_address, "{s}", label.?), - 1 => { - const format_item = "Segmentation fault at address 0x{x}"; - var buf: [format_item.len + 64]u8 = undefined; // 64 is arbitrary, but sufficiently large - const to_print = std.fmt.bufPrint(buf[0..buf.len], format_item, .{info.ExceptionRecord.ExceptionInformation[1]}) catch unreachable; - panicImpl(null, exception_address, to_print); - }, - 2 => panicImpl(null, exception_address, "Illegal Instruction"), - else => unreachable, - } - } + } + + waitForOtherThreadToFinishPanicking(); + }, + 1 => { + panic_stage = 2; + io.getStdErr().writeAll("aborting due to recursive panic\n") catch {}; + }, + else => {}, + }; + posix.abort(); } fn dumpSegfaultInfoWindows(info: *windows.EXCEPTION_POINTERS, msg: u8, label: ?[]const u8) void { @@ -1347,7 +1395,7 @@ pub fn dumpStackPointerAddr(prefix: []const u8) void { const sp = asm ("" : [argc] "={rsp}" (-> usize), ); - std.debug.print("{s} sp = 0x{x}\n", .{ prefix, sp }); + print("{s} sp = 0x{x}\n", .{ prefix, sp }); } test "manage resources correctly" { diff --git a/zig/lib/std/debug/FormattedPanic.zig b/zig/lib/std/debug/FormattedPanic.zig new file mode 100644 index 0000000000..0ad6ea696c --- /dev/null +++ b/zig/lib/std/debug/FormattedPanic.zig @@ -0,0 +1,45 @@ +//! This namespace is the default one used by the Zig compiler to emit various +//! kinds of safety panics, due to the logic in `std.builtin.Panic`. +//! +//! Since Zig does not have interfaces, this file serves as an example template +//! for users to provide their own alternative panic handling. +//! +//! As an alternative, see `std.debug.SimplePanic`. + +const std = @import("../std.zig"); + +/// Dumps a stack trace to standard error, then aborts. +/// +/// Explicit calls to `@panic` lower to calling this function. +pub const call: fn ([]const u8, ?*std.builtin.StackTrace, ?usize) noreturn = std.debug.defaultPanic; + +pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { + @branchHint(.cold); + std.debug.panicExtra(null, @returnAddress(), "sentinel mismatch: expected {any}, found {any}", .{ + expected, found, + }); +} + +pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { + @branchHint(.cold); + std.debug.panicExtra(ert, @returnAddress(), "attempt to unwrap error: {s}", .{@errorName(err)}); +} + +pub fn outOfBounds(index: usize, len: usize) noreturn { + @branchHint(.cold); + std.debug.panicExtra(null, @returnAddress(), "index out of bounds: index {d}, len {d}", .{ index, len }); +} + +pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { + @branchHint(.cold); + std.debug.panicExtra(null, @returnAddress(), "start index {d} is larger than end index {d}", .{ start, end }); +} + +pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { + @branchHint(.cold); + std.debug.panicExtra(null, @returnAddress(), "access of union field '{s}' while field '{s}' is active", .{ + @tagName(accessed), @tagName(active), + }); +} + +pub const messages = std.debug.SimplePanic.messages; diff --git a/zig/lib/std/debug/SimplePanic.zig b/zig/lib/std/debug/SimplePanic.zig new file mode 100644 index 0000000000..9685642a5c --- /dev/null +++ b/zig/lib/std/debug/SimplePanic.zig @@ -0,0 +1,86 @@ +//! This namespace is the default one used by the Zig compiler to emit various +//! kinds of safety panics, due to the logic in `std.builtin.Panic`. +//! +//! Since Zig does not have interfaces, this file serves as an example template +//! for users to provide their own alternative panic handling. +//! +//! As an alternative, see `std.debug.FormattedPanic`. + +const std = @import("../std.zig"); + +/// Prints the message to stderr without a newline and then traps. +/// +/// Explicit calls to `@panic` lower to calling this function. +pub fn call(msg: []const u8, ert: ?*std.builtin.StackTrace, ra: ?usize) noreturn { + @branchHint(.cold); + _ = ert; + _ = ra; + std.debug.lockStdErr(); + const stderr = std.io.getStdErr(); + stderr.writeAll(msg) catch {}; + @trap(); +} + +pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { + _ = found; + call("sentinel mismatch", null, null); +} + +pub fn unwrapError(ert: ?*std.builtin.StackTrace, err: anyerror) noreturn { + _ = ert; + _ = &err; + call("attempt to unwrap error", null, null); +} + +pub fn outOfBounds(index: usize, len: usize) noreturn { + _ = index; + _ = len; + call("index out of bounds", null, null); +} + +pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { + _ = start; + _ = end; + call("start index is larger than end index", null, null); +} + +pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { + _ = accessed; + call("access of inactive union field", null, null); +} + +pub const messages = struct { + pub const reached_unreachable = "reached unreachable code"; + pub const unwrap_null = "attempt to use null value"; + pub const cast_to_null = "cast causes pointer to be null"; + pub const incorrect_alignment = "incorrect alignment"; + pub const invalid_error_code = "invalid error code"; + pub const cast_truncated_data = "integer cast truncated bits"; + pub const negative_to_unsigned = "attempt to cast negative value to unsigned integer"; + pub const integer_overflow = "integer overflow"; + pub const shl_overflow = "left shift overflowed bits"; + pub const shr_overflow = "right shift overflowed bits"; + pub const divide_by_zero = "division by zero"; + pub const exact_division_remainder = "exact division produced remainder"; + pub const integer_part_out_of_bounds = "integer part of floating point value out of bounds"; + pub const corrupt_switch = "switch on corrupt value"; + pub const shift_rhs_too_big = "shift amount is greater than the type size"; + pub const invalid_enum_value = "invalid enum value"; + pub const for_len_mismatch = "for loop over objects with non-equal lengths"; + pub const memcpy_len_mismatch = "@memcpy arguments have non-equal lengths"; + pub const memcpy_alias = "@memcpy arguments alias"; + pub const noreturn_returned = "'noreturn' function returned"; + + /// To be deleted after zig1.wasm is updated. + pub const inactive_union_field = "access of inactive union field"; + /// To be deleted after zig1.wasm is updated. + pub const sentinel_mismatch = "sentinel mismatch"; + /// To be deleted after zig1.wasm is updated. + pub const unwrap_error = "attempt to unwrap error"; + /// To be deleted after zig1.wasm is updated. + pub const index_out_of_bounds = "index out of bounds"; + /// To be deleted after zig1.wasm is updated. + pub const start_index_greater_than_end = "start index is larger than end index"; + /// To be deleted after zig1.wasm is updated. + pub const unreach = reached_unreachable; +}; diff --git a/zig/lib/std/elf.zig b/zig/lib/std/elf.zig index d92973c314..792694dffb 100644 --- a/zig/lib/std/elf.zig +++ b/zig/lib/std/elf.zig @@ -453,18 +453,27 @@ pub const ET = enum(u16) { /// Core file CORE = 4, + /// Beginning of OS-specific codes + pub const LOOS = 0xfe00; + + /// End of OS-specific codes + pub const HIOS = 0xfeff; + /// Beginning of processor-specific codes pub const LOPROC = 0xff00; - /// Processor-specific + /// End of processor-specific codes pub const HIPROC = 0xffff; }; /// All integers are native endian. pub const Header = struct { + is_64: bool, endian: std.builtin.Endian, + os_abi: OSABI, + abi_version: u8, + type: ET, machine: EM, - is_64: bool, entry: u64, phoff: u64, shoff: u64, @@ -501,6 +510,12 @@ pub const Header = struct { if (!mem.eql(u8, hdr32.e_ident[0..4], MAGIC)) return error.InvalidElfMagic; if (hdr32.e_ident[EI_VERSION] != 1) return error.InvalidElfVersion; + const is_64 = switch (hdr32.e_ident[EI_CLASS]) { + ELFCLASS32 => false, + ELFCLASS64 => true, + else => return error.InvalidElfClass, + }; + const endian: std.builtin.Endian = switch (hdr32.e_ident[EI_DATA]) { ELFDATA2LSB => .little, ELFDATA2MSB => .big, @@ -508,11 +523,15 @@ pub const Header = struct { }; const need_bswap = endian != native_endian; - const is_64 = switch (hdr32.e_ident[EI_CLASS]) { - ELFCLASS32 => false, - ELFCLASS64 => true, - else => return error.InvalidElfClass, - }; + const os_abi: OSABI = @enumFromInt(hdr32.e_ident[EI_OSABI]); + + // The meaning of this value depends on `os_abi` so just make it available as `u8`. + const abi_version = hdr32.e_ident[EI_ABIVERSION]; + + const @"type" = if (need_bswap) blk: { + const value = @intFromEnum(hdr32.e_type); + break :blk @as(ET, @enumFromInt(@byteSwap(value))); + } else hdr32.e_type; const machine = if (need_bswap) blk: { const value = @intFromEnum(hdr32.e_machine); @@ -520,9 +539,12 @@ pub const Header = struct { } else hdr32.e_machine; return @as(Header, .{ + .is_64 = is_64, .endian = endian, + .os_abi = os_abi, + .abi_version = abi_version, + .type = @"type", .machine = machine, - .is_64 = is_64, .entry = int(is_64, need_bswap, hdr32.e_entry, hdr64.e_entry), .phoff = int(is_64, need_bswap, hdr32.e_phoff, hdr64.e_phoff), .shoff = int(is_64, need_bswap, hdr32.e_shoff, hdr64.e_shoff), @@ -637,7 +659,7 @@ pub fn SectionHeaderIterator(comptime ParseSource: anytype) type { }; } -pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { +fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @TypeOf(int_64) { if (is_64) { if (need_bswap) { return @byteSwap(int_64); @@ -649,7 +671,7 @@ pub fn int(is_64: bool, need_bswap: bool, int_32: anytype, int_64: anytype) @Typ } } -pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { +fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { if (need_bswap) { return @byteSwap(int_32); } else { @@ -657,21 +679,24 @@ pub fn int32(need_bswap: bool, int_32: anytype, comptime Int64: anytype) Int64 { } } -pub const EI_NIDENT = 16; - -pub const EI_CLASS = 4; pub const ELFCLASSNONE = 0; pub const ELFCLASS32 = 1; pub const ELFCLASS64 = 2; pub const ELFCLASSNUM = 3; -pub const EI_DATA = 5; pub const ELFDATANONE = 0; pub const ELFDATA2LSB = 1; pub const ELFDATA2MSB = 2; pub const ELFDATANUM = 3; +pub const EI_CLASS = 4; +pub const EI_DATA = 5; pub const EI_VERSION = 6; +pub const EI_OSABI = 7; +pub const EI_ABIVERSION = 8; +pub const EI_PAD = 9; + +pub const EI_NIDENT = 16; pub const Elf32_Half = u16; pub const Elf64_Half = u16; @@ -1094,6 +1119,57 @@ pub const Addr = switch (@sizeOf(usize)) { }; pub const Half = u16; +pub const OSABI = enum(u8) { + /// UNIX System V ABI + NONE = 0, + /// HP-UX operating system + HPUX = 1, + /// NetBSD + NETBSD = 2, + /// GNU (Hurd/Linux) + GNU = 3, + /// Solaris + SOLARIS = 6, + /// AIX + AIX = 7, + /// IRIX + IRIX = 8, + /// FreeBSD + FREEBSD = 9, + /// TRU64 UNIX + TRU64 = 10, + /// Novell Modesto + MODESTO = 11, + /// OpenBSD + OPENBSD = 12, + /// OpenVMS + OPENVMS = 13, + /// Hewlett-Packard Non-Stop Kernel + NSK = 14, + /// AROS + AROS = 15, + /// FenixOS + FENIXOS = 16, + /// Nuxi CloudABI + CLOUDABI = 17, + /// Stratus Technologies OpenVOS + OPENVOS = 18, + /// NVIDIA CUDA architecture + CUDA = 51, + /// AMD HSA Runtime + AMDGPU_HSA = 64, + /// AMD PAL Runtime + AMDGPU_PAL = 65, + /// AMD Mesa3D Runtime + AMDGPU_MESA3D = 66, + /// ARM + ARM = 97, + /// Standalone (embedded) application + STANDALONE = 255, + + _, +}; + /// Machine architectures. /// /// See current registered ELF machine architectures at: @@ -1552,6 +1628,14 @@ pub const EM = enum(u16) { /// Adapteva's Epiphany architecture ADAPTEVA_EPIPHANY = 0x1223, + /// Parallax Propeller (P1) + /// This value is an unofficial ELF value used in: https://github.com/parallaxinc/propgcc + PROPELLER = 0x5072, + + /// Parallax Propeller 2 (P2) + /// This value is an unofficial ELF value used in: https://github.com/ne75/llvm-project + PROPELLER2 = 300, + _, }; diff --git a/zig/lib/std/fmt.zig b/zig/lib/std/fmt.zig index 12504b6872..123122fd56 100644 --- a/zig/lib/std/fmt.zig +++ b/zig/lib/std/fmt.zig @@ -1197,7 +1197,7 @@ pub fn formatInt( if (base == 10) { while (a >= 100) : (a = @divTrunc(a, 100)) { index -= 2; - buf[index..][0..2].* = digits2(@as(usize, @intCast(a % 100))); + buf[index..][0..2].* = digits2(@intCast(a % 100)); } if (a < 10) { @@ -1205,13 +1205,13 @@ pub fn formatInt( buf[index] = '0' + @as(u8, @intCast(a)); } else { index -= 2; - buf[index..][0..2].* = digits2(@as(usize, @intCast(a))); + buf[index..][0..2].* = digits2(@intCast(a)); } } else { while (true) { const digit = a % base; index -= 1; - buf[index] = digitToChar(@as(u8, @intCast(digit)), case); + buf[index] = digitToChar(@intCast(digit), case); a /= base; if (a == 0) break; } @@ -1242,11 +1242,7 @@ pub fn formatIntBuf(out_buf: []u8, value: anytype, base: u8, case: Case, options // Converts values in the range [0, 100) to a string. pub fn digits2(value: usize) [2]u8 { - return ("0001020304050607080910111213141516171819" ++ - "2021222324252627282930313233343536373839" ++ - "4041424344454647484950515253545556575859" ++ - "6061626364656667686970717273747576777879" ++ - "8081828384858687888990919293949596979899")[value * 2 ..][0..2].*; + return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*; } const FormatDurationData = struct { diff --git a/zig/lib/std/fs/Dir.zig b/zig/lib/std/fs/Dir.zig index 2e84d1097f..d504ecb0c4 100644 --- a/zig/lib/std/fs/Dir.zig +++ b/zig/lib/std/fs/Dir.zig @@ -804,11 +804,14 @@ pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.Ope } if (native_os == .wasi and !builtin.link_libc) { var base: std.os.wasi.rights_t = .{}; + // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or FD_WRITE + // is also set. if (flags.isRead()) { base.FD_READ = true; base.FD_TELL = true; base.FD_SEEK = true; base.FD_FILESTAT_GET = true; + base.POLL_FD_READWRITE = true; } if (flags.isWrite()) { base.FD_WRITE = true; @@ -821,6 +824,7 @@ pub fn openFile(self: Dir, sub_path: []const u8, flags: File.OpenFlags) File.Ope base.FD_ADVISE = true; base.FD_FILESTAT_SET_TIMES = true; base.FD_FILESTAT_SET_SIZE = true; + base.POLL_FD_READWRITE = true; } const fd = try posix.openatWasi(self.fd, sub_path, .{}, .{}, .{}, base, .{}); return .{ .handle = fd }; @@ -982,6 +986,9 @@ pub fn createFile(self: Dir, sub_path: []const u8, flags: File.CreateFlags) File .FD_FILESTAT_SET_TIMES = true, .FD_FILESTAT_SET_SIZE = true, .FD_FILESTAT_GET = true, + // POLL_FD_READWRITE only grants extra rights if the corresponding FD_READ and/or + // FD_WRITE is also set. + .POLL_FD_READWRITE = true, }, .{}), }; } diff --git a/zig/lib/std/fs/test.zig b/zig/lib/std/fs/test.zig index b0810f81a5..618323dce3 100644 --- a/zig/lib/std/fs/test.zig +++ b/zig/lib/std/fs/test.zig @@ -1647,6 +1647,36 @@ test "open file with exclusive nonblocking lock twice (absolute paths)" { try testing.expectError(error.WouldBlock, file2); } +test "read from locked file" { + try testWithAllSupportedPathTypes(struct { + fn impl(ctx: *TestContext) !void { + const filename = try ctx.transformPath("read_lock_file_test.txt"); + + { + const f = try ctx.dir.createFile(filename, .{ .read = true }); + defer f.close(); + var buffer: [1]u8 = undefined; + _ = try f.readAll(&buffer); + } + { + const f = try ctx.dir.createFile(filename, .{ + .read = true, + .lock = .exclusive, + }); + defer f.close(); + const f2 = try ctx.dir.openFile(filename, .{}); + defer f2.close(); + var buffer: [1]u8 = undefined; + if (builtin.os.tag == .windows) { + try std.testing.expectError(error.LockViolation, f2.readAll(&buffer)); + } else { + try std.testing.expectEqual(0, f2.readAll(&buffer)); + } + } + } + }.impl); +} + test "walker" { if (native_os == .wasi and builtin.link_libc) return error.SkipZigTest; diff --git a/zig/lib/std/heap.zig b/zig/lib/std/heap.zig index 18332c79a8..3d19d8daa6 100644 --- a/zig/lib/std/heap.zig +++ b/zig/lib/std/heap.zig @@ -501,8 +501,6 @@ pub const FixedBufferAllocator = struct { } }; -pub const ThreadSafeFixedBufferAllocator = @compileError("ThreadSafeFixedBufferAllocator has been replaced with `threadSafeAllocator` on FixedBufferAllocator"); - /// Returns a `StackFallbackAllocator` allocating using either a /// `FixedBufferAllocator` on an array of size `size` and falling back to /// `fallback_allocator` if that fails. diff --git a/zig/lib/std/http/test.zig b/zig/lib/std/http/test.zig index caeed0e1ea..dc944fbabb 100644 --- a/zig/lib/std/http/test.zig +++ b/zig/lib/std/http/test.zig @@ -230,6 +230,11 @@ test "echo content server" { } test "Server.Request.respondStreaming non-chunked, unknown content-length" { + if (builtin.os.tag == .windows) { + // https://github.com/ziglang/zig/issues/21457 + return error.SkipZigTest; + } + // In this case, the response is expected to stream until the connection is // closed, indicating the end of the body. const test_server = try createTestServer(struct { diff --git a/zig/lib/std/io.zig b/zig/lib/std/io.zig index 6455693d67..0a9b2bf867 100644 --- a/zig/lib/std/io.zig +++ b/zig/lib/std/io.zig @@ -442,6 +442,7 @@ pub fn poll( .overlapped = [1]windows.OVERLAPPED{ mem.zeroes(windows.OVERLAPPED), } ** enum_fields.len, + .small_bufs = undefined, .active = .{ .count = 0, .handles_buf = undefined, @@ -481,6 +482,7 @@ pub fn Poller(comptime StreamEnum: type) type { windows: if (is_windows) struct { first_read_done: bool, overlapped: [enum_fields.len]windows.OVERLAPPED, + small_bufs: [enum_fields.len][128]u8, active: struct { count: math.IntFittingRange(0, enum_fields.len), handles_buf: [enum_fields.len]windows.HANDLE, @@ -534,24 +536,31 @@ pub fn Poller(comptime StreamEnum: type) type { const bump_amt = 512; if (!self.windows.first_read_done) { - // Windows Async IO requires an initial call to ReadFile before waiting on the handle + var already_read_data = false; for (0..enum_fields.len) |i| { const handle = self.windows.active.handles_buf[i]; - switch (try windowsAsyncRead( + switch (try windowsAsyncReadToFifoAndQueueSmallRead( handle, &self.windows.overlapped[i], &self.fifos[i], + &self.windows.small_bufs[i], bump_amt, )) { - .pending => { + .populated, .empty => |state| { + if (state == .populated) already_read_data = true; self.windows.active.handles_buf[self.windows.active.count] = handle; self.windows.active.stream_map[self.windows.active.count] = @as(StreamEnum, @enumFromInt(i)); self.windows.active.count += 1; }, .closed => {}, // don't add to the wait_objects list + .closed_populated => { + // don't add to the wait_objects list, but we did already get data + already_read_data = true; + }, } } self.windows.first_read_done = true; + if (already_read_data) return true; } while (true) { @@ -576,32 +585,35 @@ pub fn Poller(comptime StreamEnum: type) type { const active_idx = status - windows.WAIT_OBJECT_0; - const handle = self.windows.active.handles_buf[active_idx]; const stream_idx = @intFromEnum(self.windows.active.stream_map[active_idx]); - var read_bytes: u32 = undefined; - if (0 == windows.kernel32.GetOverlappedResult( - handle, - &self.windows.overlapped[stream_idx], - &read_bytes, - 0, - )) switch (windows.GetLastError()) { - .BROKEN_PIPE => { + const handle = self.windows.active.handles_buf[active_idx]; + + const overlapped = &self.windows.overlapped[stream_idx]; + const stream_fifo = &self.fifos[stream_idx]; + const small_buf = &self.windows.small_bufs[stream_idx]; + + const num_bytes_read = switch (try windowsGetReadResult(handle, overlapped, false)) { + .success => |n| n, + .closed => { self.windows.active.removeAt(active_idx); continue; }, - else => |err| return windows.unexpectedError(err), + .aborted => unreachable, }; + try stream_fifo.write(small_buf[0..num_bytes_read]); - self.fifos[stream_idx].update(read_bytes); - - switch (try windowsAsyncRead( + switch (try windowsAsyncReadToFifoAndQueueSmallRead( handle, - &self.windows.overlapped[stream_idx], - &self.fifos[stream_idx], + overlapped, + stream_fifo, + small_buf, bump_amt, )) { - .pending => {}, - .closed => self.windows.active.removeAt(active_idx), + .empty => {}, // irrelevant, we already got data from the small buffer + .populated => {}, + .closed, + .closed_populated, // identical, since we already got data from the small buffer + => self.windows.active.removeAt(active_idx), } return true; } @@ -654,25 +666,145 @@ pub fn Poller(comptime StreamEnum: type) type { }; } -fn windowsAsyncRead( +/// The `ReadFile` docuementation states that `lpNumberOfBytesRead` does not have a meaningful +/// result when using overlapped I/O, but also that it cannot be `null` on Windows 7. For +/// compatibility, we point it to this dummy variables, which we never otherwise access. +/// See: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile +var win_dummy_bytes_read: u32 = undefined; + +/// Read as much data as possible from `handle` with `overlapped`, and write it to the FIFO. Before +/// returning, queue a read into `small_buf` so that `WaitForMultipleObjects` returns when more data +/// is available. `handle` must have no pending asynchronous operation. +fn windowsAsyncReadToFifoAndQueueSmallRead( handle: windows.HANDLE, overlapped: *windows.OVERLAPPED, fifo: *PollFifo, + small_buf: *[128]u8, bump_amt: usize, -) !enum { pending, closed } { +) !enum { empty, populated, closed_populated, closed } { + var read_any_data = false; while (true) { - const buf = try fifo.writableWithSize(bump_amt); - var read_bytes: u32 = undefined; - const read_result = windows.kernel32.ReadFile(handle, buf.ptr, math.cast(u32, buf.len) orelse math.maxInt(u32), &read_bytes, overlapped); - if (read_result == 0) return switch (windows.GetLastError()) { - .IO_PENDING => .pending, - .BROKEN_PIPE => .closed, - else => |err| windows.unexpectedError(err), + const fifo_read_pending = while (true) { + const buf = try fifo.writableWithSize(bump_amt); + const buf_len = math.cast(u32, buf.len) orelse math.maxInt(u32); + + if (0 == windows.kernel32.ReadFile( + handle, + buf.ptr, + buf_len, + &win_dummy_bytes_read, + overlapped, + )) switch (windows.GetLastError()) { + .IO_PENDING => break true, + .BROKEN_PIPE => return if (read_any_data) .closed_populated else .closed, + else => |err| return windows.unexpectedError(err), + }; + + const num_bytes_read = switch (try windowsGetReadResult(handle, overlapped, false)) { + .success => |n| n, + .closed => return if (read_any_data) .closed_populated else .closed, + .aborted => unreachable, + }; + + read_any_data = true; + fifo.update(num_bytes_read); + + if (num_bytes_read == buf_len) { + // We filled the buffer, so there's probably more data available. + continue; + } else { + // We didn't fill the buffer, so assume we're out of data. + // There is no pending read. + break false; + } }; - fifo.update(read_bytes); + + if (fifo_read_pending) cancel_read: { + // Cancel the pending read into the FIFO. + _ = windows.kernel32.CancelIo(handle); + + // We have to wait for the handle to be signalled, i.e. for the cancellation to complete. + switch (windows.kernel32.WaitForSingleObject(handle, windows.INFINITE)) { + windows.WAIT_OBJECT_0 => {}, + windows.WAIT_FAILED => return windows.unexpectedError(windows.GetLastError()), + else => unreachable, + } + + // If it completed before we canceled, make sure to tell the FIFO! + const num_bytes_read = switch (try windowsGetReadResult(handle, overlapped, true)) { + .success => |n| n, + .closed => return if (read_any_data) .closed_populated else .closed, + .aborted => break :cancel_read, + }; + read_any_data = true; + fifo.update(num_bytes_read); + } + + // Try to queue the 1-byte read. + if (0 == windows.kernel32.ReadFile( + handle, + small_buf, + small_buf.len, + &win_dummy_bytes_read, + overlapped, + )) switch (windows.GetLastError()) { + .IO_PENDING => { + // 1-byte read pending as intended + return if (read_any_data) .populated else .empty; + }, + .BROKEN_PIPE => return if (read_any_data) .closed_populated else .closed, + else => |err| return windows.unexpectedError(err), + }; + + // We got data back this time. Write it to the FIFO and run the main loop again. + const num_bytes_read = switch (try windowsGetReadResult(handle, overlapped, false)) { + .success => |n| n, + .closed => return if (read_any_data) .closed_populated else .closed, + .aborted => unreachable, + }; + try fifo.write(small_buf[0..num_bytes_read]); + read_any_data = true; } } +/// Simple wrapper around `GetOverlappedResult` to determine the result of a `ReadFile` operation. +/// If `!allow_aborted`, then `aborted` is never returned (`OPERATION_ABORTED` is considered unexpected). +/// +/// The `ReadFile` documentation states that the number of bytes read by an overlapped `ReadFile` must be determined using `GetOverlappedResult`, even if the +/// operation immediately returns data: +/// "Use NULL for [lpNumberOfBytesRead] if this is an asynchronous operation to avoid potentially +/// erroneous results." +/// "If `hFile` was opened with `FILE_FLAG_OVERLAPPED`, the following conditions are in effect: [...] +/// The lpNumberOfBytesRead parameter should be set to NULL. Use the GetOverlappedResult function to +/// get the actual number of bytes read." +/// See: https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-readfile +fn windowsGetReadResult( + handle: windows.HANDLE, + overlapped: *windows.OVERLAPPED, + allow_aborted: bool, +) !union(enum) { + success: u32, + closed, + aborted, +} { + var num_bytes_read: u32 = undefined; + if (0 == windows.kernel32.GetOverlappedResult( + handle, + overlapped, + &num_bytes_read, + 0, + )) switch (windows.GetLastError()) { + .BROKEN_PIPE => return .closed, + .OPERATION_ABORTED => |err| if (allow_aborted) { + return .aborted; + } else { + return windows.unexpectedError(err); + }, + else => |err| return windows.unexpectedError(err), + }; + return .{ .success = num_bytes_read }; +} + /// Given an enum, returns a struct with fields of that enum, each field /// representing an I/O stream for polling. pub fn PollFiles(comptime StreamEnum: type) type { diff --git a/zig/lib/std/io/Reader/test.zig b/zig/lib/std/io/Reader/test.zig index e92d1ec4db..30f0e1269c 100644 --- a/zig/lib/std/io/Reader/test.zig +++ b/zig/lib/std/io/Reader/test.zig @@ -1,3 +1,4 @@ +const builtin = @import("builtin"); const std = @import("../../std.zig"); const testing = std.testing; @@ -11,7 +12,7 @@ test "Reader" { b = 99, c = 2, d = 3, - }, undefined)) == .c); + }, builtin.cpu.arch.endian())) == .c); try testing.expectError(error.EndOfStream, reader.readByte()); } diff --git a/zig/lib/std/io/buffered_reader.zig b/zig/lib/std/io/buffered_reader.zig index ca132202a7..bcf54fb882 100644 --- a/zig/lib/std/io/buffered_reader.zig +++ b/zig/lib/std/io/buffered_reader.zig @@ -17,26 +17,27 @@ pub fn BufferedReader(comptime buffer_size: usize, comptime ReaderType: type) ty const Self = @This(); pub fn read(self: *Self, dest: []u8) Error!usize { - var dest_index: usize = 0; - - while (dest_index < dest.len) { - const written = @min(dest.len - dest_index, self.end - self.start); - @memcpy(dest[dest_index..][0..written], self.buf[self.start..][0..written]); - if (written == 0) { - // buf empty, fill it - const n = try self.unbuffered_reader.read(self.buf[0..]); - if (n == 0) { - // reading from the unbuffered stream returned nothing - // so we have nothing left to read. - return dest_index; - } - self.start = 0; - self.end = n; - } - self.start += written; - dest_index += written; + // First try reading from the already buffered data onto the destination. + const current = self.buf[self.start..self.end]; + if (current.len != 0) { + const to_transfer = @min(current.len, dest.len); + @memcpy(dest[0..to_transfer], current[0..to_transfer]); + self.start += to_transfer; + return to_transfer; } - return dest.len; + + // If dest is large, read from the unbuffered reader directly into the destination. + if (dest.len >= buffer_size) { + return self.unbuffered_reader.read(dest); + } + + // If dest is small, read from the unbuffered reader into our own internal buffer, + // and then transfer to destination. + self.end = try self.unbuffered_reader.read(&self.buf); + const to_transfer = @min(self.end, dest.len); + @memcpy(dest[0..to_transfer], self.buf[0..to_transfer]); + self.start = to_transfer; + return to_transfer; } pub fn reader(self: *Self) Reader { @@ -134,12 +135,13 @@ test "Block" { var test_buf_reader: BufferedReader(4, BlockReader) = .{ .unbuffered_reader = BlockReader.init(block, 2), }; + const reader = test_buf_reader.reader(); var out_buf: [4]u8 = undefined; - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, block); - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, block); - try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); + try testing.expectEqual(try reader.readAll(&out_buf), 0); } // len out < block @@ -147,14 +149,15 @@ test "Block" { var test_buf_reader: BufferedReader(4, BlockReader) = .{ .unbuffered_reader = BlockReader.init(block, 2), }; + const reader = test_buf_reader.reader(); var out_buf: [3]u8 = undefined; - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, "012"); - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, "301"); - const n = try test_buf_reader.read(&out_buf); + const n = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, out_buf[0..n], "23"); - try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); + try testing.expectEqual(try reader.readAll(&out_buf), 0); } // len out > block @@ -162,12 +165,13 @@ test "Block" { var test_buf_reader: BufferedReader(4, BlockReader) = .{ .unbuffered_reader = BlockReader.init(block, 2), }; + const reader = test_buf_reader.reader(); var out_buf: [5]u8 = undefined; - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, "01230"); - const n = try test_buf_reader.read(&out_buf); + const n = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, out_buf[0..n], "123"); - try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); + try testing.expectEqual(try reader.readAll(&out_buf), 0); } // len out == 0 @@ -175,8 +179,9 @@ test "Block" { var test_buf_reader: BufferedReader(4, BlockReader) = .{ .unbuffered_reader = BlockReader.init(block, 2), }; + const reader = test_buf_reader.reader(); var out_buf: [0]u8 = undefined; - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, ""); } @@ -185,11 +190,12 @@ test "Block" { var test_buf_reader: BufferedReader(5, BlockReader) = .{ .unbuffered_reader = BlockReader.init(block, 2), }; + const reader = test_buf_reader.reader(); var out_buf: [4]u8 = undefined; - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, block); - _ = try test_buf_reader.read(&out_buf); + _ = try reader.readAll(&out_buf); try testing.expectEqualSlices(u8, &out_buf, block); - try testing.expectEqual(try test_buf_reader.read(&out_buf), 0); + try testing.expectEqual(try reader.readAll(&out_buf), 0); } } diff --git a/zig/lib/std/math/float.zig b/zig/lib/std/math/float.zig index a10332f863..b7269b3ba9 100644 --- a/zig/lib/std/math/float.zig +++ b/zig/lib/std/math/float.zig @@ -172,9 +172,6 @@ test nan { } test snan { - // TODO: https://github.com/ziglang/zig/issues/14366 - if (builtin.zig_backend == .stage2_llvm and comptime builtin.cpu.arch.isArmOrThumb()) return error.SkipZigTest; - const snan_u16: u16 = 0x7D00; const snan_u32: u32 = 0x7FA00000; const snan_u64: u64 = 0x7FF4000000000000; diff --git a/zig/lib/std/math/gcd.zig b/zig/lib/std/math/gcd.zig index 36ba8e3614..16ca7846f1 100644 --- a/zig/lib/std/math/gcd.zig +++ b/zig/lib/std/math/gcd.zig @@ -1,41 +1,50 @@ //! Greatest common divisor (https://mathworld.wolfram.com/GreatestCommonDivisor.html) const std = @import("std"); -const expectEqual = std.testing.expectEqual; -/// Returns the greatest common divisor (GCD) of two unsigned integers (a and b) which are not both zero. -/// For example, the GCD of 8 and 12 is 4, that is, gcd(8, 12) == 4. +/// Returns the greatest common divisor (GCD) of two unsigned integers (`a` and `b`) which are not both zero. +/// For example, the GCD of `8` and `12` is `4`, that is, `gcd(8, 12) == 4`. pub fn gcd(a: anytype, b: anytype) @TypeOf(a, b) { - - // only unsigned integers are allowed and not both must be zero - comptime switch (@typeInfo(@TypeOf(a, b))) { - .int => |int| std.debug.assert(int.signedness == .unsigned), - .comptime_int => { - std.debug.assert(a >= 0); - std.debug.assert(b >= 0); - }, - else => unreachable, + const N = switch (@TypeOf(a, b)) { + // convert comptime_int to some sized int type for @ctz + comptime_int => std.math.IntFittingRange(@min(a, b), @max(a, b)), + else => |T| T, }; + if (@typeInfo(N) != .int or @typeInfo(N).int.signedness != .unsigned) { + @compileError("`a` and `b` must be usigned integers"); + } + + // using an optimised form of Stein's algorithm: + // https://en.wikipedia.org/wiki/Binary_GCD_algorithm std.debug.assert(a != 0 or b != 0); - // if one of them is zero, the other is returned if (a == 0) return b; if (b == 0) return a; - // init vars - var x: @TypeOf(a, b) = a; - var y: @TypeOf(a, b) = b; - var m: @TypeOf(a, b) = a; + var x: N = a; + var y: N = b; - // using the Euclidean algorithm (https://mathworld.wolfram.com/EuclideanAlgorithm.html) - while (y != 0) { - m = x % y; - x = y; - y = m; + const xz = @ctz(x); + const yz = @ctz(y); + const shift = @min(xz, yz); + x >>= @intCast(xz); + y >>= @intCast(yz); + + var diff = y -% x; + while (diff != 0) : (diff = y -% x) { + // ctz is invariant under negation, we + // put it here to ease data dependencies, + // makes the CPU happy. + const zeros = @ctz(diff); + if (x > y) diff = -%diff; + y = @min(x, y); + x = diff >> @intCast(zeros); } - return x; + return y << @intCast(shift); } -test "gcd" { +test gcd { + const expectEqual = std.testing.expectEqual; + try expectEqual(gcd(0, 5), 5); try expectEqual(gcd(5, 0), 5); try expectEqual(gcd(8, 12), 4); @@ -45,4 +54,6 @@ test "gcd" { try expectEqual(gcd(49865, 69811), 9973); try expectEqual(gcd(300_000, 2_300_000), 100_000); try expectEqual(gcd(90000000_000_000_000_000_000, 2), 2); + try expectEqual(gcd(@as(u80, 90000000_000_000_000_000_000), 2), 2); + try expectEqual(gcd(300_000, @as(u32, 2_300_000)), 100_000); } diff --git a/zig/lib/std/math/isnan.zig b/zig/lib/std/math/isnan.zig index cb929e5890..a85100ba90 100644 --- a/zig/lib/std/math/isnan.zig +++ b/zig/lib/std/math/isnan.zig @@ -32,7 +32,13 @@ test isSignalNan { // TODO: Signalling NaN values get converted to quiet NaN values in // some cases where they shouldn't such that this can fail. // See https://github.com/ziglang/zig/issues/14366 - // try expect(isSignalNan(math.snan(T))); + if (!builtin.cpu.arch.isArmOrThumb() and + !builtin.cpu.arch.isAARCH64() and + !builtin.cpu.arch.isPowerPC() and + builtin.zig_backend != .stage2_c) + { + try expect(isSignalNan(math.snan(T))); + } try expect(!isSignalNan(math.nan(T))); try expect(!isSignalNan(@as(T, 1.0))); try expect(!isSignalNan(math.inf(T))); diff --git a/zig/lib/std/mem.zig b/zig/lib/std/mem.zig index b4580b1aa4..d458e26989 100644 --- a/zig/lib/std/mem.zig +++ b/zig/lib/std/mem.zig @@ -4334,8 +4334,6 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize { return alignForward(usize, addr, alignment); } -pub const alignForwardGeneric = @compileError("renamed to alignForward"); - /// Force an evaluation of the expression; this tries to prevent /// the compiler from optimizing the computation away even if the /// result eventually gets discarded. @@ -4459,8 +4457,6 @@ pub fn alignBackward(comptime T: type, addr: T, alignment: T) T { return addr & ~(alignment - 1); } -pub const alignBackwardGeneric = @compileError("renamed to alignBackward"); - /// Returns whether `alignment` is a valid alignment, meaning it is /// a positive power of 2. pub fn isValidAlign(alignment: usize) bool { diff --git a/zig/lib/std/meta.zig b/zig/lib/std/meta.zig index e7ea5b5f0e..ea81c87648 100644 --- a/zig/lib/std/meta.zig +++ b/zig/lib/std/meta.zig @@ -240,8 +240,6 @@ pub fn Sentinel(comptime T: type, comptime sentinel_val: Elem(T)) type { @compileError("Unable to derive a sentinel pointer type from " ++ @typeName(T)); } -pub const assumeSentinel = @compileError("This function has been removed, consider using std.mem.sliceTo() or if needed a @ptrCast()"); - pub fn containerLayout(comptime T: type) Type.ContainerLayout { return switch (@typeInfo(T)) { .@"struct" => |info| info.layout, @@ -628,7 +626,7 @@ pub fn DeclEnum(comptime T: type) type { } return @Type(.{ .@"enum" = .{ - .tag_type = std.math.IntFittingRange(0, fieldInfos.len - 1), + .tag_type = std.math.IntFittingRange(0, if (fieldInfos.len == 0) 0 else fieldInfos.len - 1), .fields = &enumDecls, .decls = &decls, .is_exhaustive = true, @@ -654,9 +652,12 @@ test DeclEnum { pub const b: void = {}; pub const c: f32 = 0; }; + const D = struct {}; + try expectEqualEnum(enum { a }, DeclEnum(A)); try expectEqualEnum(enum { a, b, c }, DeclEnum(B)); try expectEqualEnum(enum { a, b, c }, DeclEnum(C)); + try expectEqualEnum(enum {}, DeclEnum(D)); } pub fn Tag(comptime T: type) type { @@ -930,8 +931,6 @@ pub fn fieldIndex(comptime T: type, comptime name: []const u8) ?comptime_int { return null; } -pub const refAllDecls = @compileError("refAllDecls has been moved from std.meta to std.testing"); - /// Returns a slice of pointers to public declarations of a namespace. pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const Decl { const S = struct { @@ -951,8 +950,6 @@ pub fn declList(comptime Namespace: type, comptime Decl: type) []const *const De } } -pub const IntType = @compileError("replaced by std.meta.Int"); - pub fn Int(comptime signedness: std.builtin.Signedness, comptime bit_count: u16) type { return @Type(.{ .int = .{ diff --git a/zig/lib/std/os/linux.zig b/zig/lib/std/os/linux.zig index 9039acedee..03eef2bb8e 100644 --- a/zig/lib/std/os/linux.zig +++ b/zig/lib/std/os/linux.zig @@ -29,16 +29,12 @@ test { } } -const syscall_bits = switch (native_arch) { - .thumb => @import("linux/thumb.zig"), - else => arch_bits, -}; - const arch_bits = switch (native_arch) { .x86 => @import("linux/x86.zig"), .x86_64 => @import("linux/x86_64.zig"), - .aarch64, .aarch64_be => @import("linux/arm64.zig"), - .arm, .armeb, .thumb, .thumbeb => @import("linux/arm-eabi.zig"), + .aarch64, .aarch64_be => @import("linux/aarch64.zig"), + .arm, .armeb, .thumb, .thumbeb => @import("linux/arm.zig"), + .hexagon => @import("linux/hexagon.zig"), .riscv32 => @import("linux/riscv32.zig"), .riscv64 => @import("linux/riscv64.zig"), .sparc64 => @import("linux/sparc64.zig"), @@ -47,11 +43,15 @@ const arch_bits = switch (native_arch) { .mips64, .mips64el => @import("linux/mips64.zig"), .powerpc, .powerpcle => @import("linux/powerpc.zig"), .powerpc64, .powerpc64le => @import("linux/powerpc64.zig"), + .s390x => @import("linux/s390x.zig"), else => struct { pub const ucontext_t = void; pub const getcontext = {}; }, }; + +const syscall_bits = if (native_arch.isThumb()) @import("linux/thumb.zig") else arch_bits; + pub const syscall0 = syscall_bits.syscall0; pub const syscall1 = syscall_bits.syscall1; pub const syscall2 = syscall_bits.syscall2; @@ -115,7 +115,7 @@ pub const user_desc = arch_bits.user_desc; pub const getcontext = arch_bits.getcontext; pub const tls = @import("linux/tls.zig"); -pub const pie = @import("linux/start_pie.zig"); +pub const pie = @import("linux/pie.zig"); pub const BPF = @import("linux/bpf.zig"); pub const IOCTL = @import("linux/ioctl.zig"); pub const SECCOMP = @import("linux/seccomp.zig"); @@ -276,6 +276,29 @@ pub const MAP = switch (native_arch) { UNINITIALIZED: bool = false, _: u5 = 0, }, + .hexagon, .s390x => packed struct(u32) { + TYPE: MAP_TYPE, + FIXED: bool = false, + ANONYMOUS: bool = false, + _4: u1 = 0, + _5: u1 = 0, + GROWSDOWN: bool = false, + _7: u1 = 0, + _8: u1 = 0, + DENYWRITE: bool = false, + EXECUTABLE: bool = false, + LOCKED: bool = false, + NORESERVE: bool = false, + POPULATE: bool = false, + NONBLOCK: bool = false, + STACK: bool = false, + HUGETLB: bool = false, + SYNC: bool = false, + FIXED_NOREPLACE: bool = false, + _19: u5 = 0, + UNINITIALIZED: bool = false, + _: u5 = 0, + }, else => @compileError("missing std.os.linux.MAP constants for this architecture"), }; @@ -417,6 +440,32 @@ pub const O = switch (native_arch) { TMPFILE: bool = false, _: u9 = 0, }, + .hexagon, .s390x => packed struct(u32) { + ACCMODE: ACCMODE = .RDONLY, + _2: u4 = 0, + CREAT: bool = false, + EXCL: bool = false, + NOCTTY: bool = false, + TRUNC: bool = false, + APPEND: bool = false, + NONBLOCK: bool = false, + DSYNC: bool = false, + ASYNC: bool = false, + DIRECT: bool = false, + LARGEFILE: bool = false, + DIRECTORY: bool = false, + NOFOLLOW: bool = false, + NOATIME: bool = false, + CLOEXEC: bool = false, + _17: u1 = 0, + PATH: bool = false, + _: u10 = 0, + + // #define O_RSYNC 04010000 + // #define O_SYNC 04010000 + // #define O_TMPFILE 020200000 + // #define O_NDELAY O_NONBLOCK + }, else => @compileError("missing std.os.linux.O constants for this architecture"), }; @@ -854,7 +903,19 @@ pub fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: MAP, fd: i32, of @truncate(@as(u64, @bitCast(offset)) / MMAP2_UNIT), ); } else { - return syscall6( + // The s390x mmap() syscall existed before Linux supported syscalls with 5+ parameters, so + // it takes a single pointer to an array of arguments instead. + return if (native_arch == .s390x) syscall1( + .mmap, + @intFromPtr(&[_]usize{ + @intFromPtr(address), + length, + prot, + @as(u32, @bitCast(flags)), + @bitCast(@as(isize, fd)), + @as(u64, @bitCast(offset)), + }), + ) else syscall6( .mmap, @intFromPtr(address), length, @@ -6501,12 +6562,12 @@ pub const tc_oflag_t = if (is_ppc) packed struct(tcflag_t) { ONLRET: bool = false, OFILL: bool = false, OFDEL: bool = false, - NLDLY: NLDLY = 0, - TABDLY: TABDLY = 0, - CRDLY: CRDLY = 0, - FFDLY: FFDLY = 0, - BSDLY: BSDLY = 0, - VTDLY: VTDLY = 0, + NLDLY: NLDLY = .NL0, + TABDLY: TABDLY = .TAB0, + CRDLY: CRDLY = .CR0, + FFDLY: FFDLY = .FF0, + BSDLY: BSDLY = .BS0, + VTDLY: VTDLY = .VT0, _17: u15 = 0, } else if (is_sparc) packed struct(tcflag_t) { OPOST: bool = false, @@ -8014,11 +8075,33 @@ pub const rtattr = extern struct { len: c_ushort, /// Type of option - type: IFLA, + type: extern union { + /// IFLA_* from linux/if_link.h + link: IFLA, + /// IFA_* from linux/if_addr.h + addr: IFA, + }, pub const ALIGNTO = 4; }; +pub const IFA = enum(c_ushort) { + UNSPEC, + ADDRESS, + LOCAL, + LABEL, + BROADCAST, + ANYCAST, + CACHEINFO, + MULTICAST, + FLAGS, + RT_PRIORITY, + TARGET_NETNSID, + PROTO, + + _, +}; + pub const IFLA = enum(c_ushort) { UNSPEC, ADDRESS, diff --git a/zig/lib/std/os/linux/IoUring.zig b/zig/lib/std/os/linux/IoUring.zig index c7717524a9..731877e5ae 100644 --- a/zig/lib/std/os/linux/IoUring.zig +++ b/zig/lib/std/os/linux/IoUring.zig @@ -3886,7 +3886,13 @@ inline fn skipKernelLessThan(required: std.SemanticVersion) !void { } const release = mem.sliceTo(&uts.release, 0); - var current = try std.SemanticVersion.parse(release); + // Strips potential extra, as kernel version might not be semver compliant, example "6.8.9-300.fc40.x86_64" + const extra_index = std.mem.indexOfAny(u8, release, "-+"); + const stripped = release[0..(extra_index orelse release.len)]; + // Make sure the input don't rely on the extra we just stripped + try testing.expect(required.pre == null and required.build == null); + + var current = try std.SemanticVersion.parse(stripped); current.pre = null; // don't check pre field if (required.order(current) == .gt) return error.SkipZigTest; } diff --git a/zig/lib/std/os/linux/arm64.zig b/zig/lib/std/os/linux/aarch64.zig similarity index 100% rename from zig/lib/std/os/linux/arm64.zig rename to zig/lib/std/os/linux/aarch64.zig diff --git a/zig/lib/std/os/linux/arm-eabi.zig b/zig/lib/std/os/linux/arm.zig similarity index 100% rename from zig/lib/std/os/linux/arm-eabi.zig rename to zig/lib/std/os/linux/arm.zig diff --git a/zig/lib/std/os/linux/hexagon.zig b/zig/lib/std/os/linux/hexagon.zig new file mode 100644 index 0000000000..e9bf9ab57c --- /dev/null +++ b/zig/lib/std/os/linux/hexagon.zig @@ -0,0 +1,254 @@ +const std = @import("../../std.zig"); +const iovec = std.posix.iovec; +const iovec_const = std.posix.iovec_const; +const linux = std.os.linux; +const SYS = linux.SYS; +const uid_t = std.os.linux.uid_t; +const gid_t = std.os.linux.gid_t; +const pid_t = std.os.linux.pid_t; +const sockaddr = linux.sockaddr; +const socklen_t = linux.socklen_t; +const timespec = std.os.linux.timespec; + +pub fn syscall0(number: SYS) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + : "memory" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + : "memory" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + : "memory" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + : "memory" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + : "memory" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + : "memory" + ); +} + +pub fn syscall6( + number: SYS, + arg1: usize, + arg2: usize, + arg3: usize, + arg4: usize, + arg5: usize, + arg6: usize, +) usize { + return asm volatile ("trap0(#1)" + : [ret] "={r0}" (-> usize), + : [number] "{r6}" (@intFromEnum(number)), + [arg1] "{r0}" (arg1), + [arg2] "{r1}" (arg2), + [arg3] "{r2}" (arg3), + [arg4] "{r3}" (arg4), + [arg5] "{r4}" (arg5), + [arg6] "{r5}" (arg6), + : "memory" + ); +} + +pub fn clone() callconv(.Naked) usize { + // __clone(func, stack, flags, arg, ptid, tls, ctid) + // r0, r1, r2, r3, r4, r5, +0 + // + // syscall(SYS_clone, flags, stack, ptid, ctid, tls) + // r6 r0, r1, r2, r3, r4 + asm volatile ( + \\ allocframe(#8) + \\ + \\ r11 = r0 + \\ r10 = r3 + \\ + \\ r6 = #220 // SYS_clone + \\ r0 = r2 + \\ r1 = and(r1, #-8) + \\ r2 = r4 + \\ r3 = memw(r30 + #8) + \\ r4 = r5 + \\ trap0(#1) + \\ + \\ p0 = cmp.eq(r0, #0) + \\ if (!p0) dealloc_return + \\ + \\ r0 = r10 + \\ callr r11 + \\ + \\ r6 = #93 // SYS_exit + \\ r0 = #0 + \\ trap0(#1) + ); +} + +pub const restore = restore_rt; + +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\ trap0(#0) + : + : [number] "{r6}" (@intFromEnum(SYS.rt_sigreturn)), + : "memory" + ); +} + +pub const F = struct { + pub const DUPFD = 0; + pub const GETFD = 1; + pub const SETFD = 2; + pub const GETFL = 3; + pub const SETFL = 4; + pub const GETLK = 5; + pub const SETLK = 6; + pub const SETLKW = 7; + pub const SETOWN = 8; + pub const GETOWN = 9; + pub const SETSIG = 10; + pub const GETSIG = 11; + + pub const RDLCK = 0; + pub const WRLCK = 1; + pub const UNLCK = 2; + + pub const SETOWN_EX = 15; + pub const GETOWN_EX = 16; + + pub const GETOWNER_UIDS = 17; +}; + +pub const timeval = extern struct { + sec: time_t, + usec: i32, +}; + +pub const Flock = extern struct { + type: i16, + whence: i16, + start: off_t, + len: off_t, + pid: pid_t, + __unused: [4]u8, +}; + +pub const msghdr = extern struct { + name: ?*sockaddr, + namelen: socklen_t, + iov: [*]iovec, + iovlen: i32, + __pad1: i32 = 0, + control: ?*anyopaque, + controllen: socklen_t, + __pad2: socklen_t = 0, + flags: i32, +}; + +pub const msghdr_const = extern struct { + name: ?*const sockaddr, + namelen: socklen_t, + iov: [*]const iovec_const, + iovlen: i32, + __pad1: i32 = 0, + control: ?*const anyopaque, + controllen: socklen_t, + __pad2: socklen_t = 0, + flags: i32, +}; + +pub const blksize_t = i32; +pub const nlink_t = u32; +pub const time_t = i32; +pub const mode_t = u32; +pub const off_t = i64; +pub const ino_t = u64; +pub const dev_t = u64; +pub const blkcnt_t = i64; + +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + mode: mode_t, + nlink: nlink_t, + uid: uid_t, + gid: gid_t, + rdev: dev_t, + __pad: u32, + size: off_t, + blksize: blksize_t, + __pad2: i32, + blocks: blkcnt_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + __unused: [2]u32, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) timespec { + return self.ctim; + } +}; + +pub const Elf_Symndx = u32; + +pub const MMAP2_UNIT = 4096; + +pub const VDSO = void; + +/// TODO +pub const ucontext_t = void; + +/// TODO +pub const getcontext = {}; diff --git a/zig/lib/std/os/linux/start_pie.zig b/zig/lib/std/os/linux/pie.zig similarity index 100% rename from zig/lib/std/os/linux/start_pie.zig rename to zig/lib/std/os/linux/pie.zig diff --git a/zig/lib/std/os/linux/powerpc64.zig b/zig/lib/std/os/linux/powerpc64.zig index 04936a113d..06b67c17f1 100644 --- a/zig/lib/std/os/linux/powerpc64.zig +++ b/zig/lib/std/os/linux/powerpc64.zig @@ -48,7 +48,7 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { : [number] "{r0}" (@intFromEnum(number)), [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), - : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + : "memory", "cr0", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); } @@ -63,7 +63,7 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { [arg1] "{r3}" (arg1), [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), - : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + : "memory", "cr0", "r6", "r7", "r8", "r9", "r10", "r11", "r12" ); } @@ -79,7 +79,7 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) [arg2] "{r4}" (arg2), [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), - : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + : "memory", "cr0", "r7", "r8", "r9", "r10", "r11", "r12" ); } @@ -96,7 +96,7 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, [arg3] "{r5}" (arg3), [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), - : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + : "memory", "cr0", "r8", "r9", "r10", "r11", "r12" ); } @@ -122,7 +122,7 @@ pub fn syscall6( [arg4] "{r6}" (arg4), [arg5] "{r7}" (arg5), [arg6] "{r8}" (arg6), - : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + : "memory", "cr0", "r9", "r10", "r11", "r12" ); } diff --git a/zig/lib/std/os/linux/s390x.zig b/zig/lib/std/os/linux/s390x.zig new file mode 100644 index 0000000000..efc48af4ff --- /dev/null +++ b/zig/lib/std/os/linux/s390x.zig @@ -0,0 +1,276 @@ +const std = @import("../../std.zig"); +const iovec = std.posix.iovec; +const iovec_const = std.posix.iovec_const; +const linux = std.os.linux; +const SYS = linux.SYS; +const uid_t = std.os.linux.uid_t; +const gid_t = std.os.linux.gid_t; +const pid_t = std.os.linux.pid_t; +const sockaddr = linux.sockaddr; +const socklen_t = linux.socklen_t; +const timespec = std.os.linux.timespec; +const stack_t = std.os.linux.stack_t; +const sigset_t = std.os.linux.sigset_t; + +pub fn syscall0(number: SYS) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + : "memory" + ); +} + +pub fn syscall1(number: SYS, arg1: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + : "memory" + ); +} + +pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + [arg2] "{r3}" (arg2), + : "memory" + ); +} + +pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + [arg2] "{r3}" (arg2), + [arg3] "{r4}" (arg3), + : "memory" + ); +} + +pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + [arg2] "{r3}" (arg2), + [arg3] "{r4}" (arg3), + [arg4] "{r5}" (arg4), + : "memory" + ); +} + +pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + [arg2] "{r3}" (arg2), + [arg3] "{r4}" (arg3), + [arg4] "{r5}" (arg4), + [arg5] "{r6}" (arg5), + : "memory" + ); +} + +pub fn syscall6(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize, arg6: usize) usize { + return asm volatile ("svc 0" + : [ret] "={r2}" (-> usize), + : [number] "{r1}" (@intFromEnum(number)), + [arg1] "{r2}" (arg1), + [arg2] "{r3}" (arg2), + [arg3] "{r4}" (arg3), + [arg4] "{r5}" (arg4), + [arg5] "{r6}" (arg5), + [arg6] "{r7}" (arg6), + : "memory" + ); +} + +pub fn clone() callconv(.Naked) usize { + asm volatile ( + \\# int clone( + \\# fn, a = r2 + \\# stack, b = r3 + \\# flags, c = r4 + \\# arg, d = r5 + \\# ptid, e = r6 + \\# tls, f = *(r15+160) + \\# ctid) g = *(r15+168) + \\# + \\# pseudo C code: + \\# tid = syscall(SYS_clone,b,c,e,g,f); + \\# if (!tid) syscall(SYS_exit, a(d)); + \\# return tid; + \\ + \\# preserve call-saved register used as syscall arg + \\stg %%r6, 48(%%r15) + \\ + \\# create initial stack frame for new thread + \\nill %%r3, 0xfff8 + \\aghi %%r3, -160 + \\lghi %%r0, 0 + \\stg %%r0, 0(%%r3) + \\ + \\# save fn and arg to child stack + \\stg %%r2, 8(%%r3) + \\stg %%r5, 16(%%r3) + \\ + \\# shuffle args into correct registers and call SYS_clone + \\lgr %%r2, %%r3 + \\lgr %%r3, %%r4 + \\lgr %%r4, %%r6 + \\lg %%r5, 168(%%r15) + \\lg %%r6, 160(%%r15) + \\svc 120 + \\ + \\# restore call-saved register + \\lg %%r6, 48(%%r15) + \\ + \\# if error or if we're the parent, return + \\ltgr %%r2, %%r2 + \\bnzr %%r14 + \\ + \\# we're the child. call fn(arg) + \\lg %%r1, 8(%%r15) + \\lg %%r2, 16(%%r15) + \\basr %%r14, %%r1 + \\ + \\# call SYS_exit. exit code is already in r2 from fn return value + \\svc 1 + \\ + ); +} + +pub const restore = restore_rt; + +pub fn restore_rt() callconv(.Naked) noreturn { + asm volatile ( + \\svc 0 + : + : [number] "{r1}" (@intFromEnum(SYS.rt_sigreturn)), + : "memory" + ); +} + +pub const F = struct { + pub const DUPFD = 0; + pub const GETFD = 1; + pub const SETFD = 2; + pub const GETFL = 3; + pub const SETFL = 4; + pub const GETLK = 5; + pub const SETLK = 6; + pub const SETLKW = 7; + pub const SETOWN = 8; + pub const GETOWN = 9; + pub const SETSIG = 10; + pub const GETSIG = 11; + + pub const SETOWN_EX = 15; + pub const GETOWN_EX = 16; + + pub const GETOWNER_UIDS = 17; +}; + +pub const blksize_t = i64; +pub const nlink_t = u64; +pub const time_t = i64; +pub const mode_t = u32; +pub const off_t = i64; +pub const ino_t = u64; +pub const dev_t = u64; +pub const blkcnt_t = i64; + +pub const timeval = extern struct { + sec: time_t, + usec: i64, +}; + +pub const Flock = extern struct { + type: i16, + whence: i16, + start: off_t, + len: off_t, + pid: pid_t, +}; + +pub const msghdr = extern struct { + name: ?*sockaddr, + namelen: socklen_t, + iov: [*]iovec, + __pad1: i32 = 0, + iovlen: i32, + control: ?*anyopaque, + __pad2: i32 = 0, + controllen: socklen_t, + flags: i32, +}; + +pub const msghdr_const = extern struct { + name: ?*const sockaddr, + namelen: socklen_t, + iov: [*]const iovec_const, + __pad1: i32 = 0, + iovlen: i32, + control: ?*const anyopaque, + __pad2: i32 = 0, + controllen: socklen_t, + flags: i32, +}; + +// The `stat` definition used by the Linux kernel. +pub const Stat = extern struct { + dev: dev_t, + ino: ino_t, + nlink: nlink_t, + mode: mode_t, + uid: uid_t, + gid: gid_t, + rdev: dev_t, + size: off_t, + atim: timespec, + mtim: timespec, + ctim: timespec, + blksize: blksize_t, + blocks: blkcnt_t, + __unused: [3]c_ulong, + + pub fn atime(self: @This()) timespec { + return self.atim; + } + + pub fn mtime(self: @This()) timespec { + return self.mtim; + } + + pub fn ctime(self: @This()) timespec { + return self.ctim; + } +}; + +pub const Elf_Symndx = u64; + +pub const VDSO = struct { + pub const CGT_SYM = "__kernel_clock_gettime"; + pub const CGT_VER = "LINUX_2.6.29"; +}; + +pub const ucontext_t = extern struct { + flags: u64, + link: ?*ucontext_t, + stack: stack_t, + mcontext: mcontext_t, + sigmask: sigset_t, +}; + +pub const mcontext_t = extern struct { + __regs1: [18]u64, + __regs2: [18]u32, + __regs3: [16]f64, +}; + +/// TODO +pub const getcontext = {}; diff --git a/zig/lib/std/os/linux/syscalls.zig b/zig/lib/std/os/linux/syscalls.zig index d08a77b47c..ef04387ea6 100644 --- a/zig/lib/std/os/linux/syscalls.zig +++ b/zig/lib/std/os/linux/syscalls.zig @@ -6852,7 +6852,7 @@ pub const Arc = enum(usize) { keyctl = 219, clone = 220, execve = 221, - mmap_pgoff = 222, + mmap2 = 222, fadvise64_64 = 223, swapon = 224, swapoff = 225, @@ -7538,7 +7538,7 @@ pub const Hexagon = enum(usize) { keyctl = 219, clone = 220, execve = 221, - mmap_pgoff = 222, + mmap2 = 222, fadvise64_64 = 223, swapon = 224, swapoff = 225, diff --git a/zig/lib/std/os/linux/thumb.zig b/zig/lib/std/os/linux/thumb.zig index baaf130578..a464030858 100644 --- a/zig/lib/std/os/linux/thumb.zig +++ b/zig/lib/std/os/linux/thumb.zig @@ -141,7 +141,7 @@ pub fn syscall6( ); } -pub const clone = @import("arm-eabi.zig").clone; +pub const clone = @import("arm.zig").clone; pub fn restore() callconv(.Naked) noreturn { asm volatile ( diff --git a/zig/lib/std/os/linux/tls.zig b/zig/lib/std/os/linux/tls.zig index 7dab38024c..d1292e86dd 100644 --- a/zig/lib/std/os/linux/tls.zig +++ b/zig/lib/std/os/linux/tls.zig @@ -541,7 +541,19 @@ inline fn mmap(address: ?[*]u8, length: usize, prot: usize, flags: linux.MAP, fd @as(usize, @truncate(@as(u64, @bitCast(offset)) / linux.MMAP2_UNIT)), }); } else { - return @call(.always_inline, linux.syscall6, .{ + // The s390x mmap() syscall existed before Linux supported syscalls with 5+ parameters, so + // it takes a single pointer to an array of arguments instead. + return if (native_arch == .s390x) @call(.always_inline, linux.syscall1, .{ + .mmap, + @intFromPtr(&[_]usize{ + @intFromPtr(address), + length, + prot, + @as(u32, @bitCast(flags)), + @as(usize, @bitCast(@as(isize, fd))), + @as(u64, @bitCast(offset)), + }), + }) else @call(.always_inline, linux.syscall6, .{ .mmap, @intFromPtr(address), length, diff --git a/zig/lib/std/os/uefi/pool_allocator.zig b/zig/lib/std/os/uefi/pool_allocator.zig index aa9798c6e5..f7962f22aa 100644 --- a/zig/lib/std/os/uefi/pool_allocator.zig +++ b/zig/lib/std/os/uefi/pool_allocator.zig @@ -48,11 +48,9 @@ const UefiPoolAllocator = struct { ret_addr: usize, ) bool { _ = ret_addr; + _ = log2_old_ptr_align; if (new_len > buf.len) return false; - - _ = mem.alignAllocLen(buf.len, new_len, log2_old_ptr_align); - return true; } @@ -121,9 +119,6 @@ fn uefi_resize( std.debug.assert(log2_old_ptr_align <= 3); if (new_len > buf.len) return false; - - _ = mem.alignAllocLen(buf.len, new_len, 8); - return true; } diff --git a/zig/lib/std/os/wasi.zig b/zig/lib/std/os/wasi.zig index 2c7d0d3272..5ffde3c1f6 100644 --- a/zig/lib/std/os/wasi.zig +++ b/zig/lib/std/os/wasi.zig @@ -315,35 +315,77 @@ pub const SOCK = struct { }; pub const rights_t = packed struct(u64) { + /// The right to invoke fd_datasync. If PATH_OPEN is set, includes the right to invoke + /// path_open with fdflags_t.dsync. FD_DATASYNC: bool = false, + /// The right to invoke fd_read and sock_recv. If FD_SEEK is set, includes the right to invoke + /// fd_pread. FD_READ: bool = false, + /// The right to invoke fd_seek. This flag implies FD_TELL. FD_SEEK: bool = false, + /// The right to invoke fd_fdstat_set_flags. FD_FDSTAT_SET_FLAGS: bool = false, + /// The right to invoke fd_sync. If PATH_OPEN is set, includes the right to invoke path_open + /// with fdflags_t.RSYNC and fdflags_t.DSYNC. FD_SYNC: bool = false, + /// The right to invoke fd_seek in such a way that the file offset remains unaltered (i.e. + /// whence_t.CUR with offset zero), or to invoke fd_tell. FD_TELL: bool = false, + /// The right to invoke fd_write and sock_send. If FD_SEEK is set, includes the right to invoke + /// fd_pwrite. FD_WRITE: bool = false, + /// The right to invoke fd_advise. FD_ADVISE: bool = false, + /// The right to invoke fd_allocate. FD_ALLOCATE: bool = false, + /// The right to invoke path_create_directory. PATH_CREATE_DIRECTORY: bool = false, + /// If PATH_OPEN is set, the right to invoke path_open with oflags_t.CREAT. PATH_CREATE_FILE: bool = false, + /// The right to invoke path_link with the file descriptor as the source directory. PATH_LINK_SOURCE: bool = false, + /// The right to invoke path_link with the file descriptor as the target directory. PATH_LINK_TARGET: bool = false, + /// The right to invoke path_open. PATH_OPEN: bool = false, + /// The right to invoke fd_readdir. FD_READDIR: bool = false, + /// The right to invoke path_readlink. PATH_READLINK: bool = false, + /// The right to invoke path_rename with the file descriptor as the source directory. PATH_RENAME_SOURCE: bool = false, + /// The right to invoke path_rename with the file descriptor as the target directory. PATH_RENAME_TARGET: bool = false, + /// The right to invoke path_filestat_get. PATH_FILESTAT_GET: bool = false, + /// The right to change a file's size. If PATH_OPEN is set, includes the right to invoke + /// path_open with oflags_t.TRUNC. Note: there is no function named path_filestat_set_size. + /// This follows POSIX design, which only has ftruncate and does not provide ftruncateat. While + /// such function would be desirable from the API design perspective, there are virtually no + /// use cases for it since no code written for POSIX systems would use it. Moreover, + /// implementing it would require multiple syscalls, leading to inferior performance. PATH_FILESTAT_SET_SIZE: bool = false, + /// The right to invoke path_filestat_set_times. PATH_FILESTAT_SET_TIMES: bool = false, + /// The right to invoke fd_filestat_get. FD_FILESTAT_GET: bool = false, + /// The right to invoke fd_filestat_set_size. FD_FILESTAT_SET_SIZE: bool = false, + /// The right to invoke fd_filestat_set_times. FD_FILESTAT_SET_TIMES: bool = false, + /// The right to invoke path_symlink. PATH_SYMLINK: bool = false, + /// The right to invoke path_remove_directory. PATH_REMOVE_DIRECTORY: bool = false, + /// The right to invoke path_unlink_file. PATH_UNLINK_FILE: bool = false, + /// If FD_READ is set, includes the right to invoke poll_oneoff to subscribe to + /// eventtype_t.FD_READ. If FD_WRITE is set, includes the right to invoke poll_oneoff to + /// subscribe to eventtype_t.FD_WRITE. POLL_FD_READWRITE: bool = false, + /// The right to invoke sock_shutdown. SOCK_SHUTDOWN: bool = false, + /// The right to invoke sock_accept. SOCK_ACCEPT: bool = false, _: u34 = 0, }; diff --git a/zig/lib/std/os/windows.zig b/zig/lib/std/os/windows.zig index d277361352..7f4d3290dc 100644 --- a/zig/lib/std/os/windows.zig +++ b/zig/lib/std/os/windows.zig @@ -599,6 +599,8 @@ pub const ReadFileError = error{ /// The specified network name is no longer available. ConnectionResetByPeer, OperationAborted, + /// Unable to read file due to lock. + LockViolation, Unexpected, }; @@ -630,6 +632,7 @@ pub fn ReadFile(in_hFile: HANDLE, buffer: []u8, offset: ?u64) ReadFileError!usiz .BROKEN_PIPE => return 0, .HANDLE_EOF => return 0, .NETNAME_DELETED => return error.ConnectionResetByPeer, + .LOCK_VIOLATION => return error.LockViolation, else => |err| return unexpectedError(err), } } diff --git a/zig/lib/std/os/windows/tls.zig b/zig/lib/std/os/windows/tls.zig index f98e22b620..4723b31011 100644 --- a/zig/lib/std/os/windows/tls.zig +++ b/zig/lib/std/os/windows/tls.zig @@ -9,7 +9,7 @@ export var __xl_a: windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLA") = null; export var __xl_z: windows.PIMAGE_TLS_CALLBACK linksection(".CRT$XLZ") = null; comptime { - if (builtin.cpu.arch == .x86 and builtin.abi == .msvc and builtin.zig_backend != .stage2_c) { + if (builtin.cpu.arch == .x86 and !builtin.abi.isGnu() and builtin.zig_backend != .stage2_c) { // The __tls_array is the offset of the ThreadLocalStoragePointer field // in the TEB block whose base address held in the %fs segment. asm ( diff --git a/zig/lib/std/posix.zig b/zig/lib/std/posix.zig index 94b37a0878..bb21a79690 100644 --- a/zig/lib/std/posix.zig +++ b/zig/lib/std/posix.zig @@ -798,6 +798,13 @@ pub const ReadError = error{ /// In WASI, this error occurs when the file descriptor does /// not hold the required rights to read from it. AccessDenied, + + /// This error occurs in Linux if the process to be read from + /// no longer exists. + ProcessNotFound, + + /// Unable to read file due to lock. + LockViolation, } || UnexpectedError; /// Returns the number of bytes that were read, which can be less than @@ -854,6 +861,7 @@ pub fn read(fd: fd_t, buf: []u8) ReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .CANCELED => return error.Canceled, .BADF => return error.NotOpenForReading, // Can be a race condition. @@ -917,6 +925,7 @@ pub fn readv(fd: fd_t, iov: []const iovec) ReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForReading, // can be a race condition .IO => return error.InputOutput, @@ -996,6 +1005,7 @@ pub fn pread(fd: fd_t, buf: []u8, offset: u64) PReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForReading, // Can be a race condition. .IO => return error.InputOutput, @@ -1133,6 +1143,7 @@ pub fn preadv(fd: fd_t, iov: []const iovec, offset: u64) PReadError!usize { .INTR => continue, .INVAL => unreachable, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForReading, // can be a race condition .IO => return error.InputOutput, @@ -1176,6 +1187,10 @@ pub const WriteError = error{ /// Connection reset by peer. ConnectionResetByPeer, + + /// This error occurs in Linux if the process being written to + /// no longer exists. + ProcessNotFound, } || UnexpectedError; /// Write to a file descriptor. @@ -1243,6 +1258,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize { .INTR => continue, .INVAL => return error.InvalidArgument, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // can be a race condition. .DESTADDRREQ => unreachable, // `connect` was never called. @@ -1315,6 +1331,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize { .INTR => continue, .INVAL => return error.InvalidArgument, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // Can be a race condition. .DESTADDRREQ => unreachable, // `connect` was never called. @@ -1404,6 +1421,7 @@ pub fn pwrite(fd: fd_t, bytes: []const u8, offset: u64) PWriteError!usize { .INTR => continue, .INVAL => return error.InvalidArgument, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // Can be a race condition. .DESTADDRREQ => unreachable, // `connect` was never called. @@ -1488,6 +1506,7 @@ pub fn pwritev(fd: fd_t, iov: []const iovec_const, offset: u64) PWriteError!usiz .INTR => continue, .INVAL => return error.InvalidArgument, .FAULT => unreachable, + .NOENT => return error.ProcessNotFound, .AGAIN => return error.WouldBlock, .BADF => return error.NotOpenForWriting, // Can be a race condition. .DESTADDRREQ => unreachable, // `connect` was never called. @@ -4544,13 +4563,16 @@ pub const FanotifyInitError = error{ SystemFdQuotaExceeded, SystemResources, PermissionDenied, + /// The kernel does not recognize the flags passed, likely because it is an + /// older version. + UnsupportedFlags, } || UnexpectedError; pub fn fanotify_init(flags: std.os.linux.fanotify.InitFlags, event_f_flags: u32) FanotifyInitError!i32 { const rc = system.fanotify_init(flags, event_f_flags); switch (errno(rc)) { .SUCCESS => return @intCast(rc), - .INVAL => unreachable, + .INVAL => return error.UnsupportedFlags, .MFILE => return error.ProcessFdQuotaExceeded, .NFILE => return error.SystemFdQuotaExceeded, .NOMEM => return error.SystemResources, @@ -6763,6 +6785,7 @@ pub const MemFdCreateError = error{ OutOfMemory, /// Either the name provided exceeded `NAME_MAX`, or invalid flags were passed. NameTooLong, + SystemOutdated, } || UnexpectedError; pub fn memfd_createZ(name: [*:0]const u8, flags: u32) MemFdCreateError!fd_t { diff --git a/zig/lib/std/posix/test.zig b/zig/lib/std/posix/test.zig index e62ffa39ca..dba7dcde6d 100644 --- a/zig/lib/std/posix/test.zig +++ b/zig/lib/std/posix/test.zig @@ -368,6 +368,11 @@ test "fstatat" { // now repeat but using `fstatat` instead const flags = if (native_os == .wasi) 0x0 else posix.AT.SYMLINK_NOFOLLOW; const statat = try posix.fstatat(tmp.dir.fd, "file.txt", flags); + + // s390x-linux does not have nanosecond precision for fstat(), but it does for fstatat(). As a + // result, comparing the two structures is doomed to fail. + if (builtin.cpu.arch == .s390x and builtin.os.tag == .linux) return error.SkipZigTest; + try expectEqual(stat, statat); } diff --git a/zig/lib/std/process/Child.zig b/zig/lib/std/process/Child.zig index 3a54ede2ad..bd0a91ce77 100644 --- a/zig/lib/std/process/Child.zig +++ b/zig/lib/std/process/Child.zig @@ -316,9 +316,7 @@ pub const RunResult = struct { }; fn fifoToOwnedArrayList(fifo: *std.io.PollFifo) std.ArrayList(u8) { - if (fifo.head > 0) { - @memcpy(fifo.buf[0..fifo.count], fifo.buf[fifo.head..][0..fifo.count]); - } + if (fifo.head != 0) fifo.realign(); const result = std.ArrayList(u8){ .items = fifo.buf[0..fifo.count], .capacity = fifo.buf.len, diff --git a/zig/lib/std/sort.zig b/zig/lib/std/sort.zig index 23707f1385..8705d24017 100644 --- a/zig/lib/std/sort.zig +++ b/zig/lib/std/sort.zig @@ -769,10 +769,38 @@ pub fn equalRange( context: anytype, comptime compareFn: fn (@TypeOf(context), T) std.math.Order, ) struct { usize, usize } { - return .{ - lowerBound(T, items, context, compareFn), - upperBound(T, items, context, compareFn), - }; + var low: usize = 0; + var high: usize = items.len; + + while (low < high) { + const mid = low + (high - low) / 2; + switch (compareFn(context, items[mid])) { + .gt => { + low = mid + 1; + }, + .lt => { + high = mid; + }, + .eq => { + return .{ + low + std.sort.lowerBound( + T, + items[low..mid], + context, + compareFn, + ), + mid + std.sort.upperBound( + T, + items[mid..high], + context, + compareFn, + ), + }; + }, + } + } + + return .{ low, low }; } test equalRange { @@ -800,6 +828,7 @@ test equalRange { try std.testing.expectEqual(.{ 6, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 16, 32, 64 }, @as(i32, 100), S.orderI32)); try std.testing.expectEqual(.{ 2, 6 }, equalRange(i32, &[_]i32{ 2, 4, 8, 8, 8, 8, 15, 22 }, @as(i32, 8), S.orderI32)); try std.testing.expectEqual(.{ 2, 2 }, equalRange(u32, &[_]u32{ 2, 4, 8, 16, 32, 64 }, @as(u32, 5), S.orderU32)); + try std.testing.expectEqual(.{ 3, 5 }, equalRange(u32, &[_]u32{ 2, 3, 4, 5, 5 }, @as(u32, 5), S.orderU32)); try std.testing.expectEqual(.{ 1, 1 }, equalRange(f32, &[_]f32{ -54.2, -26.7, 0.0, 56.55, 100.1, 322.0 }, @as(f32, -33.4), S.orderF32)); try std.testing.expectEqual(.{ 3, 5 }, equalRange( []const u8, diff --git a/zig/lib/std/start.zig b/zig/lib/std/start.zig index a8109f7ed9..01a33522d0 100644 --- a/zig/lib/std/start.zig +++ b/zig/lib/std/start.zig @@ -271,8 +271,8 @@ fn _start() callconv(.Naked) noreturn { \\ b %[posixCallMainAndExit] , .arc => - // The `arc` tag currently means ARCv2, which has an unusually low stack alignment - // requirement. ARCv3 increases it from 4 to 16, but we don't support ARCv3 yet. + // The `arc` tag currently means ARC v1 and v2, which have an unusually low stack + // alignment requirement. ARC v3 increases it from 4 to 16, but we don't support v3 yet. \\ mov fp, 0 \\ mov blink, 0 \\ mov r0, sp @@ -391,6 +391,7 @@ fn _start() callconv(.Naked) noreturn { \\ stdu 0, -32(1) \\ mtlr 0 \\ b %[posixCallMainAndExit] + \\ nop , .s390x => // Set up the stack frame (register save area and cleared back-chain slot). @@ -539,6 +540,7 @@ fn expandStackSize(phdrs: []elf.Phdr) void { for (phdrs) |*phdr| { switch (phdr.p_type) { elf.PT_GNU_STACK => { + if (phdr.p_memsz == 0) break; assert(phdr.p_memsz % std.mem.page_size == 0); // Silently fail if we are unable to get limits. diff --git a/zig/lib/std/tar.zig b/zig/lib/std/tar.zig index f15a5e8c8a..060b802f19 100644 --- a/zig/lib/std/tar.zig +++ b/zig/lib/std/tar.zig @@ -848,6 +848,7 @@ test PaxIterator { test { _ = @import("tar/test.zig"); + _ = @import("tar/writer.zig"); _ = Diagnostics; } diff --git a/zig/lib/std/tar/writer.zig b/zig/lib/std/tar/writer.zig index e75e6c42d6..4ced287eec 100644 --- a/zig/lib/std/tar/writer.zig +++ b/zig/lib/std/tar/writer.zig @@ -84,7 +84,7 @@ pub fn Writer(comptime WriterType: type) type { /// Writes fs.Dir.WalkerEntry. Uses `mtime` from file system entry and /// default for entry mode . - pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.WalkerEntry) !void { + pub fn writeEntry(self: *Self, entry: std.fs.Dir.Walker.Entry) !void { switch (entry.kind) { .directory => { try self.writeDir(entry.path, .{ .mtime = try entryMtime(entry) }); @@ -95,7 +95,7 @@ pub fn Writer(comptime WriterType: type) type { try self.writeFile(entry.path, file); }, .sym_link => { - var link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; const link_name = try entry.dir.readLink(entry.basename, &link_name_buffer); try self.writeLink(entry.path, link_name, .{ .mtime = try entryMtime(entry) }); }, @@ -133,7 +133,7 @@ pub fn Writer(comptime WriterType: type) type { return self.mtime_now; } - fn entryMtime(entry: std.fs.Dir.Walker.WalkerEntry) !u64 { + fn entryMtime(entry: std.fs.Dir.Walker.Entry) !u64 { const stat = try entry.dir.statFile(entry.basename); return @intCast(@divFloor(stat.mtime, std.time.ns_per_s)); } @@ -424,8 +424,8 @@ test "write files" { .{ .path = "e123456789" ** 11, .content = "e" }, }; - var file_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; - var link_name_buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined; + var file_name_buffer: [std.fs.max_path_bytes]u8 = undefined; + var link_name_buffer: [std.fs.max_path_bytes]u8 = undefined; // with root { diff --git a/zig/lib/std/time.zig b/zig/lib/std/time.zig index a80a2477ac..d253b63512 100644 --- a/zig/lib/std/time.zig +++ b/zig/lib/std/time.zig @@ -8,82 +8,8 @@ const posix = std.posix; pub const epoch = @import("time/epoch.zig"); -/// Spurious wakeups are possible and no precision of timing is guaranteed. -pub fn sleep(nanoseconds: u64) void { - if (builtin.os.tag == .windows) { - const big_ms_from_ns = nanoseconds / ns_per_ms; - const ms = math.cast(windows.DWORD, big_ms_from_ns) orelse math.maxInt(windows.DWORD); - windows.kernel32.Sleep(ms); - return; - } - - if (builtin.os.tag == .wasi) { - const w = std.os.wasi; - const userdata: w.userdata_t = 0x0123_45678; - const clock: w.subscription_clock_t = .{ - .id = .MONOTONIC, - .timeout = nanoseconds, - .precision = 0, - .flags = 0, - }; - const in: w.subscription_t = .{ - .userdata = userdata, - .u = .{ - .tag = .CLOCK, - .u = .{ .clock = clock }, - }, - }; - - var event: w.event_t = undefined; - var nevents: usize = undefined; - _ = w.poll_oneoff(&in, &event, 1, &nevents); - return; - } - - if (builtin.os.tag == .uefi) { - const boot_services = std.os.uefi.system_table.boot_services.?; - const us_from_ns = nanoseconds / ns_per_us; - const us = math.cast(usize, us_from_ns) orelse math.maxInt(usize); - _ = boot_services.stall(us); - return; - } - - const s = nanoseconds / ns_per_s; - const ns = nanoseconds % ns_per_s; - - // Newer kernel ports don't have old `nanosleep()` and `clock_nanosleep()` has been around - // since Linux 2.6 and glibc 2.1 anyway. - if (builtin.os.tag == .linux) { - const linux = std.os.linux; - - var req: linux.timespec = .{ - .sec = std.math.cast(linux.time_t, s) orelse std.math.maxInt(linux.time_t), - .nsec = std.math.cast(linux.time_t, ns) orelse std.math.maxInt(linux.time_t), - }; - var rem: linux.timespec = undefined; - - while (true) { - switch (linux.E.init(linux.clock_nanosleep(.MONOTONIC, .{ .ABSTIME = false }, &req, &rem))) { - .SUCCESS => return, - .INTR => { - req = rem; - continue; - }, - .FAULT, - .INVAL, - .OPNOTSUPP, - => unreachable, - else => return, - } - } - } - - posix.nanosleep(s, ns); -} - -test sleep { - sleep(1); -} +/// Deprecated: moved to std.Thread.sleep +pub const sleep = std.Thread.sleep; /// Get a calendar timestamp, in seconds, relative to UTC 1970-01-01. /// Precision of timing depends on the hardware and operating system. @@ -155,7 +81,7 @@ test milliTimestamp { const margin = ns_per_ms * 50; const time_0 = milliTimestamp(); - sleep(ns_per_ms); + std.Thread.sleep(ns_per_ms); const time_1 = milliTimestamp(); const interval = time_1 - time_0; try testing.expect(interval > 0); @@ -359,7 +285,7 @@ test Timer { const margin = ns_per_ms * 150; var timer = try Timer.start(); - sleep(10 * ns_per_ms); + std.Thread.sleep(10 * ns_per_ms); const time_0 = timer.read(); try testing.expect(time_0 > 0); // Tests should not depend on timings: skip test if outside margin. diff --git a/zig/lib/std/zig.zig b/zig/lib/std/zig.zig index 325b7bea90..c3ce106634 100644 --- a/zig/lib/std/zig.zig +++ b/zig/lib/std/zig.zig @@ -233,7 +233,6 @@ pub fn binNameAlloc(allocator: Allocator, options: BinNameOptions) error{OutOfMe }), }, .nvptx => return std.fmt.allocPrint(allocator, "{s}.ptx", .{root_name}), - .dxcontainer => return std.fmt.allocPrint(allocator, "{s}.dxil", .{root_name}), } } diff --git a/zig/lib/std/zig/AstGen.zig b/zig/lib/std/zig/AstGen.zig index 14902a6726..7e11f8d44b 100644 --- a/zig/lib/std/zig/AstGen.zig +++ b/zig/lib/std/zig/AstGen.zig @@ -2716,7 +2716,7 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .array_type_sentinel, .elem_type, .indexable_ptr_elem_type, - .vector_elem_type, + .vec_arr_elem_type, .vector_type, .indexable_ptr_len, .anyframe_type, @@ -2901,7 +2901,6 @@ fn addEnsureResult(gz: *GenZir, maybe_unused_result: Zir.Inst.Ref, statement: As .extended => switch (gz.astgen.instructions.items(.data)[@intFromEnum(inst)].extended.opcode) { .breakpoint, .disable_instrumentation, - .fence, .set_float_mode, .set_align_stack, .branch_hint, @@ -3156,6 +3155,9 @@ fn deferStmt( const have_err_code = scope_tag == .defer_error and payload_token != 0; const sub_scope = if (!have_err_code) &defer_gen.base else blk: { const ident_name = try gz.astgen.identAsString(payload_token); + if (std.mem.eql(u8, tree.tokenSlice(payload_token), "_")) { + return gz.astgen.failTok(payload_token, "discard of error capture; omit it instead", .{}); + } const remapped_err_code: Zir.Inst.Index = @enumFromInt(gz.astgen.instructions.len); opt_remapped_err_code = remapped_err_code.toOptional(); try gz.astgen.instructions.append(gz.astgen.gpa, .{ @@ -9139,7 +9141,7 @@ fn minMax( ) InnerError!Zir.Inst.Ref { const astgen = gz.astgen; if (args.len < 2) { - return astgen.failNode(node, "expected at least 2 arguments, found 0", .{}); + return astgen.failNode(node, "expected at least 2 arguments, found {}", .{args.len}); } if (args.len == 2) { const tag: Zir.Inst.Tag = switch (op) { @@ -9304,15 +9306,6 @@ fn builtinCall( }); return rvalue(gz, ri, result, node); }, - .fence => { - const atomic_order_ty = try gz.addBuiltinValue(node, .atomic_order); - const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = atomic_order_ty } }, params[0]); - _ = try gz.addExtendedPayload(.fence, Zir.Inst.UnNode{ - .node = gz.nodeIndexToRelative(node), - .operand = order, - }); - return rvalue(gz, ri, .void_value, node); - }, .set_float_mode => { const float_mode_ty = try gz.addBuiltinValue(node, .float_mode); const order = try expr(gz, scope, .{ .rl = .{ .coerced_ty = float_mode_ty } }, params[0]); @@ -9536,7 +9529,7 @@ fn builtinCall( .splat => { const result_type = try ri.rl.resultTypeForCast(gz, node, builtin_name); - const elem_type = try gz.addUnNode(.vector_elem_type, result_type, node); + const elem_type = try gz.addUnNode(.vec_arr_elem_type, result_type, node); const scalar = try expr(gz, scope, .{ .rl = .{ .ty = elem_type } }, params[0]); const result = try gz.addPlNode(.splat, node, Zir.Inst.Bin{ .lhs = result_type, diff --git a/zig/lib/std/zig/AstRlAnnotate.zig b/zig/lib/std/zig/AstRlAnnotate.zig index 597baa2936..104cea1154 100644 --- a/zig/lib/std/zig/AstRlAnnotate.zig +++ b/zig/lib/std/zig/AstRlAnnotate.zig @@ -908,7 +908,6 @@ fn builtinCall(astrl: *AstRlAnnotate, block: ?*Block, ri: ResultInfo, node: Ast. .c_include, .wasm_memory_size, .splat, - .fence, .set_float_mode, .set_align_stack, .type_info, diff --git a/zig/lib/std/zig/BuiltinFn.zig b/zig/lib/std/zig/BuiltinFn.zig index 95c6c7be12..6b0d0cc0a2 100644 --- a/zig/lib/std/zig/BuiltinFn.zig +++ b/zig/lib/std/zig/BuiltinFn.zig @@ -48,7 +48,6 @@ pub const Tag = enum { error_cast, @"export", @"extern", - fence, field, field_parent_ptr, float_cast, @@ -500,13 +499,6 @@ pub const list = list: { .param_count = 2, }, }, - .{ - "@fence", - .{ - .tag = .fence, - .param_count = 1, - }, - }, .{ "@field", .{ diff --git a/zig/lib/std/zig/LibCDirs.zig b/zig/lib/std/zig/LibCDirs.zig index 8fb961c187..8b8a3a8d42 100644 --- a/zig/lib/std/zig/LibCDirs.zig +++ b/zig/lib/std/zig/LibCDirs.zig @@ -69,7 +69,7 @@ pub fn detect( // On windows, instead of the native (mingw) abi, we want to check // for the MSVC abi as a fallback. const use_system_abi = if (builtin.os.tag == .windows) - target.abi == .msvc + target.abi == .msvc or target.abi == .itanium else is_native_abi; @@ -242,35 +242,20 @@ fn libCGenericName(target: std.Target) [:0]const u8 { .muslx32, .none, .ohos, + .ohoseabi, => return "musl", .code16, .eabi, .eabihf, .ilp32, .android, + .androideabi, .msvc, .itanium, .cygnus, .simulator, .macabi, => unreachable, - - .pixel, - .vertex, - .geometry, - .hull, - .domain, - .compute, - .library, - .raygeneration, - .intersection, - .anyhit, - .closesthit, - .miss, - .callable, - .mesh, - .amplification, - => unreachable, } } diff --git a/zig/lib/std/zig/LibCInstallation.zig b/zig/lib/std/zig/LibCInstallation.zig index 686471bde5..3d163532d1 100644 --- a/zig/lib/std/zig/LibCInstallation.zig +++ b/zig/lib/std/zig/LibCInstallation.zig @@ -86,14 +86,14 @@ pub fn parse( return error.ParseError; } - if (self.msvc_lib_dir == null and os_tag == .windows and target.abi == .msvc) { + if (self.msvc_lib_dir == null and os_tag == .windows and (target.abi == .msvc or target.abi == .itanium)) { log.err("msvc_lib_dir may not be empty for {s}-{s}", .{ @tagName(os_tag), @tagName(target.abi), }); return error.ParseError; } - if (self.kernel32_lib_dir == null and os_tag == .windows and target.abi == .msvc) { + if (self.kernel32_lib_dir == null and os_tag == .windows and (target.abi == .msvc or target.abi == .itanium)) { log.err("kernel32_lib_dir may not be empty for {s}-{s}", .{ @tagName(os_tag), @tagName(target.abi), @@ -690,12 +690,340 @@ fn appendCcExe(args: *std.ArrayList([]const u8), skip_cc_env_var: bool) !void { } } +/// These are basenames. This data is produced with a pure function. See also +/// `CsuPaths`. +pub const CrtBasenames = struct { + crt0: ?[]const u8 = null, + crti: ?[]const u8 = null, + crtbegin: ?[]const u8 = null, + crtend: ?[]const u8 = null, + crtn: ?[]const u8 = null, + + pub const GetArgs = struct { + target: std.Target, + link_libc: bool, + output_mode: std.builtin.OutputMode, + link_mode: std.builtin.LinkMode, + pie: bool, + }; + + /// Determine file system path names of C runtime startup objects for supported + /// link modes. + pub fn get(args: GetArgs) CrtBasenames { + // crt objects are only required for libc. + if (!args.link_libc) return .{}; + + // Flatten crt cases. + const mode: enum { + dynamic_lib, + dynamic_exe, + dynamic_pie, + static_exe, + static_pie, + } = switch (args.output_mode) { + .Obj => return .{}, + .Lib => switch (args.link_mode) { + .dynamic => .dynamic_lib, + .static => return .{}, + }, + .Exe => switch (args.link_mode) { + .dynamic => if (args.pie) .dynamic_pie else .dynamic_exe, + .static => if (args.pie) .static_pie else .static_exe, + }, + }; + + const target = args.target; + + if (target.isAndroid()) return switch (mode) { + .dynamic_lib => .{ + .crtbegin = "crtbegin_so.o", + .crtend = "crtend_so.o", + }, + .dynamic_exe, .dynamic_pie => .{ + .crtbegin = "crtbegin_dynamic.o", + .crtend = "crtend_android.o", + }, + .static_exe, .static_pie => .{ + .crtbegin = "crtbegin_static.o", + .crtend = "crtend_android.o", + }, + }; + + return switch (target.os.tag) { + .linux => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtn = "crtn.o", + }, + .dynamic_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtn = "crtn.o", + }, + .dynamic_pie => .{ + .crt0 = "Scrt1.o", + .crti = "crti.o", + .crtn = "crtn.o", + }, + .static_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtn = "crtn.o", + }, + .static_pie => .{ + .crt0 = "rcrt1.o", + .crti = "crti.o", + .crtn = "crtn.o", + }, + }, + .dragonfly => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .dynamic_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .dynamic_pie => .{ + .crt0 = "Scrt1.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .static_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .static_pie => .{ + .crt0 = "Scrt1.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + }, + .freebsd => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .dynamic_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .dynamic_pie => .{ + .crt0 = "Scrt1.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .static_exe => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtbegin = "crtbeginT.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .static_pie => .{ + .crt0 = "Scrt1.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + }, + .netbsd => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .dynamic_exe => .{ + .crt0 = "crt0.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .dynamic_pie => .{ + .crt0 = "crt0.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .static_exe => .{ + .crt0 = "crt0.o", + .crti = "crti.o", + .crtbegin = "crtbeginT.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .static_pie => .{ + .crt0 = "crt0.o", + .crti = "crti.o", + .crtbegin = "crtbeginT.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + }, + .openbsd => switch (mode) { + .dynamic_lib => .{ + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + }, + .dynamic_exe, .dynamic_pie => .{ + .crt0 = "crt0.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + }, + .static_exe, .static_pie => .{ + .crt0 = "rcrt0.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + }, + }, + .haiku => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .dynamic_exe => .{ + .crt0 = "start_dyn.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .dynamic_pie => .{ + .crt0 = "start_dyn.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + .static_exe => .{ + .crt0 = "start_dyn.o", + .crti = "crti.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + .crtn = "crtn.o", + }, + .static_pie => .{ + .crt0 = "start_dyn.o", + .crti = "crti.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + .crtn = "crtn.o", + }, + }, + .solaris, .illumos => switch (mode) { + .dynamic_lib => .{ + .crti = "crti.o", + .crtn = "crtn.o", + }, + .dynamic_exe, .dynamic_pie => .{ + .crt0 = "crt1.o", + .crti = "crti.o", + .crtn = "crtn.o", + }, + .static_exe, .static_pie => .{}, + }, + else => .{}, + }; + } +}; + +pub const CrtPaths = struct { + crt0: ?Path = null, + crti: ?Path = null, + crtbegin: ?Path = null, + crtend: ?Path = null, + crtn: ?Path = null, +}; + +pub fn resolveCrtPaths( + lci: LibCInstallation, + arena: Allocator, + crt_basenames: CrtBasenames, + target: std.Target, +) error{ OutOfMemory, LibCInstallationMissingCrtDir }!CrtPaths { + const crt_dir_path: Path = .{ + .root_dir = std.Build.Cache.Directory.cwd(), + .sub_path = lci.crt_dir orelse return error.LibCInstallationMissingCrtDir, + }; + switch (target.os.tag) { + .dragonfly => { + const gccv: []const u8 = if (target.os.version_range.semver.isAtLeast(.{ + .major = 5, + .minor = 4, + .patch = 0, + }) orelse true) "gcc80" else "gcc54"; + return .{ + .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, + .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, + .crtbegin = if (crt_basenames.crtbegin) |basename| .{ + .root_dir = crt_dir_path.root_dir, + .sub_path = try fs.path.join(arena, &.{ crt_dir_path.sub_path, gccv, basename }), + } else null, + .crtend = if (crt_basenames.crtend) |basename| .{ + .root_dir = crt_dir_path.root_dir, + .sub_path = try fs.path.join(arena, &.{ crt_dir_path.sub_path, gccv, basename }), + } else null, + .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, + }; + }, + .haiku => { + const gcc_dir_path: Path = .{ + .root_dir = std.Build.Cache.Directory.cwd(), + .sub_path = lci.gcc_dir orelse return error.LibCInstallationMissingCrtDir, + }; + return .{ + .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, + .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, + .crtbegin = if (crt_basenames.crtbegin) |basename| try gcc_dir_path.join(arena, basename) else null, + .crtend = if (crt_basenames.crtend) |basename| try gcc_dir_path.join(arena, basename) else null, + .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, + }; + }, + else => { + return .{ + .crt0 = if (crt_basenames.crt0) |basename| try crt_dir_path.join(arena, basename) else null, + .crti = if (crt_basenames.crti) |basename| try crt_dir_path.join(arena, basename) else null, + .crtbegin = if (crt_basenames.crtbegin) |basename| try crt_dir_path.join(arena, basename) else null, + .crtend = if (crt_basenames.crtend) |basename| try crt_dir_path.join(arena, basename) else null, + .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, + }; + }, + } +} + const LibCInstallation = @This(); const std = @import("std"); const builtin = @import("builtin"); const Target = std.Target; const fs = std.fs; const Allocator = std.mem.Allocator; +const Path = std.Build.Cache.Path; const is_darwin = builtin.target.isDarwin(); const is_windows = builtin.target.os.tag == .windows; diff --git a/zig/lib/std/zig/Zir.zig b/zig/lib/std/zig/Zir.zig index dda7e7bbd0..9c76f72663 100644 --- a/zig/lib/std/zig/Zir.zig +++ b/zig/lib/std/zig/Zir.zig @@ -247,9 +247,9 @@ pub const Inst = struct { /// element type. Emits a compile error if the type is not an indexable pointer. /// Uses the `un_node` field. indexable_ptr_elem_type, - /// Given a vector type, returns its element type. + /// Given a vector or array type, returns its element type. /// Uses the `un_node` field. - vector_elem_type, + vec_arr_elem_type, /// Given a pointer to an indexable object, returns the len property. This is /// used by for loops. This instruction also emits a for-loop specific compile /// error if the indexable object is not indexable. @@ -1065,7 +1065,7 @@ pub const Inst = struct { .vector_type, .elem_type, .indexable_ptr_elem_type, - .vector_elem_type, + .vec_arr_elem_type, .indexable_ptr_len, .anyframe_type, .as_node, @@ -1375,7 +1375,7 @@ pub const Inst = struct { .vector_type, .elem_type, .indexable_ptr_elem_type, - .vector_elem_type, + .vec_arr_elem_type, .indexable_ptr_len, .anyframe_type, .as_node, @@ -1575,7 +1575,7 @@ pub const Inst = struct { => false, .extended => switch (data.extended.opcode) { - .fence, .branch_hint, .breakpoint, .disable_instrumentation => true, + .branch_hint, .breakpoint, .disable_instrumentation => true, else => false, }, }; @@ -1607,7 +1607,7 @@ pub const Inst = struct { .vector_type = .pl_node, .elem_type = .un_node, .indexable_ptr_elem_type = .un_node, - .vector_elem_type = .un_node, + .vec_arr_elem_type = .un_node, .indexable_ptr_len = .un_node, .anyframe_type = .un_node, .as_node = .pl_node, @@ -1979,9 +1979,6 @@ pub const Inst = struct { /// The `@prefetch` builtin. /// `operand` is payload index to `BinNode`. prefetch, - /// Implements the `@fence` builtin. - /// `operand` is payload index to `UnNode`. - fence, /// Implement builtin `@setFloatMode`. /// `operand` is payload index to `UnNode`. set_float_mode, @@ -3784,7 +3781,7 @@ fn findDeclsInner( .vector_type, .elem_type, .indexable_ptr_elem_type, - .vector_elem_type, + .vec_arr_elem_type, .indexable_ptr_len, .anyframe_type, .as_node, @@ -4014,7 +4011,6 @@ fn findDeclsInner( .wasm_memory_size, .wasm_memory_grow, .prefetch, - .fence, .set_float_mode, .set_align_stack, .error_cast, diff --git a/zig/lib/std/zig/system.zig b/zig/lib/std/zig/system.zig index 046bd3854e..5feb08ab28 100644 --- a/zig/lib/std/zig/system.zig +++ b/zig/lib/std/zig/system.zig @@ -172,6 +172,7 @@ pub const DetectError = error{ DeviceBusy, OSVersionDetectionFail, Unexpected, + ProcessNotFound, }; /// Given a `Target.Query`, which specifies in detail which parts of the @@ -385,6 +386,16 @@ pub fn resolveTargetQuery(query: Target.Query) DetectError!Target { query.cpu_features_sub, ); + if (cpu_arch == .hexagon) { + // Both LLVM and LLD have broken support for the small data area. Yet LLVM has the feature + // on by default for all Hexagon CPUs. Clang sort of solves this by defaulting the `-gpsize` + // command line parameter for the Hexagon backend to 0, so that no constants get placed in + // the SDA. (This of course breaks down if the user passes `-G ` to Clang...) We can't do + // the `-gpsize` hack because we can have multiple concurrent LLVM emit jobs, and command + // line options in LLVM are shared globally. So just force this feature off. Lovely stuff. + result.cpu.features.removeFeature(@intFromEnum(Target.hexagon.Feature.small_data)); + } + // https://github.com/llvm/llvm-project/issues/105978 if (result.cpu.arch.isArmOrThumb() and result.floatAbi() == .soft) { result.cpu.features.removeFeature(@intFromEnum(Target.arm.Feature.vfp2)); @@ -443,6 +454,7 @@ pub const AbiAndDynamicLinkerFromFileError = error{ Unexpected, UnexpectedEndOfFile, NameTooLong, + ProcessNotFound, }; pub fn abiAndDynamicLinkerFromFile( @@ -831,6 +843,7 @@ fn glibcVerFromRPath(rpath: []const u8) !std.SemanticVersion { error.UnableToReadElfFile, error.Unexpected, error.FileSystem, + error.ProcessNotFound, => |e| return e, }; } @@ -1077,6 +1090,7 @@ fn detectAbiAndDynamicLinker( const len = preadAtLeast(file, &buffer, 0, min_len) catch |err| switch (err) { error.UnexpectedEndOfFile, error.UnableToReadElfFile, + error.ProcessNotFound, => return defaultAbiAndDynamicLinker(cpu, os, query), else => |e| return e, @@ -1120,6 +1134,7 @@ fn detectAbiAndDynamicLinker( error.SymLinkLoop, error.ProcessFdQuotaExceeded, error.SystemFdQuotaExceeded, + error.ProcessNotFound, => |e| return e, error.UnableToReadElfFile, @@ -1147,7 +1162,7 @@ fn defaultAbiAndDynamicLinker(cpu: Target.Cpu, os: Target.Os, query: Target.Quer .abi = abi, .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), .dynamic_linker = if (query.dynamic_linker.get() == null) - Target.DynamicLinker.standard(cpu, os.tag, abi) + Target.DynamicLinker.standard(cpu, os, abi) else query.dynamic_linker, }; @@ -1176,6 +1191,8 @@ fn preadAtLeast(file: fs.File, buf: []u8, offset: u64, min_read_len: usize) !usi error.Unexpected => return error.Unexpected, error.InputOutput => return error.FileSystem, error.AccessDenied => return error.Unexpected, + error.ProcessNotFound => return error.ProcessNotFound, + error.LockViolation => return error.UnableToReadElfFile, }; if (len == 0) return error.UnexpectedEndOfFile; i += len; diff --git a/zig/lib/std/zig/target.zig b/zig/lib/std/zig/target.zig index b60586da85..59fccc582c 100644 --- a/zig/lib/std/zig/target.zig +++ b/zig/lib/std/zig/target.zig @@ -35,6 +35,7 @@ pub const available_libcs = [_]ArchOsAbi{ .{ .arch = .x86, .os = .linux, .abi = .musl }, .{ .arch = .x86, .os = .windows, .abi = .gnu }, .{ .arch = .loongarch64, .os = .linux, .abi = .gnu, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 } }, + .{ .arch = .loongarch64, .os = .linux, .abi = .gnusf, .glibc_min = .{ .major = 2, .minor = 36, .patch = 0 } }, .{ .arch = .loongarch64, .os = .linux, .abi = .musl }, .{ .arch = .m68k, .os = .linux, .abi = .gnu }, .{ .arch = .m68k, .os = .linux, .abi = .musl }, diff --git a/zig/lib/std/zig/tokenizer.zig b/zig/lib/std/zig/tokenizer.zig index db69693a93..7f82db786f 100644 --- a/zig/lib/std/zig/tokenizer.zig +++ b/zig/lib/std/zig/tokenizer.zig @@ -535,6 +535,8 @@ pub const Tokenizer = struct { switch (self.buffer[self.index]) { 0 => if (self.index == self.buffer.len) { result.tag = .invalid; + } else { + continue :state .invalid; }, '\n' => result.tag = .invalid, else => continue :state .invalid, @@ -1250,6 +1252,7 @@ test "invalid token characters" { test "invalid literal/comment characters" { try testTokenize("\"\x00\"", &.{.invalid}); + try testTokenize("`\x00`", &.{.invalid}); try testTokenize("//\x00", &.{.invalid}); try testTokenize("//\x1f", &.{.invalid}); try testTokenize("//\x7f", &.{.invalid}); diff --git a/zig/lib/tsan/builtins/assembly.h b/zig/lib/tsan/builtins/assembly.h new file mode 100644 index 0000000000..8c42fc7734 --- /dev/null +++ b/zig/lib/tsan/builtins/assembly.h @@ -0,0 +1,293 @@ +//===-- assembly.h - compiler-rt assembler support macros -----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines macros for use in compiler-rt assembler source. +// This file is not part of the interface of this library. +// +//===----------------------------------------------------------------------===// + +#ifndef COMPILERRT_ASSEMBLY_H +#define COMPILERRT_ASSEMBLY_H + +#if defined(__linux__) && defined(__CET__) +#if __has_include() +#include +#endif +#endif + +#if defined(__APPLE__) && defined(__aarch64__) +#define SEPARATOR %% +#else +#define SEPARATOR ; +#endif + +#if defined(__APPLE__) +#define HIDDEN(name) .private_extern name +#define LOCAL_LABEL(name) L_##name +// tell linker it can break up file at label boundaries +#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols +#define SYMBOL_IS_FUNC(name) +#define CONST_SECTION .const + +#define NO_EXEC_STACK_DIRECTIVE + +#elif defined(__ELF__) + +#define HIDDEN(name) .hidden name +#define LOCAL_LABEL(name) .L_##name +#define FILE_LEVEL_DIRECTIVE +#if defined(__arm__) || defined(__aarch64__) +#define SYMBOL_IS_FUNC(name) .type name,%function +#else +#define SYMBOL_IS_FUNC(name) .type name,@function +#endif +#define CONST_SECTION .section .rodata + +#if defined(__GNU__) || defined(__FreeBSD__) || defined(__Fuchsia__) || \ + defined(__linux__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + +#else // !__APPLE__ && !__ELF__ + +#define HIDDEN(name) +#define LOCAL_LABEL(name) .L ## name +#define FILE_LEVEL_DIRECTIVE +#define SYMBOL_IS_FUNC(name) \ + .def name SEPARATOR \ + .scl 2 SEPARATOR \ + .type 32 SEPARATOR \ + .endef +#define CONST_SECTION .section .rdata,"rd" + +#define NO_EXEC_STACK_DIRECTIVE + +#endif + +#if defined(__arm__) || defined(__aarch64__) +#define FUNC_ALIGN \ + .text SEPARATOR \ + .balign 16 SEPARATOR +#else +#define FUNC_ALIGN +#endif + +// BTI and PAC gnu property note +#define NT_GNU_PROPERTY_TYPE_0 5 +#define GNU_PROPERTY_AARCH64_FEATURE_1_AND 0xc0000000 +#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI 1 +#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC 2 + +#if defined(__ARM_FEATURE_BTI_DEFAULT) +#define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI +#else +#define BTI_FLAG 0 +#endif + +#if __ARM_FEATURE_PAC_DEFAULT & 3 +#define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC +#else +#define PAC_FLAG 0 +#endif + +#define GNU_PROPERTY(type, value) \ + .pushsection .note.gnu.property, "a" SEPARATOR \ + .p2align 3 SEPARATOR \ + .word 4 SEPARATOR \ + .word 16 SEPARATOR \ + .word NT_GNU_PROPERTY_TYPE_0 SEPARATOR \ + .asciz "GNU" SEPARATOR \ + .word type SEPARATOR \ + .word 4 SEPARATOR \ + .word value SEPARATOR \ + .word 0 SEPARATOR \ + .popsection + +#if BTI_FLAG != 0 +#define BTI_C hint #34 +#define BTI_J hint #36 +#else +#define BTI_C +#define BTI_J +#endif + +#if (BTI_FLAG | PAC_FLAG) != 0 +#define GNU_PROPERTY_BTI_PAC \ + GNU_PROPERTY(GNU_PROPERTY_AARCH64_FEATURE_1_AND, BTI_FLAG | PAC_FLAG) +#else +#define GNU_PROPERTY_BTI_PAC +#endif + +#if defined(__clang__) || defined(__GCC_HAVE_DWARF2_CFI_ASM) +#define CFI_START .cfi_startproc +#define CFI_END .cfi_endproc +#else +#define CFI_START +#define CFI_END +#endif + +#if defined(__arm__) + +// Determine actual [ARM][THUMB[1][2]] ISA using compiler predefined macros: +// - for '-mthumb -march=armv6' compiler defines '__thumb__' +// - for '-mthumb -march=armv7' compiler defines '__thumb__' and '__thumb2__' +#if defined(__thumb2__) || defined(__thumb__) +#define DEFINE_CODE_STATE .thumb SEPARATOR +#define DECLARE_FUNC_ENCODING .thumb_func SEPARATOR +#if defined(__thumb2__) +#define USE_THUMB_2 +#define IT(cond) it cond +#define ITT(cond) itt cond +#define ITE(cond) ite cond +#else +#define USE_THUMB_1 +#define IT(cond) +#define ITT(cond) +#define ITE(cond) +#endif // defined(__thumb__2) +#else // !defined(__thumb2__) && !defined(__thumb__) +#define DEFINE_CODE_STATE .arm SEPARATOR +#define DECLARE_FUNC_ENCODING +#define IT(cond) +#define ITT(cond) +#define ITE(cond) +#endif + +#if defined(USE_THUMB_1) && defined(USE_THUMB_2) +#error "USE_THUMB_1 and USE_THUMB_2 can't be defined together." +#endif + +#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 +#define ARM_HAS_BX +#endif +#if !defined(__ARM_FEATURE_CLZ) && !defined(USE_THUMB_1) && \ + (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__))) +#define __ARM_FEATURE_CLZ +#endif + +#ifdef ARM_HAS_BX +#define JMP(r) bx r +#define JMPc(r, c) bx##c r +#else +#define JMP(r) mov pc, r +#define JMPc(r, c) mov##c pc, r +#endif + +// pop {pc} can't switch Thumb mode on ARMv4T +#if __ARM_ARCH >= 5 +#define POP_PC() pop {pc} +#else +#define POP_PC() \ + pop {ip}; \ + JMP(ip) +#endif + +#if defined(USE_THUMB_2) +#define WIDE(op) op.w +#else +#define WIDE(op) op +#endif +#else // !defined(__arm) +#define DECLARE_FUNC_ENCODING +#define DEFINE_CODE_STATE +#endif + +#define GLUE2_(a, b) a##b +#define GLUE(a, b) GLUE2_(a, b) +#define GLUE2(a, b) GLUE2_(a, b) +#define GLUE3_(a, b, c) a##b##c +#define GLUE3(a, b, c) GLUE3_(a, b, c) +#define GLUE4_(a, b, c, d) a##b##c##d +#define GLUE4(a, b, c, d) GLUE4_(a, b, c, d) + +#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) + +#ifdef VISIBILITY_HIDDEN +#define DECLARE_SYMBOL_VISIBILITY(name) \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR +#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) \ + HIDDEN(name) SEPARATOR +#else +#define DECLARE_SYMBOL_VISIBILITY(name) +#define DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) +#endif + +#define DEFINE_COMPILERRT_FUNCTION(name) \ + DEFINE_CODE_STATE \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) \ + DECLARE_FUNC_ENCODING \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \ + DEFINE_CODE_STATE \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ + .thumb_func SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \ + DEFINE_CODE_STATE \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_FUNC_ENCODING \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \ + DEFINE_CODE_STATE \ + .globl name SEPARATOR \ + SYMBOL_IS_FUNC(name) SEPARATOR \ + HIDDEN(name) SEPARATOR \ + DECLARE_FUNC_ENCODING \ + name: + +#define DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(name) \ + DEFINE_CODE_STATE \ + FUNC_ALIGN \ + .globl name SEPARATOR \ + SYMBOL_IS_FUNC(name) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY_UNMANGLED(name) SEPARATOR \ + DECLARE_FUNC_ENCODING \ + name: \ + SEPARATOR CFI_START \ + SEPARATOR BTI_C + +#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ + .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR + +#if defined(__ARM_EABI__) +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \ + DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name) +#else +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) +#endif + +#ifdef __ELF__ +#define END_COMPILERRT_FUNCTION(name) \ + .size SYMBOL_NAME(name), . - SYMBOL_NAME(name) +#define END_COMPILERRT_OUTLINE_FUNCTION(name) \ + CFI_END SEPARATOR \ + .size SYMBOL_NAME(name), . - SYMBOL_NAME(name) +#else +#define END_COMPILERRT_FUNCTION(name) +#define END_COMPILERRT_OUTLINE_FUNCTION(name) \ + CFI_END +#endif + +#endif // COMPILERRT_ASSEMBLY_H diff --git a/zig/lib/tsan/interception/interception.h b/zig/lib/tsan/interception/interception.h index 069f73d276..38c152952e 100644 --- a/zig/lib/tsan/interception/interception.h +++ b/zig/lib/tsan/interception/interception.h @@ -185,6 +185,11 @@ const interpose_substitution substitution_##func_name[] \ # else # define __ASM_WEAK_WRAPPER(func) ".weak " #func "\n" # endif // SANITIZER_FREEBSD || SANITIZER_NETBSD +# if defined(__arm__) || defined(__aarch64__) +# define ASM_TYPE_FUNCTION_STR "%function" +# else +# define ASM_TYPE_FUNCTION_STR "@function" +# endif // Keep trampoline implementation in sync with sanitizer_common/sanitizer_asm.h # define DECLARE_WRAPPER(ret_type, func, ...) \ extern "C" ret_type func(__VA_ARGS__); \ @@ -196,12 +201,14 @@ const interpose_substitution substitution_##func_name[] \ __ASM_WEAK_WRAPPER(func) \ ".set " #func ", " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ ".globl " SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ - ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", %function\n" \ + ".type " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ + ASM_TYPE_FUNCTION_STR "\n" \ SANITIZER_STRINGIFY(TRAMPOLINE(func)) ":\n" \ - SANITIZER_STRINGIFY(CFI_STARTPROC) "\n" \ - SANITIZER_STRINGIFY(ASM_TAIL_CALL) " __interceptor_" \ - SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func)) "\n" \ - SANITIZER_STRINGIFY(CFI_ENDPROC) "\n" \ + C_ASM_STARTPROC "\n" \ + C_ASM_TAIL_CALL(SANITIZER_STRINGIFY(TRAMPOLINE(func)), \ + "__interceptor_" \ + SANITIZER_STRINGIFY(ASM_PREEMPTIBLE_SYM(func))) "\n" \ + C_ASM_ENDPROC "\n" \ ".size " SANITIZER_STRINGIFY(TRAMPOLINE(func)) ", " \ ".-" SANITIZER_STRINGIFY(TRAMPOLINE(func)) "\n" \ ); @@ -341,6 +348,18 @@ typedef unsigned long long uptr; #else typedef unsigned long uptr; #endif // _WIN64 + +#if defined(__ELF__) && !SANITIZER_FUCHSIA +// The use of interceptors makes many sanitizers unusable for static linking. +// Define a function, if called, will cause a linker error (undefined _DYNAMIC). +// However, -static-pie (which is not common) cannot be detected at link time. +extern uptr kDynamic[] asm("_DYNAMIC"); +inline void DoesNotSupportStaticLinking() { + [[maybe_unused]] volatile auto x = &kDynamic; +} +#else +inline void DoesNotSupportStaticLinking() {} +#endif } // namespace __interception #define INCLUDED_FROM_INTERCEPTION_LIB diff --git a/zig/lib/tsan/interception/interception_linux.h b/zig/lib/tsan/interception/interception_linux.h index 433a3d9bd7..2e01ff4457 100644 --- a/zig/lib/tsan/interception/interception_linux.h +++ b/zig/lib/tsan/interception/interception_linux.h @@ -28,12 +28,14 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, uptr func, uptr trampoline); } // namespace __interception -#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ - ::__interception::InterceptFunction( \ - #func, \ - (::__interception::uptr *)&REAL(func), \ - (::__interception::uptr)&(func), \ - (::__interception::uptr)&TRAMPOLINE(func)) +// Cast func to type of REAL(func) before casting to uptr in case it is an +// overloaded function, which is the case for some glibc functions when +// _FORTIFY_SOURCE is used. This disambiguates which overload to use. +#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ + ::__interception::InterceptFunction( \ + #func, (::__interception::uptr *)&REAL(func), \ + (::__interception::uptr)(decltype(REAL(func)))&(func), \ + (::__interception::uptr) &TRAMPOLINE(func)) // dlvsym is a GNU extension supported by some other platforms. #if SANITIZER_GLIBC || SANITIZER_FREEBSD || SANITIZER_NETBSD @@ -41,7 +43,7 @@ bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, ::__interception::InterceptFunction( \ #func, symver, \ (::__interception::uptr *)&REAL(func), \ - (::__interception::uptr)&(func), \ + (::__interception::uptr)(decltype(REAL(func)))&(func), \ (::__interception::uptr)&TRAMPOLINE(func)) #else #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ diff --git a/zig/lib/tsan/interception/interception_win.cpp b/zig/lib/tsan/interception/interception_win.cpp index 00c317510e..a638e66ecc 100644 --- a/zig/lib/tsan/interception/interception_win.cpp +++ b/zig/lib/tsan/interception/interception_win.cpp @@ -1,4 +1,4 @@ -//===-- interception_linux.cpp ----------------------------------*- C++ -*-===// +//===-- interception_win.cpp ------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -339,7 +339,7 @@ struct TrampolineMemoryRegion { uptr max_size; }; -UNUSED static const uptr kTrampolineScanLimitRange = 1 << 31; // 2 gig +UNUSED static const uptr kTrampolineScanLimitRange = 1ull << 31; // 2 gig static const int kMaxTrampolineRegion = 1024; static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion]; @@ -431,7 +431,8 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) { // The following prologues cannot be patched because of the short jump // jumping to the patching region. -#if SANITIZER_WINDOWS64 +// Short jump patterns below are only for x86_64. +# if SANITIZER_WINDOWS_x64 // ntdll!wcslen in Win11 // 488bc1 mov rax,rcx // 0fb710 movzx edx,word ptr [rax] @@ -457,7 +458,12 @@ static const u8 kPrologueWithShortJump2[] = { // Returns 0 on error. static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { -#if SANITIZER_WINDOWS64 +#if SANITIZER_ARM64 + // An ARM64 instruction is 4 bytes long. + return 4; +#endif + +# if SANITIZER_WINDOWS_x64 if (memcmp((u8*)address, kPrologueWithShortJump1, sizeof(kPrologueWithShortJump1)) == 0 || memcmp((u8*)address, kPrologueWithShortJump2, @@ -473,6 +479,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { switch (*(u8*)address) { case 0x90: // 90 : nop + case 0xC3: // C3 : ret (for small/empty function interception + case 0xCC: // CC : int 3 i.e. registering weak functions) return 1; case 0x50: // push eax / rax @@ -496,7 +504,6 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { // Cannot overwrite control-instruction. Return 0 to indicate failure. case 0xE9: // E9 XX XX XX XX : jmp