This directory contains scripts for running LLGo locally and inside reusable Linux dev containers.
- Docker installed and running
- Docker Compose v2 (
docker compose, notdocker-compose)
Start an interactive shell (pick one):
./dev/docker.sh amd64
./dev/docker.sh arm64
./dev/docker.sh i386Notes:
amd64uses thepydepsimage target (includes extra Python demo deps likenumpy/torch).arm64andi386use the smallerbasetarget (no extra Python ML deps).
Inside the container, run tests/builds using the repo scripts:
./dev/llgo.sh test ./...
./dev/llgo.sh test ./test
# WASI/WASM (wasip1/wasm)
./dev/llgo_wasm.sh build ./...Notes:
dev/docker.shstarts in the same repo subdirectory you launched it from.dev/llgo.shanddev/llgo_wasm.shmust be run from withinLLGO_ROOT(the repo) and will error otherwise.
./dev/docker.sh amd64 bash -lc './dev/llgo.sh test ./test'From anywhere inside the repo:
./dev/llgo.sh test ./test
./dev/llgo_wasm.sh build ./..../dev/local_ci.shThis script creates a temporary workspace, runs formatting/build/tests, runs llgo test, and then runs demo checks.
You can control demo parallelism via LLGO_DEMO_JOBS (defaults to up to 4 jobs).
dev/docker.sh is a thin wrapper around docker compose:
./dev/docker.sh <arch> [command...]<arch>must beamd64,arm64, ori386.- If
[command...]is omitted, it starts an interactivebash. - If
[command...]is provided, it runs that command and exits. - You must run it from within the repo (within
LLGO_ROOT), and it will start in the matching repo subdirectory inside the container.
LLGo has separate refresh flows for runtime data and LLVM IR checks:
gentestsfor runtime-output and package-metadata golden fileslitgenfor the curated set of source-embedded, autogenerated// LITTESTFileCheck snapshots
Run:
go run ./chore/gentestsBehavior:
- Refreshes
expect.txtfor the built-in runtime test suites using the existing execution flow. - Refreshes
meta-expect.txtfor package-metadata tests. - Preserves the runtime-output skip convention where
expect.txtcontaining only;means "do not refresh".
LLVM IR is not part of the gentests workflow; it is checked from the marked
Go source with FileCheck.
Autogenerated checks stay in the Go source file. A test opts in with an
autogenerated note immediately after // LITTEST; the note also records the
arguments required to reproduce the checks:
// LITTEST
// NOTE: Assertions have been autogenerated by chore/litgen UTC_ARGS: --function=run --check-globals=smartCreate or replace an autogenerated region explicitly:
go run ./chore/litgen --function=run --check-globals=smart path/to/in.goRefresh existing autogenerated tests recursively, using the arguments recorded in each source file:
go run ./chore/litgen -u clCheck that committed autogenerated checks are current without modifying files:
go run ./chore/litgen -u --check clBehavior:
- Accepts one or more paths.
- If the path is a
.gofile, it refreshes only that file. The file must start with// LITTEST. - If the path is a directory, it walks that directory recursively and processes marked source files in a stable order.
-u/--update-onlyupdates only tests that already carry the autogenerated note. Handwritten checks are never silently replaced.--checkreports stale autogenerated checks and does not write files.--functionis repeatable and selects functions by regular expression. Use--all-functionsonly when the entire generated module is genuinely the test contract.--check-globals=none|smart|allcontrols global checks.smartkeeps globals referenced by selected functions.- Generated checks abstract numeric LLVM SSA values, block suffixes, numeric globals, and generated cgo symbol hashes to reduce irrelevant churn.
- Does not update runtime-output or package-metadata goldens.
Use litgen only when a test intentionally checks a broad IR shape. Prefer
short, handwritten FileCheck assertions for a single lowering or ABI property.
Runtime output does not replace focused IR checks; it only removes the need for
a second full-output snapshot.
Use 100 FileCheck directive lines as an audit threshold rather than a size cap.
For a larger handwritten fixture, every group should correspond to an explicit
semantic contract. Convert long contiguous IR-shape checks to an opted-in
litgen snapshot instead.
Source-embedded IR checks are enabled by putting this marker on the first line of the source file:
// LITTESTThe generated directives are consumed by the existing littest/FileCheck path in the compiler tests.
The plain marker retains the existing IR stage for the fixture's effective target. To check that stage for several platforms independently of the host, list a cross-compilation matrix explicitly:
// LITTEST darwin/arm64 linux/amd64The harness generates IR once for every listed GOOS/GOARCH pair and enables
CHECK together with the corresponding architecture and specific prefixes,
such as CHECK,ARM64,DARWIN-ARM64 or CHECK,AMD64,LINUX-AMD64. Keep portable
assertions under CHECK, assertions shared by an architecture under ARM64,
AMD64, and similar prefixes, and only OS-specific differences under the exact
target prefix. Do not hide known platform differences in regular-expression
alternatives.
The fixture's current effective target is always checked as well. Targets on
the marker add cross-compilation coverage rather than replacing the platform
running the test, and a listed target equal to the current target is
deduplicated. An unlisted CI platform therefore still exercises all portable
CHECK assertions; add its explicit prefix when it has a distinct IR contract.
A test can instead check the module after target ABI lowering and before LLVM optimization:
// LITTEST: POST-ABIWithout an autogenerated note, post-ABI checks remain handwritten and
litgen -u leaves them untouched.
A post-ABI fixture can request several GOOS/GOARCH configurations on the same marker. The harness generates IR once per listed target while the target prefixes keep the differing assertions in one file. Runtime output, when present, is still executed once with the fixture's normal run configuration.
// LITTEST: POST-ABI linux/amd64 linux/arm64To opt a post-ABI target matrix into automatic maintenance, add the same
autogenerated note used by an ordinary fixture. Automatic post-ABI
generation requires at least one explicit GOOS/GOARCH target on the marker so
the result is reproducible. For either matrix stage, litgen generates each
requested target, emits identical directives as shared CHECK lines, and keeps
same-architecture directives under the GOARCH prefix. Only remaining
differences use exact target prefixes.
// LITTEST: POST-ABI linux/amd64 linux/arm64
// NOTE: Assertions have been autogenerated by chore/litgen UTC_ARGS: --function=f32ToI32 --check-globals=noneCross-target IR generation does not require running target binaries. A fixture
that imports C, directly or through a dependency, is the exception: cgo also
needs a target C compiler, headers, and sysroot. Keep such fixtures on plain
// LITTEST unless the test environment supplies that complete cross-cgo
toolchain; their explicit target-prefixed assertions are then exercised by the
matching platform CI.
Example:
- cl/_testrt/litdemo/in.go is a minimal
_testrtcase that demonstrateslitgenoutput. - cl/_testlibc/setjmp/in.go demonstrates a handwritten default-stage cross-target matrix.
- cl/_testgo/postabi/in.go demonstrates a handwritten post-ABI check with shared assertions and target-specific prefixes.
- cl/_testdata/floatint/in.go demonstrates an automatically maintained post-ABI target matrix.