Iter 5c: Cross-Module-Codegen

Symbol-Mangling-Schema einheitlich auf @ail_<modul>_<def> umgestellt
(auch für Single-Modul-Programme), String-Globals als
@.str_<modul>_<idx>. main bleibt LLVM-/C-ABI-Eintrittspunkt und ist
ein Trampoline auf @ail_<entry>_main. lower_workspace emittiert eine
einzige .ll für den ganzen Workspace, alphabetisch nach Modulname,
Cross-Module-Calls über Import-Map aufgelöst. ail build / ail emit-ir
laufen jetzt durch den Workspace-Pfad. IR-Snapshots regeneriert,
neuer ws_main-Snapshot. E2E-Test workspace_build_runs_imported_fn
prüft, dass das Binary die importierte Funktion korrekt aufruft.
Schuld #19 (source_filename) durch einheitliches <entry>.ail-Schema
geschlossen.
This commit is contained in:
2026-05-07 11:39:59 +02:00
parent b2878fe655
commit a20ab93c66
11 changed files with 493 additions and 157 deletions
+8
View File
@@ -100,6 +100,14 @@ Begründung:
Trade-off: keine Inline-Optimierungen über die LLVM-API. Wir setzen auf
`clang -O2` als Standard-Pipeline.
## Mangling-Schema (Iter 5c)
Alle AILang-Funktionen werden zu `@ail_<modul>_<def>` gemangelt — auch im
Single-Modul-Fall. Globale Strings/Konstanten zu `@.str_<modul>_<idx>`
bzw. `@ail_<modul>_<def>`. Eintrittspunkt ist eine `define i64 @main()`-
Trampoline, die `@ail_<entry-modul>_main()` aufruft. `source_filename`
existiert genau einmal pro Workspace und trägt den Eintrittsmodulnamen.
## Konvention: Qualifizierte Cross-Module-Verweise (Iter 5b)
Cross-Module-Aufrufe nutzen **keinen** neuen AST-Knoten. Stattdessen ist ein
+43
View File
@@ -249,3 +249,46 @@ IR-Snapshots.
Punkt-Konvention deckt nur einen Punkt ab — verschachtelte Modulpfade
(`a.b.c`) gibt es nicht; das wäre erst mit Hierarchie-Modulen ein
Thema und fällt aktuell als `unbound-var` durch.
## 2026-05-07 — Iter 5c fertig: Cross-Module-Codegen
- **Mangling-Bruch (mit Bedacht).** Alle AILang-Funktionen heißen jetzt
`@ail_<modul>_<def>`, auch in Single-Modul-Programmen. Die alte Form
`@ail_<def>` ist weg. Strings/Const-Globals analog
(`@.str_<modul>_<hint>_<idx>`, `@ail_<modul>_<const>`). Eintrittspunkt
bleibt `main` als C-ABI: ein `define i32 @main()`-Trampoline ruft
`@ail_<entry-modul>_main()`. Fehlt im Eintrittsmodul ein
`main : () -> Unit !IO`, fällt der Build mit `MissingEntryMain`.
- **Workspace-Lowering.** Neue Top-Level-API
`ailang_codegen::lower_workspace(ws: &Workspace) -> Result<String>`
produziert eine einzelne `.ll` für den ganzen Workspace. Module
alphabetisch (BTreeMap-Order); Defs in AST-Reihenfolge. Cross-Module-
Calls werden im Codegen über die Import-Map des aufrufenden Moduls
aufgelöst — gleiche Logik wie im Typchecker, lokal dupliziert mit
Verweis (kein gemeinsames Helper-Modul, weil die Typ-Welten
unterschiedlich sind: Typchecker hantiert mit `Type`, Codegen mit
`FnSig` aus llvm-Typen).
- **CLI.** `ail build` und `ail emit-ir` laden jetzt immer den Workspace
und checken/lowern ihn vollständig. Single-Modul-Programme funktionieren
weiter (Trivial-Workspace mit einem Modul). `emit_ir(m)` bleibt im
Codegen-Crate als Bequemlichkeits-API erhalten und wrapt intern in
einen Trivial-Workspace.
- **Snapshots regeneriert.** `sum.ll`, `max3.ll`, `hello.ll`, `list.ll`
zeigen das neue Mangling. Neuer `ws_main.ll`-Snapshot dokumentiert den
Cross-Module-Build: `@ail_ws_main_main` ruft `@ail_ws_lib_add` auf.
- **Tests.** 40 grün (vorher 37). Neu: `workspace_build_runs_imported_fn`
(e2e: druckt 5), `ir_snapshot_ws_main`, `missing_entry_main_is_error`
(codegen-unit). Bestehende Verhaltens-Tests
(`sum_1_to_10_is_55`, `max3_picks_largest`, `hello_world_str_lit`,
`list_sum_via_match`) bleiben grün — Verhalten unverändert, nur das
Mangling ist neu.
**Schulden geschlossen:**
- **#19 (`source_filename` härten).** In der Workspace-Welt ist
`source_filename` jetzt einheitlich `<entry-modul>.ail`, einmal pro
Workspace. Der bisherige hartkodierte Pfad-Punkt entfällt damit.
**Stand:** Modulsystem ist Ende-zu-Ende geschlossen — Loader + Typcheck
+ Codegen + Build sehen den Workspace als kohärente Einheit. Multi-
Diagnose-Refactor und ggf. ADT-Cross-Module bleiben für später.