authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-04-30 14:14:54-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-05-01 12:05:25-07:00
log7b908cb02499534ac68fbd9d76b713608030a750
treec97f79900b4a0c0f0a8723760573323f994bb764
parent16d3f7b2fa7461643e85a9a52dcd2bf9c01caa1e

cbe: fix ub with integer `@abs`


2 files changed, 71 insertions(+), 228 deletions(-)

lib/zig.h+26-58
...@@ -530,6 +530,10 @@ typedef ptrdiff_t intptr_t;...@@ -530,6 +530,10 @@ typedef ptrdiff_t intptr_t;
530 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \530 return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
531 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \531 ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
532 } \532 } \
533\
534 static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
535 return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
536 } \
533\537\
534 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \538 zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
535\539\
...@@ -990,24 +994,6 @@ typedef unsigned long zig_Builtin64;...@@ -990,24 +994,6 @@ typedef unsigned long zig_Builtin64;
990typedef unsigned long long zig_Builtin64;994typedef unsigned long long zig_Builtin64;
991#endif995#endif
992996
993#define zig_builtin8_rev(name, val) __builtin_##name(val)
994
995#define zig_builtin16_rev(name, val) __builtin_##name(val)
996
997#if INT_MIN <= INT32_MIN
998#define zig_builtin32_rev(name, val) __builtin_##name(val)
999#elif LONG_MIN <= INT32_MIN
1000#define zig_builtin32_rev(name, val) __builtin_l##name(val)
1001#endif
1002
1003#if INT_MIN <= INT64_MIN
1004#define zig_builtin64_rev(name, val) __builtin_##name(val)
1005#elif LONG_MIN <= INT64_MIN
1006#define zig_builtin64_rev(name, val) __builtin_l##name(val)
1007#elif LLONG_MIN <= INT64_MIN
1008#define zig_builtin64_rev(name, val) __builtin_ll##name(val)
1009#endif
1010
1011static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {997static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
1012 return zig_wrap_u8(val >> (8 - bits), bits);998 return zig_wrap_u8(val >> (8 - bits), bits);
1013}999}
...@@ -1203,24 +1189,6 @@ zig_builtin_clz(16)...@@ -1203,24 +1189,6 @@ zig_builtin_clz(16)
1203zig_builtin_clz(32)1189zig_builtin_clz(32)
1204zig_builtin_clz(64)1190zig_builtin_clz(64)
12051191
1206#if zig_has_builtin(abs) || defined(zig_gnuc)
1207#define zig_builtin_abs(w) \
1208 static inline int##w##_t zig_abs_i##w(int##w##_t val) { \
1209 return zig_builtin##w##_rev(abs, val); \
1210 }
1211#else
1212#define zig_builtin_abs(w) \
1213 static inline int##w##_t zig_abs_i##w(int##w##_t val) { \
1214 if (val == INT##w##_MIN) return val; \
1215 int##w##_t tmp = val >> (w - 1); \
1216 return (val ^ tmp) - tmp; \
1217 }
1218#endif
1219zig_builtin_abs(8)
1220zig_builtin_abs(16)
1221zig_builtin_abs(32)
1222zig_builtin_abs(64)
1223
1224/* ======================== 128-bit Integer Support ========================= */1192/* ======================== 128-bit Integer Support ========================= */
12251193
1226#if !defined(zig_has_int128)1194#if !defined(zig_has_int128)
...@@ -3375,31 +3343,31 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))...@@ -3375,31 +3343,31 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
3375 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, sub, -) \3343 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, sub, -) \
3376 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, mul, *) \3344 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, mul, *) \
3377 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, div, /) \3345 zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, div, /) \
3378 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sqrt)))(zig_f##w, zig_float_fn_f##w##_sqrt, zig_libc_name_f##w(sqrt), (zig_f##w x), (x)) \3346 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sqrt)))(zig_f##w, zig_sqrt_f##w, zig_libc_name_f##w(sqrt), (zig_f##w x), (x)) \
3379 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sin)))(zig_f##w, zig_float_fn_f##w##_sin, zig_libc_name_f##w(sin), (zig_f##w x), (x)) \3347 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sin)))(zig_f##w, zig_sin_f##w, zig_libc_name_f##w(sin), (zig_f##w x), (x)) \
3380 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(cos)))(zig_f##w, zig_float_fn_f##w##_cos, zig_libc_name_f##w(cos), (zig_f##w x), (x)) \3348 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(cos)))(zig_f##w, zig_cos_f##w, zig_libc_name_f##w(cos), (zig_f##w x), (x)) \
3381 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(tan)))(zig_f##w, zig_float_fn_f##w##_tan, zig_libc_name_f##w(tan), (zig_f##w x), (x)) \3349 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(tan)))(zig_f##w, zig_tan_f##w, zig_libc_name_f##w(tan), (zig_f##w x), (x)) \
3382 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp)))(zig_f##w, zig_float_fn_f##w##_exp, zig_libc_name_f##w(exp), (zig_f##w x), (x)) \3350 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp)))(zig_f##w, zig_exp_f##w, zig_libc_name_f##w(exp), (zig_f##w x), (x)) \
3383 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp2)))(zig_f##w, zig_float_fn_f##w##_exp2, zig_libc_name_f##w(exp2), (zig_f##w x), (x)) \3351 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp2)))(zig_f##w, zig_exp2_f##w, zig_libc_name_f##w(exp2), (zig_f##w x), (x)) \
3384 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log)))(zig_f##w, zig_float_fn_f##w##_log, zig_libc_name_f##w(log), (zig_f##w x), (x)) \3352 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log)))(zig_f##w, zig_log_f##w, zig_libc_name_f##w(log), (zig_f##w x), (x)) \
3385 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log2)))(zig_f##w, zig_float_fn_f##w##_log2, zig_libc_name_f##w(log2), (zig_f##w x), (x)) \3353 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log2)))(zig_f##w, zig_log2_f##w, zig_libc_name_f##w(log2), (zig_f##w x), (x)) \
3386 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log10)))(zig_f##w, zig_float_fn_f##w##_log10, zig_libc_name_f##w(log10), (zig_f##w x), (x)) \3354 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log10)))(zig_f##w, zig_log10_f##w, zig_libc_name_f##w(log10), (zig_f##w x), (x)) \
3387 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fabs)))(zig_f##w, zig_float_fn_f##w##_fabs, zig_libc_name_f##w(fabs), (zig_f##w x), (x)) \3355 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fabs)))(zig_f##w, zig_abs_f##w, zig_libc_name_f##w(fabs), (zig_f##w x), (x)) \
3388 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(floor)))(zig_f##w, zig_float_fn_f##w##_floor, zig_libc_name_f##w(floor), (zig_f##w x), (x)) \3356 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(floor)))(zig_f##w, zig_floor_f##w, zig_libc_name_f##w(floor), (zig_f##w x), (x)) \
3389 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(ceil)))(zig_f##w, zig_float_fn_f##w##_ceil, zig_libc_name_f##w(ceil), (zig_f##w x), (x)) \3357 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(ceil)))(zig_f##w, zig_ceil_f##w, zig_libc_name_f##w(ceil), (zig_f##w x), (x)) \
3390 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(round)))(zig_f##w, zig_float_fn_f##w##_round, zig_libc_name_f##w(round), (zig_f##w x), (x)) \3358 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(round)))(zig_f##w, zig_round_f##w, zig_libc_name_f##w(round), (zig_f##w x), (x)) \
3391 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(trunc)))(zig_f##w, zig_float_fn_f##w##_trunc, zig_libc_name_f##w(trunc), (zig_f##w x), (x)) \3359 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(trunc)))(zig_f##w, zig_trunc_f##w, zig_libc_name_f##w(trunc), (zig_f##w x), (x)) \
3392 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmod)))(zig_f##w, zig_float_fn_f##w##_fmod, zig_libc_name_f##w(fmod), (zig_f##w x, zig_f##w y), (x, y)) \3360 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmod)))(zig_f##w, zig_fmod_f##w, zig_libc_name_f##w(fmod), (zig_f##w x, zig_f##w y), (x, y)) \
3393 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmin)))(zig_f##w, zig_float_fn_f##w##_fmin, zig_libc_name_f##w(fmin), (zig_f##w x, zig_f##w y), (x, y)) \3361 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmin)))(zig_f##w, zig_min_f##w, zig_libc_name_f##w(fmin), (zig_f##w x, zig_f##w y), (x, y)) \
3394 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_float_fn_f##w##_fmax, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \3362 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \
3395 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_float_fn_f##w##_fma, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \3363 zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \
3396\3364\
3397 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \3365 static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
3398 return zig_float_fn_f##w##_trunc(zig_div_f##w(lhs, rhs)); \3366 return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
3399 } \3367 } \
3400\3368\
3401 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \3369 static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
3402 return zig_float_fn_f##w##_floor(zig_div_f##w(lhs, rhs)); \3370 return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
3403 } \3371 } \
3404\3372\
3405 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \3373 static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
...@@ -3503,7 +3471,7 @@ zig_float_builtins(64)...@@ -3503,7 +3471,7 @@ zig_float_builtins(64)
3503 zig_##Type zig_atomicrmw_desired; \3471 zig_##Type zig_atomicrmw_desired; \
3504 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \3472 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3505 do { \3473 do { \
3506 zig_atomicrmw_desired = zig_float_fn_##Type##_fmin(zig_atomicrmw_expected, arg); \3474 zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \
3507 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \3475 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
3508 res = zig_atomicrmw_expected; \3476 res = zig_atomicrmw_expected; \
3509} while (0)3477} while (0)
...@@ -3512,7 +3480,7 @@ zig_float_builtins(64)...@@ -3512,7 +3480,7 @@ zig_float_builtins(64)
3512 zig_##Type zig_atomicrmw_desired; \3480 zig_##Type zig_atomicrmw_desired; \
3513 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \3481 zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
3514 do { \3482 do { \
3515 zig_atomicrmw_desired = zig_float_fn_##Type##_fmax(zig_atomicrmw_expected, arg); \3483 zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \
3516 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \3484 } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
3517 res = zig_atomicrmw_expected; \3485 res = zig_atomicrmw_expected; \
3518} while (0)3486} while (0)
src/codegen/c.zig+45-170
...@@ -3176,6 +3176,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3176,6 +3176,7 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3176 const zcu = f.object.dg.zcu;3176 const zcu = f.object.dg.zcu;
3177 const ip = &zcu.intern_pool;3177 const ip = &zcu.intern_pool;
3178 const air_tags = f.air.instructions.items(.tag);3178 const air_tags = f.air.instructions.items(.tag);
3179 const air_datas = f.air.instructions.items(.data);
31793180
3180 for (body) |inst| {3181 for (body) |inst| {
3181 if (f.liveness.isUnused(inst) and !f.air.mustLower(inst, ip))3182 if (f.liveness.isUnused(inst) and !f.air.mustLower(inst, ip))
...@@ -3203,23 +3204,23 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3203,23 +3204,23 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3203 .sub => try airBinOp(f, inst, "-", "sub", .none),3204 .sub => try airBinOp(f, inst, "-", "sub", .none),
3204 .mul => try airBinOp(f, inst, "*", "mul", .none),3205 .mul => try airBinOp(f, inst, "*", "mul", .none),
32053206
3206 .neg => try airFloatNeg(f, inst),3207 .neg => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "neg", .none),
3207 .div_float => try airBinBuiltinCall(f, inst, "div", .none),3208 .div_float => try airBinBuiltinCall(f, inst, "div", .none),
32083209
3209 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),3210 .div_trunc, .div_exact => try airBinOp(f, inst, "/", "div_trunc", .none),
3210 .rem => blk: {3211 .rem => blk: {
3211 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;3212 const bin_op = air_datas[@intFromEnum(inst)].bin_op;
3212 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);3213 const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu);
3213 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),3214 // For binary operations @TypeOf(lhs)==@TypeOf(rhs),
3214 // so we only check one.3215 // so we only check one.
3215 break :blk if (lhs_scalar_ty.isInt(zcu))3216 break :blk if (lhs_scalar_ty.isInt(zcu))
3216 try airBinOp(f, inst, "%", "rem", .none)3217 try airBinOp(f, inst, "%", "rem", .none)
3217 else3218 else
3218 try airBinFloatOp(f, inst, "fmod");3219 try airBinBuiltinCall(f, inst, "fmod", .none);
3219 },3220 },
3220 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),3221 .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none),
3221 .mod => try airBinBuiltinCall(f, inst, "mod", .none),3222 .mod => try airBinBuiltinCall(f, inst, "mod", .none),
3222 .abs => try airAbs(f, inst),3223 .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none),
32233224
3224 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),3225 .add_wrap => try airBinBuiltinCall(f, inst, "addw", .bits),
3225 .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits),3226 .sub_wrap => try airBinBuiltinCall(f, inst, "subw", .bits),
...@@ -3230,19 +3231,19 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3230,19 +3231,19 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3230 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),3231 .mul_sat => try airBinBuiltinCall(f, inst, "muls", .bits),
3231 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits),3232 .shl_sat => try airBinBuiltinCall(f, inst, "shls", .bits),
32323233
3233 .sqrt => try airUnFloatOp(f, inst, "sqrt"),3234 .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none),
3234 .sin => try airUnFloatOp(f, inst, "sin"),3235 .sin => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sin", .none),
3235 .cos => try airUnFloatOp(f, inst, "cos"),3236 .cos => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "cos", .none),
3236 .tan => try airUnFloatOp(f, inst, "tan"),3237 .tan => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "tan", .none),
3237 .exp => try airUnFloatOp(f, inst, "exp"),3238 .exp => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "exp", .none),
3238 .exp2 => try airUnFloatOp(f, inst, "exp2"),3239 .exp2 => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "exp2", .none),
3239 .log => try airUnFloatOp(f, inst, "log"),3240 .log => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "log", .none),
3240 .log2 => try airUnFloatOp(f, inst, "log2"),3241 .log2 => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "log2", .none),
3241 .log10 => try airUnFloatOp(f, inst, "log10"),3242 .log10 => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "log10", .none),
3242 .floor => try airUnFloatOp(f, inst, "floor"),3243 .floor => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "floor", .none),
3243 .ceil => try airUnFloatOp(f, inst, "ceil"),3244 .ceil => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "ceil", .none),
3244 .round => try airUnFloatOp(f, inst, "round"),3245 .round => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "round", .none),
3245 .trunc_float => try airUnFloatOp(f, inst, "trunc"),3246 .trunc_float => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "trunc", .none),
32463247
3247 .mul_add => try airMulAdd(f, inst),3248 .mul_add => try airMulAdd(f, inst),
32483249
...@@ -3251,21 +3252,21 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3251,21 +3252,21 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3251 .mul_with_overflow => try airOverflow(f, inst, "mul", .bits),3252 .mul_with_overflow => try airOverflow(f, inst, "mul", .bits),
3252 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),3253 .shl_with_overflow => try airOverflow(f, inst, "shl", .bits),
32533254
3254 .min => try airMinMax(f, inst, '<', "fmin"),3255 .min => try airMinMax(f, inst, '<', "min"),
3255 .max => try airMinMax(f, inst, '>', "fmax"),3256 .max => try airMinMax(f, inst, '>', "max"),
32563257
3257 .slice => try airSlice(f, inst),3258 .slice => try airSlice(f, inst),
32583259
3259 .cmp_gt => try airCmpOp(f, inst, f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op, .gt),3260 .cmp_gt => try airCmpOp(f, inst, air_datas[@intFromEnum(inst)].bin_op, .gt),
3260 .cmp_gte => try airCmpOp(f, inst, f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op, .gte),3261 .cmp_gte => try airCmpOp(f, inst, air_datas[@intFromEnum(inst)].bin_op, .gte),
3261 .cmp_lt => try airCmpOp(f, inst, f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op, .lt),3262 .cmp_lt => try airCmpOp(f, inst, air_datas[@intFromEnum(inst)].bin_op, .lt),
3262 .cmp_lte => try airCmpOp(f, inst, f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op, .lte),3263 .cmp_lte => try airCmpOp(f, inst, air_datas[@intFromEnum(inst)].bin_op, .lte),
32633264
3264 .cmp_eq => try airEquality(f, inst, .eq),3265 .cmp_eq => try airEquality(f, inst, .eq),
3265 .cmp_neq => try airEquality(f, inst, .neq),3266 .cmp_neq => try airEquality(f, inst, .neq),
32663267
3267 .cmp_vector => blk: {3268 .cmp_vector => blk: {
3268 const ty_pl = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_pl;3269 const ty_pl = air_datas[@intFromEnum(inst)].ty_pl;
3269 const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data;3270 const extra = f.air.extraData(Air.VectorCmp, ty_pl.payload).data;
3270 break :blk try airCmpOp(f, inst, extra, extra.compareOperator());3271 break :blk try airCmpOp(f, inst, extra, extra.compareOperator());
3271 },3272 },
...@@ -3324,11 +3325,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,...@@ -3324,11 +3325,11 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) error{ AnalysisFail,
3324 .memcpy => try airMemcpy(f, inst),3325 .memcpy => try airMemcpy(f, inst),
3325 .set_union_tag => try airSetUnionTag(f, inst),3326 .set_union_tag => try airSetUnionTag(f, inst),
3326 .get_union_tag => try airGetUnionTag(f, inst),3327 .get_union_tag => try airGetUnionTag(f, inst),
3327 .clz => try airUnBuiltinCall(f, inst, "clz", .bits),3328 .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits),
3328 .ctz => try airUnBuiltinCall(f, inst, "ctz", .bits),3329 .ctz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "ctz", .bits),
3329 .popcount => try airUnBuiltinCall(f, inst, "popcount", .bits),3330 .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popcount", .bits),
3330 .byte_swap => try airUnBuiltinCall(f, inst, "byte_swap", .bits),3331 .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits),
3331 .bit_reverse => try airUnBuiltinCall(f, inst, "bit_reverse", .bits),3332 .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits),
3332 .tag_name => try airTagName(f, inst),3333 .tag_name => try airTagName(f, inst),
3333 .error_name => try airErrorName(f, inst),3334 .error_name => try airErrorName(f, inst),
3334 .splat => try airSplat(f, inst),3335 .splat => try airSplat(f, inst),
...@@ -4139,7 +4140,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -4139,7 +4140,7 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
4139 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;4140 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
4140 const operand_ty = f.typeOf(ty_op.operand);4141 const operand_ty = f.typeOf(ty_op.operand);
4141 const scalar_ty = operand_ty.scalarType(zcu);4142 const scalar_ty = operand_ty.scalarType(zcu);
4142 if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, "not", .bits);4143 if (scalar_ty.toIntern() != .bool_type) return try airUnBuiltinCall(f, inst, ty_op.operand, "not", .bits);
41434144
4144 const op = try f.resolveInst(ty_op.operand);4145 const op = try f.resolveInst(ty_op.operand);
4145 try reap(f, inst, &.{ty_op.operand});4146 try reap(f, inst, &.{ty_op.operand});
...@@ -4389,10 +4390,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons...@@ -4389,10 +4390,8 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons
4389 const inst_ty = f.typeOfIndex(inst);4390 const inst_ty = f.typeOfIndex(inst);
4390 const inst_scalar_ty = inst_ty.scalarType(zcu);4391 const inst_scalar_ty = inst_ty.scalarType(zcu);
43914392
4392 if (inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64)4393 if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat())
4393 return try airBinBuiltinCall(f, inst, operation[1..], .none);4394 return try airBinBuiltinCall(f, inst, operation, .none);
4394 if (inst_scalar_ty.isRuntimeFloat())
4395 return try airBinFloatOp(f, inst, operation);
43964395
4397 const lhs = try f.resolveInst(bin_op.lhs);4396 const lhs = try f.resolveInst(bin_op.lhs);
4398 const rhs = try f.resolveInst(bin_op.rhs);4397 const rhs = try f.resolveInst(bin_op.rhs);
...@@ -6276,17 +6275,17 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -6276,17 +6275,17 @@ fn airIntFromPtr(f: *Function, inst: Air.Inst.Index) !CValue {
6276fn airUnBuiltinCall(6275fn airUnBuiltinCall(
6277 f: *Function,6276 f: *Function,
6278 inst: Air.Inst.Index,6277 inst: Air.Inst.Index,
6278 operand_ref: Air.Inst.Ref,
6279 operation: []const u8,6279 operation: []const u8,
6280 info: BuiltinInfo,6280 info: BuiltinInfo,
6281) !CValue {6281) !CValue {
6282 const zcu = f.object.dg.zcu;6282 const zcu = f.object.dg.zcu;
6283 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
62846283
6285 const operand = try f.resolveInst(ty_op.operand);6284 const operand = try f.resolveInst(operand_ref);
6286 try reap(f, inst, &.{ty_op.operand});6285 try reap(f, inst, &.{operand_ref});
6287 const inst_ty = f.typeOfIndex(inst);6286 const inst_ty = f.typeOfIndex(inst);
6288 const inst_scalar_ty = inst_ty.scalarType(zcu);6287 const inst_scalar_ty = inst_ty.scalarType(zcu);
6289 const operand_ty = f.typeOf(ty_op.operand);6288 const operand_ty = f.typeOf(operand_ref);
6290 const scalar_ty = operand_ty.scalarType(zcu);6289 const scalar_ty = operand_ty.scalarType(zcu);
62916290
6292 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);6291 const inst_scalar_ctype = try f.ctypeFromType(inst_scalar_ty, .complete);
...@@ -7009,7 +7008,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7009,7 +7008,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7009 const use_operator = scalar_ty.bitSize(zcu) <= 64;7008 const use_operator = scalar_ty.bitSize(zcu) <= 64;
7010 const op: union(enum) {7009 const op: union(enum) {
7011 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };7010 const Func = struct { operation: []const u8, info: BuiltinInfo = .none };
7012 float_op: Func,
7013 builtin: Func,7011 builtin: Func,
7014 infix: []const u8,7012 infix: []const u8,
7015 ternary: []const u8,7013 ternary: []const u8,
...@@ -7018,30 +7016,22 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7018,30 +7016,22 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7018 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },7016 .Or => if (use_operator) .{ .infix = " |= " } else .{ .builtin = .{ .operation = "or" } },
7019 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },7017 .Xor => if (use_operator) .{ .infix = " ^= " } else .{ .builtin = .{ .operation = "xor" } },
7020 .Min => switch (scalar_ty.zigTypeTag(zcu)) {7018 .Min => switch (scalar_ty.zigTypeTag(zcu)) {
7021 .Int => if (use_operator) .{ .ternary = " < " } else .{7019 .Int => if (use_operator) .{ .ternary = " < " } else .{ .builtin = .{ .operation = "min" } },
7022 .builtin = .{ .operation = "min" },7020 .Float => .{ .builtin = .{ .operation = "min" } },
7023 },
7024 .Float => .{ .float_op = .{ .operation = "fmin" } },
7025 else => unreachable,7021 else => unreachable,
7026 },7022 },
7027 .Max => switch (scalar_ty.zigTypeTag(zcu)) {7023 .Max => switch (scalar_ty.zigTypeTag(zcu)) {
7028 .Int => if (use_operator) .{ .ternary = " > " } else .{7024 .Int => if (use_operator) .{ .ternary = " > " } else .{ .builtin = .{ .operation = "max" } },
7029 .builtin = .{ .operation = "max" },7025 .Float => .{ .builtin = .{ .operation = "max" } },
7030 },
7031 .Float => .{ .float_op = .{ .operation = "fmax" } },
7032 else => unreachable,7026 else => unreachable,
7033 },7027 },
7034 .Add => switch (scalar_ty.zigTypeTag(zcu)) {7028 .Add => switch (scalar_ty.zigTypeTag(zcu)) {
7035 .Int => if (use_operator) .{ .infix = " += " } else .{7029 .Int => if (use_operator) .{ .infix = " += " } else .{ .builtin = .{ .operation = "addw", .info = .bits } },
7036 .builtin = .{ .operation = "addw", .info = .bits },
7037 },
7038 .Float => .{ .builtin = .{ .operation = "add" } },7030 .Float => .{ .builtin = .{ .operation = "add" } },
7039 else => unreachable,7031 else => unreachable,
7040 },7032 },
7041 .Mul => switch (scalar_ty.zigTypeTag(zcu)) {7033 .Mul => switch (scalar_ty.zigTypeTag(zcu)) {
7042 .Int => if (use_operator) .{ .infix = " *= " } else .{7034 .Int => if (use_operator) .{ .infix = " *= " } else .{ .builtin = .{ .operation = "mulw", .info = .bits } },
7043 .builtin = .{ .operation = "mulw", .info = .bits },
7044 },
7045 .Float => .{ .builtin = .{ .operation = "mul" } },7035 .Float => .{ .builtin = .{ .operation = "mul" } },
7046 else => unreachable,7036 else => unreachable,
7047 },7037 },
...@@ -7105,17 +7095,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7105,17 +7095,6 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue {
7105 const v = try Vectorize.start(f, inst, writer, operand_ty);7095 const v = try Vectorize.start(f, inst, writer, operand_ty);
7106 try f.writeCValue(writer, accum, .Other);7096 try f.writeCValue(writer, accum, .Other);
7107 switch (op) {7097 switch (op) {
7108 .float_op => |func| {
7109 try writer.writeAll(" = zig_float_fn_");
7110 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
7111 try writer.print("_{s}(", .{func.operation});
7112 try f.writeCValue(writer, accum, .FunctionArgument);
7113 try writer.writeAll(", ");
7114 try f.writeCValue(writer, operand, .Other);
7115 try v.elem(f, writer);
7116 try f.object.dg.renderBuiltinInfo(writer, scalar_ty, func.info);
7117 try writer.writeByte(')');
7118 },
7119 .builtin => |func| {7098 .builtin => |func| {
7120 try writer.print(" = zig_{s}_", .{func.operation});7099 try writer.print(" = zig_{s}_", .{func.operation});
7121 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);7100 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
...@@ -7396,110 +7375,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7396,110 +7375,6 @@ fn airWasmMemoryGrow(f: *Function, inst: Air.Inst.Index) !CValue {
7396 return local;7375 return local;
7397}7376}
73987377
7399fn airFloatNeg(f: *Function, inst: Air.Inst.Index) !CValue {
7400 const zcu = f.object.dg.zcu;
7401 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
7402
7403 const operand = try f.resolveInst(un_op);
7404 try reap(f, inst, &.{un_op});
7405
7406 const operand_ty = f.typeOf(un_op);
7407 const scalar_ty = operand_ty.scalarType(zcu);
7408
7409 const writer = f.object.writer();
7410 const local = try f.allocLocal(inst, operand_ty);
7411 const v = try Vectorize.start(f, inst, writer, operand_ty);
7412 try f.writeCValue(writer, local, .Other);
7413 try v.elem(f, writer);
7414 try writer.writeAll(" = zig_neg_");
7415 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
7416 try writer.writeByte('(');
7417 try f.writeCValue(writer, operand, .FunctionArgument);
7418 try v.elem(f, writer);
7419 try writer.writeAll(");\n");
7420 try v.end(f, inst, writer);
7421
7422 return local;
7423}
7424
7425fn airAbs(f: *Function, inst: Air.Inst.Index) !CValue {
7426 const zcu = f.object.dg.zcu;
7427 const ty_op = f.air.instructions.items(.data)[@intFromEnum(inst)].ty_op;
7428 const operand = try f.resolveInst(ty_op.operand);
7429 const ty = f.typeOf(ty_op.operand);
7430 const scalar_ty = ty.scalarType(zcu);
7431
7432 switch (scalar_ty.zigTypeTag(zcu)) {
7433 .Int => if (ty.zigTypeTag(zcu) == .Vector) {
7434 return f.fail("TODO implement airAbs for '{}'", .{ty.fmt(zcu)});
7435 } else {
7436 return airUnBuiltinCall(f, inst, "abs", .none);
7437 },
7438 .Float => return unFloatOp(f, inst, operand, ty, "fabs"),
7439 else => unreachable,
7440 }
7441}
7442
7443fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, operation: []const u8) !CValue {
7444 const zcu = f.object.dg.zcu;
7445 const scalar_ty = ty.scalarType(zcu);
7446
7447 const writer = f.object.writer();
7448 const local = try f.allocLocal(inst, ty);
7449 const v = try Vectorize.start(f, inst, writer, ty);
7450 try f.writeCValue(writer, local, .Other);
7451 try v.elem(f, writer);
7452 try writer.writeAll(" = zig_float_fn_");
7453 try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty);
7454 try writer.print("_{s}(", .{operation});
7455 try f.writeCValue(writer, operand, .FunctionArgument);
7456 try v.elem(f, writer);
7457 try writer.writeAll(");\n");
7458 try v.end(f, inst, writer);
7459
7460 return local;
7461}
7462
7463fn airUnFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7464 const un_op = f.air.instructions.items(.data)[@intFromEnum(inst)].un_op;
7465
7466 const operand = try f.resolveInst(un_op);
7467 try reap(f, inst, &.{un_op});
7468
7469 const inst_ty = f.typeOfIndex(inst);
7470 return unFloatOp(f, inst, operand, inst_ty, operation);
7471}
7472
7473fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CValue {
7474 const zcu = f.object.dg.zcu;
7475 const bin_op = f.air.instructions.items(.data)[@intFromEnum(inst)].bin_op;
7476
7477 const lhs = try f.resolveInst(bin_op.lhs);
7478 const rhs = try f.resolveInst(bin_op.rhs);
7479 try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs });
7480
7481 const inst_ty = f.typeOfIndex(inst);
7482 const inst_scalar_ty = inst_ty.scalarType(zcu);
7483
7484 const writer = f.object.writer();
7485 const local = try f.allocLocal(inst, inst_ty);
7486 const v = try Vectorize.start(f, inst, writer, inst_ty);
7487 try f.writeCValue(writer, local, .Other);
7488 try v.elem(f, writer);
7489 try writer.writeAll(" = zig_float_fn_");
7490 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
7491 try writer.print("_{s}(", .{operation});
7492 try f.writeCValue(writer, lhs, .FunctionArgument);
7493 try v.elem(f, writer);
7494 try writer.writeAll(", ");
7495 try f.writeCValue(writer, rhs, .FunctionArgument);
7496 try v.elem(f, writer);
7497 try writer.writeAll(");\n");
7498 try v.end(f, inst, writer);
7499
7500 return local;
7501}
7502
7503fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {7378fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7504 const zcu = f.object.dg.zcu;7379 const zcu = f.object.dg.zcu;
7505 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;7380 const pl_op = f.air.instructions.items(.data)[@intFromEnum(inst)].pl_op;
...@@ -7518,9 +7393,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {...@@ -7518,9 +7393,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
7518 const v = try Vectorize.start(f, inst, writer, inst_ty);7393 const v = try Vectorize.start(f, inst, writer, inst_ty);
7519 try f.writeCValue(writer, local, .Other);7394 try f.writeCValue(writer, local, .Other);
7520 try v.elem(f, writer);7395 try v.elem(f, writer);
7521 try writer.writeAll(" = zig_float_fn_");7396 try writer.writeAll(" = zig_fma_");
7522 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);7397 try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty);
7523 try writer.writeAll("_fma(");7398 try writer.writeByte('(');
7524 try f.writeCValue(writer, mulend1, .FunctionArgument);7399 try f.writeCValue(writer, mulend1, .FunctionArgument);
7525 try v.elem(f, writer);7400 try v.elem(f, writer);
7526 try writer.writeAll(", ");7401 try writer.writeAll(", ");