Files
Odin/core/rexcode/ir/wasm/wasm.odin

111 lines
4.7 KiB
Odin

// rexcode · Brendan Punsky (dotbmp@github), original author
// Ginger Bill (gingerBill@github)
// rexcode/ir/wasm -- the WebAssembly intermediate representation.
//
// WASM is a stack bytecode: a byte stream with LEB128 immediates, one encoding
// form per opcode, over an *implicit value stack* with a minimal type system.
// On the two axes that sort the IR family (docs/ir_design.md §2) it is
// **table-driven** on encoding -- a static `opcode -> operand-layout` table,
// exactly the ISA `ENCODING_TABLE` shape -- and **STACK** on dataflow (the one
// outlier among the modelled IRs; SPIR-V/LLVM are SSA).
//
// So this package is a sibling of the SPIR-V package under `ir/`: it re-exports
// the shared `ir` vocabulary (Module / Function / Block / Operation / Operand /
// Type / Id / ...), owns a `u16` `Opcode` (the WASM opcode set, with the 0xFC/
// 0xFD/0xFE prefix groups folded in), a static `ENCODING_TABLE` that drives a
// byte/LEB codec, the three Module-based verbs (`encode` / `decode` / `print`),
// a `Relocation` for object-file index fixups, and the WASM value-type model.
//
// This is the migration anticipated by docs/ir_design.md §4: WASM was shaped as
// an ISA arch package (`core:rexcode/wasm`); its real `encode`/`decode` already
// dropped the ISA verbs' `label_defs`/`resolve`/`base_address` (WASM has no
// PC-relative pass -- branches carry structured label depths), so moving it onto
// the `ir` Module/Operation/Operand model is a change of *leaf shape*, not of
// codec. The table-driven codec below is carried over intact; what changed is
// the leaf (`ir.Operation` in place of the old fixed-operand `Instruction`), the
// operand model (`ir.Operand`, with WASM memarg/blocktype/lane riding in `aux`),
// and the unit of work (an `ir.Module` of functions->blocks->operations).
package rexcode_wasm
import "core:rexcode/ir"
// =============================================================================
// SECTION: Re-exported shared vocabulary (the IR naming contract, ir_design §4)
// =============================================================================
//
// A consumer sees one namespace -- `wasm.Operation`, `wasm.Operand`, ... -- the
// way an arch package re-exports `isa`. `Module` is NOT re-exported: WASM's
// module carries container sections (types / imports / exports / ...) the shared
// core has no slot for, so it is a superset struct embedding `ir.Module`; see
// module.odin (exactly as `spirv.Module` does).
Function :: ir.Function
Block :: ir.Block
Global :: ir.Global
Operation :: ir.Operation
Operation_Flags :: ir.Operation_Flags
Operand :: ir.Operand
Operand_Kind :: ir.Operand_Kind
Result :: ir.Result
Type :: ir.Type
Type_Ref :: ir.Type_Ref
Type_Kind :: ir.Type_Kind
Id :: ir.Id
Ref :: ir.Ref
Ref_Space :: ir.Ref_Space
Symbol_Table :: ir.Symbol_Table
Dataflow :: ir.Dataflow
Error :: ir.Error
Error_Code :: ir.Error_Code
Token :: ir.Token
Token_Kind :: ir.Token_Kind
Print_Options :: ir.Print_Options
Print_Result :: ir.Print_Result
ID_NONE :: ir.ID_NONE
TYPE_NONE :: ir.TYPE_NONE
DEFAULT_PRINT_OPTIONS :: ir.DEFAULT_PRINT_OPTIONS
print_hex :: ir.print_hex
print_decimal :: ir.print_decimal
// Shared operand / type / ref constructors (WASM adds the dialect helpers -- a
// memarg, a blocktype, a lane index -- in operands.odin).
op_int :: ir.op_int
op_float :: ir.op_float
op_type :: ir.op_type
op_ref :: ir.op_ref
op_value :: ir.op_value
op_block :: ir.op_block
operand_id :: ir.operand_id
operand_type :: ir.operand_type
ref :: ir.ref
type_void :: ir.type_void
type_int :: ir.type_int
type_float :: ir.type_float
type_vector :: ir.type_vector
type_pointer :: ir.type_pointer
symbol_table_init :: ir.symbol_table_init
symbol_table_destroy :: ir.symbol_table_destroy
symbol_define :: ir.symbol_define
symbol_reserve :: ir.symbol_reserve
symbol_lookup :: ir.symbol_lookup
// =============================================================================
// SECTION: Physical format (WebAssembly core spec §5 -- the byte stream)
// =============================================================================
// The four bytes that begin every module: "\0asm" as a little-endian u32.
WASM_MAGIC :: u32(0x6d73_6100)
WASM_VERSION :: u32(1)
// Opcode-space prefix bytes. A prefixed opcode is `prefix byte` then an unsigned
// LEB128 sub-opcode (SIMD reaches 0x113, so the sub-opcode can be two bytes).
PREFIX_NONE :: u8(0x00)
PREFIX_MISC :: u8(0xFC) // saturating truncation, bulk memory / table
PREFIX_SIMD :: u8(0xFD) // vector (v128)
PREFIX_ATOM :: u8(0xFE) // threads / atomics