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