mirror of
https://github.com/ziglang/zig.git
synced 2024-11-26 15:12:31 +00:00
Merge branch 'master' into issue-21946
This commit is contained in:
commit
da0eb66b67
@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.14.0-dev.1622+2ac543388"
|
||||
PREFIX="$HOME/deps/$CACHE_BASENAME"
|
||||
ZIG="$PREFIX/bin/zig"
|
||||
|
||||
export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-9.1.0/bin:$HOME/local/bin:$PATH"
|
||||
export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-9.2.0-rc1/bin:$HOME/local/bin:$PATH"
|
||||
|
||||
# Make the `zig version` number consistent.
|
||||
# This will affect the cmake command below.
|
||||
@ -64,7 +64,7 @@ stage3-debug/bin/zig build \
|
||||
|
||||
stage3-debug/bin/zig build test docs \
|
||||
--maxrss 21000000000 \
|
||||
-Dlldb=$HOME/deps/lldb-zig/Debug-6ece8bda1/bin/lldb \
|
||||
-Dlldb=$HOME/deps/lldb-zig/Debug-bfeada333/bin/lldb \
|
||||
-fqemu \
|
||||
-fwasmtime \
|
||||
-Dstatic-llvm \
|
||||
|
@ -12,7 +12,7 @@ CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.14.0-dev.1622+2ac543388"
|
||||
PREFIX="$HOME/deps/$CACHE_BASENAME"
|
||||
ZIG="$PREFIX/bin/zig"
|
||||
|
||||
export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-9.1.0/bin:$HOME/local/bin:$PATH"
|
||||
export PATH="$HOME/deps/wasmtime-v10.0.2-$ARCH-linux:$HOME/deps/qemu-linux-x86_64-9.2.0-rc1/bin:$HOME/local/bin:$PATH"
|
||||
|
||||
# Make the `zig version` number consistent.
|
||||
# This will affect the cmake command below.
|
||||
@ -64,7 +64,7 @@ stage3-release/bin/zig build \
|
||||
|
||||
stage3-release/bin/zig build test docs \
|
||||
--maxrss 21000000000 \
|
||||
-Dlldb=$HOME/deps/lldb-zig/Release-6ece8bda1/bin/lldb \
|
||||
-Dlldb=$HOME/deps/lldb-zig/Release-bfeada333/bin/lldb \
|
||||
-fqemu \
|
||||
-fwasmtime \
|
||||
-Dstatic-llvm \
|
||||
|
@ -220,6 +220,7 @@ comptime {
|
||||
_ = @import("compiler_rt/aulldiv.zig");
|
||||
_ = @import("compiler_rt/aullrem.zig");
|
||||
_ = @import("compiler_rt/clear_cache.zig");
|
||||
_ = @import("compiler_rt/hexagon.zig");
|
||||
|
||||
if (@import("builtin").object_format != .c) {
|
||||
_ = @import("compiler_rt/atomics.zig");
|
||||
|
@ -73,13 +73,13 @@ fn __clzsi2_thumb1() callconv(.Naked) void {
|
||||
\\ subs r1, #4
|
||||
\\ movs r0, r2
|
||||
\\ 1:
|
||||
\\ ldr r3, =LUT
|
||||
\\ ldr r3, .lut
|
||||
\\ ldrb r0, [r3, r0]
|
||||
\\ subs r0, r1, r0
|
||||
\\ bx lr
|
||||
\\ .p2align 2
|
||||
\\ // Number of bits set in the 0-15 range
|
||||
\\ LUT:
|
||||
\\ .lut:
|
||||
\\ .byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4
|
||||
);
|
||||
|
||||
|
1787
lib/compiler_rt/hexagon.zig
Normal file
1787
lib/compiler_rt/hexagon.zig
Normal file
File diff suppressed because it is too large
Load Diff
1
lib/libc/musl/arch/i386/crt_arch.h
vendored
1
lib/libc/musl/arch/i386/crt_arch.h
vendored
@ -3,6 +3,7 @@ __asm__(
|
||||
".weak _DYNAMIC \n"
|
||||
".hidden _DYNAMIC \n"
|
||||
".global " START "\n"
|
||||
".type " START ",%function \n"
|
||||
START ":\n"
|
||||
" xor %ebp,%ebp \n"
|
||||
" mov %esp,%eax \n"
|
||||
|
1
lib/libc/musl/arch/x86_64/crt_arch.h
vendored
1
lib/libc/musl/arch/x86_64/crt_arch.h
vendored
@ -1,6 +1,7 @@
|
||||
__asm__(
|
||||
".text \n"
|
||||
".global " START " \n"
|
||||
".type " START ",%function \n"
|
||||
START ": \n"
|
||||
" xor %rbp,%rbp \n"
|
||||
" mov %rsp,%rdi \n"
|
||||
|
160
lib/libc/musl/libc.S
vendored
160
lib/libc/musl/libc.S
vendored
@ -7,6 +7,13 @@
|
||||
#define PTR_SIZE_BYTES 4
|
||||
#define PTR2_SIZE_BYTES 8
|
||||
#endif
|
||||
|
||||
#ifdef TIME32
|
||||
#define WEAKTIME64 .globl
|
||||
#else
|
||||
#define WEAKTIME64 .weak
|
||||
#endif
|
||||
|
||||
.bss
|
||||
.weak ___environ
|
||||
.type ___environ, %object;
|
||||
@ -168,18 +175,64 @@ _IO_putc:
|
||||
.weak _IO_putc_unlocked
|
||||
.type _IO_putc_unlocked, %function;
|
||||
_IO_putc_unlocked:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef ARCH_i386
|
||||
.globl ___tls_get_addr
|
||||
.type ___tls_get_addr, %function;
|
||||
___tls_get_addr:
|
||||
#endif
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __adjtime64
|
||||
.type __adjtime64, %function;
|
||||
__adjtime64:
|
||||
.globl __adjtimex_time64
|
||||
.type __adjtimex_time64, %function;
|
||||
__adjtimex_time64:
|
||||
#endif
|
||||
#ifdef ARCH_arm
|
||||
.globl __aeabi_atexit
|
||||
.type __aeabi_atexit, %function;
|
||||
__aeabi_atexit:
|
||||
.globl __aeabi_memclr
|
||||
.type __aeabi_memclr, %function;
|
||||
__aeabi_memclr:
|
||||
.globl __aeabi_memclr4
|
||||
.type __aeabi_memclr4, %function;
|
||||
__aeabi_memclr4:
|
||||
.globl __aeabi_memclr8
|
||||
.type __aeabi_memclr8, %function;
|
||||
__aeabi_memclr8:
|
||||
.globl __aeabi_memcpy
|
||||
.type __aeabi_memcpy, %function;
|
||||
__aeabi_memcpy:
|
||||
.globl __aeabi_memcpy4
|
||||
.type __aeabi_memcpy4, %function;
|
||||
__aeabi_memcpy4:
|
||||
.globl __aeabi_memcpy8
|
||||
.type __aeabi_memcpy8, %function;
|
||||
__aeabi_memcpy8:
|
||||
.globl __aeabi_memmove
|
||||
.type __aeabi_memmove, %function;
|
||||
__aeabi_memmove:
|
||||
.globl __aeabi_memmove4
|
||||
.type __aeabi_memmove4, %function;
|
||||
__aeabi_memmove4:
|
||||
.globl __aeabi_memmove8
|
||||
.type __aeabi_memmove8, %function;
|
||||
__aeabi_memmove8:
|
||||
.globl __aeabi_memset
|
||||
.type __aeabi_memset, %function;
|
||||
__aeabi_memset:
|
||||
.globl __aeabi_memset4
|
||||
.type __aeabi_memset4, %function;
|
||||
__aeabi_memset4:
|
||||
.globl __aeabi_memset8
|
||||
.type __aeabi_memset8, %function;
|
||||
__aeabi_memset8:
|
||||
.globl __aeabi_read_tp
|
||||
.type __aeabi_read_tp, %function;
|
||||
__aeabi_read_tp:
|
||||
#endif
|
||||
#ifdef TIME32
|
||||
.globl __aio_suspend_time64
|
||||
.type __aio_suspend_time64, %function;
|
||||
__aio_suspend_time64:
|
||||
@ -187,12 +240,12 @@ __aio_suspend_time64:
|
||||
.globl __assert_fail
|
||||
.type __assert_fail, %function;
|
||||
__assert_fail:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_mips
|
||||
.globl __cachectl
|
||||
.type __cachectl, %function;
|
||||
__cachectl:
|
||||
#endif
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __clock_adjtime64
|
||||
.type __clock_adjtime64, %function;
|
||||
__clock_adjtime64:
|
||||
@ -236,7 +289,7 @@ __cxa_atexit:
|
||||
.globl __cxa_finalize
|
||||
.type __cxa_finalize, %function;
|
||||
__cxa_finalize:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __difftime64
|
||||
.type __difftime64, %function;
|
||||
__difftime64:
|
||||
@ -247,7 +300,12 @@ __dls2b:
|
||||
.globl __dls3
|
||||
.type __dls3, %function;
|
||||
__dls3:
|
||||
#ifdef PTR32
|
||||
#ifdef FAMILY_mips
|
||||
.globl __dlstart
|
||||
.type __dlstart, %function;
|
||||
__dlstart:
|
||||
#endif
|
||||
#ifdef TIME32
|
||||
.globl __dlsym_time64
|
||||
.type __dlsym_time64, %function;
|
||||
__dlsym_time64:
|
||||
@ -312,7 +370,7 @@ __fseterr:
|
||||
.globl __fsetlocking
|
||||
.type __fsetlocking, %function;
|
||||
__fsetlocking:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.weak __fstat_time64
|
||||
.type __fstat_time64, %function;
|
||||
__fstat_time64:
|
||||
@ -347,7 +405,7 @@ __fxstatat:
|
||||
.weak __getdelim
|
||||
.type __getdelim, %function;
|
||||
__getdelim:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __getitimer_time64
|
||||
.type __getitimer_time64, %function;
|
||||
__getitimer_time64:
|
||||
@ -364,6 +422,11 @@ __gmtime64:
|
||||
.type __gmtime64_r, %function;
|
||||
__gmtime64_r:
|
||||
#endif
|
||||
#ifdef ARCH_arm
|
||||
.globl __gnu_Unwind_Find_exidx
|
||||
.type __gnu_Unwind_Find_exidx, %function;
|
||||
__gnu_Unwind_Find_exidx:
|
||||
#endif
|
||||
.globl __h_errno_location
|
||||
.type __h_errno_location, %function;
|
||||
__h_errno_location:
|
||||
@ -490,7 +553,7 @@ __libc_current_sigrtmin:
|
||||
.globl __libc_start_main
|
||||
.type __libc_start_main, %function;
|
||||
__libc_start_main:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __localtime64
|
||||
.type __localtime64, %function;
|
||||
__localtime64:
|
||||
@ -498,12 +561,12 @@ __localtime64:
|
||||
.type __localtime64_r, %function;
|
||||
__localtime64_r:
|
||||
#endif
|
||||
#if !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_riscv
|
||||
.globl __longjmp
|
||||
.type __longjmp, %function;
|
||||
__longjmp:
|
||||
#endif
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __lstat_time64
|
||||
.type __lstat_time64, %function;
|
||||
__lstat_time64:
|
||||
@ -514,7 +577,7 @@ __lutimes_time64:
|
||||
.globl __lxstat
|
||||
.type __lxstat, %function;
|
||||
__lxstat:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __mktime64
|
||||
.type __mktime64, %function;
|
||||
__mktime64:
|
||||
@ -547,7 +610,7 @@ __overflow:
|
||||
.weak __posix_getopt
|
||||
.type __posix_getopt, %function;
|
||||
__posix_getopt:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __ppoll_time64
|
||||
.type __ppoll_time64, %function;
|
||||
__ppoll_time64:
|
||||
@ -576,17 +639,7 @@ __recvmmsg_time64:
|
||||
.globl __res_state
|
||||
.type __res_state, %function;
|
||||
__res_state:
|
||||
#if !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
.globl __restore
|
||||
.type __restore, %function;
|
||||
__restore:
|
||||
#endif
|
||||
#if !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
.globl __restore_rt
|
||||
.type __restore_rt, %function;
|
||||
__restore_rt:
|
||||
#endif
|
||||
#if !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_riscv
|
||||
.globl __riscv_flush_icache
|
||||
.type __riscv_flush_icache, %function;
|
||||
__riscv_flush_icache:
|
||||
@ -594,7 +647,7 @@ __riscv_flush_icache:
|
||||
.globl __sched_cpucount
|
||||
.type __sched_cpucount, %function;
|
||||
__sched_cpucount:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __sched_rr_get_interval_time64
|
||||
.type __sched_rr_get_interval_time64, %function;
|
||||
__sched_rr_get_interval_time64:
|
||||
@ -614,7 +667,7 @@ __setitimer_time64:
|
||||
.globl __setjmp
|
||||
.type __setjmp, %function;
|
||||
__setjmp:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __settimeofday_time64
|
||||
.type __settimeofday_time64, %function;
|
||||
__settimeofday_time64:
|
||||
@ -631,7 +684,7 @@ __signbitl:
|
||||
.globl __sigsetjmp
|
||||
.type __sigsetjmp, %function;
|
||||
__sigsetjmp:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __sigtimedwait_time64
|
||||
.type __sigtimedwait_time64, %function;
|
||||
__sigtimedwait_time64:
|
||||
@ -639,7 +692,7 @@ __sigtimedwait_time64:
|
||||
.globl __stack_chk_fail
|
||||
.type __stack_chk_fail, %function;
|
||||
__stack_chk_fail:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __stat_time64
|
||||
.type __stat_time64, %function;
|
||||
__stat_time64:
|
||||
@ -692,7 +745,7 @@ __strxfrm_l:
|
||||
.weak __sysv_signal
|
||||
.type __sysv_signal, %function;
|
||||
__sysv_signal:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __thrd_sleep_time64
|
||||
.type __thrd_sleep_time64, %function;
|
||||
__thrd_sleep_time64:
|
||||
@ -718,9 +771,16 @@ __timerfd_settime64:
|
||||
.type __timespec_get_time64, %function;
|
||||
__timespec_get_time64:
|
||||
#endif
|
||||
#if !defined(ARCH_s390x)
|
||||
.globl __tls_get_addr
|
||||
.type __tls_get_addr, %function;
|
||||
__tls_get_addr:
|
||||
#endif
|
||||
#ifdef ARCH_s390x
|
||||
.globl __tls_get_offset
|
||||
.type __tls_get_offset, %function;
|
||||
__tls_get_offset:
|
||||
#endif
|
||||
.globl __tolower_l
|
||||
.type __tolower_l, %function;
|
||||
__tolower_l:
|
||||
@ -743,7 +803,7 @@ __uflow:
|
||||
.globl __uselocale
|
||||
.type __uselocale, %function;
|
||||
__uselocale:
|
||||
#ifdef PTR32
|
||||
#ifdef TIME32
|
||||
.globl __utime64
|
||||
.type __utime64, %function;
|
||||
__utime64:
|
||||
@ -796,7 +856,7 @@ _dl_debug_state:
|
||||
.globl _dlstart
|
||||
.type _dlstart, %function;
|
||||
_dlstart:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_mips) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_mips
|
||||
.globl _dlstart_data
|
||||
.type _dlstart_data, %function;
|
||||
_dlstart_data:
|
||||
@ -807,7 +867,7 @@ _exit:
|
||||
.weak _fini
|
||||
.type _fini, %function;
|
||||
_fini:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_mips
|
||||
.globl _flush_cache
|
||||
.type _flush_cache, %function;
|
||||
_flush_cache:
|
||||
@ -908,7 +968,7 @@ aligned_alloc:
|
||||
.globl alphasort
|
||||
.type alphasort, %function;
|
||||
alphasort:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_x86
|
||||
.globl arch_prctl
|
||||
.type arch_prctl, %function;
|
||||
arch_prctl:
|
||||
@ -1033,12 +1093,10 @@ cabsf:
|
||||
.globl cabsl
|
||||
.type cabsl, %function;
|
||||
cabsl:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_mips
|
||||
.weak cachectl
|
||||
.type cachectl, %function;
|
||||
cachectl:
|
||||
#endif
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
.weak cacheflush
|
||||
.type cacheflush, %function;
|
||||
cacheflush:
|
||||
@ -1232,10 +1290,10 @@ clock_getcpuclockid:
|
||||
.globl clock_getres
|
||||
.type clock_getres, %function;
|
||||
clock_getres:
|
||||
WEAK64 clock_gettime
|
||||
WEAKTIME64 clock_gettime
|
||||
.type clock_gettime, %function;
|
||||
clock_gettime:
|
||||
WEAK64 clock_nanosleep
|
||||
WEAKTIME64 clock_nanosleep
|
||||
.type clock_nanosleep, %function;
|
||||
clock_nanosleep:
|
||||
.globl clock_settime
|
||||
@ -2018,10 +2076,10 @@ fsetpos:
|
||||
.globl fsetxattr
|
||||
.type fsetxattr, %function;
|
||||
fsetxattr:
|
||||
WEAK64 fstat
|
||||
WEAKTIME64 fstat
|
||||
.type fstat, %function;
|
||||
fstat:
|
||||
WEAK64 fstatat
|
||||
WEAKTIME64 fstatat
|
||||
.type fstatat, %function;
|
||||
fstatat:
|
||||
.weak fstatfs
|
||||
@ -2063,7 +2121,7 @@ futimens:
|
||||
.globl futimes
|
||||
.type futimes, %function;
|
||||
futimes:
|
||||
WEAK64 futimesat
|
||||
WEAKTIME64 futimesat
|
||||
.type futimesat, %function;
|
||||
futimesat:
|
||||
.globl fwide
|
||||
@ -2408,7 +2466,7 @@ globfree:
|
||||
.globl gmtime
|
||||
.type gmtime, %function;
|
||||
gmtime:
|
||||
WEAK64 gmtime_r
|
||||
WEAKTIME64 gmtime_r
|
||||
.type gmtime_r, %function;
|
||||
gmtime_r:
|
||||
.globl grantpt
|
||||
@ -2549,12 +2607,12 @@ insque:
|
||||
.globl ioctl
|
||||
.type ioctl, %function;
|
||||
ioctl:
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_mips64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#if !defined(ARCH_aarch64) && !defined(ARCH_arm) && !defined(ARCH_loongarch64) && !defined(ARCH_mips64) && !defined(ARCH_mipsn32) && !defined(ARCH_riscv32) && !defined(ARCH_riscv64) && !defined(ARCH_s390x)
|
||||
.globl ioperm
|
||||
.type ioperm, %function;
|
||||
ioperm:
|
||||
#endif
|
||||
#if !defined(ARCH_riscv64) && !defined(ARCH_mips64) && !defined(ARCH_aarch64) && !defined(ARCH_riscv32) && !defined(ARCH_loongarch64)
|
||||
#if !defined(ARCH_aarch64) && !defined(ARCH_arm) && !defined(ARCH_loongarch64) && !defined(ARCH_mips64) && !defined(ARCH_mipsn32) && !defined(ARCH_riscv32) && !defined(ARCH_riscv64) && !defined(ARCH_s390x)
|
||||
.globl iopl
|
||||
.type iopl, %function;
|
||||
iopl:
|
||||
@ -2853,7 +2911,7 @@ localeconv:
|
||||
.globl localtime
|
||||
.type localtime, %function;
|
||||
localtime:
|
||||
WEAK64 localtime_r
|
||||
WEAKTIME64 localtime_r
|
||||
.type localtime_r, %function;
|
||||
localtime_r:
|
||||
.globl lockf
|
||||
@ -3552,7 +3610,7 @@ pthread_cond_init:
|
||||
.globl pthread_cond_signal
|
||||
.type pthread_cond_signal, %function;
|
||||
pthread_cond_signal:
|
||||
WEAK64 pthread_cond_timedwait
|
||||
WEAKTIME64 pthread_cond_timedwait
|
||||
.type pthread_cond_timedwait, %function;
|
||||
pthread_cond_timedwait:
|
||||
.globl pthread_cond_wait
|
||||
@ -3642,7 +3700,7 @@ pthread_mutex_lock:
|
||||
.globl pthread_mutex_setprioceiling
|
||||
.type pthread_mutex_setprioceiling, %function;
|
||||
pthread_mutex_setprioceiling:
|
||||
WEAK64 pthread_mutex_timedlock
|
||||
WEAKTIME64 pthread_mutex_timedlock
|
||||
.type pthread_mutex_timedlock, %function;
|
||||
pthread_mutex_timedlock:
|
||||
.weak pthread_mutex_trylock
|
||||
@ -3693,10 +3751,10 @@ pthread_rwlock_init:
|
||||
.weak pthread_rwlock_rdlock
|
||||
.type pthread_rwlock_rdlock, %function;
|
||||
pthread_rwlock_rdlock:
|
||||
WEAK64 pthread_rwlock_timedrdlock
|
||||
WEAKTIME64 pthread_rwlock_timedrdlock
|
||||
.type pthread_rwlock_timedrdlock, %function;
|
||||
pthread_rwlock_timedrdlock:
|
||||
WEAK64 pthread_rwlock_timedwrlock
|
||||
WEAKTIME64 pthread_rwlock_timedwrlock
|
||||
.type pthread_rwlock_timedwrlock, %function;
|
||||
pthread_rwlock_timedwrlock:
|
||||
.weak pthread_rwlock_tryrdlock
|
||||
@ -3774,7 +3832,7 @@ pthread_spin_unlock:
|
||||
.weak pthread_testcancel
|
||||
.type pthread_testcancel, %function;
|
||||
pthread_testcancel:
|
||||
WEAK64 pthread_timedjoin_np
|
||||
WEAKTIME64 pthread_timedjoin_np
|
||||
.type pthread_timedjoin_np, %function;
|
||||
pthread_timedjoin_np:
|
||||
.weak pthread_tryjoin_np
|
||||
@ -3999,7 +4057,7 @@ rintf:
|
||||
.globl rintl
|
||||
.type rintl, %function;
|
||||
rintl:
|
||||
#if !defined(ARCH_mips) && !defined(ARCH_mips64) && !defined(ARCH_x86) && !defined(ARCH_x86_64) && !defined(ARCH_powerpc) && !defined(ARCH_powerpc64) && !defined(ARCH_aarch64) && !defined(ARCH_loongarch64)
|
||||
#ifdef FAMILY_riscv
|
||||
.weak riscv_flush_icache
|
||||
.type riscv_flush_icache, %function;
|
||||
riscv_flush_icache:
|
||||
|
2
lib/libc/musl/src/signal/riscv32/restore.s
vendored
2
lib/libc/musl/src/signal/riscv32/restore.s
vendored
@ -1,7 +1,9 @@
|
||||
.global __restore
|
||||
.hidden __restore
|
||||
.type __restore, %function
|
||||
__restore:
|
||||
.global __restore_rt
|
||||
.hidden __restore_rt
|
||||
.type __restore_rt, %function
|
||||
__restore_rt:
|
||||
li a7, 139 # SYS_rt_sigreturn
|
||||
|
2
lib/libc/musl/src/signal/riscv64/restore.s
vendored
2
lib/libc/musl/src/signal/riscv64/restore.s
vendored
@ -1,7 +1,9 @@
|
||||
.global __restore
|
||||
.hidden __restore
|
||||
.type __restore, %function
|
||||
__restore:
|
||||
.global __restore_rt
|
||||
.hidden __restore_rt
|
||||
.type __restore_rt, %function
|
||||
__restore_rt:
|
||||
li a7, 139 # SYS_rt_sigreturn
|
||||
|
@ -5,6 +5,7 @@ __tls_get_offset:
|
||||
aghi %r15, -160
|
||||
|
||||
la %r2, 0(%r2, %r12)
|
||||
.hidden __tls_get_addr
|
||||
brasl %r14, __tls_get_addr
|
||||
|
||||
ear %r1, %a0
|
||||
|
@ -7,10 +7,23 @@ pub const timing_safe = @import("crypto/timing_safe.zig");
|
||||
/// Authenticated Encryption with Associated Data
|
||||
pub const aead = struct {
|
||||
pub const aegis = struct {
|
||||
pub const Aegis128L = @import("crypto/aegis.zig").Aegis128L;
|
||||
pub const Aegis128L_256 = @import("crypto/aegis.zig").Aegis128L_256;
|
||||
pub const Aegis256 = @import("crypto/aegis.zig").Aegis256;
|
||||
pub const Aegis256_256 = @import("crypto/aegis.zig").Aegis256_256;
|
||||
const variants = @import("crypto/aegis.zig");
|
||||
|
||||
pub const Aegis128X4 = variants.Aegis128X4;
|
||||
pub const Aegis128X2 = variants.Aegis128X2;
|
||||
pub const Aegis128L = variants.Aegis128L;
|
||||
|
||||
pub const Aegis256X4 = variants.Aegis256X4;
|
||||
pub const Aegis256X2 = variants.Aegis256X2;
|
||||
pub const Aegis256 = variants.Aegis256;
|
||||
|
||||
pub const Aegis128X4_256 = variants.Aegis128X4_256;
|
||||
pub const Aegis128X2_256 = variants.Aegis128X2_256;
|
||||
pub const Aegis128L_256 = variants.Aegis128L_256;
|
||||
|
||||
pub const Aegis256X4_256 = variants.Aegis256X4_256;
|
||||
pub const Aegis256X2_256 = variants.Aegis256X2_256;
|
||||
pub const Aegis256_256 = variants.Aegis256_256;
|
||||
};
|
||||
|
||||
pub const aes_gcm = struct {
|
||||
@ -44,10 +57,22 @@ pub const auth = struct {
|
||||
pub const hmac = @import("crypto/hmac.zig");
|
||||
pub const siphash = @import("crypto/siphash.zig");
|
||||
pub const aegis = struct {
|
||||
pub const Aegis128LMac = @import("crypto/aegis.zig").Aegis128LMac;
|
||||
pub const Aegis128LMac_128 = @import("crypto/aegis.zig").Aegis128LMac_128;
|
||||
pub const Aegis256Mac = @import("crypto/aegis.zig").Aegis256Mac;
|
||||
pub const Aegis256Mac_128 = @import("crypto/aegis.zig").Aegis256Mac_128;
|
||||
const variants = @import("crypto/aegis.zig");
|
||||
pub const Aegis128X4Mac = variants.Aegis128X4Mac;
|
||||
pub const Aegis128X2Mac = variants.Aegis128X2Mac;
|
||||
pub const Aegis128LMac = variants.Aegis128LMac;
|
||||
|
||||
pub const Aegis256X4Mac = variants.Aegis256X4Mac;
|
||||
pub const Aegis256X2Mac = variants.Aegis256X2Mac;
|
||||
pub const Aegis256Mac = variants.Aegis256Mac;
|
||||
|
||||
pub const Aegis128X4Mac_128 = variants.Aegis128X4Mac_128;
|
||||
pub const Aegis128X2Mac_128 = variants.Aegis128X2Mac_128;
|
||||
pub const Aegis128LMac_128 = variants.Aegis128LMac_128;
|
||||
|
||||
pub const Aegis256X4Mac_128 = variants.Aegis256X4Mac_128;
|
||||
pub const Aegis256X2Mac_128 = variants.Aegis256X2Mac_128;
|
||||
pub const Aegis256Mac_128 = variants.Aegis256Mac_128;
|
||||
};
|
||||
pub const cmac = @import("crypto/cmac.zig");
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -22,6 +22,7 @@ pub const has_hardware_support =
|
||||
(builtin.cpu.arch == .aarch64 and has_armaes);
|
||||
|
||||
pub const Block = impl.Block;
|
||||
pub const BlockVec = impl.BlockVec;
|
||||
pub const AesEncryptCtx = impl.AesEncryptCtx;
|
||||
pub const AesDecryptCtx = impl.AesDecryptCtx;
|
||||
pub const Aes128 = impl.Aes128;
|
||||
|
@ -2,18 +2,23 @@ const std = @import("../../std.zig");
|
||||
const builtin = @import("builtin");
|
||||
const mem = std.mem;
|
||||
const debug = std.debug;
|
||||
const BlockVec = @Vector(2, u64);
|
||||
|
||||
const has_vaes = builtin.cpu.arch == .x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .vaes);
|
||||
const has_avx512f = builtin.cpu.arch == .x86_64 and std.Target.x86.featureSetHas(builtin.cpu.features, .avx512f);
|
||||
|
||||
/// A single AES block.
|
||||
pub const Block = struct {
|
||||
const Repr = @Vector(2, u64);
|
||||
|
||||
/// The length of an AES block in bytes.
|
||||
pub const block_length: usize = 16;
|
||||
|
||||
/// Internal representation of a block.
|
||||
repr: BlockVec,
|
||||
repr: Repr,
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [16]u8) Block {
|
||||
const repr = mem.bytesToValue(BlockVec, bytes);
|
||||
const repr = mem.bytesToValue(Repr, bytes);
|
||||
return Block{ .repr = repr };
|
||||
}
|
||||
|
||||
@ -33,7 +38,7 @@ pub const Block = struct {
|
||||
return Block{
|
||||
.repr = asm (
|
||||
\\ vaesenc %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> BlockVec),
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[rk] "x" (round_key.repr),
|
||||
),
|
||||
@ -45,7 +50,7 @@ pub const Block = struct {
|
||||
return Block{
|
||||
.repr = asm (
|
||||
\\ vaesenclast %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> BlockVec),
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[rk] "x" (round_key.repr),
|
||||
),
|
||||
@ -57,7 +62,7 @@ pub const Block = struct {
|
||||
return Block{
|
||||
.repr = asm (
|
||||
\\ vaesdec %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> BlockVec),
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[rk] "x" (inv_round_key.repr),
|
||||
),
|
||||
@ -69,7 +74,7 @@ pub const Block = struct {
|
||||
return Block{
|
||||
.repr = asm (
|
||||
\\ vaesdeclast %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> BlockVec),
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[rk] "x" (inv_round_key.repr),
|
||||
),
|
||||
@ -168,17 +173,158 @@ pub const Block = struct {
|
||||
};
|
||||
};
|
||||
|
||||
/// A fixed-size vector of AES blocks.
|
||||
/// All operations are performed in parallel, using SIMD instructions when available.
|
||||
pub fn BlockVec(comptime blocks_count: comptime_int) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
/// The number of AES blocks the target architecture can process with a single instruction.
|
||||
pub const native_vector_size = w: {
|
||||
if (has_avx512f and blocks_count % 4 == 0) break :w 4;
|
||||
if (has_vaes and blocks_count % 2 == 0) break :w 2;
|
||||
break :w 1;
|
||||
};
|
||||
|
||||
/// The size of the AES block vector that the target architecture can process with a single instruction, in bytes.
|
||||
pub const native_word_size = native_vector_size * 16;
|
||||
|
||||
const native_words = blocks_count / native_vector_size;
|
||||
|
||||
const Repr = @Vector(native_vector_size * 2, u64);
|
||||
|
||||
/// Internal representation of a block vector.
|
||||
repr: [native_words]Repr,
|
||||
|
||||
/// Length of the block vector in bytes.
|
||||
pub const block_length: usize = blocks_count * 16;
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [blocks_count * 16]u8) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = mem.bytesToValue(Repr, bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Convert the internal representation of a block vector into a byte sequence.
|
||||
pub inline fn toBytes(block_vec: Self) [blocks_count * 16]u8 {
|
||||
var out: [blocks_count * 16]u8 = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out[i * native_word_size ..][0..native_word_size].* = mem.toBytes(block_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// XOR the block vector with a byte sequence.
|
||||
pub inline fn xorBytes(block_vec: Self, bytes: *const [blocks_count * 16]u8) [blocks_count * 16]u8 {
|
||||
var x: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
x.repr[i] = block_vec.repr[i] ^ mem.bytesToValue(Repr, bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return x.toBytes();
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn encrypt(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = asm (
|
||||
\\ vaesenc %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block_vec.repr[i]),
|
||||
[rk] "x" (round_key_vec.repr[i]),
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn encryptLast(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = asm (
|
||||
\\ vaesenclast %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block_vec.repr[i]),
|
||||
[rk] "x" (round_key_vec.repr[i]),
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn decrypt(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = asm (
|
||||
\\ vaesdec %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block_vec.repr[i]),
|
||||
[rk] "x" (inv_round_key_vec.repr[i]),
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn decryptLast(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = asm (
|
||||
\\ vaesdeclast %[rk], %[in], %[out]
|
||||
: [out] "=x" (-> Repr),
|
||||
: [in] "x" (block_vec.repr[i]),
|
||||
[rk] "x" (inv_round_key_vec.repr[i]),
|
||||
);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise XOR operation to the content of two block vectors.
|
||||
pub inline fn xorBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i] ^ block_vec2.repr[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise AND operation to the content of two block vectors.
|
||||
pub inline fn andBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i] & block_vec2.repr[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise OR operation to the content of two block vectors.
|
||||
pub inline fn orBlocks(block_vec1: Self, block_vec2: Block) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i] | block_vec2.repr[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn KeySchedule(comptime Aes: type) type {
|
||||
std.debug.assert(Aes.rounds == 10 or Aes.rounds == 14);
|
||||
const rounds = Aes.rounds;
|
||||
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
const Repr = Aes.block.Repr;
|
||||
|
||||
round_keys: [rounds + 1]Block,
|
||||
|
||||
fn drc(comptime second: bool, comptime rc: u8, t: BlockVec, tx: BlockVec) BlockVec {
|
||||
var s: BlockVec = undefined;
|
||||
var ts: BlockVec = undefined;
|
||||
fn drc(comptime second: bool, comptime rc: u8, t: Repr, tx: Repr) Repr {
|
||||
var s: Repr = undefined;
|
||||
var ts: Repr = undefined;
|
||||
return asm (
|
||||
\\ vaeskeygenassist %[rc], %[t], %[s]
|
||||
\\ vpslldq $4, %[tx], %[ts]
|
||||
@ -187,7 +333,7 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
\\ vpxor %[ts], %[r], %[r]
|
||||
\\ vpshufd %[mask], %[s], %[ts]
|
||||
\\ vpxor %[ts], %[r], %[r]
|
||||
: [r] "=&x" (-> BlockVec),
|
||||
: [r] "=&x" (-> Repr),
|
||||
[s] "=&x" (s),
|
||||
[ts] "=&x" (ts),
|
||||
: [rc] "n" (rc),
|
||||
@ -234,7 +380,7 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
inv_round_keys[i] = Block{
|
||||
.repr = asm (
|
||||
\\ vaesimc %[rk], %[inv_rk]
|
||||
: [inv_rk] "=x" (-> BlockVec),
|
||||
: [inv_rk] "=x" (-> Repr),
|
||||
: [rk] "x" (round_keys[rounds - i].repr),
|
||||
),
|
||||
};
|
||||
|
@ -1,18 +1,19 @@
|
||||
const std = @import("../../std.zig");
|
||||
const mem = std.mem;
|
||||
const debug = std.debug;
|
||||
const BlockVec = @Vector(2, u64);
|
||||
|
||||
/// A single AES block.
|
||||
pub const Block = struct {
|
||||
const Repr = @Vector(2, u64);
|
||||
|
||||
pub const block_length: usize = 16;
|
||||
|
||||
/// Internal representation of a block.
|
||||
repr: BlockVec,
|
||||
repr: Repr,
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [16]u8) Block {
|
||||
const repr = mem.bytesToValue(BlockVec, bytes);
|
||||
const repr = mem.bytesToValue(Repr, bytes);
|
||||
return Block{ .repr = repr };
|
||||
}
|
||||
|
||||
@ -36,7 +37,7 @@ pub const Block = struct {
|
||||
\\ mov %[out].16b, %[in].16b
|
||||
\\ aese %[out].16b, %[zero].16b
|
||||
\\ aesmc %[out].16b, %[out].16b
|
||||
: [out] "=&x" (-> BlockVec),
|
||||
: [out] "=&x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[zero] "x" (zero),
|
||||
)) ^ round_key.repr,
|
||||
@ -49,7 +50,7 @@ pub const Block = struct {
|
||||
.repr = (asm (
|
||||
\\ mov %[out].16b, %[in].16b
|
||||
\\ aese %[out].16b, %[zero].16b
|
||||
: [out] "=&x" (-> BlockVec),
|
||||
: [out] "=&x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[zero] "x" (zero),
|
||||
)) ^ round_key.repr,
|
||||
@ -63,7 +64,7 @@ pub const Block = struct {
|
||||
\\ mov %[out].16b, %[in].16b
|
||||
\\ aesd %[out].16b, %[zero].16b
|
||||
\\ aesimc %[out].16b, %[out].16b
|
||||
: [out] "=&x" (-> BlockVec),
|
||||
: [out] "=&x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[zero] "x" (zero),
|
||||
)) ^ inv_round_key.repr,
|
||||
@ -76,7 +77,7 @@ pub const Block = struct {
|
||||
.repr = (asm (
|
||||
\\ mov %[out].16b, %[in].16b
|
||||
\\ aesd %[out].16b, %[zero].16b
|
||||
: [out] "=&x" (-> BlockVec),
|
||||
: [out] "=&x" (-> Repr),
|
||||
: [in] "x" (block.repr),
|
||||
[zero] "x" (zero),
|
||||
)) ^ inv_round_key.repr,
|
||||
@ -165,6 +166,118 @@ pub const Block = struct {
|
||||
};
|
||||
};
|
||||
|
||||
/// A fixed-size vector of AES blocks.
|
||||
/// All operations are performed in parallel, using SIMD instructions when available.
|
||||
pub fn BlockVec(comptime blocks_count: comptime_int) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
/// The number of AES blocks the target architecture can process with a single instruction.
|
||||
pub const native_vector_size = 1;
|
||||
|
||||
/// The size of the AES block vector that the target architecture can process with a single instruction, in bytes.
|
||||
pub const native_word_size = native_vector_size * 16;
|
||||
|
||||
const native_words = blocks_count;
|
||||
|
||||
/// Internal representation of a block vector.
|
||||
repr: [native_words]Block,
|
||||
|
||||
/// Length of the block vector in bytes.
|
||||
pub const block_length: usize = blocks_count * 16;
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [blocks_count * 16]u8) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = Block.fromBytes(bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Convert the internal representation of a block vector into a byte sequence.
|
||||
pub inline fn toBytes(block_vec: Self) [blocks_count * 16]u8 {
|
||||
var out: [blocks_count * 16]u8 = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out[i * native_word_size ..][0..native_word_size].* = block_vec.repr[i].toBytes();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// XOR the block vector with a byte sequence.
|
||||
pub inline fn xorBytes(block_vec: Self, bytes: *const [blocks_count * 16]u8) [32]u8 {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].xorBytes(bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn encrypt(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].encrypt(round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn encryptLast(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].encryptLast(round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn decrypt(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].decrypt(inv_round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn decryptLast(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].decryptLast(inv_round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise XOR operation to the content of two block vectors.
|
||||
pub inline fn xorBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].xorBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise AND operation to the content of two block vectors.
|
||||
pub inline fn andBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].andBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise OR operation to the content of two block vectors.
|
||||
pub inline fn orBlocks(block_vec1: Self, block_vec2: Block) Self {
|
||||
var out: Self = undefined;
|
||||
inline for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].orBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn KeySchedule(comptime Aes: type) type {
|
||||
std.debug.assert(Aes.rounds == 10 or Aes.rounds == 14);
|
||||
const rounds = Aes.rounds;
|
||||
@ -172,17 +285,19 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
const Repr = Aes.block.Repr;
|
||||
|
||||
const zero = @Vector(2, u64){ 0, 0 };
|
||||
const mask1 = @Vector(16, u8){ 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12 };
|
||||
const mask2 = @Vector(16, u8){ 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15, 12, 13, 14, 15 };
|
||||
|
||||
round_keys: [rounds + 1]Block,
|
||||
|
||||
fn drc128(comptime rc: u8, t: BlockVec) BlockVec {
|
||||
var v1: BlockVec = undefined;
|
||||
var v2: BlockVec = undefined;
|
||||
var v3: BlockVec = undefined;
|
||||
var v4: BlockVec = undefined;
|
||||
fn drc128(comptime rc: u8, t: Repr) Repr {
|
||||
var v1: Repr = undefined;
|
||||
var v2: Repr = undefined;
|
||||
var v3: Repr = undefined;
|
||||
var v4: Repr = undefined;
|
||||
|
||||
return asm (
|
||||
\\ movi %[v2].4s, %[rc]
|
||||
@ -196,7 +311,7 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
\\ eor %[v1].16b, %[v1].16b, %[r].16b
|
||||
\\ eor %[r].16b, %[v1].16b, %[v3].16b
|
||||
\\ eor %[r].16b, %[r].16b, %[v4].16b
|
||||
: [r] "=&x" (-> BlockVec),
|
||||
: [r] "=&x" (-> Repr),
|
||||
[v1] "=&x" (v1),
|
||||
[v2] "=&x" (v2),
|
||||
[v3] "=&x" (v3),
|
||||
@ -208,11 +323,11 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
);
|
||||
}
|
||||
|
||||
fn drc256(comptime second: bool, comptime rc: u8, t: BlockVec, tx: BlockVec) BlockVec {
|
||||
var v1: BlockVec = undefined;
|
||||
var v2: BlockVec = undefined;
|
||||
var v3: BlockVec = undefined;
|
||||
var v4: BlockVec = undefined;
|
||||
fn drc256(comptime second: bool, comptime rc: u8, t: Repr, tx: Repr) Repr {
|
||||
var v1: Repr = undefined;
|
||||
var v2: Repr = undefined;
|
||||
var v3: Repr = undefined;
|
||||
var v4: Repr = undefined;
|
||||
|
||||
return asm (
|
||||
\\ movi %[v2].4s, %[rc]
|
||||
@ -226,7 +341,7 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
\\ eor %[v1].16b, %[v1].16b, %[v2].16b
|
||||
\\ eor %[v1].16b, %[v1].16b, %[v3].16b
|
||||
\\ eor %[r].16b, %[v1].16b, %[v4].16b
|
||||
: [r] "=&x" (-> BlockVec),
|
||||
: [r] "=&x" (-> Repr),
|
||||
[v1] "=&x" (v1),
|
||||
[v2] "=&x" (v2),
|
||||
[v3] "=&x" (v3),
|
||||
@ -276,7 +391,7 @@ fn KeySchedule(comptime Aes: type) type {
|
||||
inv_round_keys[i] = Block{
|
||||
.repr = asm (
|
||||
\\ aesimc %[inv_rk].16b, %[rk].16b
|
||||
: [inv_rk] "=x" (-> BlockVec),
|
||||
: [inv_rk] "=x" (-> Repr),
|
||||
: [rk] "x" (round_keys[rounds - i].repr),
|
||||
),
|
||||
};
|
||||
|
@ -2,16 +2,16 @@ const std = @import("../../std.zig");
|
||||
const math = std.math;
|
||||
const mem = std.mem;
|
||||
|
||||
const BlockVec = [4]u32;
|
||||
|
||||
const side_channels_mitigations = std.options.side_channels_mitigations;
|
||||
|
||||
/// A single AES block.
|
||||
pub const Block = struct {
|
||||
const Repr = [4]u32;
|
||||
|
||||
pub const block_length: usize = 16;
|
||||
|
||||
/// Internal representation of a block.
|
||||
repr: BlockVec align(16),
|
||||
repr: Repr align(16),
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [16]u8) Block {
|
||||
@ -19,7 +19,7 @@ pub const Block = struct {
|
||||
const s1 = mem.readInt(u32, bytes[4..8], .little);
|
||||
const s2 = mem.readInt(u32, bytes[8..12], .little);
|
||||
const s3 = mem.readInt(u32, bytes[12..16], .little);
|
||||
return Block{ .repr = BlockVec{ s0, s1, s2, s3 } };
|
||||
return Block{ .repr = Repr{ s0, s1, s2, s3 } };
|
||||
}
|
||||
|
||||
/// Convert the internal representation of a block into a byte sequence.
|
||||
@ -65,7 +65,7 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Encrypt a block with a round key *WITHOUT ANY PROTECTION AGAINST SIDE CHANNELS*
|
||||
@ -110,7 +110,7 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Encrypt a block with the last round key.
|
||||
@ -136,7 +136,7 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Decrypt a block with a round key.
|
||||
@ -161,7 +161,7 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Decrypt a block with a round key *WITHOUT ANY PROTECTION AGAINST SIDE CHANNELS*
|
||||
@ -206,7 +206,7 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Decrypt a block with the last round key.
|
||||
@ -232,12 +232,12 @@ pub const Block = struct {
|
||||
t2 ^= round_key.repr[2];
|
||||
t3 ^= round_key.repr[3];
|
||||
|
||||
return Block{ .repr = BlockVec{ t0, t1, t2, t3 } };
|
||||
return Block{ .repr = Repr{ t0, t1, t2, t3 } };
|
||||
}
|
||||
|
||||
/// Apply the bitwise XOR operation to the content of two blocks.
|
||||
pub inline fn xorBlocks(block1: Block, block2: Block) Block {
|
||||
var x: BlockVec = undefined;
|
||||
var x: Repr = undefined;
|
||||
comptime var i = 0;
|
||||
inline while (i < 4) : (i += 1) {
|
||||
x[i] = block1.repr[i] ^ block2.repr[i];
|
||||
@ -247,7 +247,7 @@ pub const Block = struct {
|
||||
|
||||
/// Apply the bitwise AND operation to the content of two blocks.
|
||||
pub inline fn andBlocks(block1: Block, block2: Block) Block {
|
||||
var x: BlockVec = undefined;
|
||||
var x: Repr = undefined;
|
||||
comptime var i = 0;
|
||||
inline while (i < 4) : (i += 1) {
|
||||
x[i] = block1.repr[i] & block2.repr[i];
|
||||
@ -257,7 +257,7 @@ pub const Block = struct {
|
||||
|
||||
/// Apply the bitwise OR operation to the content of two blocks.
|
||||
pub inline fn orBlocks(block1: Block, block2: Block) Block {
|
||||
var x: BlockVec = undefined;
|
||||
var x: Repr = undefined;
|
||||
comptime var i = 0;
|
||||
inline while (i < 4) : (i += 1) {
|
||||
x[i] = block1.repr[i] | block2.repr[i];
|
||||
@ -332,6 +332,118 @@ pub const Block = struct {
|
||||
};
|
||||
};
|
||||
|
||||
/// A fixed-size vector of AES blocks.
|
||||
/// All operations are performed in parallel, using SIMD instructions when available.
|
||||
pub fn BlockVec(comptime blocks_count: comptime_int) type {
|
||||
return struct {
|
||||
const Self = @This();
|
||||
|
||||
/// The number of AES blocks the target architecture can process with a single instruction.
|
||||
pub const native_vector_size = 1;
|
||||
|
||||
/// The size of the AES block vector that the target architecture can process with a single instruction, in bytes.
|
||||
pub const native_word_size = native_vector_size * 16;
|
||||
|
||||
const native_words = blocks_count;
|
||||
|
||||
/// Internal representation of a block vector.
|
||||
repr: [native_words]Block,
|
||||
|
||||
/// Length of the block vector in bytes.
|
||||
pub const block_length: usize = blocks_count * 16;
|
||||
|
||||
/// Convert a byte sequence into an internal representation.
|
||||
pub inline fn fromBytes(bytes: *const [blocks_count * 16]u8) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = Block.fromBytes(bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Convert the internal representation of a block vector into a byte sequence.
|
||||
pub inline fn toBytes(block_vec: Self) [blocks_count * 16]u8 {
|
||||
var out: [blocks_count * 16]u8 = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out[i * native_word_size ..][0..native_word_size].* = block_vec.repr[i].toBytes();
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// XOR the block vector with a byte sequence.
|
||||
pub inline fn xorBytes(block_vec: Self, bytes: *const [blocks_count * 16]u8) [32]u8 {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].xorBytes(bytes[i * native_word_size ..][0..native_word_size]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn encrypt(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].encrypt(round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the forward AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn encryptLast(block_vec: Self, round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].encryptLast(round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of round keys.
|
||||
pub inline fn decrypt(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].decrypt(inv_round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the inverse AES operation to the block vector with a vector of last round keys.
|
||||
pub inline fn decryptLast(block_vec: Self, inv_round_key_vec: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec.repr[i].decryptLast(inv_round_key_vec.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise XOR operation to the content of two block vectors.
|
||||
pub inline fn xorBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].xorBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise AND operation to the content of two block vectors.
|
||||
pub inline fn andBlocks(block_vec1: Self, block_vec2: Self) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].andBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/// Apply the bitwise OR operation to the content of two block vectors.
|
||||
pub inline fn orBlocks(block_vec1: Self, block_vec2: Block) Self {
|
||||
var out: Self = undefined;
|
||||
for (0..native_words) |i| {
|
||||
out.repr[i] = block_vec1.repr[i].orBlocks(block_vec2.repr[i]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn KeySchedule(comptime Aes: type) type {
|
||||
std.debug.assert(Aes.rounds == 10 or Aes.rounds == 14);
|
||||
const key_length = Aes.key_bits / 8;
|
||||
@ -671,7 +783,7 @@ fn mul(a: u8, b: u8) u8 {
|
||||
|
||||
const cache_line_bytes = std.atomic.cache_line;
|
||||
|
||||
inline fn sbox_lookup(sbox: *align(64) const [256]u8, idx0: u8, idx1: u8, idx2: u8, idx3: u8) [4]u8 {
|
||||
fn sbox_lookup(sbox: *align(64) const [256]u8, idx0: u8, idx1: u8, idx2: u8, idx3: u8) [4]u8 {
|
||||
if (side_channels_mitigations == .none) {
|
||||
return [4]u8{
|
||||
sbox[idx0],
|
||||
@ -709,7 +821,7 @@ inline fn sbox_lookup(sbox: *align(64) const [256]u8, idx0: u8, idx1: u8, idx2:
|
||||
}
|
||||
}
|
||||
|
||||
inline fn table_lookup(table: *align(64) const [4][256]u32, idx0: u8, idx1: u8, idx2: u8, idx3: u8) [4]u32 {
|
||||
fn table_lookup(table: *align(64) const [4][256]u32, idx0: u8, idx1: u8, idx2: u8, idx3: u8) [4]u32 {
|
||||
if (side_channels_mitigations == .none) {
|
||||
return [4]u32{
|
||||
table[0][idx0],
|
||||
@ -718,17 +830,18 @@ inline fn table_lookup(table: *align(64) const [4][256]u32, idx0: u8, idx1: u8,
|
||||
table[3][idx3],
|
||||
};
|
||||
} else {
|
||||
const table_len: usize = 256;
|
||||
const stride = switch (side_channels_mitigations) {
|
||||
.none => unreachable,
|
||||
.basic => table[0].len / 4,
|
||||
.medium => @max(1, @min(table[0].len, 2 * cache_line_bytes / 4)),
|
||||
.full => @max(1, @min(table[0].len, cache_line_bytes / 4)),
|
||||
.basic => table_len / 4,
|
||||
.medium => @max(1, @min(table_len, 2 * cache_line_bytes / 4)),
|
||||
.full => @max(1, @min(table_len, cache_line_bytes / 4)),
|
||||
};
|
||||
const of0 = idx0 % stride;
|
||||
const of1 = idx1 % stride;
|
||||
const of2 = idx2 % stride;
|
||||
const of3 = idx3 % stride;
|
||||
var t: [4][table[0].len / stride]u32 align(64) = undefined;
|
||||
var t: [4][table_len / stride]u32 align(64) = undefined;
|
||||
var i: usize = 0;
|
||||
while (i < t[0].len) : (i += 1) {
|
||||
const tx = table[0][i * stride ..];
|
||||
|
@ -563,15 +563,57 @@ const pbkdf_prf = struct {
|
||||
};
|
||||
|
||||
/// bcrypt-pbkdf is a key derivation function based on bcrypt.
|
||||
/// This is the function used in OpenSSH to derive encryption keys from passphrases.
|
||||
///
|
||||
/// This implementation is compatible with the OpenBSD implementation (https://github.com/openbsd/src/blob/master/lib/libutil/bcrypt_pbkdf.c).
|
||||
///
|
||||
/// Unlike the password hashing function `bcrypt`, this function doesn't silently truncate passwords longer than 72 bytes.
|
||||
pub fn pbkdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void {
|
||||
try crypto.pwhash.pbkdf2(key, pass, salt, rounds, pbkdf_prf);
|
||||
}
|
||||
|
||||
/// The function used in OpenSSH to derive encryption keys from passphrases.
|
||||
///
|
||||
/// This implementation is compatible with the OpenBSD implementation (https://github.com/openbsd/src/blob/master/lib/libutil/bcrypt_pbkdf.c).
|
||||
pub fn opensshKdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !void {
|
||||
var tmp: [32]u8 = undefined;
|
||||
var tmp2: [32]u8 = undefined;
|
||||
if (rounds < 1 or pass.len == 0 or salt.len == 0 or key.len == 0 or key.len > tmp.len * tmp.len) {
|
||||
return error.InvalidInput;
|
||||
}
|
||||
var sha2pass: [Sha512.digest_length]u8 = undefined;
|
||||
Sha512.hash(pass, &sha2pass, .{});
|
||||
const stride = (key.len + tmp.len - 1) / tmp.len;
|
||||
var amt = (key.len + stride - 1) / stride;
|
||||
if (math.shr(usize, key.len, 32) >= amt) {
|
||||
return error.InvalidInput;
|
||||
}
|
||||
var key_remainder = key.len;
|
||||
var count: u32 = 1;
|
||||
while (key_remainder > 0) : (count += 1) {
|
||||
var count_salt: [4]u8 = undefined;
|
||||
std.mem.writeInt(u32, count_salt[0..], count, .big);
|
||||
var sha2salt: [Sha512.digest_length]u8 = undefined;
|
||||
var h = Sha512.init(.{});
|
||||
h.update(salt);
|
||||
h.update(&count_salt);
|
||||
h.final(&sha2salt);
|
||||
tmp2 = pbkdf_prf.hash(sha2pass, sha2salt);
|
||||
tmp = tmp2;
|
||||
for (1..rounds) |_| {
|
||||
Sha512.hash(&tmp2, &sha2salt, .{});
|
||||
tmp2 = pbkdf_prf.hash(sha2pass, sha2salt);
|
||||
for (&tmp, tmp2) |*o, t| o.* ^= t;
|
||||
}
|
||||
amt = @min(amt, key_remainder);
|
||||
key_remainder -= for (0..amt) |i| {
|
||||
const dest = i * stride + (count - 1);
|
||||
if (dest >= key.len) break i;
|
||||
key[dest] = tmp[i];
|
||||
} else amt;
|
||||
}
|
||||
crypto.secureZero(u8, &tmp);
|
||||
crypto.secureZero(u8, &tmp2);
|
||||
crypto.secureZero(u8, &sha2pass);
|
||||
}
|
||||
|
||||
const crypt_format = struct {
|
||||
/// String prefix for bcrypt
|
||||
pub const prefix = "$2";
|
||||
@ -847,3 +889,13 @@ test "bcrypt phc format" {
|
||||
verify_options,
|
||||
);
|
||||
}
|
||||
|
||||
test "openssh kdf" {
|
||||
var key: [100]u8 = undefined;
|
||||
const pass = "password";
|
||||
const salt = "salt";
|
||||
const rounds = 5;
|
||||
try opensshKdf(pass, salt, &key, rounds);
|
||||
const expected = [_]u8{ 65, 207, 68, 58, 55, 252, 114, 141, 255, 65, 216, 175, 5, 92, 235, 68, 220, 92, 118, 161, 40, 13, 241, 190, 56, 152, 69, 136, 41, 214, 51, 205, 37, 221, 101, 59, 105, 73, 133, 36, 14, 59, 94, 212, 111, 107, 109, 237, 213, 235, 246, 119, 59, 76, 45, 130, 142, 81, 178, 231, 161, 158, 138, 108, 18, 162, 26, 50, 218, 251, 23, 66, 2, 232, 20, 202, 216, 46, 12, 250, 247, 246, 252, 23, 155, 74, 77, 195, 120, 113, 57, 88, 126, 81, 9, 249, 72, 18, 208, 160 };
|
||||
try testing.expectEqualSlices(u8, &key, &expected);
|
||||
}
|
||||
|
@ -72,6 +72,10 @@ const macs = [_]Crypto{
|
||||
Crypto{ .ty = crypto.auth.siphash.SipHash64(1, 3), .name = "siphash-1-3" },
|
||||
Crypto{ .ty = crypto.auth.siphash.SipHash128(2, 4), .name = "siphash128-2-4" },
|
||||
Crypto{ .ty = crypto.auth.siphash.SipHash128(1, 3), .name = "siphash128-1-3" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis128X4Mac, .name = "aegis-128x4 mac" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis256X4Mac, .name = "aegis-256x4 mac" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis128X2Mac, .name = "aegis-128x2 mac" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis256X2Mac, .name = "aegis-256x2 mac" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis128LMac, .name = "aegis-128l mac" },
|
||||
Crypto{ .ty = crypto.auth.aegis.Aegis256Mac, .name = "aegis-256 mac" },
|
||||
Crypto{ .ty = crypto.auth.cmac.CmacAes128, .name = "aes-cmac" },
|
||||
@ -283,7 +287,11 @@ const aeads = [_]Crypto{
|
||||
Crypto{ .ty = crypto.aead.chacha_poly.XChaCha20Poly1305, .name = "xchacha20Poly1305" },
|
||||
Crypto{ .ty = crypto.aead.chacha_poly.XChaCha8Poly1305, .name = "xchacha8Poly1305" },
|
||||
Crypto{ .ty = crypto.aead.salsa_poly.XSalsa20Poly1305, .name = "xsalsa20Poly1305" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis128X4, .name = "aegis-128x4" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis128X2, .name = "aegis-128x2" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis128L, .name = "aegis-128l" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis256X4, .name = "aegis-256x4" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis256X2, .name = "aegis-256x2" },
|
||||
Crypto{ .ty = crypto.aead.aegis.Aegis256, .name = "aegis-256" },
|
||||
Crypto{ .ty = crypto.aead.aes_gcm.Aes128Gcm, .name = "aes128-gcm" },
|
||||
Crypto{ .ty = crypto.aead.aes_gcm.Aes256Gcm, .name = "aes256-gcm" },
|
||||
|
@ -1531,9 +1531,9 @@ pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize
|
||||
}
|
||||
|
||||
pub const SafetyLock = struct {
|
||||
state: State = .unlocked,
|
||||
state: State = if (runtime_safety) .unlocked else .unknown,
|
||||
|
||||
pub const State = if (runtime_safety) enum { unlocked, locked } else enum { unlocked };
|
||||
pub const State = if (runtime_safety) enum { unlocked, locked } else enum { unknown };
|
||||
|
||||
pub fn lock(l: *SafetyLock) void {
|
||||
if (!runtime_safety) return;
|
||||
@ -1551,8 +1551,22 @@ pub const SafetyLock = struct {
|
||||
if (!runtime_safety) return;
|
||||
assert(l.state == .unlocked);
|
||||
}
|
||||
|
||||
pub fn assertLocked(l: SafetyLock) void {
|
||||
if (!runtime_safety) return;
|
||||
assert(l.state == .locked);
|
||||
}
|
||||
};
|
||||
|
||||
test SafetyLock {
|
||||
var safety_lock: SafetyLock = .{};
|
||||
safety_lock.assertUnlocked();
|
||||
safety_lock.lock();
|
||||
safety_lock.assertLocked();
|
||||
safety_lock.unlock();
|
||||
safety_lock.assertUnlocked();
|
||||
}
|
||||
|
||||
/// Detect whether the program is being executed in the Valgrind virtual machine.
|
||||
///
|
||||
/// When Valgrind integrations are disabled, this returns comptime-known false.
|
||||
|
@ -48,7 +48,8 @@ fn read(ma: *MemoryAccessor, address: usize, buf: []u8) bool {
|
||||
switch (linux.E.init(bytes_read)) {
|
||||
.SUCCESS => return bytes_read == buf.len,
|
||||
.FAULT => return false,
|
||||
.INVAL, .PERM, .SRCH => unreachable, // own pid is always valid
|
||||
.INVAL, .SRCH => unreachable, // own pid is always valid
|
||||
.PERM => {}, // Known to happen in containers.
|
||||
.NOMEM => {},
|
||||
.NOSYS => {}, // QEMU is known not to implement this syscall.
|
||||
else => unreachable, // unexpected
|
||||
|
@ -224,7 +224,6 @@ pub const Placeholder = struct {
|
||||
pub fn parse(comptime str: anytype) Placeholder {
|
||||
const view = std.unicode.Utf8View.initComptime(&str);
|
||||
comptime var parser = Parser{
|
||||
.buf = &str,
|
||||
.iter = view.iterator(),
|
||||
};
|
||||
|
||||
@ -311,10 +310,13 @@ pub const Specifier = union(enum) {
|
||||
named: []const u8,
|
||||
};
|
||||
|
||||
/// A stream based parser for format strings.
|
||||
///
|
||||
/// Allows to implement formatters compatible with std.fmt without replicating
|
||||
/// the standard library behavior.
|
||||
pub const Parser = struct {
|
||||
buf: []const u8,
|
||||
pos: usize = 0,
|
||||
iter: std.unicode.Utf8Iterator = undefined,
|
||||
iter: std.unicode.Utf8Iterator,
|
||||
|
||||
// Returns a decimal number or null if the current character is not a
|
||||
// digit
|
||||
|
@ -1692,7 +1692,7 @@ pub fn HashMapUnmanaged(
|
||||
}
|
||||
|
||||
self.size = 0;
|
||||
self.pointer_stability = .{ .state = .unlocked };
|
||||
self.pointer_stability = .{};
|
||||
std.mem.swap(Self, self, &map);
|
||||
map.deinit(allocator);
|
||||
}
|
||||
|
@ -301,8 +301,9 @@ pub fn reallocAdvanced(
|
||||
return mem.bytesAsSlice(T, new_bytes);
|
||||
}
|
||||
|
||||
/// Free an array allocated with `alloc`. To free a single item,
|
||||
/// see `destroy`.
|
||||
/// Free an array allocated with `alloc`.
|
||||
/// If memory has length 0, free is a no-op.
|
||||
/// To free a single item, see `destroy`.
|
||||
pub fn free(self: Allocator, memory: anytype) void {
|
||||
const Slice = @typeInfo(@TypeOf(memory)).pointer;
|
||||
const bytes = mem.sliceAsBytes(memory);
|
||||
|
@ -737,13 +737,15 @@ test TagPayload {
|
||||
try testing.expect(MovedEvent == @TypeOf(e.Moved));
|
||||
}
|
||||
|
||||
/// Compares two of any type for equality. Containers are compared on a field-by-field basis,
|
||||
/// where possible. Pointers are not followed.
|
||||
/// Compares two of any type for equality. Containers that do not support comparison
|
||||
/// on their own are compared on a field-by-field basis. Pointers are not followed.
|
||||
pub fn eql(a: anytype, b: @TypeOf(a)) bool {
|
||||
const T = @TypeOf(a);
|
||||
|
||||
switch (@typeInfo(T)) {
|
||||
.@"struct" => |info| {
|
||||
if (info.layout == .@"packed") return a == b;
|
||||
|
||||
inline for (info.fields) |field_info| {
|
||||
if (!eql(@field(a, field_info.name), @field(b, field_info.name))) return false;
|
||||
}
|
||||
|
@ -1817,6 +1817,7 @@ pub fn openatZ(dir_fd: fd_t, file_path: [*:0]const u8, flags: O, mode: mode_t) O
|
||||
.OPNOTSUPP => return error.FileLocksNotSupported,
|
||||
.AGAIN => return error.WouldBlock,
|
||||
.TXTBSY => return error.FileBusy,
|
||||
.NXIO => return error.NoDevice,
|
||||
.ILSEQ => |err| if (native_os == .wasi)
|
||||
return error.InvalidUtf8
|
||||
else
|
||||
|
@ -6024,7 +6024,7 @@ fn tryExpr(
|
||||
if (!parent_gz.is_comptime) {
|
||||
try emitDbgNode(parent_gz, node);
|
||||
}
|
||||
const try_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
const try_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
|
||||
const operand_rl: ResultInfo.Loc, const block_tag: Zir.Inst.Tag = switch (ri.rl) {
|
||||
.ref => .{ .ref, .try_ptr },
|
||||
@ -6577,6 +6577,7 @@ fn whileExpr(
|
||||
const astgen = parent_gz.astgen;
|
||||
const tree = astgen.tree;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
|
||||
const need_rl = astgen.nodes_need_rl.contains(node);
|
||||
const block_ri: ResultInfo = if (need_rl) ri else .{
|
||||
@ -6774,6 +6775,16 @@ fn whileExpr(
|
||||
try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
|
||||
const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
|
||||
if (!continue_scope.endsWithNoReturn()) {
|
||||
astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
|
||||
try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
|
||||
_ = try parent_gz.add(.{
|
||||
.tag = .extended,
|
||||
.data = .{ .extended = .{
|
||||
.opcode = .dbg_empty_stmt,
|
||||
.small = undefined,
|
||||
.operand = undefined,
|
||||
} },
|
||||
});
|
||||
_ = try continue_scope.addBreak(break_tag, continue_block, .void_value);
|
||||
}
|
||||
try continue_scope.setBlockBody(continue_block);
|
||||
@ -6882,6 +6893,7 @@ fn forExpr(
|
||||
}
|
||||
const tree = astgen.tree;
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_tags = tree.nodes.items(.tag);
|
||||
const node_data = tree.nodes.items(.data);
|
||||
const gpa = astgen.gpa;
|
||||
@ -7087,8 +7099,18 @@ fn forExpr(
|
||||
|
||||
try checkUsed(parent_gz, &then_scope.base, then_sub_scope);
|
||||
|
||||
const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
|
||||
astgen.advanceSourceCursor(token_starts[tree.lastToken(then_node)]);
|
||||
try emitDbgStmt(parent_gz, .{ astgen.source_line - parent_gz.decl_line, astgen.source_column });
|
||||
_ = try parent_gz.add(.{
|
||||
.tag = .extended,
|
||||
.data = .{ .extended = .{
|
||||
.opcode = .dbg_empty_stmt,
|
||||
.small = undefined,
|
||||
.operand = undefined,
|
||||
} },
|
||||
});
|
||||
|
||||
const break_tag: Zir.Inst.Tag = if (is_inline) .break_inline else .@"break";
|
||||
_ = try then_scope.addBreak(break_tag, cond_block, .void_value);
|
||||
|
||||
var else_scope = parent_gz.makeSubBlock(&cond_scope.base);
|
||||
@ -7135,6 +7157,7 @@ fn forExpr(
|
||||
.lhs = index_ptr,
|
||||
.rhs = index_plus_one,
|
||||
});
|
||||
|
||||
const repeat_tag: Zir.Inst.Tag = if (is_inline) .repeat_inline else .repeat;
|
||||
_ = try loop_scope.addNode(repeat_tag, node);
|
||||
|
||||
@ -7279,7 +7302,7 @@ fn switchExprErrUnion(
|
||||
};
|
||||
|
||||
astgen.advanceSourceCursorToNode(operand_node);
|
||||
const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
|
||||
const raw_operand = try reachableExpr(parent_gz, scope, operand_ri, operand_node, switch_node);
|
||||
const item_ri: ResultInfo = .{ .rl = .none };
|
||||
@ -7868,7 +7891,7 @@ fn switchExpr(
|
||||
const operand_ri: ResultInfo = .{ .rl = if (any_payload_is_ref) .ref else .none };
|
||||
|
||||
astgen.advanceSourceCursorToNode(operand_node);
|
||||
const operand_lc = LineColumn{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
const operand_lc: LineColumn = .{ astgen.source_line - parent_gz.decl_line, astgen.source_column };
|
||||
|
||||
const raw_operand = try expr(parent_gz, scope, operand_ri, operand_node);
|
||||
const item_ri: ResultInfo = .{ .rl = .none };
|
||||
@ -8214,7 +8237,7 @@ fn ret(gz: *GenZir, scope: *Scope, node: Ast.Node.Index) InnerError!Zir.Inst.Ref
|
||||
if (!gz.is_comptime) {
|
||||
try emitDbgNode(gz, node);
|
||||
}
|
||||
const ret_lc = LineColumn{ astgen.source_line - gz.decl_line, astgen.source_column };
|
||||
const ret_lc: LineColumn = .{ astgen.source_line - gz.decl_line, astgen.source_column };
|
||||
|
||||
const defer_outer = &astgen.fn_block.?.base;
|
||||
|
||||
|
@ -2088,6 +2088,8 @@ pub const Inst = struct {
|
||||
/// `operand` is `Zir.Inst.Ref` of the loaded LHS (*not* its type).
|
||||
/// `small` is an `Inst.InplaceOp`.
|
||||
inplace_arith_result_ty,
|
||||
/// Marks a statement that can be stepped to but produces no code.
|
||||
dbg_empty_stmt,
|
||||
|
||||
pub const InstData = struct {
|
||||
opcode: Extended,
|
||||
@ -4062,6 +4064,7 @@ fn findDeclsInner(
|
||||
.branch_hint,
|
||||
.inplace_arith_result_ty,
|
||||
.tuple_decl,
|
||||
.dbg_empty_stmt,
|
||||
=> return,
|
||||
|
||||
// `@TypeOf` has a body.
|
||||
|
@ -256,6 +256,8 @@ typedef char bool;
|
||||
#define zig_trap() __asm__ volatile("udf #0xfe")
|
||||
#elif defined(__arm__) || defined(__aarch64__)
|
||||
#define zig_trap() __asm__ volatile("udf #0xfdee")
|
||||
#elif defined(__hexagon__)
|
||||
#define zig_trap() __asm__ volatile("r27:26 = memd(#0xbadc0fee)")
|
||||
#elif defined(__loongarch__) || defined(__powerpc__)
|
||||
#define zig_trap() __asm__ volatile(".word 0x0")
|
||||
#elif defined(__mips__)
|
||||
@ -280,6 +282,8 @@ typedef char bool;
|
||||
#define zig_breakpoint() __asm__ volatile("bkpt #0x0")
|
||||
#elif defined(__aarch64__)
|
||||
#define zig_breakpoint() __asm__ volatile("brk #0xf000")
|
||||
#elif defined(__hexagon__)
|
||||
#define zig_breakpoint() __asm__ volatile("brkpt")
|
||||
#elif defined(__loongarch__)
|
||||
#define zig_breakpoint() __asm__ volatile("break 0x0")
|
||||
#elif defined(__mips__)
|
||||
|
@ -460,6 +460,8 @@ pub const Inst = struct {
|
||||
/// Result type is always void.
|
||||
/// Uses the `dbg_stmt` field.
|
||||
dbg_stmt,
|
||||
/// Marks a statement that can be stepped to but produces no code.
|
||||
dbg_empty_stmt,
|
||||
/// A block that represents an inlined function call.
|
||||
/// Uses the `ty_pl` field. Payload is `DbgInlineBlock`.
|
||||
dbg_inline_block,
|
||||
@ -1468,6 +1470,7 @@ pub fn typeOfIndex(air: *const Air, inst: Air.Inst.Index, ip: *const InternPool)
|
||||
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
.dbg_arg_inline,
|
||||
@ -1629,6 +1632,7 @@ pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
|
||||
.try_ptr,
|
||||
.try_ptr_cold,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.dbg_inline_block,
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
|
@ -417,6 +417,7 @@ fn checkBody(air: Air, body: []const Air.Inst.Index, zcu: *Zcu) bool {
|
||||
.work_group_size,
|
||||
.work_group_id,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.err_return_trace,
|
||||
.save_err_return_trace_index,
|
||||
.repeat,
|
||||
|
@ -5884,7 +5884,9 @@ pub const FileExt = enum {
|
||||
};
|
||||
|
||||
pub fn hasObjectExt(filename: []const u8) bool {
|
||||
return mem.endsWith(u8, filename, ".o") or mem.endsWith(u8, filename, ".obj");
|
||||
return mem.endsWith(u8, filename, ".o") or
|
||||
mem.endsWith(u8, filename, ".lo") or
|
||||
mem.endsWith(u8, filename, ".obj");
|
||||
}
|
||||
|
||||
pub fn hasStaticLibraryExt(filename: []const u8) bool {
|
||||
|
@ -334,6 +334,7 @@ pub fn categorizeOperand(
|
||||
.repeat,
|
||||
.switch_dispatch,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.unreach,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
@ -973,6 +974,7 @@ fn analyzeInst(
|
||||
.ret_ptr,
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
.wasm_memory_size,
|
||||
|
@ -56,6 +56,7 @@ fn verifyBody(self: *Verify, body: []const Air.Inst.Index) Error!void {
|
||||
.ret_ptr,
|
||||
.breakpoint,
|
||||
.dbg_stmt,
|
||||
.dbg_empty_stmt,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
.wasm_memory_size,
|
||||
|
29
src/Sema.zig
29
src/Sema.zig
@ -1355,6 +1355,11 @@ fn analyzeBodyInner(
|
||||
.field_parent_ptr => try sema.zirFieldParentPtr(block, extended),
|
||||
.builtin_value => try sema.zirBuiltinValue(block, extended),
|
||||
.inplace_arith_result_ty => try sema.zirInplaceArithResultTy(extended),
|
||||
.dbg_empty_stmt => {
|
||||
try sema.zirDbgEmptyStmt(block, inst);
|
||||
i += 1;
|
||||
continue;
|
||||
},
|
||||
};
|
||||
},
|
||||
|
||||
@ -2584,18 +2589,7 @@ fn validateAlign(
|
||||
src: LazySrcLoc,
|
||||
alignment: u64,
|
||||
) !Alignment {
|
||||
const result = try validateAlignAllowZero(sema, block, src, alignment);
|
||||
if (result == .none) return sema.fail(block, src, "alignment must be >= 1", .{});
|
||||
return result;
|
||||
}
|
||||
|
||||
fn validateAlignAllowZero(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
src: LazySrcLoc,
|
||||
alignment: u64,
|
||||
) !Alignment {
|
||||
if (alignment == 0) return .none;
|
||||
if (alignment == 0) return sema.fail(block, src, "alignment must be >= 1", .{});
|
||||
if (!std.math.isPowerOfTwo(alignment)) {
|
||||
return sema.fail(block, src, "alignment value '{d}' is not a power of two", .{
|
||||
alignment,
|
||||
@ -6682,6 +6676,11 @@ fn zirDbgStmt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!voi
|
||||
});
|
||||
}
|
||||
|
||||
fn zirDbgEmptyStmt(_: *Sema, block: *Block, _: Zir.Inst.Index) CompileError!void {
|
||||
if (block.is_comptime or block.ownerModule().strip) return;
|
||||
_ = try block.addNoOp(.dbg_empty_stmt);
|
||||
}
|
||||
|
||||
fn zirDbgVar(
|
||||
sema: *Sema,
|
||||
block: *Block,
|
||||
@ -20542,7 +20541,7 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
||||
else => {},
|
||||
}
|
||||
const align_bytes = (try val.getUnsignedIntSema(pt)).?;
|
||||
break :blk try sema.validateAlignAllowZero(block, align_src, align_bytes);
|
||||
break :blk try sema.validateAlign(block, align_src, align_bytes);
|
||||
} else .none;
|
||||
|
||||
const address_space: std.builtin.AddressSpace = if (inst_data.flags.has_addrspace) blk: {
|
||||
@ -26904,7 +26903,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
if (val.isGenericPoison()) {
|
||||
break :blk null;
|
||||
}
|
||||
break :blk try sema.validateAlignAllowZero(block, align_src, try val.toUnsignedIntSema(pt));
|
||||
break :blk try sema.validateAlign(block, align_src, try val.toUnsignedIntSema(pt));
|
||||
} else if (extra.data.bits.has_align_ref) blk: {
|
||||
const align_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
@ -26922,7 +26921,7 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
|
||||
error.GenericPoison => break :blk null,
|
||||
else => |e| return e,
|
||||
};
|
||||
break :blk try sema.validateAlignAllowZero(block, align_src, try align_val.toUnsignedIntSema(pt));
|
||||
break :blk try sema.validateAlign(block, align_src, try align_val.toUnsignedIntSema(pt));
|
||||
} else .none;
|
||||
|
||||
const @"addrspace": ?std.builtin.AddressSpace = if (extra.data.bits.has_addrspace_body) blk: {
|
||||
|
@ -800,6 +800,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.try_ptr_cold => try self.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => self.finishAirBookkeeping(),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
|
@ -787,6 +787,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.try_ptr_cold => try self.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => self.finishAirBookkeeping(),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
|
@ -1593,6 +1593,7 @@ fn genBody(func: *Func, body: []const Air.Inst.Index) InnerError!void {
|
||||
.frame_addr => try func.airFrameAddress(inst),
|
||||
.cond_br => try func.airCondBr(inst),
|
||||
.dbg_stmt => try func.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => func.finishAirBookkeeping(),
|
||||
.fptrunc => try func.airFptrunc(inst),
|
||||
.fpext => try func.airFpext(inst),
|
||||
.intcast => try func.airIntCast(inst),
|
||||
|
@ -642,6 +642,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.try_ptr_cold => @panic("TODO try self.airTryPtrCold(inst)"),
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => self.finishAirBookkeeping(),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
|
@ -1924,6 +1924,7 @@ fn genInst(func: *CodeGen, inst: Air.Inst.Index) InnerError!void {
|
||||
.try_ptr_cold => func.airTryPtr(inst),
|
||||
|
||||
.dbg_stmt => func.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => try func.finishAir(inst, .none, &.{}),
|
||||
.dbg_inline_block => func.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr => func.airDbgVar(inst, .local_var, true),
|
||||
.dbg_var_val => func.airDbgVar(inst, .local_var, false),
|
||||
|
@ -961,9 +961,16 @@ pub fn generate(
|
||||
},
|
||||
.debug_output = debug_output,
|
||||
.code = code,
|
||||
.prev_di_loc = .{
|
||||
.line = func.lbrace_line,
|
||||
.column = func.lbrace_column,
|
||||
.is_stmt = switch (debug_output) {
|
||||
.dwarf => |dwarf| dwarf.dwarf.debug_line.header.default_is_stmt,
|
||||
.plan9 => undefined,
|
||||
.none => undefined,
|
||||
},
|
||||
},
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = func.lbrace_line,
|
||||
.prev_di_column = func.lbrace_column,
|
||||
};
|
||||
defer emit.deinit();
|
||||
emit.emitMir() catch |err| switch (err) {
|
||||
@ -1066,9 +1073,8 @@ pub fn generateLazy(
|
||||
},
|
||||
.debug_output = debug_output,
|
||||
.code = code,
|
||||
.prev_di_loc = undefined, // no debug info yet
|
||||
.prev_di_pc = undefined, // no debug info yet
|
||||
.prev_di_line = undefined, // no debug info yet
|
||||
.prev_di_column = undefined, // no debug info yet
|
||||
};
|
||||
defer emit.deinit();
|
||||
emit.emitMir() catch |err| switch (err) {
|
||||
@ -1194,13 +1200,16 @@ fn formatWipMir(
|
||||
switch (mir_inst.ops) {
|
||||
else => unreachable,
|
||||
.pseudo_dbg_prologue_end_none,
|
||||
.pseudo_dbg_line_line_column,
|
||||
.pseudo_dbg_epilogue_begin_none,
|
||||
.pseudo_dbg_enter_block_none,
|
||||
.pseudo_dbg_leave_block_none,
|
||||
.pseudo_dbg_var_args_none,
|
||||
.pseudo_dead_none,
|
||||
=> {},
|
||||
.pseudo_dbg_line_stmt_line_column, .pseudo_dbg_line_line_column => try writer.print(
|
||||
" {[line]d}, {[column]d}",
|
||||
mir_inst.data.line_column,
|
||||
),
|
||||
.pseudo_dbg_enter_inline_func, .pseudo_dbg_leave_inline_func => try writer.print(" {}", .{
|
||||
ip.getNav(ip.indexToKey(mir_inst.data.func).func.owner_nav).name.fmt(ip),
|
||||
}),
|
||||
@ -1281,14 +1290,7 @@ fn addInst(self: *Self, inst: Mir.Inst) error{OutOfMemory}!Mir.Inst.Index {
|
||||
try self.mir_instructions.ensureUnusedCapacity(gpa, 1);
|
||||
const result_index: Mir.Inst.Index = @intCast(self.mir_instructions.len);
|
||||
self.mir_instructions.appendAssumeCapacity(inst);
|
||||
if (inst.tag != .pseudo or switch (inst.ops) {
|
||||
else => true,
|
||||
.pseudo_dbg_prologue_end_none,
|
||||
.pseudo_dbg_line_line_column,
|
||||
.pseudo_dbg_epilogue_begin_none,
|
||||
.pseudo_dead_none,
|
||||
=> false,
|
||||
}) wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});
|
||||
wip_mir_log.debug("{}", .{self.fmtWipMir(result_index)});
|
||||
return result_index;
|
||||
}
|
||||
|
||||
@ -2218,7 +2220,7 @@ fn gen(self: *Self) InnerError!void {
|
||||
// Drop them off at the rbrace.
|
||||
_ = try self.addInst(.{
|
||||
.tag = .pseudo,
|
||||
.ops = .pseudo_dbg_line_line_column,
|
||||
.ops = .pseudo_dbg_line_stmt_line_column,
|
||||
.data = .{ .line_column = .{
|
||||
.line = self.end_di_line,
|
||||
.column = self.end_di_column,
|
||||
@ -2426,6 +2428,7 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
|
||||
.try_ptr_cold => try self.airTryPtr(inst), // TODO
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => try self.airDbgEmptyStmt(),
|
||||
.dbg_inline_block => try self.airDbgInlineBlock(inst),
|
||||
.dbg_var_ptr,
|
||||
.dbg_var_val,
|
||||
@ -13281,7 +13284,7 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const dbg_stmt = self.air.instructions.items(.data)[@intFromEnum(inst)].dbg_stmt;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .pseudo,
|
||||
.ops = .pseudo_dbg_line_line_column,
|
||||
.ops = .pseudo_dbg_line_stmt_line_column,
|
||||
.data = .{ .line_column = .{
|
||||
.line = dbg_stmt.line,
|
||||
.column = dbg_stmt.column,
|
||||
@ -13290,6 +13293,14 @@ fn airDbgStmt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgEmptyStmt(self: *Self) !void {
|
||||
if (self.mir_instructions.len > 0 and
|
||||
self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] == .pseudo_dbg_line_stmt_line_column)
|
||||
self.mir_instructions.items(.ops)[self.mir_instructions.len - 1] = .pseudo_dbg_line_line_column;
|
||||
try self.asmOpOnly(.{ ._, .nop });
|
||||
self.finishAirBookkeeping();
|
||||
}
|
||||
|
||||
fn airDbgInlineBlock(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
|
@ -6,8 +6,7 @@ atom_index: u32,
|
||||
debug_output: link.File.DebugInfoOutput,
|
||||
code: *std.ArrayList(u8),
|
||||
|
||||
prev_di_line: u32,
|
||||
prev_di_column: u32,
|
||||
prev_di_loc: Loc,
|
||||
/// Relative to the beginning of `code`.
|
||||
prev_di_pc: usize,
|
||||
|
||||
@ -263,77 +262,71 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
else => unreachable,
|
||||
.pseudo => switch (mir_inst.ops) {
|
||||
else => unreachable,
|
||||
.pseudo_dbg_prologue_end_none => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| try dw.setPrologueEnd(),
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_prologue_end_none => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| try dwarf.setPrologueEnd(),
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(
|
||||
mir_inst.data.line_column.line,
|
||||
mir_inst.data.line_column.column,
|
||||
),
|
||||
.pseudo_dbg_epilogue_begin_none => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
try dw.setEpilogueBegin();
|
||||
log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
|
||||
emit.prev_di_line, emit.prev_di_column,
|
||||
});
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_line_stmt_line_column => try emit.dbgAdvancePCAndLine(.{
|
||||
.line = mir_inst.data.line_column.line,
|
||||
.column = mir_inst.data.line_column.column,
|
||||
.is_stmt = true,
|
||||
}),
|
||||
.pseudo_dbg_line_line_column => try emit.dbgAdvancePCAndLine(.{
|
||||
.line = mir_inst.data.line_column.line,
|
||||
.column = mir_inst.data.line_column.column,
|
||||
.is_stmt = false,
|
||||
}),
|
||||
.pseudo_dbg_epilogue_begin_none => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
try dwarf.setEpilogueBegin();
|
||||
log.debug("mirDbgEpilogueBegin (line={d}, col={d})", .{
|
||||
emit.prev_di_loc.line, emit.prev_di_loc.column,
|
||||
});
|
||||
try emit.dbgAdvancePCAndLine(emit.prev_di_loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_enter_block_none => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
log.debug("mirDbgEnterBlock (line={d}, col={d})", .{
|
||||
emit.prev_di_line, emit.prev_di_column,
|
||||
});
|
||||
try dw.enterBlock(emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_enter_block_none => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
log.debug("mirDbgEnterBlock (line={d}, col={d})", .{
|
||||
emit.prev_di_loc.line, emit.prev_di_loc.column,
|
||||
});
|
||||
try dwarf.enterBlock(emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_leave_block_none => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{
|
||||
emit.prev_di_line, emit.prev_di_column,
|
||||
});
|
||||
try dw.leaveBlock(emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_leave_block_none => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
log.debug("mirDbgLeaveBlock (line={d}, col={d})", .{
|
||||
emit.prev_di_loc.line, emit.prev_di_loc.column,
|
||||
});
|
||||
try dwarf.leaveBlock(emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_enter_inline_func => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
log.debug("mirDbgEnterInline (line={d}, col={d})", .{
|
||||
emit.prev_di_line, emit.prev_di_column,
|
||||
});
|
||||
try dw.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_line, emit.prev_di_column);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_enter_inline_func => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
log.debug("mirDbgEnterInline (line={d}, col={d})", .{
|
||||
emit.prev_di_loc.line, emit.prev_di_loc.column,
|
||||
});
|
||||
try dwarf.enterInlineFunc(mir_inst.data.func, emit.code.items.len, emit.prev_di_loc.line, emit.prev_di_loc.column);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_leave_inline_func => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
|
||||
emit.prev_di_line, emit.prev_di_column,
|
||||
});
|
||||
try dw.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_leave_inline_func => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
log.debug("mirDbgLeaveInline (line={d}, col={d})", .{
|
||||
emit.prev_di_loc.line, emit.prev_di_loc.column,
|
||||
});
|
||||
try dwarf.leaveInlineFunc(mir_inst.data.func, emit.code.items.len);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_local_a,
|
||||
.pseudo_dbg_local_ai_s,
|
||||
@ -344,129 +337,125 @@ pub fn emitMir(emit: *Emit) Error!void {
|
||||
.pseudo_dbg_local_aro,
|
||||
.pseudo_dbg_local_af,
|
||||
.pseudo_dbg_local_am,
|
||||
=> {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
var loc_buf: [2]link.File.Dwarf.Loc = undefined;
|
||||
const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
|
||||
=> switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| {
|
||||
var loc_buf: [2]link.File.Dwarf.Loc = undefined;
|
||||
const air_inst_index, const loc: link.File.Dwarf.Loc = switch (mir_inst.ops) {
|
||||
else => unreachable,
|
||||
.pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
|
||||
.pseudo_dbg_local_ai_s,
|
||||
.pseudo_dbg_local_ai_u,
|
||||
.pseudo_dbg_local_ai_64,
|
||||
=> .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
|
||||
loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
|
||||
.signed => |s| .{ .consts = s },
|
||||
.unsigned => |u| .{ .constu = u },
|
||||
};
|
||||
break :stack_value &loc_buf[0];
|
||||
} } },
|
||||
.pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
|
||||
.sym = mir_inst.data.as.sym_index,
|
||||
} } },
|
||||
.pseudo_dbg_local_aso => loc: {
|
||||
const sym_off = emit.lower.mir.extraData(
|
||||
bits.SymbolOffset,
|
||||
mir_inst.data.ax.payload,
|
||||
).data;
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
sym: {
|
||||
loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
|
||||
break :sym &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = sym_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_aro => loc: {
|
||||
const air_off = emit.lower.mir.extraData(
|
||||
Mir.AirOffset,
|
||||
mir_inst.data.rx.payload,
|
||||
).data;
|
||||
break :loc .{ air_off.air_inst, .{ .plus = .{
|
||||
reg: {
|
||||
loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
|
||||
break :reg &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = air_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_af => loc: {
|
||||
const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
|
||||
bits.FrameAddr,
|
||||
mir_inst.data.ax.payload,
|
||||
).data);
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
reg: {
|
||||
loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
|
||||
break :reg &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = reg_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_am => loc: {
|
||||
const mem = emit.lower.mem(mir_inst.data.ax.payload);
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
base: {
|
||||
loc_buf[0] = switch (mem.base()) {
|
||||
.none => .{ .constu = 0 },
|
||||
.reg => |reg| .{ .breg = reg.dwarfNum() },
|
||||
.frame => unreachable,
|
||||
.reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
|
||||
};
|
||||
break :base &loc_buf[0];
|
||||
},
|
||||
disp: {
|
||||
loc_buf[1] = switch (mem.disp()) {
|
||||
.signed => |s| .{ .consts = s },
|
||||
.unsigned => |u| .{ .constu = u },
|
||||
};
|
||||
break :disp &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
};
|
||||
const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
|
||||
const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
|
||||
const name: Air.NullTerminatedString = switch (air_inst.tag) {
|
||||
else => unreachable,
|
||||
.arg => air_inst.data.arg.name,
|
||||
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
|
||||
};
|
||||
try dwarf.genLocalDebugInfo(
|
||||
switch (air_inst.tag) {
|
||||
else => unreachable,
|
||||
.pseudo_dbg_local_a => .{ mir_inst.data.a.air_inst, .empty },
|
||||
.pseudo_dbg_local_ai_s,
|
||||
.pseudo_dbg_local_ai_u,
|
||||
.pseudo_dbg_local_ai_64,
|
||||
=> .{ mir_inst.data.ai.air_inst, .{ .stack_value = stack_value: {
|
||||
loc_buf[0] = switch (emit.lower.imm(mir_inst.ops, mir_inst.data.ai.i)) {
|
||||
.signed => |s| .{ .consts = s },
|
||||
.unsigned => |u| .{ .constu = u },
|
||||
};
|
||||
break :stack_value &loc_buf[0];
|
||||
} } },
|
||||
.pseudo_dbg_local_as => .{ mir_inst.data.as.air_inst, .{ .addr = .{
|
||||
.sym = mir_inst.data.as.sym_index,
|
||||
} } },
|
||||
.pseudo_dbg_local_aso => loc: {
|
||||
const sym_off = emit.lower.mir.extraData(
|
||||
bits.SymbolOffset,
|
||||
mir_inst.data.ax.payload,
|
||||
).data;
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
sym: {
|
||||
loc_buf[0] = .{ .addr = .{ .sym = sym_off.sym_index } };
|
||||
break :sym &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = sym_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_aro => loc: {
|
||||
const air_off = emit.lower.mir.extraData(
|
||||
Mir.AirOffset,
|
||||
mir_inst.data.rx.payload,
|
||||
).data;
|
||||
break :loc .{ air_off.air_inst, .{ .plus = .{
|
||||
reg: {
|
||||
loc_buf[0] = .{ .breg = mir_inst.data.rx.r1.dwarfNum() };
|
||||
break :reg &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = air_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_af => loc: {
|
||||
const reg_off = emit.lower.mir.resolveFrameAddr(emit.lower.mir.extraData(
|
||||
bits.FrameAddr,
|
||||
mir_inst.data.ax.payload,
|
||||
).data);
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
reg: {
|
||||
loc_buf[0] = .{ .breg = reg_off.reg.dwarfNum() };
|
||||
break :reg &loc_buf[0];
|
||||
},
|
||||
off: {
|
||||
loc_buf[1] = .{ .consts = reg_off.off };
|
||||
break :off &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
.pseudo_dbg_local_am => loc: {
|
||||
const mem = emit.lower.mem(mir_inst.data.ax.payload);
|
||||
break :loc .{ mir_inst.data.ax.air_inst, .{ .plus = .{
|
||||
base: {
|
||||
loc_buf[0] = switch (mem.base()) {
|
||||
.none => .{ .constu = 0 },
|
||||
.reg => |reg| .{ .breg = reg.dwarfNum() },
|
||||
.frame => unreachable,
|
||||
.reloc => |sym_index| .{ .addr = .{ .sym = sym_index } },
|
||||
};
|
||||
break :base &loc_buf[0];
|
||||
},
|
||||
disp: {
|
||||
loc_buf[1] = switch (mem.disp()) {
|
||||
.signed => |s| .{ .consts = s },
|
||||
.unsigned => |u| .{ .constu = u },
|
||||
};
|
||||
break :disp &loc_buf[1];
|
||||
},
|
||||
} } };
|
||||
},
|
||||
};
|
||||
const ip = &emit.lower.bin_file.comp.zcu.?.intern_pool;
|
||||
const air_inst = emit.air.instructions.get(@intFromEnum(air_inst_index));
|
||||
const name: Air.NullTerminatedString = switch (air_inst.tag) {
|
||||
.arg, .dbg_arg_inline => .local_arg,
|
||||
.dbg_var_ptr, .dbg_var_val => .local_var,
|
||||
},
|
||||
name.toSlice(emit.air),
|
||||
switch (air_inst.tag) {
|
||||
else => unreachable,
|
||||
.arg => air_inst.data.arg.name,
|
||||
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => @enumFromInt(air_inst.data.pl_op.payload),
|
||||
};
|
||||
try dw.genLocalDebugInfo(
|
||||
switch (air_inst.tag) {
|
||||
else => unreachable,
|
||||
.arg, .dbg_arg_inline => .local_arg,
|
||||
.dbg_var_ptr, .dbg_var_val => .local_var,
|
||||
},
|
||||
name.toSlice(emit.air),
|
||||
switch (air_inst.tag) {
|
||||
else => unreachable,
|
||||
.arg => emit.air.typeOfIndex(air_inst_index, ip),
|
||||
.dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
|
||||
.dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
|
||||
},
|
||||
loc,
|
||||
);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.arg => emit.air.typeOfIndex(air_inst_index, ip),
|
||||
.dbg_var_ptr => emit.air.typeOf(air_inst.data.pl_op.operand, ip).childTypeIp(ip),
|
||||
.dbg_var_val, .dbg_arg_inline => emit.air.typeOf(air_inst.data.pl_op.operand, ip),
|
||||
},
|
||||
loc,
|
||||
);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dbg_var_args_none => {
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| try dw.genVarArgsDebugInfo(),
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
}
|
||||
.pseudo_dbg_var_args_none => switch (emit.debug_output) {
|
||||
.dwarf => |dwarf| try dwarf.genVarArgsDebugInfo(),
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
},
|
||||
.pseudo_dead_none => {},
|
||||
},
|
||||
@ -515,16 +504,22 @@ fn fixupRelocs(emit: *Emit) Error!void {
|
||||
}
|
||||
}
|
||||
|
||||
fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
|
||||
const delta_line = @as(i33, line) - @as(i33, emit.prev_di_line);
|
||||
const Loc = struct {
|
||||
line: u32,
|
||||
column: u32,
|
||||
is_stmt: bool,
|
||||
};
|
||||
|
||||
fn dbgAdvancePCAndLine(emit: *Emit, loc: Loc) Error!void {
|
||||
const delta_line = @as(i33, loc.line) - @as(i33, emit.prev_di_loc.line);
|
||||
const delta_pc: usize = emit.code.items.len - emit.prev_di_pc;
|
||||
log.debug(" (advance pc={d} and line={d})", .{ delta_pc, delta_line });
|
||||
switch (emit.debug_output) {
|
||||
.dwarf => |dw| {
|
||||
if (column != emit.prev_di_column) try dw.setColumn(column);
|
||||
try dw.advancePCAndLine(delta_line, delta_pc);
|
||||
emit.prev_di_line = line;
|
||||
emit.prev_di_column = column;
|
||||
.dwarf => |dwarf| {
|
||||
if (loc.is_stmt != emit.prev_di_loc.is_stmt) try dwarf.negateStmt();
|
||||
if (loc.column != emit.prev_di_loc.column) try dwarf.setColumn(loc.column);
|
||||
try dwarf.advancePCAndLine(delta_line, delta_pc);
|
||||
emit.prev_di_loc = loc;
|
||||
emit.prev_di_pc = emit.code.items.len;
|
||||
},
|
||||
.plan9 => |dbg_out| {
|
||||
@ -553,11 +548,10 @@ fn dbgAdvancePCAndLine(emit: *Emit, line: u32, column: u32) Error!void {
|
||||
// we don't need to do anything, because adding the pc quanta does it for us
|
||||
} else unreachable;
|
||||
if (dbg_out.start_line == null)
|
||||
dbg_out.start_line = emit.prev_di_line;
|
||||
dbg_out.end_line = line;
|
||||
dbg_out.start_line = emit.prev_di_loc.line;
|
||||
dbg_out.end_line = loc.line;
|
||||
// only do this if the pc changed
|
||||
emit.prev_di_line = line;
|
||||
emit.prev_di_column = column;
|
||||
emit.prev_di_loc = loc;
|
||||
emit.prev_di_pc = emit.code.items.len;
|
||||
},
|
||||
.none => {},
|
||||
|
@ -310,6 +310,7 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct {
|
||||
}),
|
||||
|
||||
.pseudo_dbg_prologue_end_none,
|
||||
.pseudo_dbg_line_stmt_line_column,
|
||||
.pseudo_dbg_line_line_column,
|
||||
.pseudo_dbg_epilogue_begin_none,
|
||||
.pseudo_dbg_enter_block_none,
|
||||
|
@ -930,7 +930,10 @@ pub const Inst = struct {
|
||||
|
||||
/// End of prologue
|
||||
pseudo_dbg_prologue_end_none,
|
||||
/// Update debug line
|
||||
/// Update debug line with is_stmt register set
|
||||
/// Uses `line_column` payload.
|
||||
pseudo_dbg_line_stmt_line_column,
|
||||
/// Update debug line with is_stmt register clear
|
||||
/// Uses `line_column` payload.
|
||||
pseudo_dbg_line_line_column,
|
||||
/// Start of epilogue
|
||||
|
@ -3289,6 +3289,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
|
||||
.try_ptr_cold => try airTryPtr(f, inst),
|
||||
|
||||
.dbg_stmt => try airDbgStmt(f, inst),
|
||||
.dbg_empty_stmt => try airDbgEmptyStmt(f, inst),
|
||||
.dbg_var_ptr, .dbg_var_val, .dbg_arg_inline => try airDbgVar(f, inst),
|
||||
|
||||
.float_from_int,
|
||||
@ -4601,6 +4602,11 @@ fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgEmptyStmt(f: *Function, _: Air.Inst.Index) !CValue {
|
||||
try f.object.writer().writeAll("(void)0;\n");
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgInlineBlock(f: *Function, inst: Air.Inst.Index) !CValue {
|
||||
const pt = f.object.dg.pt;
|
||||
const zcu = pt.zcu;
|
||||
|
@ -5391,6 +5391,7 @@ pub const FuncGen = struct {
|
||||
.inferred_alloc, .inferred_alloc_comptime => unreachable,
|
||||
|
||||
.dbg_stmt => try self.airDbgStmt(inst),
|
||||
.dbg_empty_stmt => try self.airDbgEmptyStmt(inst),
|
||||
.dbg_var_ptr => try self.airDbgVarPtr(inst),
|
||||
.dbg_var_val => try self.airDbgVarVal(inst, false),
|
||||
.dbg_arg_inline => try self.airDbgVarVal(inst, true),
|
||||
@ -7433,6 +7434,12 @@ pub const FuncGen = struct {
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgEmptyStmt(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
_ = self;
|
||||
_ = inst;
|
||||
return .none;
|
||||
}
|
||||
|
||||
fn airDbgInlineBlock(self: *FuncGen, inst: Air.Inst.Index) !Builder.Value {
|
||||
const ty_pl = self.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;
|
||||
const extra = self.air.extraData(Air.DbgInlineBlock, ty_pl.payload);
|
||||
|
@ -81,6 +81,7 @@ pub const Env = enum {
|
||||
=> true,
|
||||
.cc_command,
|
||||
.translate_c_command,
|
||||
.fmt_command,
|
||||
.jit_command,
|
||||
.fetch_command,
|
||||
.init_command,
|
||||
@ -168,6 +169,7 @@ pub const Feature = enum {
|
||||
clang_command,
|
||||
cc_command,
|
||||
translate_c_command,
|
||||
fmt_command,
|
||||
jit_command,
|
||||
fetch_command,
|
||||
init_command,
|
||||
|
@ -1474,6 +1474,11 @@ pub const WipNav = struct {
|
||||
try uleb128(dlw, column + 1);
|
||||
}
|
||||
|
||||
pub fn negateStmt(wip_nav: *WipNav) error{OutOfMemory}!void {
|
||||
const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);
|
||||
try dlw.writeByte(DW.LNS.negate_stmt);
|
||||
}
|
||||
|
||||
pub fn setPrologueEnd(wip_nav: *WipNav) error{OutOfMemory}!void {
|
||||
const dlw = wip_nav.debug_line.writer(wip_nav.dwarf.gpa);
|
||||
try dlw.writeByte(DW.LNS.set_prologue_end);
|
||||
|
@ -113,8 +113,6 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty,
|
||||
merge_sections: std.ArrayListUnmanaged(Merge.Section) = .empty,
|
||||
comment_merge_section_index: ?Merge.Section.Index = null,
|
||||
|
||||
first_eflags: ?elf.Word = null,
|
||||
|
||||
/// `--verbose-link` output.
|
||||
/// Initialized on creation, appended to as inputs are added, printed during `flush`.
|
||||
dump_argv_list: std.ArrayListUnmanaged([]const u8),
|
||||
@ -791,7 +789,7 @@ pub fn loadInput(self: *Elf, input: link.Input) !void {
|
||||
.res => unreachable,
|
||||
.dso_exact => @panic("TODO"),
|
||||
.object => |obj| try parseObject(self, obj),
|
||||
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, &self.first_eflags, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
|
||||
.archive => |obj| try parseArchive(gpa, diags, &self.file_handles, &self.files, target, debug_fmt_strip, default_sym_version, &self.objects, obj, is_static_lib),
|
||||
.dso => |dso| try parseDso(gpa, diags, dso, &self.shared_objects, &self.files, target),
|
||||
}
|
||||
}
|
||||
@ -1124,7 +1122,6 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
|
||||
|
||||
const gpa = self.base.comp.gpa;
|
||||
const diags = &self.base.comp.link_diags;
|
||||
const first_eflags = &self.first_eflags;
|
||||
const target = self.base.comp.root_mod.resolved_target.result;
|
||||
const debug_fmt_strip = self.base.comp.config.debug_format == .strip;
|
||||
const default_sym_version = self.default_sym_version;
|
||||
@ -1145,7 +1142,7 @@ fn parseObject(self: *Elf, obj: link.Input.Object) !void {
|
||||
try self.objects.append(gpa, index);
|
||||
|
||||
const object = self.file(index).?.object;
|
||||
try object.parseCommon(gpa, diags, obj.path, handle, target, first_eflags);
|
||||
try object.parseCommon(gpa, diags, obj.path, handle, target);
|
||||
if (!self.base.isStaticLib()) {
|
||||
try object.parse(gpa, diags, obj.path, handle, target, debug_fmt_strip, default_sym_version);
|
||||
}
|
||||
@ -1156,7 +1153,6 @@ fn parseArchive(
|
||||
diags: *Diags,
|
||||
file_handles: *std.ArrayListUnmanaged(File.Handle),
|
||||
files: *std.MultiArrayList(File.Entry),
|
||||
first_eflags: *?elf.Word,
|
||||
target: std.Target,
|
||||
debug_fmt_strip: bool,
|
||||
default_sym_version: elf.Versym,
|
||||
@ -1179,7 +1175,7 @@ fn parseArchive(
|
||||
const object = &files.items(.data)[index].object;
|
||||
object.index = index;
|
||||
object.alive = init_alive;
|
||||
try object.parseCommon(gpa, diags, obj.path, obj.file, target, first_eflags);
|
||||
try object.parseCommon(gpa, diags, obj.path, obj.file, target);
|
||||
if (!is_static_lib)
|
||||
try object.parse(gpa, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version);
|
||||
try objects.append(gpa, index);
|
||||
|
@ -99,7 +99,6 @@ pub fn parseCommon(
|
||||
path: Path,
|
||||
handle: fs.File,
|
||||
target: std.Target,
|
||||
first_eflags: *?elf.Word,
|
||||
) !void {
|
||||
const offset = if (self.archive) |ar| ar.offset else 0;
|
||||
const file_size = (try handle.stat()).size;
|
||||
@ -114,7 +113,7 @@ pub fn parseCommon(
|
||||
@tagName(self.header.?.e_machine),
|
||||
});
|
||||
}
|
||||
try validateEFlags(diags, path, target, self.header.?.e_flags, first_eflags);
|
||||
try validateEFlags(diags, path, target, self.header.?.e_flags);
|
||||
|
||||
if (self.header.?.e_shnum == 0) return;
|
||||
|
||||
@ -180,39 +179,81 @@ pub fn parseCommon(
|
||||
}
|
||||
}
|
||||
|
||||
fn validateEFlags(
|
||||
pub fn validateEFlags(
|
||||
diags: *Diags,
|
||||
path: Path,
|
||||
target: std.Target,
|
||||
e_flags: elf.Word,
|
||||
first_eflags: *?elf.Word,
|
||||
) error{LinkFailure}!void {
|
||||
if (first_eflags.*) |*self_eflags| {
|
||||
switch (target.cpu.arch) {
|
||||
.riscv64 => {
|
||||
if (e_flags != self_eflags.*) {
|
||||
const riscv_eflags: riscv.RiscvEflags = @bitCast(e_flags);
|
||||
const self_riscv_eflags: *riscv.RiscvEflags = @ptrCast(self_eflags);
|
||||
) !void {
|
||||
switch (target.cpu.arch) {
|
||||
.riscv64 => {
|
||||
const features = target.cpu.features;
|
||||
const flags: riscv.Eflags = @bitCast(e_flags);
|
||||
var any_errors: bool = false;
|
||||
|
||||
self_riscv_eflags.rvc = self_riscv_eflags.rvc or riscv_eflags.rvc;
|
||||
self_riscv_eflags.tso = self_riscv_eflags.tso or riscv_eflags.tso;
|
||||
// For an input object to target an ABI that the target CPU doesn't have enabled
|
||||
// is invalid, and will throw an error.
|
||||
|
||||
var any_errors: bool = false;
|
||||
if (self_riscv_eflags.fabi != riscv_eflags.fabi) {
|
||||
any_errors = true;
|
||||
diags.addParseError(path, "cannot link object files with different float-point ABIs", .{});
|
||||
}
|
||||
if (self_riscv_eflags.rve != riscv_eflags.rve) {
|
||||
any_errors = true;
|
||||
diags.addParseError(path, "cannot link object files with different RVEs", .{});
|
||||
}
|
||||
if (any_errors) return error.LinkFailure;
|
||||
}
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
} else {
|
||||
first_eflags.* = e_flags;
|
||||
// Invalid when
|
||||
// 1. The input uses C and we do not.
|
||||
if (flags.rvc and !std.Target.riscv.featureSetHas(features, .c)) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting the C feature without having the C feature enabled",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
// Invalid when
|
||||
// 1. We use E and the input does not.
|
||||
// 2. The input uses E and we do not.
|
||||
if (std.Target.riscv.featureSetHas(features, .e) != flags.rve) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"{s}",
|
||||
.{
|
||||
if (flags.rve)
|
||||
"cannot link object file targeting the E feature without having the E feature enabled"
|
||||
else
|
||||
"cannot link object file not targeting the E feature while having the E feature enabled",
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Invalid when
|
||||
// 1. We use total store order and the input does not.
|
||||
// 2. The input uses total store order and we do not.
|
||||
if (flags.tso != std.Target.riscv.featureSetHas(features, .ztso)) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting the TSO memory model without having the ztso feature enabled",
|
||||
.{},
|
||||
);
|
||||
}
|
||||
|
||||
const fabi: riscv.Eflags.FloatAbi =
|
||||
if (std.Target.riscv.featureSetHas(features, .d))
|
||||
.double
|
||||
else if (std.Target.riscv.featureSetHas(features, .f))
|
||||
.single
|
||||
else
|
||||
.soft;
|
||||
|
||||
if (flags.fabi != fabi) {
|
||||
any_errors = true;
|
||||
diags.addParseError(
|
||||
path,
|
||||
"cannot link object file targeting a different floating-point ABI. targeting {s}, found {s}",
|
||||
.{ @tagName(fabi), @tagName(flags.fabi) },
|
||||
);
|
||||
}
|
||||
|
||||
if (any_errors) return error.LinkFailure;
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1496,7 +1496,7 @@ pub fn updateFunc(
|
||||
});
|
||||
defer gpa.free(name);
|
||||
const osec = if (self.text_index) |sect_sym_index|
|
||||
self.symbol(sect_sym_index).output_section_index
|
||||
self.symbol(sect_sym_index).outputShndx(elf_file).?
|
||||
else osec: {
|
||||
const osec = try elf_file.addSection(.{
|
||||
.name = try elf_file.insertShString(".text"),
|
||||
|
@ -70,18 +70,20 @@ fn bitSlice(
|
||||
return @truncate((value >> low) & (1 << (high - low + 1)) - 1);
|
||||
}
|
||||
|
||||
pub const RiscvEflags = packed struct(u32) {
|
||||
pub const Eflags = packed struct(u32) {
|
||||
rvc: bool,
|
||||
fabi: enum(u2) {
|
||||
fabi: FloatAbi,
|
||||
rve: bool,
|
||||
tso: bool,
|
||||
_reserved: u19 = 0,
|
||||
_unused: u8 = 0,
|
||||
|
||||
pub const FloatAbi = enum(u2) {
|
||||
soft = 0b00,
|
||||
single = 0b01,
|
||||
double = 0b10,
|
||||
quad = 0b11,
|
||||
},
|
||||
rve: bool,
|
||||
tso: bool,
|
||||
_reserved: u19,
|
||||
_unused: u8,
|
||||
};
|
||||
};
|
||||
|
||||
const mem = std.mem;
|
||||
|
@ -309,6 +309,7 @@ fn mainArgs(gpa: Allocator, arena: Allocator, args: []const []const u8) !void {
|
||||
.server = use_server,
|
||||
});
|
||||
} else if (mem.eql(u8, cmd, "fmt")) {
|
||||
dev.check(.fmt_command);
|
||||
return @import("fmt.zig").run(gpa, arena, cmd_args);
|
||||
} else if (mem.eql(u8, cmd, "objcopy")) {
|
||||
return jitCmd(gpa, arena, cmd_args, .{
|
||||
|
49
src/musl.zig
49
src/musl.zig
@ -138,17 +138,6 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
|
||||
try addSrcFile(arena, &source_table, src_file);
|
||||
}
|
||||
|
||||
const time32_compat_arch_list = [_][]const u8{
|
||||
"arm",
|
||||
"i386",
|
||||
"m68k",
|
||||
"microblaze",
|
||||
"mips",
|
||||
"mipsn32",
|
||||
"or1k",
|
||||
"powerpc",
|
||||
"sh",
|
||||
};
|
||||
for (time32_compat_arch_list) |time32_compat_arch| {
|
||||
if (mem.eql(u8, arch_name, time32_compat_arch)) {
|
||||
for (compat_time32_files) |compat_time32_file| {
|
||||
@ -239,13 +228,29 @@ pub fn buildCrtFile(comp: *Compilation, in_crt_file: CrtFile, prog_node: std.Pro
|
||||
});
|
||||
|
||||
const target = comp.root_mod.resolved_target.result;
|
||||
const arch_define = try std.fmt.allocPrint(arena, "-DARCH_{s}", .{
|
||||
@tagName(target.cpu.arch),
|
||||
});
|
||||
const arch_name = std.zig.target.muslArchName(target.cpu.arch, target.abi);
|
||||
const time32 = for (time32_compat_arch_list) |time32_compat_arch| {
|
||||
if (mem.eql(u8, arch_name, time32_compat_arch)) break true;
|
||||
} else false;
|
||||
const arch_define = try std.fmt.allocPrint(arena, "-DARCH_{s}", .{arch_name});
|
||||
const family_define = switch (target.cpu.arch) {
|
||||
.arm, .armeb, .thumb, .thumbeb => "-DFAMILY_arm",
|
||||
.aarch64, .aarch64_be => "-DFAMILY_aarch64",
|
||||
.loongarch64 => "-DFAMILY_loongarch",
|
||||
.m68k => "-DFAMILY_m68k",
|
||||
.mips, .mipsel, .mips64, .mips64el => "-DFAMILY_mips",
|
||||
.powerpc, .powerpc64, .powerpc64le => "-DFAMILY_powerpc",
|
||||
.riscv32, .riscv64 => "-DFAMILY_riscv",
|
||||
.s390x => "-DFAMILY_s390x",
|
||||
.x86, .x86_64 => "-DFAMILY_x86",
|
||||
else => unreachable,
|
||||
};
|
||||
const cc_argv: []const []const u8 = if (target.ptrBitWidth() == 64)
|
||||
&.{ "-DPTR64", arch_define }
|
||||
&.{ "-DPTR64", arch_define, family_define }
|
||||
else if (time32)
|
||||
&.{ "-DTIME32", arch_define, family_define }
|
||||
else
|
||||
&.{arch_define};
|
||||
&.{ arch_define, family_define };
|
||||
|
||||
const root_mod = try Module.create(arena, .{
|
||||
.global_cache_directory = comp.global_cache_directory,
|
||||
@ -347,6 +352,18 @@ pub fn needsCrt0(output_mode: std.builtin.OutputMode, link_mode: std.builtin.Lin
|
||||
};
|
||||
}
|
||||
|
||||
const time32_compat_arch_list = [_][]const u8{
|
||||
"arm",
|
||||
"i386",
|
||||
"m68k",
|
||||
"microblaze",
|
||||
"mips",
|
||||
"mipsn32",
|
||||
"or1k",
|
||||
"powerpc",
|
||||
"sh",
|
||||
};
|
||||
|
||||
fn isArchName(name: []const u8) bool {
|
||||
const musl_arch_names = [_][]const u8{
|
||||
"aarch64",
|
||||
|
@ -202,6 +202,7 @@ const Writer = struct {
|
||||
|
||||
.trap,
|
||||
.breakpoint,
|
||||
.dbg_empty_stmt,
|
||||
.unreach,
|
||||
.ret_addr,
|
||||
.frame_addr,
|
||||
|
@ -621,6 +621,8 @@ const Writer = struct {
|
||||
.field_parent_ptr => try self.writeFieldParentPtr(stream, extended),
|
||||
.builtin_value => try self.writeBuiltinValue(stream, extended),
|
||||
.inplace_arith_result_ty => try self.writeInplaceArithResultTy(stream, extended),
|
||||
|
||||
.dbg_empty_stmt => try stream.writeAll("))"),
|
||||
}
|
||||
}
|
||||
|
||||
|
52
test/cases/compile_errors/align_zero.zig
Normal file
52
test/cases/compile_errors/align_zero.zig
Normal file
@ -0,0 +1,52 @@
|
||||
pub var global_var: i32 align(0) = undefined;
|
||||
|
||||
pub export fn a() void {
|
||||
_ = &global_var;
|
||||
}
|
||||
|
||||
pub extern var extern_var: i32 align(0);
|
||||
|
||||
pub export fn b() void {
|
||||
_ = &extern_var;
|
||||
}
|
||||
|
||||
pub export fn c() align(0) void {}
|
||||
|
||||
pub export fn d() void {
|
||||
_ = *align(0) fn () i32;
|
||||
}
|
||||
|
||||
pub export fn e() void {
|
||||
var local_var: i32 align(0) = undefined;
|
||||
_ = &local_var;
|
||||
}
|
||||
|
||||
pub export fn f() void {
|
||||
_ = *align(0) i32;
|
||||
}
|
||||
|
||||
pub export fn g() void {
|
||||
_ = []align(0) i32;
|
||||
}
|
||||
|
||||
pub export fn h() void {
|
||||
_ = struct { field: i32 align(0) };
|
||||
}
|
||||
|
||||
pub export fn i() void {
|
||||
_ = union { field: i32 align(0) };
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :1:31: error: alignment must be >= 1
|
||||
// :7:38: error: alignment must be >= 1
|
||||
// :13:25: error: alignment must be >= 1
|
||||
// :16:16: error: alignment must be >= 1
|
||||
// :20:30: error: alignment must be >= 1
|
||||
// :25:16: error: alignment must be >= 1
|
||||
// :29:17: error: alignment must be >= 1
|
||||
// :33:35: error: alignment must be >= 1
|
||||
// :37:34: error: alignment must be >= 1
|
@ -1,4 +1,4 @@
|
||||
export fn entry() align(0) void {}
|
||||
export fn entry() align(64) void {}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
|
@ -808,6 +808,424 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
||||
\\1 breakpoints deleted; 0 breakpoint locations disabled.
|
||||
},
|
||||
);
|
||||
db.addLldbTest(
|
||||
"step_single_stmt_loops",
|
||||
target,
|
||||
&.{
|
||||
.{
|
||||
.path = "step_single_stmt_loops.zig",
|
||||
.source =
|
||||
\\pub fn main() void {
|
||||
\\ var x: u32 = 0;
|
||||
\\ for (0..3) |_| {
|
||||
\\ x +%= 1;
|
||||
\\ }
|
||||
\\ {
|
||||
\\ var i: u32 = 0;
|
||||
\\ while (i < 3) : (i +%= 1) {
|
||||
\\ x +%= 1;
|
||||
\\ }
|
||||
\\ }
|
||||
\\ {
|
||||
\\ var i: u32 = 0;
|
||||
\\ while (i < 3) {
|
||||
\\ i +%= 1;
|
||||
\\ }
|
||||
\\ }
|
||||
\\ inline for (0..3) |_| {
|
||||
\\ x +%= 1;
|
||||
\\ }
|
||||
\\ {
|
||||
\\ comptime var i: u32 = 0;
|
||||
\\ inline while (i < 3) : (i +%= 1) {
|
||||
\\ x +%= 1;
|
||||
\\ }
|
||||
\\ }
|
||||
\\ {
|
||||
\\ comptime var i: u32 = 0;
|
||||
\\ inline while (i < 3) {
|
||||
\\ i +%= 1;
|
||||
\\ }
|
||||
\\ }
|
||||
\\ x +%= 1;
|
||||
\\}
|
||||
\\
|
||||
,
|
||||
},
|
||||
},
|
||||
\\breakpoint set --name step_single_stmt_loops.main
|
||||
\\process launch
|
||||
\\thread step-in
|
||||
\\#00
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#01
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#02
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#03
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#04
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#05
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#06
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#07
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#08
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#09
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#10
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#11
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#12
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#13
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#14
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#15
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#16
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#17
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#18
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#19
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#20
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#21
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#22
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#23
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#24
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#25
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#26
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#27
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#28
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#29
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#30
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#31
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#32
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#33
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#34
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#35
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#36
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#37
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#38
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#39
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#40
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#41
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#42
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#43
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#44
|
||||
\\frame variable x
|
||||
\\thread step-in
|
||||
\\#45
|
||||
\\frame variable x
|
||||
\\
|
||||
,
|
||||
&.{
|
||||
\\(lldb) #00
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 0
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #01
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 0
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #02
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 1
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #03
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 1
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #04
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 1
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #05
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 2
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #06
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 2
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #07
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 2
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #08
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 3
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #09
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 3
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #10
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 3
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #11
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 3
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #12
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 3
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #13
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 4
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #14
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 4
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #15
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 4
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #16
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 5
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #17
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 5
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #18
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 5
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #19
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #20
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #21
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #22
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #23
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #24
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #25
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #26
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #27
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #28
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #29
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #30
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #31
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #32
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 6
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #33
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 7
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #34
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 7
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #35
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 8
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #36
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 8
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #37
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 9
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #38
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 9
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #39
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 10
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #40
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 10
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #41
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 11
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #42
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 11
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #43
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 12
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #44
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 12
|
||||
\\(lldb) thread step-in
|
||||
,
|
||||
\\(lldb) #45
|
||||
\\(lldb) frame variable x
|
||||
\\(u32) x = 12
|
||||
},
|
||||
);
|
||||
db.addLldbTest(
|
||||
"inline_call",
|
||||
target,
|
||||
@ -1533,17 +1951,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
||||
&.{
|
||||
\\(lldb) frame variable --show-types -- list0 list0.len list0.capacity list0[0] list0[1] list0[2] list0.0 list0.1 list0.2
|
||||
\\(std.multi_array_list.MultiArrayList(struct { u32, u8, u16 })) list0 = len=3 capacity=8 {
|
||||
\\ (std.struct { u32, u8, u16 }) [0] = {
|
||||
\\ (struct { u32, u8, u16 }) [0] = {
|
||||
\\ (u32) .@"0" = 1
|
||||
\\ (u8) .@"1" = 2
|
||||
\\ (u16) .@"2" = 3
|
||||
\\ }
|
||||
\\ (std.struct { u32, u8, u16 }) [1] = {
|
||||
\\ (struct { u32, u8, u16 }) [1] = {
|
||||
\\ (u32) .@"0" = 4
|
||||
\\ (u8) .@"1" = 5
|
||||
\\ (u16) .@"2" = 6
|
||||
\\ }
|
||||
\\ (std.struct { u32, u8, u16 }) [2] = {
|
||||
\\ (struct { u32, u8, u16 }) [2] = {
|
||||
\\ (u32) .@"0" = 7
|
||||
\\ (u8) .@"1" = 8
|
||||
\\ (u16) .@"2" = 9
|
||||
@ -1551,17 +1969,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
||||
\\}
|
||||
\\(usize) list0.len = 3
|
||||
\\(usize) list0.capacity = 8
|
||||
\\(std.struct { u32, u8, u16 }) list0[0] = {
|
||||
\\(struct { u32, u8, u16 }) list0[0] = {
|
||||
\\ (u32) .@"0" = 1
|
||||
\\ (u8) .@"1" = 2
|
||||
\\ (u16) .@"2" = 3
|
||||
\\}
|
||||
\\(std.struct { u32, u8, u16 }) list0[1] = {
|
||||
\\(struct { u32, u8, u16 }) list0[1] = {
|
||||
\\ (u32) .@"0" = 4
|
||||
\\ (u8) .@"1" = 5
|
||||
\\ (u16) .@"2" = 6
|
||||
\\}
|
||||
\\(std.struct { u32, u8, u16 }) list0[2] = {
|
||||
\\(struct { u32, u8, u16 }) list0[2] = {
|
||||
\\ (u32) .@"0" = 7
|
||||
\\ (u8) .@"1" = 8
|
||||
\\ (u16) .@"2" = 9
|
||||
@ -1583,17 +2001,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
||||
\\}
|
||||
\\(lldb) frame variable --show-types -- slice0 slice0.len slice0.capacity slice0[0] slice0[1] slice0[2] slice0.0 slice0.1 slice0.2
|
||||
\\(std.multi_array_list.MultiArrayList(struct { u32, u8, u16 }).Slice) slice0 = len=3 capacity=8 {
|
||||
\\ (std.struct { u32, u8, u16 }) [0] = {
|
||||
\\ (struct { u32, u8, u16 }) [0] = {
|
||||
\\ (u32) .@"0" = 1
|
||||
\\ (u8) .@"1" = 2
|
||||
\\ (u16) .@"2" = 3
|
||||
\\ }
|
||||
\\ (std.struct { u32, u8, u16 }) [1] = {
|
||||
\\ (struct { u32, u8, u16 }) [1] = {
|
||||
\\ (u32) .@"0" = 4
|
||||
\\ (u8) .@"1" = 5
|
||||
\\ (u16) .@"2" = 6
|
||||
\\ }
|
||||
\\ (std.struct { u32, u8, u16 }) [2] = {
|
||||
\\ (struct { u32, u8, u16 }) [2] = {
|
||||
\\ (u32) .@"0" = 7
|
||||
\\ (u8) .@"1" = 8
|
||||
\\ (u16) .@"2" = 9
|
||||
@ -1601,17 +2019,17 @@ pub fn addTestsForTarget(db: *Debugger, target: Target) void {
|
||||
\\}
|
||||
\\(usize) slice0.len = 3
|
||||
\\(usize) slice0.capacity = 8
|
||||
\\(std.struct { u32, u8, u16 }) slice0[0] = {
|
||||
\\(struct { u32, u8, u16 }) slice0[0] = {
|
||||
\\ (u32) .@"0" = 1
|
||||
\\ (u8) .@"1" = 2
|
||||
\\ (u16) .@"2" = 3
|
||||
\\}
|
||||
\\(std.struct { u32, u8, u16 }) slice0[1] = {
|
||||
\\(struct { u32, u8, u16 }) slice0[1] = {
|
||||
\\ (u32) .@"0" = 4
|
||||
\\ (u8) .@"1" = 5
|
||||
\\ (u16) .@"2" = 6
|
||||
\\}
|
||||
\\(std.struct { u32, u8, u16 }) slice0[2] = {
|
||||
\\(struct { u32, u8, u16 }) slice0[2] = {
|
||||
\\ (u32) .@"0" = 7
|
||||
\\ (u8) .@"1" = 8
|
||||
\\ (u16) .@"2" = 9
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user