summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ast.h1
-rw-r--r--src/binary-reader.h1
-rw-r--r--src/binary-writer.h1
-rw-r--r--src/common.cc32
-rw-r--r--src/common.h247
-rw-r--r--src/interpreter-opcode.def38
-rw-r--r--src/interpreter.cc24
-rw-r--r--src/interpreter.h15
-rw-r--r--src/opcode.cc41
-rw-r--r--src/opcode.def224
-rw-r--r--src/opcode.h81
-rw-r--r--src/type-checker.h1
12 files changed, 400 insertions, 306 deletions
diff --git a/src/ast.h b/src/ast.h
index 346f2257..4359a982 100644
--- a/src/ast.h
+++ b/src/ast.h
@@ -27,6 +27,7 @@
#include "binding-hash.h"
#include "common.h"
+#include "opcode.h"
namespace wabt {
diff --git a/src/binary-reader.h b/src/binary-reader.h
index e8e5c45f..d52e4dfd 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -22,6 +22,7 @@
#include "binary.h"
#include "common.h"
+#include "opcode.h"
#define WABT_READ_BINARY_OPTIONS_DEFAULT \
{ nullptr, false }
diff --git a/src/binary-writer.h b/src/binary-writer.h
index 0b131b7f..e42503a4 100644
--- a/src/binary-writer.h
+++ b/src/binary-writer.h
@@ -18,6 +18,7 @@
#define WABT_BINARY_WRITER_H_
#include "common.h"
+#include "opcode.h"
#include "stream.h"
namespace wabt {
diff --git a/src/common.cc b/src/common.cc
index 72198f8c..c27fc15c 100644
--- a/src/common.cc
+++ b/src/common.cc
@@ -34,27 +34,6 @@ namespace wabt {
Reloc::Reloc(RelocType type, size_t offset, uint32_t index, int32_t addend)
: type(type), offset(offset), index(index), addend(addend) {}
-OpcodeInfo g_opcode_info[kOpcodeCount];
-
-/* TODO(binji): It's annoying to have to have an initializer function, but it
- * seems to be necessary as g++ doesn't allow non-trival designated
- * initializers (e.g. [314] = "blah") */
-void init_opcode_info(void) {
- static bool s_initialized = false;
- if (!s_initialized) {
-#define V(rtype, type1, type2, mem_size, code, NAME, text) \
- g_opcode_info[code].name = text; \
- g_opcode_info[code].result_type = Type::rtype; \
- g_opcode_info[code].param1_type = Type::type1; \
- g_opcode_info[code].param2_type = Type::type2; \
- g_opcode_info[code].memory_size = mem_size;
-
- WABT_FOREACH_OPCODE(V)
-
-#undef V
- }
-}
-
const char* g_kind_name[] = {"func", "table", "memory", "global"};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_kind_name) == kExternalKindCount);
@@ -69,17 +48,6 @@ const char* g_reloc_type_name[] = {"R_FUNC_INDEX_LEB",
};
WABT_STATIC_ASSERT(WABT_ARRAY_SIZE(g_reloc_type_name) == kRelocTypeCount);
-bool is_naturally_aligned(Opcode opcode, uint32_t alignment) {
- uint32_t opcode_align = get_opcode_memory_size(opcode);
- return alignment == WABT_USE_NATURAL_ALIGNMENT || alignment == opcode_align;
-}
-
-uint32_t get_opcode_alignment(Opcode opcode, uint32_t alignment) {
- if (alignment == WABT_USE_NATURAL_ALIGNMENT)
- return get_opcode_memory_size(opcode);
- return alignment;
-}
-
StringSlice empty_string_slice(void) {
StringSlice result;
result.start = "";
diff --git a/src/common.h b/src/common.h
index b7153046..0b909b88 100644
--- a/src/common.h
+++ b/src/common.h
@@ -130,7 +130,7 @@ enum class Type {
Anyfunc = -0x10,
Func = -0x20,
Void = -0x40,
- ___ = Void, /* convenient for the opcode table below */
+ ___ = Void, /* convenient for the opcode table in opcode.h */
Any = 0, /* Not actually specified, but useful for type-checking */
};
typedef std::vector<Type> TypeVector;
@@ -179,209 +179,6 @@ struct Limits {
enum { WABT_USE_NATURAL_ALIGNMENT = 0xFFFFFFFF };
-/*
- * tr: result type
- * t1: type of the 1st parameter
- * t2: type of the 2nd parameter
- * m: memory size of the operation, if any
- * code: opcode
- * NAME: used to generate the opcode enum
- * text: a string of the opcode name in the AST format
- *
- * tr t1 t2 m code NAME text
- * ============================ */
-#define WABT_FOREACH_OPCODE(V) \
- V(___, ___, ___, 0, 0x00, Unreachable, "unreachable") \
- V(___, ___, ___, 0, 0x01, Nop, "nop") \
- V(___, ___, ___, 0, 0x02, Block, "block") \
- V(___, ___, ___, 0, 0x03, Loop, "loop") \
- V(___, ___, ___, 0, 0x04, If, "if") \
- V(___, ___, ___, 0, 0x05, Else, "else") \
- V(___, ___, ___, 0, 0x0b, End, "end") \
- V(___, ___, ___, 0, 0x0c, Br, "br") \
- V(___, ___, ___, 0, 0x0d, BrIf, "br_if") \
- V(___, ___, ___, 0, 0x0e, BrTable, "br_table") \
- V(___, ___, ___, 0, 0x0f, Return, "return") \
- V(___, ___, ___, 0, 0x10, Call, "call") \
- V(___, ___, ___, 0, 0x11, CallIndirect, "call_indirect") \
- V(___, ___, ___, 0, 0x1a, Drop, "drop") \
- V(___, ___, ___, 0, 0x1b, Select, "select") \
- V(___, ___, ___, 0, 0x20, GetLocal, "get_local") \
- V(___, ___, ___, 0, 0x21, SetLocal, "set_local") \
- V(___, ___, ___, 0, 0x22, TeeLocal, "tee_local") \
- V(___, ___, ___, 0, 0x23, GetGlobal, "get_global") \
- V(___, ___, ___, 0, 0x24, SetGlobal, "set_global") \
- V(I32, I32, ___, 4, 0x28, I32Load, "i32.load") \
- V(I64, I32, ___, 8, 0x29, I64Load, "i64.load") \
- V(F32, I32, ___, 4, 0x2a, F32Load, "f32.load") \
- V(F64, I32, ___, 8, 0x2b, F64Load, "f64.load") \
- V(I32, I32, ___, 1, 0x2c, I32Load8S, "i32.load8_s") \
- V(I32, I32, ___, 1, 0x2d, I32Load8U, "i32.load8_u") \
- V(I32, I32, ___, 2, 0x2e, I32Load16S, "i32.load16_s") \
- V(I32, I32, ___, 2, 0x2f, I32Load16U, "i32.load16_u") \
- V(I64, I32, ___, 1, 0x30, I64Load8S, "i64.load8_s") \
- V(I64, I32, ___, 1, 0x31, I64Load8U, "i64.load8_u") \
- V(I64, I32, ___, 2, 0x32, I64Load16S, "i64.load16_s") \
- V(I64, I32, ___, 2, 0x33, I64Load16U, "i64.load16_u") \
- V(I64, I32, ___, 4, 0x34, I64Load32S, "i64.load32_s") \
- V(I64, I32, ___, 4, 0x35, I64Load32U, "i64.load32_u") \
- V(___, I32, I32, 4, 0x36, I32Store, "i32.store") \
- V(___, I32, I64, 8, 0x37, I64Store, "i64.store") \
- V(___, I32, F32, 4, 0x38, F32Store, "f32.store") \
- V(___, I32, F64, 8, 0x39, F64Store, "f64.store") \
- V(___, I32, I32, 1, 0x3a, I32Store8, "i32.store8") \
- V(___, I32, I32, 2, 0x3b, I32Store16, "i32.store16") \
- V(___, I32, I64, 1, 0x3c, I64Store8, "i64.store8") \
- V(___, I32, I64, 2, 0x3d, I64Store16, "i64.store16") \
- V(___, I32, I64, 4, 0x3e, I64Store32, "i64.store32") \
- V(I32, ___, ___, 0, 0x3f, CurrentMemory, "current_memory") \
- V(I32, I32, ___, 0, 0x40, GrowMemory, "grow_memory") \
- V(I32, ___, ___, 0, 0x41, I32Const, "i32.const") \
- V(I64, ___, ___, 0, 0x42, I64Const, "i64.const") \
- V(F32, ___, ___, 0, 0x43, F32Const, "f32.const") \
- V(F64, ___, ___, 0, 0x44, F64Const, "f64.const") \
- V(I32, I32, ___, 0, 0x45, I32Eqz, "i32.eqz") \
- V(I32, I32, I32, 0, 0x46, I32Eq, "i32.eq") \
- V(I32, I32, I32, 0, 0x47, I32Ne, "i32.ne") \
- V(I32, I32, I32, 0, 0x48, I32LtS, "i32.lt_s") \
- V(I32, I32, I32, 0, 0x49, I32LtU, "i32.lt_u") \
- V(I32, I32, I32, 0, 0x4a, I32GtS, "i32.gt_s") \
- V(I32, I32, I32, 0, 0x4b, I32GtU, "i32.gt_u") \
- V(I32, I32, I32, 0, 0x4c, I32LeS, "i32.le_s") \
- V(I32, I32, I32, 0, 0x4d, I32LeU, "i32.le_u") \
- V(I32, I32, I32, 0, 0x4e, I32GeS, "i32.ge_s") \
- V(I32, I32, I32, 0, 0x4f, I32GeU, "i32.ge_u") \
- V(I32, I64, ___, 0, 0x50, I64Eqz, "i64.eqz") \
- V(I32, I64, I64, 0, 0x51, I64Eq, "i64.eq") \
- V(I32, I64, I64, 0, 0x52, I64Ne, "i64.ne") \
- V(I32, I64, I64, 0, 0x53, I64LtS, "i64.lt_s") \
- V(I32, I64, I64, 0, 0x54, I64LtU, "i64.lt_u") \
- V(I32, I64, I64, 0, 0x55, I64GtS, "i64.gt_s") \
- V(I32, I64, I64, 0, 0x56, I64GtU, "i64.gt_u") \
- V(I32, I64, I64, 0, 0x57, I64LeS, "i64.le_s") \
- V(I32, I64, I64, 0, 0x58, I64LeU, "i64.le_u") \
- V(I32, I64, I64, 0, 0x59, I64GeS, "i64.ge_s") \
- V(I32, I64, I64, 0, 0x5a, I64GeU, "i64.ge_u") \
- V(I32, F32, F32, 0, 0x5b, F32Eq, "f32.eq") \
- V(I32, F32, F32, 0, 0x5c, F32Ne, "f32.ne") \
- V(I32, F32, F32, 0, 0x5d, F32Lt, "f32.lt") \
- V(I32, F32, F32, 0, 0x5e, F32Gt, "f32.gt") \
- V(I32, F32, F32, 0, 0x5f, F32Le, "f32.le") \
- V(I32, F32, F32, 0, 0x60, F32Ge, "f32.ge") \
- V(I32, F64, F64, 0, 0x61, F64Eq, "f64.eq") \
- V(I32, F64, F64, 0, 0x62, F64Ne, "f64.ne") \
- V(I32, F64, F64, 0, 0x63, F64Lt, "f64.lt") \
- V(I32, F64, F64, 0, 0x64, F64Gt, "f64.gt") \
- V(I32, F64, F64, 0, 0x65, F64Le, "f64.le") \
- V(I32, F64, F64, 0, 0x66, F64Ge, "f64.ge") \
- V(I32, I32, ___, 0, 0x67, I32Clz, "i32.clz") \
- V(I32, I32, ___, 0, 0x68, I32Ctz, "i32.ctz") \
- V(I32, I32, ___, 0, 0x69, I32Popcnt, "i32.popcnt") \
- V(I32, I32, I32, 0, 0x6a, I32Add, "i32.add") \
- V(I32, I32, I32, 0, 0x6b, I32Sub, "i32.sub") \
- V(I32, I32, I32, 0, 0x6c, I32Mul, "i32.mul") \
- V(I32, I32, I32, 0, 0x6d, I32DivS, "i32.div_s") \
- V(I32, I32, I32, 0, 0x6e, I32DivU, "i32.div_u") \
- V(I32, I32, I32, 0, 0x6f, I32RemS, "i32.rem_s") \
- V(I32, I32, I32, 0, 0x70, I32RemU, "i32.rem_u") \
- V(I32, I32, I32, 0, 0x71, I32And, "i32.and") \
- V(I32, I32, I32, 0, 0x72, I32Or, "i32.or") \
- V(I32, I32, I32, 0, 0x73, I32Xor, "i32.xor") \
- V(I32, I32, I32, 0, 0x74, I32Shl, "i32.shl") \
- V(I32, I32, I32, 0, 0x75, I32ShrS, "i32.shr_s") \
- V(I32, I32, I32, 0, 0x76, I32ShrU, "i32.shr_u") \
- V(I32, I32, I32, 0, 0x77, I32Rotl, "i32.rotl") \
- V(I32, I32, I32, 0, 0x78, I32Rotr, "i32.rotr") \
- V(I64, I64, ___, 0, 0x79, I64Clz, "i64.clz") \
- V(I64, I64, ___, 0, 0x7a, I64Ctz, "i64.ctz") \
- V(I64, I64, ___, 0, 0x7b, I64Popcnt, "i64.popcnt") \
- V(I64, I64, I64, 0, 0x7c, I64Add, "i64.add") \
- V(I64, I64, I64, 0, 0x7d, I64Sub, "i64.sub") \
- V(I64, I64, I64, 0, 0x7e, I64Mul, "i64.mul") \
- V(I64, I64, I64, 0, 0x7f, I64DivS, "i64.div_s") \
- V(I64, I64, I64, 0, 0x80, I64DivU, "i64.div_u") \
- V(I64, I64, I64, 0, 0x81, I64RemS, "i64.rem_s") \
- V(I64, I64, I64, 0, 0x82, I64RemU, "i64.rem_u") \
- V(I64, I64, I64, 0, 0x83, I64And, "i64.and") \
- V(I64, I64, I64, 0, 0x84, I64Or, "i64.or") \
- V(I64, I64, I64, 0, 0x85, I64Xor, "i64.xor") \
- V(I64, I64, I64, 0, 0x86, I64Shl, "i64.shl") \
- V(I64, I64, I64, 0, 0x87, I64ShrS, "i64.shr_s") \
- V(I64, I64, I64, 0, 0x88, I64ShrU, "i64.shr_u") \
- V(I64, I64, I64, 0, 0x89, I64Rotl, "i64.rotl") \
- V(I64, I64, I64, 0, 0x8a, I64Rotr, "i64.rotr") \
- V(F32, F32, F32, 0, 0x8b, F32Abs, "f32.abs") \
- V(F32, F32, F32, 0, 0x8c, F32Neg, "f32.neg") \
- V(F32, F32, F32, 0, 0x8d, F32Ceil, "f32.ceil") \
- V(F32, F32, F32, 0, 0x8e, F32Floor, "f32.floor") \
- V(F32, F32, F32, 0, 0x8f, F32Trunc, "f32.trunc") \
- V(F32, F32, F32, 0, 0x90, F32Nearest, "f32.nearest") \
- V(F32, F32, F32, 0, 0x91, F32Sqrt, "f32.sqrt") \
- V(F32, F32, F32, 0, 0x92, F32Add, "f32.add") \
- V(F32, F32, F32, 0, 0x93, F32Sub, "f32.sub") \
- V(F32, F32, F32, 0, 0x94, F32Mul, "f32.mul") \
- V(F32, F32, F32, 0, 0x95, F32Div, "f32.div") \
- V(F32, F32, F32, 0, 0x96, F32Min, "f32.min") \
- V(F32, F32, F32, 0, 0x97, F32Max, "f32.max") \
- V(F32, F32, F32, 0, 0x98, F32Copysign, "f32.copysign") \
- V(F64, F64, F64, 0, 0x99, F64Abs, "f64.abs") \
- V(F64, F64, F64, 0, 0x9a, F64Neg, "f64.neg") \
- V(F64, F64, F64, 0, 0x9b, F64Ceil, "f64.ceil") \
- V(F64, F64, F64, 0, 0x9c, F64Floor, "f64.floor") \
- V(F64, F64, F64, 0, 0x9d, F64Trunc, "f64.trunc") \
- V(F64, F64, F64, 0, 0x9e, F64Nearest, "f64.nearest") \
- V(F64, F64, F64, 0, 0x9f, F64Sqrt, "f64.sqrt") \
- V(F64, F64, F64, 0, 0xa0, F64Add, "f64.add") \
- V(F64, F64, F64, 0, 0xa1, F64Sub, "f64.sub") \
- V(F64, F64, F64, 0, 0xa2, F64Mul, "f64.mul") \
- V(F64, F64, F64, 0, 0xa3, F64Div, "f64.div") \
- V(F64, F64, F64, 0, 0xa4, F64Min, "f64.min") \
- V(F64, F64, F64, 0, 0xa5, F64Max, "f64.max") \
- V(F64, F64, F64, 0, 0xa6, F64Copysign, "f64.copysign") \
- V(I32, I64, ___, 0, 0xa7, I32WrapI64, "i32.wrap/i64") \
- V(I32, F32, ___, 0, 0xa8, I32TruncSF32, "i32.trunc_s/f32") \
- V(I32, F32, ___, 0, 0xa9, I32TruncUF32, "i32.trunc_u/f32") \
- V(I32, F64, ___, 0, 0xaa, I32TruncSF64, "i32.trunc_s/f64") \
- V(I32, F64, ___, 0, 0xab, I32TruncUF64, "i32.trunc_u/f64") \
- V(I64, I32, ___, 0, 0xac, I64ExtendSI32, "i64.extend_s/i32") \
- V(I64, I32, ___, 0, 0xad, I64ExtendUI32, "i64.extend_u/i32") \
- V(I64, F32, ___, 0, 0xae, I64TruncSF32, "i64.trunc_s/f32") \
- V(I64, F32, ___, 0, 0xaf, I64TruncUF32, "i64.trunc_u/f32") \
- V(I64, F64, ___, 0, 0xb0, I64TruncSF64, "i64.trunc_s/f64") \
- V(I64, F64, ___, 0, 0xb1, I64TruncUF64, "i64.trunc_u/f64") \
- V(F32, I32, ___, 0, 0xb2, F32ConvertSI32, "f32.convert_s/i32") \
- V(F32, I32, ___, 0, 0xb3, F32ConvertUI32, "f32.convert_u/i32") \
- V(F32, I64, ___, 0, 0xb4, F32ConvertSI64, "f32.convert_s/i64") \
- V(F32, I64, ___, 0, 0xb5, F32ConvertUI64, "f32.convert_u/i64") \
- V(F32, F64, ___, 0, 0xb6, F32DemoteF64, "f32.demote/f64") \
- V(F64, I32, ___, 0, 0xb7, F64ConvertSI32, "f64.convert_s/i32") \
- V(F64, I32, ___, 0, 0xb8, F64ConvertUI32, "f64.convert_u/i32") \
- V(F64, I64, ___, 0, 0xb9, F64ConvertSI64, "f64.convert_s/i64") \
- V(F64, I64, ___, 0, 0xba, F64ConvertUI64, "f64.convert_u/i64") \
- V(F64, F32, ___, 0, 0xbb, F64PromoteF32, "f64.promote/f32") \
- V(I32, F32, ___, 0, 0xbc, I32ReinterpretF32, "i32.reinterpret/f32") \
- V(I64, F64, ___, 0, 0xbd, I64ReinterpretF64, "i64.reinterpret/f64") \
- V(F32, I32, ___, 0, 0xbe, F32ReinterpretI32, "f32.reinterpret/i32") \
- V(F64, I64, ___, 0, 0xbf, F64ReinterpretI64, "f64.reinterpret/i64")
-
-enum class Opcode {
-#define V(rtype, type1, type2, mem_size, code, Name, text) Name = code,
- WABT_FOREACH_OPCODE(V)
-#undef V
-
- First = Unreachable,
- Last = F64ReinterpretI64,
-};
-static const int kOpcodeCount = WABT_ENUM_COUNT(Opcode);
-
-struct OpcodeInfo {
- const char* name;
- Type result_type;
- Type param1_type;
- Type param2_type;
- int memory_size;
-};
-
enum class LiteralType {
Int,
Float,
@@ -421,14 +218,6 @@ static WABT_INLINE StringSlice dup_string_slice(StringSlice str) {
return result;
}
-/* return 1 if |alignment| matches the alignment of |opcode|, or if |alignment|
- * is WABT_USE_NATURAL_ALIGNMENT */
-bool is_naturally_aligned(Opcode opcode, uint32_t alignment);
-
-/* if |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of
- * |opcode|, else return |alignment| */
-uint32_t get_opcode_alignment(Opcode opcode, uint32_t alignment);
-
StringSlice empty_string_slice(void);
bool string_slice_eq_cstr(const StringSlice* s1, const char* s2);
bool string_slice_startswith(const StringSlice* s1, const char* s2);
@@ -462,40 +251,6 @@ bool default_binary_error_callback(uint32_t offset,
void init_stdio();
-/* opcode info */
-extern OpcodeInfo g_opcode_info[];
-void init_opcode_info(void);
-
-static WABT_INLINE const char* get_opcode_name(Opcode opcode) {
- assert(static_cast<int>(opcode) < kOpcodeCount);
- init_opcode_info();
- return g_opcode_info[static_cast<size_t>(opcode)].name;
-}
-
-static WABT_INLINE Type get_opcode_result_type(Opcode opcode) {
- assert(static_cast<int>(opcode) < kOpcodeCount);
- init_opcode_info();
- return g_opcode_info[static_cast<size_t>(opcode)].result_type;
-}
-
-static WABT_INLINE Type get_opcode_param_type_1(Opcode opcode) {
- assert(static_cast<int>(opcode) < kOpcodeCount);
- init_opcode_info();
- return g_opcode_info[static_cast<size_t>(opcode)].param1_type;
-}
-
-static WABT_INLINE Type get_opcode_param_type_2(Opcode opcode) {
- assert(static_cast<int>(opcode) < kOpcodeCount);
- init_opcode_info();
- return g_opcode_info[static_cast<size_t>(opcode)].param2_type;
-}
-
-static WABT_INLINE int get_opcode_memory_size(Opcode opcode) {
- assert(static_cast<int>(opcode) < kOpcodeCount);
- init_opcode_info();
- return g_opcode_info[static_cast<size_t>(opcode)].memory_size;
-}
-
/* external kind */
extern const char* g_kind_name[];
diff --git a/src/interpreter-opcode.def b/src/interpreter-opcode.def
new file mode 100644
index 00000000..6b16b9df
--- /dev/null
+++ b/src/interpreter-opcode.def
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2017 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_OPCODE
+#error "You must define WABT_OPCODE before including this file."
+#endif
+
+/*
+ * tr: result type
+ * t1: type of the 1st parameter
+ * t2: type of the 2nd parameter
+ * m: memory size of the operation, if any
+ * code: opcode
+ * Name: used to generate the opcode enum
+ * text: a string of the opcode name in the AST format
+ *
+ * tr t1 t2 m code Name text
+ * ============================================================ */
+
+#include "opcode.def"
+WABT_OPCODE(___, ___, ___, 0, 0xc0, Alloca, "alloca")
+WABT_OPCODE(___, ___, ___, 0, 0xc1, BrUnless, "br_unless")
+WABT_OPCODE(___, ___, ___, 0, 0xc2, CallHost, "call_host")
+WABT_OPCODE(___, ___, ___, 0, 0xc3, Data, "data")
+WABT_OPCODE(___, ___, ___, 0, 0xc4, DropKeep, "drop_keep")
diff --git a/src/interpreter.cc b/src/interpreter.cc
index ba56db94..dabf008f 100644
--- a/src/interpreter.cc
+++ b/src/interpreter.cc
@@ -27,7 +27,13 @@
namespace wabt {
-static const char* s_interpreter_opcode_name[256];
+static const char* s_interpreter_opcode_name[256] = {
+
+#define WABT_OPCODE(rtype, type1, type2, mem_size, code, NAME, text) text,
+#include "interpreter-opcode.def"
+#undef WABT_OPCODE
+
+};
#define CHECK_RESULT(expr) \
do { \
@@ -35,23 +41,7 @@ static const char* s_interpreter_opcode_name[256];
return Result::Error; \
} while (0)
-/* TODO(binji): It's annoying to have to have an initializer function, but it
- * seems to be necessary as g++ doesn't allow non-trival designated
- * initializers (e.g. [314] = "blah") */
-static void init_interpreter_opcode_table(void) {
- static bool s_initialized = false;
- if (!s_initialized) {
-#define V(rtype, type1, type2, mem_size, code, NAME, text) \
- s_interpreter_opcode_name[code] = text;
-
- WABT_FOREACH_INTERPRETER_OPCODE(V)
-
-#undef V
- }
-}
-
static const char* get_interpreter_opcode_name(InterpreterOpcode opcode) {
- init_interpreter_opcode_table();
return s_interpreter_opcode_name[static_cast<int>(opcode)];
}
diff --git a/src/interpreter.h b/src/interpreter.h
index 8f4143fe..37f0e2a1 100644
--- a/src/interpreter.h
+++ b/src/interpreter.h
@@ -24,6 +24,7 @@
#include "common.h"
#include "binding-hash.h"
+#include "opcode.h"
#include "writer.h"
namespace wabt {
@@ -80,19 +81,11 @@ enum class InterpreterResult {
#define WABT_TABLE_ENTRY_DROP_OFFSET sizeof(uint32_t)
#define WABT_TABLE_ENTRY_KEEP_OFFSET (sizeof(uint32_t) * 2)
-#define WABT_FOREACH_INTERPRETER_OPCODE(V) \
- WABT_FOREACH_OPCODE(V) \
- V(___, ___, ___, 0, 0xfb, Alloca, "alloca") \
- V(___, ___, ___, 0, 0xfc, BrUnless, "br_unless") \
- V(___, ___, ___, 0, 0xfd, CallHost, "call_host") \
- V(___, ___, ___, 0, 0xfe, Data, "data") \
- V(___, ___, ___, 0, 0xff, DropKeep, "drop_keep")
-
enum class InterpreterOpcode {
/* push space on the value stack for N entries */
-#define V(rtype, type1, type2, mem_size, code, Name, text) Name = code,
- WABT_FOREACH_INTERPRETER_OPCODE(V)
-#undef V
+#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) Name = code,
+#include "interpreter-opcode.def"
+#undef WABT_OPCODE
First = static_cast<int>(Opcode::First),
Last = DropKeep,
diff --git a/src/opcode.cc b/src/opcode.cc
new file mode 100644
index 00000000..3d2d9d14
--- /dev/null
+++ b/src/opcode.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2017 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.
+ */
+
+#include "opcode.h"
+
+namespace wabt {
+
+OpcodeInfo g_opcode_info[kOpcodeCount] = {
+
+#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) \
+ {text, Type::rtype, Type::type1, Type::type2, mem_size},
+#include "opcode.def"
+#undef WABT_OPCODE
+
+};
+
+bool is_naturally_aligned(Opcode opcode, uint32_t alignment) {
+ uint32_t opcode_align = get_opcode_memory_size(opcode);
+ return alignment == WABT_USE_NATURAL_ALIGNMENT || alignment == opcode_align;
+}
+
+uint32_t get_opcode_alignment(Opcode opcode, uint32_t alignment) {
+ if (alignment == WABT_USE_NATURAL_ALIGNMENT)
+ return get_opcode_memory_size(opcode);
+ return alignment;
+}
+
+} // namespace
diff --git a/src/opcode.def b/src/opcode.def
new file mode 100644
index 00000000..8207500d
--- /dev/null
+++ b/src/opcode.def
@@ -0,0 +1,224 @@
+/*
+ * Copyright 2017 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_OPCODE
+#error "You must define WABT_OPCODE before including this file."
+#endif
+
+/*
+ * tr: result type
+ * t1: type of the 1st parameter
+ * t2: type of the 2nd parameter
+ * m: memory size of the operation, if any
+ * code: opcode
+ * Name: used to generate the opcode enum
+ * text: a string of the opcode name in the AST format
+ *
+ * tr t1 t2 m code Name text
+ * ============================================================ */
+
+WABT_OPCODE(___, ___, ___, 0, 0x00, Unreachable, "unreachable")
+WABT_OPCODE(___, ___, ___, 0, 0x01, Nop, "nop")
+WABT_OPCODE(___, ___, ___, 0, 0x02, Block, "block")
+WABT_OPCODE(___, ___, ___, 0, 0x03, Loop, "loop")
+WABT_OPCODE(___, ___, ___, 0, 0x04, If, "if")
+WABT_OPCODE(___, ___, ___, 0, 0x05, Else, "else")
+WABT_OPCODE(___, ___, ___, 0, 0x06, Invalid_0x06, "<invalid:0x06>")
+WABT_OPCODE(___, ___, ___, 0, 0x07, Invalid_0x07, "<invalid:0x07>")
+WABT_OPCODE(___, ___, ___, 0, 0x08, Invalid_0x08, "<invalid:0x08>")
+WABT_OPCODE(___, ___, ___, 0, 0x09, Invalid_0x09, "<invalid:0x09>")
+WABT_OPCODE(___, ___, ___, 0, 0x0a, Invalid_0x0A, "<invalid:0x0a>")
+WABT_OPCODE(___, ___, ___, 0, 0x0b, End, "end")
+WABT_OPCODE(___, ___, ___, 0, 0x0c, Br, "br")
+WABT_OPCODE(___, ___, ___, 0, 0x0d, BrIf, "br_if")
+WABT_OPCODE(___, ___, ___, 0, 0x0e, BrTable, "br_table")
+WABT_OPCODE(___, ___, ___, 0, 0x0f, Return, "return")
+WABT_OPCODE(___, ___, ___, 0, 0x10, Call, "call")
+WABT_OPCODE(___, ___, ___, 0, 0x11, CallIndirect, "call_indirect")
+WABT_OPCODE(___, ___, ___, 0, 0x12, Invalid_0x12, "<invalid:0x12>")
+WABT_OPCODE(___, ___, ___, 0, 0x13, Invalid_0x13, "<invalid:0x13>")
+WABT_OPCODE(___, ___, ___, 0, 0x14, Invalid_0x14, "<invalid:0x14>")
+WABT_OPCODE(___, ___, ___, 0, 0x15, Invalid_0x15, "<invalid:0x15>")
+WABT_OPCODE(___, ___, ___, 0, 0x16, Invalid_0x16, "<invalid:0x16>")
+WABT_OPCODE(___, ___, ___, 0, 0x17, Invalid_0x17, "<invalid:0x17>")
+WABT_OPCODE(___, ___, ___, 0, 0x18, Invalid_0x18, "<invalid:0x18>")
+WABT_OPCODE(___, ___, ___, 0, 0x19, Invalid_0x19, "<invalid:0x19>")
+WABT_OPCODE(___, ___, ___, 0, 0x1a, Drop, "drop")
+WABT_OPCODE(___, ___, ___, 0, 0x1b, Select, "select")
+WABT_OPCODE(___, ___, ___, 0, 0x1c, Invalid_0x1c, "<invalid:0x1c>")
+WABT_OPCODE(___, ___, ___, 0, 0x1d, Invalid_0x1d, "<invalid:0x1d>")
+WABT_OPCODE(___, ___, ___, 0, 0x1e, Invalid_0x1e, "<invalid:0x1e>")
+WABT_OPCODE(___, ___, ___, 0, 0x1f, Invalid_0x1f, "<invalid:0x1f>")
+WABT_OPCODE(___, ___, ___, 0, 0x20, GetLocal, "get_local")
+WABT_OPCODE(___, ___, ___, 0, 0x21, SetLocal, "set_local")
+WABT_OPCODE(___, ___, ___, 0, 0x22, TeeLocal, "tee_local")
+WABT_OPCODE(___, ___, ___, 0, 0x23, GetGlobal, "get_global")
+WABT_OPCODE(___, ___, ___, 0, 0x24, SetGlobal, "set_global")
+WABT_OPCODE(___, ___, ___, 0, 0x25, Invalid_0x25, "<invalid:0x25>")
+WABT_OPCODE(___, ___, ___, 0, 0x26, Invalid_0x26, "<invalid:0x26>")
+WABT_OPCODE(___, ___, ___, 0, 0x27, Invalid_0x27, "<invalid:0x27>")
+WABT_OPCODE(I32, I32, ___, 4, 0x28, I32Load, "i32.load")
+WABT_OPCODE(I64, I32, ___, 8, 0x29, I64Load, "i64.load")
+WABT_OPCODE(F32, I32, ___, 4, 0x2a, F32Load, "f32.load")
+WABT_OPCODE(F64, I32, ___, 8, 0x2b, F64Load, "f64.load")
+WABT_OPCODE(I32, I32, ___, 1, 0x2c, I32Load8S, "i32.load8_s")
+WABT_OPCODE(I32, I32, ___, 1, 0x2d, I32Load8U, "i32.load8_u")
+WABT_OPCODE(I32, I32, ___, 2, 0x2e, I32Load16S, "i32.load16_s")
+WABT_OPCODE(I32, I32, ___, 2, 0x2f, I32Load16U, "i32.load16_u")
+WABT_OPCODE(I64, I32, ___, 1, 0x30, I64Load8S, "i64.load8_s")
+WABT_OPCODE(I64, I32, ___, 1, 0x31, I64Load8U, "i64.load8_u")
+WABT_OPCODE(I64, I32, ___, 2, 0x32, I64Load16S, "i64.load16_s")
+WABT_OPCODE(I64, I32, ___, 2, 0x33, I64Load16U, "i64.load16_u")
+WABT_OPCODE(I64, I32, ___, 4, 0x34, I64Load32S, "i64.load32_s")
+WABT_OPCODE(I64, I32, ___, 4, 0x35, I64Load32U, "i64.load32_u")
+WABT_OPCODE(___, I32, I32, 4, 0x36, I32Store, "i32.store")
+WABT_OPCODE(___, I32, I64, 8, 0x37, I64Store, "i64.store")
+WABT_OPCODE(___, I32, F32, 4, 0x38, F32Store, "f32.store")
+WABT_OPCODE(___, I32, F64, 8, 0x39, F64Store, "f64.store")
+WABT_OPCODE(___, I32, I32, 1, 0x3a, I32Store8, "i32.store8")
+WABT_OPCODE(___, I32, I32, 2, 0x3b, I32Store16, "i32.store16")
+WABT_OPCODE(___, I32, I64, 1, 0x3c, I64Store8, "i64.store8")
+WABT_OPCODE(___, I32, I64, 2, 0x3d, I64Store16, "i64.store16")
+WABT_OPCODE(___, I32, I64, 4, 0x3e, I64Store32, "i64.store32")
+WABT_OPCODE(I32, ___, ___, 0, 0x3f, CurrentMemory, "current_memory")
+WABT_OPCODE(I32, I32, ___, 0, 0x40, GrowMemory, "grow_memory")
+WABT_OPCODE(I32, ___, ___, 0, 0x41, I32Const, "i32.const")
+WABT_OPCODE(I64, ___, ___, 0, 0x42, I64Const, "i64.const")
+WABT_OPCODE(F32, ___, ___, 0, 0x43, F32Const, "f32.const")
+WABT_OPCODE(F64, ___, ___, 0, 0x44, F64Const, "f64.const")
+WABT_OPCODE(I32, I32, ___, 0, 0x45, I32Eqz, "i32.eqz")
+WABT_OPCODE(I32, I32, I32, 0, 0x46, I32Eq, "i32.eq")
+WABT_OPCODE(I32, I32, I32, 0, 0x47, I32Ne, "i32.ne")
+WABT_OPCODE(I32, I32, I32, 0, 0x48, I32LtS, "i32.lt_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x49, I32LtU, "i32.lt_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x4a, I32GtS, "i32.gt_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x4b, I32GtU, "i32.gt_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x4c, I32LeS, "i32.le_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x4d, I32LeU, "i32.le_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x4e, I32GeS, "i32.ge_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x4f, I32GeU, "i32.ge_u")
+WABT_OPCODE(I32, I64, ___, 0, 0x50, I64Eqz, "i64.eqz")
+WABT_OPCODE(I32, I64, I64, 0, 0x51, I64Eq, "i64.eq")
+WABT_OPCODE(I32, I64, I64, 0, 0x52, I64Ne, "i64.ne")
+WABT_OPCODE(I32, I64, I64, 0, 0x53, I64LtS, "i64.lt_s")
+WABT_OPCODE(I32, I64, I64, 0, 0x54, I64LtU, "i64.lt_u")
+WABT_OPCODE(I32, I64, I64, 0, 0x55, I64GtS, "i64.gt_s")
+WABT_OPCODE(I32, I64, I64, 0, 0x56, I64GtU, "i64.gt_u")
+WABT_OPCODE(I32, I64, I64, 0, 0x57, I64LeS, "i64.le_s")
+WABT_OPCODE(I32, I64, I64, 0, 0x58, I64LeU, "i64.le_u")
+WABT_OPCODE(I32, I64, I64, 0, 0x59, I64GeS, "i64.ge_s")
+WABT_OPCODE(I32, I64, I64, 0, 0x5a, I64GeU, "i64.ge_u")
+WABT_OPCODE(I32, F32, F32, 0, 0x5b, F32Eq, "f32.eq")
+WABT_OPCODE(I32, F32, F32, 0, 0x5c, F32Ne, "f32.ne")
+WABT_OPCODE(I32, F32, F32, 0, 0x5d, F32Lt, "f32.lt")
+WABT_OPCODE(I32, F32, F32, 0, 0x5e, F32Gt, "f32.gt")
+WABT_OPCODE(I32, F32, F32, 0, 0x5f, F32Le, "f32.le")
+WABT_OPCODE(I32, F32, F32, 0, 0x60, F32Ge, "f32.ge")
+WABT_OPCODE(I32, F64, F64, 0, 0x61, F64Eq, "f64.eq")
+WABT_OPCODE(I32, F64, F64, 0, 0x62, F64Ne, "f64.ne")
+WABT_OPCODE(I32, F64, F64, 0, 0x63, F64Lt, "f64.lt")
+WABT_OPCODE(I32, F64, F64, 0, 0x64, F64Gt, "f64.gt")
+WABT_OPCODE(I32, F64, F64, 0, 0x65, F64Le, "f64.le")
+WABT_OPCODE(I32, F64, F64, 0, 0x66, F64Ge, "f64.ge")
+WABT_OPCODE(I32, I32, ___, 0, 0x67, I32Clz, "i32.clz")
+WABT_OPCODE(I32, I32, ___, 0, 0x68, I32Ctz, "i32.ctz")
+WABT_OPCODE(I32, I32, ___, 0, 0x69, I32Popcnt, "i32.popcnt")
+WABT_OPCODE(I32, I32, I32, 0, 0x6a, I32Add, "i32.add")
+WABT_OPCODE(I32, I32, I32, 0, 0x6b, I32Sub, "i32.sub")
+WABT_OPCODE(I32, I32, I32, 0, 0x6c, I32Mul, "i32.mul")
+WABT_OPCODE(I32, I32, I32, 0, 0x6d, I32DivS, "i32.div_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x6e, I32DivU, "i32.div_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x6f, I32RemS, "i32.rem_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x70, I32RemU, "i32.rem_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x71, I32And, "i32.and")
+WABT_OPCODE(I32, I32, I32, 0, 0x72, I32Or, "i32.or")
+WABT_OPCODE(I32, I32, I32, 0, 0x73, I32Xor, "i32.xor")
+WABT_OPCODE(I32, I32, I32, 0, 0x74, I32Shl, "i32.shl")
+WABT_OPCODE(I32, I32, I32, 0, 0x75, I32ShrS, "i32.shr_s")
+WABT_OPCODE(I32, I32, I32, 0, 0x76, I32ShrU, "i32.shr_u")
+WABT_OPCODE(I32, I32, I32, 0, 0x77, I32Rotl, "i32.rotl")
+WABT_OPCODE(I32, I32, I32, 0, 0x78, I32Rotr, "i32.rotr")
+WABT_OPCODE(I64, I64, ___, 0, 0x79, I64Clz, "i64.clz")
+WABT_OPCODE(I64, I64, ___, 0, 0x7a, I64Ctz, "i64.ctz")
+WABT_OPCODE(I64, I64, ___, 0, 0x7b, I64Popcnt, "i64.popcnt")
+WABT_OPCODE(I64, I64, I64, 0, 0x7c, I64Add, "i64.add")
+WABT_OPCODE(I64, I64, I64, 0, 0x7d, I64Sub, "i64.sub")
+WABT_OPCODE(I64, I64, I64, 0, 0x7e, I64Mul, "i64.mul")
+WABT_OPCODE(I64, I64, I64, 0, 0x7f, I64DivS, "i64.div_s")
+WABT_OPCODE(I64, I64, I64, 0, 0x80, I64DivU, "i64.div_u")
+WABT_OPCODE(I64, I64, I64, 0, 0x81, I64RemS, "i64.rem_s")
+WABT_OPCODE(I64, I64, I64, 0, 0x82, I64RemU, "i64.rem_u")
+WABT_OPCODE(I64, I64, I64, 0, 0x83, I64And, "i64.and")
+WABT_OPCODE(I64, I64, I64, 0, 0x84, I64Or, "i64.or")
+WABT_OPCODE(I64, I64, I64, 0, 0x85, I64Xor, "i64.xor")
+WABT_OPCODE(I64, I64, I64, 0, 0x86, I64Shl, "i64.shl")
+WABT_OPCODE(I64, I64, I64, 0, 0x87, I64ShrS, "i64.shr_s")
+WABT_OPCODE(I64, I64, I64, 0, 0x88, I64ShrU, "i64.shr_u")
+WABT_OPCODE(I64, I64, I64, 0, 0x89, I64Rotl, "i64.rotl")
+WABT_OPCODE(I64, I64, I64, 0, 0x8a, I64Rotr, "i64.rotr")
+WABT_OPCODE(F32, F32, F32, 0, 0x8b, F32Abs, "f32.abs")
+WABT_OPCODE(F32, F32, F32, 0, 0x8c, F32Neg, "f32.neg")
+WABT_OPCODE(F32, F32, F32, 0, 0x8d, F32Ceil, "f32.ceil")
+WABT_OPCODE(F32, F32, F32, 0, 0x8e, F32Floor, "f32.floor")
+WABT_OPCODE(F32, F32, F32, 0, 0x8f, F32Trunc, "f32.trunc")
+WABT_OPCODE(F32, F32, F32, 0, 0x90, F32Nearest, "f32.nearest")
+WABT_OPCODE(F32, F32, F32, 0, 0x91, F32Sqrt, "f32.sqrt")
+WABT_OPCODE(F32, F32, F32, 0, 0x92, F32Add, "f32.add")
+WABT_OPCODE(F32, F32, F32, 0, 0x93, F32Sub, "f32.sub")
+WABT_OPCODE(F32, F32, F32, 0, 0x94, F32Mul, "f32.mul")
+WABT_OPCODE(F32, F32, F32, 0, 0x95, F32Div, "f32.div")
+WABT_OPCODE(F32, F32, F32, 0, 0x96, F32Min, "f32.min")
+WABT_OPCODE(F32, F32, F32, 0, 0x97, F32Max, "f32.max")
+WABT_OPCODE(F32, F32, F32, 0, 0x98, F32Copysign, "f32.copysign")
+WABT_OPCODE(F64, F64, F64, 0, 0x99, F64Abs, "f64.abs")
+WABT_OPCODE(F64, F64, F64, 0, 0x9a, F64Neg, "f64.neg")
+WABT_OPCODE(F64, F64, F64, 0, 0x9b, F64Ceil, "f64.ceil")
+WABT_OPCODE(F64, F64, F64, 0, 0x9c, F64Floor, "f64.floor")
+WABT_OPCODE(F64, F64, F64, 0, 0x9d, F64Trunc, "f64.trunc")
+WABT_OPCODE(F64, F64, F64, 0, 0x9e, F64Nearest, "f64.nearest")
+WABT_OPCODE(F64, F64, F64, 0, 0x9f, F64Sqrt, "f64.sqrt")
+WABT_OPCODE(F64, F64, F64, 0, 0xa0, F64Add, "f64.add")
+WABT_OPCODE(F64, F64, F64, 0, 0xa1, F64Sub, "f64.sub")
+WABT_OPCODE(F64, F64, F64, 0, 0xa2, F64Mul, "f64.mul")
+WABT_OPCODE(F64, F64, F64, 0, 0xa3, F64Div, "f64.div")
+WABT_OPCODE(F64, F64, F64, 0, 0xa4, F64Min, "f64.min")
+WABT_OPCODE(F64, F64, F64, 0, 0xa5, F64Max, "f64.max")
+WABT_OPCODE(F64, F64, F64, 0, 0xa6, F64Copysign, "f64.copysign")
+WABT_OPCODE(I32, I64, ___, 0, 0xa7, I32WrapI64, "i32.wrap/i64")
+WABT_OPCODE(I32, F32, ___, 0, 0xa8, I32TruncSF32, "i32.trunc_s/f32")
+WABT_OPCODE(I32, F32, ___, 0, 0xa9, I32TruncUF32, "i32.trunc_u/f32")
+WABT_OPCODE(I32, F64, ___, 0, 0xaa, I32TruncSF64, "i32.trunc_s/f64")
+WABT_OPCODE(I32, F64, ___, 0, 0xab, I32TruncUF64, "i32.trunc_u/f64")
+WABT_OPCODE(I64, I32, ___, 0, 0xac, I64ExtendSI32, "i64.extend_s/i32")
+WABT_OPCODE(I64, I32, ___, 0, 0xad, I64ExtendUI32, "i64.extend_u/i32")
+WABT_OPCODE(I64, F32, ___, 0, 0xae, I64TruncSF32, "i64.trunc_s/f32")
+WABT_OPCODE(I64, F32, ___, 0, 0xaf, I64TruncUF32, "i64.trunc_u/f32")
+WABT_OPCODE(I64, F64, ___, 0, 0xb0, I64TruncSF64, "i64.trunc_s/f64")
+WABT_OPCODE(I64, F64, ___, 0, 0xb1, I64TruncUF64, "i64.trunc_u/f64")
+WABT_OPCODE(F32, I32, ___, 0, 0xb2, F32ConvertSI32, "f32.convert_s/i32")
+WABT_OPCODE(F32, I32, ___, 0, 0xb3, F32ConvertUI32, "f32.convert_u/i32")
+WABT_OPCODE(F32, I64, ___, 0, 0xb4, F32ConvertSI64, "f32.convert_s/i64")
+WABT_OPCODE(F32, I64, ___, 0, 0xb5, F32ConvertUI64, "f32.convert_u/i64")
+WABT_OPCODE(F32, F64, ___, 0, 0xb6, F32DemoteF64, "f32.demote/f64")
+WABT_OPCODE(F64, I32, ___, 0, 0xb7, F64ConvertSI32, "f64.convert_s/i32")
+WABT_OPCODE(F64, I32, ___, 0, 0xb8, F64ConvertUI32, "f64.convert_u/i32")
+WABT_OPCODE(F64, I64, ___, 0, 0xb9, F64ConvertSI64, "f64.convert_s/i64")
+WABT_OPCODE(F64, I64, ___, 0, 0xba, F64ConvertUI64, "f64.convert_u/i64")
+WABT_OPCODE(F64, F32, ___, 0, 0xbb, F64PromoteF32, "f64.promote/f32")
+WABT_OPCODE(I32, F32, ___, 0, 0xbc, I32ReinterpretF32, "i32.reinterpret/f32")
+WABT_OPCODE(I64, F64, ___, 0, 0xbd, I64ReinterpretF64, "i64.reinterpret/f64")
+WABT_OPCODE(F32, I32, ___, 0, 0xbe, F32ReinterpretI32, "f32.reinterpret/i32")
+WABT_OPCODE(F64, I64, ___, 0, 0xbf, F64ReinterpretI64, "f64.reinterpret/i64")
diff --git a/src/opcode.h b/src/opcode.h
new file mode 100644
index 00000000..d22b6bc1
--- /dev/null
+++ b/src/opcode.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 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_OPCODE_H_
+#define WABT_OPCODE_H_
+
+#include "common.h"
+
+namespace wabt {
+
+enum class Opcode {
+
+#define WABT_OPCODE(rtype, type1, type2, mem_size, code, Name, text) \
+ Name = code,
+#include "opcode.def"
+#undef WABT_OPCODE
+
+ First = Unreachable,
+ Last = F64ReinterpretI64,
+};
+static const int kOpcodeCount = WABT_ENUM_COUNT(Opcode);
+
+struct OpcodeInfo {
+ const char* name;
+ Type result_type;
+ Type param1_type;
+ Type param2_type;
+ int memory_size;
+};
+
+// Return 1 if |alignment| matches the alignment of |opcode|, or if |alignment|
+// is WABT_USE_NATURAL_ALIGNMENT.
+bool is_naturally_aligned(Opcode opcode, uint32_t alignment);
+
+// If |alignment| is WABT_USE_NATURAL_ALIGNMENT, return the alignment of
+// |opcode|, else return |alignment|.
+uint32_t get_opcode_alignment(Opcode opcode, uint32_t alignment);
+
+extern OpcodeInfo g_opcode_info[];
+
+inline const char* get_opcode_name(Opcode opcode) {
+ assert(static_cast<int>(opcode) < kOpcodeCount);
+ return g_opcode_info[static_cast<size_t>(opcode)].name;
+}
+
+inline Type get_opcode_result_type(Opcode opcode) {
+ assert(static_cast<int>(opcode) < kOpcodeCount);
+ return g_opcode_info[static_cast<size_t>(opcode)].result_type;
+}
+
+inline Type get_opcode_param_type_1(Opcode opcode) {
+ assert(static_cast<int>(opcode) < kOpcodeCount);
+ return g_opcode_info[static_cast<size_t>(opcode)].param1_type;
+}
+
+inline Type get_opcode_param_type_2(Opcode opcode) {
+ assert(static_cast<int>(opcode) < kOpcodeCount);
+ return g_opcode_info[static_cast<size_t>(opcode)].param2_type;
+}
+
+inline int get_opcode_memory_size(Opcode opcode) {
+ assert(static_cast<int>(opcode) < kOpcodeCount);
+ return g_opcode_info[static_cast<size_t>(opcode)].memory_size;
+}
+
+} // namespace
+
+#endif // WABT_OPCODE_H_
diff --git a/src/type-checker.h b/src/type-checker.h
index b3135d15..31547dac 100644
--- a/src/type-checker.h
+++ b/src/type-checker.h
@@ -20,6 +20,7 @@
#include <vector>
#include "common.h"
+#include "opcode.h"
namespace wabt {