From 0e905cb33072905df1ea9ac53ea9e592bc497787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 26 Aug 2020 19:16:43 +0200 Subject: [PATCH] Use simpler ops for binary instructions (fixes GCC issue) This replaces usage of std::plus{} and others with simpler in-house implementation. The difference is that the std:: versions are passing arguments by reference. In GCC builds without optimization this may cause the arguments to be swapped in commutative instructions. This is at least annoyance for floating-point add which may produce different NaN results if both inputs are NaNs. This is not a problem for Wasm conformance, but prevents running exhaustive tests against software floats implementations. --- lib/fizzy/execute.cpp | 70 ++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/lib/fizzy/execute.cpp b/lib/fizzy/execute.cpp index a905ed547..9b488fccb 100644 --- a/lib/fizzy/execute.cpp +++ b/lib/fizzy/execute.cpp @@ -449,6 +449,36 @@ inline void comparison_op(OperandStack& stack, Op op) noexcept stack.top() = uint32_t{op(val1, val2)}; } +template +inline constexpr T add(T a, T b) noexcept +{ + return a + b; +} + +template +inline constexpr T sub(T a, T b) noexcept +{ + return a - b; +} + +template +inline constexpr T mul(T a, T b) noexcept +{ + return a * b; +} + +template +inline constexpr T div(T a, T b) noexcept +{ + return a / b; +} + +template +inline constexpr T rem(T a, T b) noexcept +{ + return a % b; +} + template inline T shift_left(T lhs, T rhs) noexcept { @@ -1448,17 +1478,17 @@ ExecutionResult execute( } case Instr::i32_add: { - binary_op(stack, std::plus()); + binary_op(stack, add); break; } case Instr::i32_sub: { - binary_op(stack, std::minus()); + binary_op(stack, sub); break; } case Instr::i32_mul: { - binary_op(stack, std::multiplies()); + binary_op(stack, mul); break; } case Instr::i32_div_s: @@ -1470,7 +1500,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::divides()); + binary_op(stack, div); break; } case Instr::i32_div_u: @@ -1481,7 +1511,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::divides()); + binary_op(stack, div); break; } case Instr::i32_rem_s: @@ -1499,7 +1529,7 @@ ExecutionResult execute( stack.top() = 0; } else - binary_op(stack, std::modulus()); + binary_op(stack, rem); break; } case Instr::i32_rem_u: @@ -1510,7 +1540,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::modulus()); + binary_op(stack, rem); break; } case Instr::i32_and: @@ -1571,17 +1601,17 @@ ExecutionResult execute( } case Instr::i64_add: { - binary_op(stack, std::plus()); + binary_op(stack, add); break; } case Instr::i64_sub: { - binary_op(stack, std::minus()); + binary_op(stack, sub); break; } case Instr::i64_mul: { - binary_op(stack, std::multiplies()); + binary_op(stack, mul); break; } case Instr::i64_div_s: @@ -1593,7 +1623,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::divides()); + binary_op(stack, div); break; } case Instr::i64_div_u: @@ -1604,7 +1634,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::divides()); + binary_op(stack, div); break; } case Instr::i64_rem_s: @@ -1622,7 +1652,7 @@ ExecutionResult execute( stack.top() = 0; } else - binary_op(stack, std::modulus()); + binary_op(stack, rem); break; } case Instr::i64_rem_u: @@ -1633,7 +1663,7 @@ ExecutionResult execute( trap = true; goto end; } - binary_op(stack, std::modulus()); + binary_op(stack, rem); break; } case Instr::i64_and: @@ -1716,17 +1746,17 @@ ExecutionResult execute( case Instr::f32_add: { - binary_op(stack, std::plus{}); + binary_op(stack, add); break; } case Instr::f32_sub: { - binary_op(stack, std::minus{}); + binary_op(stack, sub); break; } case Instr::f32_mul: { - binary_op(stack, std::multiplies{}); + binary_op(stack, mul); break; } case Instr::f32_div: @@ -1794,17 +1824,17 @@ ExecutionResult execute( case Instr::f64_add: { - binary_op(stack, std::plus{}); + binary_op(stack, add); break; } case Instr::f64_sub: { - binary_op(stack, std::minus{}); + binary_op(stack, sub); break; } case Instr::f64_mul: { - binary_op(stack, std::multiplies{}); + binary_op(stack, mul); break; } case Instr::f64_div: