Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- Wasm.h - Wasm object file format -------------------------*- C++ -*-===// |
2 | // |
||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
||
4 | // See https://llvm.org/LICENSE.txt for license information. |
||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
||
6 | // |
||
7 | //===----------------------------------------------------------------------===// |
||
8 | // |
||
9 | // This file defines manifest constants for the wasm object file format. |
||
10 | // See: https://github.com/WebAssembly/design/blob/main/BinaryEncoding.md |
||
11 | // |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_BINARYFORMAT_WASM_H |
||
15 | #define LLVM_BINARYFORMAT_WASM_H |
||
16 | |||
17 | #include "llvm/ADT/ArrayRef.h" |
||
18 | #include "llvm/ADT/SmallVector.h" |
||
19 | #include "llvm/ADT/StringRef.h" |
||
20 | #include <optional> |
||
21 | |||
22 | namespace llvm { |
||
23 | namespace wasm { |
||
24 | |||
25 | // Object file magic string. |
||
26 | const char WasmMagic[] = {'\0', 'a', 's', 'm'}; |
||
27 | // Wasm binary format version |
||
28 | const uint32_t WasmVersion = 0x1; |
||
29 | // Wasm linking metadata version |
||
30 | const uint32_t WasmMetadataVersion = 0x2; |
||
31 | // Wasm uses a 64k page size |
||
32 | const uint32_t WasmPageSize = 65536; |
||
33 | |||
34 | struct WasmObjectHeader { |
||
35 | StringRef Magic; |
||
36 | uint32_t Version; |
||
37 | }; |
||
38 | |||
39 | struct WasmDylinkImportInfo { |
||
40 | StringRef Module; |
||
41 | StringRef Field; |
||
42 | uint32_t Flags; |
||
43 | }; |
||
44 | |||
45 | struct WasmDylinkExportInfo { |
||
46 | StringRef Name; |
||
47 | uint32_t Flags; |
||
48 | }; |
||
49 | |||
50 | struct WasmDylinkInfo { |
||
51 | uint32_t MemorySize; // Memory size in bytes |
||
52 | uint32_t MemoryAlignment; // P2 alignment of memory |
||
53 | uint32_t TableSize; // Table size in elements |
||
54 | uint32_t TableAlignment; // P2 alignment of table |
||
55 | std::vector<StringRef> Needed; // Shared library dependencies |
||
56 | std::vector<WasmDylinkImportInfo> ImportInfo; |
||
57 | std::vector<WasmDylinkExportInfo> ExportInfo; |
||
58 | }; |
||
59 | |||
60 | struct WasmProducerInfo { |
||
61 | std::vector<std::pair<std::string, std::string>> Languages; |
||
62 | std::vector<std::pair<std::string, std::string>> Tools; |
||
63 | std::vector<std::pair<std::string, std::string>> SDKs; |
||
64 | }; |
||
65 | |||
66 | struct WasmFeatureEntry { |
||
67 | uint8_t Prefix; |
||
68 | std::string Name; |
||
69 | }; |
||
70 | |||
71 | struct WasmExport { |
||
72 | StringRef Name; |
||
73 | uint8_t Kind; |
||
74 | uint32_t Index; |
||
75 | }; |
||
76 | |||
77 | struct WasmLimits { |
||
78 | uint8_t Flags; |
||
79 | uint64_t Minimum; |
||
80 | uint64_t Maximum; |
||
81 | }; |
||
82 | |||
83 | struct WasmTableType { |
||
84 | uint8_t ElemType; |
||
85 | WasmLimits Limits; |
||
86 | }; |
||
87 | |||
88 | struct WasmTable { |
||
89 | uint32_t Index; |
||
90 | WasmTableType Type; |
||
91 | StringRef SymbolName; // from the "linking" section |
||
92 | }; |
||
93 | |||
94 | struct WasmInitExprMVP { |
||
95 | uint8_t Opcode; |
||
96 | union { |
||
97 | int32_t Int32; |
||
98 | int64_t Int64; |
||
99 | uint32_t Float32; |
||
100 | uint64_t Float64; |
||
101 | uint32_t Global; |
||
102 | } Value; |
||
103 | }; |
||
104 | |||
105 | struct WasmInitExpr { |
||
106 | uint8_t Extended; // Set to non-zero if extended const is used (i.e. more than |
||
107 | // one instruction) |
||
108 | WasmInitExprMVP Inst; |
||
109 | ArrayRef<uint8_t> Body; |
||
110 | }; |
||
111 | |||
112 | struct WasmGlobalType { |
||
113 | uint8_t Type; |
||
114 | bool Mutable; |
||
115 | }; |
||
116 | |||
117 | struct WasmGlobal { |
||
118 | uint32_t Index; |
||
119 | WasmGlobalType Type; |
||
120 | WasmInitExpr InitExpr; |
||
121 | StringRef SymbolName; // from the "linking" section |
||
122 | }; |
||
123 | |||
124 | struct WasmTag { |
||
125 | uint32_t Index; |
||
126 | uint32_t SigIndex; |
||
127 | StringRef SymbolName; // from the "linking" section |
||
128 | }; |
||
129 | |||
130 | struct WasmImport { |
||
131 | StringRef Module; |
||
132 | StringRef Field; |
||
133 | uint8_t Kind; |
||
134 | union { |
||
135 | uint32_t SigIndex; |
||
136 | WasmGlobalType Global; |
||
137 | WasmTableType Table; |
||
138 | WasmLimits Memory; |
||
139 | }; |
||
140 | }; |
||
141 | |||
142 | struct WasmLocalDecl { |
||
143 | uint8_t Type; |
||
144 | uint32_t Count; |
||
145 | }; |
||
146 | |||
147 | struct WasmFunction { |
||
148 | uint32_t Index; |
||
149 | uint32_t SigIndex; |
||
150 | std::vector<WasmLocalDecl> Locals; |
||
151 | ArrayRef<uint8_t> Body; |
||
152 | uint32_t CodeSectionOffset; |
||
153 | uint32_t Size; |
||
154 | uint32_t CodeOffset; // start of Locals and Body |
||
155 | std::optional<StringRef> ExportName; // from the "export" section |
||
156 | StringRef SymbolName; // from the "linking" section |
||
157 | StringRef DebugName; // from the "name" section |
||
158 | uint32_t Comdat; // from the "comdat info" section |
||
159 | }; |
||
160 | |||
161 | struct WasmDataSegment { |
||
162 | uint32_t InitFlags; |
||
163 | // Present if InitFlags & WASM_DATA_SEGMENT_HAS_MEMINDEX. |
||
164 | uint32_t MemoryIndex; |
||
165 | // Present if InitFlags & WASM_DATA_SEGMENT_IS_PASSIVE == 0. |
||
166 | WasmInitExpr Offset; |
||
167 | |||
168 | ArrayRef<uint8_t> Content; |
||
169 | StringRef Name; // from the "segment info" section |
||
170 | uint32_t Alignment; |
||
171 | uint32_t LinkingFlags; |
||
172 | uint32_t Comdat; // from the "comdat info" section |
||
173 | }; |
||
174 | |||
175 | struct WasmElemSegment { |
||
176 | uint32_t Flags; |
||
177 | uint32_t TableNumber; |
||
178 | uint8_t ElemKind; |
||
179 | WasmInitExpr Offset; |
||
180 | std::vector<uint32_t> Functions; |
||
181 | }; |
||
182 | |||
183 | // Represents the location of a Wasm data symbol within a WasmDataSegment, as |
||
184 | // the index of the segment, and the offset and size within the segment. |
||
185 | struct WasmDataReference { |
||
186 | uint32_t Segment; |
||
187 | uint64_t Offset; |
||
188 | uint64_t Size; |
||
189 | }; |
||
190 | |||
191 | struct WasmRelocation { |
||
192 | uint8_t Type; // The type of the relocation. |
||
193 | uint32_t Index; // Index into either symbol or type index space. |
||
194 | uint64_t Offset; // Offset from the start of the section. |
||
195 | int64_t Addend; // A value to add to the symbol. |
||
196 | }; |
||
197 | |||
198 | struct WasmInitFunc { |
||
199 | uint32_t Priority; |
||
200 | uint32_t Symbol; |
||
201 | }; |
||
202 | |||
203 | struct WasmSymbolInfo { |
||
204 | StringRef Name; |
||
205 | uint8_t Kind; |
||
206 | uint32_t Flags; |
||
207 | // For undefined symbols the module of the import |
||
208 | std::optional<StringRef> ImportModule; |
||
209 | // For undefined symbols the name of the import |
||
210 | std::optional<StringRef> ImportName; |
||
211 | // For symbols to be exported from the final module |
||
212 | std::optional<StringRef> ExportName; |
||
213 | union { |
||
214 | // For function, table, or global symbols, the index in function, table, or |
||
215 | // global index space. |
||
216 | uint32_t ElementIndex; |
||
217 | // For a data symbols, the address of the data relative to segment. |
||
218 | WasmDataReference DataRef; |
||
219 | }; |
||
220 | }; |
||
221 | |||
222 | enum class NameType { |
||
223 | FUNCTION, |
||
224 | GLOBAL, |
||
225 | DATA_SEGMENT, |
||
226 | }; |
||
227 | |||
228 | struct WasmDebugName { |
||
229 | NameType Type; |
||
230 | uint32_t Index; |
||
231 | StringRef Name; |
||
232 | }; |
||
233 | |||
234 | struct WasmLinkingData { |
||
235 | uint32_t Version; |
||
236 | std::vector<WasmInitFunc> InitFunctions; |
||
237 | std::vector<StringRef> Comdats; |
||
238 | std::vector<WasmSymbolInfo> SymbolTable; |
||
239 | }; |
||
240 | |||
241 | enum : unsigned { |
||
242 | WASM_SEC_CUSTOM = 0, // Custom / User-defined section |
||
243 | WASM_SEC_TYPE = 1, // Function signature declarations |
||
244 | WASM_SEC_IMPORT = 2, // Import declarations |
||
245 | WASM_SEC_FUNCTION = 3, // Function declarations |
||
246 | WASM_SEC_TABLE = 4, // Indirect function table and other tables |
||
247 | WASM_SEC_MEMORY = 5, // Memory attributes |
||
248 | WASM_SEC_GLOBAL = 6, // Global declarations |
||
249 | WASM_SEC_EXPORT = 7, // Exports |
||
250 | WASM_SEC_START = 8, // Start function declaration |
||
251 | WASM_SEC_ELEM = 9, // Elements section |
||
252 | WASM_SEC_CODE = 10, // Function bodies (code) |
||
253 | WASM_SEC_DATA = 11, // Data segments |
||
254 | WASM_SEC_DATACOUNT = 12, // Data segment count |
||
255 | WASM_SEC_TAG = 13, // Tag declarations |
||
256 | WASM_SEC_LAST_KNOWN = WASM_SEC_TAG, |
||
257 | }; |
||
258 | |||
259 | // Type immediate encodings used in various contexts. |
||
260 | enum : unsigned { |
||
261 | WASM_TYPE_I32 = 0x7F, |
||
262 | WASM_TYPE_I64 = 0x7E, |
||
263 | WASM_TYPE_F32 = 0x7D, |
||
264 | WASM_TYPE_F64 = 0x7C, |
||
265 | WASM_TYPE_V128 = 0x7B, |
||
266 | WASM_TYPE_FUNCREF = 0x70, |
||
267 | WASM_TYPE_EXTERNREF = 0x6F, |
||
268 | WASM_TYPE_FUNC = 0x60, |
||
269 | WASM_TYPE_NORESULT = 0x40, // for blocks with no result values |
||
270 | }; |
||
271 | |||
272 | // Kinds of externals (for imports and exports). |
||
273 | enum : unsigned { |
||
274 | WASM_EXTERNAL_FUNCTION = 0x0, |
||
275 | WASM_EXTERNAL_TABLE = 0x1, |
||
276 | WASM_EXTERNAL_MEMORY = 0x2, |
||
277 | WASM_EXTERNAL_GLOBAL = 0x3, |
||
278 | WASM_EXTERNAL_TAG = 0x4, |
||
279 | }; |
||
280 | |||
281 | // Opcodes used in initializer expressions. |
||
282 | enum : unsigned { |
||
283 | WASM_OPCODE_END = 0x0b, |
||
284 | WASM_OPCODE_CALL = 0x10, |
||
285 | WASM_OPCODE_LOCAL_GET = 0x20, |
||
286 | WASM_OPCODE_LOCAL_SET = 0x21, |
||
287 | WASM_OPCODE_LOCAL_TEE = 0x22, |
||
288 | WASM_OPCODE_GLOBAL_GET = 0x23, |
||
289 | WASM_OPCODE_GLOBAL_SET = 0x24, |
||
290 | WASM_OPCODE_I32_STORE = 0x36, |
||
291 | WASM_OPCODE_I64_STORE = 0x37, |
||
292 | WASM_OPCODE_I32_CONST = 0x41, |
||
293 | WASM_OPCODE_I64_CONST = 0x42, |
||
294 | WASM_OPCODE_F32_CONST = 0x43, |
||
295 | WASM_OPCODE_F64_CONST = 0x44, |
||
296 | WASM_OPCODE_I32_ADD = 0x6a, |
||
297 | WASM_OPCODE_I32_SUB = 0x6b, |
||
298 | WASM_OPCODE_I32_MUL = 0x6c, |
||
299 | WASM_OPCODE_I64_ADD = 0x7c, |
||
300 | WASM_OPCODE_I64_SUB = 0x7d, |
||
301 | WASM_OPCODE_I64_MUL = 0x7e, |
||
302 | WASM_OPCODE_REF_NULL = 0xd0, |
||
303 | }; |
||
304 | |||
305 | // Opcodes used in synthetic functions. |
||
306 | enum : unsigned { |
||
307 | WASM_OPCODE_BLOCK = 0x02, |
||
308 | WASM_OPCODE_BR = 0x0c, |
||
309 | WASM_OPCODE_BR_TABLE = 0x0e, |
||
310 | WASM_OPCODE_RETURN = 0x0f, |
||
311 | WASM_OPCODE_DROP = 0x1a, |
||
312 | WASM_OPCODE_MISC_PREFIX = 0xfc, |
||
313 | WASM_OPCODE_MEMORY_INIT = 0x08, |
||
314 | WASM_OPCODE_MEMORY_FILL = 0x0b, |
||
315 | WASM_OPCODE_DATA_DROP = 0x09, |
||
316 | WASM_OPCODE_ATOMICS_PREFIX = 0xfe, |
||
317 | WASM_OPCODE_ATOMIC_NOTIFY = 0x00, |
||
318 | WASM_OPCODE_I32_ATOMIC_WAIT = 0x01, |
||
319 | WASM_OPCODE_I32_ATOMIC_STORE = 0x17, |
||
320 | WASM_OPCODE_I32_RMW_CMPXCHG = 0x48, |
||
321 | }; |
||
322 | |||
323 | enum : unsigned { |
||
324 | WASM_LIMITS_FLAG_NONE = 0x0, |
||
325 | WASM_LIMITS_FLAG_HAS_MAX = 0x1, |
||
326 | WASM_LIMITS_FLAG_IS_SHARED = 0x2, |
||
327 | WASM_LIMITS_FLAG_IS_64 = 0x4, |
||
328 | }; |
||
329 | |||
330 | enum : unsigned { |
||
331 | WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, |
||
332 | WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, |
||
333 | }; |
||
334 | |||
335 | enum : unsigned { |
||
336 | WASM_ELEM_SEGMENT_IS_PASSIVE = 0x01, |
||
337 | WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER = 0x02, |
||
338 | WASM_ELEM_SEGMENT_HAS_INIT_EXPRS = 0x04, |
||
339 | }; |
||
340 | const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND = 0x3; |
||
341 | |||
342 | // Feature policy prefixes used in the custom "target_features" section |
||
343 | enum : uint8_t { |
||
344 | WASM_FEATURE_PREFIX_USED = '+', |
||
345 | WASM_FEATURE_PREFIX_REQUIRED = '=', |
||
346 | WASM_FEATURE_PREFIX_DISALLOWED = '-', |
||
347 | }; |
||
348 | |||
349 | // Kind codes used in the custom "name" section |
||
350 | enum : unsigned { |
||
351 | WASM_NAMES_FUNCTION = 1, |
||
352 | WASM_NAMES_LOCAL = 2, |
||
353 | WASM_NAMES_GLOBAL = 7, |
||
354 | WASM_NAMES_DATA_SEGMENT = 9, |
||
355 | }; |
||
356 | |||
357 | // Kind codes used in the custom "linking" section |
||
358 | enum : unsigned { |
||
359 | WASM_SEGMENT_INFO = 0x5, |
||
360 | WASM_INIT_FUNCS = 0x6, |
||
361 | WASM_COMDAT_INFO = 0x7, |
||
362 | WASM_SYMBOL_TABLE = 0x8, |
||
363 | }; |
||
364 | |||
365 | // Kind codes used in the custom "dylink" section |
||
366 | enum : unsigned { |
||
367 | WASM_DYLINK_MEM_INFO = 0x1, |
||
368 | WASM_DYLINK_NEEDED = 0x2, |
||
369 | WASM_DYLINK_EXPORT_INFO = 0x3, |
||
370 | WASM_DYLINK_IMPORT_INFO = 0x4, |
||
371 | }; |
||
372 | |||
373 | // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO |
||
374 | enum : unsigned { |
||
375 | WASM_COMDAT_DATA = 0x0, |
||
376 | WASM_COMDAT_FUNCTION = 0x1, |
||
377 | // GLOBAL, TAG, and TABLE are in here but LLVM doesn't use them yet. |
||
378 | WASM_COMDAT_SECTION = 0x5, |
||
379 | }; |
||
380 | |||
381 | // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE |
||
382 | enum WasmSymbolType : unsigned { |
||
383 | WASM_SYMBOL_TYPE_FUNCTION = 0x0, |
||
384 | WASM_SYMBOL_TYPE_DATA = 0x1, |
||
385 | WASM_SYMBOL_TYPE_GLOBAL = 0x2, |
||
386 | WASM_SYMBOL_TYPE_SECTION = 0x3, |
||
387 | WASM_SYMBOL_TYPE_TAG = 0x4, |
||
388 | WASM_SYMBOL_TYPE_TABLE = 0x5, |
||
389 | }; |
||
390 | |||
391 | enum WasmSegmentFlag : unsigned { |
||
392 | WASM_SEG_FLAG_STRINGS = 0x1, |
||
393 | WASM_SEG_FLAG_TLS = 0x2, |
||
394 | }; |
||
395 | |||
396 | // Kinds of tag attributes. |
||
397 | enum WasmTagAttribute : uint8_t { |
||
398 | WASM_TAG_ATTRIBUTE_EXCEPTION = 0x0, |
||
399 | }; |
||
400 | |||
401 | const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; |
||
402 | const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; |
||
403 | |||
404 | const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; |
||
405 | const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; |
||
406 | const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; |
||
407 | const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; |
||
408 | const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; |
||
409 | const unsigned WASM_SYMBOL_UNDEFINED = 0x10; |
||
410 | const unsigned WASM_SYMBOL_EXPORTED = 0x20; |
||
411 | const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; |
||
412 | const unsigned WASM_SYMBOL_NO_STRIP = 0x80; |
||
413 | const unsigned WASM_SYMBOL_TLS = 0x100; |
||
414 | |||
415 | #define WASM_RELOC(name, value) name = value, |
||
416 | |||
417 | enum : unsigned { |
||
418 | #include "WasmRelocs.def" |
||
419 | }; |
||
420 | |||
421 | #undef WASM_RELOC |
||
422 | |||
423 | // Subset of types that a value can have |
||
424 | enum class ValType { |
||
425 | I32 = WASM_TYPE_I32, |
||
426 | I64 = WASM_TYPE_I64, |
||
427 | F32 = WASM_TYPE_F32, |
||
428 | F64 = WASM_TYPE_F64, |
||
429 | V128 = WASM_TYPE_V128, |
||
430 | FUNCREF = WASM_TYPE_FUNCREF, |
||
431 | EXTERNREF = WASM_TYPE_EXTERNREF, |
||
432 | }; |
||
433 | |||
434 | struct WasmSignature { |
||
435 | SmallVector<ValType, 1> Returns; |
||
436 | SmallVector<ValType, 4> Params; |
||
437 | // Support empty and tombstone instances, needed by DenseMap. |
||
438 | enum { Plain, Empty, Tombstone } State = Plain; |
||
439 | |||
440 | WasmSignature(SmallVector<ValType, 1> &&InReturns, |
||
441 | SmallVector<ValType, 4> &&InParams) |
||
442 | : Returns(InReturns), Params(InParams) {} |
||
443 | WasmSignature() = default; |
||
444 | }; |
||
445 | |||
446 | // Useful comparison operators |
||
447 | inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { |
||
448 | return LHS.State == RHS.State && LHS.Returns == RHS.Returns && |
||
449 | LHS.Params == RHS.Params; |
||
450 | } |
||
451 | |||
452 | inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { |
||
453 | return !(LHS == RHS); |
||
454 | } |
||
455 | |||
456 | inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { |
||
457 | return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; |
||
458 | } |
||
459 | |||
460 | inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { |
||
461 | return !(LHS == RHS); |
||
462 | } |
||
463 | |||
464 | inline bool operator==(const WasmLimits &LHS, const WasmLimits &RHS) { |
||
465 | return LHS.Flags == RHS.Flags && LHS.Minimum == RHS.Minimum && |
||
466 | (LHS.Flags & WASM_LIMITS_FLAG_HAS_MAX ? LHS.Maximum == RHS.Maximum |
||
467 | : true); |
||
468 | } |
||
469 | |||
470 | inline bool operator==(const WasmTableType &LHS, const WasmTableType &RHS) { |
||
471 | return LHS.ElemType == RHS.ElemType && LHS.Limits == RHS.Limits; |
||
472 | } |
||
473 | |||
474 | llvm::StringRef toString(WasmSymbolType type); |
||
475 | llvm::StringRef relocTypetoString(uint32_t type); |
||
476 | llvm::StringRef sectionTypeToString(uint32_t type); |
||
477 | bool relocTypeHasAddend(uint32_t type); |
||
478 | |||
479 | } // end namespace wasm |
||
480 | } // end namespace llvm |
||
481 | |||
482 | #endif |