summaryrefslogtreecommitdiff
path: root/include/wabt/interp/istream.h
diff options
context:
space:
mode:
authorAlex Reinking <reinking@google.com>2022-09-28 07:24:49 -0700
committerGitHub <noreply@github.com>2022-09-28 07:24:49 -0700
commita4a77c18df16d6ee672f2a2564969bc9b2beef3a (patch)
treee4368558b4b44a7421761341e3b18edbd93f9785 /include/wabt/interp/istream.h
parent520614a5f83878a4d26702a3ad67c44302c2b073 (diff)
downloadwabt-a4a77c18df16d6ee672f2a2564969bc9b2beef3a.tar.gz
wabt-a4a77c18df16d6ee672f2a2564969bc9b2beef3a.tar.bz2
wabt-a4a77c18df16d6ee672f2a2564969bc9b2beef3a.zip
Move headers to include/wabt/ (#1998)
This makes things easier for users and packagers of libwabt.
Diffstat (limited to 'include/wabt/interp/istream.h')
-rw-r--r--include/wabt/interp/istream.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/include/wabt/interp/istream.h b/include/wabt/interp/istream.h
new file mode 100644
index 00000000..06e1cfca
--- /dev/null
+++ b/include/wabt/interp/istream.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2020 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef WABT_INTERP_ISTREAM_H_
+#define WABT_INTERP_ISTREAM_H_
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "wabt/common.h"
+#include "wabt/opcode.h"
+#include "wabt/stream.h"
+
+namespace wabt {
+namespace interp {
+
+using u8 = uint8_t;
+using u16 = uint16_t;
+using u32 = uint32_t;
+using u64 = uint64_t;
+using f32 = float;
+using f64 = double;
+
+using Buffer = std::vector<u8>;
+
+using ValueType = wabt::Type;
+
+// Group instructions based on their immediates their operands. This way we can
+// simplify instruction decoding, disassembling, and tracing. There is an
+// example of an instruction that uses this encoding on the right.
+enum class InstrKind {
+ Imm_0_Op_0, // Nop
+ Imm_0_Op_1, // i32.eqz
+ Imm_0_Op_2, // i32.add
+ Imm_0_Op_3, // select
+ Imm_Jump_Op_0, // br
+ Imm_Jump_Op_1, // br_if
+ Imm_Index_Op_0, // global.get
+ Imm_Index_Op_1, // global.set
+ Imm_Index_Op_2, // table.set
+ Imm_Index_Op_3, // memory.fill
+ Imm_Index_Op_N, // call
+ Imm_Index_Index_Op_3, // memory.init
+ Imm_Index_Index_Op_N, // call_indirect
+ Imm_Index_Offset_Op_1, // i32.load
+ Imm_Index_Offset_Op_2, // i32.store
+ Imm_Index_Offset_Op_3, // i32.atomic.rmw.cmpxchg
+ Imm_Index_Offset_Lane_Op_2, // v128.load8_lane
+ Imm_I32_Op_0, // i32.const
+ Imm_I64_Op_0, // i64.const
+ Imm_F32_Op_0, // f32.const
+ Imm_F64_Op_0, // f64.const
+ Imm_I32_I32_Op_0, // drop_keep
+ Imm_I8_Op_1, // i32x4.extract_lane
+ Imm_I8_Op_2, // i32x4.replace_lane
+ Imm_V128_Op_0, // v128.const
+ Imm_V128_Op_2, // i8x16.shuffle
+};
+
+struct Instr {
+ Opcode op;
+ InstrKind kind;
+ union {
+ u8 imm_u8;
+ u32 imm_u32;
+ f32 imm_f32;
+ u64 imm_u64;
+ f64 imm_f64;
+ v128 imm_v128;
+ struct {
+ u32 fst, snd;
+ } imm_u32x2;
+ struct {
+ u32 fst, snd;
+ u8 idx;
+ } imm_u32x2_u8;
+ };
+};
+
+class Istream {
+ public:
+ using SerializedOpcode = u32; // TODO: change to u16
+ using Offset = u32;
+ static const Offset kInvalidOffset = ~0;
+ // Each br_table entry is made up of three instructions:
+ //
+ // interp_drop_keep $drop $keep
+ // interp_catch_drop $catches
+ // br $label
+ //
+ // Each opcode is a SerializedOpcode, and each immediate is a u32.
+ static const Offset kBrTableEntrySize =
+ sizeof(SerializedOpcode) * 3 + 4 * sizeof(u32);
+
+ // Emit API.
+ void Emit(u32);
+ void Emit(Opcode::Enum);
+ void Emit(Opcode::Enum, u8);
+ void Emit(Opcode::Enum, u32);
+ void Emit(Opcode::Enum, u64);
+ void Emit(Opcode::Enum, v128);
+ void Emit(Opcode::Enum, u32, u32);
+ void Emit(Opcode::Enum, u32, u32, u8);
+ void EmitDropKeep(u32 drop, u32 keep);
+ void EmitCatchDrop(u32 drop);
+
+ Offset EmitFixupU32();
+ void ResolveFixupU32(Offset);
+
+ Offset end() const;
+
+ // Read API.
+ Instr Read(Offset*) const;
+
+ // Disassemble/Trace API.
+ // TODO separate out disassembly/tracing?
+ struct TraceSource {
+ virtual ~TraceSource() {}
+ // Whatever content should go before the instruction on each line, e.g. the
+ // call stack size, value stack size, and istream offset.
+ virtual std::string Header(Offset) = 0;
+ virtual std::string Pick(Index, Instr) = 0;
+ };
+
+ struct DisassemblySource : TraceSource {
+ std::string Header(Offset) override;
+ std::string Pick(Index, Instr) override;
+ };
+
+ void Disassemble(Stream*) const;
+ Offset Disassemble(Stream*, Offset) const;
+ void Disassemble(Stream*, Offset from, Offset to) const;
+
+ Offset Trace(Stream*, Offset, TraceSource*) const;
+
+ private:
+ template <typename T>
+ void WABT_VECTORCALL EmitAt(Offset, T val);
+ template <typename T>
+ void WABT_VECTORCALL EmitInternal(T val);
+
+ template <typename T>
+ T WABT_VECTORCALL ReadAt(Offset*) const;
+
+ Buffer data_;
+};
+
+} // namespace interp
+} // namespace wabt
+
+#endif // WABT_INTERP_ISTREAM_H_