Home | History | Annotate | Download | only in wasm
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_WASM_OPCODES_H_
      6 #define V8_WASM_OPCODES_H_
      7 
      8 #include "src/machine-type.h"
      9 #include "src/signature.h"
     10 
     11 namespace v8 {
     12 namespace internal {
     13 namespace wasm {
     14 
     15 // Binary encoding of local types.
     16 enum LocalTypeCode {
     17   kLocalVoid = 0,
     18   kLocalI32 = 1,
     19   kLocalI64 = 2,
     20   kLocalF32 = 3,
     21   kLocalF64 = 4
     22 };
     23 
     24 // Binary encoding of memory types.
     25 enum MemTypeCode {
     26   kMemI8 = 0,
     27   kMemU8 = 1,
     28   kMemI16 = 2,
     29   kMemU16 = 3,
     30   kMemI32 = 4,
     31   kMemU32 = 5,
     32   kMemI64 = 6,
     33   kMemU64 = 7,
     34   kMemF32 = 8,
     35   kMemF64 = 9
     36 };
     37 
     38 // We reuse the internal machine type to represent WebAssembly AST types.
     39 // A typedef improves readability without adding a whole new type system.
     40 typedef MachineRepresentation LocalType;
     41 const LocalType kAstStmt = MachineRepresentation::kNone;
     42 const LocalType kAstI32 = MachineRepresentation::kWord32;
     43 const LocalType kAstI64 = MachineRepresentation::kWord64;
     44 const LocalType kAstF32 = MachineRepresentation::kFloat32;
     45 const LocalType kAstF64 = MachineRepresentation::kFloat64;
     46 // We use kTagged here because kNone is already used by kAstStmt.
     47 const LocalType kAstEnd = MachineRepresentation::kTagged;
     48 
     49 // Functionality related to encoding memory accesses.
     50 struct MemoryAccess {
     51   // Atomicity annotations for access to the memory and globals.
     52   enum Atomicity {
     53     kNone = 0,        // non-atomic
     54     kSequential = 1,  // sequential consistency
     55     kAcquire = 2,     // acquire semantics
     56     kRelease = 3      // release semantics
     57   };
     58 
     59   // Alignment annotations for memory accesses.
     60   enum Alignment { kAligned = 0, kUnaligned = 1 };
     61 
     62   // Bitfields for the various annotations for memory accesses.
     63   typedef BitField<Alignment, 7, 1> AlignmentField;
     64   typedef BitField<Atomicity, 5, 2> AtomicityField;
     65   typedef BitField<bool, 4, 1> OffsetField;
     66 };
     67 
     68 typedef Signature<LocalType> FunctionSig;
     69 
     70 // Control expressions and blocks.
     71 #define FOREACH_CONTROL_OPCODE(V) \
     72   V(Nop, 0x00, _)                 \
     73   V(Block, 0x01, _)               \
     74   V(Loop, 0x02, _)                \
     75   V(If, 0x03, _)                  \
     76   V(IfElse, 0x04, _)              \
     77   V(Select, 0x05, _)              \
     78   V(Br, 0x06, _)                  \
     79   V(BrIf, 0x07, _)                \
     80   V(TableSwitch, 0x08, _)         \
     81   V(Return, 0x14, _)              \
     82   V(Unreachable, 0x15, _)
     83 // TODO(titzer): numbering
     84 
     85 // Constants, locals, globals, and calls.
     86 #define FOREACH_MISC_OPCODE(V) \
     87   V(I8Const, 0x09, _)          \
     88   V(I32Const, 0x0a, _)         \
     89   V(I64Const, 0x0b, _)         \
     90   V(F64Const, 0x0c, _)         \
     91   V(F32Const, 0x0d, _)         \
     92   V(GetLocal, 0x0e, _)         \
     93   V(SetLocal, 0x0f, _)         \
     94   V(LoadGlobal, 0x10, _)       \
     95   V(StoreGlobal, 0x11, _)      \
     96   V(CallFunction, 0x12, _)     \
     97   V(CallIndirect, 0x13, _)
     98 
     99 // Load memory expressions.
    100 #define FOREACH_LOAD_MEM_OPCODE(V) \
    101   V(I32LoadMem8S, 0x20, i_i)       \
    102   V(I32LoadMem8U, 0x21, i_i)       \
    103   V(I32LoadMem16S, 0x22, i_i)      \
    104   V(I32LoadMem16U, 0x23, i_i)      \
    105   V(I64LoadMem8S, 0x24, l_i)       \
    106   V(I64LoadMem8U, 0x25, l_i)       \
    107   V(I64LoadMem16S, 0x26, l_i)      \
    108   V(I64LoadMem16U, 0x27, l_i)      \
    109   V(I64LoadMem32S, 0x28, l_i)      \
    110   V(I64LoadMem32U, 0x29, l_i)      \
    111   V(I32LoadMem, 0x2a, i_i)         \
    112   V(I64LoadMem, 0x2b, l_i)         \
    113   V(F32LoadMem, 0x2c, f_i)         \
    114   V(F64LoadMem, 0x2d, d_i)
    115 
    116 // Store memory expressions.
    117 #define FOREACH_STORE_MEM_OPCODE(V) \
    118   V(I32StoreMem8, 0x2e, i_ii)       \
    119   V(I32StoreMem16, 0x2f, i_ii)      \
    120   V(I64StoreMem8, 0x30, l_il)       \
    121   V(I64StoreMem16, 0x31, l_il)      \
    122   V(I64StoreMem32, 0x32, l_il)      \
    123   V(I32StoreMem, 0x33, i_ii)        \
    124   V(I64StoreMem, 0x34, l_il)        \
    125   V(F32StoreMem, 0x35, f_if)        \
    126   V(F64StoreMem, 0x36, d_id)
    127 
    128 // Load memory expressions.
    129 #define FOREACH_MISC_MEM_OPCODE(V) \
    130   V(MemorySize, 0x3b, i_v)         \
    131   V(GrowMemory, 0x39, i_i)
    132 
    133 // Expressions with signatures.
    134 #define FOREACH_SIMPLE_OPCODE(V)  \
    135   V(I32Add, 0x40, i_ii)           \
    136   V(I32Sub, 0x41, i_ii)           \
    137   V(I32Mul, 0x42, i_ii)           \
    138   V(I32DivS, 0x43, i_ii)          \
    139   V(I32DivU, 0x44, i_ii)          \
    140   V(I32RemS, 0x45, i_ii)          \
    141   V(I32RemU, 0x46, i_ii)          \
    142   V(I32And, 0x47, i_ii)           \
    143   V(I32Ior, 0x48, i_ii)           \
    144   V(I32Xor, 0x49, i_ii)           \
    145   V(I32Shl, 0x4a, i_ii)           \
    146   V(I32ShrU, 0x4b, i_ii)          \
    147   V(I32ShrS, 0x4c, i_ii)          \
    148   V(I32Eq, 0x4d, i_ii)            \
    149   V(I32Ne, 0x4e, i_ii)            \
    150   V(I32LtS, 0x4f, i_ii)           \
    151   V(I32LeS, 0x50, i_ii)           \
    152   V(I32LtU, 0x51, i_ii)           \
    153   V(I32LeU, 0x52, i_ii)           \
    154   V(I32GtS, 0x53, i_ii)           \
    155   V(I32GeS, 0x54, i_ii)           \
    156   V(I32GtU, 0x55, i_ii)           \
    157   V(I32GeU, 0x56, i_ii)           \
    158   V(I32Clz, 0x57, i_i)            \
    159   V(I32Ctz, 0x58, i_i)            \
    160   V(I32Popcnt, 0x59, i_i)         \
    161   V(BoolNot, 0x5a, i_i)           \
    162   V(I64Add, 0x5b, l_ll)           \
    163   V(I64Sub, 0x5c, l_ll)           \
    164   V(I64Mul, 0x5d, l_ll)           \
    165   V(I64DivS, 0x5e, l_ll)          \
    166   V(I64DivU, 0x5f, l_ll)          \
    167   V(I64RemS, 0x60, l_ll)          \
    168   V(I64RemU, 0x61, l_ll)          \
    169   V(I64And, 0x62, l_ll)           \
    170   V(I64Ior, 0x63, l_ll)           \
    171   V(I64Xor, 0x64, l_ll)           \
    172   V(I64Shl, 0x65, l_ll)           \
    173   V(I64ShrU, 0x66, l_ll)          \
    174   V(I64ShrS, 0x67, l_ll)          \
    175   V(I64Eq, 0x68, i_ll)            \
    176   V(I64Ne, 0x69, i_ll)            \
    177   V(I64LtS, 0x6a, i_ll)           \
    178   V(I64LeS, 0x6b, i_ll)           \
    179   V(I64LtU, 0x6c, i_ll)           \
    180   V(I64LeU, 0x6d, i_ll)           \
    181   V(I64GtS, 0x6e, i_ll)           \
    182   V(I64GeS, 0x6f, i_ll)           \
    183   V(I64GtU, 0x70, i_ll)           \
    184   V(I64GeU, 0x71, i_ll)           \
    185   V(I64Clz, 0x72, l_l)            \
    186   V(I64Ctz, 0x73, l_l)            \
    187   V(I64Popcnt, 0x74, l_l)         \
    188   V(F32Add, 0x75, f_ff)           \
    189   V(F32Sub, 0x76, f_ff)           \
    190   V(F32Mul, 0x77, f_ff)           \
    191   V(F32Div, 0x78, f_ff)           \
    192   V(F32Min, 0x79, f_ff)           \
    193   V(F32Max, 0x7a, f_ff)           \
    194   V(F32Abs, 0x7b, f_f)            \
    195   V(F32Neg, 0x7c, f_f)            \
    196   V(F32CopySign, 0x7d, f_ff)      \
    197   V(F32Ceil, 0x7e, f_f)           \
    198   V(F32Floor, 0x7f, f_f)          \
    199   V(F32Trunc, 0x80, f_f)          \
    200   V(F32NearestInt, 0x81, f_f)     \
    201   V(F32Sqrt, 0x82, f_f)           \
    202   V(F32Eq, 0x83, i_ff)            \
    203   V(F32Ne, 0x84, i_ff)            \
    204   V(F32Lt, 0x85, i_ff)            \
    205   V(F32Le, 0x86, i_ff)            \
    206   V(F32Gt, 0x87, i_ff)            \
    207   V(F32Ge, 0x88, i_ff)            \
    208   V(F64Add, 0x89, d_dd)           \
    209   V(F64Sub, 0x8a, d_dd)           \
    210   V(F64Mul, 0x8b, d_dd)           \
    211   V(F64Div, 0x8c, d_dd)           \
    212   V(F64Min, 0x8d, d_dd)           \
    213   V(F64Max, 0x8e, d_dd)           \
    214   V(F64Abs, 0x8f, d_d)            \
    215   V(F64Neg, 0x90, d_d)            \
    216   V(F64CopySign, 0x91, d_dd)      \
    217   V(F64Ceil, 0x92, d_d)           \
    218   V(F64Floor, 0x93, d_d)          \
    219   V(F64Trunc, 0x94, d_d)          \
    220   V(F64NearestInt, 0x95, d_d)     \
    221   V(F64Sqrt, 0x96, d_d)           \
    222   V(F64Eq, 0x97, i_dd)            \
    223   V(F64Ne, 0x98, i_dd)            \
    224   V(F64Lt, 0x99, i_dd)            \
    225   V(F64Le, 0x9a, i_dd)            \
    226   V(F64Gt, 0x9b, i_dd)            \
    227   V(F64Ge, 0x9c, i_dd)            \
    228   V(I32SConvertF32, 0x9d, i_f)    \
    229   V(I32SConvertF64, 0x9e, i_d)    \
    230   V(I32UConvertF32, 0x9f, i_f)    \
    231   V(I32UConvertF64, 0xa0, i_d)    \
    232   V(I32ConvertI64, 0xa1, i_l)     \
    233   V(I64SConvertF32, 0xa2, l_f)    \
    234   V(I64SConvertF64, 0xa3, l_d)    \
    235   V(I64UConvertF32, 0xa4, l_f)    \
    236   V(I64UConvertF64, 0xa5, l_d)    \
    237   V(I64SConvertI32, 0xa6, l_i)    \
    238   V(I64UConvertI32, 0xa7, l_i)    \
    239   V(F32SConvertI32, 0xa8, f_i)    \
    240   V(F32UConvertI32, 0xa9, f_i)    \
    241   V(F32SConvertI64, 0xaa, f_l)    \
    242   V(F32UConvertI64, 0xab, f_l)    \
    243   V(F32ConvertF64, 0xac, f_d)     \
    244   V(F32ReinterpretI32, 0xad, f_i) \
    245   V(F64SConvertI32, 0xae, d_i)    \
    246   V(F64UConvertI32, 0xaf, d_i)    \
    247   V(F64SConvertI64, 0xb0, d_l)    \
    248   V(F64UConvertI64, 0xb1, d_l)    \
    249   V(F64ConvertF32, 0xb2, d_f)     \
    250   V(F64ReinterpretI64, 0xb3, d_l) \
    251   V(I32ReinterpretF32, 0xb4, i_f) \
    252   V(I64ReinterpretF64, 0xb5, l_d)
    253 
    254 // All opcodes.
    255 #define FOREACH_OPCODE(V)     \
    256   FOREACH_CONTROL_OPCODE(V)   \
    257   FOREACH_MISC_OPCODE(V)      \
    258   FOREACH_SIMPLE_OPCODE(V)    \
    259   FOREACH_STORE_MEM_OPCODE(V) \
    260   FOREACH_LOAD_MEM_OPCODE(V)  \
    261   FOREACH_MISC_MEM_OPCODE(V)
    262 
    263 // All signatures.
    264 #define FOREACH_SIGNATURE(V)         \
    265   V(i_ii, kAstI32, kAstI32, kAstI32) \
    266   V(i_i, kAstI32, kAstI32)           \
    267   V(i_v, kAstI32)                    \
    268   V(i_ff, kAstI32, kAstF32, kAstF32) \
    269   V(i_f, kAstI32, kAstF32)           \
    270   V(i_dd, kAstI32, kAstF64, kAstF64) \
    271   V(i_d, kAstI32, kAstF64)           \
    272   V(i_l, kAstI32, kAstI64)           \
    273   V(l_ll, kAstI64, kAstI64, kAstI64) \
    274   V(i_ll, kAstI32, kAstI64, kAstI64) \
    275   V(l_l, kAstI64, kAstI64)           \
    276   V(l_i, kAstI64, kAstI32)           \
    277   V(l_f, kAstI64, kAstF32)           \
    278   V(l_d, kAstI64, kAstF64)           \
    279   V(f_ff, kAstF32, kAstF32, kAstF32) \
    280   V(f_f, kAstF32, kAstF32)           \
    281   V(f_d, kAstF32, kAstF64)           \
    282   V(f_i, kAstF32, kAstI32)           \
    283   V(f_l, kAstF32, kAstI64)           \
    284   V(d_dd, kAstF64, kAstF64, kAstF64) \
    285   V(d_d, kAstF64, kAstF64)           \
    286   V(d_f, kAstF64, kAstF32)           \
    287   V(d_i, kAstF64, kAstI32)           \
    288   V(d_l, kAstF64, kAstI64)           \
    289   V(d_id, kAstF64, kAstI32, kAstF64) \
    290   V(f_if, kAstF32, kAstI32, kAstF32) \
    291   V(l_il, kAstI64, kAstI32, kAstI64)
    292 
    293 enum WasmOpcode {
    294 // Declare expression opcodes.
    295 #define DECLARE_NAMED_ENUM(name, opcode, sig) kExpr##name = opcode,
    296   FOREACH_OPCODE(DECLARE_NAMED_ENUM)
    297 #undef DECLARE_NAMED_ENUM
    298 };
    299 
    300 // A collection of opcode-related static methods.
    301 class WasmOpcodes {
    302  public:
    303   static bool IsSupported(WasmOpcode opcode);
    304   static const char* OpcodeName(WasmOpcode opcode);
    305   static FunctionSig* Signature(WasmOpcode opcode);
    306 
    307   static byte MemSize(MachineType type) {
    308     return 1 << ElementSizeLog2Of(type.representation());
    309   }
    310 
    311   static LocalTypeCode LocalTypeCodeFor(LocalType type) {
    312     switch (type) {
    313       case kAstI32:
    314         return kLocalI32;
    315       case kAstI64:
    316         return kLocalI64;
    317       case kAstF32:
    318         return kLocalF32;
    319       case kAstF64:
    320         return kLocalF64;
    321       case kAstStmt:
    322         return kLocalVoid;
    323       default:
    324         UNREACHABLE();
    325         return kLocalVoid;
    326     }
    327   }
    328 
    329   static MemTypeCode MemTypeCodeFor(MachineType type) {
    330     if (type == MachineType::Int8()) {
    331       return kMemI8;
    332     } else if (type == MachineType::Uint8()) {
    333       return kMemU8;
    334     } else if (type == MachineType::Int16()) {
    335       return kMemI16;
    336     } else if (type == MachineType::Uint16()) {
    337       return kMemU16;
    338     } else if (type == MachineType::Int32()) {
    339       return kMemI32;
    340     } else if (type == MachineType::Uint32()) {
    341       return kMemU32;
    342     } else if (type == MachineType::Int64()) {
    343       return kMemI64;
    344     } else if (type == MachineType::Uint64()) {
    345       return kMemU64;
    346     } else if (type == MachineType::Float32()) {
    347       return kMemF32;
    348     } else if (type == MachineType::Float64()) {
    349       return kMemF64;
    350     } else {
    351       UNREACHABLE();
    352       return kMemI32;
    353     }
    354   }
    355 
    356   static MachineType MachineTypeFor(LocalType type) {
    357     switch (type) {
    358       case kAstI32:
    359         return MachineType::Int32();
    360       case kAstI64:
    361         return MachineType::Int64();
    362       case kAstF32:
    363         return MachineType::Float32();
    364       case kAstF64:
    365         return MachineType::Float64();
    366       case kAstStmt:
    367         return MachineType::None();
    368       default:
    369         UNREACHABLE();
    370         return MachineType::None();
    371     }
    372   }
    373 
    374   static LocalType LocalTypeFor(MachineType type) {
    375     if (type == MachineType::Int8()) {
    376       return kAstI32;
    377     } else if (type == MachineType::Uint8()) {
    378       return kAstI32;
    379     } else if (type == MachineType::Int16()) {
    380       return kAstI32;
    381     } else if (type == MachineType::Uint16()) {
    382       return kAstI32;
    383     } else if (type == MachineType::Int32()) {
    384       return kAstI32;
    385     } else if (type == MachineType::Uint32()) {
    386       return kAstI32;
    387     } else if (type == MachineType::Int64()) {
    388       return kAstI64;
    389     } else if (type == MachineType::Uint64()) {
    390       return kAstI64;
    391     } else if (type == MachineType::Float32()) {
    392       return kAstF32;
    393     } else if (type == MachineType::Float64()) {
    394       return kAstF64;
    395     } else {
    396       UNREACHABLE();
    397       return kAstI32;
    398     }
    399   }
    400 
    401   // TODO(titzer): remove this method
    402   static WasmOpcode LoadStoreOpcodeOf(MachineType type, bool store) {
    403     if (type == MachineType::Int8()) {
    404       return store ? kExprI32StoreMem8 : kExprI32LoadMem8S;
    405     } else if (type == MachineType::Uint8()) {
    406       return store ? kExprI32StoreMem8 : kExprI32LoadMem8U;
    407     } else if (type == MachineType::Int16()) {
    408       return store ? kExprI32StoreMem16 : kExprI32LoadMem16S;
    409     } else if (type == MachineType::Uint16()) {
    410       return store ? kExprI32StoreMem16 : kExprI32LoadMem16U;
    411     } else if (type == MachineType::Int32()) {
    412       return store ? kExprI32StoreMem : kExprI32LoadMem;
    413     } else if (type == MachineType::Uint32()) {
    414       return store ? kExprI32StoreMem : kExprI32LoadMem;
    415     } else if (type == MachineType::Int64()) {
    416       return store ? kExprI64StoreMem : kExprI64LoadMem;
    417     } else if (type == MachineType::Uint64()) {
    418       return store ? kExprI64StoreMem : kExprI64LoadMem;
    419     } else if (type == MachineType::Float32()) {
    420       return store ? kExprF32StoreMem : kExprF32LoadMem;
    421     } else if (type == MachineType::Float64()) {
    422       return store ? kExprF64StoreMem : kExprF64LoadMem;
    423     } else {
    424       UNREACHABLE();
    425       return kExprNop;
    426     }
    427   }
    428 
    429   static byte LoadStoreAccessOf(bool with_offset) {
    430     return MemoryAccess::OffsetField::encode(with_offset);
    431   }
    432 
    433   static char ShortNameOf(LocalType type) {
    434     switch (type) {
    435       case kAstI32:
    436         return 'i';
    437       case kAstI64:
    438         return 'l';
    439       case kAstF32:
    440         return 'f';
    441       case kAstF64:
    442         return 'd';
    443       case kAstStmt:
    444         return 'v';
    445       case kAstEnd:
    446         return 'x';
    447       default:
    448         UNREACHABLE();
    449         return '?';
    450     }
    451   }
    452 
    453   static const char* TypeName(LocalType type) {
    454     switch (type) {
    455       case kAstI32:
    456         return "i32";
    457       case kAstI64:
    458         return "i64";
    459       case kAstF32:
    460         return "f32";
    461       case kAstF64:
    462         return "f64";
    463       case kAstStmt:
    464         return "<stmt>";
    465       case kAstEnd:
    466         return "<end>";
    467       default:
    468         return "<unknown>";
    469     }
    470   }
    471 };
    472 }  // namespace wasm
    473 }  // namespace internal
    474 }  // namespace v8
    475 
    476 #endif  // V8_WASM_OPCODES_H_
    477