diff options
Diffstat (limited to 'src/tools/spectest-interp.cc')
-rw-r--r-- | src/tools/spectest-interp.cc | 187 |
1 files changed, 91 insertions, 96 deletions
diff --git a/src/tools/spectest-interp.cc b/src/tools/spectest-interp.cc index 57f9e855..f335e572 100644 --- a/src/tools/spectest-interp.cc +++ b/src/tools/spectest-interp.cc @@ -150,10 +150,6 @@ class ActionCommandBase : public CommandMixin<TypeEnum> { }; typedef ActionCommandBase<CommandType::Action> ActionCommand; -typedef ActionCommandBase<CommandType::AssertReturnCanonicalNan> - AssertReturnCanonicalNanCommand; -typedef ActionCommandBase<CommandType::AssertReturnArithmeticNan> - AssertReturnArithmeticNanCommand; class RegisterCommand : public CommandMixin<CommandType::Register> { public: @@ -161,10 +157,16 @@ class RegisterCommand : public CommandMixin<CommandType::Register> { std::string name; }; +struct ExpectedValue { + bool is_expected_nan; + TypedValue value; + ExpectedNan expectedNan; +}; + class AssertReturnCommand : public CommandMixin<CommandType::AssertReturn> { public: Action action; - TypedValues expected; + std::vector<ExpectedValue> expected; }; class AssertReturnFuncCommand @@ -226,7 +228,12 @@ class JSONParser { wabt::Result ParseTypeObject(Type* out_type); wabt::Result ParseTypeVector(TypeVector* out_types); wabt::Result ParseConst(TypedValue* out_value); + wabt::Result ParseConstValue(TypedValue* out_value, + string_view type_str, + string_view value_str); wabt::Result ParseConstVector(TypedValues* out_values); + wabt::Result ParseExpectedValue(ExpectedValue* out_value); + wabt::Result ParseExpectedValues(std::vector<ExpectedValue>* out_values); wabt::Result ParseAction(Action* out_action); wabt::Result ParseActionResult(); wabt::Result ParseModuleType(ModuleType* out_type); @@ -496,9 +503,14 @@ wabt::Result JSONParser::ParseConst(TypedValue* out_value) { PARSE_KEY_STRING_VALUE("value", &value_str); EXPECT("}"); + return ParseConstValue(out_value, type_str, value_str); +} + +wabt::Result JSONParser::ParseConstValue(TypedValue* out_value, + string_view type_str, + string_view value_str) { const char* value_start = value_str.data(); const char* value_end = value_str.data() + value_str.size(); - if (type_str == "i32") { uint32_t value; if (Failed((ParseInt32(value_start, value_end, &value, @@ -564,13 +576,56 @@ wabt::Result JSONParser::ParseConst(TypedValue* out_value) { out_value->type = Type::Funcref; out_value->value.ref = {RefType::Func, value}; } else { - PrintError("unknown concrete type: \"%s\"", type_str.c_str()); + PrintError("unknown concrete type: \"%s\"", type_str.to_string().c_str()); return wabt::Result::Error; } return wabt::Result::Ok; } +wabt::Result JSONParser::ParseExpectedValue(ExpectedValue* out_value) { + std::string type_str; + std::string value_str; + EXPECT("{"); + PARSE_KEY_STRING_VALUE("type", &type_str); + EXPECT(","); + PARSE_KEY_STRING_VALUE("value", &value_str); + EXPECT("}"); + + if (type_str == "f32" || type_str == "f64") { + if (value_str == "nan:canonical") { + out_value->value.type = type_str == "f32" ? Type::F32 : Type::F64; + out_value->is_expected_nan = true; + out_value->expectedNan = ExpectedNan::Canonical; + return wabt::Result::Ok; + } else if (value_str == "nan:arithmetic") { + out_value->value.type = type_str == "f32" ? Type::F32 : Type::F64; + out_value->is_expected_nan = true; + out_value->expectedNan = ExpectedNan::Arithmetic; + return wabt::Result::Ok; + } + } + + out_value->is_expected_nan = false; + return ParseConstValue(&out_value->value, type_str, value_str); +} + +wabt::Result JSONParser::ParseExpectedValues(std::vector<ExpectedValue>* out_values) { + out_values->clear(); + EXPECT("["); + bool first = true; + while (!Match("]")) { + if (!first) { + EXPECT(","); + } + ExpectedValue value; + CHECK_RESULT(ParseExpectedValue(&value)); + out_values->push_back(value); + first = false; + } + return wabt::Result::Ok; +} + wabt::Result JSONParser::ParseConstVector(TypedValues* out_values) { out_values->clear(); EXPECT("["); @@ -759,7 +814,7 @@ wabt::Result JSONParser::ParseCommand(CommandPtr* out_command) { CHECK_RESULT(ParseAction(&command->action)); EXPECT(","); EXPECT_KEY("expected"); - CHECK_RESULT(ParseConstVector(&command->expected)); + CHECK_RESULT(ParseExpectedValues(&command->expected)); *out_command = std::move(command); } else if (Match("\"assert_return_func\"")) { auto command = MakeUnique<AssertReturnFuncCommand>(); @@ -768,24 +823,6 @@ wabt::Result JSONParser::ParseCommand(CommandPtr* out_command) { EXPECT(","); CHECK_RESULT(ParseAction(&command->action)); *out_command = std::move(command); - } else if (Match("\"assert_return_canonical_nan\"")) { - auto command = MakeUnique<AssertReturnCanonicalNanCommand>(); - EXPECT(","); - CHECK_RESULT(ParseLine(&command->line)); - EXPECT(","); - CHECK_RESULT(ParseAction(&command->action)); - EXPECT(","); - CHECK_RESULT(ParseActionResult()); - *out_command = std::move(command); - } else if (Match("\"assert_return_arithmetic_nan\"")) { - auto command = MakeUnique<AssertReturnArithmeticNanCommand>(); - EXPECT(","); - CHECK_RESULT(ParseLine(&command->line)); - EXPECT(","); - CHECK_RESULT(ParseAction(&command->action)); - EXPECT(","); - CHECK_RESULT(ParseActionResult()); - *out_command = std::move(command); } else if (Match("\"assert_trap\"")) { auto command = MakeUnique<AssertTrapCommand>(); EXPECT(","); @@ -862,8 +899,6 @@ class CommandRunner { const AssertUninstantiableCommand*); wabt::Result OnAssertReturnCommand(const AssertReturnCommand*); wabt::Result OnAssertReturnFuncCommand(const AssertReturnFuncCommand*); - template <typename NanCommand> - wabt::Result OnAssertReturnNanCommand(const NanCommand*); wabt::Result OnAssertTrapCommand(const AssertTrapCommand*); wabt::Result OnAssertExhaustionCommand(const AssertExhaustionCommand*); @@ -974,16 +1009,6 @@ wabt::Result CommandRunner::Run(const Script& script) { OnAssertReturnFuncCommand(cast<AssertReturnFuncCommand>(command.get()))); break; - case CommandType::AssertReturnCanonicalNan: - TallyCommand(OnAssertReturnNanCommand( - cast<AssertReturnCanonicalNanCommand>(command.get()))); - break; - - case CommandType::AssertReturnArithmeticNan: - TallyCommand(OnAssertReturnNanCommand( - cast<AssertReturnArithmeticNanCommand>(command.get()))); - break; - case CommandType::AssertTrap: TallyCommand( OnAssertTrapCommand(cast<AssertTrapCommand>(command.get()))); @@ -1364,73 +1389,43 @@ wabt::Result CommandRunner::OnAssertReturnCommand( wabt::Result result = wabt::Result::Ok; for (size_t i = 0; i < exec_result.values.size(); ++i) { - const TypedValue& expected_tv = command->expected[i]; - const TypedValue& actual_tv = exec_result.values[i]; - if (!TypedValuesAreEqual(expected_tv, actual_tv)) { - PrintError(command->line, - "mismatch in result %" PRIzd - " of assert_return: expected %s, got %s", - i, TypedValueToString(expected_tv).c_str(), - TypedValueToString(actual_tv).c_str()); - result = wabt::Result::Error; - } - } - - return result; -} - -template <typename NanCommand> -wabt::Result CommandRunner::OnAssertReturnNanCommand( - const NanCommand* command) { - ExecResult exec_result = - RunAction(command->line, &command->action, RunVerbosity::Quiet); - - if (!exec_result.ok()) { - PrintError(command->line, "unexpected trap: %s", - ResultToString(exec_result.result).c_str()); - return wabt::Result::Error; - } - - if (exec_result.values.size() != 1) { - PrintError(command->line, "expected one result, got %" PRIzd, - exec_result.values.size()); - return wabt::Result::Error; - } - - const bool is_canonical = - command->type == CommandType::AssertReturnCanonicalNan; - - const TypedValue& actual = exec_result.values[0]; - switch (actual.type) { - case Type::F32: { - bool is_nan = is_canonical ? IsCanonicalNan(actual.value.f32_bits) - : IsArithmeticNan(actual.value.f32_bits); + const ExpectedValue& expected = command->expected[i]; + const TypedValue& actual = exec_result.values[i]; + if (expected.is_expected_nan) { + bool is_nan; + if (expected.expectedNan == ExpectedNan::Arithmetic) { + if (expected.value.type == Type::F64) { + is_nan = IsArithmeticNan(actual.value.f64_bits); + } else { + is_nan = IsArithmeticNan(actual.value.f32_bits); + } + } else if (expected.expectedNan == ExpectedNan::Canonical) { + if (expected.value.type == Type::F64) { + is_nan = IsCanonicalNan(actual.value.f64_bits); + } else { + is_nan = IsCanonicalNan(actual.value.f32_bits); + } + } else { + WABT_UNREACHABLE; + } if (!is_nan) { PrintError(command->line, "expected result to be nan, got %s", TypedValueToString(actual).c_str()); - return wabt::Result::Error; + result = wabt::Result::Error; } - break; - } - - case Type::F64: { - bool is_nan = is_canonical ? IsCanonicalNan(actual.value.f64_bits) - : IsArithmeticNan(actual.value.f64_bits); - if (!is_nan) { - PrintError(command->line, "expected result to be nan, got %s", + } else { + if (!TypedValuesAreEqual(expected.value, actual)) { + PrintError(command->line, + "mismatch in result %" PRIzd + " of assert_return: expected %s, got %s", + i, TypedValueToString(expected.value).c_str(), TypedValueToString(actual).c_str()); - return wabt::Result::Error; + result = wabt::Result::Error; } - break; } - - default: - PrintError(command->line, "expected result type to be f32 or f64, got %s", - GetTypeName(actual.type)); - return wabt::Result::Error; } - return wabt::Result::Ok; + return result; } wabt::Result CommandRunner::OnAssertTrapCommand( |