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