# How the TypePHP Compiler Achieves Self-Hosting: Bootstrap Pipeline and Two-Phase Compilation

> Discover how TypePHP achieves self-hosting with its pure-PHP bootstrap script and two-phase compilation pipeline. Learn how it compiles PHP source into a native binary.

- Repository: [Swoole Project/typephp](https://github.com/swoole/typephp)
- Tags: internals
- Published: 2026-08-30

---

**The TypePHP compiler achieves full self-hosting by using a pure-PHP bootstrap script to load its own source modules, then executing a two-phase prepare-and-convert pipeline that compiles its PHP source into a native binary capable of replacing the original bootstrap script.**

The swoole/typephp repository implements a rare feat in compiler construction: a production-quality AOT (Ahead-of-Time) compiler written entirely in PHP that compiles itself into native machine code. This self-hosting architecture eliminates dependency on external compiler toolchains during the build process, allowing TypePHP to bootstrap from pure PHP source to optimized native binary.

## The Bootstrap Entry Point

Self-hosting begins with the executable script at [`bin/tpc.php`](https://github.com/swoole/typephp/blob/main/bin/tpc.php). This entry point loads the compiler's runtime environment by requiring a specific sequence of PHP modules:

```php
require __DIR__ . '/bootstrap.php';
require TYPEPHP_ROOT_PATH . '/src/polyfills.php';
require TYPEPHP_ROOT_PATH . '/src/gen_stub.php';
require TYPEPHP_ROOT_PATH . '/src/compiler.php';

```

The constant `TYPEPHP_PHP_SCRIPT_ENTRY` distinguishes this PHP-hosted execution from the already-compiled binary version. When present, the runtime interprets the source rather than executing native code, establishing the foundation for the self-hosting loop.

## Two-Phase Compilation Pipeline

The `main()` function in [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php) orchestrates the transformation through two distinct phases that ensure deterministic output.

### Prepare Phase: Symbol Model Construction

During **prepare**, the compiler parses every PHP file in the target source tree—including its own source when self-hosting—and constructs a complete symbol model without allocating runtime IDs. This phase performs semantic analysis and type inference across the entire codebase before any code generation occurs.

### Convert Phase: AST Lowering to C++17

The **convert** phase transforms the prepared Abstract Syntax Tree (AST) into C++17 source code. TypePHP then invokes the native compiler (Clang) to generate the final binary. As implemented in the source, this pipeline follows the sequence: PHP source → parse → lower → native compiler → binary.

## The Self-Hosting Mechanism

TypePHP achieves self-hosting by treating its own source code as a standard compilation target. When you invoke the compiler without the `--compiler` flag, it executes the same `main()` function used for any project build.

### Compiling the Compiler Itself

To create the self-hosted binary, run the bootstrap script against its own entry point:

```bash

# Bootstrap phase: compile the compiler using PHP interpreter

php bin/tpc.php bin/tpc.php -O2 -j 8

```

This command produces a native binary `./tpc` that contains the compiled version of the compiler. The resulting binary can then compile other PHP projects without requiring the PHP runtime:

```bash

# Self-hosted phase: use the native binary

./tpc examples/yield.php -O3 -r -- --help

```

### Deterministic Build Guarantees

Because TypePHP uses identical two-phase logic for both bootstrapping and self-hosted compilation, the binary produced from PHP source remains deterministic. The compiler applies the same symbol resolution and code generation paths to its own source as it does to user projects, preventing "bootstrap drift" where the compiled compiler diverges from its source representation.

## Native Type Assignment for Cross-Runtime Consistency

A critical technical requirement for self-hosting is ensuring that PHP variables maintain consistent behavior across both interpreted and compiled execution contexts. In [`src/CompilerBase.php`](https://github.com/swoole/typephp/blob/main/src/CompilerBase.php), the compiler assigns each PHP local variable a **fixed C++ type** during the conversion phase. The source code explicitly notes: "The self-hosted compiler assigns one fixed C++ type to each PHP local variable."

This deterministic typing ensures that when the compiler runs as PHP source (during bootstrap) versus as compiled C++ (after self-hosting), variable semantics remain identical. Without this guarantee, the compiler might produce different outputs when interpreting its own source versus executing its compiled form, breaking the self-hosting invariant.

## Summary

- **Pure PHP Bootstrap**: The [`bin/tpc.php`](https://github.com/swoole/typephp/blob/main/bin/tpc.php) script loads compiler modules via `require` statements, establishing the entry point for self-hosting.
- **Two-Phase Pipeline**: The `main()` function in [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php) executes prepare (symbol model) and convert (C++ generation) phases deterministically.
- **Self-Compilation**: TypePHP compiles its own source tree using the same pipeline as user projects, producing the `./tpc` native binary.
- **Type Consistency**: Fixed C++ type assignment in [`CompilerBase.php`](https://github.com/swoole/typephp/blob/main/CompilerBase.php) ensures identical behavior between interpreted and compiled execution.
- **Deterministic Output**: Identical compilation paths for bootstrap and self-hosted builds prevent divergence between source and binary.

## Frequently Asked Questions

### What does "self-hosting" mean for the TypePHP compiler?

Self-hosting means the TypePHP compiler is written entirely in PHP and can compile its own source code into a native executable. As stated in the repository README, "the `tpc` compiler binary is built by compiling the compiler's own PHP source code with TypePHP." This creates a feedback loop where the compiler builds itself through successive recompilations.

### How does the bootstrap process work without a pre-existing binary?

The bootstrap relies on the PHP interpreter to execute [`bin/tpc.php`](https://github.com/swoole/typephp/blob/main/bin/tpc.php), which loads the compiler's source modules from [`src/compiler.php`](https://github.com/swoole/typephp/blob/main/src/compiler.php) and related files. This interpreted execution compiles the TypePHP source into a native binary, after which the system no longer requires the PHP interpreter for compilation tasks.

### Why is deterministic typing crucial for TypePHP's self-hosting?

Deterministic typing ensures that each PHP variable receives exactly one fixed C++ type during compilation, regardless of whether the compiler is running as interpreted PHP (during bootstrap) or as compiled C++ (after self-hosting). This prevents semantic differences that would cause the compiled compiler to generate different code than the interpreted version, which would break the self-hosting guarantee.

### Can the self-hosted TypePHP compiler compile any PHP project?

Yes, the self-hosted binary uses the same `main()` function and two-phase pipeline as the bootstrap version. Once built, the native `./tpc` binary can compile any compatible PHP project using the command `./tpc <source> [options]`, offering the same optimization levels and code generation capabilities as the bootstrap process.