Compilation pipeline

How the PHP compiler
turns code into machine code

Seven well-defined phases compile your PHP source into a standalone native binary. The compilation pipeline transforms PHP code into optimized assembly for the selected target, then assembles and links it into a native executable. No Zend Engine, VM, interpreter, or opcode fallback is involved in the compiled path.

Aa
01

Lexer

Character-by-character scanning of PHP source into keywords, operators, literals, and identifiers.

{}
02

Parser

Pratt parser with binding powers builds a structured tree of expressions and statements.

>>
03

Resolver

Builds the compile-time autoload registry from Composer metadata and SPL rules, lowers per-file PHP magic constants, runs the ifdef/--define conditional pass, pre-scans statically-resolvable include targets for declarations, folds compile-time include path expressions, lowers include_once and require_once runtime guards, runs static autoload file insertion for referenced classes, then resolves namespaces and use imports to fully qualified names — merging multiple files into one AST.

T:
04

Type Checker

Infers and validates types for every variable and expression. Catches errors before assembly is emitted.

opt
05

Optimizer

Constant folding, constant propagation, control-flow pruning and normalization, and dead-code elimination with CFG-lite reachability. Conservative by design — rewrites only happen when the shape is statically provable.

asm
06

Codegen

Every AST node is translated to annotated assembly for the selected target: macOS ARM64, Linux ARM64, or Linux x86_64. Each line is commented explaining what and why.

ld
07

Link

The host `as` assembles to object code, then `ld` links into a standalone executable (Mach-O on macOS, ELF on Linux) with elephc runtime routines included.

.php tokens AST resolved AST typed AST optimized AST .s .o binary

Code examples

Write PHP.
Compile to native.

80+ working PHP code examples ship with the compiler. Each one compiles to a standalone native binary and produces identical output to the PHP interpreter. From hello world to inheritance and exceptions — all compiled to native machine code.

hello.php
Hello World
1 <?php
2 echo "Hello, World!\n";
fibonacci.php
Fibonacci
1 <?php
2 function fib($n) {
3 if ($n <= 1) {
4 return $n;
5 }
6 return fib($n - 1) + fib($n - 2);
7 }
8
9 for ($i = 0; $i <= 20; $i++) {
10 echo fib($i) . "\n";
11 }
fizzbuzz.php
FizzBuzz
1 <?php
2 $i = 1;
3 while ($i <= 100) {
4 if ($i % 15 == 0) {
5 echo "FizzBuzz\n";
6 } elseif ($i % 3 == 0) {
7 echo "Fizz\n";
8 } else {
9 echo $i . "\n";
10 }
11 $i++;
12 }
primes.php
Prime Checker
1 <?php
2 function is_prime($n) {
3 if ($n <= 1) return false;
4 $i = 2;
5 while ($i * $i <= $n) {
6 if ($n % $i == 0)
7 return false;
8 $i++;
9 }
10 return true;
11 }
abstract-properties.php
Abstract Properties
1 <?php
2
3 abstract class Shape {
4 abstract public int $sides;
5 abstract public string $name;
6 public function describe() {
7 return $this->name . " has " . $this->sides . " sides";
8 }
9 }
10
11 class Triangle extends Shape {
12 public int $sides = 3;
13 public string $name = "triangle";
14 }
15
16 $shape = new Triangle();
17 echo $shape->describe() . " ";
pointers.php
Pointers
1 <?php
2 $x = 42;
3 $p = ptr($x);
4 echo ptr_get($p) . "\n";
5 ptr_set($p, 100);
6 $typed = ptr_cast<int>($p);
7 echo ($p === $typed ? "same" : "diff") . "\n";

All 80+ included examples

hello advanced-functions arithmetic arrays assoc-arrays attributes binary-literals bitwise callbacks classes cli-args closures concat constant-propagation constants constructor-promotion control-flow countdown cow date-json-regex default-params enums error-control exceptions factorial ffi ffi-memory fibonacci file-io final-classes fizzbuzz float-math foreach-ref functions generators guess-game hot-path ifdef inheritance instanceof interfaces iterable iterators json-basic json-exception json-flags json-jsonserializable logical magic-constants magic-methods math multi-file namespaces nested-arrays never nullsafe-operator numeric-literals pointers primes readline sdl_audio sdl_framebuffer sdl_input sdl_window static-classes static-properties strict-compare string-builder string-ops switch-match system-info traits type-ops typed-properties union-types v017-trio variadic variables case-insensitive-symbols file-modify file-stat fibers paths print-expression spl-autoload spl-foundation streams-ext strtotime-relative symlinks

Documentation

Learn how a
PHP compiler works

12 guides covering every aspect of building a PHP compiler — from lexing and parsing, to type checking, code generation, and the ARM64 instruction set. No prior assembly or compiler knowledge required.

"Every line of Rust that emits ARM64 assembly is annotated with an inline comment explaining what it does and why."

From stack frame setup to syscall invocation, from integer-to-string conversion to array memory layout. If you've ever wondered what happens between echo "hello" and the CPU executing it, follow the code from src/codegen/ and read the comments.