boot2

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

boot4-gen-runscm.sh (6268B)


      1 #!/bin/sh
      2 ## boot4-gen-runscm.sh — emit run.scm driving boot4's tcc0→tcc1→tcc2
      3 ## chain inside the seed kernel. Mirrors boot/boot4.sh's per-stage shell
      4 ## emission; per-arch values resolved on the host so the .scm body is
      5 ## straight-line (run …) calls.
      6 ##
      7 ## Reads use in/<name>; writes (intermediates and exports) use out/<name>.
      8 ##
      9 ## Usage: bootprep/boot4-gen-runscm.sh <arch>
     10 ##   Writes build/<arch>/src/run/boot4.scm.
     11 
     12 set -eu
     13 [ "$#" -eq 1 ] || { echo "usage: $0 <arch>" >&2; exit 2; }
     14 ARCH=$1
     15 OUT=build/$ARCH/src/run/boot4.scm
     16 mkdir -p "$(dirname "$OUT")"
     17 
     18 case "$ARCH" in
     19     aarch64) LIB_HELPER_SRC=lib-arm64.c; LIB_HELPER_OBJ=lib-arm64.o
     20              LIB_HELPER_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_ARM64=1" "-D" "TCC_TARGET_ARM=1"'
     21              LIBTCC1_C_SRCS="lib-arm64.c"
     22              LIBTCC1_C_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_ARM64=1" "-D" "TCC_TARGET_ARM=1"'
     23              LIBTCC1_ASM_SRCS="" ;;
     24     amd64)   LIB_HELPER_SRC=va_list.c; LIB_HELPER_OBJ=va_list.o
     25              LIB_HELPER_DEFS='"-D" "TCC_TARGET_X86_64=1"'
     26              LIBTCC1_C_SRCS="libtcc1.c va_list.c"
     27              LIBTCC1_C_DEFS='"-D" "TCC_TARGET_X86_64=1"'
     28              LIBTCC1_ASM_SRCS="alloca86_64.S alloca86_64-bt.S" ;;
     29     riscv64) LIB_HELPER_SRC=lib-arm64.c; LIB_HELPER_OBJ=lib-arm64.o
     30              LIB_HELPER_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_RISCV64=1"'
     31              LIBTCC1_C_SRCS="lib-arm64.c"
     32              LIBTCC1_C_DEFS='"-D" "HAVE_CONFIG_H=1" "-D" "TCC_TARGET_RISCV64=1"'
     33              LIBTCC1_ASM_SRCS="" ;;
     34     *)       echo "boot4-gen: unknown arch $ARCH" >&2; exit 2 ;;
     35 esac
     36 
     37 # Per-arch link base for user binaries.  tcc 0.9.26's riscv64-link.c
     38 # defaults to ELF_START_ADDR=0x10000, which lives below the seed
     39 # kernel's USER_VA_LO (0x200000).  amd64 (0x400000) and aarch64
     40 # (0x400000) defaults already sit inside the user window, so we leave
     41 # them alone.  Everywhere else in the chain (M0/hex2pp -B, boot6
     42 # -Wl,-Ttext) we link riscv64 user binaries at 0x600000; do the same
     43 # here so tcc-built outputs are loadable inside the seed kernel.
     44 case "$ARCH" in
     45     riscv64) LINK_TTEXT='"-Wl,-Ttext=0x600000"' ;;
     46     *)       LINK_TTEXT= ;;
     47 esac
     48 
     49 # emit_helpers — cc reads .S/.c sources from in/, writes .o to out/.
     50 # cc_path is the cwd-relative path to the spawned compiler binary (in/tcc0
     51 # for round B; out/tcc1, out/tcc2 in later rounds).
     52 emit_helpers() {
     53     cc_path=$1; tag=$2
     54     cat <<EOF
     55 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/start.o"     "in/start.S")        "$tag start.o")
     56 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/sys_stubs.o" "in/sys_stubs.S")    "$tag sys_stubs.o")
     57 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/mem.o"       "in/mem.c")          "$tag mem.o")
     58 (must (run "$cc_path" "-nostdlib" "-c" "-o" "out/libc.o"      "in/libc.flat.c")    "$tag libc.o")
     59 (must (run "$cc_path" "-nostdlib" $LIB_HELPER_DEFS "-c" "-o" "out/$LIB_HELPER_OBJ" "in/$LIB_HELPER_SRC") "$tag $LIB_HELPER_OBJ")
     60 EOF
     61 }
     62 
     63 # emit_archive — uses prefix to namespace output object names per stage.
     64 # pfx="s1-"/"s2-" for stage C/D. The .o objects archived into libtcc1.a
     65 # keep their bare basenames (lib-arm64.o, …) — tcc -ar stores basenames
     66 # only, so this matches podman's archive members exactly. They overwrite
     67 # the stage's helper-named .o files; nothing post-archive in the same
     68 # stage reads them as standalone .o.
     69 emit_archive() {
     70     cc_path=$1; tag=$2; pfx=$3
     71     echo "(must (run \"in/catm\" \"out/${pfx}crt1.o\" \"out/start.o\") \"copy crt1.o $pfx\")"
     72     echo "(must (run \"$cc_path\" \"-ar\" \"rcs\" \"out/${pfx}libc.a\" \"out/sys_stubs.o\" \"out/mem.o\" \"out/libc.o\") \"$tag ${pfx}libc.a\")"
     73     libtcc1_objs=""
     74     for src in $LIBTCC1_C_SRCS; do
     75         obj=${src%.c}.o
     76         echo "(must (run \"$cc_path\" \"-nostdlib\" $LIBTCC1_C_DEFS \"-c\" \"-o\" \"out/${obj}\" \"in/$src\") \"$tag lt ${obj}\")"
     77         libtcc1_objs="$libtcc1_objs \"out/${obj}\""
     78     done
     79     for src in $LIBTCC1_ASM_SRCS; do
     80         obj=${src%.S}.o
     81         echo "(must (run \"$cc_path\" \"-nostdlib\" \"-c\" \"-o\" \"out/${obj}\" \"in/$src\") \"$tag lt ${obj}\")"
     82         libtcc1_objs="$libtcc1_objs \"out/${obj}\""
     83     done
     84     echo "(must (run \"$cc_path\" \"-ar\" \"rcs\" \"out/${pfx}libtcc1.a\"$libtcc1_objs) \"$tag ${pfx}libtcc1.a\")"
     85 }
     86 
     87 emit_link_tcc() {
     88     cc_path=$1; tag=$2; pfx=$3; out=$4
     89     echo "(must (run \"$cc_path\" \"-nostdlib\" $LINK_TTEXT \"out/${pfx}crt1.o\" \"in/tcc.flat.c\" \"out/${pfx}libc.a\" \"out/${pfx}libtcc1.a\" \"out/${pfx}libc.a\" \"-o\" \"out/$out\") \"$tag -> $out\")"
     90 }
     91 
     92 {
     93 cat <<'PROLOGUE'
     94 ;; boot4 run.scm — drive tcc0 -> tcc1 -> tcc2 inside seed kernel.
     95 ;; Generated by bootprep/boot4-gen-runscm.sh; mirrors boot/boot4.sh's
     96 ;; podman path stage-for-stage. Reads use in/; writes (intermediates and
     97 ;; exports) use out/. tcc0 is staged as in/tcc0; tcc1/tcc2 are produced
     98 ;; and exported under out/.
     99 ;;
    100 ;; Stages C and D use the SAME archive-based link line, so tcc0's output
    101 ;; (tcc1) is directly comparable to tcc1's output (tcc2): once tcc0 is a
    102 ;; faithful compilation of tcc.c, tcc1 == tcc2 is the fixed point.
    103 
    104 (define (must r tag)
    105   (if (and (car r) (= 0 (cdr r)))
    106       r
    107       (begin
    108         (write-string stderr "boot4: step failed: ")
    109         (write-string stderr tag)
    110         (write-string stderr "\n")
    111         (exit 1))))
    112 
    113 (write-string stdout "boot4: stage C (tcc0 -> tcc1)\n")
    114 PROLOGUE
    115 
    116 # Stage C: tcc0 builds helpers + archive, links tcc1 — same link line as
    117 # stage D so tcc1 is directly comparable to tcc2.
    118 emit_helpers in/tcc0 tcc0
    119 emit_archive in/tcc0 tcc0 "s1-"
    120 emit_link_tcc in/tcc0 tcc0 "s1-" tcc1
    121 
    122 cat <<EOF
    123 
    124 (write-string stdout "boot4: stage D (tcc1 -> tcc2)\n")
    125 EOF
    126 
    127 # Stage D: tcc1 rebuilds helpers + archive, links tcc2. tcc1 == tcc2 is
    128 # the bootstrap fixed point (asserted host-side in boot4.sh). The s2-
    129 # archives + crt1.o built here are boot4's exported deliverables.
    130 emit_helpers out/tcc1 tcc1
    131 emit_archive out/tcc1 tcc1 "s2-"
    132 emit_link_tcc out/tcc1 tcc1 "s2-" tcc2
    133 
    134 cat <<EOF
    135 
    136 (write-string stdout "boot4: linking hello\n")
    137 (must (run "out/tcc1" "-nostdlib" $LINK_TTEXT "out/s2-crt1.o" "in/hello.c" "out/s2-libc.a" "out/s2-libtcc1.a" "out/s2-libc.a" "-o" "out/hello") "tcc1 -> hello")
    138 (write-string stdout "boot4: ALL-OK\n")
    139 (exit 0)
    140 EOF
    141 } > "$OUT"