Home | History | Annotate | Line # | Download | only in BinaryFormat
      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 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 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_EVENT = 13      // Event 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_EVENT = 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, EVENT, 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_EVENT = 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 event attributes.
    366 enum WasmEventAttribute : unsigned {
    367   WASM_EVENT_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 
    408   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 std::string toString(WasmSymbolType type);
    433 std::string relocTypetoString(uint32_t type);
    434 bool relocTypeHasAddend(uint32_t type);
    435 
    436 } // end namespace wasm
    437 } // end namespace llvm
    438 
    439 #endif
    440