Commit Graph

17870 Commits

Author SHA1 Message Date
Brendan Punsky
d39cf98931 rexcode/ir/spirv: encoded_size + measure-mode writer
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.
2026-06-26 13:34:53 -04:00
Brendan Punsky
6665d5b552 rexcode/ir/spirv: generate the typed builders (both layers) from the grammar
Extend tablegen to emit builders_gen.odin -- 723 opcodes get a low-level
inst_<OpName>(buf, ...) constructor and a high-level Builder method, mapping each
grammar operand to a typed param (IdResultType->Type_Ref, IdResult->auto-allocated
Id, IdRef->Id, LiteralInteger->i64, ValueEnum/BitEnum->the typed enum, trailing
IdRef* -> []Id). builder.odin keeps just the hand-written Builder infrastructure.

Skipped (stay hand-writable, like an ISA's can_generate_builder): operands that
aren't simple typed params yet (optional, Pair* composites, LiteralString),
type-declaration opcodes (those are ir.Type), and verbs colliding with Odin
keywords/builtins (return_, switch_, size_of, ...).

Validated: a function body built via i_add / return_ encodes + round-trips
byte-exact (builder_made test) -> 10 passed.
2026-06-26 13:32:07 -04:00
Brendan Punsky
dfbb0abed3 rexcode/ir/spirv: typed instruction builders (foundation)
Two layers, the SPIR-V analog of an ISA's mnemonic builders:
  - low level: inst_<OpName>(buf, ...) -> Operation, stateless + alloc-free, the
    caller owns the operand backing (SPIR-V operands are a slice, so unlike an
    ISA's inline [4]Operand they can't be owned by the return value).
  - high level: a Builder owning operand storage + a result-<id> allocator;
    iadd/load/store/call/variable/ret/ret_value append to the current block and
    return the new <id>.

Hand-written here for a representative slice (Id / no-result / variadic / enum
operands) to fix the pattern; tablegen will generate the full per-opcode set.
Validated: a builder-made function body round-trips byte-exact.
2026-06-26 13:23:55 -04:00
Brendan Punsky
c2a5091336 rexcode/ir/spirv: round-trip opaque types (image/sampler/event/...) verbatim
Type-defining instructions the codec doesn't model structurally -- OpTypeImage,
OpTypeSampler, OpTypeSampledImage, OpTypeMatrix, OpTypeOpaque, OpTypeEvent,
OpTypeDeviceEvent, OpTypeReserveId, OpTypeQueue, OpTypePipe -- decode to
Type{.OPAQUE} plus an Opaque_Info{opcode, words} side entry (the operand words
after the result <id>) and re-emit verbatim. One generic fallback covers every
opaque SPIR-V type byte-exact, with no per-type fields.

Test: image_type (OpTypeImage, 7 operands) round-trips -> 9 passed.
2026-06-26 12:11:25 -04:00
Brendan Punsky
ac1d51a0cd rexcode/ir/spirv: printer -- BitEnum names + trailing enum-param operands
- 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.
2026-06-26 12:09:05 -04:00
Brendan Punsky
0cd5ed84b2 rexcode/ir/spirv: dependency-ordered definitions + runtime arrays
- Definition order: Module.defs records the exact type/constant/global
  interleaving (SPIR-V's single 'types, constants, global variables' section must
  be dependency-ordered -- a length constant before the array type that uses it,
  etc.). decode records it; encode replays it for byte-exact, spec-valid output
  (empty defs falls back to all-types, then -constants, then -globals).
  emit_one_type/constant/global factored out for the replay; no encoder alloc.
- OpTypeRuntimeArray: ARRAY with len_ref == ID_NONE (vs OpTypeArray's <id> length).

Tests: bool_and_array sets defs so OpConstant precedes OpTypeArray (verified in
disasm); runtime_array added -> 7 passed.
2026-06-26 12:04:27 -04:00
Brendan Punsky
fe27dcdbd4 rexcode/ir: add Type_Kind.BOOL + array <id> length; SPIR-V bool/array round-trip
Extend the shared type model so SPIR-V's OpTypeBool and OpTypeArray (whose length
is a constant <id>, not a literal) lower cleanly:
  - ir.Type_Kind gains BOOL (a distinct boolean; LLVM i1 will use it too).
  - ir.Type gains len_ref: Id -- an ARRAY length carried as a constant <id>
    (alongside the existing literal count for dialects with literal lengths).
  - type_bool / type_array constructors.

SPIR-V codec: OpTypeBool <-> Type{.BOOL}; OpTypeArray <-> Type{.ARRAY, elem,
len_ref}. Test bool_and_array round-trips byte-exact -> 6 passed.

NOTE: a spec-valid module orders an array's length constant before the array
type; the codec round-trips the shape byte-exact regardless, but emitting the
types/constants section in dependency order is a follow-up.
2026-06-26 11:45:35 -04:00
Brendan Punsky
7a8dc34d5f rexcode/ir/spirv: confirm big-endian decode (round-trip test)
The decoder already detects endianness from the magic word and byte-swaps each
word; strings are read from word values, so both endiannesses decode. Lock it in:
the round-trip helper now also byte-swaps every word to big-endian, decodes, and
asserts the re-encoding reproduces the original little-endian bytes -- across all
5 cases.
2026-06-26 11:23:38 -04:00
Brendan Punsky
0f5fa3d1d9 rexcode: wire the ir/ packages into build.lua
build.lua was ISA-centric; add an IRS catalog (ir/<name>) and route it through
the gen / check / test tasks. IR packages have a single-stage generator (gen.odin
emits Odin directly), a plain odin check, and a tests/ suite -- no mnemonic
builders or external-assembler verify, so only those three tasks apply. Purely
additive: the ISA catalog, task functions, and verify-tool probing are untouched.

luajit build.lua --check --test now reports spirv alongside the ISAs
(check ok, test 5 passed).
2026-06-26 11:21:33 -04:00
Brendan Punsky
4de6a7e6b6 rexcode/ir/spirv: printer -- symbolic ValueEnum names + computed bound in header
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.
2026-06-26 11:17:39 -04:00
Brendan Punsky
35fac68c7c rexcode/ir/spirv: codec completeness -- function params, computed bound, enum-param operands
- OpFunctionParameter: the entry block's Block.params round-trip as
  OpFunctionParameter (emitted between OpFunction and the entry OpLabel, decoded
  back onto the entry block).
- encode computes bound (max <id> + 1) when the caller leaves it 0; a non-zero
  bound (e.g. from decode) is preserved, so re-encode is stable.
- Trailing operands an enum value/bit pulls in (MemoryAccess Aligned's alignment,
  ...) are captured on decode as literals, so enum-parameter instructions
  re-encode byte-exact.

Tests: param_function + load_aligned added -> 5 passed.
2026-06-26 11:14:12 -04:00
Brendan Punsky
47c23d6d35 rexcode/ir/spirv: printer (disassembly) -- the third ir verb
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.
2026-06-26 11:05:14 -04:00
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
Brendan Punsky
3d852158bc rexcode/x86: generate the encode-recipe table (drop the @init interim)
Move ENCODE_RECIPES from a startup-built (@init) static table in the library to
a generated, #loaded table like every other one. The tablegen runs
form_to_recipe over every form, serializes to x86.encode_recipes.bin, and the
loader #loads it -- no @init, no allocation; the forms remain the single source
of truth and the recipe is derived from them.

- tablegen/gen.odin: ENCODE_RECIPES added to the BLOBS manifest (which drives
  both the Stage B serializer and the loader's #load); emit the generated-package
  global plus an @init that fills it from ENCODE_FORMS via lib.form_to_recipe.
- encoder_recipe.odin: drop the @init, the static storage, and the ENCODE_RECIPES
  declaration. form_to_recipe stays -- now solely the tablegen-time derivation.
- tables.odin, generated/{encode_tables,writer}.odin: regenerated.
- tables/x86.encode_recipes.bin: the generated blob (28260 bytes = 2355 x 12).

No behavior change: the recipes are identical to the @init ones. gen / builders /
check / test / idempotent green (2282 cases, 22 byte-stable artifacts); encode
perf unchanged.
2026-06-26 05:08:39 -04:00
gingerBill
19bb9070e1 Add @(require_results) where missing 2026-06-23 13:24:25 +01:00
gingerBill
f3a275c4dc Merge branch 'master' into bill/rexcode 2026-06-23 13:21:46 +01:00
gingerBill
8c63a70aad Fix identation 2026-06-23 13:14:56 +01:00
gingerBill
87297950c1 Merge pull request #6435 from mtarik34b/improve-flags-bitset-support
Improve `bit_set` support in the `flags` package
2026-06-23 12:50:21 +01:00
gingerBill
2b684ed1ec Add json.unparse allowing for json.Value to io.Writer without the need for RTTI 2026-06-23 12:47:38 +01:00
gingerBill
6698ebacb1 Integrate docs from PR #5119 2026-06-23 12:35:58 +01:00
gingerBill
a1fe7222bb Remove using fmt for example docs 2026-06-23 12:28:27 +01:00
gingerBill
28df949279 Fix typo 2026-06-23 12:25:36 +01:00
gingerBill
ebcf85a1fd Merge branch 'master' of https://github.com/odin-lang/Odin 2026-06-23 12:21:39 +01:00
gingerBill
7d36866fe9 pool -> arena 2026-06-23 12:21:29 +01:00
gingerBill
dc7cfbf443 Merge pull request #6671 from MaierN/master
fix memory leak and inconsistency in os.read_entire_file_from_file
2026-06-23 12:20:36 +01:00
gingerBill
82b2b293e9 Merge pull request #6515 from Peter0x44/master
Add missing rlgl bindings for raylib 5.5
2026-06-23 12:19:08 +01:00
gingerBill
1b75c44508 Change mem.Dynamic_Arena's alignment to be minimum_alignment 2026-06-23 12:18:15 +01:00
gingerBill
e30da0beb3 Remove old dynamic_pool_ aliases 2026-06-23 12:10:26 +01:00
gingerBill
bc1d6eb240 Merge branch 'master' of https://github.com/odin-lang/Odin 2026-06-23 12:10:00 +01:00
gingerBill
a95d45e913 Fix typo 2026-06-23 12:09:51 +01:00
gingerBill
3b56706439 Merge pull request #6471 from Carlyle-Foster/master
rename DEFAULT_PAGE_SIZE to PAGE_SIZE
2026-06-23 12:08:37 +01:00
gingerBill
8f83598750 Correct numerous issues with SDL3 and add missing procedures 2026-06-23 12:03:36 +01:00
gingerBill
0fdc0fd9da Merge pull request #5662 from leecommamichael/stbtt_types
[vendor:stb_truetype] amend PackFontRanges types
2026-06-23 11:51:19 +01:00
gingerBill
e3729aefc3 Add Maybe to SDL3 RenderGeometry 2026-06-23 11:50:33 +01:00
gingerBill
5ba39f42ea Improve error message on calls with varying argument count 2026-06-23 11:49:00 +01:00
gingerBill
a20363c2bf Add windows.GetConsoleScreenBufferInfoEx 2026-06-23 11:46:37 +01:00
gingerBill
8397c83560 Merge pull request #5508 from Paul-Andre/print-errors-before-assert
Flush accumulated errors before printing assert
2026-06-23 11:41:48 +01:00
gingerBill
38fa18023d Use intrinsics.count_leading_zeros internally for math.next_power_of_two 2026-06-23 11:39:19 +01:00
gingerBill
8afac0f32f Ignore the previous commit :D 2026-06-22 16:15:26 +01:00
gingerBill
13832011fa Add core:time/tzdata to examples/all 2026-06-22 16:12:44 +01:00
gingerBill
36e14eba48 Merge branch 'master' into bill/rexcode 2026-06-22 15:44:52 +01:00
gingerBill
3bbeecea41 Merge branch 'master' of https://github.com/odin-lang/Odin 2026-06-22 15:41:52 +01:00
gingerBill
d16a37e649 Add warning to help very large return values (partially fixes #6568) 2026-06-22 15:41:43 +01:00
Jeroen van Rijn
6bae6eb3f1 Clarify "it" 2026-06-22 15:46:02 +02:00
Jeroen van Rijn
8148b04a6c Add missing word. 2026-06-22 15:44:11 +02:00