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