summaryrefslogtreecommitdiff
path: root/deps/v8/test/unittests/wasm/wasm-text-unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/test/unittests/wasm/wasm-text-unittest.cc')
-rw-r--r--deps/v8/test/unittests/wasm/wasm-text-unittest.cc121
1 files changed, 121 insertions, 0 deletions
diff --git a/deps/v8/test/unittests/wasm/wasm-text-unittest.cc b/deps/v8/test/unittests/wasm/wasm-text-unittest.cc
new file mode 100644
index 0000000000..e960b730a5
--- /dev/null
+++ b/deps/v8/test/unittests/wasm/wasm-text-unittest.cc
@@ -0,0 +1,121 @@
+// Copyright 2019 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <sstream>
+
+#include "test/unittests/test-utils.h"
+
+#include "src/wasm/module-decoder.h"
+#include "src/wasm/wasm-module-builder.h"
+#include "src/wasm/wasm-module.h"
+#include "src/wasm/wasm-opcodes.h"
+#include "src/wasm/wasm-text.h"
+#include "test/common/wasm/test-signatures.h"
+
+namespace v8 {
+namespace internal {
+namespace wasm {
+
+class WasmTextTest : public TestWithIsolateAndZone {
+ public:
+ TestSignatures sigs;
+ WasmFeatures enabled_features_;
+
+ void TestInstruction(const byte* func_start, size_t func_size) {
+ WasmModuleBuilder mb(zone());
+ auto* fb = mb.AddFunction(sigs.v_v());
+ fb->EmitCode(func_start, static_cast<uint32_t>(func_size));
+ fb->Emit(kExprEnd);
+
+ ZoneBuffer buffer(zone());
+ mb.WriteTo(&buffer);
+
+ ModuleWireBytes wire_bytes(
+ Vector<const byte>(buffer.begin(), buffer.size()));
+
+ ModuleResult result = DecodeWasmModule(
+ enabled_features_, buffer.begin(), buffer.end(), false, kWasmOrigin,
+ isolate()->counters(), isolate()->wasm_engine()->allocator());
+ EXPECT_TRUE(result.ok());
+
+ std::stringstream ss;
+ PrintWasmText(result.value().get(), wire_bytes, 0, ss, nullptr);
+ }
+};
+
+TEST_F(WasmTextTest, EveryOpcodeCanBeDecoded) {
+ static const struct {
+ WasmOpcode opcode;
+ const char* debug_name;
+ } kValues[] = {
+#define DECLARE_ELEMENT(name, opcode, sig) {kExpr##name, "kExpr" #name},
+ FOREACH_OPCODE(DECLARE_ELEMENT)};
+#undef DECLARE_ELEMENT
+
+ for (const auto& value : kValues) {
+ // Pad with 0 for any immediate values. If they're not needed, they'll be
+ // interpreted as unreachable.
+ byte data[20] = {0};
+
+ printf("%s\n", value.debug_name);
+ switch (value.opcode) {
+ // Instructions that have a special case because they affect the control
+ // depth.
+ case kExprBlock:
+ case kExprLoop:
+ case kExprIf:
+ case kExprTry:
+ data[0] = value.opcode;
+ data[1] = kLocalVoid;
+ data[2] = kExprEnd;
+ break;
+ case kExprElse:
+ data[0] = kExprIf;
+ data[1] = value.opcode;
+ data[2] = kExprEnd;
+ break;
+ case kExprCatch:
+ data[0] = kExprTry;
+ data[1] = value.opcode;
+ data[2] = kExprEnd;
+ break;
+ case kExprEnd:
+ break;
+
+ // Instructions with special requirements for immediates.
+ case kExprSelectWithType:
+ data[0] = kExprSelectWithType;
+ data[1] = 1;
+ data[2] = kLocalI32;
+ break;
+
+ default: {
+ if (value.opcode >= 0x100) {
+ data[0] = value.opcode >> 8; // Prefix byte.
+ byte opcode = value.opcode & 0xff; // Actual opcode.
+ if (opcode >= 0x80) {
+ // Opcode with prefix, and needs to be LEB encoded (3 bytes).
+ // For now, this can only be in the range [0x80, 0xff], which means
+ // that the third byte is always 1.
+ data[1] = (opcode & 0x7f) | 0x80;
+ data[2] = 1;
+ } else {
+ // Opcode with prefix (2 bytes).
+ data[1] = opcode;
+ }
+ } else {
+ // Single-byte opcode.
+ data[0] = value.opcode;
+ }
+ break;
+ }
+ }
+
+ TestInstruction(data, arraysize(data));
+ }
+}
+
+} // namespace wasm
+} // namespace internal
+} // namespace v8