aboutsummaryrefslogtreecommitdiff
path: root/src/tools/automap.sh
diff options
context:
space:
mode:
authorGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
committerGravatar Moon Flower <moonflower@elhenney.local> 2026-10-12 08:46:23 +0330
commitecc350ca5c2eb50be8309c5f14f8bf0d87db9a02 (patch)
tree70e0af76a1b13affff7c6cc8aac7b3e6ef960478 /src/tools/automap.sh
a
Diffstat (limited to 'src/tools/automap.sh')
-rwxr-xr-xsrc/tools/automap.sh58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/tools/automap.sh b/src/tools/automap.sh
new file mode 100755
index 0000000..8cefe6a
--- /dev/null
+++ b/src/tools/automap.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+# sizes a memory map to the program it holds, before the program is compiled for it.
+# src/tools/automap.sh PRESET OUTDIR FILE...
+# PRESET is run, small, default or lsp. DOCS=1 makes the genome with its doc comments. FILE... are appended after the map's own
+# rt.zc (and compiler.zc, for the presets that carry the compiler). the result
+# is OUTDIR/memmap.h and OUTDIR/genome.h, and they agree with each other.
+#
+# a genome's length doesn't depend on where it lives (every address is a one
+# word literal), so two passes are enough: compile once on the preset's map
+# to learn the length, then lay the map out again with a genome slot of exactly
+# that length, rounded up to 4096 words, and let a fixed-size map grow if it has
+# to. the second compile must come out the same length, and that is checked.
+# zc0 reads the map at build time, so it is built again for each layout.
+# GENMAP can name a genmap that is already built.
+set -e
+cd "$(dirname "$0")/../.."
+P=$1; O=$2; shift 2
+[ -n "$P" ] && [ -n "$O" ] || { echo "usage: src/tools/automap.sh run|small|default|lsp OUTDIR FILE..." >&2; exit 2; }
+CC=${CC:-gcc}
+mkdir -p "$O"
+ZC0=$O/.zc0
+if [ -z "$GENMAP" ]; then
+ GENMAP=$O/.genmap
+ if [ ! -x "$GENMAP" ] || [ src/tools/genmap.c -nt "$GENMAP" ]; then $CC -O2 -w -fwrapv src/tools/genmap.c -o "$GENMAP"; fi
+fi
+lay() { # $1 = genome slot, or empty for the preset's own
+ rm -rf "$O/map"
+ "$GENMAP" --preset "$P" --grow ${1:+--genome $1} -o "$O/map" >/dev/null 2>&1
+ $CC -O1 -w -fwrapv src/tools/zc0.c -I"$O/map" -Isrc/core -o "$ZC0"
+}
+build() {
+ if [ -f "$O/map/compiler.zc" ]; then cat "$O/map/rt.zc" "$O/map/compiler.zc" "$@"; else cat "$O/map/rt.zc" "$@"; fi | "$ZC0"
+}
+# with DOCS=1 the genome is made again with zc0 built for docs (ZC0DOCS), so the
+# image carries the doc comments of the sources and the program can answer
+# docofs(). the image is the same code either way; the docs are stored after it.
+docs() {
+ $CC -O1 -w -fwrapv -DZC0DOCS src/tools/zc0.c -I"$O/map" -Isrc/core -o "$O/.zc0docs"
+ if [ -f "$O/map/compiler.zc" ]; then cat "$O/map/rt.zc" "$O/map/compiler.zc" "$@"; else cat "$O/map/rt.zc" "$@"; fi | "$O/.zc0docs"
+}
+len() { grep -m1 '#define GLEN' "$1" | awk '{print $3}'; }
+lay ""
+build "$@" > "$O/genome.h"
+glen=$(len "$O/genome.h")
+slot=$(( (glen + 4095) / 4096 * 4096 ))
+lay "$slot"
+build "$@" > "$O/genome.h"
+if [ -n "$DOCS" ]; then
+ lay $((slot + 65536)) # room for the image with its docs while it is being made
+ docs "$@" > "$O/genome.h"
+ glen=$(len "$O/genome.h")
+ slot=$(( (glen + 4095) / 4096 * 4096 ))
+ lay "$slot"
+ docs "$@" > "$O/genome.h"
+fi
+[ "$(len "$O/genome.h")" = "$glen" ] || { echo "automap: the genome changed length with the map" >&2; exit 1; }
+cp "$O/map/memmap.h" "$O/map/map.txt" "$O/"
+echo "automap $P: genome $glen words in a slot of $slot, $(grep -m1 '^MW' "$O/map/map.txt")"