diff --git a/src/builtins/sfns.c b/src/builtins/sfns.c index f2e4da06..15348109 100644 --- a/src/builtins/sfns.c +++ b/src/builtins/sfns.c @@ -357,8 +357,8 @@ B slash_c1(B t, B x) { #if SINGELI && defined(__BMI2__) if (xia<=32768 && xe==el_bit) { u64* xp = bitarr_ptr(x); - if (xia<=128) { i8* rp; r = m_i8arrv (&rp, s+8); a(r)->ia-= 8; bmipopc_1slash8 (xp, rp, xia); } - else { i16* rp; r = m_i16arrv(&rp, s+16); a(r)->ia-= 16; bmipopc_1slash16(xp, rp, xia); } + if (xia<=128) { i8* rp = m_tyarrvO(&r, 1, s, t_i8arr , 8); bmipopc_1slash8 (xp, rp, xia); } + else { i16* rp = m_tyarrvO(&r, 2, s, t_i16arr, 16); bmipopc_1slash16(xp, rp, xia); } } else #endif { @@ -445,8 +445,8 @@ B slash_c2(B t, B w, B x) { goto bit_ret; } #if SINGELI - case el_i8: { i8* xp = i8any_ptr (x); i8* rp; r = m_i8arrv (&rp, wsum+8); a(r)->ia-= 8; bmipopc_2slash8 (wp, xp, rp, wia); goto bit_ret; } - case el_i16: { i16* xp = i16any_ptr(x); i16* rp; r = m_i16arrv(&rp, wsum+16); a(r)->ia-= 16; bmipopc_2slash16(wp, xp, rp, wia); goto bit_ret; } + case el_c8: case el_i8: { i8* xp=tyany_ptr(x); i8* rp=m_tyarrvO(&r,1,wsum,el2t(xe), 8); bmipopc_2slash8 (wp, xp, rp, wia); goto bit_ret; } + case el_c16:case el_i16: { i16* xp=tyany_ptr(x); i16* rp=m_tyarrvO(&r,2,wsum,el2t(xe), 16); bmipopc_2slash16(wp, xp, rp, wia); goto bit_ret; } #endif } #endif @@ -459,18 +459,15 @@ B slash_c2(B t, B w, B x) { switch(xe) { default: UD; #if !SINGELI - case el_i8: { i8* xp = i8any_ptr (x); i8* rp; r = m_i8arrv (&rp,wsum); for (usz i=0; itype==t_harr) return harr_ptr(x); - if (v(x)->type==t_fillarr) return fillarr_ptr(a(x)); - if (v(x)->type==t_hslice) return c(HSlice,x)->a; - if (v(x)->type==t_fillslice) return c(FillSlice,x)->a; - return NULL; -} -static B* arrV_bptr(Arr* x) { - if (x->type==t_harr) return ((HArr*)x)->a; - if (x->type==t_fillarr) return fillarr_ptr(x); - if (x->type==t_hslice) return ((HSlice*)x)->a; - if (x->type==t_fillslice) return ((FillSlice*)x)->a; - return NULL; -} -static void* tyany_ptr(B x) { - u8 t = v(x)->type; - return IS_SLICE(t)? c(TySlice,x)->a : c(TyArr,x)->a; -} - typedef struct BFn { struct Fun; diff --git a/src/core/arrFns.h b/src/core/arrFns.h new file mode 100644 index 00000000..c2dfd8ec --- /dev/null +++ b/src/core/arrFns.h @@ -0,0 +1,35 @@ +#pragma once + +static B* arr_bptr(B x) { assert(isArr(x)); + if (v(x)->type==t_harr) return harr_ptr(x); + if (v(x)->type==t_fillarr) return fillarr_ptr(a(x)); + if (v(x)->type==t_hslice) return c(HSlice,x)->a; + if (v(x)->type==t_fillslice) return c(FillSlice,x)->a; + return NULL; +} +static B* arrV_bptr(Arr* x) { + if (x->type==t_harr) return ((HArr*)x)->a; + if (x->type==t_fillarr) return fillarr_ptr(x); + if (x->type==t_hslice) return ((HSlice*)x)->a; + if (x->type==t_fillslice) return ((FillSlice*)x)->a; + return NULL; +} +static void* tyany_ptr(B x) { + u8 t = v(x)->type; + return IS_SLICE(t)? c(TySlice,x)->a : c(TyArr,x)->a; +} + +#define M_TYARR(OVER, MID) { \ + Arr* r = m_arr(TYARR_SZW(w, ia) OVER, type, ia); \ + MID \ + *rp = taga(r); \ + return ((TyArr*)r)->a; \ +} +// width in bytes for m_tyarr*; overalloc is a byte count +static void* m_tyarrp (B* rp, usz w, usz ia, u8 type ) M_TYARR( , ) +static void* m_tyarrpO(B* rp, usz w, usz ia, u8 type, usz over) M_TYARR(+over, ) +static void* m_tyarrv (B* rp, usz w, usz ia, u8 type ) M_TYARR( , arr_shVec((Arr*)r);) +static void* m_tyarrvO(B* rp, usz w, usz ia, u8 type, usz over) M_TYARR(+over, arr_shVec((Arr*)r);) + +extern u8 elType2type[]; +#define el2t(X) elType2type[X] // TODO maybe reorganize array types such that this can just be addition? \ No newline at end of file diff --git a/src/core/stuff.h b/src/core/stuff.h index a55cfa27..e650aa29 100644 --- a/src/core/stuff.h +++ b/src/core/stuff.h @@ -32,6 +32,7 @@ static void decSh(Value* x) { if (RARE(prnk(x)>1)) tptr_dec(shObjP(x), mm_free); #define TYARR_SZ(T,IA) fsizeof(TyArr, a, T##Atom, IA) #define TYARR_SZ2(T,IA) TYARR_SZ(T,IA) +#define TYARR_SZW(W,IA) (offsetof(TyArr, a) + (W)*(IA)) #define WRAP(X,IA,MSG) ({ i64 wV=(i64)(X); u64 iaW=(IA); if(RARE((u64)wV >= iaW)) { if(wV<0) wV+= iaW; if((u64)wV >= iaW) {MSG;} }; (usz)wV; }) diff --git a/src/core/tyarr.c b/src/core/tyarr.c index 415739b7..4d66842f 100644 --- a/src/core/tyarr.c +++ b/src/core/tyarr.c @@ -1,6 +1,14 @@ #include "../core.h" #include "../utils/mut.h" +u8 elType2type[] = { + [el_bit] = t_bitarr, + [el_i8 ] = t_i8arr, [el_c8 ] = t_c8arr, + [el_i16] = t_i16arr,[el_c16] = t_c16arr, + [el_i32] = t_i32arr,[el_c32] = t_c32arr, + [el_f64] = t_f64arr +}; + B m_i8(i8 x) { return m_i32(x); } B m_i16(i16 x) { return m_i32(x); } B m_c8(u8 x) { return m_c32(x); } B m_c16(u16 x) { return m_c32(x); } #define TU I8 diff --git a/src/opt/mm_buddyTemplate.h b/src/opt/mm_buddyTemplate.h index 0c481363..5036a4c2 100644 --- a/src/opt/mm_buddyTemplate.h +++ b/src/opt/mm_buddyTemplate.h @@ -31,7 +31,12 @@ static void* BN(allocL)(i64 bucket, u8 type) { x->refc = 1; x->type = type; x->mmInfo = bucket; - #if defined(DEBUG) && !defined(DONT_FREE) + #if defined(SET_HEAP) + u8* p = (u8*)x; + u8* s = p + sizeof(Value); + u8* e = p + BSZ(bucket); + memset(s, SET_HEAP, e-s); + #elif defined(DEBUG) && !defined(DONT_FREE) u64* p = (u64*)x; u64* s = p + sizeof(Value)/8; u64* e = p + BSZ(bucket)/8; diff --git a/src/singeli/src/slash.singeli b/src/singeli/src/slash.singeli index b76ae22c..301dfb5f 100644 --- a/src/singeli/src/slash.singeli +++ b/src/singeli/src/slash.singeli @@ -26,20 +26,21 @@ def comp16{w:*u64, X, r:*i16, l:u64} = { r+= pc } step{w&15} - step{w>>4} + step{w>>4} # this runs even if the above step was all that's required, so it'll act on the invalid result of "r+= pc", so we need to overallocate even more to compensate } } slash2{F, T}(w:*u64, x:*T, r:*T, l:u64) : void = { xv:= reinterpret{*u64, x} - F{w, {} => {c:= *xv; xv+=1; c}, r, l} + F{w, {} => {c:= *xv; xv+= 1; c}, r, l} } slash1{F, T, iota, add}(w:*u64, r:*T, l:u64) : void = { x:u64 = iota - F{w, {} => {c:=x; x+= add; c}, r, l} + F{w, {} => {c:= x; x+= add; c}, r, l} } +# 8-bit writes ~8 bytes of garbage past end, 16-bit writes ~16 bytes 'bmipopc_2slash8' = slash2{comp8, i8} 'bmipopc_2slash16' = slash2{comp16, i16} 'bmipopc_1slash8' = slash1{comp8, i8, 0x0706050403020100, 0x0808080808080808} diff --git a/src/singeli/src/sse3.singeli b/src/singeli/src/sse3.singeli index e8727a62..9cd6dbaf 100644 --- a/src/singeli/src/sse3.singeli +++ b/src/singeli/src/sse3.singeli @@ -43,6 +43,21 @@ def broadcast{T, v & w128i{T, 64}} = emit{T, '_mm_set1_epi64x',promote{eltype{T} def broadcast{T, v & w128f{T, 64}} = emit{T, '_mm_set1_pd', v} def broadcast{T, v & w128f{T, 32}} = emit{T, '_mm_set1_ps', v} +def make{T==[2]f64,a,b} = emit{T,'_mm_setr_pd',a,b} +def make{T==[4]f32,a,b,c,d} = emit{T,'_mm_setr_ps',a,b,c,d} + +def makeGen{T,s,x} = apply{emit, merge{tup{T,s}, each{{c}=>promote{eltype{T},c}, x}}} +def make{T,a,b & w128i{T,64}} = makeGen{T, '_mm_set_epi64x', tup{b,a}} # yay no _mm_setr_epi64x +def make{T,a,b,c,d & w128i{T,32}} = makeGen{T, '_mm_setr_epi32', tup{a,b,c,d}} +def make{T,a,b,c,d,e,f,g,h & w128i{T,16}} = makeGen{T, '_mm_setr_epi16', tup{a,b,c,d,e,f,g,h}} +def make{T,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p & w128i{T,8}} = makeGen{T, '_mm_setr_epi8', tup{a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p}} +def make{T,x & w128{T} & istup{x}} = apply{make, merge{tup{T}, x}} + +def iota{T & w128{T,64}} = make{T,0,1} +def iota{T & w128{T,32}} = make{T,0,1,2,3} +def iota{T & w128{T,16}} = make{T,0,1,2,3,4,5,6,7} +def iota{T & w128{T,8}} = make{T,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15} + # signed comparison def __eq{a:T,b:T & T==[16]i8 } = emit{[16]u8, '_mm_cmpeq_epi8', a, b} def __eq{a:T,b:T & T==[ 8]i16} = emit{[ 8]u16, '_mm_cmpeq_epi16', a, b} diff --git a/test/README.md b/test/README.md index adae28b4..8ee599c1 100644 --- a/test/README.md +++ b/test/README.md @@ -11,4 +11,5 @@ test/moreCfgs.sh path/to/mlochbaum/BQN // run "2+2" in a bunch of configurations ./BQN test/copy.bqn // fuzz-test creating new arrays with elements copied from another ./BQN test/bitcpy.bqn // fuzz-test bit_cpy; requires a CBQN build with -DTEST_BITCPY ./BQN test/squeeze.bqn // fuzz-test squeezing; requires a CBQN build with -DEEQUAL_NEGZERO +./BQN test/random.bqn // various random tests ``` \ No newline at end of file diff --git a/test/random.bqn b/test/random.bqn new file mode 100644 index 00000000..44b22ae1 --- /dev/null +++ b/test/random.bqn @@ -0,0 +1,47 @@ +⟨LV⇐ListVariations, V⇐Variation, I⇐Info, TY⇐Type, Refc⇐Refc⟩ ← •internal +u ← ⌊100×(•UnixTime+1|100וMonoTime)@ + +rand ← •MakeRand •Show u +R ← rand.Range +RB ← "Ab" V R⟜2 # uniformly random boolean array +RB2 ← {¬⍟(R 2) "Ab" V 𝕩 R 1+R 2⋆R 10} # random boolean array with random uniform probability + +rByteVals ← "Ai8"V {𝕩-256×𝕩>127} ∾{{2⊸×⊸+˜´ 8↑/⁼ 𝕩 •rand.Subset 8}¨ ↕9}¨↕20 +RByte ← (R (≠rByteVals)˙)⊸(⊑⟜rByteVals) +RH ← R⥊¨RByte # store to a variable to randomize heap by 𝕨 values, each up to 𝕩 bytes +CH ← { # do "var CH↩" to a variable assigned to a result of RH + "heap corruption" ! ∧´2=Refc¨ 𝕩 + "heap corruption" ! 1 ≡ Refc 𝕩 + 0 +} +rByteVals {! "i8arr" ≡ TY 𝕩⥊𝕨}⌜ ↕10 # ⥊ is dumb for now, but when it realizes that n⥊0 is a bitarr this'll need changing + +OrScanBitarr ← {𝕊: + n ← 1 + R 2⋆R 13 + ! (∨` ≡ ⊢∘∨`) "Ab" V {𝕊: 1⌾((R n)⊸⊑)𝕩}⍟2 0⥊˜ n +}¨ ↕ + +PlusScanBitarr ← {𝕊: + a ← RB2 R 2⋆R 13 + ! (+` ≡ ⊢∘+`) a +}¨ ↕ + +BitSlash ← {ty‿dy‿max𝕊n: + f ← dy ⊑ ⟨/∘⊢ ⋄ {𝕩/ty V 𝕨 R 100}⟩ + {𝕊: + # 𝕩⊸{•Show 𝕨}⍟⊢ 0=10000|𝕩 + t1←20 RH 100 + n←R max + x←n F n↑RB2 128+n + t2←20 RH 100 + x↩0 ⋄ t1 CH↩ ⋄ t2 CH↩ + }¨↕n +} + +•Show "∨`bitarr" ⋄ OrScanBitarr 100000 +•Show "+`bitarr" ⋄ PlusScanBitarr 100000 + +•Show "heap corruption of /bit" ⋄ @‿0‿200 BitSlash 1000000 +•Show "heap corruption of bit/i8" ⋄ "Ai8"‿1‿50 BitSlash 1000000 +•Show "heap corruption of bit/i16" ⋄ "Ai16"‿1‿50 BitSlash 1000000 +•Show "heap corruption of bit/i32" ⋄ "Ai32"‿1‿50 BitSlash 1000000