From 69e496f7fa6c3299c37ff327f33556250ac49173 Mon Sep 17 00:00:00 2001 From: Marshall Lochbaum Date: Fri, 4 Feb 2022 16:23:05 -0500 Subject: [PATCH] =?UTF-8?q?Avoid=20=E2=80=A2bit.=5Fcast=20aliasing,=20and?= =?UTF-8?q?=20all=20copying=20by=20using=20slices?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/builtins/sysfn.c | 29 ++++++++++++++++++----------- src/h.h | 1 + 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/builtins/sysfn.c b/src/builtins/sysfn.c index 7f715fc1..9aad8b02 100644 --- a/src/builtins/sysfn.c +++ b/src/builtins/sysfn.c @@ -872,14 +872,14 @@ CastType getCastType(B e) { } return (CastType) { o2s(s), t }; } -TyArr* convert(CastType t, B x) { +B convert(CastType t, B x) { switch (t.s) { - case 1: return toBitArr(x); - case 8: return t.t=='c' ? toC8Arr (x) : toI8Arr (x); - case 16: return t.t=='c' ? toC16Arr(x) : toI16Arr(x); - case 32: return t.t=='c' ? toC32Arr(x) : toI32Arr(x); - case 64: return toF64Arr(x); - default: thrM("•bit._cast: unsupported result width"); + case 1: return taga(toBitArr(x)); + case 8: return t.t=='c' ? toC8Any (x) : toI8Any (x); + case 16: return t.t=='c' ? toC16Any(x) : toI16Any(x); + case 32: return t.t=='c' ? toC32Any(x) : toI32Any(x); + case 64: return toF64Any(x); + default: thrM("•bit._cast: unsupported input width"); } } u8 typeOfCast(CastType t) { @@ -903,14 +903,21 @@ B bitcast_c1(Md1D* d, B x) { B f = d->f; usz s=xt.s*sh[xr-1], zl=s/zt.s; if (zl*zt.s != s) thrM("•bit._cast: incompatible lengths"); // Convert to input type - B r = taga(convert(xt, x)); + B r = convert(xt, x); + if (v(r)->refc!=1) { + r = taga(TI(r,slice)(r, 0, a(r)->ia)); + sprnk(v(r),xr); + } // Cast to output type - v(r)->type = typeOfCast(zt); + u8 rt = typeOfCast(zt); if (IS_SLICE(v(r)->type)) rt = TO_SLICE(rt); + v(r)->type = rt; // Adjust shape if (xr<=1) { - a(r)->sh[xr-1]=zl; + Arr* a = a(r); + a->ia = zl; + a->sh = &a->ia; } else { - if (shObj(r)->refc>1) { + if (shObj(x)->refc>1) { usz* zsh = arr_shAlloc(a(r), xr); memcpy(zsh, sh, (xr-1)*sizeof(usz)); sh = zsh; diff --git a/src/h.h b/src/h.h index 8ba03958..72e099d4 100644 --- a/src/h.h +++ b/src/h.h @@ -226,6 +226,7 @@ enum Type { }; #define IS_SLICE(T) ((T)>=t_hslice & (T)<=t_f64slice) #define IS_ARR(T) ((T)>=t_harr & (T)<=t_bitarr) +#define TO_SLICE(T) ((T) + t_hslice - t_harr) // Assumes T!=t_bitarr enum ElType { // a⌈b shall return the type that can store both, if possible el_bit=0,