| ... | ... | @@ -3559,12 +3559,75 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T { |
| 3559 | 3559 | /// Force an evaluation of the expression; this tries to prevent |
| 3560 | 3560 | /// the compiler from optimizing the computation away even if the |
| 3561 | 3561 | /// result eventually gets discarded. |
| 3562 | // TODO: use @declareSideEffect() when it is available - https://github.com/ziglang/zig/issues/6168 |
| 3562 | 3563 | pub fn doNotOptimizeAway(val: anytype) void { |
| 3563 | | asm volatile ("" |
| 3564 | | : |
| 3565 | | : [val] "rm" (val), |
| 3566 | | : "memory" |
| 3567 | | ); |
| 3564 | var a: u8 = 0; |
| 3565 | if (@typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime) return; |
| 3566 | |
| 3567 | const max_gp_register_bits = @bitSizeOf(c_long); |
| 3568 | const t = @typeInfo(@TypeOf(val)); |
| 3569 | switch (t) { |
| 3570 | .Void, .Null, .ComptimeInt, .ComptimeFloat => return, |
| 3571 | .Enum => doNotOptimizeAway(@enumToInt(val)), |
| 3572 | .Bool => doNotOptimizeAway(@boolToInt(val)), |
| 3573 | .Int => { |
| 3574 | const bits = t.Int.bits; |
| 3575 | if (bits <= max_gp_register_bits) { |
| 3576 | const val2 = @as( |
| 3577 | std.meta.Int(t.Int.signedness, @max(8, std.math.ceilPowerOfTwoAssert(u16, bits))), |
| 3578 | val, |
| 3579 | ); |
| 3580 | asm volatile ("" |
| 3581 | : |
| 3582 | : [val2] "r" (val2), |
| 3583 | ); |
| 3584 | } else doNotOptimizeAway(&val); |
| 3585 | }, |
| 3586 | .Float => { |
| 3587 | if (t.Float.bits == 32 or t.Float.bits == 64) { |
| 3588 | asm volatile ("" |
| 3589 | : |
| 3590 | : [val] "rm" (val), |
| 3591 | ); |
| 3592 | } else doNotOptimizeAway(&val); |
| 3593 | }, |
| 3594 | .Pointer => asm volatile ("" |
| 3595 | : |
| 3596 | : [val] "m" (val), |
| 3597 | : "memory" |
| 3598 | ), |
| 3599 | .Array => { |
| 3600 | if (t.Array.len * @sizeOf(t.Array.child) <= 64) { |
| 3601 | for (val) |v| doNotOptimizeAway(v); |
| 3602 | } else doNotOptimizeAway(&val); |
| 3603 | }, |
| 3604 | else => doNotOptimizeAway(&val), |
| 3605 | } |
| 3606 | } |
| 3607 | |
| 3608 | test "doNotOptimizeAway" { |
| 3609 | comptime doNotOptimizeAway("test"); |
| 3610 | |
| 3611 | doNotOptimizeAway(null); |
| 3612 | doNotOptimizeAway(true); |
| 3613 | doNotOptimizeAway(0); |
| 3614 | doNotOptimizeAway(0.0); |
| 3615 | doNotOptimizeAway(@as(u1, 0)); |
| 3616 | doNotOptimizeAway(@as(u3, 0)); |
| 3617 | doNotOptimizeAway(@as(u8, 0)); |
| 3618 | doNotOptimizeAway(@as(u16, 0)); |
| 3619 | doNotOptimizeAway(@as(u32, 0)); |
| 3620 | doNotOptimizeAway(@as(u64, 0)); |
| 3621 | doNotOptimizeAway(@as(u128, 0)); |
| 3622 | doNotOptimizeAway(@as(u13, 0)); |
| 3623 | doNotOptimizeAway(@as(u37, 0)); |
| 3624 | doNotOptimizeAway(@as(u96, 0)); |
| 3625 | doNotOptimizeAway(@as(u200, 0)); |
| 3626 | doNotOptimizeAway(@as(f32, 0.0)); |
| 3627 | doNotOptimizeAway(@as(f64, 0.0)); |
| 3628 | doNotOptimizeAway([_]u8{0} ** 4); |
| 3629 | doNotOptimizeAway([_]u8{0} ** 100); |
| 3630 | doNotOptimizeAway(@as(std.builtin.Endian, .Little)); |
| 3568 | 3631 | } |
| 3569 | 3632 | |
| 3570 | 3633 | test "alignForward" { |