| ... | @@ -3559,12 +3559,75 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T { | ... | @@ -3559,12 +3559,75 @@ pub fn alignForwardGeneric(comptime T: type, addr: T, alignment: T) T { |
| 3559 | /// Force an evaluation of the expression; this tries to prevent | 3559 | /// Force an evaluation of the expression; this tries to prevent |
| 3560 | /// the compiler from optimizing the computation away even if the | 3560 | /// the compiler from optimizing the computation away even if the |
| 3561 | /// result eventually gets discarded. | 3561 | /// result eventually gets discarded. |
| | 3562 | // TODO: use @declareSideEffect() when it is available - https://github.com/ziglang/zig/issues/6168 |
| 3562 | pub fn doNotOptimizeAway(val: anytype) void { | 3563 | pub fn doNotOptimizeAway(val: anytype) void { |
| 3563 | asm volatile ("" | 3564 | var a: u8 = 0; |
| 3564 | : | 3565 | if (@typeInfo(@TypeOf(.{a})).Struct.fields[0].is_comptime) return; |
| 3565 | : [val] "rm" (val), | 3566 | |
| 3566 | : "memory" | 3567 | const max_gp_register_bits = @bitSizeOf(c_long); |
| 3567 | ); | 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 | test "alignForward" { | 3633 | test "alignForward" { |