1 /*
2  * Copyright 2015 WebAssembly Community Group participants
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //
18 // Parses and emits WebAssembly binary code
19 //
20 
21 #ifndef wasm_wasm_binary_h
22 #define wasm_wasm_binary_h
23 
24 #include <cassert>
25 #include <ostream>
26 #include <type_traits>
27 
28 #include "asm_v_wasm.h"
29 #include "asmjs/shared-constants.h"
30 #include "ir/import-utils.h"
31 #include "ir/module-utils.h"
32 #include "parsing.h"
33 #include "support/debug.h"
34 #include "wasm-builder.h"
35 #include "wasm-traversal.h"
36 #include "wasm-validator.h"
37 #include "wasm.h"
38 
39 #define DEBUG_TYPE "binary"
40 
41 namespace wasm {
42 
43 enum {
44   // the maximum amount of bytes we emit per LEB
45   MaxLEB32Bytes = 5,
46 };
47 
48 // wasm VMs on the web have decided to impose some limits on what they
49 // accept
50 enum WebLimitations : uint32_t {
51   MaxDataSegments = 100 * 1000,
52   MaxFunctionBodySize = 128 * 1024,
53   MaxFunctionLocals = 50 * 1000
54 };
55 
56 template<typename T, typename MiniT> struct LEB {
57   static_assert(sizeof(MiniT) == 1, "MiniT must be a byte");
58 
59   T value;
60 
61   LEB() = default;
LEBLEB62   LEB(T value) : value(value) {}
63 
hasMoreLEB64   bool hasMore(T temp, MiniT byte) {
65     // for signed, we must ensure the last bit has the right sign, as it will
66     // zero extend
67     return std::is_signed<T>::value
68              ? (temp != 0 && temp != T(-1)) || (value >= 0 && (byte & 64)) ||
69                  (value < 0 && !(byte & 64))
70              : (temp != 0);
71   }
72 
writeLEB73   void write(std::vector<uint8_t>* out) {
74     T temp = value;
75     bool more;
76     do {
77       uint8_t byte = temp & 127;
78       temp >>= 7;
79       more = hasMore(temp, byte);
80       if (more) {
81         byte = byte | 128;
82       }
83       out->push_back(byte);
84     } while (more);
85   }
86 
87   // @minimum: a minimum number of bytes to write, padding as necessary
88   // returns the number of bytes written
89   size_t writeAt(std::vector<uint8_t>* out, size_t at, size_t minimum = 0) {
90     T temp = value;
91     size_t offset = 0;
92     bool more;
93     do {
94       uint8_t byte = temp & 127;
95       temp >>= 7;
96       more = hasMore(temp, byte) || offset + 1 < minimum;
97       if (more) {
98         byte = byte | 128;
99       }
100       (*out)[at + offset] = byte;
101       offset++;
102     } while (more);
103     return offset;
104   }
105 
readLEB106   LEB<T, MiniT>& read(std::function<MiniT()> get) {
107     value = 0;
108     T shift = 0;
109     MiniT byte;
110     while (1) {
111       byte = get();
112       bool last = !(byte & 128);
113       T payload = byte & 127;
114       typedef typename std::make_unsigned<T>::type mask_type;
115       auto shift_mask = 0 == shift
116                           ? ~mask_type(0)
117                           : ((mask_type(1) << (sizeof(T) * 8 - shift)) - 1u);
118       T significant_payload = payload & shift_mask;
119       if (significant_payload != payload) {
120         if (!(std::is_signed<T>::value && last)) {
121           throw ParseException("LEB dropped bits only valid for signed LEB");
122         }
123       }
124       value |= significant_payload << shift;
125       if (last) {
126         break;
127       }
128       shift += 7;
129       if (size_t(shift) >= sizeof(T) * 8) {
130         throw ParseException("LEB overflow");
131       }
132     }
133     // If signed LEB, then we might need to sign-extend. (compile should
134     // optimize this out if not needed).
135     if (std::is_signed<T>::value) {
136       shift += 7;
137       if ((byte & 64) && size_t(shift) < 8 * sizeof(T)) {
138         size_t sext_bits = 8 * sizeof(T) - size_t(shift);
139         value <<= sext_bits;
140         value >>= sext_bits;
141         if (value >= 0) {
142           throw ParseException(
143             " LEBsign-extend should produce a negative value");
144         }
145       }
146     }
147     return *this;
148   }
149 };
150 
151 typedef LEB<uint32_t, uint8_t> U32LEB;
152 typedef LEB<uint64_t, uint8_t> U64LEB;
153 typedef LEB<int32_t, int8_t> S32LEB;
154 typedef LEB<int64_t, int8_t> S64LEB;
155 
156 //
157 // We mostly stream into a buffer as we create the binary format, however,
158 // sometimes we need to backtrack and write to a location behind us - wasm
159 // is optimized for reading, not writing.
160 //
161 class BufferWithRandomAccess : public std::vector<uint8_t> {
162 public:
163   BufferWithRandomAccess() = default;
164 
165   BufferWithRandomAccess& operator<<(int8_t x) {
166     BYN_TRACE("writeInt8: " << (int)(uint8_t)x << " (at " << size() << ")\n");
167     push_back(x);
168     return *this;
169   }
170   BufferWithRandomAccess& operator<<(int16_t x) {
171     BYN_TRACE("writeInt16: " << x << " (at " << size() << ")\n");
172     push_back(x & 0xff);
173     push_back(x >> 8);
174     return *this;
175   }
176   BufferWithRandomAccess& operator<<(int32_t x) {
177     BYN_TRACE("writeInt32: " << x << " (at " << size() << ")\n");
178     push_back(x & 0xff);
179     x >>= 8;
180     push_back(x & 0xff);
181     x >>= 8;
182     push_back(x & 0xff);
183     x >>= 8;
184     push_back(x & 0xff);
185     return *this;
186   }
187   BufferWithRandomAccess& operator<<(int64_t x) {
188     BYN_TRACE("writeInt64: " << x << " (at " << size() << ")\n");
189     push_back(x & 0xff);
190     x >>= 8;
191     push_back(x & 0xff);
192     x >>= 8;
193     push_back(x & 0xff);
194     x >>= 8;
195     push_back(x & 0xff);
196     x >>= 8;
197     push_back(x & 0xff);
198     x >>= 8;
199     push_back(x & 0xff);
200     x >>= 8;
201     push_back(x & 0xff);
202     x >>= 8;
203     push_back(x & 0xff);
204     return *this;
205   }
206   BufferWithRandomAccess& operator<<(U32LEB x) {
207     size_t before = -1;
208     WASM_UNUSED(before);
209     BYN_DEBUG(before = size(); std::cerr << "writeU32LEB: " << x.value
210                                          << " (at " << before << ")"
211                                          << std::endl;);
212     x.write(this);
213     BYN_DEBUG(for (size_t i = before; i < size(); i++) {
214       std::cerr << "  " << (int)at(i) << " (at " << i << ")\n";
215     });
216     return *this;
217   }
218   BufferWithRandomAccess& operator<<(U64LEB x) {
219     size_t before = -1;
220     WASM_UNUSED(before);
221     BYN_DEBUG(before = size(); std::cerr << "writeU64LEB: " << x.value
222                                          << " (at " << before << ")"
223                                          << std::endl;);
224     x.write(this);
225     BYN_DEBUG(for (size_t i = before; i < size(); i++) {
226       std::cerr << "  " << (int)at(i) << " (at " << i << ")\n";
227     });
228     return *this;
229   }
230   BufferWithRandomAccess& operator<<(S32LEB x) {
231     size_t before = -1;
232     WASM_UNUSED(before);
233     BYN_DEBUG(before = size(); std::cerr << "writeS32LEB: " << x.value
234                                          << " (at " << before << ")"
235                                          << std::endl;);
236     x.write(this);
237     BYN_DEBUG(for (size_t i = before; i < size(); i++) {
238       std::cerr << "  " << (int)at(i) << " (at " << i << ")\n";
239     });
240     return *this;
241   }
242   BufferWithRandomAccess& operator<<(S64LEB x) {
243     size_t before = -1;
244     WASM_UNUSED(before);
245     BYN_DEBUG(before = size(); std::cerr << "writeS64LEB: " << x.value
246                                          << " (at " << before << ")"
247                                          << std::endl;);
248     x.write(this);
249     BYN_DEBUG(for (size_t i = before; i < size(); i++) {
250       std::cerr << "  " << (int)at(i) << " (at " << i << ")\n";
251     });
252     return *this;
253   }
254 
255   BufferWithRandomAccess& operator<<(uint8_t x) { return *this << (int8_t)x; }
256   BufferWithRandomAccess& operator<<(uint16_t x) { return *this << (int16_t)x; }
257   BufferWithRandomAccess& operator<<(uint32_t x) { return *this << (int32_t)x; }
258   BufferWithRandomAccess& operator<<(uint64_t x) { return *this << (int64_t)x; }
259 
260   BufferWithRandomAccess& operator<<(float x) {
261     BYN_TRACE("writeFloat32: " << x << " (at " << size() << ")\n");
262     return *this << Literal(x).reinterpreti32();
263   }
264   BufferWithRandomAccess& operator<<(double x) {
265     BYN_TRACE("writeFloat64: " << x << " (at " << size() << ")\n");
266     return *this << Literal(x).reinterpreti64();
267   }
268 
writeAt(size_t i,uint16_t x)269   void writeAt(size_t i, uint16_t x) {
270     BYN_TRACE("backpatchInt16: " << x << " (at " << i << ")\n");
271     (*this)[i] = x & 0xff;
272     (*this)[i + 1] = x >> 8;
273   }
writeAt(size_t i,uint32_t x)274   void writeAt(size_t i, uint32_t x) {
275     BYN_TRACE("backpatchInt32: " << x << " (at " << i << ")\n");
276     (*this)[i] = x & 0xff;
277     x >>= 8;
278     (*this)[i + 1] = x & 0xff;
279     x >>= 8;
280     (*this)[i + 2] = x & 0xff;
281     x >>= 8;
282     (*this)[i + 3] = x & 0xff;
283   }
284 
285   // writes out an LEB to an arbitrary location. this writes the LEB as a full
286   // 5 bytes, the fixed amount that can easily be set aside ahead of time
writeAtFullFixedSize(size_t i,U32LEB x)287   void writeAtFullFixedSize(size_t i, U32LEB x) {
288     BYN_TRACE("backpatchU32LEB: " << x.value << " (at " << i << ")\n");
289     // fill all 5 bytes, we have to do this when backpatching
290     x.writeAt(this, i, MaxLEB32Bytes);
291   }
292   // writes out an LEB of normal size
293   // returns how many bytes were written
writeAt(size_t i,U32LEB x)294   size_t writeAt(size_t i, U32LEB x) {
295     BYN_TRACE("writeAtU32LEB: " << x.value << " (at " << i << ")\n");
296     return x.writeAt(this, i);
297   }
298 
writeTo(T & o)299   template<typename T> void writeTo(T& o) {
300     for (auto c : *this) {
301       o << c;
302     }
303   }
304 
getAsChars()305   std::vector<char> getAsChars() {
306     std::vector<char> ret;
307     ret.resize(size());
308     std::copy(begin(), end(), ret.begin());
309     return ret;
310   }
311 };
312 
313 namespace BinaryConsts {
314 
315 enum Meta { Magic = 0x6d736100, Version = 0x01 };
316 
317 enum Section {
318   User = 0,
319   Type = 1,
320   Import = 2,
321   Function = 3,
322   Table = 4,
323   Memory = 5,
324   Global = 6,
325   Export = 7,
326   Start = 8,
327   Element = 9,
328   Code = 10,
329   Data = 11,
330   DataCount = 12,
331   Event = 13
332 };
333 
334 enum SegmentFlag { IsPassive = 0x01, HasMemIndex = 0x02 };
335 
336 enum EncodedType {
337   // value_type
338   i32 = -0x1,  // 0x7f
339   i64 = -0x2,  // 0x7e
340   f32 = -0x3,  // 0x7d
341   f64 = -0x4,  // 0x7c
342   v128 = -0x5, // 0x7b
343   // function reference type
344   funcref = -0x10, // 0x70
345   // opaque host reference type
346   externref = -0x11, // 0x6f
347   // any reference type
348   anyref = -0x12, // 0x6e
349   // comparable reference type
350   eqref = -0x13, // 0x6d
351   // integer reference type
352   i31ref = -0x16, // 0x6a
353   // exception reference type
354   exnref = -0x18, // 0x68
355   // func_type form
356   Func = -0x20, // 0x60
357   // block_type
358   Empty = -0x40 // 0x40
359 };
360 
361 enum EncodedHeapType {
362   func = -0x10,    // 0x70
363   extern_ = -0x11, // 0x6f
364   any = -0x12,     // 0x6e
365   eq = -0x13,      // 0x6d
366   i31 = -0x17,     // 0x69, != i31ref
367   exn = -0x18,     // 0x68
368 };
369 
370 namespace UserSections {
371 extern const char* Name;
372 extern const char* SourceMapUrl;
373 extern const char* Dylink;
374 extern const char* Linking;
375 extern const char* Producers;
376 extern const char* TargetFeatures;
377 
378 extern const char* AtomicsFeature;
379 extern const char* BulkMemoryFeature;
380 extern const char* ExceptionHandlingFeature;
381 extern const char* MutableGlobalsFeature;
382 extern const char* TruncSatFeature;
383 extern const char* SignExtFeature;
384 extern const char* SIMD128Feature;
385 extern const char* ExceptionHandlingFeature;
386 extern const char* TailCallFeature;
387 extern const char* ReferenceTypesFeature;
388 extern const char* MultivalueFeature;
389 extern const char* GCFeature;
390 extern const char* Memory64Feature;
391 
392 enum Subsection {
393   NameModule = 0,
394   NameFunction = 1,
395   NameLocal = 2,
396   // see: https://github.com/WebAssembly/extended-name-section
397   NameLabel = 3,
398   NameType = 4,
399   NameTable = 5,
400   NameMemory = 6,
401   NameGlobal = 7,
402   NameElem = 8,
403   NameData = 9
404 };
405 
406 } // namespace UserSections
407 
408 enum ASTNodes {
409   Unreachable = 0x00,
410   Nop = 0x01,
411   Block = 0x02,
412   Loop = 0x03,
413   If = 0x04,
414   Else = 0x05,
415 
416   End = 0x0b,
417   Br = 0x0c,
418   BrIf = 0x0d,
419   BrTable = 0x0e,
420   Return = 0x0f,
421 
422   CallFunction = 0x10,
423   CallIndirect = 0x11,
424   RetCallFunction = 0x12,
425   RetCallIndirect = 0x13,
426 
427   Drop = 0x1a,
428   Select = 0x1b,
429   SelectWithType = 0x1c, // added in reference types proposal
430 
431   LocalGet = 0x20,
432   LocalSet = 0x21,
433   LocalTee = 0x22,
434   GlobalGet = 0x23,
435   GlobalSet = 0x24,
436 
437   I32LoadMem = 0x28,
438   I64LoadMem = 0x29,
439   F32LoadMem = 0x2a,
440   F64LoadMem = 0x2b,
441 
442   I32LoadMem8S = 0x2c,
443   I32LoadMem8U = 0x2d,
444   I32LoadMem16S = 0x2e,
445   I32LoadMem16U = 0x2f,
446   I64LoadMem8S = 0x30,
447   I64LoadMem8U = 0x31,
448   I64LoadMem16S = 0x32,
449   I64LoadMem16U = 0x33,
450   I64LoadMem32S = 0x34,
451   I64LoadMem32U = 0x35,
452 
453   I32StoreMem = 0x36,
454   I64StoreMem = 0x37,
455   F32StoreMem = 0x38,
456   F64StoreMem = 0x39,
457 
458   I32StoreMem8 = 0x3a,
459   I32StoreMem16 = 0x3b,
460   I64StoreMem8 = 0x3c,
461   I64StoreMem16 = 0x3d,
462   I64StoreMem32 = 0x3e,
463 
464   MemorySize = 0x3f,
465   MemoryGrow = 0x40,
466 
467   I32Const = 0x41,
468   I64Const = 0x42,
469   F32Const = 0x43,
470   F64Const = 0x44,
471 
472   I32EqZ = 0x45,
473   I32Eq = 0x46,
474   I32Ne = 0x47,
475   I32LtS = 0x48,
476   I32LtU = 0x49,
477   I32GtS = 0x4a,
478   I32GtU = 0x4b,
479   I32LeS = 0x4c,
480   I32LeU = 0x4d,
481   I32GeS = 0x4e,
482   I32GeU = 0x4f,
483   I64EqZ = 0x50,
484   I64Eq = 0x51,
485   I64Ne = 0x52,
486   I64LtS = 0x53,
487   I64LtU = 0x54,
488   I64GtS = 0x55,
489   I64GtU = 0x56,
490   I64LeS = 0x57,
491   I64LeU = 0x58,
492   I64GeS = 0x59,
493   I64GeU = 0x5a,
494   F32Eq = 0x5b,
495   F32Ne = 0x5c,
496   F32Lt = 0x5d,
497   F32Gt = 0x5e,
498   F32Le = 0x5f,
499   F32Ge = 0x60,
500   F64Eq = 0x61,
501   F64Ne = 0x62,
502   F64Lt = 0x63,
503   F64Gt = 0x64,
504   F64Le = 0x65,
505   F64Ge = 0x66,
506 
507   I32Clz = 0x67,
508   I32Ctz = 0x68,
509   I32Popcnt = 0x69,
510   I32Add = 0x6a,
511   I32Sub = 0x6b,
512   I32Mul = 0x6c,
513   I32DivS = 0x6d,
514   I32DivU = 0x6e,
515   I32RemS = 0x6f,
516   I32RemU = 0x70,
517   I32And = 0x71,
518   I32Or = 0x72,
519   I32Xor = 0x73,
520   I32Shl = 0x74,
521   I32ShrS = 0x75,
522   I32ShrU = 0x76,
523   I32RotL = 0x77,
524   I32RotR = 0x78,
525 
526   I64Clz = 0x79,
527   I64Ctz = 0x7a,
528   I64Popcnt = 0x7b,
529   I64Add = 0x7c,
530   I64Sub = 0x7d,
531   I64Mul = 0x7e,
532   I64DivS = 0x7f,
533   I64DivU = 0x80,
534   I64RemS = 0x81,
535   I64RemU = 0x82,
536   I64And = 0x83,
537   I64Or = 0x84,
538   I64Xor = 0x85,
539   I64Shl = 0x86,
540   I64ShrS = 0x87,
541   I64ShrU = 0x88,
542   I64RotL = 0x89,
543   I64RotR = 0x8a,
544 
545   F32Abs = 0x8b,
546   F32Neg = 0x8c,
547   F32Ceil = 0x8d,
548   F32Floor = 0x8e,
549   F32Trunc = 0x8f,
550   F32NearestInt = 0x90,
551   F32Sqrt = 0x91,
552   F32Add = 0x92,
553   F32Sub = 0x93,
554   F32Mul = 0x94,
555   F32Div = 0x95,
556   F32Min = 0x96,
557   F32Max = 0x97,
558   F32CopySign = 0x98,
559 
560   F64Abs = 0x99,
561   F64Neg = 0x9a,
562   F64Ceil = 0x9b,
563   F64Floor = 0x9c,
564   F64Trunc = 0x9d,
565   F64NearestInt = 0x9e,
566   F64Sqrt = 0x9f,
567   F64Add = 0xa0,
568   F64Sub = 0xa1,
569   F64Mul = 0xa2,
570   F64Div = 0xa3,
571   F64Min = 0xa4,
572   F64Max = 0xa5,
573   F64CopySign = 0xa6,
574 
575   I32WrapI64 = 0xa7,
576   I32STruncF32 = 0xa8,
577   I32UTruncF32 = 0xa9,
578   I32STruncF64 = 0xaa,
579   I32UTruncF64 = 0xab,
580   I64SExtendI32 = 0xac,
581   I64UExtendI32 = 0xad,
582   I64STruncF32 = 0xae,
583   I64UTruncF32 = 0xaf,
584   I64STruncF64 = 0xb0,
585   I64UTruncF64 = 0xb1,
586   F32SConvertI32 = 0xb2,
587   F32UConvertI32 = 0xb3,
588   F32SConvertI64 = 0xb4,
589   F32UConvertI64 = 0xb5,
590   F32DemoteI64 = 0xb6,
591   F64SConvertI32 = 0xb7,
592   F64UConvertI32 = 0xb8,
593   F64SConvertI64 = 0xb9,
594   F64UConvertI64 = 0xba,
595   F64PromoteF32 = 0xbb,
596 
597   I32ReinterpretF32 = 0xbc,
598   I64ReinterpretF64 = 0xbd,
599   F32ReinterpretI32 = 0xbe,
600   F64ReinterpretI64 = 0xbf,
601 
602   I32ExtendS8 = 0xc0,
603   I32ExtendS16 = 0xc1,
604   I64ExtendS8 = 0xc2,
605   I64ExtendS16 = 0xc3,
606   I64ExtendS32 = 0xc4,
607 
608   // prefixes
609 
610   GCPrefix = 0xfb,
611   MiscPrefix = 0xfc,
612   SIMDPrefix = 0xfd,
613   AtomicPrefix = 0xfe,
614 
615   // atomic opcodes
616 
617   AtomicNotify = 0x00,
618   I32AtomicWait = 0x01,
619   I64AtomicWait = 0x02,
620   AtomicFence = 0x03,
621 
622   I32AtomicLoad = 0x10,
623   I64AtomicLoad = 0x11,
624   I32AtomicLoad8U = 0x12,
625   I32AtomicLoad16U = 0x13,
626   I64AtomicLoad8U = 0x14,
627   I64AtomicLoad16U = 0x15,
628   I64AtomicLoad32U = 0x16,
629   I32AtomicStore = 0x17,
630   I64AtomicStore = 0x18,
631   I32AtomicStore8 = 0x19,
632   I32AtomicStore16 = 0x1a,
633   I64AtomicStore8 = 0x1b,
634   I64AtomicStore16 = 0x1c,
635   I64AtomicStore32 = 0x1d,
636 
637   AtomicRMWOps_Begin = 0x1e,
638   I32AtomicRMWAdd = 0x1e,
639   I64AtomicRMWAdd = 0x1f,
640   I32AtomicRMWAdd8U = 0x20,
641   I32AtomicRMWAdd16U = 0x21,
642   I64AtomicRMWAdd8U = 0x22,
643   I64AtomicRMWAdd16U = 0x23,
644   I64AtomicRMWAdd32U = 0x24,
645   I32AtomicRMWSub = 0x25,
646   I64AtomicRMWSub = 0x26,
647   I32AtomicRMWSub8U = 0x27,
648   I32AtomicRMWSub16U = 0x28,
649   I64AtomicRMWSub8U = 0x29,
650   I64AtomicRMWSub16U = 0x2a,
651   I64AtomicRMWSub32U = 0x2b,
652   I32AtomicRMWAnd = 0x2c,
653   I64AtomicRMWAnd = 0x2d,
654   I32AtomicRMWAnd8U = 0x2e,
655   I32AtomicRMWAnd16U = 0x2f,
656   I64AtomicRMWAnd8U = 0x30,
657   I64AtomicRMWAnd16U = 0x31,
658   I64AtomicRMWAnd32U = 0x32,
659   I32AtomicRMWOr = 0x33,
660   I64AtomicRMWOr = 0x34,
661   I32AtomicRMWOr8U = 0x35,
662   I32AtomicRMWOr16U = 0x36,
663   I64AtomicRMWOr8U = 0x37,
664   I64AtomicRMWOr16U = 0x38,
665   I64AtomicRMWOr32U = 0x39,
666   I32AtomicRMWXor = 0x3a,
667   I64AtomicRMWXor = 0x3b,
668   I32AtomicRMWXor8U = 0x3c,
669   I32AtomicRMWXor16U = 0x3d,
670   I64AtomicRMWXor8U = 0x3e,
671   I64AtomicRMWXor16U = 0x3f,
672   I64AtomicRMWXor32U = 0x40,
673   I32AtomicRMWXchg = 0x41,
674   I64AtomicRMWXchg = 0x42,
675   I32AtomicRMWXchg8U = 0x43,
676   I32AtomicRMWXchg16U = 0x44,
677   I64AtomicRMWXchg8U = 0x45,
678   I64AtomicRMWXchg16U = 0x46,
679   I64AtomicRMWXchg32U = 0x47,
680   AtomicRMWOps_End = 0x47,
681 
682   AtomicCmpxchgOps_Begin = 0x48,
683   I32AtomicCmpxchg = 0x48,
684   I64AtomicCmpxchg = 0x49,
685   I32AtomicCmpxchg8U = 0x4a,
686   I32AtomicCmpxchg16U = 0x4b,
687   I64AtomicCmpxchg8U = 0x4c,
688   I64AtomicCmpxchg16U = 0x4d,
689   I64AtomicCmpxchg32U = 0x4e,
690   AtomicCmpxchgOps_End = 0x4e,
691 
692   // truncsat opcodes
693 
694   I32STruncSatF32 = 0x00,
695   I32UTruncSatF32 = 0x01,
696   I32STruncSatF64 = 0x02,
697   I32UTruncSatF64 = 0x03,
698   I64STruncSatF32 = 0x04,
699   I64UTruncSatF32 = 0x05,
700   I64STruncSatF64 = 0x06,
701   I64UTruncSatF64 = 0x07,
702 
703   // SIMD opcodes
704 
705   V128Load = 0x00,
706   I16x8LoadExtSVec8x8 = 0x01,
707   I16x8LoadExtUVec8x8 = 0x02,
708   I32x4LoadExtSVec16x4 = 0x03,
709   I32x4LoadExtUVec16x4 = 0x04,
710   I64x2LoadExtSVec32x2 = 0x05,
711   I64x2LoadExtUVec32x2 = 0x06,
712   V8x16LoadSplat = 0x07,
713   V16x8LoadSplat = 0x08,
714   V32x4LoadSplat = 0x09,
715   V64x2LoadSplat = 0x0a,
716   V128Store = 0x0b,
717 
718   V128Const = 0x0c,
719   V8x16Shuffle = 0x0d,
720   V8x16Swizzle = 0x0e,
721 
722   I8x16Splat = 0x0f,
723   I16x8Splat = 0x10,
724   I32x4Splat = 0x11,
725   I64x2Splat = 0x12,
726   F32x4Splat = 0x13,
727   F64x2Splat = 0x14,
728 
729   I8x16ExtractLaneS = 0x15,
730   I8x16ExtractLaneU = 0x16,
731   I8x16ReplaceLane = 0x17,
732   I16x8ExtractLaneS = 0x18,
733   I16x8ExtractLaneU = 0x19,
734   I16x8ReplaceLane = 0x1a,
735   I32x4ExtractLane = 0x1b,
736   I32x4ReplaceLane = 0x1c,
737   I64x2ExtractLane = 0x1d,
738   I64x2ReplaceLane = 0x1e,
739   F32x4ExtractLane = 0x1f,
740   F32x4ReplaceLane = 0x20,
741   F64x2ExtractLane = 0x21,
742   F64x2ReplaceLane = 0x22,
743 
744   I8x16Eq = 0x23,
745   I8x16Ne = 0x24,
746   I8x16LtS = 0x25,
747   I8x16LtU = 0x26,
748   I8x16GtS = 0x27,
749   I8x16GtU = 0x28,
750   I8x16LeS = 0x29,
751   I8x16LeU = 0x2a,
752   I8x16GeS = 0x2b,
753   I8x16GeU = 0x2c,
754   I16x8Eq = 0x2d,
755   I16x8Ne = 0x2e,
756   I16x8LtS = 0x2f,
757   I16x8LtU = 0x30,
758   I16x8GtS = 0x31,
759   I16x8GtU = 0x32,
760   I16x8LeS = 0x33,
761   I16x8LeU = 0x34,
762   I16x8GeS = 0x35,
763   I16x8GeU = 0x36,
764   I32x4Eq = 0x37,
765   I32x4Ne = 0x38,
766   I32x4LtS = 0x39,
767   I32x4LtU = 0x3a,
768   I32x4GtS = 0x3b,
769   I32x4GtU = 0x3c,
770   I32x4LeS = 0x3d,
771   I32x4LeU = 0x3e,
772   I32x4GeS = 0x3f,
773   I32x4GeU = 0x40,
774   F32x4Eq = 0x41,
775   F32x4Ne = 0x42,
776   F32x4Lt = 0x43,
777   F32x4Gt = 0x44,
778   F32x4Le = 0x45,
779   F32x4Ge = 0x46,
780   F64x2Eq = 0x47,
781   F64x2Ne = 0x48,
782   F64x2Lt = 0x49,
783   F64x2Gt = 0x4a,
784   F64x2Le = 0x4b,
785   F64x2Ge = 0x4c,
786 
787   V128Not = 0x4d,
788   V128And = 0x4e,
789   V128AndNot = 0x4f,
790   V128Or = 0x50,
791   V128Xor = 0x51,
792   V128Bitselect = 0x52,
793 
794   I8x16Abs = 0x60,
795   I8x16Neg = 0x61,
796   I8x16AnyTrue = 0x62,
797   I8x16AllTrue = 0x63,
798   I8x16Bitmask = 0x64,
799   I8x16NarrowSI16x8 = 0x65,
800   I8x16NarrowUI16x8 = 0x66,
801   I8x16Shl = 0x6b,
802   I8x16ShrS = 0x6c,
803   I8x16ShrU = 0x6d,
804   I8x16Add = 0x6e,
805   I8x16AddSatS = 0x6f,
806   I8x16AddSatU = 0x70,
807   I8x16Sub = 0x71,
808   I8x16SubSatS = 0x72,
809   I8x16SubSatU = 0x73,
810   I8x16Mul = 0x75,
811   I8x16MinS = 0x76,
812   I8x16MinU = 0x77,
813   I8x16MaxS = 0x78,
814   I8x16MaxU = 0x79,
815   I8x16AvgrU = 0x7b,
816 
817   I16x8Abs = 0x80,
818   I16x8Neg = 0x81,
819   I16x8AnyTrue = 0x82,
820   I16x8AllTrue = 0x83,
821   I16x8Bitmask = 0x84,
822   I16x8NarrowSI32x4 = 0x85,
823   I16x8NarrowUI32x4 = 0x86,
824   I16x8WidenLowSI8x16 = 0x87,
825   I16x8WidenHighSI8x16 = 0x88,
826   I16x8WidenLowUI8x16 = 0x89,
827   I16x8WidenHighUI8x16 = 0x8a,
828   I16x8Shl = 0x8b,
829   I16x8ShrS = 0x8c,
830   I16x8ShrU = 0x8d,
831   I16x8Add = 0x8e,
832   I16x8AddSatS = 0x8f,
833   I16x8AddSatU = 0x90,
834   I16x8Sub = 0x91,
835   I16x8SubSatS = 0x92,
836   I16x8SubSatU = 0x93,
837   I16x8Mul = 0x95,
838   I16x8MinS = 0x96,
839   I16x8MinU = 0x97,
840   I16x8MaxS = 0x98,
841   I16x8MaxU = 0x99,
842   I16x8AvgrU = 0x9b,
843 
844   I32x4Abs = 0xa0,
845   I32x4Neg = 0xa1,
846   I32x4AnyTrue = 0xa2,
847   I32x4AllTrue = 0xa3,
848   I32x4Bitmask = 0xa4,
849   I32x4WidenLowSI16x8 = 0xa7,
850   I32x4WidenHighSI16x8 = 0xa8,
851   I32x4WidenLowUI16x8 = 0xa9,
852   I32x4WidenHighUI16x8 = 0xaa,
853   I32x4Shl = 0xab,
854   I32x4ShrS = 0xac,
855   I32x4ShrU = 0xad,
856   I32x4Add = 0xae,
857   I32x4Sub = 0xb1,
858   I32x4Mul = 0xb5,
859   I32x4MinS = 0xb6,
860   I32x4MinU = 0xb7,
861   I32x4MaxS = 0xb8,
862   I32x4MaxU = 0xb9,
863   I32x4DotSVecI16x8 = 0xba,
864 
865   I64x2Neg = 0xc1,
866   I64x2AnyTrue = 0xc2,
867   I64x2AllTrue = 0xc3,
868   I64x2Shl = 0xcb,
869   I64x2ShrS = 0xcc,
870   I64x2ShrU = 0xcd,
871   I64x2Add = 0xce,
872   I64x2Sub = 0xd1,
873   I64x2Mul = 0xd5,
874 
875   F32x4Abs = 0xe0,
876   F32x4Neg = 0xe1,
877   F32x4Sqrt = 0xe3,
878   F32x4Add = 0xe4,
879   F32x4Sub = 0xe5,
880   F32x4Mul = 0xe6,
881   F32x4Div = 0xe7,
882   F32x4Min = 0xe8,
883   F32x4Max = 0xe9,
884   F32x4PMin = 0xea,
885   F32x4PMax = 0xeb,
886 
887   F32x4Ceil = 0xd8,
888   F32x4Floor = 0xd9,
889   F32x4Trunc = 0xda,
890   F32x4Nearest = 0xdb,
891   F64x2Ceil = 0xdc,
892   F64x2Floor = 0xdd,
893   F64x2Trunc = 0xde,
894   F64x2Nearest = 0xdf,
895 
896   F64x2Abs = 0xec,
897   F64x2Neg = 0xed,
898   F64x2Sqrt = 0xef,
899   F64x2Add = 0xf0,
900   F64x2Sub = 0xf1,
901   F64x2Mul = 0xf2,
902   F64x2Div = 0xf3,
903   F64x2Min = 0xf4,
904   F64x2Max = 0xf5,
905   F64x2PMin = 0xf6,
906   F64x2PMax = 0xf7,
907 
908   I32x4TruncSatSF32x4 = 0xf8,
909   I32x4TruncSatUF32x4 = 0xf9,
910   F32x4ConvertSI32x4 = 0xfa,
911   F32x4ConvertUI32x4 = 0xfb,
912 
913   V128Load32Zero = 0xfc,
914   V128Load64Zero = 0xfd,
915 
916   F32x4QFMA = 0xb4,
917   F32x4QFMS = 0xd4,
918   F64x2QFMA = 0xfe,
919   F64x2QFMS = 0xff,
920 
921   I64x2TruncSatSF64x2 = 0x0100,
922   I64x2TruncSatUF64x2 = 0x0101,
923   F64x2ConvertSI64x2 = 0x0102,
924   F64x2ConvertUI64x2 = 0x0103,
925 
926   // bulk memory opcodes
927 
928   MemoryInit = 0x08,
929   DataDrop = 0x09,
930   MemoryCopy = 0x0a,
931   MemoryFill = 0x0b,
932 
933   // reference types opcodes
934 
935   RefNull = 0xd0,
936   RefIsNull = 0xd1,
937   RefFunc = 0xd2,
938 
939   // exception handling opcodes
940 
941   Try = 0x06,
942   Catch = 0x07,
943   Throw = 0x08,
944   Rethrow = 0x09,
945   BrOnExn = 0x0a,
946 
947   // gc opcodes
948 
949   RefEq = 0xd5,
950   StructNewWithRtt = 0x01,
951   StructNewDefaultWithRtt = 0x02,
952   StructGet = 0x03,
953   StructGetS = 0x04,
954   StructGetU = 0x05,
955   StructSet = 0x06,
956   ArrayNewWithRtt = 0x11,
957   ArrayNewDefaultWithRtt = 0x12,
958   ArrayGet = 0x13,
959   ArrayGetS = 0x14,
960   ArrayGetU = 0x15,
961   ArraySet = 0x16,
962   ArrayLen = 0x17,
963   I31New = 0x20,
964   I31GetS = 0x21,
965   I31GetU = 0x22,
966   RttCanon = 0x30,
967   RttSub = 0x31,
968   RefTest = 0x40,
969   RefCast = 0x41,
970   BrOnCast = 0x42
971 };
972 
973 enum MemoryAccess {
974   Offset = 0x10,    // bit 4
975   Alignment = 0x80, // bit 7
976   NaturalAlignment = 0
977 };
978 
979 enum MemoryFlags { HasMaximum = 1 << 0, IsShared = 1 << 1, Is64 = 1 << 2 };
980 
981 enum FeaturePrefix {
982   FeatureUsed = '+',
983   FeatureRequired = '=',
984   FeatureDisallowed = '-'
985 };
986 
987 } // namespace BinaryConsts
988 
binaryType(Type type)989 inline S32LEB binaryType(Type type) {
990   int ret = 0;
991   TODO_SINGLE_COMPOUND(type);
992   switch (type.getBasic()) {
993     // None only used for block signatures. TODO: Separate out?
994     case Type::none:
995       ret = BinaryConsts::EncodedType::Empty;
996       break;
997     case Type::i32:
998       ret = BinaryConsts::EncodedType::i32;
999       break;
1000     case Type::i64:
1001       ret = BinaryConsts::EncodedType::i64;
1002       break;
1003     case Type::f32:
1004       ret = BinaryConsts::EncodedType::f32;
1005       break;
1006     case Type::f64:
1007       ret = BinaryConsts::EncodedType::f64;
1008       break;
1009     case Type::v128:
1010       ret = BinaryConsts::EncodedType::v128;
1011       break;
1012     case Type::funcref:
1013       ret = BinaryConsts::EncodedType::funcref;
1014       break;
1015     case Type::externref:
1016       ret = BinaryConsts::EncodedType::externref;
1017       break;
1018     case Type::exnref:
1019       ret = BinaryConsts::EncodedType::exnref;
1020       break;
1021     case Type::anyref:
1022       ret = BinaryConsts::EncodedType::anyref;
1023       break;
1024     case Type::eqref:
1025       ret = BinaryConsts::EncodedType::eqref;
1026       break;
1027     case Type::i31ref:
1028       ret = BinaryConsts::EncodedType::i31ref;
1029       break;
1030     case Type::unreachable:
1031       WASM_UNREACHABLE("unexpected type");
1032   }
1033   return S32LEB(ret);
1034 }
1035 
binaryHeapType(HeapType type)1036 inline S32LEB binaryHeapType(HeapType type) {
1037   int ret = 0;
1038   switch (type.kind) {
1039     case HeapType::FuncKind:
1040       ret = BinaryConsts::EncodedHeapType::func;
1041       break;
1042     case HeapType::ExternKind:
1043       ret = BinaryConsts::EncodedHeapType::extern_;
1044       break;
1045     case HeapType::ExnKind:
1046       ret = BinaryConsts::EncodedHeapType::exn;
1047       break;
1048     case HeapType::AnyKind:
1049       ret = BinaryConsts::EncodedHeapType::any;
1050       break;
1051     case HeapType::EqKind:
1052       ret = BinaryConsts::EncodedHeapType::eq;
1053       break;
1054     case HeapType::I31Kind:
1055       ret = BinaryConsts::EncodedHeapType::i31;
1056       break;
1057     case HeapType::SignatureKind:
1058     case HeapType::StructKind:
1059     case HeapType::ArrayKind:
1060       WASM_UNREACHABLE("TODO: compound GC types");
1061   }
1062   return S32LEB(ret); // TODO: Actually encoded as s33
1063 }
1064 
1065 // Writes out wasm to the binary format
1066 
1067 class WasmBinaryWriter {
1068   // Computes the indexes in a wasm binary, i.e., with function imports
1069   // and function implementations sharing a single index space, etc.,
1070   // and with the imports first (the Module's functions and globals
1071   // arrays are not assumed to be in a particular order, so we can't
1072   // just use them directly).
1073   struct BinaryIndexes {
1074     std::unordered_map<Name, Index> functionIndexes;
1075     std::unordered_map<Name, Index> eventIndexes;
1076     std::unordered_map<Name, Index> globalIndexes;
1077 
BinaryIndexesBinaryIndexes1078     BinaryIndexes(Module& wasm) {
1079       auto addIndexes = [&](auto& source, auto& indexes) {
1080         auto addIndex = [&](auto* curr) {
1081           auto index = indexes.size();
1082           indexes[curr->name] = index;
1083         };
1084         for (auto& curr : source) {
1085           if (curr->imported()) {
1086             addIndex(curr.get());
1087           }
1088         }
1089         for (auto& curr : source) {
1090           if (!curr->imported()) {
1091             addIndex(curr.get());
1092           }
1093         }
1094       };
1095       addIndexes(wasm.functions, functionIndexes);
1096       addIndexes(wasm.events, eventIndexes);
1097 
1098       // Globals may have tuple types in the IR, in which case they lower to
1099       // multiple globals, one for each tuple element, in the binary. Tuple
1100       // globals therefore occupy multiple binary indices, and we have to take
1101       // that into account when calculating indices.
1102       Index globalCount = 0;
1103       auto addGlobal = [&](auto* curr) {
1104         globalIndexes[curr->name] = globalCount;
1105         globalCount += curr->type.size();
1106       };
1107       for (auto& curr : wasm.globals) {
1108         if (curr->imported()) {
1109           addGlobal(curr.get());
1110         }
1111       }
1112       for (auto& curr : wasm.globals) {
1113         if (!curr->imported()) {
1114           addGlobal(curr.get());
1115         }
1116       }
1117     }
1118   };
1119 
1120 public:
WasmBinaryWriter(Module * input,BufferWithRandomAccess & o)1121   WasmBinaryWriter(Module* input, BufferWithRandomAccess& o)
1122     : wasm(input), o(o), indexes(*input) {
1123     prepare();
1124   }
1125 
1126   // locations in the output binary for the various parts of the module
1127   struct TableOfContents {
1128     struct Entry {
1129       Name name;
1130       size_t offset; // where the entry starts
1131       size_t size;   // the size of the entry
EntryTableOfContents::Entry1132       Entry(Name name, size_t offset, size_t size)
1133         : name(name), offset(offset), size(size) {}
1134     };
1135     std::vector<Entry> functionBodies;
1136   } tableOfContents;
1137 
setNamesSection(bool set)1138   void setNamesSection(bool set) { debugInfo = set; }
setSourceMap(std::ostream * set,std::string url)1139   void setSourceMap(std::ostream* set, std::string url) {
1140     sourceMap = set;
1141     sourceMapUrl = url;
1142   }
setSymbolMap(std::string set)1143   void setSymbolMap(std::string set) { symbolMap = set; }
1144 
1145   void write();
1146   void writeHeader();
1147   int32_t writeU32LEBPlaceholder();
1148   void writeResizableLimits(
1149     Address initial, Address maximum, bool hasMaximum, bool shared, bool is64);
1150   template<typename T> int32_t startSection(T code);
1151   void finishSection(int32_t start);
1152   int32_t startSubsection(BinaryConsts::UserSections::Subsection code);
1153   void finishSubsection(int32_t start);
1154   void writeStart();
1155   void writeMemory();
1156   void writeTypes();
1157   void writeImports();
1158 
1159   void writeFunctionSignatures();
1160   void writeExpression(Expression* curr);
1161   void writeFunctions();
1162   void writeGlobals();
1163   void writeExports();
1164   void writeDataCount();
1165   void writeDataSegments();
1166   void writeEvents();
1167 
1168   uint32_t getFunctionIndex(Name name) const;
1169   uint32_t getGlobalIndex(Name name) const;
1170   uint32_t getEventIndex(Name name) const;
1171   uint32_t getTypeIndex(Signature sig) const;
1172 
1173   void writeFunctionTableDeclaration();
1174   void writeTableElements();
1175   void writeNames();
1176   void writeSourceMapUrl();
1177   void writeSymbolMap();
1178   void writeLateUserSections();
1179   void writeUserSection(const UserSection& section);
1180   void writeFeaturesSection();
1181   void writeDylinkSection();
1182 
1183   void initializeDebugInfo();
1184   void writeSourceMapProlog();
1185   void writeSourceMapEpilog();
1186   void writeDebugLocation(const Function::DebugLocation& loc);
1187   void writeDebugLocation(Expression* curr, Function* func);
1188   void writeDebugLocationEnd(Expression* curr, Function* func);
1189   void writeExtraDebugLocation(Expression* curr,
1190                                Function* func,
1191                                BinaryLocations::DelimiterId id);
1192 
1193   // helpers
1194   void writeInlineString(const char* name);
1195   void writeEscapedName(const char* name);
1196   void writeInlineBuffer(const char* data, size_t size);
1197 
1198   struct Buffer {
1199     const char* data;
1200     size_t size;
1201     size_t pointerLocation;
BufferBuffer1202     Buffer(const char* data, size_t size, size_t pointerLocation)
1203       : data(data), size(size), pointerLocation(pointerLocation) {}
1204   };
1205 
1206   std::vector<Buffer> buffersToWrite;
1207 
1208   void emitBuffer(const char* data, size_t size);
1209   void emitString(const char* str);
1210   void finishUp();
1211 
getModule()1212   Module* getModule() { return wasm; }
1213 
1214 private:
1215   Module* wasm;
1216   BufferWithRandomAccess& o;
1217   BinaryIndexes indexes;
1218   std::unordered_map<Signature, Index> typeIndices;
1219   std::vector<Signature> types;
1220 
1221   bool debugInfo = true;
1222   std::ostream* sourceMap = nullptr;
1223   std::string sourceMapUrl;
1224   std::string symbolMap;
1225 
1226   MixedArena allocator;
1227 
1228   // storage of source map locations until the section is placed at its final
1229   // location (shrinking LEBs may cause changes there)
1230   std::vector<std::pair<size_t, const Function::DebugLocation*>>
1231     sourceMapLocations;
1232   size_t sourceMapLocationsSizeAtSectionStart;
1233   Function::DebugLocation lastDebugLocation;
1234 
1235   std::unique_ptr<ImportInfo> importInfo;
1236 
1237   // General debugging info: track locations as we write.
1238   BinaryLocations binaryLocations;
1239   size_t binaryLocationsSizeAtSectionStart;
1240   // Track the expressions that we added for the current function being
1241   // written, so that we can update those specific binary locations when
1242   // the function is written out.
1243   std::vector<Expression*> binaryLocationTrackedExpressionsForFunc;
1244 
1245   void prepare();
1246 };
1247 
1248 class WasmBinaryBuilder {
1249   Module& wasm;
1250   MixedArena& allocator;
1251   const std::vector<char>& input;
1252   std::istream* sourceMap;
1253   std::pair<uint32_t, Function::DebugLocation> nextDebugLocation;
1254   bool DWARF = false;
1255 
1256   size_t pos = 0;
1257   Index startIndex = -1;
1258   std::set<Function::DebugLocation> debugLocation;
1259   size_t codeSectionLocation;
1260 
1261   std::set<BinaryConsts::Section> seenSections;
1262 
1263   // All signatures present in the type section
1264   std::vector<Signature> signatures;
1265 
1266 public:
WasmBinaryBuilder(Module & wasm,const std::vector<char> & input)1267   WasmBinaryBuilder(Module& wasm, const std::vector<char>& input)
1268     : wasm(wasm), allocator(wasm.allocator), input(input), sourceMap(nullptr),
1269       nextDebugLocation(0, {0, 0, 0}), debugLocation() {}
1270 
setDWARF(bool value)1271   void setDWARF(bool value) { DWARF = value; }
1272   void read();
1273   void readUserSection(size_t payloadLen);
1274 
more()1275   bool more() { return pos < input.size(); }
1276 
1277   uint8_t getInt8();
1278   uint16_t getInt16();
1279   uint32_t getInt32();
1280   uint64_t getInt64();
1281   uint8_t getLaneIndex(size_t lanes);
1282   // it is unsafe to return a float directly, due to ABI issues with the
1283   // signalling bit
1284   Literal getFloat32Literal();
1285   Literal getFloat64Literal();
1286   Literal getVec128Literal();
1287   uint32_t getU32LEB();
1288   uint64_t getU64LEB();
1289   int32_t getS32LEB();
1290   int64_t getS64LEB();
1291   Type getType();
1292   HeapType getHeapType();
1293   Type getConcreteType();
1294   Name getInlineString();
1295   void verifyInt8(int8_t x);
1296   void verifyInt16(int16_t x);
1297   void verifyInt32(int32_t x);
1298   void verifyInt64(int64_t x);
1299   void ungetInt8();
1300   void readHeader();
1301   void readStart();
1302   void readMemory();
1303   void readSignatures();
1304 
1305   // gets a name in the combined import+defined space
1306   Name getFunctionName(Index index);
1307   Name getGlobalName(Index index);
1308   Name getEventName(Index index);
1309 
1310   void getResizableLimits(Address& initial,
1311                           Address& max,
1312                           bool& shared,
1313                           Type& indexType,
1314                           Address defaultIfNoMax);
1315   void readImports();
1316 
1317   // The signatures of each function, given in the function section
1318   std::vector<Signature> functionSignatures;
1319 
1320   void readFunctionSignatures();
1321   size_t nextLabel;
1322 
1323   Name getNextLabel();
1324 
1325   // We read functions and globals before we know their names, so we need to
1326   // backpatch the names later
1327 
1328   // we store functions here before wasm.addFunction after we know their names
1329   std::vector<Function*> functions;
1330   // we store function imports here before wasm.addFunctionImport after we know
1331   // their names
1332   std::vector<Function*> functionImports;
1333   // at index i we have all refs to the function i
1334   std::map<Index, std::vector<Expression*>> functionRefs;
1335   Function* currFunction = nullptr;
1336   // before we see a function (like global init expressions), there is no end of
1337   // function to check
1338   Index endOfFunction = -1;
1339 
1340   // we store globals here before wasm.addGlobal after we know their names
1341   std::vector<Global*> globals;
1342   // we store global imports here before wasm.addGlobalImport after we know
1343   // their names
1344   std::vector<Global*> globalImports;
1345   // at index i we have all refs to the global i
1346   std::map<Index, std::vector<Expression*>> globalRefs;
1347 
1348   // Throws a parsing error if we are not in a function context
1349   void requireFunctionContext(const char* error);
1350 
1351   void readFunctions();
1352 
1353   std::map<Export*, Index> exportIndices;
1354   std::vector<Export*> exportOrder;
1355   void readExports();
1356 
1357   Expression* readExpression();
1358   void readGlobals();
1359 
1360   struct BreakTarget {
1361     Name name;
1362     Type type;
BreakTargetBreakTarget1363     BreakTarget(Name name, Type type) : name(name), type(type) {}
1364   };
1365   std::vector<BreakTarget> breakStack;
1366   // the names that breaks target. this lets us know if a block has breaks to it
1367   // or not.
1368   std::unordered_set<Name> breakTargetNames;
1369 
1370   std::vector<Expression*> expressionStack;
1371 
1372   // Control flow structure parsing: these have not just the normal binary
1373   // data for an instruction, but also some bytes later on like "end" or "else".
1374   // We must be aware of the connection between those things, for debug info.
1375   std::vector<Expression*> controlFlowStack;
1376 
1377   // Called when we parse the beginning of a control flow structure.
1378   void startControlFlow(Expression* curr);
1379 
1380   // Called when we parse a later part of a control flow structure, like "end"
1381   // or "else".
1382   void continueControlFlow(BinaryLocations::DelimiterId id, BinaryLocation pos);
1383 
1384   // set when we know code is unreachable in the sense of the wasm spec: we are
1385   // in a block and after an unreachable element. this helps parse stacky wasm
1386   // code, which can be unsuitable for our IR when unreachable.
1387   bool unreachableInTheWasmSense;
1388 
1389   // set when the current code being processed will not be emitted in the
1390   // output, which is the case when it is literally unreachable, for example,
1391   // (block $a
1392   //   (unreachable)
1393   //   (block $b
1394   //     ;; code here is reachable in the wasm sense, even though $b as a whole
1395   //     ;; is not
1396   //     (unreachable)
1397   //     ;; code here is unreachable in the wasm sense
1398   //   )
1399   // )
1400   bool willBeIgnored;
1401 
1402   BinaryConsts::ASTNodes lastSeparator = BinaryConsts::End;
1403 
1404   // process a block-type scope, until an end or else marker, or the end of the
1405   // function
1406   void processExpressions();
1407   void skipUnreachableCode();
1408 
1409   void pushExpression(Expression* curr);
1410   Expression* popExpression();
1411   Expression* popNonVoidExpression();
1412   Expression* popTuple(size_t numElems);
1413   Expression* popTypedExpression(Type type);
1414 
1415   void validateBinary(); // validations that cannot be performed on the Module
1416   void processNames();
1417 
1418   size_t dataCount = 0;
1419   bool hasDataCount = false;
1420 
1421   void readDataSegments();
1422   void readDataCount();
1423 
1424   std::map<Index, std::vector<Index>> functionTable;
1425 
1426   void readFunctionTableDeclaration();
1427   void readTableElements();
1428 
1429   void readEvents();
1430 
1431   static Name escape(Name name);
1432   void readNames(size_t);
1433   void readFeatures(size_t);
1434   void readDylink(size_t);
1435 
1436   // Debug information reading helpers
setDebugLocations(std::istream * sourceMap_)1437   void setDebugLocations(std::istream* sourceMap_) { sourceMap = sourceMap_; }
1438   std::unordered_map<std::string, Index> debugInfoFileIndices;
1439   void readNextDebugLocation();
1440   void readSourceMapHeader();
1441 
1442   void handleBrOnExnNotTaken(Expression* curr);
1443 
1444   // AST reading
1445   int depth = 0; // only for debugging
1446 
1447   BinaryConsts::ASTNodes readExpression(Expression*& curr);
1448   void pushBlockElements(Block* curr, Type type, size_t start);
1449   void visitBlock(Block* curr);
1450 
1451   // Gets a block of expressions. If it's just one, return that singleton.
1452   Expression* getBlockOrSingleton(Type type);
1453 
1454   void visitIf(If* curr);
1455   void visitLoop(Loop* curr);
1456   BreakTarget getBreakTarget(int32_t offset);
1457   void visitBreak(Break* curr, uint8_t code);
1458   void visitSwitch(Switch* curr);
1459 
1460   void visitCall(Call* curr);
1461   void visitCallIndirect(CallIndirect* curr);
1462   void visitLocalGet(LocalGet* curr);
1463   void visitLocalSet(LocalSet* curr, uint8_t code);
1464   void visitGlobalGet(GlobalGet* curr);
1465   void visitGlobalSet(GlobalSet* curr);
1466   void readMemoryAccess(Address& alignment, Address& offset);
1467   bool maybeVisitLoad(Expression*& out, uint8_t code, bool isAtomic);
1468   bool maybeVisitStore(Expression*& out, uint8_t code, bool isAtomic);
1469   bool maybeVisitNontrappingTrunc(Expression*& out, uint32_t code);
1470   bool maybeVisitAtomicRMW(Expression*& out, uint8_t code);
1471   bool maybeVisitAtomicCmpxchg(Expression*& out, uint8_t code);
1472   bool maybeVisitAtomicWait(Expression*& out, uint8_t code);
1473   bool maybeVisitAtomicNotify(Expression*& out, uint8_t code);
1474   bool maybeVisitAtomicFence(Expression*& out, uint8_t code);
1475   bool maybeVisitConst(Expression*& out, uint8_t code);
1476   bool maybeVisitUnary(Expression*& out, uint8_t code);
1477   bool maybeVisitBinary(Expression*& out, uint8_t code);
1478   bool maybeVisitTruncSat(Expression*& out, uint32_t code);
1479   bool maybeVisitSIMDBinary(Expression*& out, uint32_t code);
1480   bool maybeVisitSIMDUnary(Expression*& out, uint32_t code);
1481   bool maybeVisitSIMDConst(Expression*& out, uint32_t code);
1482   bool maybeVisitSIMDStore(Expression*& out, uint32_t code);
1483   bool maybeVisitSIMDExtract(Expression*& out, uint32_t code);
1484   bool maybeVisitSIMDReplace(Expression*& out, uint32_t code);
1485   bool maybeVisitSIMDShuffle(Expression*& out, uint32_t code);
1486   bool maybeVisitSIMDTernary(Expression*& out, uint32_t code);
1487   bool maybeVisitSIMDShift(Expression*& out, uint32_t code);
1488   bool maybeVisitSIMDLoad(Expression*& out, uint32_t code);
1489   bool maybeVisitMemoryInit(Expression*& out, uint32_t code);
1490   bool maybeVisitDataDrop(Expression*& out, uint32_t code);
1491   bool maybeVisitMemoryCopy(Expression*& out, uint32_t code);
1492   bool maybeVisitMemoryFill(Expression*& out, uint32_t code);
1493   bool maybeVisitI31New(Expression*& out, uint32_t code);
1494   bool maybeVisitI31Get(Expression*& out, uint32_t code);
1495   bool maybeVisitRefTest(Expression*& out, uint32_t code);
1496   bool maybeVisitRefCast(Expression*& out, uint32_t code);
1497   bool maybeVisitBrOnCast(Expression*& out, uint32_t code);
1498   bool maybeVisitRttCanon(Expression*& out, uint32_t code);
1499   bool maybeVisitRttSub(Expression*& out, uint32_t code);
1500   bool maybeVisitStructNew(Expression*& out, uint32_t code);
1501   bool maybeVisitStructGet(Expression*& out, uint32_t code);
1502   bool maybeVisitStructSet(Expression*& out, uint32_t code);
1503   bool maybeVisitArrayNew(Expression*& out, uint32_t code);
1504   bool maybeVisitArrayGet(Expression*& out, uint32_t code);
1505   bool maybeVisitArraySet(Expression*& out, uint32_t code);
1506   bool maybeVisitArrayLen(Expression*& out, uint32_t code);
1507   void visitSelect(Select* curr, uint8_t code);
1508   void visitReturn(Return* curr);
1509   void visitMemorySize(MemorySize* curr);
1510   void visitMemoryGrow(MemoryGrow* curr);
1511   void visitNop(Nop* curr);
1512   void visitUnreachable(Unreachable* curr);
1513   void visitDrop(Drop* curr);
1514   void visitRefNull(RefNull* curr);
1515   void visitRefIsNull(RefIsNull* curr);
1516   void visitRefFunc(RefFunc* curr);
1517   void visitRefEq(RefEq* curr);
1518   void visitTryOrTryInBlock(Expression*& out);
1519   void visitThrow(Throw* curr);
1520   void visitRethrow(Rethrow* curr);
1521   void visitBrOnExn(BrOnExn* curr);
1522 
1523   void throwError(std::string text);
1524 
1525 private:
1526   bool hasDWARFSections();
1527 };
1528 
1529 } // namespace wasm
1530 
1531 #undef DEBUG_TYPE
1532 
1533 #endif // wasm_wasm_binary_h
1534