Add a count-only mode to the Writer (advance pos without storing) and factor the
section walk into emit_module, so encode and the new encoded_size(m) share one
path. encoded_size returns the exact byte count encode will produce -- the SPIR-V
analog of an ISA's encode_max_code_size, here exact rather than an upper bound.
The printer now sizes its scratch buffer with it instead of retry-on-overflow.
Verified: encoded_size == encode byte_count; suite 10 passed.
- fmt_bitenum prints the common BitEnum operands as their set bits' names joined
with '|' (or None when empty): FunctionControl, MemoryAccess, SelectionControl,
LoopControl, ImageOperands -- so OpFunction ... None, OpLoad ... Aligned.
- fmt_inst now also prints words trailing the fixed operand layout (the params an
enum value/bit pulls in, e.g. MemoryAccess Aligned's alignment), previously
dropped: OpLoad %2 %7 Aligned 16.
fmt_enum prints the common ValueEnum operands by name (Capability Shader,
Addressing/Memory model Logical GLSL450, ExecutionModel GLCompute, StorageClass,
Decoration, ...); BitEnums stay numeric (their bit_set %v form is too verbose to
read inline). The header comment now reads version/generator/bound from the
encoded words, so Bound reflects the computed value, not the pre-encode 0.
print(m, sb, options): disassemble a Module into a spirv-dis-style listing.
Encodes to a scratch buffer (doubling on overflow) and walks the word stream
generically through the operand-layout table, so every opcode disassembles with
no per-op code -- Id operands as %id, LiteralString quoted, the result-id column
right-aligned before OpName:
; SPIR-V
; Version: 1.5
; Bound: 9
%2 = OpTypeInt 32 1
%4 = OpConstant %2 10
%6 = OpIAdd %2 %4 %5
OpReturn
Enums print numerically for now (symbolic names a refinement). Completes the
encode / decode / print verb triad.