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 WasmDylinkExport { 40 StringRef Name; 41 uint32_t Flags; 42 }; 43 44 struct WasmDylinkInfo { 45 uint32_t MemorySize; // Memory size in bytes 46 uint32_t MemoryAlignment; // P2 alignment of memory 47 uint32_t TableSize; // Table size in elements 48 uint32_t TableAlignment; // P2 alignment of table 49 std::vector<StringRef> Needed; // Shared library dependencies 50 std::vector<WasmDylinkExport> ExportInfo; // Shared library dependencies 51 }; 52 53 struct WasmProducerInfo { 54 std::vector<std::pair<std::string, std::string>> Languages; 55 std::vector<std::pair<std::string, std::string>> Tools; 56 std::vector<std::pair<std::string, std::string>> SDKs; 57 }; 58 59 struct WasmFeatureEntry { 60 uint8_t Prefix; 61 std::string Name; 62 }; 63 64 struct WasmExport { 65 StringRef Name; 66 uint8_t Kind; 67 uint32_t Index; 68 }; 69 70 struct WasmLimits { 71 uint8_t Flags; 72 uint64_t Minimum; 73 uint64_t Maximum; 74 }; 75 76 struct WasmTableType { 77 uint8_t ElemType; 78 WasmLimits Limits; 79 }; 80 81 struct WasmTable { 82 uint32_t Index; 83 WasmTableType Type; 84 StringRef SymbolName; // from the "linking" section 85 }; 86 87 struct WasmInitExpr { 88 uint8_t Opcode; 89 union { 90 int32_t Int32; 91 int64_t Int64; 92 uint32_t Float32; 93 uint64_t Float64; 94 uint32_t Global; 95 } Value; 96 }; 97 98 struct WasmGlobalType { 99 uint8_t Type; 100 bool Mutable; 101 }; 102 103 struct WasmGlobal { 104 uint32_t Index; 105 WasmGlobalType Type; 106 WasmInitExpr InitExpr; 107 StringRef SymbolName; // from the "linking" section 108 }; 109 110 struct WasmTag { 111 uint32_t Index; 112 uint32_t SigIndex; 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 }; 126 }; 127 128 struct WasmLocalDecl { 129 uint8_t Type; 130 uint32_t Count; 131 }; 132 133 struct WasmFunction { 134 uint32_t Index; 135 uint32_t SigIndex; 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 LinkingFlags; 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_TAG = 13 // Tag 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_TAG = 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_BLOCK = 0x02, 288 WASM_OPCODE_BR = 0x0c, 289 WASM_OPCODE_BR_TABLE = 0x0e, 290 WASM_OPCODE_RETURN = 0x0f, 291 WASM_OPCODE_DROP = 0x1a, 292 WASM_OPCODE_MISC_PREFIX = 0xfc, 293 WASM_OPCODE_MEMORY_INIT = 0x08, 294 WASM_OPCODE_DATA_DROP = 0x09, 295 WASM_OPCODE_ATOMICS_PREFIX = 0xfe, 296 WASM_OPCODE_ATOMIC_NOTIFY = 0x00, 297 WASM_OPCODE_I32_ATOMIC_WAIT = 0x01, 298 WASM_OPCODE_I32_ATOMIC_STORE = 0x17, 299 WASM_OPCODE_I32_RMW_CMPXCHG = 0x48, 300 }; 301 302 enum : unsigned { 303 WASM_LIMITS_FLAG_NONE = 0x0, 304 WASM_LIMITS_FLAG_HAS_MAX = 0x1, 305 WASM_LIMITS_FLAG_IS_SHARED = 0x2, 306 WASM_LIMITS_FLAG_IS_64 = 0x4, 307 }; 308 309 enum : unsigned { 310 WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, 311 WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, 312 }; 313 314 enum : unsigned { 315 WASM_ELEM_SEGMENT_IS_PASSIVE = 0x01, 316 WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER = 0x02, 317 WASM_ELEM_SEGMENT_HAS_INIT_EXPRS = 0x04, 318 }; 319 const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_KIND = 0x3; 320 321 // Feature policy prefixes used in the custom "target_features" section 322 enum : uint8_t { 323 WASM_FEATURE_PREFIX_USED = '+', 324 WASM_FEATURE_PREFIX_REQUIRED = '=', 325 WASM_FEATURE_PREFIX_DISALLOWED = '-', 326 }; 327 328 // Kind codes used in the custom "name" section 329 enum : unsigned { 330 WASM_NAMES_FUNCTION = 1, 331 WASM_NAMES_LOCAL = 2, 332 WASM_NAMES_GLOBAL = 7, 333 WASM_NAMES_DATA_SEGMENT = 9, 334 }; 335 336 // Kind codes used in the custom "linking" section 337 enum : unsigned { 338 WASM_SEGMENT_INFO = 0x5, 339 WASM_INIT_FUNCS = 0x6, 340 WASM_COMDAT_INFO = 0x7, 341 WASM_SYMBOL_TABLE = 0x8, 342 }; 343 344 // Kind codes used in the custom "dylink" section 345 enum : unsigned { 346 WASM_DYLINK_MEM_INFO = 0x1, 347 WASM_DYLINK_NEEDED = 0x2, 348 WASM_DYLINK_EXPORT_INFO = 0x3, 349 }; 350 351 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO 352 enum : unsigned { 353 WASM_COMDAT_DATA = 0x0, 354 WASM_COMDAT_FUNCTION = 0x1, 355 // GLOBAL, TAG, and TABLE are in here but LLVM doesn't use them yet. 356 WASM_COMDAT_SECTION = 0x5, 357 }; 358 359 // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE 360 enum WasmSymbolType : unsigned { 361 WASM_SYMBOL_TYPE_FUNCTION = 0x0, 362 WASM_SYMBOL_TYPE_DATA = 0x1, 363 WASM_SYMBOL_TYPE_GLOBAL = 0x2, 364 WASM_SYMBOL_TYPE_SECTION = 0x3, 365 WASM_SYMBOL_TYPE_TAG = 0x4, 366 WASM_SYMBOL_TYPE_TABLE = 0x5, 367 }; 368 369 enum WasmSegmentFlag : unsigned { 370 WASM_SEG_FLAG_STRINGS = 0x1, 371 WASM_SEG_FLAG_TLS = 0x2, 372 }; 373 374 // Kinds of tag attributes. 375 enum WasmTagAttribute : uint8_t { 376 WASM_TAG_ATTRIBUTE_EXCEPTION = 0x0, 377 }; 378 379 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; 380 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; 381 382 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; 383 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; 384 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; 385 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; 386 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; 387 const unsigned WASM_SYMBOL_UNDEFINED = 0x10; 388 const unsigned WASM_SYMBOL_EXPORTED = 0x20; 389 const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; 390 const unsigned WASM_SYMBOL_NO_STRIP = 0x80; 391 const unsigned WASM_SYMBOL_TLS = 0x100; 392 393 #define WASM_RELOC(name, value) name = value, 394 395 enum : unsigned { 396 #include "WasmRelocs.def" 397 }; 398 399 #undef WASM_RELOC 400 401 // Subset of types that a value can have 402 enum class ValType { 403 I32 = WASM_TYPE_I32, 404 I64 = WASM_TYPE_I64, 405 F32 = WASM_TYPE_F32, 406 F64 = WASM_TYPE_F64, 407 V128 = WASM_TYPE_V128, 408 FUNCREF = WASM_TYPE_FUNCREF, 409 EXTERNREF = WASM_TYPE_EXTERNREF, 410 }; 411 412 struct WasmSignature { 413 SmallVector<ValType, 1> Returns; 414 SmallVector<ValType, 4> Params; 415 // Support empty and tombstone instances, needed by DenseMap. 416 enum { Plain, Empty, Tombstone } State = Plain; 417 WasmSignatureWasmSignature418 WasmSignature(SmallVector<ValType, 1> &&InReturns, 419 SmallVector<ValType, 4> &&InParams) 420 : Returns(InReturns), Params(InParams) {} 421 WasmSignature() = default; 422 }; 423 424 // Useful comparison operators 425 inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { 426 return LHS.State == RHS.State && LHS.Returns == RHS.Returns && 427 LHS.Params == RHS.Params; 428 } 429 430 inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { 431 return !(LHS == RHS); 432 } 433 434 inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 435 return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; 436 } 437 438 inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 439 return !(LHS == RHS); 440 } 441 442 inline bool operator==(const WasmLimits &LHS, const WasmLimits &RHS) { 443 return LHS.Flags == RHS.Flags && LHS.Minimum == RHS.Minimum && 444 (LHS.Flags & WASM_LIMITS_FLAG_HAS_MAX ? LHS.Maximum == RHS.Maximum 445 : true); 446 } 447 448 inline bool operator==(const WasmTableType &LHS, const WasmTableType &RHS) { 449 return LHS.ElemType == RHS.ElemType && LHS.Limits == RHS.Limits; 450 } 451 452 std::string toString(WasmSymbolType type); 453 std::string relocTypetoString(uint32_t type); 454 bool relocTypeHasAddend(uint32_t type); 455 456 } // end namespace wasm 457 } // end namespace llvm 458 459 #endif 460