Catalog · How the catalog works
plang
A Pascal compiler built on LLVM.
- ★ 1 on GitHub
Anyone may press Interesting, signed in or not. It helps others find this project.
README
plang — Pascal LLVM Compiler
plang is a Pascal compiler built on LLVM, currently targeting both Linux and macOS platforms using either x86_64 or aarch64 CPUs. It implements ISO 7185 Standard Pascal at level 1 (conformant array parameters included) and ISO 10206 Extended Pascal. Turbo Pascal support is in development, with future support also planned for Delphi/Object Pascal and Free Pascal.
Native Windows support is not available, although it may be considered for a future update. For now, Windows users can run plang using WSL.
Background
plang is an experiment in crafting a Pascal compiler as a modern LLVM toolchain, utilizing the substantial code optimization and generation framework that LLVM offers. plang is intended to be intuitive for users who are accustomed to working with gcc and clang, and other compilers in those families.
I will be fully honest and transparent: this compiler was built using the assistance of AI technology. I understand that some of you will have deep philosophical issues with this, but it is not up for debate. Another aspect of this experiment is to explore and learn what AI technology can help us achieve as designers and developers. If you have an issue with this stance, then there are plenty of other Pascal solutions available for you to use. I wish you nothing but the best.
That said, I do strongly believe in code quality. The bottom line is that this compiler needs to be something that everyone can proudly and confidently use. AI can make mistakes, and merely putting out AI slop is not useful to anyone. Checking what AI produces is essential to ensure the quality of the compiler. One of the aims of this project is to produce new tests and sourcing existing ones to help validate the quality of this compiler and improve it wherever we can.
This project is not intended to take away from the excellent work of the Free Pascal project. I greatly admire their efforts to promote and support the Pascal langauge. I simply offer plang as another alternative solution for users who want to compile Pascal programs and leverage the use of the LLVM technology stack.
I welcome issue reports and contributions from the community. If you happen to find an issue, please report it on the issues page for this project. I am also very open to pull requests for quality fixes and enhancements.
IMPORTANT NOTE: plang is not an official component of the LLVM project. I am following many of their design choices and development practices, as they represent sound engineering principles.
Status
plang should be considered alpha quality at this time. I am actively iterating through issues and new features, but I would not consider it ready for production just yet. There are likely bugs yet to be discovered.
plang intends to support a rich set of Pascal language dialects:
Dialect (-std=) |
Description | Status |
|---|---|---|
iso7185 |
ISO 7185 Standard Pascal, level 1 | Feature complete |
iso10206 |
ISO 10206 Extended Pascal | Feature complete |
turbo |
Turbo Pascal extensions | In development |
delphi |
Delphi / Object Pascal extensions | Planned |
fpc |
Free Pascal extensions | Planned |
Unimplemented dialects are accepted on the command line but rejected
with an error; only iso7185, iso10206, and turbo are currently
accepted (turbo is in development and does not yet support the full
Turbo Pascal language). iso7185 is the default Pascal dialect unless
another dialect is specified.
plang currently passes all of the tests for ISO 7185 Standard Pascal in the Pascal Acceptance Test. As no comparable suite exists for Pascal extensions such as ISO 10206 Extended Pascal and others, support for these extensions is considered best effort. I will do my best to find and fix any bugs as they are encountered.
Documentation
| Document | Contents |
|---|---|
docs/technical_info.md |
How the compiler is put together, its diagnostics and warnings, and the test suite |
docs/conformance.md |
The ISO 7185 clause 5.1 documentation: implementation-defined and implementation-dependent behavior, and which of the standard's errors are reported |
docs/modules.md |
Extended Pascal modules and separate compilation |
Prerequisites
- CMake ≥ 3.16
- LLVM (any recent release; tested with 22.x) —
llcmust be onPATH - GCC ≥ 14 or Clang ≥ 18 (C++23 required)
- Google Test — only to build the test suite, which is off by default. Most of the suite is LLVM's
lit+FileCheck; Google Test covers a small, permanent set of unit tests over internals with no CLI-visible surface, the same split Clang itself uses betweenclang/test/andclang/unittests/.
Linking prerequisites vary by platform:
| Platform | Requirement |
|---|---|
| Linux | lld (ld.lld on PATH), and a GCC installation, whose startup files and libgcc the link uses |
| macOS | The Xcode command line tools (xcode-select --install), which supply the linker and the SDK |
Building and Installing
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(getconf _NPROCESSORS_ONLN)
cmake --install buildThe test suite is off by default and is built with -DPLANG_ENABLE_TESTS=ON.
See docs/technical_info.md for details as to
what is in it.
Embedding the frontend library
cmake --install also installs CMake package metadata for libplang-frontend
(the shared library behind the plang driver's own -pc1 frontend pass, and
the frontend for embedders), so a separate CMake project can do:
project(my_project LANGUAGES C CXX) # C is required -- see note below
find_package(plang REQUIRED)
target_link_libraries(my_target PRIVATE plang::plang_frontend)LANGUAGES C CXX, not just CXX: LLVM's own LLVMConfig.cmake needs a C
compiler enabled in the calling project (FindLibEdit.cmake's
check_include_file()), even though nothing plang-specific touches C.
plang_frontend links LLVM PRIVATE, so consumers don't inherit LLVM's own
CMake requirements just to link against it — this is the one exception,
coming from find_package(LLVM CONFIG) validating plang_frontend's link
interface at find_package(plang) time.
Only the frontend library is exported this way; the plang driver
executable itself is not.
The entry point an embedder actually calls is plang::compile()
(include/plang/Frontend/Compilation.h): a CompilationRequest in (source,
either a file path or an in-memory buffer, plus LangOptions/
DiagnosticOptions), a CompilationResult out (Success, an optional
Output string, and a Diagnostics vector) -- entirely in-process, no
subprocess and no stdout/stderr/exit-code protocol to parse back apart:
#include "plang/Frontend/Compilation.h"
plang::CompilationRequest Request;
Request.SourceName = "hello.pas";
Request.Buffer = "program hello; begin writeln('hi') end.";
plang::CompilationResult Result = plang::compile(Request);
if (!Result.Success) {
for (const plang::Diagnostic& D : Result.Diagnostics)
std::cerr << D.Message << "\n";
return 1;
}
// Result.Output holds the compiled LLVM IR text.See Compilation.h's own comments for the two constraints an embedder has
to design around (process-global locale selection, and .pmi/.tui
interface-file publishing as a side effect of compiling a module or unit).
Usage
# Compile and link
plang hello.pas -o hello
# Compile to object file only
plang -c hello.pas -o hello.o
# Emit LLVM IR
plang -emit-llvm hello.pas -o hello.ll
# Emit native assembly
plang -S hello.pas -o hello.s
# Optimization
plang -O2 program.pas -o program
# Debugging - see important notes below
plang -g program.pas -o program
gdb program
# Dialect selection (iso7185 is the default; turbo is in development, delphi and fpc are planned)
plang -std=iso10206 program.pas -o program # Extended Pascal
# Show the commands without running them
plang -### program.pas -o program
# Warnings are all on by default; turn one off, or all of them
plang --help-warnings # list them
plang -Wno-unused-parameter program.pas
plang -Werror program.pas
plang -w program.pas
# Give up after a set number of errors rather than cascading
plang -ferror-limit=5 program.pasNote: A record/pointer variable of a schema type (EP §6.4.7) whose extent is
only fixed at run time prints correctly under this ordinary gdb
workflow for its discriminant and any field at or before the first
varying-extent one; a field declared AFTER one does not (a real DWARF
limitation, not a plang bug -- see issue #130). If your program uses such
a schema and you want every field to print correctly, source the
companion gdb pretty-printer once per session:
gdb -ex "source /path/to/plang/share/plang/gdb/plang_schema_printers.py" program
Also: IMPORTANT (issue #145): that pretty-printer only ever corrects WHOLE-value
printing, e.g. print q^. A direct field-path access, e.g. print q^.field, bypasses it entirely and can still show a wrong value for a
field declared after a varying one -- gdb resolves that expression itself,
off the DWARF member offset, before the pretty-printer ever runs. This is
a limitation of gdb's pretty-printer API, not something more plang code
can fix; always print the whole value (print q^) for a correct view.
License
Apache License 2.0 with LLVM Exceptions. See LICENSE.md for the full text.

