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 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 WasmTagType { 105 // Kind of tag. Currently only WASM_TAG_ATTRIBUTE_EXCEPTION is possible. 106 uint8_t Attribute; 107 uint32_t SigIndex; 108 }; 109 110 struct WasmTag { 111 uint32_t Index; 112 WasmTagType 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 WasmTagType Tag; 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 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_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, TAG, 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_TAG = 0x4, 357 WASM_SYMBOL_TYPE_TABLE = 0x5, 358 }; 359 360 enum WasmSegmentFlag : unsigned { 361 WASM_SEG_FLAG_STRINGS = 0x1, 362 WASM_SEG_FLAG_TLS = 0x2, 363 }; 364 365 // Kinds of tag attributes. 366 enum WasmTagAttribute : uint8_t { 367 WASM_TAG_ATTRIBUTE_EXCEPTION = 0x0, 368 }; 369 370 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; 371 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; 372 373 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; 374 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; 375 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; 376 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; 377 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; 378 const unsigned WASM_SYMBOL_UNDEFINED = 0x10; 379 const unsigned WASM_SYMBOL_EXPORTED = 0x20; 380 const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; 381 const unsigned WASM_SYMBOL_NO_STRIP = 0x80; 382 383 #define WASM_RELOC(name, value) name = value, 384 385 enum : unsigned { 386 #include "WasmRelocs.def" 387 }; 388 389 #undef WASM_RELOC 390 391 // Subset of types that a value can have 392 enum class ValType { 393 I32 = WASM_TYPE_I32, 394 I64 = WASM_TYPE_I64, 395 F32 = WASM_TYPE_F32, 396 F64 = WASM_TYPE_F64, 397 V128 = WASM_TYPE_V128, 398 FUNCREF = WASM_TYPE_FUNCREF, 399 EXTERNREF = WASM_TYPE_EXTERNREF, 400 }; 401 402 struct WasmSignature { 403 SmallVector<ValType, 1> Returns; 404 SmallVector<ValType, 4> Params; 405 // Support empty and tombstone instances, needed by DenseMap. 406 enum { Plain, Empty, Tombstone } State = Plain; 407 WasmSignatureWasmSignature408 WasmSignature(SmallVector<ValType, 1> &&InReturns, 409 SmallVector<ValType, 4> &&InParams) 410 : Returns(InReturns), Params(InParams) {} 411 WasmSignature() = default; 412 }; 413 414 // Useful comparison operators 415 inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { 416 return LHS.State == RHS.State && LHS.Returns == RHS.Returns && 417 LHS.Params == RHS.Params; 418 } 419 420 inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { 421 return !(LHS == RHS); 422 } 423 424 inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 425 return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; 426 } 427 428 inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 429 return !(LHS == RHS); 430 } 431 432 inline bool operator==(const WasmLimits &LHS, const WasmLimits &RHS) { 433 return LHS.Flags == RHS.Flags && LHS.Minimum == RHS.Minimum && 434 (LHS.Flags & WASM_LIMITS_FLAG_HAS_MAX ? LHS.Maximum == RHS.Maximum 435 : true); 436 } 437 438 inline bool operator==(const WasmTableType &LHS, const WasmTableType &RHS) { 439 return LHS.ElemType == RHS.ElemType && LHS.Limits == RHS.Limits; 440 } 441 442 std::string toString(WasmSymbolType type); 443 std::string relocTypetoString(uint32_t type); 444 bool relocTypeHasAddend(uint32_t type); 445 446 } // end namespace wasm 447 } // end namespace llvm 448 449 #endif 450