Skip to content

Commit

Permalink
Implement f64.promote_f32 instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Aug 9, 2020
1 parent 9e82ffc commit 128ebd3
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
6 changes: 5 additions & 1 deletion lib/fizzy/execute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1543,6 +1543,11 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
convert<uint64_t, double>(stack);
break;
}
case Instr::f64_promote_f32:
{
stack.top() = double{stack.top().f32};
break;
}

case Instr::f32_load:
case Instr::f64_load:
Expand Down Expand Up @@ -1587,7 +1592,6 @@ ExecutionResult execute(Instance& instance, FuncIdx func_idx, span<const Value>
case Instr::f64_max:
case Instr::f64_copysign:
case Instr::f32_demote_f64:
case Instr::f64_promote_f32:
case Instr::i32_reinterpret_f32:
case Instr::i64_reinterpret_f64:
case Instr::f32_reinterpret_i32:
Expand Down
45 changes: 45 additions & 0 deletions test/unittests/execute_floating_point_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,51 @@ TEST(execute_floating_point, f64_add)
EXPECT_THAT(execute(*instance, 0, {1.0011, 6.0066}), Result(7.0077));
}

TEST(execute_floating_point, f64_promote_f32)
{
/* wat2wasm
(func (param f32) (result f64)
local.get 0
f64.promote_f32
)
*/
auto wasm = from_hex("0061736d0100000001060160017d017c030201000a070105002000bb0b");
auto instance = instantiate(parse(wasm));

using f32_limits = std::numeric_limits<float>;
using f64_limits = std::numeric_limits<double>;

EXPECT_THAT(execute(*instance, 0, {0.0f}), Result(0.0));
EXPECT_THAT(execute(*instance, 0, {-0.0f}), Result(-0.0));
EXPECT_THAT(execute(*instance, 0, {1.0f}), Result(1.0));
EXPECT_THAT(execute(*instance, 0, {-1.0f}), Result(-1.0));

EXPECT_THAT(execute(*instance, 0, {f32_limits::max()}), Result(double{f32_limits::max()}));
EXPECT_THAT(execute(*instance, 0, {f32_limits::min()}), Result(double{f32_limits::min()}));
EXPECT_THAT(
execute(*instance, 0, {f32_limits::lowest()}), Result(double{f32_limits::lowest()}));

EXPECT_THAT(execute(*instance, 0, {f32_limits::infinity()}), Result(f64_limits::infinity()));
EXPECT_THAT(execute(*instance, 0, {-f32_limits::infinity()}), Result(-f64_limits::infinity()));

// The canonical NaN must result in canonical NaN (only the top bit set).
EXPECT_THAT(execute(*instance, 0, {FP32::nan(FP32::canon)}), Result(FP64::nan(FP64::canon)));

// An arithmetic NaN must result in any arithmetic NaN (payload >= canonical payload).
// The spec allows the result to be the canonical NaN, but in the current implementation it
// is not the case and the check is more restrictive than the spec requires.
const auto res1 = execute(*instance, 0, {FP32::nan(FP32::canon + 1)});
ASSERT_TRUE(!res1.trapped && res1.has_value);
EXPECT_GT(FP{res1.value.f64}.nan_payload(), FP64::canon);

// Other NaN must also result in arithmetic NaN.
// The spec allows the result to be the canonical NaN, but in the current implementation it
// is not the case and the check is more restrictive than the spec requires.
const auto res2 = execute(*instance, 0, {FP32::nan(1)});
ASSERT_TRUE(!res2.trapped && res2.has_value);
EXPECT_GT(FP{res2.value.f64}.nan_payload(), FP64::canon);
}


template <typename SrcT, typename DstT>
struct ConversionPairWasmTraits;
Expand Down

0 comments on commit 128ebd3

Please sign in to comment.