boot2

Playing with the boostrap
git clone https://git.ryansepassi.com/git/boot2.git
Log | Files | Refs | README

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)"