diff options
| author | 2026-10-14 16:02:56 +0330 | |
|---|---|---|
| committer | 2026-10-14 16:02:56 +0330 | |
| commit | fb2679438835fc6bad2dd135887957d7642c8023 (patch) | |
| tree | 671398389c2b44af21f374e20b61afe5c8e4fb02 | |
| parent | merge line tables (diff) | |
| parent | make: keep the x86-64 jit by default (LLVM=1 opts in), record the llvm mode s... (diff) | |
merge: llvm auto-build (opt-in on x86-64), mode stamp
| -rw-r--r-- | Makefile | 50 | ||||
| -rw-r--r-- | README.md | 2 | ||||
| -rw-r--r-- | TODO.md | 13 |
3 files changed, 58 insertions, 7 deletions
@@ -13,6 +13,9 @@ # (src/tools/xref.sh): build/xref/report.txt and report.json; # make xref XREF_ARGS=--check compares with tests/xref.baseline # make genome build/core/genome.bin from src/, with the fixpoint check +# make LLVM=1 on x86_64, build zy with the llvm backend instead of the x86-64 jit +# make NOLLVM=1 on other hosts, leave out the llvm backend (in by default when a +# usable llvm-config is on PATH, or LLVM_CONFIG names one) # make build/bin/zyi the interpreter alone (zy has a jit on arm64 and on x86-64 linux) # make lsp build/bin/zclsp, the language server # make web build/web/: the page, its script and zc.wasm @@ -95,9 +98,50 @@ $(B)/core/genome.bin: $(ZC_DEPS) $(BIN)/zc0$(EXE) $(BIN)/mkgenome$(EXE) src/core cp $(B)/s1/genome.bin $@ @echo "fixpoint: $$(( $$(wc -c < $@) / 8 )) words, $@ updated" -# the vm core with the compiler genome inside: a jit on arm64 and x86-64 linux, else the interpreter -$(BIN)/zy$(EXE): src/core/core.c $(IO) $(B)/core/genome.bin $(CORE_H) | $(BIN) - $(CC) $(CFLAGS) -DJTYPE=int src/core/core.c $(IO) $(COREINC) -o $@ +# the llvm backend (-DZYLLVM) in zy. -DZYLLVM replaces the x86-64 jit, so on x86_64 hosts +# (uname -m) it is built only when LLVM=1 is given; on other hosts it is in whenever an llvm +# is found, and NOLLVM=1 leaves it out. the llvm is LLVM_CONFIG when given, else llvm-config, +# else llvm-config-19 on PATH; it is used only when llvm-c/Core.h exists, --libs is not +# empty and a tiny program links against it (llvm-config can exist without headers or libs). +# otherwise the build goes on without it and prints a one-line note. +HOST_ARCH := $(shell uname -m 2>/dev/null) +ifeq ($(HOST_ARCH),x86_64) + WANT_LLVM := $(if $(filter 1,$(LLVM)),1,) +else + WANT_LLVM := $(if $(filter 1,$(NOLLVM)),,1) +endif +ifeq ($(WANT_LLVM),1) + ifeq ($(origin LLVM_CONFIG),undefined) + LLVM_CONFIG := $(firstword $(shell command -v llvm-config llvm-config-19 2>/dev/null)) + endif + ifneq ($(LLVM_CONFIG),) + ifneq ($(wildcard $(shell $(LLVM_CONFIG) --includedir 2>/dev/null)/llvm-c/Core.h),) + llvm_try_libs := $(shell $(LLVM_CONFIG) --libs 2>/dev/null) + ifneq ($(strip $(llvm_try_libs)),) + llvm_try_cflags := $(shell $(LLVM_CONFIG) --cflags 2>/dev/null) + llvm_try_ldflags := $(shell $(LLVM_CONFIG) --ldflags 2>/dev/null) + llvm_link_ok := $(shell d=$$(mktemp -d) && printf '\043include <llvm-c/Core.h>\nint main(void){LLVMContextDispose(LLVMContextCreate());return 0;}\n' > $$d/t.c && $(CC) $(llvm_try_cflags) $$d/t.c -o $$d/t $(llvm_try_ldflags) $(llvm_try_libs) >/dev/null 2>&1 && echo yes; rm -rf $$d) + ifeq ($(llvm_link_ok),yes) + LLVM_CFLAGS := -DZYLLVM $(llvm_try_cflags) + LLVM_LIBS := $(llvm_try_ldflags) $(llvm_try_libs) + endif + endif + endif + endif + ifeq ($(LLVM_CFLAGS),) + $(info note: no usable llvm (llvm-config with headers, libs and a test link), building zy without the llvm backend) + endif +endif +# the mode zy was built in; rewritten only when it changes, so switching rebuilds zy +LLVM_MODE := $(if $(LLVM_CFLAGS),llvm,nollvm) +ifneq ($(MAKECMDGOALS),clean) + $(shell mkdir -p $(B); [ "$$(cat $(B)/llvm.mode 2>/dev/null)" = "$(LLVM_MODE)" ] || echo $(LLVM_MODE) > $(B)/llvm.mode) +endif + +# the vm core with the compiler genome inside: a jit on arm64 and x86-64 linux, else the +# interpreter; plus the llvm backend when found (above) +$(BIN)/zy$(EXE): src/core/core.c $(IO) $(B)/core/genome.bin $(CORE_H) $(B)/llvm.mode | $(BIN) + $(CC) $(CFLAGS) -DJTYPE=int $(LLVM_CFLAGS) src/core/core.c $(IO) $(COREINC) -o $@ $(LLVM_LIBS) # the interpreter alone, even on a host with a jit: make build/bin/zyi, to compare against zy $(BIN)/zyi$(EXE): src/core/core.c $(IO) $(B)/core/genome.bin $(CORE_H) | $(BIN) $(CC) $(CFLAGS) -DZYINTERP -DJTYPE=int src/core/core.c $(IO) $(COREINC) -o $@ @@ -72,7 +72,7 @@ windows needs clang or gcc and powershell for the tests. the batch file is the s ### native backends -on arm64, `src/core/core.c` uses its arm64 jit by default, and on x86-64 linux its x86-64 jit. other hosts use the interpreter. `-DZYINTERP` forces interpretation (`make build/bin/zyi` builds that core beside `zy`); `-DZYLLVM` enables the llvm backend when its headers and libraries are available. direct builds from the root are: +on arm64, `src/core/core.c` uses its arm64 jit by default, and on x86-64 linux its x86-64 jit. other hosts use the interpreter. `-DZYINTERP` forces interpretation (`make build/bin/zyi` builds that core beside `zy`); `-DZYLLVM` enables the llvm backend when its headers and libraries are available. on x86_64 hosts (`uname -m`) `make` keeps the x86-64 jit in `zy` and adds the llvm backend only with `make LLVM=1`, since `-DZYLLVM` replaces that jit; on other hosts `make` adds it whenever it finds a usable llvm, and `make NOLLVM=1` leaves it out. the llvm is `LLVM_CONFIG` if given, else `llvm-config`, else `llvm-config-19` on `PATH`, and it counts only when `llvm-c/Core.h` exists, `--libs` is not empty and a tiny test program links; otherwise the build prints a one-line note and goes on without it. the chosen mode is kept in `build/llvm.mode`, so switching rebuilds `zy` without `make clean`. direct builds from the root are: ```sh make genome @@ -241,9 +241,16 @@ the reasoning behind the open items survives the session. translation validation of each compile over proving the compiler whole. - native code: the hand-written jit exists for arm64 and (phase 1, no o3 regions or inlined enhancements yet) x86-64 linux; the llvm backend - (`-DZYLLVM`) is the portable native tier but the default build leaves it - out. cheap win: build the llvm core by default whenever `llvm-config` is - found. the x86-64 port of the hand-written jit is worth it for compile + (`-DZYLLVM`) is the portable native tier. `make` puts it in `zy` on + non-x86_64 hosts whenever a usable llvm is found (`NOLLVM=1` turns it off); + on x86_64 it stays out unless `LLVM=1`, because `-DZYLLVM` replaces the + x86-64 jit (owner's call: keep the jit as the x86-64 default). usable means + `llvm-config` or `llvm-config-19` with `llvm-c/Core.h`, non-empty `--libs` + and a tiny test link; otherwise a one-line note. `build/llvm.mode` (llvm or + nollvm, rewritten only on change) makes switching rebuild `zy` without a + clean. checked on x86_64 with llvm 19: plain make uses the jit (no llvm + regions on o3.zc) and reaches the fixpoint, `make LLVM=1` rebuilds zy with + 8 llvm regions, plain make switches back. the non-x86_64 path is untested. the x86-64 port of the hand-written jit is worth it for compile latency (microseconds per block against milliseconds for llvm), which matters for short programs and the language server. |
