From 5ebeb2021ec9ae618b9c6dac6a0cda9bbc41edb7 Mon Sep 17 00:00:00 2001 From: PurHur Date: Tue, 16 Jun 2026 00:01:04 +0000 Subject: [PATCH] M5 spine link: refuse Zend inventory rebuild when NO_ZEND_FALLBACK set (#8716) Extend bootstrap_ensure_inventory_argv_driver to fail closed under BOOTSTRAP_NO_ZEND_FALLBACK=1 (not only BOOTSTRAP_M5_NO_ZEND), fall back to native driver resolver in lib-spine-smoke-link, and fix ObGzhandlerJitRuntime PHI dominance that blocked inventory argv emit verify(). Co-authored-by: Cursor --- docs/bootstrap-selfhost.md | 4 ++-- lib/JIT/Builtin/ObGzhandlerJitRuntime.php | 3 ++- script/bootstrap-resolve-compile-invoke.sh | 6 ++++-- ...bootstrap-selfhost-lib-spine-smoke-link.sh | 21 +++++++++++++++---- test/unit/BootstrapLibSpineVmSmokeTest.php | 7 ++++--- test/unit/BootstrapSelfhostLinkTest.php | 9 ++++++-- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/docs/bootstrap-selfhost.md b/docs/bootstrap-selfhost.md index 10a23af053c..20a993dbbf5 100644 --- a/docs/bootstrap-selfhost.md +++ b/docs/bootstrap-selfhost.md @@ -1,6 +1,6 @@ # Self-host bootstrap roadmap -**Gen-0 without Zend:** `BOOTSTRAP_M5_NO_ZEND=1 make bootstrap-selfhost-link` installs `prelinked/bootstrap-gen0/bin-compile-aot` and links `compiler_minimal` without `php bin/compile.php` ([#3053](https://github.com/PurHur/php-compiler/issues/3053)). +**Gen-0 without Zend:** `BOOTSTRAP_M5_NO_ZEND=1 make bootstrap-selfhost-link` installs `prelinked/bootstrap-gen0/bin-compile-aot` and links `compiler_minimal` without `php bin/compile.php` ([#3053](https://github.com/PurHur/php-compiler/issues/3053)). **M5 lib spine compile:** `BOOTSTRAP_NO_ZEND_FALLBACK=1 make bootstrap-selfhost-lib-spine-smoke` (default in link script) refuses host `php bin/compile.php` on the spine emit path ([#8716](https://github.com/PurHur/php-compiler/issues/8716)). **Project north star:** The **compiler fully compiles itself** — native AOT from `lib/` (no `vendor/` at cold boot), then compiles PHP and rebuilds the next compiler revision without Zend. **M2 spine:** **2643/2643** Phase A inventory (`php script/bootstrap-spine-count.php`; `check-selfhost-spine-coverage-sync.php`). **M5 daily gate:** `make north-star5-verify-fast` (~1–2 min) ✅; **`--strict`** (~1h) pre-merge only. Committed `prelinked/bootstrap-gen0/` sidecars + vendor **3/3** cold boot. **Hot loop:** VM driver execute probe ~**20ms**; full spine relink only with `BOOTSTRAP_VM_DRIVER_EXECUTE_PROBE_FULL_LINK=1` ([#2201](https://github.com/PurHur/php-compiler/issues/2201)). **Living tracker:** [#1492](https://github.com/PurHur/php-compiler/issues/1492) (was [#1056](https://github.com/PurHur/php-compiler/issues/1056)) · **re-root doc:** [self-host-target.md](self-host-target.md) · **generation ladder:** [bootstrap-generations.md](bootstrap-generations.md) · **M5 fast path:** [bootstrap-m5-fast-path.md](bootstrap-m5-fast-path.md) · public status: [development-status § North star](https://purhur.github.io/php-compiler/development-status.html#north-star-self-host). Parent tracking: [#78](https://github.com/PurHur/php-compiler/issues/78) (roadmap), [#212](https://github.com/PurHur/php-compiler/issues/212) (closed umbrella). @@ -39,7 +39,7 @@ | Self-host native link | `./script/bootstrap-selfhost-link.sh` | ✅ `build/selfhost` prints `compiler_minimal bundle OK` ([#557](https://github.com/PurHur/php-compiler/issues/557), [#913](https://github.com/PurHur/php-compiler/issues/913)) | | M2 lib spine smoke lint | `./script/bootstrap-selfhost-lib-spine-smoke-lint.sh` or `make bootstrap-selfhost-lib-spine-smoke-lint` | ✅ spine entry AOT lint — skip SourceBundler on `-l` ([#8391](https://github.com/PurHur/php-compiler/issues/8391)); uses `PHP_COMPILER_LLVM_MEMORY_LIMIT` | | M2 spine coverage drift | `php script/check-selfhost-spine-coverage-sync.php` | ✅ **2643** Phase A inventory files covered; `SELFHOST_SPINE_COVERAGE_SYNC_GATE=1` ([#1945](https://github.com/PurHur/php-compiler/issues/1945), [#2840](https://github.com/PurHur/php-compiler/issues/2840)) -| M2 lib spine smoke native run | `./script/bootstrap-selfhost-lib-spine-smoke-link.sh` or `BOOTSTRAP_LIB_SPINE_SMOKE=1 make bootstrap-selfhost-lib-spine-smoke` | ✅ `build/selfhost-lib-spine-smoke` prints `compiler_lib_spine_smoke bundle OK` | +| M2 lib spine smoke native run | `./script/bootstrap-selfhost-lib-spine-smoke-link.sh` or `BOOTSTRAP_LIB_SPINE_SMOKE=1 make bootstrap-selfhost-lib-spine-smoke` | ✅ `build/selfhost-lib-spine-smoke` prints `compiler_lib_spine_smoke bundle OK`; link script sets `BOOTSTRAP_NO_ZEND_FALLBACK=1` — no Zend gen-0 fallback ([#8716](https://github.com/PurHur/php-compiler/issues/8716)) | | M2 lib spine VM `-r` smoke | `./script/bootstrap-selfhost-lib-spine-vm-smoke.sh` or `BOOTSTRAP_LIB_SPINE_VM_SMOKE=1 make bootstrap-selfhost-lib-spine-vm-smoke` | ✅ same binary + `PHP_COMPILER_VM_SPINE_SMOKE=1` prints `vm-spine-ok` ([#1846](https://github.com/PurHur/php-compiler/issues/1846); `ci-local.sh` default `BOOTSTRAP_LIB_SPINE_VM_SMOKE_GATE=1` ([#1867](https://github.com/PurHur/php-compiler/issues/1867)); set `0` to skip) | | M2 VM driver execute | `./script/bootstrap-selfhost-vm-driver-execute-probe.sh` or `make bootstrap-selfhost-vm-driver-execute-probe` | ✅ spine binary + `PHP_COMPILER_VM_DRIVER_EXECUTE=1` → `vm driver ok` ([#2201](https://github.com/PurHur/php-compiler/issues/2201)); **~20ms** when binary present (no relink on stale SHA); `BOOTSTRAP_VM_DRIVER_EXECUTE_PROBE_FULL_LINK=1` for full rebuild; `ci-local.sh` default `BOOTSTRAP_VM_DRIVER_EXECUTE_GATE=1` ([#2227](https://github.com/PurHur/php-compiler/issues/2227)); opt-out `BOOTSTRAP_VM_DRIVER_EXECUTE_GATE=0` | | M3 HelloWorld self-host probe lint | `php bin/compile.php -l test/selfhost/compiler_helloworld_smoke/main.php` | ✅ `compiler_compile_smoke` spine + `helloworld_compile_smoke` driver (linkable) | diff --git a/lib/JIT/Builtin/ObGzhandlerJitRuntime.php b/lib/JIT/Builtin/ObGzhandlerJitRuntime.php index 647e9ae6c63..cc4afb1bf2e 100644 --- a/lib/JIT/Builtin/ObGzhandlerJitRuntime.php +++ b/lib/JIT/Builtin/ObGzhandlerJitRuntime.php @@ -265,12 +265,13 @@ private static function emitResolveEncoding(Context $context, LlvmFunction $fn): $context->builder->branch($doneBb); $context->builder->positionAtEnd($resolveBb); $resolved = self::emitReadAcceptEncoding($context, $fn); + $resolveDoneBb = $context->builder->getInsertBlock(); $context->builder->store($resolved, $encPtr); $context->builder->branch($doneBb); $context->builder->positionAtEnd($doneBb); $phi = $context->builder->phi($i64, 'ogz_enc'); $phi->addIncoming($cached, $cachedBb); - $phi->addIncoming($resolved, $resolveBb); + $phi->addIncoming($resolved, $resolveDoneBb); return $phi; } diff --git a/script/bootstrap-resolve-compile-invoke.sh b/script/bootstrap-resolve-compile-invoke.sh index 46e9b58250e..1777a2aab3b 100755 --- a/script/bootstrap-resolve-compile-invoke.sh +++ b/script/bootstrap-resolve-compile-invoke.sh @@ -21,6 +21,7 @@ # BOOTSTRAP_GEN0_ZEND_ONLY=1 — always php bin/compile.php (requires php on PATH) # BOOTSTRAP_ALLOW_GEN0_ZEND=0 — refuse Zend when no native driver (empty build/) # BOOTSTRAP_M5_NO_ZEND=1 — refuse Zend fallback (implies BOOTSTRAP_NO_ZEND_FALLBACK=1) +# BOOTSTRAP_NO_ZEND_FALLBACK=1 — refuse Zend on spine/M5 compile paths (#8716) # BOOTSTRAP_USE_INVENTORY_DRIVER=1 — inventory argv driver only (#2894) set -euo pipefail @@ -366,8 +367,9 @@ bootstrap_ensure_inventory_argv_driver() { return 0 fi fi - if [[ "${BOOTSTRAP_M5_NO_ZEND:-0}" == "1" ]]; then - echo "bootstrap-ensure-inventory-argv-driver: BOOTSTRAP_M5_NO_ZEND=1 — prelinked inventory driver failed smoke (#3053)" >&2 + if [[ "${BOOTSTRAP_M5_NO_ZEND:-0}" == "1" || "${BOOTSTRAP_NO_ZEND_FALLBACK:-0}" == "1" ]]; then + rm -f "${out}" "${root}/build/.m3_bin_compile_aot_blob" + echo "bootstrap-ensure-inventory-argv-driver: BOOTSTRAP_NO_ZEND_FALLBACK=1 — prelinked inventory driver failed smoke (#8716, #3053)" >&2 return 1 fi fi diff --git a/script/bootstrap-selfhost-lib-spine-smoke-link.sh b/script/bootstrap-selfhost-lib-spine-smoke-link.sh index 05c78bf80f8..b25afaf5387 100755 --- a/script/bootstrap-selfhost-lib-spine-smoke-link.sh +++ b/script/bootstrap-selfhost-lib-spine-smoke-link.sh @@ -129,11 +129,24 @@ if [[ "${BOOTSTRAP_LIB_SPINE_SMOKE_USE_COMPILE_INVOKE:-0}" != "1" ]]; then echo "bootstrap-selfhost-lib-spine-smoke-link: compile invoker=${SPINE_COMPILE_DRIVER} (no vendor/ tree)" >&2 else # Emit-helper build/bin-compile-aot (gen-2 spine) must not masquerade as inventory argv driver (#3012). - if ! bootstrap_ensure_inventory_argv_driver "${INVENTORY_ARGV_DRIVER}"; then - echo "bootstrap-selfhost-lib-spine-smoke-link: failed to ensure inventory argv driver ${INVENTORY_ARGV_DRIVER}" >&2 - exit 1 + if bootstrap_ensure_inventory_argv_driver "${INVENTORY_ARGV_DRIVER}"; then + SPINE_COMPILE_DRIVER="${INVENTORY_ARGV_DRIVER}" + else + echo "bootstrap-selfhost-lib-spine-smoke-link: inventory argv driver unavailable (no Zend — #8716); resolving native driver" >&2 + if ! bootstrap_resolve_compile_driver || [[ "${BOOTSTRAP_COMPILE_DRIVER_MODE:-}" != "native" ]]; then + echo "bootstrap-selfhost-lib-spine-smoke-link: building compiled argv driver (bootstrap-selfhost-driver-smoke) to avoid Zend fallback" >&2 + if ! ./script/bootstrap-selfhost-driver-smoke.sh >/dev/null; then + echo "bootstrap-selfhost-lib-spine-smoke-link: failed to build compiled driver (see stderr above)" >&2 + exit 1 + fi + if ! bootstrap_resolve_compile_driver || [[ "${BOOTSTRAP_COMPILE_DRIVER_MODE:-}" != "native" ]]; then + echo "bootstrap-selfhost-lib-spine-smoke-link: compiled driver still missing after driver-smoke (would require Zend fallback)" >&2 + exit 1 + fi + fi + SPINE_COMPILE_DRIVER="${BOOTSTRAP_COMPILE_DRIVER}" + echo "bootstrap-selfhost-lib-spine-smoke-link: compile invoker=${SPINE_COMPILE_DRIVER} (inventory prelinked smoke failed — #8716)" >&2 fi - SPINE_COMPILE_DRIVER="${INVENTORY_ARGV_DRIVER}" fi # Best-effort segfault breadcrumbs (written before invoking the native driver). diff --git a/test/unit/BootstrapLibSpineVmSmokeTest.php b/test/unit/BootstrapLibSpineVmSmokeTest.php index 56db265eab7..cb6d8278c21 100644 --- a/test/unit/BootstrapLibSpineVmSmokeTest.php +++ b/test/unit/BootstrapLibSpineVmSmokeTest.php @@ -55,15 +55,16 @@ public function testCompilePhpSkipsSourceBundlerForSpineLint(): void $this->assertStringContainsString('!$skipBundle', $compile); } - public function testLibSpineLinkScriptSeedsSidecarsAndGen0Fallback(): void + public function testLibSpineLinkScriptSeedsSidecarsAndRefusesZendFallback(): void { $script = (string) file_get_contents(self::$root.'/script/bootstrap-selfhost-lib-spine-smoke-link.sh'); $this->assertStringContainsString('bootstrap-gen0-install-prelinked-driver.sh', $script); $this->assertStringContainsString('ci_ensure_vendor_patches', $script); $this->assertStringContainsString('bootstrap_ensure_m3_compiler_lib_sidecar', $script); - $this->assertStringContainsString('PHP_COMPILER_M3_SIDECAR_HOST=1', $script); + $this->assertStringContainsString('export BOOTSTRAP_NO_ZEND_FALLBACK=1', $script); + $this->assertStringContainsString('inventory argv driver unavailable (no Zend — #8716)', $script); $this->assertStringContainsString('BOOTSTRAP_LIB_SPINE_SMOKE_GEN0_FALLBACK', $script); - $this->assertStringContainsString('gen-0 Zend fallback', $script); + $this->assertStringContainsString('BOOTSTRAP_NO_ZEND_FALLBACK:-0}" != "1"', $script); } public function testSpineEntryBundlesBinVmPhp(): void diff --git a/test/unit/BootstrapSelfhostLinkTest.php b/test/unit/BootstrapSelfhostLinkTest.php index c75e8543cb5..cc0740a618b 100644 --- a/test/unit/BootstrapSelfhostLinkTest.php +++ b/test/unit/BootstrapSelfhostLinkTest.php @@ -112,11 +112,16 @@ public function testLinkScriptUsesCompiledDriverResolver(): void $this->assertStringContainsString('falling back to Zend gen-0', $body); $this->assertStringContainsString('BOOTSTRAP_M5_NO_ZEND', $body); $this->assertStringContainsString( - 'BOOTSTRAP_M5_NO_ZEND=1 — prelinked inventory driver failed smoke', + 'BOOTSTRAP_NO_ZEND_FALLBACK=1 — prelinked inventory driver failed smoke', $body, - 'inventory argv driver refuses Zend rebuild under M5 no-Zend (#3053)' + 'inventory argv driver refuses Zend rebuild when no-Zend fallback (#8716, #3053)' ); + $spineLink = (string) file_get_contents(self::$root.'/script/bootstrap-selfhost-lib-spine-smoke-link.sh'); + $this->assertStringContainsString('export BOOTSTRAP_NO_ZEND_FALLBACK=1', $spineLink); + $this->assertStringContainsString('inventory argv driver unavailable (no Zend — #8716)', $spineLink); + $this->assertStringContainsString('BOOTSTRAP_NO_ZEND_FALLBACK:-0}" != "1"', $spineLink); + $coldBoot = self::$root.'/script/bootstrap-selfhost-cold-boot-probe.sh'; $this->assertFileExists($coldBoot); $this->assertStringContainsString('BOOTSTRAP_M5_NO_ZEND=1', (string) file_get_contents($coldBoot));