kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

run.sh (5598B)


      1 #!/usr/bin/env bash
      2 # Behavioral check for the O1 tiny-function inliner.
      3 #
      4 # Compiles a toy program where __user_main calls the tiny helper add1(x)=x+1,
      5 # and asserts that at -O1 the `bl add1` is gone from __user_main (the helper
      6 # was inlined). Also confirms the program still computes the right value via
      7 # the in-process JIT.
      8 set -euo pipefail
      9 
     10 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     11 KIT="${KIT:-$ROOT/build/kit}"
     12 SRC="$ROOT/test/toy/cases/135_inline_cleanup_quality.toy"
     13 WORK="$ROOT/build/test/opt/inline"
     14 mkdir -p "$WORK"
     15 
     16 "$KIT" cc -target aarch64-linux-gnu -O1 -c "$SRC" \
     17   -o "$WORK/x.o" > "$WORK/cc.out" 2>&1
     18 "$KIT" objdump -d "$WORK/x.o" > "$WORK/dis.out" 2>&1
     19 
     20 # Slice out the __user_main function body.
     21 awk '
     22   /^[0-9a-f]+ <__user_main>:/ { in_fn = 1; next }
     23   /^[0-9a-f]+ </ { in_fn = 0 }
     24   in_fn { print }
     25 ' "$WORK/dis.out" > "$WORK/user_main.dis"
     26 
     27 if grep -Eq '\bbl\b.*add1' "$WORK/user_main.dis"; then
     28   printf 'tiny-inline check FAILED: add1 was not inlined into __user_main:\n' >&2
     29   sed 's/^/  | /' "$WORK/user_main.dis" >&2
     30   exit 1
     31 fi
     32 
     33 # The inlined body must actually be present (an add of the constant), i.e. the
     34 # function is more than just a tail jump.
     35 if ! grep -Eq '\badd\b' "$WORK/user_main.dis"; then
     36   printf 'tiny-inline check FAILED: inlined add1 body missing from __user_main:\n' >&2
     37   sed 's/^/  | /' "$WORK/user_main.dis" >&2
     38   exit 1
     39 fi
     40 
     41 # Runtime correctness through the in-process JIT: main returns add1(41) == 42.
     42 for opt in -O0 -O1; do
     43   if "$KIT" run "$opt" -e main "$SRC" > /dev/null 2>&1; then
     44     rc=0
     45   else
     46     rc=$?
     47   fi
     48   if [ "$rc" -ne 42 ]; then
     49     printf 'tiny-inline runtime check FAILED at %s: exit %d (want 42)\n' \
     50       "$opt" "$rc" >&2
     51     exit 1
     52   fi
     53 done
     54 
     55 cat > "$WORK/dead_jt.c" <<'EOF'
     56 #include <kit/cg.h>
     57 int p(void) { return 0; }
     58 EOF
     59 "$KIT" cc -O1 -I "$ROOT/include" -c "$WORK/dead_jt.c" \
     60   -o "$WORK/dead_jt.o" > "$WORK/dead_jt.cc.out" 2>&1
     61 "$KIT" nm "$WORK/dead_jt.o" > "$WORK/dead_jt.nm" 2>&1
     62 if grep -q '\.Lkit_jt' "$WORK/dead_jt.nm"; then
     63   printf 'O1 deferred jump-table check FAILED: dead inline leaked .Lkit_jt:\n' >&2
     64   sed 's/^/  | /' "$WORK/dead_jt.nm" >&2
     65   exit 1
     66 fi
     67 
     68 cat > "$WORK/live_jt.c" <<'EOF'
     69 int p(int x) {
     70   switch (x) {
     71     case 0: return 3;
     72     case 1: return 4;
     73     case 2: return 5;
     74     case 3: return 6;
     75     case 4: return 7;
     76     case 5: return 8;
     77     case 6: return 9;
     78     case 7: return 10;
     79     default: return 11;
     80   }
     81 }
     82 EOF
     83 "$KIT" cc -O1 -c "$WORK/live_jt.c" \
     84   -o "$WORK/live_jt.o" > "$WORK/live_jt.cc.out" 2>&1
     85 "$KIT" nm "$WORK/live_jt.o" > "$WORK/live_jt.nm" 2>&1
     86 if grep -Eq '[[:space:]][uU][[:space:]]+\.Lkit_jt' "$WORK/live_jt.nm" ||
     87    ! grep -Eq '[[:space:]][dDrR][[:space:]]+\.Lkit_jt' "$WORK/live_jt.nm"; then
     88   printf 'O1 deferred jump-table check FAILED: live switch table not defined:\n' >&2
     89   sed 's/^/  | /' "$WORK/live_jt.nm" >&2
     90   exit 1
     91 fi
     92 
     93 cat > "$WORK/dead_ro.c" <<'EOF'
     94 static inline const char *q(void) { return "abc"; }
     95 int p(void) { return 0; }
     96 EOF
     97 "$KIT" cc -O1 -c "$WORK/dead_ro.c" \
     98   -o "$WORK/dead_ro.o" > "$WORK/dead_ro.cc.out" 2>&1
     99 "$KIT" nm "$WORK/dead_ro.o" > "$WORK/dead_ro.nm" 2>&1
    100 if grep -q '\.Lkit_ro' "$WORK/dead_ro.nm"; then
    101   printf 'O1 deferred const-data check FAILED: dead inline leaked .Lkit_ro:\n' >&2
    102   sed 's/^/  | /' "$WORK/dead_ro.nm" >&2
    103   exit 1
    104 fi
    105 
    106 cat > "$WORK/live_ro.c" <<'EOF'
    107 extern int sink(const char *);
    108 int p(void) { return sink("abc"); }
    109 EOF
    110 "$KIT" cc -O1 -c "$WORK/live_ro.c" \
    111   -o "$WORK/live_ro.o" > "$WORK/live_ro.cc.out" 2>&1
    112 "$KIT" nm "$WORK/live_ro.o" > "$WORK/live_ro.nm" 2>&1
    113 if grep -Eq '[[:space:]][uU][[:space:]]+\.Lkit_ro' "$WORK/live_ro.nm" ||
    114    ! grep -Eq '[[:space:]][dDrR][[:space:]]+\.Lkit_ro' "$WORK/live_ro.nm"; then
    115   printf 'O1 deferred const-data check FAILED: live const data not defined:\n' >&2
    116   sed 's/^/  | /' "$WORK/live_ro.nm" >&2
    117   exit 1
    118 fi
    119 
    120 cat > "$WORK/live_label_addr.c" <<'EOF'
    121 int p(void) { L: return &&L != 0 ? 42 : 7; }
    122 int q(void) { void *x = &&L; return x != 0 ? 11 : 3; L: return 5; }
    123 EOF
    124 "$KIT" cc -O1 -c "$WORK/live_label_addr.c" \
    125   -o "$WORK/live_label_addr.o" > "$WORK/live_label_addr.cc.out" 2>&1
    126 "$KIT" nm "$WORK/live_label_addr.o" > "$WORK/live_label_addr.nm" 2>&1
    127 if grep -Eq '[[:space:]][uU][[:space:]]+\.Lcfblk' "$WORK/live_label_addr.nm"; then
    128   printf 'O1 label-address check FAILED: live &&label target is undefined:\n' >&2
    129   sed 's/^/  | /' "$WORK/live_label_addr.nm" >&2
    130   exit 1
    131 fi
    132 if "$KIT" run -O1 -e p "$WORK/live_label_addr.c" \
    133      > "$WORK/live_label_addr.run.out" 2>&1; then
    134   rc=0
    135 else
    136   rc=$?
    137 fi
    138 if [ "$rc" -ne 42 ]; then
    139   printf 'O1 label-address runtime check FAILED: exit %d (want 42)\n' "$rc" >&2
    140   sed 's/^/  | /' "$WORK/live_label_addr.run.out" >&2
    141   exit 1
    142 fi
    143 if "$KIT" run -O1 -e q "$WORK/live_label_addr.c" \
    144      > "$WORK/live_label_addr_q.run.out" 2>&1; then
    145   rc=0
    146 else
    147   rc=$?
    148 fi
    149 if [ "$rc" -ne 11 ]; then
    150   printf 'O1 label-address runtime check FAILED: q exit %d (want 11)\n' \
    151     "$rc" >&2
    152   sed 's/^/  | /' "$WORK/live_label_addr_q.run.out" >&2
    153   exit 1
    154 fi
    155 
    156 cat > "$WORK/dead_inline_label_addr.c" <<'EOF'
    157 static inline void *q(void) { L: return &&L; }
    158 int p(void) { return 0; }
    159 EOF
    160 "$KIT" cc -O1 -c "$WORK/dead_inline_label_addr.c" \
    161   -o "$WORK/dead_inline_label_addr.o" \
    162   > "$WORK/dead_inline_label_addr.cc.out" 2>&1
    163 "$KIT" nm "$WORK/dead_inline_label_addr.o" \
    164   > "$WORK/dead_inline_label_addr.nm" 2>&1
    165 if grep -q '\.Lcfblk' "$WORK/dead_inline_label_addr.nm"; then
    166   printf 'O1 label-address check FAILED: dead inline leaked .Lcfblk:\n' >&2
    167   sed 's/^/  | /' "$WORK/dead_inline_label_addr.nm" >&2
    168   exit 1
    169 fi
    170 
    171 printf 'tiny-inline: ok\n'