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 
MemSize(MachineType type)307   static byte MemSize(MachineType type) {
308     return 1 << ElementSizeLog2Of(type.representation());
309   }
310 
LocalTypeCodeFor(LocalType type)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 
MemTypeCodeFor(MachineType type)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 
MachineTypeFor(LocalType type)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 
LocalTypeFor(MachineType type)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
LoadStoreOpcodeOf(MachineType type,bool store)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 
LoadStoreAccessOf(bool with_offset)429   static byte LoadStoreAccessOf(bool with_offset) {
430     return MemoryAccess::OffsetField::encode(with_offset);
431   }
432 
ShortNameOf(LocalType type)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 
TypeName(LocalType type)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