From 7beb5fe687431ecc6b5e79379284cbaa898f3776 Mon Sep 17 00:00:00 2001 From: _ov4 Date: Wed, 14 Oct 2026 09:32:08 +0000 Subject: docs(toolchain): document LLVM and Clang 23 requirements Update build and native-link examples, PATH version-check rules and LLVM API guidance. Record Linux verification and retain the Windows/macOS verification limits. Co-Authored-By: Claude Fable 5.1 --- AGENTS/ARCH.md | 39 ++++++++++-------- AGENTS/EXTENDING.md | 2 +- AGENTS/PITFALLS.md | 6 +-- doc/build.md | 63 +++++++++++++++++++----------- doc/cpsc.1.md | 8 ++-- doc/language/keyword/cpsc-keyword-try.7.md | 2 +- 6 files changed, 73 insertions(+), 47 deletions(-) diff --git a/AGENTS/ARCH.md b/AGENTS/ARCH.md index 6901c19..178a8a6 100644 --- a/AGENTS/ARCH.md +++ b/AGENTS/ARCH.md @@ -1,7 +1,8 @@ # Architecture `cpsc` compiles CIE A-Level 9618 pseudocode to LLVM IR. Classic three-stage -Kaleidoscope-style design, C++17, built with LLVM 18. Execution is selected at +Kaleidoscope-style design, C++17, built with LLVM 23 and Clang 23. CMake rejects +other major versions and non-Clang compilers. Execution is selected at build time: external lli, an embedded static LLVM engine, or disabled. ``` @@ -38,12 +39,12 @@ development libraries to build; NONE still generates IR. Native binaries remain ```bash # Prepare dependencies using the recommendations in doc/build.md. cmake -S . -B build -DCPSC_RUN_MODE=EMBEDDED \ - -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ + -DCMAKE_C_COMPILER=clang-23 -DCMAKE_CXX_COMPILER=clang++-23 cmake --build build build/cpsc prog.cps -o prog.ll # default without -o: prog.ir beside the source build/cpsc prog.cps -r # execute using the selected build mode build/cpsc prog.cps -r -o prog.ir # save IR, then run it -clang++-18 prog.ll -o prog && ./prog +clang++-23 prog.ll -o prog && ./prog ``` `doc/build.md` recommends which packages to install and which to download; @@ -55,8 +56,11 @@ under the build directory are also searched. The shared reports missing required dependencies. Compilers, make, LLVM, support libraries, Pandoc, Git and installer/relocation tools use the same lookup policy. System-only and mixed installations are supported. Local dependencies override cached system -paths. Build tools are resolved before `project()` enables compiler checks; -compiler information is refreshed when the selected executable changes. +paths except for supplied compilers. Cached or explicit CMake compiler paths and +initial CC/CXX selections are preserved and validated; default discovery prefers +clang-23/clang++-23, then unversioned clang/clang++. Build tools are resolved before +`project()` enables compiler checks; compiler information is refreshed when the +selected executable changes. Platform modules relocate package paths only inside the extraction directory; Homebrew bottles also receive local Cellar/opt links and Mach-O relocation/signing. Package hashes skip unchanged extractions; a changed package set rebuilds the @@ -65,10 +69,10 @@ not to CMake. The Windows Pandoc ZIP is downloaded directly from its official release because MSYS2 has no Pandoc package. Only the Linux build is verified. Generated IR uses the C++ exception ABI; native binaries must link its runtime -(use `clang++-18`). TRY/CATCH/ENDTRY and bare THROW are compiler extensions. +(use `clang++-23`). TRY/CATCH/ENDTRY and bare THROW are compiler extensions. Runtime checks throw anonymous exceptions; the final handler in generated main prints `Unhandled exception. Program terminated.` to stdout and returns 1. -Exception execution is verified on Linux with LLVM 18; Windows/macOS are unverified. +Exception execution is verified on Linux with LLVM 23; Windows/macOS are unverified. Driver behavior (`tools/driver/main.cc`): @@ -91,8 +95,11 @@ Driver behavior (`tools/driver/main.cc`): (including symlinks/hard links) are rejected. - In PATH mode, `-r` executes PATH's `lli` using LLVM Support process APIs, with inherited stdin/stdout/stderr and no shell. Missing lli is rejected before - compiling or writing output. Process-launch/crash failures return 1. `-r` - alone uses temporary IR removed on return, including execution failure. + compiling or writing output. The selected `lli --version` must identify LLVM 23 + and succeed within five seconds; other or unrecognized versions fail before + source compilation. Without `-r`, no external tools are checked; clang/clang++ + are never invoked or checked by this mode. Process-launch/crash failures return 1. + `-r` alone uses temporary IR removed on return, including execution failure. - In EMBEDDED mode, `-r` uses MCJIT in-process (`tools/driver/EmbeddedRunner.cc`). The engine owns a clone of CodeGen's module; CodeGen retains the context and must outlive the engine. Static C++ exception ABI symbols are explicitly @@ -105,10 +112,10 @@ Driver behavior (`tools/driver/main.cc`): streams. `-r -o` saves IR before executing and keeps it on execution failure. EMBEDDED requires static LLVM archives. `cmake/EmbeddedLLVM.cmake` also selects -static compression/terminal support archives when LLVM uses them. Linux GCC/Clang +static compression/terminal support archives when LLVM uses them. Linux Clang builds link the C++ runtime statically; MinGW uses `-static`. The tested Debian -LLVM 18 executable has only libc, libm and the system loader as dynamic dependencies, -and runs in a minimal chroot without LLVM/lli. Windows EMBEDDED is untested. +LLVM 23 executable has only libc, libm and the system loader as dynamic dependencies. +Windows EMBEDDED is untested. On Linux, `make -C build install` builds the manual and calls the POSIX `install.sh` to copy `cpsc` into `CMAKE_INSTALL_PREFIX/bin` and all manuals into @@ -160,10 +167,10 @@ Linux smoke tests can configure an isolated build with `-DWIN32=TRUE` to exercis HTML/ZIP packaging; the resulting renamed Linux executable is only a test fixture, not a usable Windows release. -Build pin: developed and tested against **LLVM 18**. (The historical LLVM 19 breakage — -`ArithmeticHandler.cc` touching `llvm::Module` through a transitive include — is gone -now that string concatenation lives in `StringHandler`, but newer LLVM versions remain -untested.) +Build pin: **LLVM 23 and upstream Clang 23** (any 23.x release); 23.1.3 is verified +on Linux. LLVM 23 uses `CreateGlobalString` for opaque string pointers, +`hasTerminator()` for block termination checks (its `getTerminator()` requires an +existing terminator), and an explicit `llvm::Triple` for the embedded target. ## Layout diff --git a/AGENTS/EXTENDING.md b/AGENTS/EXTENDING.md index ac9f50e..2b1549f 100644 --- a/AGENTS/EXTENDING.md +++ b/AGENTS/EXTENDING.md @@ -11,7 +11,7 @@ unique_ptr children, move ctor, raw-ptr getters) → `ParseXxx` in `ParseExprList(close, allowEmpty)`; add the new statement's leading keyword to `syncToStatementStart`) → `dynamic_cast` branch in `CodeGen::emitStmt`. Guard every fall-through branch in control-flow codegen with -`if (!Builder->GetInsertBlock()->getTerminator())` — a RETURN in the body may have +`if (!Builder->GetInsertBlock()->hasTerminator())` — a RETURN in the body may have already terminated the block. **New builtin function:** add a `{Name, Arity, ReturnTypeName}` row to the static diff --git a/AGENTS/PITFALLS.md b/AGENTS/PITFALLS.md index 6e0202e..9b32150 100644 --- a/AGENTS/PITFALLS.md +++ b/AGENTS/PITFALLS.md @@ -82,8 +82,8 @@ test programs. ENDTRY. Bare THROW raises a new anonymous exception even inside CATCH; there is no rethrow syntax, error object or what(). Runtime checks are catchable; compiler errors are not. Uncaught exceptions print only the generic message - and return 1. Native binaries must link the C++ runtime with `clang++-18`. - Unwinding does not free heap strings/arrays or close files. Linux LLVM 18 is + and return 1. Native binaries must link the C++ runtime with `clang++-23`. + Unwinding does not free heap strings/arrays or close files. Linux LLVM 23 is verified; Windows and macOS exception execution is not. - **C type extensions.** C_STRING is a raw char pointer, not a STRING: explicitly @@ -93,7 +93,7 @@ test programs. require casts even for literals. C scalar arithmetic uses native promotions, but / always returns REAL. Cast aliases must precede their use. long double may have padding; sizeof does not identify its floating-point format. Native - C support is verified on Linux LLVM 18; cross-target and EXTERN are unsupported. + C support is verified on Linux LLVM 23; cross-target and EXTERN are unsupported. ## Not implemented (9618 features) diff --git a/doc/build.md b/doc/build.md index 4942859..c8345a3 100644 --- a/doc/build.md +++ b/doc/build.md @@ -15,11 +15,14 @@ optional tools all follow the same lookup rule: local build directories first, then the system. A required dependency missing from both locations is an error. System-only and mixed installations are supported, including system-installed LLVM without any local LLVM download. Local dependencies take precedence over -previously cached system paths. +previously cached system paths, except for an explicitly selected compiler. CMake searches standard `bin/`, `lib/` and `include/` directories under the build directory as well as the extracted package layouts. Compiler and make selection -follow the same rule as LLVM and Pandoc selection. +follow the same rule as LLVM and Pandoc selection unless a compiler is supplied +through `CMAKE_C_COMPILER`, `CMAKE_CXX_COMPILER` (including cached values), or +the initial `CC`/`CXX` environment. Supplied compilers are preserved and checked. +Default discovery prefers `clang-23` and `clang++-23`, then `clang` and `clang++`. Unchanged packages are not extracted again. Keep one version of each package in the download directory; remove old archives before downloading a different @@ -29,15 +32,21 @@ instead. Removing the build directory also removes its downloaded dependencies. All three execution modes need LLVM development libraries to build, including `NONE`. Users of an `EMBEDDED` executable do not need LLVM or `lli`. -LLVM 18 is the tested version; newer versions remain untested. +CMake strictly requires LLVM development libraries and both C/C++ compilers to +have major version 23. The compilers must be upstream Clang; GCC and AppleClang +are rejected. Any 23.x release is accepted; 22 and 24 are rejected. LLVM/Clang +23.1.3 is verified on Linux; Windows and macOS remain unverified. + +When upgrading an existing build, replace its old LLVM packages and explicitly +select Clang 23 for both cached compiler paths, or use a fresh build directory. ### Linux (Debian/Ubuntu) -Use a distribution repository that provides LLVM 18. Recommended build tools: +Use a distribution repository that provides LLVM 23. Recommended build tools: ```bash sudo apt-get update -sudo apt-get install -y --no-install-recommends build-essential cmake clang-18 +sudo apt-get install -y --no-install-recommends build-essential cmake clang-23 ``` Recommended LLVM and support-package downloads: @@ -47,8 +56,8 @@ mkdir -p build/deps/packages ( cd build/deps/packages apt-get download \ - llvm-18-dev llvm-18 llvm-18-runtime llvm-18-tools llvm-18-linker-tools \ - libllvm18 libclang-cpp18 libz3-dev libz3-4 \ + llvm-23-dev llvm-23 llvm-23-runtime llvm-23-tools llvm-23-linker-tools \ + libllvm23 libclang-cpp23 libz3-dev libz3-4 \ libffi-dev libffi8 libxml2-dev libxml2 \ zlib1g-dev zlib1g libzstd-dev libzstd1 libncurses-dev libtinfo6 ) @@ -90,12 +99,13 @@ pacman -Sw --noconfirm --cachedir "$PWD/build/deps/packages" \ `-Sw` downloads packages without installing them; omit `--needed` here so that already installed dependencies are also downloaded. CMake keeps the packages' `mingw64/` layout under `build/deps/root/`. MSYS2 supplies its current LLVM -version. Windows builds have only been reviewed statically. +version; check that it is 23. Windows builds have only been reviewed statically. ### macOS (Homebrew) -Use Clang and make from the Xcode Command Line Tools. If they are missing, run -`xcode-select --install`. Install CMake with Homebrew: +Install the Xcode Command Line Tools for the macOS SDK, make and package +relocation tools with `xcode-select --install` if needed. The LLVM bottle below +provides Clang 23. Install CMake with Homebrew: ```bash brew install cmake @@ -106,10 +116,12 @@ Recommended binary-bottle downloads to the build directory: ```bash mkdir -p build/deps/packages HOMEBREW_CACHE="$PWD/build/deps/packages" brew fetch --force-bottle \ - llvm@18 zlib zstd ncurses lz4 xz + llvm zlib zstd ncurses lz4 xz ``` -This requires binary bottles available for your macOS version and CPU; source +[Homebrew's `llvm` formula](https://formulae.brew.sh/formula/llvm) currently +provides 23; verify the downloaded version before configuring. This requires +binary bottles available for your macOS version and CPU; source archives are not used. CMake extracts the bottles into a local `Cellar/`, creates local `opt/` links and relocates their CMake and dynamic-library paths using the Command Line Tools. The macOS build has only been reviewed statically. @@ -121,7 +133,7 @@ initial configuration; there is no default. The choice is saved in CMake's cache | Mode | Behavior of `-r` | |---|---| -| `PATH` | Run external `lli` from PATH; reject `-r` if it is unavailable. | +| `PATH` | Run external `lli` from LLVM 23 in PATH; reject `-r` before compilation if it is missing or its version cannot be validated. | | `EMBEDDED` | Run with the statically linked LLVM engine inside `cpsc`; no PATH lookup. | | `NONE` | Reject `-r`; compiling to IR still works. | @@ -129,7 +141,7 @@ Linux: ```bash cmake -S . -B build -DCPSC_RUN_MODE=EMBEDDED -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_COMPILER=clang-18 -DCMAKE_CXX_COMPILER=clang++-18 + -DCMAKE_C_COMPILER=clang-23 -DCMAKE_CXX_COMPILER=clang++-23 cmake --build build -j4 ``` @@ -146,7 +158,8 @@ macOS: ```bash cmake -S . -B build -DCPSC_RUN_MODE=EMBEDDED -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ + -DCMAKE_C_COMPILER="$PWD/build/deps/root/opt/llvm/bin/clang" \ + -DCMAKE_CXX_COMPILER="$PWD/build/deps/root/opt/llvm/bin/clang++" cmake --build build -j4 ``` @@ -155,20 +168,26 @@ skip the download steps and use the same build commands. Local and system dependencies can also be mixed; the lookup rule applies to each dependency. Local packages do not need `-DLLVM_DIR`. You can specify `-DLLVM_DIR=/path/to/lib/cmake/llvm` for a system installation outside the usual -search paths or to select a system LLVM version when several are installed. +search paths or to select LLVM 23 when several system versions are installed. +For a system Homebrew installation, select the compilers under +`$(brew --prefix llvm)/bin` instead of the extracted paths above. Distribute `build/cpsc` (Windows: `build/cpsc.exe`) for `EMBEDDED`. LLVM and its required compression/terminal support libraries are linked statically; a missing required archive is a configure error. Linux also links the C++ runtime statically, -and MinGW uses static linking. The tested Debian/LLVM 18 executable needs only +and MinGW uses static linking. The tested Debian/LLVM 23 executable needs only the system libc, libm and dynamic loader. Build for the intended OS and CPU. -For `PATH` mode, add the extracted `lli` directory to your shell's PATH after -configuration. On Linux, also expose its downloaded runtime libraries: +For `PATH` mode, add the extracted LLVM 23 `lli` directory to your shell's PATH +after configuration. Only `-r` checks the selected `lli --version`, with a +five-second timeout. Missing, wrong or unrecognized versions fail before source +compilation or IR output. Compiling without `-r` does not check external tools; +execution does not invoke or check `clang`/`clang++`. On Linux, also expose its +downloaded runtime libraries: ```bash -export PATH="$PWD/build/deps/root/usr/lib/llvm-18/bin:$PATH" -export LD_LIBRARY_PATH="$PWD/build/deps/root/usr/lib/$(cc -print-multiarch)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" +export PATH="$PWD/build/deps/root/usr/lib/llvm-23/bin:$PATH" +export LD_LIBRARY_PATH="$PWD/build/deps/root/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" ``` MSYS2 MINGW64: @@ -180,7 +199,7 @@ export PATH="$PWD/build/deps/root/mingw64/bin:$PATH" macOS: ```bash -export PATH="$PWD/build/deps/root/opt/llvm@18/bin:$PATH" +export PATH="$PWD/build/deps/root/opt/llvm/bin:$PATH" ``` ## Manual diff --git a/doc/cpsc.1.md b/doc/cpsc.1.md index b6b7ad0..362d48b 100644 --- a/doc/cpsc.1.md +++ b/doc/cpsc.1.md @@ -32,7 +32,7 @@ Without **-o** or **-r**, replace the source filename's extension with `.ir` and The executable has one of the following execution modes, selected when it was built. All modes can compile to LLVM IR; the mode determines whether and how **-r** runs the program. **PATH** -: Run `lli` from PATH. If it cannot be found, **-r** fails before compilation or output writing. Without **-o**, write temporary IR and delete it afterward, including on execution failure. +: Run `lli` from LLVM 23 in PATH. With **-r**, check the selected executable's version before compilation or output writing; a missing executable, a different major version or a failed or unrecognized version check is a fatal error. Version detection has a five-second timeout. Without **-r**, no external tools are checked. This mode does not invoke or check `clang` or `clang++`. Without **-o**, write temporary IR and delete it afterward, including on execution failure. **EMBEDDED** : Run the statically linked LLVM engine inside `cpsc`, without looking for `lli` in PATH. Without **-o**, execute the module in memory. Users do not need LLVM or `lli` installed; the executable may still depend on the operating system's C runtime libraries. @@ -70,7 +70,7 @@ Build a native program with a C++ linker so the exception runtime is linked: ```sh cpsc test.cps -o test.ll -clang++-18 test.ll -o test +clang++-23 test.ll -o test ./test ``` @@ -80,7 +80,7 @@ clang++-18 test.ll -o test : Compilation succeeded, or **-h** printed the documentation entry point. **1** -: An argument, file, compilation or execution-engine error occurred, including missing input, when PATH mode cannot find `lli` or NONE mode receives **-r**. +: An argument, file, compilation or execution-engine error occurred, including missing input, when PATH mode cannot validate `lli` from LLVM 23 or NONE mode receives **-r**. With **-r**, return the executed program's exit status. In PATH mode, failure to launch `lli` or a child-process crash returns 1. @@ -92,7 +92,7 @@ Compiler diagnostics go to stderr. Failed compilation does not write IR. Success Missing input, including invoking `cpsc` without arguments, reports `cpsc: fatal error: no input files`. Ordinary lexical, syntax and semantic errors use `error:`; failures that prevent compilation, such as file I/O errors, use `fatal error:`. Compilation and argument failures end with one `compilation terminated.` line. Execution-stage failures do not print that line. -Generated IR uses the C++ exception ABI. Native binaries need the C++ runtime; EMBEDDED includes it, while PATH uses the runtime available to `lli`. Exception execution is verified on Linux with LLVM 18; Windows and macOS remain unverified. +Generated IR uses the C++ exception ABI. Native binaries need the C++ runtime; EMBEDDED includes it, while PATH uses the runtime available to `lli`. Exception execution is verified on Linux with LLVM 23; Windows and macOS remain unverified. # SEE ALSO diff --git a/doc/language/keyword/cpsc-keyword-try.7.md b/doc/language/keyword/cpsc-keyword-try.7.md index 3b48dc4..5892027 100644 --- a/doc/language/keyword/cpsc-keyword-try.7.md +++ b/doc/language/keyword/cpsc-keyword-try.7.md @@ -26,7 +26,7 @@ THROW takes no argument and always raises a new anonymous exception. An exceptio Runtime checks throw the same anonymous exceptions for division by zero, array index errors, null pointer dereferences, invalid enumeration values, array-parameter bounds mismatches, and file misuse. Compiler errors cannot be caught. A caught exception prints nothing automatically. If no handler catches an exception, the program prints `Unhandled exception. Program terminated.` to standard output and returns status 1. -Arrays declared inside either body remain local to that block. Stack unwinding does not automatically free heap strings or arrays, close files, or run user-defined destructors. Exception execution is verified on Linux with LLVM 18; Windows and macOS remain unverified. +Arrays declared inside either body remain local to that block. Stack unwinding does not automatically free heap strings or arrays, close files, or run user-defined destructors. Exception execution is verified on Linux with LLVM 23; Windows and macOS remain unverified. # EXAMPLE -- cgit v1.3.1-4-g156e