Toolchain layout
What an installed Prismio toolchain contains, why a compiler is a directory rather than a file, and how to read a missing-module error.
Last verified
A Prismio compiler is a layout, not a file. The executable resolves everything else relative to its own location, so the pieces have to travel together.
<prefix>/
bin/prismio the compiler
lib/runtime/*.bc LLVM bitcode merged into every program
lib/runtime.hash which sources those modules came from
stdlib/*.plib what `import std.*` resolves to
bin/LLVM-C.dll Windows onlyThere is no hardcoded installation prefix and no environment variable to set. Move, rename or copy the whole directory and it keeps working; take bin/prismio out on its own and it can no longer build anything.
Where LLVM is
LLVM is inside the compiler, not next to it. On macOS and Linux, bin/prismio links the pinned LLVM 23.1.1 statically. It optimizes a program and generates its machine code in the same process, so the prefix needs no LLVM installed on the machine, and a brew upgrade or distribution update cannot change what it builds. Windows is the exception: the compiler loads LLVM from LLVM-C.dll in its own bin/ directory.
The one outside tool a build runs is the system's linker, and only for the last step: linking the finished object with the platform's C library. On macOS and Linux that is cc. On Windows it is Visual Studio's link.exe, found through vswhere together with the newest Windows SDK, so no developer prompt is needed. A cross build uses clang, because the driver has to accept --target. That is the same arrangement rustc uses. Set PRISMIO_CC to choose a different driver. On macOS the driver is asked only once what linker command it would run; later builds run ld with that command directly, which saves about 10 ms a build, and an Xcode update or an xcode-select switch is noticed and asks again. PRISMIO_LINK_CACHE=0 turns that off.
Why the runtime is bitcode
Everything a Prismio program needs at run time — strings, lists, maps, allocation, tasks — is implemented in C and shipped as LLVM bitcode, one module per runtime translation unit, rather than as an object archive.
The reason is optimization. The driver merges that bitcode into your program's own IR before the optimizer runs, so LLVM sees runtime function bodies while inlining, global optimization and dead-code elimination happen. An archive would be linked afterwards, opaque, and every call across the boundary would stay a call.
Two consequences are worth knowing:
- Your executable does not contain the whole runtime. After the merge, runtime definitions nothing reaches are deleted. A program that never touches a map does not carry the map implementation.
- There is no fallback. When an installed artifact is missing or unreadable, the build stops with an error that names the file. It does not quietly compile the runtime from source, which would produce a working but slower program and no indication of why.
Why the standard library is .plib
Each standard-library module installs as one compiled artifact — stdlib/map.plib for std.map. A PLIB holds two things: the module's interface, which the frontend still parses, and its compiled bitcode, which joins the same merge as the runtime.
The interface is still source text because generics have to be instantiated against your concrete types — Map<String, Int> in your program cannot be pre-compiled in the library. Non-generic definitions come from the bitcode.
The directory is flattened: std.map lives at stdlib/map.plib, with no std/ component on disk. Never derive a module's logical name from its path.
Inside a checkout, sources win
If you are working in a Prismio checkout, import std.string resolves to std/string.psm — the source — because imports search upward from your entry file before consulting the installed toolchain. A local standard-library edit therefore takes effect on your next build with no packaging step.
Outside a checkout there is nothing to find, and the same import resolves to stdlib/string.plib. Both paths produce the same program; only the discovery differs.
Reading a missing-module error
ERROR: Prismio installation is incomplete or corrupted.
Missing runtime module: lib/runtime/lang_runtime.bc
Reinstall Prismio and try again.The message names the exact file the compiler looked for, relative to the prefix. In practice it means one of three things:
- The binary was copied out of its prefix. Point at the original, or copy the whole directory.
- The toolchain was never assembled. A binary straight out of
tools/bootstrap.shis a compiler that can build compilers and nothing else. Runtools/package.py— see Installation. - The build names a target that was not packaged. Cross builds look under
lib/runtime/<triple>/, and a prefix only carries the targets it was packaged for.
prismio --version prints the compiler and standard-library directories it resolved, which distinguishes "wrong prefix" from "incomplete prefix" immediately.