Merge branch 'master' into issue-21946

This commit is contained in:
gabeuehlein 2024-11-25 16:34:30 -05:00 committed by GitHub
commit da0eb66b67
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
60 changed files with 4162 additions and 1448 deletions

View File

@ -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 \

View File

@ -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 \

View File

@ -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");

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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"

View File

@ -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
View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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),
),
};

View File

@ -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),
),
};

View File

@ -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 ..];

View File

@ -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);
}

View File

@ -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" },

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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__)

View File

@ -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,

View File

@ -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,

View File

@ -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 {

View File

@ -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,

View File

@ -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,

View File

@ -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: {

View File

@ -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,

View File

@ -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,

View File

@ -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),

View File

@ -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,

View File

@ -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),

View File

@ -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);

View File

@ -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 => {},

View File

@ -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,

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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);

View File

@ -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 => {},
}
}

View File

@ -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"),

View File

@ -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;

View File

@ -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, .{

View File

@ -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",

View File

@ -202,6 +202,7 @@ const Writer = struct {
.trap,
.breakpoint,
.dbg_empty_stmt,
.unreach,
.ret_addr,
.frame_addr,

View File

@ -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("))"),
}
}

View 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

View File

@ -1,4 +1,4 @@
export fn entry() align(0) void {}
export fn entry() align(64) void {}
// error
// backend=stage2

View File

@ -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