build_qbe.sh 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. #
  2. # Builds the Test2 compiler (SimpleMod2 scalar subset -> QBE backend)
  3. # and runs the end-to-end tests.
  4. # Requires GNU Modula-2 (gm2), the CR binary, qbe and cc.
  5. #
  6. # Usage: ./build_qbe.sh (from the Test2 directory)
  7. #
  8. # Pipeline per test: SimpleQ tests/<f>.mod -> gen_qbe/<F>.ssa
  9. # -> qbe -> cc -> ./<F> ; exit code must match the expectation below.
  10. # Test convention: a global VAR ExitCode : INTEGER selects the process
  11. # exit code; without it the program returns 0.
  12. #
  13. pass=0
  14. fail=0
  15. expect_run() {
  16. # $1 = test file (no dir), $2 = expected exit code
  17. name="$1"
  18. want="$2"
  19. mod="$(basename "$name" .mod)"
  20. # The backend names the .ssa after the MODULE name; the newest .ssa
  21. # is the one just produced (tests run sequentially, names unique).
  22. out=$(./SimpleQ "tests/$name" 2>&1)
  23. case "$out" in
  24. *"Parsed correctly"*) ;;
  25. *) echo "FAIL $name: SimpleQ rejected it: $out"; fail=$((fail+1)); return ;;
  26. esac
  27. ssa=$(ls -t gen_qbe/*.ssa 2>/dev/null | head -n 1)
  28. if [ -z "$ssa" ]; then
  29. echo "FAIL $name: no .ssa produced"; fail=$((fail+1)); return
  30. fi
  31. base=$(basename "$ssa" .ssa)
  32. if ! qbe -o "gen_qbe/$base.s" "$ssa" 2> "gen_qbe/$base.qbeerr"; then
  33. echo "FAIL $name: qbe rejected $ssa:"; cat "gen_qbe/$base.qbeerr"; fail=$((fail+1)); return
  34. fi
  35. if ! cc "gen_qbe/$base.s" -o "gen_qbe/$base" 2> "gen_qbe/$base.ccerr"; then
  36. echo "FAIL $name: cc failed:"; cat "gen_qbe/$base.ccerr"; fail=$((fail+1)); return
  37. fi
  38. "gen_qbe/$base" > /dev/null 2>&1
  39. got=$?
  40. if [ "$got" = "$want" ]; then
  41. echo "ok $name -> exit $got"
  42. pass=$((pass+1))
  43. else
  44. echo "FAIL $name: exit $got, expected $want"
  45. fail=$((fail+1))
  46. fi
  47. }
  48. expect_fail() {
  49. # $1 = test file, $2 = message text that must appear in the .LST
  50. # (listings show messages, not numeric codes)
  51. name="$1"
  52. want="$2"
  53. out=$(./SimpleQ "tests/$name" 2>&1)
  54. case "$out" in
  55. *"Incorrect source"*) ;;
  56. *) echo "FAIL $name: expected rejection, got: $out"; fail=$((fail+1)); return ;;
  57. esac
  58. lst="tests/$(basename "$name" .mod).LST"
  59. if grep -q "$want" "$lst" 2>/dev/null; then
  60. echo "ok $name rejected with $want"
  61. pass=$((pass+1))
  62. else
  63. echo "FAIL $name: $want not found in $lst"
  64. fail=$((fail+1))
  65. fi
  66. }
  67. echo "=== Regenerating SimpleQS / SimpleQP / SimpleQ from SimpleQ.atg ==="
  68. CRFRAMES="$(pwd)" ../CR -m -C SimpleQ.atg || exit 1
  69. echo "=== Deleting all o files ==="
  70. rm -f ./*.o
  71. echo "=== Compiling the needed modules ==="
  72. for m in FileIO SymTab QbeGen SimpleQS SimpleQP SimpleQ; do
  73. gm2 -fiso -c "$m.mod" || exit 1
  74. done
  75. echo "=== Phase 1: generating the module list ==="
  76. gm2 -fiso -fgen-module-list=modules.lst -o /dev/null \
  77. SimpleQS.o SimpleQP.o FileIO.o SymTab.o QbeGen.o SimpleQ.mod || exit 1
  78. echo "=== Phase 2: compiling main module and linking using the module list ==="
  79. gm2 -fiso -fuse-list=modules.lst -o SimpleQ \
  80. SimpleQS.o SimpleQP.o FileIO.o SymTab.o QbeGen.o SimpleQ.mod || exit 1
  81. echo "=== SimpleQ built ==="
  82. mkdir -p gen_qbe tests
  83. echo "=== Positive tests (compile + qbe + cc + run) ==="
  84. expect_run q_minimal.mod 0
  85. expect_run q_arith.mod 7
  86. expect_run q_const.mod 15
  87. expect_run q_bool.mod 42
  88. expect_run q_if.mod 20
  89. expect_run q_case.mod 103
  90. expect_run q_while.mod 55
  91. expect_run q_repeat.mod 55
  92. expect_run q_loop.mod 7
  93. expect_run q_for.mod 85
  94. expect_run q_real.mod 31
  95. expect_run q_char.mod 97
  96. expect_run q_enum.mod 1
  97. expect_run q_full.mod 74
  98. echo "=== Negative tests (must be rejected) ==="
  99. expect_fail q_bad_array.mod "qbe backend"
  100. expect_fail q_bad_with.mod "qbe backend"
  101. expect_fail q_bad_set.mod "qbe backend"
  102. expect_fail q_bad_exit.mod "qbe backend"
  103. expect_fail q_bad_const.mod "qbe backend"
  104. expect_fail q_bad_asn.mod "incompatible assignment"
  105. echo "=== $pass passed, $fail failed ==="
  106. test "$fail" = 0