HLO: skainet-io-iree-params with IrpaWriter + emit #flow.parameter.named (PR C of #523)#525
Merged
michalharakal merged 1 commit intodevelopfrom Apr 19, 2026
Merged
Conversation
Writes IREE parameter archives (.irpa) consumable by `iree-compile --iree-opt-import-parameters=<path>` and by `iree-run-module --parameters=<scope>=<path>`. The archive format per IREE's `parameter_archive.h`: +--- 40 B ----+ fixed header (magic "IRPA", version, counts) +--- 48 B ----+ three segment references +--- pad 16 --+ +-------------+ entry segment: 80-byte DATA records +-------------+ metadata segment: concatenated key bytes +--- pad 64 --+ +-------------+ storage segment: raw tensor bytes per entry All u16/u32/u64 values little-endian. The C entry-header struct has an implicit 4-byte pad after `u32 type` to align the following `u64 flags` — the writer emits that pad explicitly and a byte-level test pins the 80-byte layout so future changes can't silently re-break it. No scope column in the archive itself: scope is a runtime binding (`--parameters=<scope>=<file>`). Callers with multiple scopes group via `IrpaWriter.groupByScope(refs)` and emit one .irpa per scope. The writer delegates byte sourcing to `BufferHandle`; Owned and Borrowed variants are wired today, with Mapped / FileBacked landing in PR E (#523) to give the gguf and safetensors loaders a zero-copy path into the archive. ### Companion fix in skainet-compile-hlo PR B (#524) emitted `util.global private @key : type` without an initializer, which iree-compile treats as uninitialized — it would not import anything from a .irpa. PR C completes the emission: util.global private @key = #flow.parameter.named<"scope"::"key"> : type %r = util.global.load @key : type `MlirValidator` was also taught to accept module-scope `util.global` assignments: the `@`-prefixed symbol is a global, not an SSA value, and must not trip the existing `%`-only SSA-format check. ### Tests - IrpaWriterTest pins the byte layout against the IREE spec — header magic/version, segment offsets, entry-record fields, key concatenation, data placement with 64-byte per-entry alignment, Owned / Borrowed handle support, groupByScope ordering, empty- input rejection. - Existing ConstantMaterializationPolicyTest updated to assert the new `#flow.parameter.named<...>` initializer on every externalized global. - Full `:skainet-compile:skainet-compile-hlo:jvmTest` and `:skainet-io:skainet-io-iree-params:jvmTest` pass. ### Deferred verification A real `iree-compile --iree-opt-import-parameters=<written.irpa>` round-trip test will land once CI has an IREE toolchain available. Byte-level layout tests are a close proxy — any deviation from the reference C format breaks both. Part of #523. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced Apr 19, 2026
michalharakal
added a commit
that referenced
this pull request
Apr 19, 2026
Fixes `./gradlew allTests` configuration failure on develop: the module declared a `js()` target but depends on :skainet-compile-hlo, which does not publish one. Gradle resolution fails with a platform-type variant mismatch (consumer wants `js`, producer only has `wasm`). Wasm targets stay — they use a distinct `wasm` platform attribute that :skainet-compile-hlo does publish. This fix was originally part of PR #525 (commit fdd378e) but got dropped during the merge; only the first commit landed. Re-applying as a standalone, narrow fix. Closes #527 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
skainet-io-iree-params(peer ofskainet-io-gguf/skainet-io-safetensors) withIrpaWriter: streams IREE parameter archives (.irpa) fromList<ExternalParameterRef>.util.global private @key = #flow.parameter.named<\"scope\"::\"key\"> : typeinstead of an uninitialized global — this is what binds the symbol to the archive entry atiree-compile --iree-opt-import-parameters=<path>time.MlirValidatorupdated to accept module-scopeutil.globalbindings (they use@-prefixed symbols, not%-prefixed SSA values).Format notes
Byte layout per IREE's
parameter_archive.h: 40-byte v0 header + 48-byte segment refs, then entry / metadata / storage segments with 16- and 64-byte alignments respectively. The C entry-header struct has an implicit 4-byte pad afteru32 typeto alignu64 flags— the writer emits that explicitly and a byte-level test pins the 80-byte entry size so the wire format cannot drift silently.Scope is not encoded in the archive. A
.irpabinds to one scope at runtime via--parameters=<scope>=<file>.irpa.IrpaWriter.groupByScope(refs)helps callers split multi-scope inputs.What's NOT here
iree-compileround-trip yet — needs an IREE toolchain in CI. Byte-level layout tests stand in: any drift from the reference C format breaks them.BufferHandlepath — that's PR E (Mapped/FileBacked). Writer acceptsOwned+Borrowedtoday; other flavors raise with a pointer to PR E.Test plan
IrpaWriterTest.testHeaderMagicAndVersion—\"IRPA\"magic, v0.0,header_size = 40.testEntryCountAndSegmentOffsets— segment offsets match the spec layout for a 2-entry archive.testDataEntryLayout— 80-byte entry record with the post-typepad in the right place.testKeysAndDataRoundTripExactly— concatenated keys + per-entry data at 64-aligned storage offsets.testEmptyInputIsRejectedLoudly,testGroupByScopePreservesOrder,testOwnedBufferHandleWithOffsetAndBorrowedBoth.:skainet-compile:skainet-compile-hlo:jvmTestand:skainet-io:skainet-io-iree-params:jvmTestgreen.iree-compile --iree-opt-import-parameters=<written.irpa>once a CI toolchain exists.Part of #523. After this lands, PR D (skainet-whisper wiring) and PR E (mmap in gguf + safetensors) can proceed in parallel on disjoint modules.
🤖 Generated with Claude Code