Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:43:22

0001 //===- Wasm.h - Wasm object file format -------------------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 //
0009 // This file defines manifest constants for the wasm object file format.
0010 // See: https://github.com/WebAssembly/design/blob/main/BinaryEncoding.md
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_BINARYFORMAT_WASM_H
0015 #define LLVM_BINARYFORMAT_WASM_H
0016 
0017 #include "llvm/ADT/ArrayRef.h"
0018 #include "llvm/ADT/SmallVector.h"
0019 #include "llvm/ADT/StringRef.h"
0020 #include <optional>
0021 
0022 namespace llvm {
0023 namespace wasm {
0024 
0025 // Object file magic string.
0026 const char WasmMagic[] = {'\0', 'a', 's', 'm'};
0027 // Wasm binary format version
0028 const uint32_t WasmVersion = 0x1;
0029 // Wasm linking metadata version
0030 const uint32_t WasmMetadataVersion = 0x2;
0031 // Wasm uses a 64k page size
0032 const uint32_t WasmPageSize = 65536;
0033 
0034 enum : unsigned {
0035   WASM_SEC_CUSTOM = 0,     // Custom / User-defined section
0036   WASM_SEC_TYPE = 1,       // Function signature declarations
0037   WASM_SEC_IMPORT = 2,     // Import declarations
0038   WASM_SEC_FUNCTION = 3,   // Function declarations
0039   WASM_SEC_TABLE = 4,      // Indirect function table and other tables
0040   WASM_SEC_MEMORY = 5,     // Memory attributes
0041   WASM_SEC_GLOBAL = 6,     // Global declarations
0042   WASM_SEC_EXPORT = 7,     // Exports
0043   WASM_SEC_START = 8,      // Start function declaration
0044   WASM_SEC_ELEM = 9,       // Elements section
0045   WASM_SEC_CODE = 10,      // Function bodies (code)
0046   WASM_SEC_DATA = 11,      // Data segments
0047   WASM_SEC_DATACOUNT = 12, // Data segment count
0048   WASM_SEC_TAG = 13,       // Tag declarations
0049   WASM_SEC_LAST_KNOWN = WASM_SEC_TAG,
0050 };
0051 
0052 // Type immediate encodings used in various contexts.
0053 enum : unsigned {
0054   WASM_TYPE_I32 = 0x7F,
0055   WASM_TYPE_I64 = 0x7E,
0056   WASM_TYPE_F32 = 0x7D,
0057   WASM_TYPE_F64 = 0x7C,
0058   WASM_TYPE_V128 = 0x7B,
0059   WASM_TYPE_NULLFUNCREF = 0x73,
0060   WASM_TYPE_NULLEXTERNREF = 0x72,
0061   WASM_TYPE_NULLEXNREF = 0x74,
0062   WASM_TYPE_NULLREF = 0x71,
0063   WASM_TYPE_FUNCREF = 0x70,
0064   WASM_TYPE_EXTERNREF = 0x6F,
0065   WASM_TYPE_EXNREF = 0x69,
0066   WASM_TYPE_ANYREF = 0x6E,
0067   WASM_TYPE_EQREF = 0x6D,
0068   WASM_TYPE_I31REF = 0x6C,
0069   WASM_TYPE_STRUCTREF = 0x6B,
0070   WASM_TYPE_ARRAYREF = 0x6A,
0071   WASM_TYPE_NONNULLABLE = 0x64,
0072   WASM_TYPE_NULLABLE = 0x63,
0073   WASM_TYPE_FUNC = 0x60,
0074   WASM_TYPE_ARRAY = 0x5E,
0075   WASM_TYPE_STRUCT = 0x5F,
0076   WASM_TYPE_SUB = 0x50,
0077   WASM_TYPE_SUB_FINAL = 0x4F,
0078   WASM_TYPE_REC = 0x4E,
0079   WASM_TYPE_NORESULT = 0x40, // for blocks with no result values
0080 };
0081 
0082 // Kinds of externals (for imports and exports).
0083 enum : unsigned {
0084   WASM_EXTERNAL_FUNCTION = 0x0,
0085   WASM_EXTERNAL_TABLE = 0x1,
0086   WASM_EXTERNAL_MEMORY = 0x2,
0087   WASM_EXTERNAL_GLOBAL = 0x3,
0088   WASM_EXTERNAL_TAG = 0x4,
0089 };
0090 
0091 // Opcodes used in initializer expressions.
0092 enum : unsigned {
0093   WASM_OPCODE_END = 0x0b,
0094   WASM_OPCODE_CALL = 0x10,
0095   WASM_OPCODE_LOCAL_GET = 0x20,
0096   WASM_OPCODE_LOCAL_SET = 0x21,
0097   WASM_OPCODE_LOCAL_TEE = 0x22,
0098   WASM_OPCODE_GLOBAL_GET = 0x23,
0099   WASM_OPCODE_GLOBAL_SET = 0x24,
0100   WASM_OPCODE_I32_STORE = 0x36,
0101   WASM_OPCODE_I64_STORE = 0x37,
0102   WASM_OPCODE_I32_CONST = 0x41,
0103   WASM_OPCODE_I64_CONST = 0x42,
0104   WASM_OPCODE_F32_CONST = 0x43,
0105   WASM_OPCODE_F64_CONST = 0x44,
0106   WASM_OPCODE_I32_ADD = 0x6a,
0107   WASM_OPCODE_I32_SUB = 0x6b,
0108   WASM_OPCODE_I32_MUL = 0x6c,
0109   WASM_OPCODE_I64_ADD = 0x7c,
0110   WASM_OPCODE_I64_SUB = 0x7d,
0111   WASM_OPCODE_I64_MUL = 0x7e,
0112   WASM_OPCODE_REF_NULL = 0xd0,
0113   WASM_OPCODE_REF_FUNC = 0xd2,
0114   WASM_OPCODE_GC_PREFIX = 0xfb,
0115 };
0116 
0117 // Opcodes in the GC-prefixed space (0xfb)
0118 enum : unsigned {
0119   WASM_OPCODE_STRUCT_NEW = 0x00,
0120   WASM_OPCODE_STRUCT_NEW_DEFAULT = 0x01,
0121   WASM_OPCODE_ARRAY_NEW = 0x06,
0122   WASM_OPCODE_ARRAY_NEW_DEFAULT = 0x07,
0123   WASM_OPCODE_ARRAY_NEW_FIXED = 0x08,
0124   WASM_OPCODE_REF_I31 = 0x1c,
0125   // any.convert_extern and extern.convert_any don't seem to be supported by
0126   // Binaryen.
0127 };
0128 
0129 // Opcodes used in synthetic functions.
0130 enum : unsigned {
0131   WASM_OPCODE_BLOCK = 0x02,
0132   WASM_OPCODE_BR = 0x0c,
0133   WASM_OPCODE_BR_TABLE = 0x0e,
0134   WASM_OPCODE_RETURN = 0x0f,
0135   WASM_OPCODE_DROP = 0x1a,
0136   WASM_OPCODE_MISC_PREFIX = 0xfc,
0137   WASM_OPCODE_MEMORY_INIT = 0x08,
0138   WASM_OPCODE_MEMORY_FILL = 0x0b,
0139   WASM_OPCODE_DATA_DROP = 0x09,
0140   WASM_OPCODE_ATOMICS_PREFIX = 0xfe,
0141   WASM_OPCODE_ATOMIC_NOTIFY = 0x00,
0142   WASM_OPCODE_I32_ATOMIC_WAIT = 0x01,
0143   WASM_OPCODE_I32_ATOMIC_STORE = 0x17,
0144   WASM_OPCODE_I32_RMW_CMPXCHG = 0x48,
0145 };
0146 
0147 // Sub-opcodes for catch clauses in a try_table instruction
0148 enum : unsigned {
0149   WASM_OPCODE_CATCH = 0x00,
0150   WASM_OPCODE_CATCH_REF = 0x01,
0151   WASM_OPCODE_CATCH_ALL = 0x02,
0152   WASM_OPCODE_CATCH_ALL_REF = 0x03,
0153 };
0154 
0155 enum : unsigned {
0156   WASM_LIMITS_FLAG_NONE = 0x0,
0157   WASM_LIMITS_FLAG_HAS_MAX = 0x1,
0158   WASM_LIMITS_FLAG_IS_SHARED = 0x2,
0159   WASM_LIMITS_FLAG_IS_64 = 0x4,
0160 };
0161 
0162 enum : unsigned {
0163   WASM_DATA_SEGMENT_IS_PASSIVE = 0x01,
0164   WASM_DATA_SEGMENT_HAS_MEMINDEX = 0x02,
0165 };
0166 
0167 enum : unsigned {
0168   WASM_ELEM_SEGMENT_IS_PASSIVE = 0x01,
0169   WASM_ELEM_SEGMENT_IS_DECLARATIVE = 0x02,   // if passive == 1
0170   WASM_ELEM_SEGMENT_HAS_TABLE_NUMBER = 0x02, // if passive == 0
0171   WASM_ELEM_SEGMENT_HAS_INIT_EXPRS = 0x04,
0172 };
0173 const unsigned WASM_ELEM_SEGMENT_MASK_HAS_ELEM_DESC = 0x3;
0174 
0175 // Feature policy prefixes used in the custom "target_features" section
0176 enum : uint8_t {
0177   WASM_FEATURE_PREFIX_USED = '+',
0178   WASM_FEATURE_PREFIX_DISALLOWED = '-',
0179 };
0180 
0181 // Kind codes used in the custom "name" section
0182 enum : unsigned {
0183   WASM_NAMES_MODULE = 0,
0184   WASM_NAMES_FUNCTION = 1,
0185   WASM_NAMES_LOCAL = 2,
0186   WASM_NAMES_GLOBAL = 7,
0187   WASM_NAMES_DATA_SEGMENT = 9,
0188 };
0189 
0190 // Kind codes used in the custom "linking" section
0191 enum : unsigned {
0192   WASM_SEGMENT_INFO = 0x5,
0193   WASM_INIT_FUNCS = 0x6,
0194   WASM_COMDAT_INFO = 0x7,
0195   WASM_SYMBOL_TABLE = 0x8,
0196 };
0197 
0198 // Kind codes used in the custom "dylink" section
0199 enum : unsigned {
0200   WASM_DYLINK_MEM_INFO = 0x1,
0201   WASM_DYLINK_NEEDED = 0x2,
0202   WASM_DYLINK_EXPORT_INFO = 0x3,
0203   WASM_DYLINK_IMPORT_INFO = 0x4,
0204 };
0205 
0206 // Kind codes used in the custom "linking" section in the WASM_COMDAT_INFO
0207 enum : unsigned {
0208   WASM_COMDAT_DATA = 0x0,
0209   WASM_COMDAT_FUNCTION = 0x1,
0210   // GLOBAL, TAG, and TABLE are in here but LLVM doesn't use them yet.
0211   WASM_COMDAT_SECTION = 0x5,
0212 };
0213 
0214 // Kind codes used in the custom "linking" section in the WASM_SYMBOL_TABLE
0215 enum WasmSymbolType : unsigned {
0216   WASM_SYMBOL_TYPE_FUNCTION = 0x0,
0217   WASM_SYMBOL_TYPE_DATA = 0x1,
0218   WASM_SYMBOL_TYPE_GLOBAL = 0x2,
0219   WASM_SYMBOL_TYPE_SECTION = 0x3,
0220   WASM_SYMBOL_TYPE_TAG = 0x4,
0221   WASM_SYMBOL_TYPE_TABLE = 0x5,
0222 };
0223 
0224 enum WasmSegmentFlag : unsigned {
0225   WASM_SEG_FLAG_STRINGS = 0x1,
0226   WASM_SEG_FLAG_TLS = 0x2,
0227   WASM_SEG_FLAG_RETAIN = 0x4,
0228 };
0229 
0230 // Kinds of tag attributes.
0231 enum WasmTagAttribute : uint8_t {
0232   WASM_TAG_ATTRIBUTE_EXCEPTION = 0x0,
0233 };
0234 
0235 const unsigned WASM_SYMBOL_BINDING_MASK = 0x3;
0236 const unsigned WASM_SYMBOL_VISIBILITY_MASK = 0xc;
0237 
0238 const unsigned WASM_SYMBOL_BINDING_GLOBAL = 0x0;
0239 const unsigned WASM_SYMBOL_BINDING_WEAK = 0x1;
0240 const unsigned WASM_SYMBOL_BINDING_LOCAL = 0x2;
0241 const unsigned WASM_SYMBOL_VISIBILITY_DEFAULT = 0x0;
0242 const unsigned WASM_SYMBOL_VISIBILITY_HIDDEN = 0x4;
0243 const unsigned WASM_SYMBOL_UNDEFINED = 0x10;
0244 const unsigned WASM_SYMBOL_EXPORTED = 0x20;
0245 const unsigned WASM_SYMBOL_EXPLICIT_NAME = 0x40;
0246 const unsigned WASM_SYMBOL_NO_STRIP = 0x80;
0247 const unsigned WASM_SYMBOL_TLS = 0x100;
0248 const unsigned WASM_SYMBOL_ABSOLUTE = 0x200;
0249 
0250 #define WASM_RELOC(name, value) name = value,
0251 
0252 enum : unsigned {
0253 #include "WasmRelocs.def"
0254 };
0255 
0256 #undef WASM_RELOC
0257 
0258 struct WasmObjectHeader {
0259   StringRef Magic;
0260   uint32_t Version;
0261 };
0262 
0263 // Subset of types that a value can have
0264 enum class ValType {
0265   I32 = WASM_TYPE_I32,
0266   I64 = WASM_TYPE_I64,
0267   F32 = WASM_TYPE_F32,
0268   F64 = WASM_TYPE_F64,
0269   V128 = WASM_TYPE_V128,
0270   FUNCREF = WASM_TYPE_FUNCREF,
0271   EXTERNREF = WASM_TYPE_EXTERNREF,
0272   EXNREF = WASM_TYPE_EXNREF,
0273   // Unmodeled value types include ref types with heap types other than
0274   // func, extern or exn, and type-specialized funcrefs
0275   OTHERREF = 0xff,
0276 };
0277 
0278 struct WasmDylinkImportInfo {
0279   StringRef Module;
0280   StringRef Field;
0281   uint32_t Flags;
0282 };
0283 
0284 struct WasmDylinkExportInfo {
0285   StringRef Name;
0286   uint32_t Flags;
0287 };
0288 
0289 struct WasmDylinkInfo {
0290   uint32_t MemorySize; // Memory size in bytes
0291   uint32_t MemoryAlignment;  // P2 alignment of memory
0292   uint32_t TableSize;  // Table size in elements
0293   uint32_t TableAlignment;  // P2 alignment of table
0294   std::vector<StringRef> Needed; // Shared library dependencies
0295   std::vector<WasmDylinkImportInfo> ImportInfo;
0296   std::vector<WasmDylinkExportInfo> ExportInfo;
0297 };
0298 
0299 struct WasmProducerInfo {
0300   std::vector<std::pair<std::string, std::string>> Languages;
0301   std::vector<std::pair<std::string, std::string>> Tools;
0302   std::vector<std::pair<std::string, std::string>> SDKs;
0303 };
0304 
0305 struct WasmFeatureEntry {
0306   uint8_t Prefix;
0307   std::string Name;
0308 };
0309 
0310 struct WasmExport {
0311   StringRef Name;
0312   uint8_t Kind;
0313   uint32_t Index;
0314 };
0315 
0316 struct WasmLimits {
0317   uint8_t Flags;
0318   uint64_t Minimum;
0319   uint64_t Maximum;
0320 };
0321 
0322 struct WasmTableType {
0323   ValType ElemType;
0324   WasmLimits Limits;
0325 };
0326 
0327 struct WasmTable {
0328   uint32_t Index;
0329   WasmTableType Type;
0330   StringRef SymbolName; // from the "linking" section
0331 };
0332 
0333 struct WasmInitExprMVP {
0334   uint8_t Opcode;
0335   union {
0336     int32_t Int32;
0337     int64_t Int64;
0338     uint32_t Float32;
0339     uint64_t Float64;
0340     uint32_t Global;
0341   } Value;
0342 };
0343 
0344 // Extended-const init exprs and exprs with GC types are not explicitly
0345 // modeled, but the raw body of the expr is attached.
0346 struct WasmInitExpr {
0347   uint8_t Extended; // Set to non-zero if extended const is used (i.e. more than
0348                     // one instruction)
0349   WasmInitExprMVP Inst;
0350   ArrayRef<uint8_t> Body;
0351 };
0352 
0353 struct WasmGlobalType {
0354   uint8_t Type; // TODO: make this a ValType?
0355   bool Mutable;
0356 };
0357 
0358 struct WasmGlobal {
0359   uint32_t Index;
0360   WasmGlobalType Type;
0361   WasmInitExpr InitExpr;
0362   StringRef SymbolName; // from the "linking" section
0363   uint32_t Offset; // Offset of the definition in the binary's Global section
0364   uint32_t Size;   // Size of the definition in the binary's Global section
0365 };
0366 
0367 struct WasmTag {
0368   uint32_t Index;
0369   uint32_t SigIndex;
0370   StringRef SymbolName; // from the "linking" section
0371 };
0372 
0373 struct WasmImport {
0374   StringRef Module;
0375   StringRef Field;
0376   uint8_t Kind;
0377   union {
0378     uint32_t SigIndex;
0379     WasmGlobalType Global;
0380     WasmTableType Table;
0381     WasmLimits Memory;
0382   };
0383 };
0384 
0385 struct WasmLocalDecl {
0386   uint8_t Type;
0387   uint32_t Count;
0388 };
0389 
0390 struct WasmFunction {
0391   uint32_t Index;
0392   uint32_t SigIndex;
0393   std::vector<WasmLocalDecl> Locals;
0394   ArrayRef<uint8_t> Body;
0395   uint32_t CodeSectionOffset;
0396   uint32_t Size;
0397   uint32_t CodeOffset;  // start of Locals and Body
0398   std::optional<StringRef> ExportName; // from the "export" section
0399   StringRef SymbolName; // from the "linking" section
0400   StringRef DebugName;  // from the "name" section
0401   uint32_t Comdat;      // from the "comdat info" section
0402 };
0403 
0404 struct WasmDataSegment {
0405   uint32_t InitFlags;
0406   // Present if InitFlags & WASM_DATA_SEGMENT_HAS_MEMINDEX.
0407   uint32_t MemoryIndex;
0408   // Present if InitFlags & WASM_DATA_SEGMENT_IS_PASSIVE == 0.
0409   WasmInitExpr Offset;
0410 
0411   ArrayRef<uint8_t> Content;
0412   StringRef Name; // from the "segment info" section
0413   uint32_t Alignment;
0414   uint32_t LinkingFlags;
0415   uint32_t Comdat; // from the "comdat info" section
0416 };
0417 
0418 // 3 different element segment modes are encodable. This class is currently
0419 // only used during decoding (see WasmElemSegment below).
0420 enum class ElemSegmentMode { Active, Passive, Declarative };
0421 
0422 // Represents a Wasm element segment, with some limitations compared the spec:
0423 // 1) Does not model passive or declarative segments (Segment will end up with
0424 // an Offset field of i32.const 0)
0425 // 2) Does not model init exprs (Segment will get an empty Functions list)
0426 // 3) Does not model types other than basic funcref/externref/exnref (see
0427 // ValType)
0428 struct WasmElemSegment {
0429   uint32_t Flags;
0430   uint32_t TableNumber;
0431   ValType ElemKind;
0432   WasmInitExpr Offset;
0433   std::vector<uint32_t> Functions;
0434 };
0435 
0436 // Represents the location of a Wasm data symbol within a WasmDataSegment, as
0437 // the index of the segment, and the offset and size within the segment.
0438 struct WasmDataReference {
0439   uint32_t Segment;
0440   uint64_t Offset;
0441   uint64_t Size;
0442 };
0443 
0444 struct WasmRelocation {
0445   uint8_t Type;    // The type of the relocation.
0446   uint32_t Index;  // Index into either symbol or type index space.
0447   uint64_t Offset; // Offset from the start of the section.
0448   int64_t Addend;  // A value to add to the symbol.
0449 };
0450 
0451 struct WasmInitFunc {
0452   uint32_t Priority;
0453   uint32_t Symbol;
0454 };
0455 
0456 struct WasmSymbolInfo {
0457   StringRef Name;
0458   uint8_t Kind;
0459   uint32_t Flags;
0460   // For undefined symbols the module of the import
0461   std::optional<StringRef> ImportModule;
0462   // For undefined symbols the name of the import
0463   std::optional<StringRef> ImportName;
0464   // For symbols to be exported from the final module
0465   std::optional<StringRef> ExportName;
0466   union {
0467     // For function, table, or global symbols, the index in function, table, or
0468     // global index space.
0469     uint32_t ElementIndex;
0470     // For a data symbols, the address of the data relative to segment.
0471     WasmDataReference DataRef;
0472   };
0473 };
0474 
0475 enum class NameType {
0476   FUNCTION,
0477   GLOBAL,
0478   DATA_SEGMENT,
0479 };
0480 
0481 struct WasmDebugName {
0482   NameType Type;
0483   uint32_t Index;
0484   StringRef Name;
0485 };
0486 
0487 // Info from the linking metadata section of a wasm object file.
0488 struct WasmLinkingData {
0489   uint32_t Version;
0490   std::vector<WasmInitFunc> InitFunctions;
0491   std::vector<StringRef> Comdats;
0492   // The linking section also contains a symbol table. This info (represented
0493   // in a WasmSymbolInfo struct) is stored inside the WasmSymbol object instead
0494   // of in this structure; this allows vectors of WasmSymbols and
0495   // WasmLinkingDatas to be reallocated.
0496 };
0497 
0498 struct WasmSignature {
0499   SmallVector<ValType, 1> Returns;
0500   SmallVector<ValType, 4> Params;
0501   // LLVM can parse types other than functions encoded in the type section,
0502   // but does not actually model them. Instead a placeholder signature is
0503   // created in the Object's signature list.
0504   enum { Function, Tag, Placeholder } Kind = Function;
0505   // Support empty and tombstone instances, needed by DenseMap.
0506   enum { Plain, Empty, Tombstone } State = Plain;
0507 
0508   WasmSignature(SmallVector<ValType, 1> &&InReturns,
0509                 SmallVector<ValType, 4> &&InParams)
0510       : Returns(InReturns), Params(InParams) {}
0511   WasmSignature() = default;
0512 };
0513 
0514 // Useful comparison operators
0515 inline bool operator==(const WasmSignature &LHS, const WasmSignature &RHS) {
0516   return LHS.State == RHS.State && LHS.Returns == RHS.Returns &&
0517          LHS.Params == RHS.Params;
0518 }
0519 
0520 inline bool operator!=(const WasmSignature &LHS, const WasmSignature &RHS) {
0521   return !(LHS == RHS);
0522 }
0523 
0524 inline bool operator==(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
0525   return LHS.Type == RHS.Type && LHS.Mutable == RHS.Mutable;
0526 }
0527 
0528 inline bool operator!=(const WasmGlobalType &LHS, const WasmGlobalType &RHS) {
0529   return !(LHS == RHS);
0530 }
0531 
0532 inline bool operator==(const WasmLimits &LHS, const WasmLimits &RHS) {
0533   return LHS.Flags == RHS.Flags && LHS.Minimum == RHS.Minimum &&
0534          (LHS.Flags & WASM_LIMITS_FLAG_HAS_MAX ? LHS.Maximum == RHS.Maximum
0535                                                : true);
0536 }
0537 
0538 inline bool operator==(const WasmTableType &LHS, const WasmTableType &RHS) {
0539   return LHS.ElemType == RHS.ElemType && LHS.Limits == RHS.Limits;
0540 }
0541 
0542 llvm::StringRef toString(WasmSymbolType type);
0543 llvm::StringRef relocTypetoString(uint32_t type);
0544 llvm::StringRef sectionTypeToString(uint32_t type);
0545 bool relocTypeHasAddend(uint32_t type);
0546 
0547 } // end namespace wasm
0548 } // end namespace llvm
0549 
0550 #endif