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