AI-assisted project. Most ongoing development, documentation, and tooling on this fork is AI-heavy (agent workflows, automated CI gates, bulk refactors). The original idea and base architecture — a PHP-in-PHP compiler with VM, JIT, and native compilation — come from Anthony Ferrara’s ircmaxell/php-compiler (human-authored, MIT). Treat this repository as a maintained continuation, not a claim that every line was hand-written by a single author.
Compile PHP to native binaries — a CFG-based compiler with a bytecode VM, LLVM 9 JIT, and AOT linking. Ship CLI tools and small web apps that run without Zend PHP at runtime after phpc build or phpc deploy.
Stable line (2026) — First maintained stable release of this fork: demo-ready VM + AOT for a web-capable PHP subset, reference examples 000–009, and an experimental self-host path (compiler compiling its own
lib/). Not full Zend PHP compatibility — see what’s missing.
Snapshot (master @ cbc7e80c, 3 Jun 2026): VM + AOT for shipped examples ✅ · 321 builtins · self-host spine 1257/1322 (php script/bootstrap-spine-count.php) · M0 smoke ✅ in Docker — details below.
| Area | State | Notes |
|---|---|---|
VM (phpc run) |
✅ Production-shaped for dev/CI | Broadest language coverage; reference executor and JIT/AOT fallback |
AOT (phpc build) |
✅ For curated subset | Standalone binaries for examples 000–009 and small CGI apps; not arbitrary Composer stacks |
JIT (bin/jit.php) |
🚧 Partial | LLVM IR for many constructs; MCJIT execute still flaky (#98); EH scripts VM-fallback (#2114) |
| Language wave 3 | ✅ Closed batch | 12/12 language + 13/13 stdlib tracker items (#1380); closures, try/catch, generators (VM), parent::class, backed enums (VM), intersection AOT checks |
| Self-host north star | 🚧 ~99% | Compiler rebuilding its own lib/ without Zend — tracker #1492 |
phpcCLI —run,serve,build,deploy,lint,test,init,doctoron the web-capable PHP 8 subset documented indocs/capabilities-syntax.md.- Examples 000–009 — VM smoke green via
./phpc test --fast; AOT link/execute when LLVM 9 is present (make examples-aot-smoke). - 003-MiniWebApp — router, templates, forms, JSON API; native AOT execute on supported routes.
- 009-FastCGIWeb — FastCGI record codec + VM listener (#3261).
- Local/Docker CI — merge gates run on the host or in
php-compiler:22.04-dev(remote GHA disabled on this fork).
Counts from php script/bootstrap-spine-count.php (literal require_once in compiler_lib_spine_smoke vs Phase A inventory).
| Milestone | Status | What it means |
|---|---|---|
| M0–M1 | ✅ | compiler_minimal + compile-smoke bundles link and run natively |
| M2 | 🚧 1257/1322 | Spine grows toward full lib/ inventory; native spine link ✅ when patches + LLVM wired; full-spine lint still in progress |
| M3 | 🚧 | HelloWorld + inventory emit strict native ✅ (#3070); production bin/compile.php inventory path without thin TU open (#3024) |
| M4 | 🚧 | Gen-1 link + revision probe partial; gen-2→gen-3 full-spine recompile still failing on many trees — native driver when ready, emit_path=zend partial Zend fallback when blocked (#2697) |
| M5 | 🚧 | Vendor prelink 3/3 ✅; committed .o cold boot ✅; Zend still default when build/ is empty (#1416) |
Reproduce M0 smoke on a clean clone (verified May 2026):
make docker-build-22 # once
./script/docker-exec.sh -- bash -lc \
'composer install --ignore-platform-reqs -q \
&& script/apply-patches.sh \
&& make bootstrap-selfhost-link'
./build/selfhost # → compiler_minimal bundle OKDeeper ladder: docs/bootstrap-selfhost.md · docs/GETTING-STARTED.md §6–7 · make north-star4-verify.
- Not Zend PHP — no full
ext-*ecosystem, frameworks, or unmodified Composer apps at AOT runtime - Generator / enum native AOT — VM yes; native lowering open (#3074, #3076)
- JIT MCJIT execute — SIGSEGV in probe (#98)
- Fresh host PHP 8.3+ — use
composer install --ignore-platform-reqsor Docker; locked dev deps target PHP 8.1–8.2
Live matrices: status site · development status · gap tables.
This repository continues work that began as a research compiler written in PHP:
| Original project | ircmaxell/php-compiler on GitHub |
| Original author | Anthony Ferrara (ircmaxell) — idea, early architecture, and MIT-licensed codebase (LICENSE) |
| This fork | PurHur/php-compiler — LLVM-backed JIT/AOT, phpc CLI, web examples, bootstrap/self-host ladder, and ongoing maintenance |
Disclaimer: The concept of a PHP-in-PHP compiler with VM, JIT, and native compilation comes from Anthony Ferrara’s original project. This fork is a separate continuation with substantial new code, tooling, and goals (especially self-host and production-shaped phpc workflows). It is not an official release from the original author unless stated otherwise. If you cite the idea, please credit the original repository and its author.
Most PHP runs on Zend (opcode VM in C). php-compiler takes a different path:
- Parse PHP with php-cfg into a control-flow graph (CFG).
- Lower the CFG to internal opcodes (
lib/Compiler.php). - Execute via one of three backends:
| Backend | Entry | Role |
|---|---|---|
| VM | phpc run, bin/vm.php |
Interpreter loop in PHP — correct, flexible, slower |
| JIT | bin/jit.php |
LLVM MCJIT — compile at startup, then run native code |
| AOT | phpc build, bin/compile.php |
Link a standalone executable — no Zend at runtime |
flowchart LR
PHP[PHP source] --> CFG[php-cfg CFG]
CFG --> OPS[Compiler opcodes]
OPS --> VM[VM interpret]
OPS --> JIT[LLVM JIT]
OPS --> AOT[LLVM AOT link]
AOT --> BIN[Native binary]
The project targets a deliberate subset of PHP 8.x oriented toward CLI and CGI-style web apps (superglobals, routing, templates, sessions, uploads, JSON APIs) — not every language feature or extension Zend provides.
Active research direction: self-host — the compiler compiling its own lib/ tree into native binaries without relying on Zend in the bootstrap loop. Shipped examples under examples/ (e.g. MiniWebApp) are integration test fixtures for that stack, not a separate product.
Needs: PHP 8.1+, Composer. LLVM 9 only for build, JIT, and full CI (not for phpc test --fast).
git clone https://github.com/PurHur/php-compiler.git
cd php-compiler
composer install
./phpc test --fast| Step | Command | What you see |
|---|---|---|
| Hello, native | ./phpc build -o /tmp/hello examples/000-HelloWorld/example.php && /tmp/hello |
Standalone executable, no php at runtime |
| Web app (VM) | ./phpc serve examples/003-MiniWebApp → open http://127.0.0.1:8080/ |
Router, templates, JSON API |
| Self-host smoke (M0) | Docker: see Current implementation status | compiler_minimal bundle OK (needs LLVM 9 + patches) |
Presenter walkthrough: docs/GETTING-STARTED.md · public overview: status site.
./phpc is the unified developer interface (legacy bin/vm.php, bin/jit.php, bin/compile.php still work).
| Command | Purpose |
|---|---|
phpc run |
Run a script on the VM (-q / -p for CGI-style superglobals) |
phpc serve |
Dev HTTP server (VM); phpc serve --aot serves a prebuilt binary |
phpc build |
AOT compile to a native executable; --project uses phpc.json |
phpc deploy |
Package binary + public/ into a deploy tree |
phpc lint |
Report unsupported syntax in a file or tree |
phpc test |
Run CI (--fast = VM/compliance only, no LLVM) |
phpc init |
Scaffold phpc.json (--profile miniwebapp, sessionsweb, fileupload) |
phpc doctor |
Environment and gate probes |
./phpc help
./phpc run -r 'echo "Hello\n";'
./phpc build -o .phpc/bin/app examples/001-SimpleWeb/example.php
./phpc serve examples/001-SimpleWebManifest format: docs/phpc-json.md · AOT deploy guide: docs/deploy-web-aot.md.
Reference apps live under examples/. They prove VM, AOT link, native execute, and deploy paths — see examples/README.md.
| Example | Highlights |
|---|---|
| 000–002 | CLI hello, simple web, CGI query params |
| 003-MiniWebApp | Router, templates, contact form, JSON API — native execute ✅ |
| 004-ApiJson | JSON API |
| 005-SessionsWeb | session_start, flash messages |
| 006-FileUploadWeb | Multipart $_FILES |
| 007-ThrowsWeb | Caught exceptions in forms |
| 008-SelfHostProbe | Self-host presenter probe |
| 009-FastCGIWeb | FastCGI-oriented layout (adapter #173; fixture SSOT #2331) |
make web-smoke # lint + VM smoke on shipped examples
make examples-aot-smoke # AOT link + execute (when LLVM is ready)
make examples-web-smoke # phpc serve + HTTP curlsphp-compiler is not a drop-in Zend PHP replacement. It implements a web-capable PHP 8 subset aimed at small CLI/CGI apps, native deployment, and (experimentally) compiling its own lib/ tree. Capabilities differ by backend — VM, JIT, and AOT do not always match.
| Column | Meaning |
|---|---|
| VM | Runs under phpc run / bin/vm.php — broadest language coverage, slowest |
| JIT | bin/jit.php — native code via LLVM MCJIT; some CFGs fall back to VM |
| AOT | phpc build — standalone binary; strictest; many features blocked at link time |
Full matrices (auto-generated): docs/capabilities.md (builtins) · docs/capabilities-syntax.md (language) · public gap tables · PHP vs us.
Language & OOP (typical app code)
- Classes,
new, interfaces,instanceof, constructors, visibility, promoted properties,readonlyclasses - Instance and static methods,
parent::class/parent::$prop, late static binding, magic constants - Namespaces,
use function/use const, groupuse match, scalardeclare(strict_types=1), union types; intersection types with AOT call-site checks (#3103)- Closures and arrow functions on VM and JIT (LLVM IR):
use ($var)by-value and by-ref (#3108), indirect$arr[0]()invoke (#3092) try/catch/finallyon VM including return-through-finally (#3106); JIT EH IR verified (#3107) —bin/jit.phpstill VM-fallback for EH scripts- Generators (
yield, keyed yield,yield from) on VM; JIT/AOT use VM fallback (#3085) - Backed enums on VM (php-cfg patch + compliance) (#3091); traits — simple
use Trait; - Attributes — reflection read path (
getAttributes(), name only)
Web & deployment
- CGI-style superglobals (
$_GET,$_POST,$_SERVER,$_FILES,$_COOKIE,$_SESSION) phpc servedev server andphpc serve --aotfor prebuilt binaries- Sessions, multipart uploads, JSON APIs — examples 005–007
phpc build,phpc deploy,phpc.jsonproject manifests- Reference 003-MiniWebApp: router, templates, forms, native AOT execute on supported routes
Standard library (May 2026 wave)
- 321 builtins in the auto-generated matrix — strings, arrays, JSON,
preg_*, filesystem, streams - Recent VM additions:
class_uses,class_alias,get_debug_type,iterator_to_array,array_chunk(preserve keys),settype,array_replace_recursive,json_validate,preg_last_error_msg,fdiv, DateTime / DateTimeZone OOP (#3104) array_map/array_filter/usortaccept closure callbacks on VM (#3086)- Wave 3 tracked batch: 12/12 language + 13/13 stdlib items closed; ongoing stdlib work in #1380 follow-ups
Tooling
phpc lint— scan trees for unsupported syntax before compilephpc doctor— environment and example gate probes- Native vendor invoker surfaces
parseAndCompilefailure text (#3084) - Local/Docker CI:
phpc test,phpc test --fast
Language (subset gaps)
| Area | VM | JIT / AOT | Notes |
|---|---|---|---|
try / catch / finally |
Yes (compliance) | JIT IR only; execute → VM | MCJIT EH unsafe (#2114); bin/jit.php uses requiresVmLowering |
Closures / arrow fn () => |
Yes | JIT IR verify | Self-host / bootstrap may stub null; bin/jit.php MCJIT execute still flaky (#98, #72) |
Generators (yield) |
Yes | VM fallback | Native JIT/AOT lowering open (#167, #3074) |
By-ref parameters (function f(&$x)) |
Yes | No JIT | Distinct from closure use (&$x) (#140) |
| Enums in AOT | VM/JIT | No | #1356, #3076 |
Full trait adaptation (insteadof / as) |
Partial | Gaps | #144 |
| Fibers | No | No | #3130 |
Runtime & platform
- Not Zend-compatible — no
ext-*ecosystem, no Composer autoload at AOT runtime, noeval(), no full reflection beyond supported paths - LLVM 9 only — JIT/AOT tied to bundled toolchain; upgrading LLVM is non-trivial
- JIT compile cost — recompiles on each
bin/jit.phprun; not a long-lived FPM replacement - Performance — AOT can be fast; VM path is PHP-on-PHP; see
benchmarks/ - Security model — same trust as running native code; no sandbox; body size limits on
phpc serve(default 8 MiB)
Self-host (experimental, not “stable app” scope)
See Current implementation status for the full M0–M5 ladder. Summary: M0 smoke ✅ in Docker; M2 1257/1322 spine toward inventory; M3 inventory emit ✅ / production bin/compile.php 🚧 (#3024); M4 gen-2→gen-3 recompile 🚧; M5 partial (#1492). Recent: union-type php-cfg overlays (#5096); JIT try/catch/finally (#4264).
What we do not target in v1.0
- Running arbitrary Composer packages unmodified
- WordPress, Laravel, Symfony, or full framework stacks
- pthreads, fibers, or parallel extension semantics
- Every PHP 8.3+ feature as Zend ships it
./phpc lint path/to/your-app.php
./phpc lint --project . # uses phpc.json roots
./phpc build -o /tmp/app entry.php # fails early on unsupported constructsRegenerate maintainer matrices after builtin changes: php script/capability-matrix.php and php script/capability-syntax.php.
Live status: Overview · Development status.
- PHP 8.1+ (8.2 recommended):
tokenizer,mbstring,dom,xml,xmlwriter,ffi,posix,phar - Composer
- LLVM 9 for JIT/AOT — bundled into
.llvm/by./script/install-llvm9.shor first./script/ci-local.sh
composer install --ignore-platform-reqs # if host PHP is 8.3+ (locked deps target 8.1–8.2)
script/apply-patches.sh # php-cfg overlays; required before compile
./script/install-llvm9.sh # optional until you run full CI or phpc buildmake docker-build-22 # once: php-compiler:22.04-dev
make test # full CI inside containerOn Runforge/harness sandboxes use make test-harness or ./script/docker-ci-local.sh — see Troubleshooting.
| Variable | Purpose |
|---|---|
PHP_COMPILER_PHP |
PHP binary for tests (default php or php8.2) |
PHP_COMPILER_LLVM_PATH |
LLVM 9 tree (default: repo .llvm/) |
PHP_COMPILER_SKIP_SERVE_TESTS |
Skip HTTP tests when loopback bind fails |
PHP_COMPILER_DEBUG |
Verbose errors on phpc serve (500 responses) |
Full list: run ./phpc doctor or see the local CI matrix.
Merge quality is enforced locally or in Docker (GitHub Actions / CircleCI are disabled on this fork).
| Goal | Command |
|---|---|
| Fast iteration | ./phpc test --fast or ./script/ci-fast.sh |
| Full gate | ./script/ci-local.sh or make test |
| Bootstrap / self-host | make bootstrap-selfhost-link, make north-star4-verify, make bootstrap-wave-check |
Contributor matrices (regenerate when builtins change):
php script/capability-matrix.php
php script/capability-syntax.phpDeep docs: docs/README.md · self-host: docs/self-host-target.md · bootstrap gates: docs/bootstrap-selfhost.md · CI matrix: docs/local-ci-matrix.md.
The VM (lib/VM.php) is a classic decode-and-dispatch loop over compiler opcodes. It is the reference executor and the fallback when JIT/AOT cannot lower a construct yet. Running PHP on this VM is slower than Zend, but it is how most development and compliance tests run.
bin/jit.php lowers opcodes to LLVM IR, uses MCJIT, and jumps into generated machine code. Compile time is significant; some CFG shapes (generators, unstable exception lowering) still fall back to the VM.
bin/compile.php / phpc build emits object code and links a native executable with the project runtime (lib/AOT/, lib/Runtime.php). This is the deployment path for “no PHP installed on the server.”
Debug CFG and opcodes: php bin/print.php -r 'echo 1;'
We do not accept drive-by GitHub issues or pull requests without prior coordination. Contact maintainers on other channels first and align with the AI-agent workflow. Forks are welcome under MIT — see CONTRIBUTING.md.
| Symptom | Fix |
|---|---|
| Empty repo inside Docker on harness | make test-harness or ./script/docker-ci-local.sh (tar copy) |
libLLVM-9.so.1: cannot open |
./script/install-llvm9.sh or set LD_LIBRARY_PATH to .llvm/ |
| Parser/lexer errors on PHP 8.2+ | composer install + script/apply-patches.sh |
| AOT link failures | Re-run script/install-llvm9.sh; check PHP_COMPILER_LLVM_PATH |
More: docs/GETTING-STARTED.md · docs/local-ci-matrix.md.
MIT — see Lineage & disclaimer for attribution to the original project.
| Resource | URL |
|---|---|
| This repository | https://github.com/PurHur/php-compiler |
| Original project | https://github.com/ircmaxell/php-compiler |
| Status & gaps (GitHub Pages) | https://purhur.github.io/php-compiler/ |
| Anthony Ferrara (original author) | https://github.com/ircmaxell |
| Benchmarks | benchmarks/ (make bench) |