fix FFI integer overflow check on ARM

clang optimizes a raw f!=(u8)f to like f!=(u32)f on ARM which changes behavior (we're technically using UB here, but there's no reasonable alternative); use q_ functions that know how to work around this
This commit is contained in:
dzaima 2023-08-19 19:47:09 +03:00
parent 7c4599543b
commit 721dccf636
2 changed files with 13 additions and 8 deletions

View File

@ -623,14 +623,14 @@ void genObj(B o, B c, bool anyMut, void* ptr) {
switch(t) { default: UD; // thrF("FFI: Unimplemented scalar type \"%S\"", sty_names[t]);
case sty_a: *(BQNV*)ptr = makeX(inc(c)); break;
case sty_ptr: thrM("FFI: \"*\" unimplemented"); break;
case sty_u8: { u8 i = ( u8)f; if(f!=i) thrM("FFI: u8 argument not exact" ); *( u8*)ptr = i; break; }
case sty_i8: { i8 i = ( i8)f; if(f!=i) thrM("FFI: i8 argument not exact" ); *( i8*)ptr = i; break; }
case sty_u16: { u16 i = (u16)f; if(f!=i) thrM("FFI: u16 argument not exact"); *(u16*)ptr = i; break; }
case sty_i16: { i16 i = (i16)f; if(f!=i) thrM("FFI: i16 argument not exact"); *(i16*)ptr = i; break; }
case sty_u32: { u32 i = (u32)f; if(f!=i) thrM("FFI: u32 argument not exact"); *(u32*)ptr = i; break; }
case sty_i32: { i32 i = (i32)f; if(f!=i) thrM("FFI: i32 argument not exact"); *(i32*)ptr = i; break; }
case sty_u64: { u64 i = (u64)f; if(f!=i) thrM("FFI: u64 argument not exact"); if (i>=(1ULL<<53)) thrM("FFI: u64 argument value ≥ 2⋆53"); *(u64*)ptr = i; break; }
case sty_i64: { i64 i = (i64)f; if(f!=i) thrM("FFI: i64 argument not exact"); if (i>=(1LL<<53) || i<=-(1LL<<53)) thrM("FFI: i64 argument absolute value ≥ 2⋆53"); *(i64*)ptr = i; break; }
case sty_u8: { if(!q_fu8 (f)) thrM("FFI: u8 argument not exact" ); *( u8*)ptr = ( u8)f; break; }
case sty_i8: { if(!q_fi8 (f)) thrM("FFI: i8 argument not exact" ); *( i8*)ptr = ( i8)f; break; }
case sty_u16: { if(!q_fu16(f)) thrM("FFI: u16 argument not exact"); *(u16*)ptr = (u16)f; break; }
case sty_i16: { if(!q_fi16(f)) thrM("FFI: i16 argument not exact"); *(i16*)ptr = (i16)f; break; }
case sty_u32: { if(!q_fu32(f)) thrM("FFI: u32 argument not exact"); *(u32*)ptr = (u32)f; break; }
case sty_i32: { if(!q_fi32(f)) thrM("FFI: i32 argument not exact"); *(i32*)ptr = (i32)f; break; }
case sty_u64: { if(!q_fu64(f)) thrM("FFI: u64 argument not exact"); u64 i=(u64)f; if (i>=(1ULL<<53)) thrM("FFI: u64 argument value ≥ 2⋆53"); *(u64*)ptr = i; break; }
case sty_i64: { if(!q_fi64(f)) thrM("FFI: i64 argument not exact"); i64 i=(i64)f; if (i>=(1LL<<53) || i<=-(1LL<<53)) thrM("FFI: i64 argument absolute value ≥ 2⋆53"); *(i64*)ptr = i; break; }
case sty_f32: *(float* )ptr = f; break;
case sty_f64: *(double*)ptr = f; break;
}

View File

@ -492,6 +492,10 @@ FORCE_INLINE bool q_fi64(f64 x) { return x==(f64)(i64) x; } FORCE_INLINE bo
FORCE_INLINE bool q_fu64(f64 x) { return x==(f64)(u64) x; } FORCE_INLINE bool q_u64(B x) { return q_fu64(x.f); }
FORCE_INLINE bool q_fusz(f64 x) { return x==(f64)(usz) x; } FORCE_INLINE bool q_usz(B x) { return q_fusz(x.f); }
/*no need for a q_ff64*/ FORCE_INLINE bool q_f64(B x) { return isF64(x); }
FORCE_INLINE bool q_fu8 (f64 x) { return x==(f64)(u8 )(u32)x; }
FORCE_INLINE bool q_fu16(f64 x) { return x==(f64)(u16)(u32)x; }
FORCE_INLINE bool q_fu32(f64 x) { return x==(f64)(u32) x; }
FORCE_INLINE bool q_ibit(i64 x) { return x==0 | x==1; }
FORCE_INLINE bool q_ubit(u64 x) { return x==0 | x==1; }
FORCE_INLINE bool q_c8 (B x) { return x.u>>8 == ((u64)C32_TAG)<<40; }
@ -500,6 +504,7 @@ FORCE_INLINE bool q_c32(B x) { return isC32(x); }
FORCE_INLINE bool q_N (B x) { return x.u==bi_N.u; } // is ·
FORCE_INLINE bool noFill(B x) { return x.u==bi_noFill.u; }
FORCE_INLINE bool o2bG(B x) { return(x.u<<1)!=0;} FORCE_INLINE bool o2b(B x) { i32 t=(i32)x.f; if(t!=x.f || t!=0&t!=1)thrM("Expected boolean"); return o2bG(x); }
FORCE_INLINE i32 o2iG(B x) { return (i32)x.f; } FORCE_INLINE i32 o2i(B x) { if (!q_i32(x)) thrM("Expected integer"); return o2iG(x); }
FORCE_INLINE u32 o2cG(B x) { return (u32)x.u; } FORCE_INLINE u32 o2c(B x) { if (!isC32(x)) thrM("Expected character"); return o2cG(x); }