feat(toolchain): regenerate memcpy.s/memset.s from musl with a generator script#2780
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
This comment has been minimized.
This comment has been minimized.
a5eb4e7 to
f188273
Compare
This comment was marked as outdated.
This comment was marked as outdated.
f188273 to
6a7dfe2
Compare
This comment was marked as outdated.
This comment was marked as outdated.
6a7dfe2 to
5334d9b
Compare
This comment was marked as outdated.
This comment was marked as outdated.
5334d9b to
333748f
Compare
This comment was marked as outdated.
This comment was marked as outdated.
333748f to
b2a8a0a
Compare
This comment was marked as outdated.
This comment was marked as outdated.
…tor script
Replaces the glibc-derived assembly in `crates/toolchain/openvm/src/`
with musl-libc-derived equivalents, and adds a script that regenerates
them deterministically from upstream sources.
## Motivation
The current `memcpy.s` and `memset.s` were generated from glibc but
checked in without a license header. glibc is LGPL-2.1+, which carries
attribution requirements; musl-libc is MIT, matching the lineage used
in the v2.0.0 series (`develop-v2.0.0-rc.1`).
Separately, `memcpy.s` contained an orphan jump table label `.LJTI0_0`
without a function-prefix. LLVM emits the same name for the first jump
table of "function 0" in any translation unit, so under fat LTO a guest
binary whose user code happens to lower a `match` into a jump table
collides with memcpy's:
error: symbol '.LJTI0_0' is already defined
## What's in this commit
- `scripts/generate_libc_intrinsics.sh`: fetches musl sources at a
pinned commit, strips `#include` lines, compiles with
`clang -target riscv64 -march=rv64im -O3 -funroll-loops`, then
prefixes every per-TU local label (`.LBB0_*`, `.LJTI0_*`,
`.Lfunc_end0`) with the function name. Accepts `--musl-commit` and
`--clang` flags with sensible defaults. Idempotent — rerunning
produces byte-identical output for a given clang/musl pair.
- `crates/toolchain/openvm/src/{memcpy,memset}.s`: regenerated from
musl `37e18b7bf3...` with the embedded COPYRIGHT header.
- `crates/toolchain/openvm/README.md`: pointer to the generator.
## Verification
scripts/generate_libc_intrinsics.sh && git diff --exit-code \
crates/toolchain/openvm/src/memcpy.s \
crates/toolchain/openvm/src/memset.s
passes on a fresh checkout (clang 22.1.1 on aarch64-darwin).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
b2a8a0a to
9c8ce6e
Compare
|
Claude finished @shuklaayush's task in 2m 18s —— View job Code Review: PR #2780 — Regenerate memcpy.s/memset.s from musl
Well-motivated PR. The licensing fix (glibc LGPL → musl MIT) is important, the Looks goodLabel collision fix is correct. The old Annotated tag handling is correct. The Reproducibility is solid. License headers are complete. Both generated files embed the full musl MIT license text (COPYRIGHT file), properly attributed. The old files had no license header at all despite being derived from glibc (LGPL). README is accurate. The Nits / observations (non-blocking)
SummaryThe core change is sound and the script is well-crafted. No blocking issues found. LGTM. |
Note: cells_used metrics omitted because CUDA tracegen does not expose unpadded trace heights. Commit: 9c8ce6e |
…tor script (#2780) ## Summary - Replaces the glibc-derived `memcpy.s` / `memset.s` in `crates/toolchain/openvm/src/` with musl-libc equivalents (MIT-licensed; matches the v2.0.0 lineage). - Adds `scripts/generate_libc_intrinsics.sh` to regenerate both files deterministically from upstream sources. - Fixes an LLVM jump-table label collision that prevented guest binaries with dense user code from linking under fat LTO. ## Why Two problems with the current state: 1. **Licensing**: the existing files were compiled from glibc (LGPL-2.1+) but checked in without a license header or attribution. musl-libc (MIT) is permissive and was the original source used in the v2.0.x branch (`develop-v2.0.0-rc.1`), so switching back is both more permissive and continuity-preserving. 2. **Symbol collision under fat LTO**: the glibc-derived `memcpy.s` defined an orphan jump table `.LJTI0_0` (without a function prefix). LLVM emits the same name for the first jump table of "function 0" in any translation unit, so user code that happens to lower a `match` into a jump table — combined with `lto = "fat"` merging crates into a single LLVM module — causes: ``` error: symbol '.LJTI0_0' is already defined ``` The musl-derived equivalents have no jump table (at `-O3 -funroll-loops`, musl's memcpy unrolls fully), and the generator script prefixes every per-TU local label (`.LBB0_*`, `.LJTI0_*`, `.Lfunc_end0`) with the function name to make any future drift impossible. ## What's in the PR | File | Purpose | |---|---| | `scripts/generate_libc_intrinsics.sh` | Fetches musl sources at a pinned ref, strips `#include` lines, compiles with the recipe `clang -target riscv64 -march=rv64im -O3 -funroll-loops`, applies local-label prefixing, strips `.ident`, normalizes `.file`, and embeds musl `COPYRIGHT` in the file header. Accepts `--musl-ref <tag\|branch\|sha>` and `--clang <path>` with sensible defaults. Idempotent. | | `crates/toolchain/openvm/src/memcpy.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/src/memset.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/README.md` | Pointer to the generator. | ## Reproduce ```bash scripts/generate_libc_intrinsics.sh git diff --exit-code crates/toolchain/openvm/src/memcpy.s crates/toolchain/openvm/src/memset.s ``` Should produce no diff on a fresh checkout. The `.ident` directive is stripped during generation, so output bytes are independent of the clang distribution (Homebrew vs Debian vs Apple Clang); the only per-clang-version variation that remains is the `.attribute 5` ISA string (e.g. `"rv64im"` on clang ≤14 vs the canonical `"rv64i2p1_m2p0_zmmul1p0"` on clang ≥16) — same ISA, different recording. ## Test plan - [x] `scripts/generate_libc_intrinsics.sh` reruns produce byte-identical output (idempotent). - [x] Both regenerated files contain no orphan `.LJTI0_*` / `.LBB0_*` / `.Lfunc_end0` labels — every local label is function-prefixed. - [ ] CI on this PR (build, lint, riscv-test-vector, extension-tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tor script (#2780) ## Summary - Replaces the glibc-derived `memcpy.s` / `memset.s` in `crates/toolchain/openvm/src/` with musl-libc equivalents (MIT-licensed; matches the v2.0.0 lineage). - Adds `scripts/generate_libc_intrinsics.sh` to regenerate both files deterministically from upstream sources. - Fixes an LLVM jump-table label collision that prevented guest binaries with dense user code from linking under fat LTO. ## Why Two problems with the current state: 1. **Licensing**: the existing files were compiled from glibc (LGPL-2.1+) but checked in without a license header or attribution. musl-libc (MIT) is permissive and was the original source used in the v2.0.x branch (`develop-v2.0.0-rc.1`), so switching back is both more permissive and continuity-preserving. 2. **Symbol collision under fat LTO**: the glibc-derived `memcpy.s` defined an orphan jump table `.LJTI0_0` (without a function prefix). LLVM emits the same name for the first jump table of "function 0" in any translation unit, so user code that happens to lower a `match` into a jump table — combined with `lto = "fat"` merging crates into a single LLVM module — causes: ``` error: symbol '.LJTI0_0' is already defined ``` The musl-derived equivalents have no jump table (at `-O3 -funroll-loops`, musl's memcpy unrolls fully), and the generator script prefixes every per-TU local label (`.LBB0_*`, `.LJTI0_*`, `.Lfunc_end0`) with the function name to make any future drift impossible. ## What's in the PR | File | Purpose | |---|---| | `scripts/generate_libc_intrinsics.sh` | Fetches musl sources at a pinned ref, strips `#include` lines, compiles with the recipe `clang -target riscv64 -march=rv64im -O3 -funroll-loops`, applies local-label prefixing, strips `.ident`, normalizes `.file`, and embeds musl `COPYRIGHT` in the file header. Accepts `--musl-ref <tag\|branch\|sha>` and `--clang <path>` with sensible defaults. Idempotent. | | `crates/toolchain/openvm/src/memcpy.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/src/memset.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/README.md` | Pointer to the generator. | ## Reproduce ```bash scripts/generate_libc_intrinsics.sh git diff --exit-code crates/toolchain/openvm/src/memcpy.s crates/toolchain/openvm/src/memset.s ``` Should produce no diff on a fresh checkout. The `.ident` directive is stripped during generation, so output bytes are independent of the clang distribution (Homebrew vs Debian vs Apple Clang); the only per-clang-version variation that remains is the `.attribute 5` ISA string (e.g. `"rv64im"` on clang ≤14 vs the canonical `"rv64i2p1_m2p0_zmmul1p0"` on clang ≥16) — same ISA, different recording. ## Test plan - [x] `scripts/generate_libc_intrinsics.sh` reruns produce byte-identical output (idempotent). - [x] Both regenerated files contain no orphan `.LJTI0_*` / `.LBB0_*` / `.Lfunc_end0` labels — every local label is function-prefixed. - [ ] CI on this PR (build, lint, riscv-test-vector, extension-tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tor script (#2780) ## Summary - Replaces the glibc-derived `memcpy.s` / `memset.s` in `crates/toolchain/openvm/src/` with musl-libc equivalents (MIT-licensed; matches the v2.0.0 lineage). - Adds `scripts/generate_libc_intrinsics.sh` to regenerate both files deterministically from upstream sources. - Fixes an LLVM jump-table label collision that prevented guest binaries with dense user code from linking under fat LTO. ## Why Two problems with the current state: 1. **Licensing**: the existing files were compiled from glibc (LGPL-2.1+) but checked in without a license header or attribution. musl-libc (MIT) is permissive and was the original source used in the v2.0.x branch (`develop-v2.0.0-rc.1`), so switching back is both more permissive and continuity-preserving. 2. **Symbol collision under fat LTO**: the glibc-derived `memcpy.s` defined an orphan jump table `.LJTI0_0` (without a function prefix). LLVM emits the same name for the first jump table of "function 0" in any translation unit, so user code that happens to lower a `match` into a jump table — combined with `lto = "fat"` merging crates into a single LLVM module — causes: ``` error: symbol '.LJTI0_0' is already defined ``` The musl-derived equivalents have no jump table (at `-O3 -funroll-loops`, musl's memcpy unrolls fully), and the generator script prefixes every per-TU local label (`.LBB0_*`, `.LJTI0_*`, `.Lfunc_end0`) with the function name to make any future drift impossible. ## What's in the PR | File | Purpose | |---|---| | `scripts/generate_libc_intrinsics.sh` | Fetches musl sources at a pinned ref, strips `#include` lines, compiles with the recipe `clang -target riscv64 -march=rv64im -O3 -funroll-loops`, applies local-label prefixing, strips `.ident`, normalizes `.file`, and embeds musl `COPYRIGHT` in the file header. Accepts `--musl-ref <tag\|branch\|sha>` and `--clang <path>` with sensible defaults. Idempotent. | | `crates/toolchain/openvm/src/memcpy.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/src/memset.s` | Regenerated from musl v1.2.6 (`9fa28ece75d8a2191de7c5bb53bed224c5947417`). | | `crates/toolchain/openvm/README.md` | Pointer to the generator. | ## Reproduce ```bash scripts/generate_libc_intrinsics.sh git diff --exit-code crates/toolchain/openvm/src/memcpy.s crates/toolchain/openvm/src/memset.s ``` Should produce no diff on a fresh checkout. The `.ident` directive is stripped during generation, so output bytes are independent of the clang distribution (Homebrew vs Debian vs Apple Clang); the only per-clang-version variation that remains is the `.attribute 5` ISA string (e.g. `"rv64im"` on clang ≤14 vs the canonical `"rv64i2p1_m2p0_zmmul1p0"` on clang ≥16) — same ISA, different recording. ## Test plan - [x] `scripts/generate_libc_intrinsics.sh` reruns produce byte-identical output (idempotent). - [x] Both regenerated files contain no orphan `.LJTI0_*` / `.LBB0_*` / `.Lfunc_end0` labels — every local label is function-prefixed. - [ ] CI on this PR (build, lint, riscv-test-vector, extension-tests). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
memcpy.s/memset.sincrates/toolchain/openvm/src/with musl-libc equivalents (MIT-licensed; matches the v2.0.0 lineage).scripts/generate_libc_intrinsics.shto regenerate both files deterministically from upstream sources.Why
Two problems with the current state:
Licensing: the existing files were compiled from glibc (LGPL-2.1+) but checked in without a license header or attribution. musl-libc (MIT) is permissive and was the original source used in the v2.0.x branch (
develop-v2.0.0-rc.1), so switching back is both more permissive and continuity-preserving.Symbol collision under fat LTO: the glibc-derived
memcpy.sdefined an orphan jump table.LJTI0_0(without a function prefix). LLVM emits the same name for the first jump table of "function 0" in any translation unit, so user code that happens to lower amatchinto a jump table — combined withlto = "fat"merging crates into a single LLVM module — causes:The musl-derived equivalents have no jump table (at
-O3 -funroll-loops, musl's memcpy unrolls fully), and the generator script prefixes every per-TU local label (.LBB0_*,.LJTI0_*,.Lfunc_end0) with the function name to make any future drift impossible.What's in the PR
scripts/generate_libc_intrinsics.sh#includelines, compiles with the recipeclang -target riscv64 -march=rv64im -O3 -funroll-loops, applies local-label prefixing, strips.ident, normalizes.file, and embeds muslCOPYRIGHTin the file header. Accepts--musl-ref <tag|branch|sha>and--clang <path>with sensible defaults. Idempotent.crates/toolchain/openvm/src/memcpy.s9fa28ece75d8a2191de7c5bb53bed224c5947417).crates/toolchain/openvm/src/memset.s9fa28ece75d8a2191de7c5bb53bed224c5947417).crates/toolchain/openvm/README.mdReproduce
Should produce no diff on a fresh checkout. The
.identdirective is stripped during generation, so output bytes are independent of the clang distribution (Homebrew vs Debian vs Apple Clang); the only per-clang-version variation that remains is the.attribute 5ISA string (e.g."rv64im"on clang ≤14 vs the canonical"rv64i2p1_m2p0_zmmul1p0"on clang ≥16) — same ISA, different recording.Test plan
scripts/generate_libc_intrinsics.shreruns produce byte-identical output (idempotent)..LJTI0_*/.LBB0_*/.Lfunc_end0labels — every local label is function-prefixed.🤖 Generated with Claude Code