aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AGENTS/ARCH.md39
-rw-r--r--AGENTS/EXTENDING.md2
-rw-r--r--AGENTS/PITFALLS.md6
-rw-r--r--doc/build.md63
-rw-r--r--doc/cpsc.1.md8
-rw-r--r--doc/language/keyword/cpsc-keyword-try.7.md2
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