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 Initial; 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 WasmEventType { 105 // Kind of event. Currently only WASM_EVENT_ATTRIBUTE_EXCEPTION is possible. 106 uint32_t Attribute; 107 uint32_t SigIndex; 108 }; 109 110 struct WasmEvent { 111 uint32_t Index; 112 WasmEventType 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 WasmEventType Event; 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 LinkerFlags; 158 uint32_t Comdat; // from the "comdat info" section 159 }; 160 161 struct WasmElemSegment { 162 uint32_t TableIndex; 163 WasmInitExpr Offset; 164 std::vector<uint32_t> Functions; 165 }; 166 167 // Represents the location of a Wasm data symbol within a WasmDataSegment, as 168 // the index of the segment, and the offset and size within the segment. 169 struct WasmDataReference { 170 uint32_t Segment; 171 uint64_t Offset; 172 uint64_t Size; 173 }; 174 175 struct WasmRelocation { 176 uint8_t Type; // The type of the relocation. 177 uint32_t Index; // Index into either symbol or type index space. 178 uint64_t Offset; // Offset from the start of the section. 179 int64_t Addend; // A value to add to the symbol. 180 }; 181 182 struct WasmInitFunc { 183 uint32_t Priority; 184 uint32_t Symbol; 185 }; 186 187 struct WasmSymbolInfo { 188 StringRef Name; 189 uint8_t Kind; 190 uint32_t Flags; 191 // For undefined symbols the module of the import 192 Optional<StringRef> ImportModule; 193 // For undefined symbols the name of the import 194 Optional<StringRef> ImportName; 195 // For symbols to be exported from the final module 196 Optional<StringRef> ExportName; 197 union { 198 // For function, table, or global symbols, the index in function, table, or 199 // global index space. 200 uint32_t ElementIndex; 201 // For a data symbols, the address of the data relative to segment. 202 WasmDataReference DataRef; 203 }; 204 }; 205 206 enum class NameType { 207 FUNCTION, 208 GLOBAL, 209 DATA_SEGMENT, 210 }; 211 212 struct WasmDebugName { 213 NameType Type; 214 uint32_t Index; 215 StringRef Name; 216 }; 217 218 struct WasmLinkingData { 219 uint32_t Version; 220 std::vector<WasmInitFunc> InitFunctions; 221 std::vector<StringRef> Comdats; 222 std::vector<WasmSymbolInfo> SymbolTable; 223 }; 224 225 enum : unsigned { 226 WASM_SEC_CUSTOM = 0, // Custom / User-defined section 227 WASM_SEC_TYPE = 1, // Function signature declarations 228 WASM_SEC_IMPORT = 2, // Import declarations 229 WASM_SEC_FUNCTION = 3, // Function declarations 230 WASM_SEC_TABLE = 4, // Indirect function table and other tables 231 WASM_SEC_MEMORY = 5, // Memory attributes 232 WASM_SEC_GLOBAL = 6, // Global declarations 233 WASM_SEC_EXPORT = 7, // Exports 234 WASM_SEC_START = 8, // Start function declaration 235 WASM_SEC_ELEM = 9, // Elements section 236 WASM_SEC_CODE = 10, // Function bodies (code) 237 WASM_SEC_DATA = 11, // Data segments 238 WASM_SEC_DATACOUNT = 12, // Data segment count 239 WASM_SEC_EVENT = 13 // Event declarations 240 }; 241 242 // Type immediate encodings used in various contexts. 243 enum : unsigned { 244 WASM_TYPE_I32 = 0x7F, 245 WASM_TYPE_I64 = 0x7E, 246 WASM_TYPE_F32 = 0x7D, 247 WASM_TYPE_F64 = 0x7C, 248 WASM_TYPE_V128 = 0x7B, 249 WASM_TYPE_FUNCREF = 0x70, 250 WASM_TYPE_EXTERNREF = 0x6F, 251 WASM_TYPE_FUNC = 0x60, 252 WASM_TYPE_NORESULT = 0x40, // for blocks with no result values 253 }; 254 255 // Kinds of externals (for imports and exports). 256 enum : unsigned { 257 WASM_EXTERNAL_FUNCTION = 0x0, 258 WASM_EXTERNAL_TABLE = 0x1, 259 WASM_EXTERNAL_MEMORY = 0x2, 260 WASM_EXTERNAL_GLOBAL = 0x3, 261 WASM_EXTERNAL_EVENT = 0x4, 262 }; 263 264 // Opcodes used in initializer expressions. 265 enum : unsigned { 266 WASM_OPCODE_END = 0x0b, 267 WASM_OPCODE_CALL = 0x10, 268 WASM_OPCODE_LOCAL_GET = 0x20, 269 WASM_OPCODE_LOCAL_SET = 0x21, 270 WASM_OPCODE_GLOBAL_GET = 0x23, 271 WASM_OPCODE_GLOBAL_SET = 0x24, 272 WASM_OPCODE_I32_STORE = 0x36, 273 WASM_OPCODE_I64_STORE = 0x37, 274 WASM_OPCODE_I32_CONST = 0x41, 275 WASM_OPCODE_I64_CONST = 0x42, 276 WASM_OPCODE_F32_CONST = 0x43, 277 WASM_OPCODE_F64_CONST = 0x44, 278 WASM_OPCODE_I32_ADD = 0x6a, 279 WASM_OPCODE_I64_ADD = 0x7c, 280 WASM_OPCODE_REF_NULL = 0xd0, 281 }; 282 283 // Opcodes used in synthetic functions. 284 enum : unsigned { 285 WASM_OPCODE_IF = 0x04, 286 WASM_OPCODE_ELSE = 0x05, 287 WASM_OPCODE_DROP = 0x1a, 288 WASM_OPCODE_MISC_PREFIX = 0xfc, 289 WASM_OPCODE_MEMORY_INIT = 0x08, 290 WASM_OPCODE_DATA_DROP = 0x09, 291 WASM_OPCODE_ATOMICS_PREFIX = 0xfe, 292 WASM_OPCODE_ATOMIC_NOTIFY = 0x00, 293 WASM_OPCODE_I32_ATOMIC_WAIT = 0x01, 294 WASM_OPCODE_I32_ATOMIC_STORE = 0x17, 295 WASM_OPCODE_I32_RMW_CMPXCHG = 0x48, 296 }; 297 298 enum : unsigned { 299 WASM_LIMITS_FLAG_NONE = 0x0, 300 WASM_LIMITS_FLAG_HAS_MAX = 0x1, 301 WASM_LIMITS_FLAG_IS_SHARED = 0x2, 302 WASM_LIMITS_FLAG_IS_64 = 0x4, 303 }; 304 305 enum : unsigned { 306 WASM_DATA_SEGMENT_IS_PASSIVE = 0x01, 307 WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02, 308 }; 309 310 // Feature policy prefixes used in the custom "target_features" section 311 enum : uint8_t { 312 WASM_FEATURE_PREFIX_USED = '+', 313 WASM_FEATURE_PREFIX_REQUIRED = '=', 314 WASM_FEATURE_PREFIX_DISALLOWED = '-', 315 }; 316 317 // Kind codes used in the custom "name" section 318 enum : unsigned { 319 WASM_NAMES_FUNCTION = 1, 320 WASM_NAMES_LOCAL = 2, 321 WASM_NAMES_GLOBAL = 7, 322 WASM_NAMES_DATA_SEGMENT = 9, 323 }; 324 325 // Kind codes used in the custom "linking" section 326 enum : unsigned { 327 WASM_SEGMENT_INFO = 0x5, 328 WASM_INIT_FUNCS = 0x6, 329 WASM_COMDAT_INFO = 0x7, 330 WASM_SYMBOL_TABLE = 0x8, 331 }; 332 333 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO 334 enum : unsigned { 335 WASM_COMDAT_DATA = 0x0, 336 WASM_COMDAT_FUNCTION = 0x1, 337 // GLOBAL, EVENT, and TABLE are in here but LLVM doesn't use them yet. 338 WASM_COMDAT_SECTION = 0x5, 339 }; 340 341 // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE 342 enum WasmSymbolType : unsigned { 343 WASM_SYMBOL_TYPE_FUNCTION = 0x0, 344 WASM_SYMBOL_TYPE_DATA = 0x1, 345 WASM_SYMBOL_TYPE_GLOBAL = 0x2, 346 WASM_SYMBOL_TYPE_SECTION = 0x3, 347 WASM_SYMBOL_TYPE_EVENT = 0x4, 348 WASM_SYMBOL_TYPE_TABLE = 0x5, 349 }; 350 351 // Kinds of event attributes. 352 enum WasmEventAttribute : unsigned { 353 WASM_EVENT_ATTRIBUTE_EXCEPTION = 0x0, 354 }; 355 356 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3; 357 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc; 358 359 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0; 360 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1; 361 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2; 362 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0; 363 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4; 364 const unsigned WASM_SYMBOL_UNDEFINED = 0x10; 365 const unsigned WASM_SYMBOL_EXPORTED = 0x20; 366 const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40; 367 const unsigned WASM_SYMBOL_NO_STRIP = 0x80; 368 369 #define WASM_RELOC(name, value) name = value, 370 371 enum : unsigned { 372 #include "WasmRelocs.def" 373 }; 374 375 #undef WASM_RELOC 376 377 // Subset of types that a value can have 378 enum class ValType { 379 I32 = WASM_TYPE_I32, 380 I64 = WASM_TYPE_I64, 381 F32 = WASM_TYPE_F32, 382 F64 = WASM_TYPE_F64, 383 V128 = WASM_TYPE_V128, 384 FUNCREF = WASM_TYPE_FUNCREF, 385 EXTERNREF = WASM_TYPE_EXTERNREF, 386 }; 387 388 struct WasmSignature { 389 SmallVector<ValType, 1> Returns; 390 SmallVector<ValType, 4> Params; 391 // Support empty and tombstone instances, needed by DenseMap. 392 enum { Plain, Empty, Tombstone } State = Plain; 393 WasmSignatureWasmSignature394 WasmSignature(SmallVector<ValType, 1> &&InReturns, 395 SmallVector<ValType, 4> &&InParams) 396 : Returns(InReturns), Params(InParams) {} 397 WasmSignature() = default; 398 }; 399 400 // Useful comparison operators 401 inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) { 402 return LHS.State == RHS.State && LHS.Returns == RHS.Returns && 403 LHS.Params == RHS.Params; 404 } 405 406 inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) { 407 return !(LHS == RHS); 408 } 409 410 inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 411 return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable; 412 } 413 414 inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) { 415 return !(LHS == RHS); 416 } 417 418 std::string toString(WasmSymbolType type); 419 std::string relocTypetoString(uint32_t type); 420 bool relocTypeHasAddend(uint32_t type); 421 422 } // end namespace wasm 423 } // end namespace llvm 424 425 #endif 426