boot4.sh (5854B)
1 #!/bin/sh 2 ## boot4.sh — self-host tcc rebuild stages on top of boot3's tcc0. 3 ## 4 ## boot3 produced tcc0 (cc.scm-built bootstrap). boot4 runs the rest of 5 ## the three-binary chain: tcc0 → tcc1 → tcc2. The bootstrap fixed-point 6 ## check is `tcc1 == tcc2`: tcc0 ≠ tcc1 because cc.scm and tcc emit 7 ## different — but both correct — code from the same source, but once tcc 8 ## is compiling itself the output is byte-identical. Stages C and D use 9 ## the same archive-based link line, so tcc0(tcc.c) and tcc1(tcc.c) 10 ## differ only where tcc0's runtime behavior differs from tcc1's — so the 11 ## check doubles as a proof that cc.scm compiled tcc.c faithfully. 12 ## 13 ## tcc0 = tcc-source compiled by cc.scm ← boot3 14 ## tcc1 = tcc-source compiled by tcc0 ← produced here 15 ## tcc2 = tcc-source compiled by tcc1 ← produced here 16 ## 17 ## ─── Inputs (sources, from canonical tree) ─────────────────────────── 18 ## build/$ARCH/src/src/tcc/libc/$ARCH/{start.S, sys_stubs.S} 19 ## build/$ARCH/src/src/tcc/cc/mem.c 20 ## build/$ARCH/src/src/tcc/tcc-0.9.26-1147-gee75a10c/lib/<arch-specific> 21 ## build/$ARCH/src/src/tcc/tcc.flat.c 22 ## build/$ARCH/src/src/libc/libc.flat.c 23 ## build/$ARCH/src/src/test-fixtures/boot-hello.c 24 ## 25 ## ─── Inputs (binaries from prior stages) ────────────────────────────── 26 ## build/$ARCH/$DRIVER/boot3/tcc0 27 ## build/$ARCH/$DRIVER/boot2/{catm, scheme1} 28 ## 29 ## ─── Tools ──────────────────────────────────────────────────────────── 30 ## scheme1 evaluates the prep-time run.scm at 31 ## build/$ARCH/src/run/boot4.scm (generated by 32 ## bootprep/boot4-gen-runscm.sh) against the flat staging root. Every arch has CONFIG_TCC_ASM and 33 ## assembles .S inputs (start.S, sys_stubs.S) directly inside the 34 ## container; no host asm step. The aarch64 assembler is the phase-1 35 ## arm64-asm.c that flatten patches into tcc-0.9.26 (see 36 ## bootprep/stage1-flatten.sh, around the arm64-asm patch block). 37 ## 38 ## ─── Outputs ────────────────────────────────────────────────────────── 39 ## build/$ARCH/$DRIVER/boot4/{tcc1, tcc2} 40 ## tcc1 and tcc2 are byte-identical (asserted 41 ## below) — that equality is the fixed-point. 42 ## build/$ARCH/$DRIVER/boot4/crt1.o 43 ## tcc1-built startup object, kept outside 44 ## libc.a because it must lead link lines. 45 ## build/$ARCH/$DRIVER/boot4/libc.a 46 ## tcc1-built archive of sys_stubs.o + mem.o 47 ## + libc.o 48 ## build/$ARCH/$DRIVER/boot4/libtcc1.a 49 ## tcc1-built tcc compiler helper archive 50 ## build/$ARCH/$DRIVER/boot4/hello — mes-libc-linked smoke binary 51 ## 52 ## Usage: boot/boot4.sh <arch> 53 ## <arch> ∈ {aarch64, amd64, riscv64} for either DRIVER (default podman). 54 55 set -eu 56 57 . boot/lib-arch.sh 58 bootlib_init boot4 "${1:-}" 59 driver_init empty 60 require_src 61 62 case "$ARCH" in 63 aarch64) LIBTCC1_C_SRCS="lib-arm64.c"; LIBTCC1_ASM_SRCS="" ;; 64 amd64) LIBTCC1_C_SRCS="libtcc1.c va_list.c"; LIBTCC1_ASM_SRCS="alloca86_64.S alloca86_64-bt.S" ;; 65 riscv64) LIBTCC1_C_SRCS="lib-arm64.c"; LIBTCC1_ASM_SRCS="" ;; 66 esac 67 68 BOOT2=build/$ARCH/$DRIVER/boot2 69 BOOT3=build/$ARCH/$DRIVER/boot3 70 SRC=build/$ARCH/src 71 72 TCC_PKG=tcc-0.9.26-1147-gee75a10c 73 TCC_LIB_REL=tcc/$TCC_PKG/lib 74 75 # ── prerequisites ───────────────────────────────────────────────────── 76 require_prev "$BOOT3" tcc0 77 require_prev "$BOOT2" catm scheme1 78 for f in $LIBTCC1_C_SRCS $LIBTCC1_ASM_SRCS; do 79 require_file "$SRC/src/$TCC_LIB_REL/$f" 80 done 81 82 # ── stage inputs and run scheme1 + boot4 run.scm under $DRIVER ──────── 83 . boot/lib-runscm.sh 84 runscm_init "$STAGE" "$OUT" 85 runscm_runscm "$SRC/run/boot4.scm" 86 87 runscm_scheme1 "$BOOT2/scheme1" 88 runscm_prelude "$SRC/src/scheme1/prelude.scm" 89 90 runscm_input tcc0 "$BOOT3/tcc0" 91 runscm_input catm "$BOOT2/catm" 92 93 runscm_input_from_src "tcc/libc/$ARCH/start.S" 94 runscm_input_from_src "tcc/libc/$ARCH/sys_stubs.S" 95 runscm_input_from_src tcc/cc/mem.c 96 for f in $LIBTCC1_C_SRCS $LIBTCC1_ASM_SRCS; do 97 runscm_input_from_src "$TCC_LIB_REL/$f" 98 done 99 100 runscm_input_from_src tcc/tcc.flat.c 101 runscm_input_from_src libc/libc.flat.c 102 runscm_input_from_src test-fixtures/boot-hello.c hello.c 103 104 runscm_export tcc1 tcc2 s2-crt1.o s2-libc.a s2-libtcc1.a hello 105 runscm_run "${BOOT4_TIMEOUT:-5400}" 106 107 # ── fixed-point check (host-side) ───────────────────────────────────── 108 if ! cmp -s "$OUT/tcc1" "$OUT/tcc2"; then 109 s1=$(wc -c <"$OUT/tcc1") 110 s2=$(wc -c <"$OUT/tcc2") 111 echo "[$BOOT_TAG] FIXED-POINT FAIL: tcc1 ($s1) != tcc2 ($s2)" >&2 112 exit 1 113 fi 114 115 # ── normalize output names (drop s2- prefix) ────────────────────────── 116 # tcc1 / tcc2 are kept on disk: the test path (tcc-cc / tcc-libc suites) 117 # uses them as stage-2 / stage-3 self-built tcc binaries. 118 mv "$OUT/s2-crt1.o" "$OUT/crt1.o" 119 mv "$OUT/s2-libc.a" "$OUT/libc.a" 120 mv "$OUT/s2-libtcc1.a" "$OUT/libtcc1.a" 121 chmod 0700 "$OUT/tcc1" "$OUT/tcc2" "$OUT/hello" 122 123 echo "[$BOOT_TAG] sizes: libtcc1.a=$(wc -c <"$OUT/libtcc1.a") libc.a=$(wc -c <"$OUT/libc.a") hello=$(wc -c <"$OUT/hello")" 124 echo "[$BOOT_TAG] OK -> $OUT/{tcc2, crt1.o, libc.a, libtcc1.a, hello} (fixed point: tcc1 == tcc2)"