From 597e59c085f1d780866b8179fe5eb6ab3dcf846d Mon Sep 17 00:00:00 2001 From: dzaima Date: Sat, 14 Jun 2025 19:28:00 +0300 Subject: [PATCH] add STRICT_ALIGN, use by default in FOR_BUILD --- src/builtins/sysfn.c | 30 ++++++++++++++++++++++++++++-- test/cases/system.bqn | 1 - test/cases/unaligned.bqn | 12 ++++++++++++ 3 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 test/cases/unaligned.bqn diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index fcd0e5ba..8290771f 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -1513,13 +1513,18 @@ B bitcast_impl(B el0, B el1, B x) { if (rl>=USZ_MAX) thrM("•bit._cast: output too large"); B r = convert(xct, x); u8 rt = typeOfCast(rct); - if (rt==t_bitarr && (!reusable(r) || ARR_IS_SLICE(TY(r)))) { - r = taga(copy(xct, r)); + if (rt==t_bitarr) { + if (reusable(r) && !ARR_IS_SLICE(TY(r))) { + REUSE(r); + } else { + r = taga(copy(xct, r)); + } } else if (!reusable(r)) { B r0 = incG(r); Arr* r2 = TI(r,slice)(r, 0, IA(r)); r = taga(arr_shSetI(r2, xr, shObj(r0))); decG(r0); + goto possibly_unaligned; } else { REUSE(r); #if VERIFY_TAIL @@ -1527,7 +1532,28 @@ B bitcast_impl(B el0, B el1, B x) { FINISH_OVERALLOC(a(r), offsetof(TyArr,a)+IA(r)/8, offsetof(TyArr,a) + (BIT_N(IA(r))<<3)); } #endif + goto possibly_unaligned; } + + if (0) { + possibly_unaligned:; + #if STRICT_ALIGN || FOR_BUILD + if (IS_TYSLICE(TY(r))) { + assert(rct.s != 1 && xct.s != 1); // rt==t_bitarr handles rct.s==1, and xct.s==1 never currently makes a slice (..though it could) + u8 arrt = SLICE_TO_ARR(TY(r)); + void* r0p = tyslicev_ptr(a(r)); + if (ptr2u64(r0p) & ((rct.s>>3) - 1)) { + Arr* r1; + void* r2p = m_tyarrp(&r1, xct.s>>3, IA(r), arrt); + memcpy(r2p, r0p, IA(r)*(xct.s>>3)); + arr_shCopyUnchecked(r1, r); + decG(r); + r = taga(r1); + } + } + #endif + } + return set_bit_result(r, rt, xr, rl, sh); } diff --git a/test/cases/system.bqn b/test/cases/system.bqn index 090666fa..38c9720a 100644 --- a/test/cases/system.bqn +++ b/test/cases/system.bqn @@ -322,7 +322,6 @@ r←•MakeRand 1 ⋄ ! 1¨⊸≡ ∊{𝕊: 500 r.Deal 1000}¨ ↕4 %USE eqvar ⋄ {t←𝕩⊏1‿8‿16‿32‿64 ⋄ {t•bit._cast 𝕩}_eqvar 4=↕128}¨ ↕4‿4 ! 10‿1 ≡ ≢8‿16•bit._cast c←0↓2↕'a'+11 •rand.Range 26 ⋄ ! 10‿2 ≡ ≢c ! 10‿1 ≡ ≢8‿16•bit._cast c← 2↕'a'+11 •rand.Range 26 ⋄ ! 10‿2 ≡ ≢c -⊑ 8‿32•bit._cast 3↓↕7 %% 100992003 !"•bit._cast: incompatible lengths" % 1‿8•bit._cast 1⥊0 !"•bit._cast: incompatible lengths" % 8‿32•bit._cast 2⥊0 !"•bit._cast: incompatible lengths" % 8‿32•bit._cast 10⥊0 diff --git a/test/cases/unaligned.bqn b/test/cases/unaligned.bqn new file mode 100644 index 00000000..b05cabcb --- /dev/null +++ b/test/cases/unaligned.bqn @@ -0,0 +1,12 @@ +⊑ 8‿32•bit._cast 3↓↕7 %% 100992003 + +( + r←(⊑•args).GetRand@ + { ·‿dw‿·𝕊sk‿sw‿e: + a0 ← { + dw=64? 𝕩⥊0‿1; + 𝕩 r.Range e + } (1+8×1⌈dw÷sw) + {•internal.Keep¨ sw‿dw •bit._cast 1↓𝕩•internal.Variation a0}¨ ∾⟜"Inc"¨⊸∾ ∾⟜sk¨ "AS" + }⌜˜ ⟨"b"‿1‿2, "i8"‿8‿100, "i16"‿16‿1e4, "i32"‿32‿1e9, "f64"‿64‿0⟩ +)