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/master/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/Optional.h" |
19 | #include "llvm/ADT/SmallVector.h" |
20 | #include "llvm/ADT/StringRef.h" |
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 { |
35 | StringRef ; |
36 | uint32_t ; |
37 | }; |
38 | |
39 | struct WasmDylinkInfo { |
40 | uint32_t MemorySize; // Memory size in bytes |
41 | uint32_t MemoryAlignment; // P2 alignment of memory |
42 | uint32_t TableSize; // Table size in elements |
43 | uint32_t TableAlignment; // P2 alignment of table |
44 | std::vector<StringRef> Needed; // Shared library dependencies |
45 | }; |
46 | |
47 | struct WasmProducerInfo { |
48 | std::vector<std::pair<std::string, std::string>> Languages; |
49 | std::vector<std::pair<std::string, std::string>> Tools; |
50 | std::vector<std::pair<std::string, std::string>> SDKs; |
51 | }; |
52 | |
53 | struct WasmFeatureEntry { |
54 | uint8_t Prefix; |
55 | std::string Name; |
56 | }; |
57 | |
58 | struct WasmExport { |
59 | StringRef Name; |
60 | uint8_t Kind; |
61 | uint32_t Index; |
62 | }; |
63 | |
64 | struct WasmLimits { |
65 | uint8_t Flags; |
66 | uint64_t Minimum; |
67 | uint64_t Maximum; |
68 | }; |
69 | |
70 | struct WasmTableType { |
71 | uint8_t ElemType; |
72 | WasmLimits Limits; |
73 | }; |
74 | |
75 | struct WasmTable { |
76 | uint32_t Index; |
77 | WasmTableType Type; |
78 | StringRef SymbolName; // from the "linking" section |
79 | }; |
80 | |
81 | struct WasmInitExpr { |
82 | uint8_t Opcode; |
83 | union { |
84 | int32_t Int32; |
85 | int64_t Int64; |
86 | uint32_t Float32; |
87 | uint64_t Float64; |
88 | uint32_t Global; |
89 | } Value; |
90 | }; |
91 | |
92 | struct WasmGlobalType { |
93 | uint8_t Type; |
94 | bool Mutable; |
95 | }; |
96 | |
97 | struct WasmGlobal { |
98 | uint32_t Index; |
99 | WasmGlobalType Type; |
100 | WasmInitExpr InitExpr; |
101 | StringRef SymbolName; // from the "linking" section |
102 | }; |
103 | |
104 | struct WasmEventType { |
105 | // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible. |
106 | uint32_t Attribute; |
107 | uint32_t SigIndex; |
108 | }; |
109 | |
110 | struct WasmEvent { |
111 | uint32_t Index; |
112 | WasmEventType Type; |
113 | StringRef SymbolName; // from the "linking" section |
114 | }; |
115 | |
116 | struct WasmImport { |
117 | StringRef Module; |
118 | StringRef Field; |
119 | uint8_t Kind; |
120 | union { |
121 | uint32_t SigIndex; |
122 | WasmGlobalType Global; |
123 | WasmTableType Table; |
124 | WasmLimits Memory; |
125 | WasmEventType Event; |
126 | }; |
127 | }; |
128 | |
129 | struct WasmLocalDecl { |
130 | uint8_t Type; |
131 | uint32_t Count; |
132 | }; |
133 | |
134 | struct WasmFunction { |
135 | uint32_t Index; |
136 | std::vector<WasmLocalDecl> Locals; |
137 | ArrayRef<uint8_t> Body; |
138 | uint32_t CodeSectionOffset; |
139 | uint32_t Size; |
140 | uint32_t CodeOffset; // start of Locals and Body |
141 | Optional<StringRef> ExportName; // from the "export" section |
142 | StringRef SymbolName; // from the "linking" section |
143 | StringRef DebugName; // from the "name" section |
144 | uint32_t Comdat; // from the "comdat info" section |
145 | }; |
146 | |
147 | struct WasmDataSegment { |
148 | uint32_t InitFlags; |
149 | // Present if InitFlags & WASM_DATA_SEGMENT_HAS_MEMINDEX. |
150 | uint32_t MemoryIndex; |
151 | // Present if InitFlags & WASM_DATA_SEGMENT_IS_PASSIVE == 0. |
152 | WasmInitExpr Offset; |
153 | |
154 | ArrayRef<uint8_t> Content; |
155 | StringRef Name; // from the "segment info" section |
156 | uint32_t Alignment; |
157 | uint32_t LinkerFlags; |
158 | uint32_t Comdat; // from the "comdat info" section |
159 | }; |
160 | |
161 | struct WasmElemSegment { |
162 | uint32_t Flags; |
163 | uint32_t TableNumber; |
164 | uint8_t ElemKind; |
165 | WasmInitExpr Offset; |
166 | std::vector<uint32_t> Functions; |
167 | }; |
168 | |
169 | // Represents the location of a Wasm data symbol within a WasmDataSegment, as |
170 | // the index of the segment, and the offset and size within the segment. |
171 | struct WasmDataReference { |
172 | uint32_t Segment; |
173 | uint64_t Offset; |
174 | uint64_t Size; |
175 | }; |
176 | |
177 | struct WasmRelocation { |
178 | uint8_t Type; // The type of the relocation. |
179 | uint32_t Index; // Index into either symbol or type index space. |
180 | uint64_t Offset; // Offset from the start of the section. |
181 | int64_t Addend; // A value to add to the symbol. |
182 | }; |
183 | |
184 | struct WasmInitFunc { |
185 | uint32_t Priority; |
186 | uint32_t Symbol; |
187 | }; |
188 | |
189 | struct WasmSymbolInfo { |
190 | StringRef Name; |
191 | uint8_t Kind; |
192 | uint32_t Flags; |
193 | // For undefined symbols the module of the import |
194 | Optional<StringRef> ImportModule; |
195 | // For undefined symbols the name of the import |
196 | Optional<StringRef> ImportName; |
197 | // For symbols to be exported from the final module |
198 | Optional<StringRef> ExportName; |
199 | union { |
200 | // For function, table, or global symbols, the index in function, table, or |
201 | // global index space. |
202 | uint32_t ElementIndex; |
203 | // For a data symbols, the address of the data relative to segment. |
204 | WasmDataReference DataRef; |
205 | }; |
206 | }; |
207 | |
208 | enum class NameType { |
209 | FUNCTION, |
210 | GLOBAL, |
211 | DATA_SEGMENT, |
212 | }; |
213 | |
214 | struct WasmDebugName { |
215 | NameType Type; |
216 | uint32_t Index; |
217 | StringRef Name; |
218 | }; |
219 | |
220 | struct WasmLinkingData { |
221 | uint32_t Version; |
222 | std::vector<WasmInitFunc> InitFunctions; |
223 | std::vector<StringRef> Comdats; |
224 | std::vector<WasmSymbolInfo> SymbolTable; |
225 | }; |
226 | |
227 | enum : unsigned { |
228 | WASM_SEC_CUSTOM = 0, // Custom / User-defined section |
229 | WASM_SEC_TYPE = 1, // Function signature declarations |
230 | WASM_SEC_IMPORT = 2, // Import declarations |
231 | WASM_SEC_FUNCTION = 3, // Function declarations |
232 | WASM_SEC_TABLE = 4, // Indirect function table and other tables |
233 | WASM_SEC_MEMORY = 5, // Memory attributes |
234 | WASM_SEC_GLOBAL = 6, // Global declarations |
235 | WASM_SEC_EXPORT = 7, // Exports |
236 | WASM_SEC_START = 8, // Start function declaration |
237 | WASM_SEC_ELEM = 9, // Elements section |
238 | WASM_SEC_CODE = 10, // Function bodies (code) |
239 | WASM_SEC_DATA = 11, // Data segments |
240 | WASM_SEC_DATACOUNT = 12, // Data segment count |
241 | WASM_SEC_EVENT = 13 // Event declarations |
242 | }; |
243 | |
244 | // Type immediate encodings used in various contexts. |
245 | enum : unsigned { |
246 | WASM_TYPE_I32 = 0x7F, |
247 | WASM_TYPE_I64 = 0x7E, |
248 | WASM_TYPE_F32 = 0x7D, |
249 | WASM_TYPE_F64 = 0x7C, |
250 | WASM_TYPE_V128 = 0x7B, |
251 | WASM_TYPE_FUNCREF = 0x70, |
252 | WASM_TYPE_EXTERNREF = 0x6F, |
253 | WASM_TYPE_FUNC = 0x60, |
254 | WASM_TYPE_NORESULT = 0x40, // for blocks with no result values |
255 | }; |
256 | |
257 | // Kinds of externals (for imports and exports). |
258 | enum : unsigned { |
259 | WASM_EXTERNAL_FUNCTION = 0x0, |
260 | WASM_EXTERNAL_TABLE = 0x1, |
261 | WASM_EXTERNAL_MEMORY = 0x2, |
262 | WASM_EXTERNAL_GLOBAL = 0x3, |
263 | WASM_EXTERNAL_EVENT = 0x4, |
264 | }; |
265 | |
266 | // Opcodes used in initializer expressions. |
267 | enum : unsigned { |
268 | WASM_OPCODE_END = 0x0b, |
269 | WASM_OPCODE_CALL = 0x10, |
270 | WASM_OPCODE_LOCAL_GET = 0x20, |
271 | WASM_OPCODE_LOCAL_SET = 0x21, |
272 | WASM_OPCODE_GLOBAL_GET = 0x23, |
273 | WASM_OPCODE_GLOBAL_SET = 0x24, |
274 | WASM_OPCODE_I32_STORE = 0x36, |
275 | WASM_OPCODE_I64_STORE = 0x37, |
276 | WASM_OPCODE_I32_CONST = 0x41, |
277 | WASM_OPCODE_I64_CONST = 0x42, |
278 | WASM_OPCODE_F32_CONST = 0x43, |
279 | WASM_OPCODE_F64_CONST = 0x44, |
280 | WASM_OPCODE_I32_ADD = 0x6a, |
281 | WASM_OPCODE_I64_ADD = 0x7c, |
282 | WASM_OPCODE_REF_NULL = 0xd0, |
283 | }; |
284 | |
285 | // Opcodes used in synthetic functions. |
286 | enum : unsigned { |
287 | WASM_OPCODE_IF = 0x04, |
288 | WASM_OPCODE_ELSE = 0x05, |
289 | WASM_OPCODE_DROP = 0x1a, |
290 | WASM_OPCODE_MISC_PREFIX = 0xfc, |
291 | WASM_OPCODE_MEMORY_INIT = 0x08, |
292 | WASM_OPCODE_DATA_DROP = 0x09, |
293 | WASM_OPCODE_ATOMICS_PREFIX = 0xfe, |
294 | WASM_OPCODE_ATOMIC_NOTIFY = 0x00, |
295 | WASM_OPCODE_I32_ATOMIC_WAIT = 0x01, |
296 | WASM_OPCODE_I32_ATOMIC_STORE = 0x17, |
297 | WASM_OPCODE_I32_RMW_CMPXCHG = 0x48, |
298 | }; |
299 | |
300 | enum : unsigned { |
301 | WASM_LIMITS_FLAG_NONE = 0x0, |
302 | WASM_LIMITS_FLAG_HAS_MAX = 0x1, |
303 | WASM_LIMITS_FLAG_IS_SHARED = 0x2, |
304 | WASM_LIMITS_FLAG_IS_64 = 0x4, |
305 | }; |
306 | |
307 | enum : unsigned { |
308 | WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, |
309 | WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, |
310 | }; |
311 | |
312 | enum : unsigned { |
313 | WASM_ELEM_SEGMENT_IS_PASSIVE = 0x01, |
314 | WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER = 0x02, |
315 | WASM_ELEM_SEGMENT_HAS_INIT_EXPRS = 0x04, |
316 | }; |
317 | const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND = 0x3; |
318 | |
319 | // Feature policy prefixes used in the custom "target_features" section |
320 | enum : uint8_t { |
321 | WASM_FEATURE_PREFIX_USED = '+', |
322 | WASM_FEATURE_PREFIX_REQUIRED = '=', |
323 | WASM_FEATURE_PREFIX_DISALLOWED = '-', |
324 | }; |
325 | |
326 | // Kind codes used in the custom "name" section |
327 | enum : unsigned { |
328 | WASM_NAMES_FUNCTION = 1, |
329 | WASM_NAMES_LOCAL = 2, |
330 | WASM_NAMES_GLOBAL = 7, |
331 | WASM_NAMES_DATA_SEGMENT = 9, |
332 | }; |
333 | |
334 | // Kind codes used in the custom "linking" section |
335 | enum : unsigned { |
336 | WASM_SEGMENT_INFO = 0x5, |
337 | WASM_INIT_FUNCS = 0x6, |
338 | WASM_COMDAT_INFO = 0x7, |
339 | WASM_SYMBOL_TABLE = 0x8, |
340 | }; |
341 | |
342 | // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO |
343 | enum : unsigned { |
344 | WASM_COMDAT_DATA = 0x0, |
345 | WASM_COMDAT_FUNCTION = 0x1, |
346 | // GLOBAL, EVENT, and TABLE are in here but LLVM doesn't use them yet. |
347 | WASM_COMDAT_SECTION = 0x5, |
348 | }; |
349 | |
350 | // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE |
351 | enum WasmSymbolType : unsigned { |
352 | WASM_SYMBOL_TYPE_FUNCTION = 0x0, |
353 | WASM_SYMBOL_TYPE_DATA = 0x1, |
354 | WASM_SYMBOL_TYPE_GLOBAL = 0x2, |
355 | WASM_SYMBOL_TYPE_SECTION = 0x3, |
356 | WASM_SYMBOL_TYPE_EVENT = 0x4, |
357 | WASM_SYMBOL_TYPE_TABLE = 0x5, |
358 | }; |
359 | |
360 | // Kinds of event attributes. |
361 | enum WasmEventAttribute : unsigned { |
362 | WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0, |
363 | }; |
364 | |
365 | const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; |
366 | const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; |
367 | |
368 | const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; |
369 | const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; |
370 | const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; |
371 | const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; |
372 | const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; |
373 | const unsigned WASM_SYMBOL_UNDEFINED = 0x10; |
374 | const unsigned WASM_SYMBOL_EXPORTED = 0x20; |
375 | const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; |
376 | const unsigned WASM_SYMBOL_NO_STRIP = 0x80; |
377 | |
378 | #define WASM_RELOC(name, value) name = value, |
379 | |
380 | enum : unsigned { |
381 | #include "WasmRelocs.def" |
382 | }; |
383 | |
384 | #undef WASM_RELOC |
385 | |
386 | // Subset of types that a value can have |
387 | enum class ValType { |
388 | I32 = WASM_TYPE_I32, |
389 | I64 = WASM_TYPE_I64, |
390 | F32 = WASM_TYPE_F32, |
391 | F64 = WASM_TYPE_F64, |
392 | V128 = WASM_TYPE_V128, |
393 | FUNCREF = WASM_TYPE_FUNCREF, |
394 | EXTERNREF = WASM_TYPE_EXTERNREF, |
395 | }; |
396 | |
397 | struct WasmSignature { |
398 | SmallVector<ValType, 1> Returns; |
399 | SmallVector<ValType, 4> Params; |
400 | // Support empty and tombstone instances, needed by DenseMap. |
401 | enum { Plain, Empty, Tombstone } State = Plain; |
402 | |
403 | WasmSignature(SmallVector<ValType, 1> &&InReturns, |
404 | SmallVector<ValType, 4> &&InParams) |
405 | : Returns(InReturns), Params(InParams) {} |
406 | WasmSignature() = default; |
407 | }; |
408 | |
409 | // Useful comparison operators |
410 | inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { |
411 | return LHS.State == RHS.State && LHS.Returns == RHS.Returns && |
412 | LHS.Params == RHS.Params; |
413 | } |
414 | |
415 | inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { |
416 | return !(LHS == RHS); |
417 | } |
418 | |
419 | inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { |
420 | return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; |
421 | } |
422 | |
423 | inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { |
424 | return !(LHS == RHS); |
425 | } |
426 | |
427 | std::string toString(WasmSymbolType type); |
428 | std::string relocTypetoString(uint32_t type); |
429 | bool relocTypeHasAddend(uint32_t type); |
430 | |
431 | } // end namespace wasm |
432 | } // end namespace llvm |
433 | |
434 | #endif |
435 | |