# PHP-AOT-Compiler: Fallstricke für PHPEF

Diese Notiz sammelt Design-Lektionen aus KPHP, HPHPc/HHVM, PeachPie/Phalanger sowie älteren Roadsend-/phc-artigen PHP-Compileransätzen. Sie ist bewusst knapp: PHPEF soll daraus vor allem ableiten, wo ein AOT-Compiler explizite Metadaten, Diagnostik oder Runtime-Fallbacks braucht.

## Dynamische Namen

PHP erlaubt Aufrufe und Symbolzugriffe wie `call_user_func($name)`, `$obj->$method()`, variable Variablen (`$$name`) sowie dynamische Funktions- und Klassennamen. Für AOT ist das schwer, weil der vollständige Ziel-Symbolsatz vorab bekannt sein müsste. KPHP formuliert das sehr deutlich: relevante Symbole sollen zur Compile-Zeit bekannt sein; dynamische Namen sind grundsätzlich problematisch.

PHPEF-Folge: dynamische oder embed-ambige Aufrufe müssen sichtbar markiert werden, z. B. als `zendcall_X`, statt still als normaler `phpfunc_X`-Wrapper kompiliert zu werden.

## `eval`, dynamische Deklarationen und Symboltabellen

`eval`, `create_function`, dynamische Deklarationen und Runtime-Mutation der Symboltabelle sprengen die AOT-Welt. HPHPc unterstützte `eval()`/`create_function()` nicht; KPHP verbietet `eval` und dynamische Deklarationen ebenfalls.

PHPEF-Folge: solche Stellen nicht „halb“ kompilieren. Entweder klar diagnostizieren, explizit an Zend/libphp delegieren oder eine bewusst begrenzte Runtime-Policy verlangen.

## Reflection und Introspection

`function_exists`, `class_exists`, `get_declared_classes` und Reflection-APIs fragen in PHP nicht nur nach einer syntaktischen Liste, sondern nach dem effektiven Runtime-Symbolraum inklusive Extensions, Includes, Autoload und ggf. Zend-Zustand.

PHPEF-Folge: PHPEF braucht eine eigene Symbol-/Wrapper-Registry plus Zend/libphp-Referenz, wo nötig. Host-PHP-`function_exists()` darf nie als alleinige Wahrheit gelten, besonders wenn ein PHPEF-Wrapper existiert oder fehlt. Das betrifft direkt die Arbeit um `zendcall_function_exists` / `phpfunc_zendcall_function_exists`: Wrapper-/Inventory-Metadaten sind autoritativ für PHPEF-Compile-Entscheidungen; Zend kann zusätzlich klassifizieren, ob ein Symbol in der gewählten PHP-Runtime existiert.

## Extensions und Stdlib-Abdeckung

KPHP und PeachPie zeigen, dass Kompatibilitätslücken pro Extension und Funktion normal sind. Ein Compiler kann nicht still annehmen, dass „PHP-Funktion vorhanden“ gleich „PHPEF-kompilierbarer Wrapper vorhanden“ bedeutet.

PHPEF-Folge: das Runtime-Embed-Inventar ist ein expliziter Vertrag. Build, Resolver und Diagnostik sollen sagen können: Wrapper vorhanden, nur Zend-Fallback vorhanden, Extension fehlt, oder Symbol unbekannt.

## Typmodell vs. zval-Semantik

KPHP erreicht Geschwindigkeit durch Einschränkungen, Typannahmen und einen unterstützten Sprach-Subset. Vollständige PHP-Kompatibilität verlangt dagegen `zval`-Semantik, Konvertierungen, Referenzen und Zend-nahe Randfälle.

PHPEF-Folge: die aktuelle Richtung bleibt sinnvoll: zuerst zval-first/runtime-first für PHP-Kompatibilität, danach native/statische Optimierungen als sichtbare Optimizer-Schritte.

## Includes, Autoload und Composer

PHP löst Includes, Autoloading und Composer-Klassen zur Laufzeit oft dynamisch auf. AOT muss entscheiden, ob es eine vollständige Welt vorab einsammelt oder zur Laufzeit explizit an Zend/Autoload-Fallbacks delegiert.

PHPEF-Folge: die Compile-Policy muss vollständig/geschlossen vs. offen/fallbackfähig unterscheiden. Unsichere Dynamik darf nicht still zu falschem Native-Code werden.

## Referenzen, Copy-on-Write und Array-Zeiger

`&`, Aliasing, Copy-on-Write und interne Array-Zeiger (`reset`, `current`, `next`, ...) sind PHP-Spezialfälle. Sie beeinflussen Werte, Identität und Seiteneffekte und dürfen nicht wie einfache native Werte behandelt werden.

PHPEF-Folge: diese Semantik zuerst in Runtime-Core/Embed und Tests modellieren. Native Optimierungen dürfen erst greifen, wenn Alias- und COW-Regeln nachweislich erhalten bleiben.

## Deployment, Debugging und Dual-Engine-Kosten

HPHPc hatte Sprachlücken, andere Deployment-Anforderungen und parallel HPHPc/HPHPi als unterschiedliche Ausführungswelten. HHVM wechselte später Richtung JIT/Hack und beendete PHP-Support. Das zeigt: ein zweiter Engine-Pfad kostet dauerhaft Wartung, Debugging und Kompatibilität.

PHPEF-Folge: Unterschiede zwischen kompiliertem Pfad, Zend-Fallback und Host-PHP müssen explizit bleiben. Diagnostik soll klar sagen, welcher Pfad gewählt wurde und warum.

## Konkrete PHPEF-Regeln

- Wrapper- und Inventory-Metadaten sind für PHPEF-Compile-Entscheidungen autoritativ.
- Host-PHP nicht als finale Wahrheit befragen, wenn ein PHPEF-Wrapper oder Embed-Inventar existiert.
- Dynamische/embed-ambige Aufrufe explizit markieren (`zendcall_X`, später ggf. eigene Fallback-Knoten).
- Fehlende Wrapper, fehlende Extensions und unsichere Dynamik als klare Diagnostik ausgeben.
- Unsichere dynamische PHP-Features nicht still nativ kompilieren.
- zval-first/runtime-first bleibt der Kompatibilitätspfad; native/static Lowerings sind spätere, sichtbare Optimierungen.

## Quellen

- KPHP vs PHP differences: <https://vkcom.github.io/kphp/kphp-language/kphp-vs-php/kphp-vs-php-differences.html>
- KPHP call function by name: <https://vkcom.github.io/kphp/kphp-language/howto-by-kphp/call-function-by-name.html>
- PeachPie compatibility: <https://docs.peachpie.io/php/Compatibility/> und <https://docs.peachpie.io/compatibility-status/>
- PeachPie well-known differences: <https://docs.peachpie.io/php/differences/>
- HHVM Ending PHP Support: <https://hhvm.com/blog/2018/09/12/end-of-php-support-future-of-hack.html>
- HHVM/HPHPc overview mit `eval`/`create_function`/Deployment/Dual-Engine-Hinweisen: <https://allanmacgregor.com/posts/introduction-hhvm>
- phc thesis: <https://paulbiggar.com/research/thesis.pdf>
