run_compile_tests.sh 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #!/bin/bash
  2. # Build and run the direct compiler harness (tests/CompileTest.mod).
  3. #
  4. # Same two-phase ISO link recipe as tpshell: a single monolithic invocation
  5. # trips gm2's pass-3 rollup on a compiler-size program, so generate the module
  6. # list first (-fgen-module-list -> /dev/null, rc=1 is expected) and then link
  7. # with -fuse-list.
  8. set -u
  9. D=/home/eric/Projets/Projets-Modula2/MyWork/TP3-comp/shell
  10. GM2=/home/eric/bin/Modula2/Gm2/bin/gm2
  11. cd "$D" || exit 9
  12. FLAGS="-fiso"
  13. # build logs go beside the tree (TP3-comp/tmp), never in /tmp
  14. mkdir -p ../tmp
  15. # Is `compiletest` itself current? It links against the .o files, and `make`
  16. # only ever builds `tpshell` - so after an ordinary `make`, compiletest is
  17. # routinely OLDER than Compiler.o and still contains the previous compiler.
  18. # The check below used to look only at sources-versus-objects, which is blind
  19. # to exactly this: it saw "Compiler.mod is not newer than Compiler.o" and
  20. # skipped the rebuild, and the matrix then reported the previous compiler's
  21. # verdicts with total confidence. That is the worst kind of wrong, because a
  22. # real fix stays invisible and a test that should have gone red stays green.
  23. # It happened while bisecting the IF-handler bug, and it is the second time
  24. # this project has lost time to a stale harness.
  25. #
  26. # So compiletest is rebuilt whenever it is older than ANY input: the object
  27. # files it links, the sources those came from, and its own source.
  28. STALE=no
  29. for f in compiletest TextBuf.o Posix.o CompilerShared.o CompilerUtil.o CompilerSource.o CompilerSymbols.o CompilerLex.o CompilerExpr.o CompilerIO.o CompilerEmit.o Compiler.o Runtime.o \
  30. tests/CompileTest.mod TextBuf.mod Posix.c Posix.def \
  31. CompilerShared.mod CompilerUtil.mod CompilerSource.mod CompilerSymbols.mod CompilerLex.mod CompilerExpr.mod CompilerIO.mod CompilerEmit.mod Compiler.mod Runtime.mod Linker.mod; do
  32. if [ -e "$f" ] && [ compiletest -ot "$f" ]; then STALE=yes; break; fi
  33. done
  34. if [ "$STALE" = yes ]; then
  35. echo "compiletest is older than its inputs - it would report the OLD compiler"
  36. rm -f compiletest
  37. fi
  38. if [ ! -f TextBuf.o ] || [ ! -f CompilerShared.o ] || [ ! -f CompilerUtil.o ] || [ ! -f CompilerSource.o ] || [ ! -f CompilerSymbols.o ] || [ ! -f CompilerLex.o ] || [ ! -f CompilerExpr.o ] || [ ! -f CompilerIO.o ] || [ ! -f CompilerEmit.o ] \
  39. || [ ! -f Compiler.o ] || [ ! -f Posix.o ] || [ ! -f Runtime.o ] \
  40. || [ TextBuf.mod -nt TextBuf.o ] || [ CompilerShared.mod -nt CompilerShared.o ] \
  41. || [ CompilerShared.def -nt CompilerShared.o ] \
  42. || [ CompilerUtil.mod -nt CompilerUtil.o ] || [ CompilerUtil.def -nt CompilerUtil.o ] \
  43. || [ CompilerSource.mod -nt CompilerSource.o ] || [ CompilerSource.def -nt CompilerSource.o ] \
  44. || [ CompilerSymbols.mod -nt CompilerSymbols.o ] || [ CompilerSymbols.def -nt CompilerSymbols.o ] \
  45. || [ CompilerLex.mod -nt CompilerLex.o ] || [ CompilerLex.def -nt CompilerLex.o ] \
  46. || [ CompilerExpr.mod -nt CompilerExpr.o ] || [ CompilerExpr.def -nt CompilerExpr.o ] \
  47. || [ CompilerIO.mod -nt CompilerIO.o ] || [ CompilerIO.def -nt CompilerIO.o ] \
  48. || [ CompilerEmit.mod -nt CompilerEmit.o ] || [ CompilerEmit.def -nt CompilerEmit.o ] \
  49. || [ Compiler.mod -nt Compiler.o ] \
  50. || [ Runtime.mod -nt Runtime.o ] || [ Runtime.def -nt Runtime.o ] \
  51. || [ Compiler.def -nt Compiler.o ] \
  52. || [ CompilerShared.def -nt Compiler.o ] || [ CompilerUtil.def -nt Compiler.o ] || [ CompilerSource.def -nt Compiler.o ] || [ CompilerSymbols.def -nt Compiler.o ] || [ CompilerLex.def -nt Compiler.o ] || [ CompilerExpr.def -nt Compiler.o ] || [ CompilerIO.def -nt Compiler.o ] || [ CompilerEmit.def -nt Compiler.o ] \
  53. || [ Posix.c -nt Posix.o ] || [ Posix.def -nt Posix.o ]; then
  54. echo "building support modules (source newer than object)..."
  55. # Runtime is listed because Compiler now links against it: the blob is
  56. # copied into the code buffer and the TU_* offsets come from it. A
  57. # `make clean` (or a fresh checkout) removes every .o, so the C module has
  58. # to be built here too - it used to be assumed present, which made the
  59. # script fail with "cannot find Posix.o" after any clean.
  60. if [ ! -f Posix.o ] || [ Posix.c -nt Posix.o ] || [ Posix.def -nt Posix.o ]; then
  61. cc -c Posix.c >../tmp/ct_c_Posix 2>&1 \
  62. || { echo "COMPILE_FAIL Posix"; grep -m5 "error:" ../tmp/ct_c_Posix; exit 1; }
  63. fi
  64. for m in TextBuf CompilerShared CompilerUtil CompilerSource CompilerSymbols CompilerLex CompilerExpr CompilerIO CompilerEmit Compiler Runtime; do
  65. $GM2 $FLAGS -c $m.mod >../tmp/ct_c_$m 2>&1
  66. if [ $? -ne 0 ]; then
  67. echo "COMPILE_FAIL $m"
  68. grep -m5 -E "error:|Please submit" ../tmp/ct_c_$m
  69. exit 1
  70. fi
  71. done
  72. echo " support modules rebuilt"
  73. fi
  74. rm -f tests/ct.lst compiletest
  75. $GM2 $FLAGS -fgen-module-list=tests/ct.lst -o /dev/null \
  76. tests/CompileTest.mod TextBuf.o Posix.o CompilerShared.o CompilerUtil.o CompilerSource.o CompilerSymbols.o CompilerLex.o CompilerExpr.o CompilerIO.o CompilerEmit.o Compiler.o Runtime.o >../tmp/ct_p1 2>&1
  77. p1=$?
  78. $GM2 $FLAGS -fuse-list=tests/ct.lst -o compiletest \
  79. tests/CompileTest.mod TextBuf.o Posix.o CompilerShared.o CompilerUtil.o CompilerSource.o CompilerSymbols.o CompilerLex.o CompilerExpr.o CompilerIO.o CompilerEmit.o Compiler.o Runtime.o >../tmp/ct_p2 2>&1
  80. p2=$?
  81. if [ $p2 -ne 0 ]; then
  82. echo "LINK_FAIL p1_rc=$p1 p2_rc=$p2"
  83. grep -E "error:|undefined" ../tmp/ct_p2 | head -10
  84. exit 1
  85. fi
  86. echo "compiletest built (p1_rc=$p1, phase 1 rc=1 is the expected rollup)"
  87. # --build-only stops right after the build. The CALC ladder
  88. # (tests/calc_ladder.sh) runs this same compiler on a staged copy of CALC.PAS,
  89. # and it must not be the second recipe that decides whether compiletest is
  90. # current: that is exactly how the stale-harness bug above happened, and two
  91. # staleness tests that drift are one test wearing two hats. So the ladder
  92. # asks for the build here and does its own running afterwards.
  93. if [ "${1:-}" = "--build-only" ]; then
  94. exit 0
  95. fi
  96. FX=${1:-tests/fixtures}
  97. # ---- assert against tests/fixtures/expected.tsv ---------------------------
  98. # Previously this script only printed a verdict, so "17 of 23" was a number a
  99. # human counted by hand and a wrong error POSITION was invisible. Both the
  100. # verdict and the numbers are compared now, and the exit status is meaningful.
  101. EXP="$FX/expected.tsv"
  102. if [ ! -f "$EXP" ]; then
  103. echo "no expectations file $EXP - printing only"
  104. ls "$FX"/*.pas 2>/dev/null | ./compiletest
  105. exit 0
  106. fi
  107. RAW=$(mktemp) || exit 9
  108. ls "$FX"/*.pas 2>/dev/null | ./compiletest > "$RAW"
  109. # expected row for a fixture basename, normalised to single spaces
  110. # (only rows that actually carry a verdict count, so the wrapped comment
  111. # lines in expected.tsv can never be mistaken for data)
  112. expect_for() {
  113. awk -F'\t' -v n="$1" '
  114. ($2 == "OK" || $2 == "ERR") && $1 == n {
  115. out = ""
  116. for (i = 2; i <= NF; i++)
  117. out = (out == "") ? $i : out " " $i
  118. print out
  119. exit
  120. }
  121. ' "$EXP"
  122. }
  123. pass=0; fail=0
  124. while IFS= read -r base; do
  125. actual=$(grep -F "$base" "$RAW" \
  126. | head -1 \
  127. | tr -d '\r' \
  128. | sed -E 's/^[^ ]+[[:space:]]+//' \
  129. | tr -s ' ' \
  130. | sed -E 's/^OK code=([0-9]+) data=([0-9]+)$/OK \1 \2/;
  131. s/^ERROR ([0-9]+) at pos ([0-9]+)$/ERR \1 \2/')
  132. want=$(expect_for "$base" | tr -s ' ')
  133. if [ -z "$want" ]; then
  134. printf ' %-24s NO_EXPECTATION got: %s\n' "$base" "$actual"
  135. fail=$((fail + 1))
  136. elif [ "$actual" = "$want" ]; then
  137. printf ' %-24s PASS %s\n' "$base" "$actual"
  138. pass=$((pass + 1))
  139. else
  140. printf ' %-24s FAIL\n expected: %s\n actual: %s\n' \
  141. "$base" "$want" "$actual"
  142. fail=$((fail + 1))
  143. fi
  144. done <<EOF
  145. $(ls "$FX"/*.pas 2>/dev/null | xargs -n1 basename | sed 's/\.pas$//')
  146. EOF
  147. echo "----------------------------------------------------------------"
  148. echo "compile matrix: $pass passed, $fail failed (of $((pass + fail)))"
  149. rm -f "$RAW"
  150. [ "$fail" -eq 0 ] || exit 1