diff --git a/.github/actions/setup-llvm22/action.yml b/.github/actions/setup-llvm22/action.yml new file mode 100644 index 0000000000..75672bcbc3 --- /dev/null +++ b/.github/actions/setup-llvm22/action.yml @@ -0,0 +1,72 @@ +name: Setup LLVM 22 +description: > + Provision the LLVM 22 development libraries that `llvm-inprocess` links + against, and export LLVM_SYS_221_PREFIX. Every job that compiles Rust needs + this now that the feature is on by default. + +# One definition, not 44 inline recipes. The three platforms need three +# different sources and only one of them is obvious: +# +# macOS brew's llvm formula. +# Linux apt.llvm.org. The distro's `llvm-dev` is whatever the release +# froze on (Ubuntu 24.04 ships 18), so the LLVM project's own +# repository is the only way to get a pinned 22. +# Windows the official `clang+llvm-*-pc-windows-msvc` tarball. NOT +# chocolatey: its `llvm` package is the clang *toolchain* — no +# llvm-config.exe and none of the static libraries llvm-sys links +# against — and it has no 22.x pin at all. +# +# Every arm asserts the major version. llvm-sys 221 requires LLVM 22 +# specifically, and a runner image moving its formula on must fail loudly +# here rather than build something subtly different several steps later. +inputs: + version: + description: LLVM major.minor.patch used by the Windows tarball + required: false + default: "22.1.8" + +runs: + using: composite + steps: + - name: LLVM 22 (macOS, brew) + if: runner.os == 'macOS' + shell: bash + run: | + set -euo pipefail + brew install llvm@22 2>/dev/null || brew install llvm + PREFIX="$(brew --prefix llvm@22 2>/dev/null || brew --prefix llvm)" + "$PREFIX/bin/llvm-config" --version | grep -q '^22\.' \ + || { echo "::error::brew LLVM is not 22.x ($("$PREFIX/bin/llvm-config" --version))"; exit 1; } + echo "LLVM_SYS_221_PREFIX=$PREFIX" >> "$GITHUB_ENV" + + - name: LLVM 22 (Linux, apt.llvm.org) + if: runner.os == 'Linux' + shell: bash + run: | + set -euo pipefail + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key \ + | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc >/dev/null + . /etc/os-release + echo "deb http://apt.llvm.org/${VERSION_CODENAME}/ llvm-toolchain-${VERSION_CODENAME}-22 main" \ + | sudo tee /etc/apt/sources.list.d/llvm22.list >/dev/null + sudo apt-get update -qq + sudo DEBIAN_FRONTEND=noninteractive apt-get install -y -qq \ + llvm-22-dev libpolly-22-dev libzstd-dev + llvm-config-22 --version | grep -q '^22\.' \ + || { echo "::error::apt LLVM is not 22.x"; exit 1; } + echo "LLVM_SYS_221_PREFIX=$(llvm-config-22 --prefix)" >> "$GITHUB_ENV" + + - name: LLVM 22 (Windows, official MSVC tarball) + if: runner.os == 'Windows' + shell: pwsh + run: | + $ErrorActionPreference = "Stop" + $ver = "${{ inputs.version }}" + $url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-$ver/clang+llvm-$ver-x86_64-pc-windows-msvc.tar.xz" + Write-Host "downloading $url" + curl.exe -sSL --retry 3 -o "$env:RUNNER_TEMP\llvm.tar.xz" $url + New-Item -ItemType Directory -Force -Path C:\llvm | Out-Null + tar -xf "$env:RUNNER_TEMP\llvm.tar.xz" -C C:\llvm --strip-components=1 + $v = & "C:\llvm\bin\llvm-config.exe" --version + if (-not $v.StartsWith("22.")) { Write-Error "LLVM is not 22.x ($v)"; exit 1 } + "LLVM_SYS_221_PREFIX=C:\llvm" | Out-File -FilePath $env:GITHUB_ENV -Append diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 7a404a5277..615386c92c 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -43,6 +43,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo uses: actions/cache@v6 @@ -264,6 +265,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo uses: actions/cache@v6 @@ -361,6 +363,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Measure clean-build time run: | diff --git a/.github/workflows/cache-warm.yml b/.github/workflows/cache-warm.yml index 0328abccec..bbc9000ba3 100644 --- a/.github/workflows/cache-warm.yml +++ b/.github/workflows/cache-warm.yml @@ -64,6 +64,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 diff --git a/.github/workflows/container-tests.yml b/.github/workflows/container-tests.yml index d4ec4579d5..216562e6b9 100644 --- a/.github/workflows/container-tests.yml +++ b/.github/workflows/container-tests.yml @@ -95,6 +95,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo registry uses: actions/cache@v6 @@ -168,6 +169,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo registry uses: actions/cache@v6 @@ -209,6 +211,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo registry uses: actions/cache@v6 @@ -251,6 +254,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo registry uses: actions/cache@v6 diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index c94f801eab..d80962e1ea 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -33,6 +33,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: llvm-tools-preview + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/eh-transport.yml b/.github/workflows/eh-transport.yml index 4ca6c5bfee..4a33949b48 100644 --- a/.github/workflows/eh-transport.yml +++ b/.github/workflows/eh-transport.yml @@ -76,6 +76,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Setup Node.js uses: actions/setup-node@v7 diff --git a/.github/workflows/feature-matrix.yml b/.github/workflows/feature-matrix.yml index cfb1a5c5db..3c8e4a253e 100644 --- a/.github/workflows/feature-matrix.yml +++ b/.github/workflows/feature-matrix.yml @@ -34,6 +34,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/gc-moving-witnesses.yml b/.github/workflows/gc-moving-witnesses.yml index 81098cf2eb..09ef1d41b1 100644 --- a/.github/workflows/gc-moving-witnesses.yml +++ b/.github/workflows/gc-moving-witnesses.yml @@ -197,6 +197,7 @@ jobs: - name: Install Rust toolchain if: steps.relevance.outputs.run == 'true' uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 if: steps.relevance.outputs.run == 'true' diff --git a/.github/workflows/gc-native-roots.yml b/.github/workflows/gc-native-roots.yml index 7a3c72a2a5..947ce8a193 100644 --- a/.github/workflows/gc-native-roots.yml +++ b/.github/workflows/gc-native-roots.yml @@ -124,6 +124,7 @@ jobs: with: node-version-file: .node-version - uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: shared-key: gc-native-roots diff --git a/.github/workflows/gc-ratchet.yml b/.github/workflows/gc-ratchet.yml index 820cd2aa4c..5074f30e48 100644 --- a/.github/workflows/gc-ratchet.yml +++ b/.github/workflows/gc-ratchet.yml @@ -115,6 +115,7 @@ jobs: - name: Install Rust toolchain if: steps.relevance.outputs.run == 'true' uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Cache cargo if: steps.relevance.outputs.run == 'true' diff --git a/.github/workflows/gc-root-dominance.yml b/.github/workflows/gc-root-dominance.yml index ebf89aef1d..e940f820c7 100644 --- a/.github/workflows/gc-root-dominance.yml +++ b/.github/workflows/gc-root-dominance.yml @@ -156,6 +156,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 # ★ The dependency-scale corpus needs the dependency. # diff --git a/.github/workflows/node-compat-matrix.yml b/.github/workflows/node-compat-matrix.yml index de90781364..25d7b4bae8 100644 --- a/.github/workflows/node-compat-matrix.yml +++ b/.github/workflows/node-compat-matrix.yml @@ -57,6 +57,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Start sccache uses: mozilla-actions/sccache-action@v0.0.10 diff --git a/.github/workflows/node-core-subset.yml b/.github/workflows/node-core-subset.yml index 6c254f9928..cb78b0ad93 100644 --- a/.github/workflows/node-core-subset.yml +++ b/.github/workflows/node-core-subset.yml @@ -69,6 +69,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/node-suite-guard.yml b/.github/workflows/node-suite-guard.yml index b883832067..3e10b87526 100644 --- a/.github/workflows/node-suite-guard.yml +++ b/.github/workflows/node-suite-guard.yml @@ -45,6 +45,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Start sccache uses: mozilla-actions/sccache-action@v0.0.10 diff --git a/.github/workflows/npm-package-sweep.yml b/.github/workflows/npm-package-sweep.yml index 22c08a7209..7e291b0954 100644 --- a/.github/workflows/npm-package-sweep.yml +++ b/.github/workflows/npm-package-sweep.yml @@ -40,6 +40,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: diff --git a/.github/workflows/release-packages.yml b/.github/workflows/release-packages.yml index e7493d1fe6..3984898992 100644 --- a/.github/workflows/release-packages.yml +++ b/.github/workflows/release-packages.yml @@ -315,6 +315,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} + - uses: ./.github/actions/setup-llvm22 # Cache cargo registry + target/ per (matrix.target, Cargo.lock). # First run on a target is still a cold build, but every subsequent @@ -1030,6 +1031,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} + - uses: ./.github/actions/setup-llvm22 - name: Install Rust nightly + rust-src (Tier-3 only) if: matrix.tier3 diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 82b77a11c0..ee746829e6 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -23,6 +23,7 @@ jobs: with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: shared-key: security-audit @@ -155,6 +156,7 @@ jobs: with: persist-credentials: false - uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: shared-key: security-audit diff --git a/.github/workflows/simctl-tests.yml b/.github/workflows/simctl-tests.yml index 0986ef3d3a..e4d2510faa 100644 --- a/.github/workflows/simctl-tests.yml +++ b/.github/workflows/simctl-tests.yml @@ -33,6 +33,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install iOS simulator Rust target run: rustup target add aarch64-apple-ios-sim aarch64-apple-ios diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 52cb6f7ea3..c1a17dced1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -115,6 +115,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -296,6 +297,7 @@ jobs: uses: dtolnay/rust-toolchain@stable with: components: clippy + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -365,6 +367,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -432,6 +435,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -542,6 +546,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -800,6 +805,7 @@ jobs: - name: Install Rust toolchain if: steps.scope.outputs.suites != '' uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache if: steps.scope.outputs.suites != '' @@ -894,6 +900,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Setup Node.js uses: actions/setup-node@v7 @@ -1031,6 +1038,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -1137,6 +1145,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -1313,6 +1322,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -1469,6 +1479,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Install sccache uses: mozilla-actions/sccache-action@v0.0.10 @@ -1560,6 +1571,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -1650,6 +1662,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -1756,6 +1769,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -2133,6 +2147,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -2194,6 +2209,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -2260,6 +2276,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -2313,6 +2330,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: @@ -2462,6 +2480,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - name: Set up MSVC environment (Windows) # Populates LIB / INCLUDE / PATH so link.exe can find user32.lib @@ -2612,6 +2631,7 @@ jobs: - name: Install Rust toolchain uses: dtolnay/rust-toolchain@stable + - uses: ./.github/actions/setup-llvm22 - uses: Swatinem/rust-cache@v2 with: diff --git a/crates/perry-codegen/Cargo.toml b/crates/perry-codegen/Cargo.toml index 5e3006bf96..e4bf5b4e52 100644 --- a/crates/perry-codegen/Cargo.toml +++ b/crates/perry-codegen/Cargo.toml @@ -9,12 +9,23 @@ description = "LLVM code generation backend for Perry" workspace = true [features] -# exp/llvm-inprocess: compile `.ll -> .o` through the LLVM C API inside this -# process instead of shelling out to a user-supplied `clang -c`. Off by -# default — the default build has no LLVM link dependency and the text path -# is byte-for-byte untouched. Building with this feature requires LLVM 22 -# (`brew install llvm`; set LLVM_SYS_221_PREFIX if llvm-config is not on -# PATH). The backend still only runs when PERRY_LLVM_INPROCESS=1 at runtime. +# Compile `.ll -> .o` through the LLVM C API inside this process instead of +# shelling out to a user-supplied `clang -c`. +# +# ON BY DEFAULT. Perry links LLVM 22 statically and ships self-contained: we +# own the assumption instead of pushing it onto the user, and there is no +# "install a matching clang" step to get wrong. Building Perry therefore needs +# LLVM 22 present (`brew install llvm`, apt.llvm.org, or the official MSVC +# tarball; `LLVM_SYS_221_PREFIX` if llvm-config is not on PATH) — CI provisions +# it via `.github/actions/setup-llvm22`. +# +# It is also load-bearing rather than an optimization: the explicit statepoint +# bridge is gone (#7348), so RS4GC is the only native-root backend, and RS4GC +# needs this pipeline — an external `opt` feeding a different clang cannot +# parse the IR it emits (#7339). +# +# `--no-default-features` still builds the text path for bisection. +default = ["llvm-inprocess"] llvm-inprocess = ["dep:inkwell", "dep:llvm-sys"] [dependencies] diff --git a/crates/perry-codegen/src/linker.rs b/crates/perry-codegen/src/linker.rs index 467deb74a5..33fcd9f833 100644 --- a/crates/perry-codegen/src/linker.rs +++ b/crates/perry-codegen/src/linker.rs @@ -598,14 +598,37 @@ pub(crate) fn native_plan_args( (plan.effective_target, plan.clang_args) } -/// exp/llvm-inprocess: truthy `PERRY_LLVM_INPROCESS` routes `.ll -> .o` -/// through the LLVM C API inside this process (no clang subprocess, no `.ll` -/// on disk). The flag participates in both the build cache and the object -/// cache keys, so the two backends can never share a cached object. +/// Route `.ll -> .o` through the LLVM C API inside this process (no clang +/// subprocess, no `.ll` on disk). +/// +/// **ON BY DEFAULT.** Perry links LLVM 22 statically and ships self-contained, +/// so there is no "find a compatible clang" step to get wrong. It is also +/// load-bearing rather than a preference: the explicit statepoint bridge is +/// gone (#7348), leaving RS4GC as the only native-root backend, and RS4GC +/// cannot round-trip its IR through an external `opt` + a different clang +/// (#7339). +/// +/// `PERRY_LLVM_INPROCESS=0`/`off`/`false` reverts to the clang subprocess for +/// bisection. `=native` additionally builds function bodies through the C API +/// instead of rendering per-function text; that is byte-identical on the +/// 81-module zod corpus but has narrower CI coverage, so it stays opt-in until +/// that widens. +/// +/// The value participates in both the build cache and the object cache keys, +/// so the backends can never share a cached object. fn inprocess_requested() -> bool { match env::var("PERRY_LLVM_INPROCESS").as_deref() { - Ok("") | Ok("0") | Ok("off") | Ok("false") | Err(_) => false, + Ok("0") | Ok("off") | Ok("false") => false, + // Explicitly asked for: honour it even without the feature, so the + // stub below can say "rebuild with the feature" instead of silently + // serving the text path to an A/B arm that asked for this backend. Ok(_) => true, + // Unset means ON *iff* the backend is actually compiled in. It is a + // default feature, so that is the normal case — but a + // `--no-default-features` build must keep working, and defaulting to + // `true` there would route every compile into the not-built-in stub + // and fail the build outright. + Err(_) => cfg!(feature = "llvm-inprocess"), } } @@ -695,7 +718,25 @@ fn compile_ll_inprocess_in( } Ok(obj) } - Ok(bytes) => Ok(bytes), + Ok(bytes) => { + // `PERRY_LLVM_KEEP_IR` promises the whole scratch dir, `.o` + // included. The clang path gets that for free because the object + // IS a file; in-process returns bytes and would silently drop it — + // degrading a debugging aid at exactly the moment someone is + // debugging. Now that this backend is the default, write it. + if policy.keep { + let _ = fs::create_dir_all(&paths.scratch_dir); + if let Err(e) = fs::write(&plan.obj_path, &bytes) { + eprintln!( + "[perry-codegen] could not keep {}: {e}", + plan.obj_path.display() + ); + } else { + eprintln!("[perry-codegen] kept object: {}", plan.obj_path.display()); + } + } + Ok(bytes) + } Err(e) => { // Same contract as a failed clang compile: the IR that produced // the failure is left on disk and named in the error. diff --git a/crates/perry/Cargo.toml b/crates/perry/Cargo.toml index 161f9457d1..c3331a23d9 100644 --- a/crates/perry/Cargo.toml +++ b/crates/perry/Cargo.toml @@ -140,10 +140,10 @@ audit-cli = [] updater-cli = ["dep:ed25519-dalek", "dep:rand"] native-cli = [] -# exp/llvm-inprocess: compile .ll -> .o through the LLVM C API in-process -# instead of a `clang -c` subprocess. Off by default (no LLVM link dependency); -# even when built in, it only runs under PERRY_LLVM_INPROCESS=1. Requires -# LLVM 22 at build time (LLVM_SYS_221_PREFIX or llvm-config on PATH). +# Compile .ll -> .o through the LLVM C API in-process instead of a `clang -c` +# subprocess. ON BY DEFAULT via perry-codegen's own default feature — Perry +# links LLVM 22 statically and ships self-contained. See that crate's manifest +# for why this is load-bearing rather than an optimization. llvm-inprocess = ["perry-codegen/llvm-inprocess"] # Codegen backends for non-native targets. Each enables one backend crate;