Commit Graph

6 Commits

Author SHA1 Message Date
Brendan Punsky
ded7a2dea0 rexcode/ir/spirv: codec round-trip test suite
A tests/ package (the ISA test convention) that, per module shape, does
encode -> decode -> re-encode and asserts byte-identical output -- exercising the
encoder, decoder, <id> side tables, and the generic operation codec together:

  void_main      header + preamble + a void function (116 B)
  int_constants  i32 type + two scalar OpConstants incl. 0xDEADBEEF (88 B)
  iadd_function  %r = OpIAdd %i32 %a %b ; OpReturn -- generic operand codec
                 with a result + value operands (164 B)

3 passed. Run: odin run core/rexcode/ir/spirv/tests. (build.lua is ISA-centric;
wiring the ir/ packages into the gen/check/test pipeline is a follow-up.)
2026-06-26 09:43:59 -04:00
Brendan Punsky
be65df38c1 rexcode/ir/spirv: decoder + byte-exact round-trip
The inverse of the encoder: read the header (detecting endianness from the
magic word), walk the instruction stream, and lower each instruction by opcode
back into the structured Module -- the ir core (types/constants/globals/
functions, the generic table-driven operation decode), the SPIR-V sections
(preamble / debug / annotations), and the flat <id> space into the side id
tables (with an id->Type_Ref map so type-naming operands recover TYPE operands).

Single allocator pass (context.allocator), one reused per-instruction word
scratch buffer. Validated: encode -> decode -> re-encode is byte-exact on the
void compute main module (116 bytes; caps/types/functions/blocks/ops/ids/bound
all recovered). Same gaps as the encoder (OpFunctionParameter, ARRAY/bool,
enum-parameter operands); big-endian sources a later refinement.
2026-06-26 09:41:27 -04:00
Brendan Punsky
737db89ad0 rexcode/ir/spirv: complete the encoder -- types, constants, globals, function bodies
The second half of encode(): the <id> side tables (Module.type_ids /
global_ids / function_ids -- SPIR-V's flat id space, which ir.Type/Global/
Function don't carry) plus the lowering:

  emit_types       ir.Type -> OpTypeXxx (void/int/float/vector/pointer/struct/
                   function; INT signedness + POINTER storage class ride in aux)
  emit_constants   OpConstant / OpConstantComposite / true/false/null
  emit_globals     OpVariable (storage class from the pointer type)
  emit_operation   generic table-driven op emit: INSTRUCTION_INDEX gives the
                   result-type/result-id prefix, the rest stream from op.operands
  emit_functions   OpFunction / OpLabel / body / OpFunctionEnd

Validated: a complete void compute main module encodes to byte-exact-correct
SPIR-V (29 words, all checked). Known gaps: OpFunctionParameter, ARRAY/bool
types, explicit enum-parameter operands, computed bound. Decoder next.
2026-06-26 09:24:52 -04:00
Brendan Punsky
18f9f141e4 rexcode/ir/spirv: encoder foundation -- header + preamble/debug/annotation sections
The Module -> word-stream encoder's first half: a fast single-pass word writer
(one host-endian store per word; instruction headers written as a placeholder
and backpatched, so variable-length instructions need no measure pass) plus the
header and the preamble / debug / annotation sections in spec layout order
(capabilities, extensions, ext-inst imports, memory model, entry points,
execution modes, OpString/OpSource/OpName, decorations).

Validated: a minimal module encodes to byte-exact-correct SPIR-V (magic, v1.5,
OpCapability Shader, OpMemoryModel Logical GLSL450, OpEntryPoint GLCompute %main,
NUL-terminated 'main' string, correct backpatched word counts).

Types/constants/globals/function bodies (the <id> + type lowering) are next.
2026-06-26 07:33:01 -04:00
Brendan Punsky
d027fbf938 rexcode/ir/spirv: generate the operand-layout table (codec dispatch data)
Extend the tablegen to emit encoding_table.odin from the grammar -- the
per-opcode operand layout that drives the codec:

  INSTRUCTION_SPECS   flat []Operand_Spec {Spec_Kind, Quantifier}
  INSTRUCTION_INDEX   [max_opcode+1]Spec_Run -- O(1) opcode -> its operand run
  ENUM_PARAMS         enumerant -> trailing-parameter operands, so the codec
  PARAM_SPECS         reads MemoryAccess.Aligned / OpExecutionMode LocalSize /
                      Decoration.SpecId etc. correctly

873 opcodes, 3693 operand specs. Package compiles.
2026-06-26 07:08:50 -04:00
Brendan Punsky
7a8684f541 rexcode/ir/spirv: scaffold the SPIR-V IR package (foundation + generated tables)
Start the SPIR-V intermediate representation under core/rexcode/ir/spirv,
following the ir API (docs/ir_design.md) and the ISA package conventions. SPIR-V
is table-driven on encoding and SSA on dataflow, so it re-exports the shared ir
vocabulary and is laid out like an arch package.

  spirv.odin          package + ir re-exports + physical format (MAGIC, version,
                      Header, wordCount<<16|opcode framing)
  module.odin         Module :: struct { using base: ir.Module, ...sections... } --
                      capabilities, ext-imports, entry points, exec modes, constant
                      pool, decorations, debug; SPIR-V's module metadata has no
                      ir.Module slot, so it is carried alongside the core
  reloc.odin          Relocation (linkage import/export)
  opcodes.odin        GENERATED: the Opcode enum (873 opcodes)
  operand_kinds.odin  GENERATED: ValueEnum/BitEnum operand kinds + Spec_Kind
  tablegen/gen.odin   the generator (core:encoding/json)
  tablegen/spirv.core.grammar.json  vendored authoritative grammar (Khronos
                      SPIRV-Headers unified1) -- single source of truth

Generating from the authoritative grammar avoids hand-transcription errors
(hand-authoring had Quads/Aliased/... wrong). Package compiles. Codec
(encode/decode + flat<->structured lowering), printer, and tests are next.
2026-06-26 06:53:46 -04:00