1 //===- Wasm.h - Wasm object file format -------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file defines manifest constants for the wasm object file format.
11 // See: https://github.com/WebAssembly/design/blob/master/BinaryEncoding.md
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_BINARYFORMAT_WASM_H
16 #define LLVM_BINARYFORMAT_WASM_H
17 
18 #include "llvm/ADT/ArrayRef.h"
19 
20 namespace llvm {
21 namespace wasm {
22 
23 // Object file magic string.
24 const char WasmMagic[] = {'\0', 'a', 's', 'm'};
25 // Wasm binary format version
26 const uint32_t WasmVersion = 0x1;
27 // Wasm linking metadata version
28 const uint32_t WasmMetadataVersion = 0x1;
29 // Wasm uses a 64k page size
30 const uint32_t WasmPageSize = 65536;
31 
32 struct WasmObjectHeader {
33   StringRef Magic;
34   uint32_t Version;
35 };
36 
37 struct WasmSignature {
38   std::vector<uint8_t> ParamTypes;
39   uint8_t ReturnType;
40 };
41 
42 struct WasmExport {
43   StringRef Name;
44   uint8_t Kind;
45   uint32_t Index;
46 };
47 
48 struct WasmLimits {
49   uint8_t Flags;
50   uint32_t Initial;
51   uint32_t Maximum;
52 };
53 
54 struct WasmTable {
55   uint8_t ElemType;
56   WasmLimits Limits;
57 };
58 
59 struct WasmInitExpr {
60   uint8_t Opcode;
61   union {
62     int32_t Int32;
63     int64_t Int64;
64     int32_t Float32;
65     int64_t Float64;
66     uint32_t Global;
67   } Value;
68 };
69 
70 struct WasmGlobalType {
71   uint8_t Type;
72   bool Mutable;
73 };
74 
75 struct WasmGlobal {
76   uint32_t Index;
77   WasmGlobalType Type;
78   WasmInitExpr InitExpr;
79   StringRef SymbolName; // from the "linking" section
80 };
81 
82 struct WasmImport {
83   StringRef Module;
84   StringRef Field;
85   uint8_t Kind;
86   union {
87     uint32_t SigIndex;
88     WasmGlobalType Global;
89     WasmTable Table;
90     WasmLimits Memory;
91   };
92 };
93 
94 struct WasmLocalDecl {
95   uint8_t Type;
96   uint32_t Count;
97 };
98 
99 struct WasmFunction {
100   uint32_t Index;
101   std::vector<WasmLocalDecl> Locals;
102   ArrayRef<uint8_t> Body;
103   uint32_t CodeSectionOffset;
104   uint32_t Size;
105   uint32_t CodeOffset;  // start of Locals and Body
106   StringRef SymbolName; // from the "linking" section
107   StringRef DebugName; // from the "name" section
108   uint32_t Comdat; // from the "comdat info" section
109 };
110 
111 struct WasmDataSegment {
112   uint32_t MemoryIndex;
113   WasmInitExpr Offset;
114   ArrayRef<uint8_t> Content;
115   StringRef Name; // from the "segment info" section
116   uint32_t Alignment;
117   uint32_t Flags;
118   uint32_t Comdat; // from the "comdat info" section
119 };
120 
121 struct WasmElemSegment {
122   uint32_t TableIndex;
123   WasmInitExpr Offset;
124   std::vector<uint32_t> Functions;
125 };
126 
127 // Represents the location of a Wasm data symbol within a WasmDataSegment, as
128 // the index of the segment, and the offset and size within the segment.
129 struct WasmDataReference {
130   uint32_t Segment;
131   uint32_t Offset;
132   uint32_t Size;
133 };
134 
135 struct WasmRelocation {
136   uint8_t Type;    // The type of the relocation.
137   uint32_t Index;  // Index into either symbol or type index space.
138   uint64_t Offset; // Offset from the start of the section.
139   int64_t Addend;  // A value to add to the symbol.
140 };
141 
142 struct WasmInitFunc {
143   uint32_t Priority;
144   uint32_t Symbol;
145 };
146 
147 struct WasmSymbolInfo {
148   StringRef Name;
149   uint8_t Kind;
150   uint32_t Flags;
151   StringRef Module; // For undefined symbols the module name of the import
152   union {
153     // For function or global symbols, the index in function or global index
154     // space.
155     uint32_t ElementIndex;
156     // For a data symbols, the address of the data relative to segment.
157     WasmDataReference DataRef;
158   };
159 };
160 
161 struct WasmFunctionName {
162   uint32_t Index;
163   StringRef Name;
164 };
165 
166 struct WasmLinkingData {
167   uint32_t Version;
168   std::vector<WasmInitFunc> InitFunctions;
169   std::vector<StringRef> Comdats;
170   std::vector<WasmSymbolInfo> SymbolTable;
171 };
172 
173 enum : unsigned {
174   WASM_SEC_CUSTOM = 0,   // Custom / User-defined section
175   WASM_SEC_TYPE = 1,     // Function signature declarations
176   WASM_SEC_IMPORT = 2,   // Import declarations
177   WASM_SEC_FUNCTION = 3, // Function declarations
178   WASM_SEC_TABLE = 4,    // Indirect function table and other tables
179   WASM_SEC_MEMORY = 5,   // Memory attributes
180   WASM_SEC_GLOBAL = 6,   // Global declarations
181   WASM_SEC_EXPORT = 7,   // Exports
182   WASM_SEC_START = 8,    // Start function declaration
183   WASM_SEC_ELEM = 9,     // Elements section
184   WASM_SEC_CODE = 10,    // Function bodies (code)
185   WASM_SEC_DATA = 11     // Data segments
186 };
187 
188 // Type immediate encodings used in various contexts.
189 enum : unsigned {
190   WASM_TYPE_I32 = 0x7F,
191   WASM_TYPE_I64 = 0x7E,
192   WASM_TYPE_F32 = 0x7D,
193   WASM_TYPE_F64 = 0x7C,
194   WASM_TYPE_ANYFUNC = 0x70,
195   WASM_TYPE_EXCEPT_REF = 0x68,
196   WASM_TYPE_FUNC = 0x60,
197   WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
198 };
199 
200 // Kinds of externals (for imports and exports).
201 enum : unsigned {
202   WASM_EXTERNAL_FUNCTION = 0x0,
203   WASM_EXTERNAL_TABLE = 0x1,
204   WASM_EXTERNAL_MEMORY = 0x2,
205   WASM_EXTERNAL_GLOBAL = 0x3,
206 };
207 
208 // Opcodes used in initializer expressions.
209 enum : unsigned {
210   WASM_OPCODE_END = 0x0b,
211   WASM_OPCODE_GET_GLOBAL = 0x23,
212   WASM_OPCODE_I32_CONST = 0x41,
213   WASM_OPCODE_I64_CONST = 0x42,
214   WASM_OPCODE_F32_CONST = 0x43,
215   WASM_OPCODE_F64_CONST = 0x44,
216 };
217 
218 enum : unsigned {
219   WASM_LIMITS_FLAG_HAS_MAX = 0x1,
220 };
221 
222 // Subset of types that a value can have
223 enum class ValType {
224   I32 = WASM_TYPE_I32,
225   I64 = WASM_TYPE_I64,
226   F32 = WASM_TYPE_F32,
227   F64 = WASM_TYPE_F64,
228   EXCEPT_REF = WASM_TYPE_EXCEPT_REF,
229 };
230 
231 // Kind codes used in the custom "name" section
232 enum : unsigned {
233   WASM_NAMES_FUNCTION = 0x1,
234   WASM_NAMES_LOCAL    = 0x2,
235 };
236 
237 // Kind codes used in the custom "linking" section
238 enum : unsigned {
239   WASM_SEGMENT_INFO   = 0x5,
240   WASM_INIT_FUNCS     = 0x6,
241   WASM_COMDAT_INFO    = 0x7,
242   WASM_SYMBOL_TABLE   = 0x8,
243 };
244 
245 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
246 enum : unsigned {
247   WASM_COMDAT_DATA        = 0x0,
248   WASM_COMDAT_FUNCTION    = 0x1,
249 };
250 
251 // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
252 enum WasmSymbolType : unsigned {
253   WASM_SYMBOL_TYPE_FUNCTION = 0x0,
254   WASM_SYMBOL_TYPE_DATA = 0x1,
255   WASM_SYMBOL_TYPE_GLOBAL = 0x2,
256   WASM_SYMBOL_TYPE_SECTION = 0x3,
257 };
258 
259 const unsigned WASM_SYMBOL_BINDING_MASK       = 0x3;
260 const unsigned WASM_SYMBOL_VISIBILITY_MASK    = 0xc;
261 
262 const unsigned WASM_SYMBOL_BINDING_GLOBAL     = 0x0;
263 const unsigned WASM_SYMBOL_BINDING_WEAK       = 0x1;
264 const unsigned WASM_SYMBOL_BINDING_LOCAL      = 0x2;
265 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
266 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN  = 0x4;
267 const unsigned WASM_SYMBOL_UNDEFINED          = 0x10;
268 
269 #define WASM_RELOC(name, value) name = value,
270 
271 enum : unsigned {
272 #include "WasmRelocs.def"
273 };
274 
275 #undef WASM_RELOC
276 
277 // Useful comparison operators
278 inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) {
279   return LHS.ReturnType == RHS.ReturnType && LHS.ParamTypes == RHS.ParamTypes;
280 }
281 
282 inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) {
283   return !(LHS == RHS);
284 }
285 
286 inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
287   return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable;
288 }
289 
290 inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
291   return !(LHS == RHS);
292 }
293 
294 std::string toString(wasm::WasmSymbolType type);
295 std::string relocTypetoString(uint32_t type);
296 
297 } // end namespace wasm
298 } // end namespace llvm
299 
300 #endif
301