Problem
compileM3EmitTuMainNative in lib/JIT.php builds the emit bridge LLVM IR before bundled Runtime::parse / Runtime::compile are guaranteed to be real-lowered. When LLVM binds the stub (null-returning) version first, the resulting native binary produces parse returned null at runtime and the probe falls back to emit_path=zend partial.
This is the root cause identified in #2506 and the current blocker for #2442 (emit-TU execute without startup crash).
Repro
./script/docker-exec.sh -- bash -lc '
source script/php-env.sh
BOOTSTRAP_M3_LINK_COMPILE_DRIVER=1 \
BOOTSTRAP_M3_COMPILE_DRIVER_REAL_LOWERING=1 \
BOOTSTRAP_M3_RUNTIME_COMPILE=1 \
./script/bootstrap-selfhost-helloworld-probe.sh
'
# Expected: emit_path=native
# Actual: emit_path=zend partial (parse returned null)
Root cause
In lib/JIT.php, compileM3EmitTuMainNative() emits the bridge call to Runtime::parse before runQueue() / spine pre-lower has committed real lowering for the bundled Runtime methods. LLVM 9 resolves the call to the stub entry from an earlier compile pass.
Fix
Defer the emit-bridge IR construction until after runQueue() completes the spine pre-lower, or restructure compileM3EmitTuMainNative to emit the bridge as a post-queue step (similar to how compileRuntimeLoadJitM3Native gates its helpers).
Relevant code paths:
| File |
Symbol |
Notes |
lib/JIT.php |
compileM3EmitTuMainNative() |
Bridge IR built too early |
lib/JIT.php |
runQueue() / spine pre-lower |
Must complete before bridge references Runtime symbols |
test/bootstrap-aot/runtime_m3_emit_native_entry.php |
smallest emit TU |
Use for bisect |
test/bootstrap-aot/compile_smoke_m3_emit_native_entry.php |
mid emit TU |
Second bisect step |
test/bootstrap-aot/helloworld_m3_emit_native_entry.php |
full emit TU |
Final gate |
Done when
Gate sequence
# Smallest TU first:
BOOTSTRAP_M3_RUNTIME_COMPILE=1 make bootstrap-selfhost-runtime-compile-smoke
# Then full helloworld:
BOOTSTRAP_M3_LINK_COMPILE_DRIVER=1 BOOTSTRAP_M3_COMPILE_DRIVER_REAL_LOWERING=1 \
BOOTSTRAP_M3_RUNTIME_COMPILE=1 \
./script/bootstrap-selfhost-helloworld-probe.sh
Dependencies
Epic #1492 · ROADMAP #78 Phase 0
Problem
compileM3EmitTuMainNativeinlib/JIT.phpbuilds the emit bridge LLVM IR before bundledRuntime::parse/Runtime::compileare guaranteed to be real-lowered. When LLVM binds the stub (null-returning) version first, the resulting native binary producesparse returned nullat runtime and the probe falls back toemit_path=zend partial.This is the root cause identified in #2506 and the current blocker for #2442 (emit-TU execute without startup crash).
Repro
Root cause
In
lib/JIT.php,compileM3EmitTuMainNative()emits the bridge call toRuntime::parsebeforerunQueue()/ spine pre-lower has committed real lowering for the bundledRuntimemethods. LLVM 9 resolves the call to the stub entry from an earlier compile pass.Fix
Defer the emit-bridge IR construction until after
runQueue()completes the spine pre-lower, or restructurecompileM3EmitTuMainNativeto emit the bridge as a post-queue step (similar to howcompileRuntimeLoadJitM3Nativegates its helpers).Relevant code paths:
lib/JIT.phpcompileM3EmitTuMainNative()lib/JIT.phprunQueue()/ spine pre-lowertest/bootstrap-aot/runtime_m3_emit_native_entry.phptest/bootstrap-aot/compile_smoke_m3_emit_native_entry.phptest/bootstrap-aot/helloworld_m3_emit_native_entry.phpDone when
./script/bootstrap-selfhost-helloworld-probe.sh(withBOOTSTRAP_M3_LINK_COMPILE_DRIVER=1 BOOTSTRAP_M3_COMPILE_DRIVER_REAL_LOWERING=1) reportsemit_path=native(notzend partial)build/selfhost-helloworld-emitexits 0 withhelloworld_compile_smoke: compile OKdocs/bootstrap-m5-fast-path.mdStep 2 updated to remove "bridge ordering" noteGate sequence
Dependencies
Epic #1492 · ROADMAP #78 Phase 0