#!/bin/sh -e

PATH="/usr/src/llvm-common-checkinstall-tests:$PATH"
. definitions.sh
set -ex

_clang() {
    clang -g -flto=thin "$@"
}

_clang_verbose() {
    _clang -v "$@"
}

_clang_fatal() {
    set +e
    printf "!! %s\n" "invocation has failed; retrying with -v"
    _clang_verbose "$@"
    exit 1
}

_clang_call() {
    _clang "$@" || _clang_fatal "$@"
}

dir="$(mktemp -d)" && cd "$dir"
cat > a.c <<EOa.c
  #include <stdint.h>

  struct xorshift64star_state {
    uint64_t x;
  };

  /* xorshift64s, variant A_1(12,25,27) with multiplier M_32 from line 3 of table 5 */
  uint64_t xorshift64star(struct xorshift64star_state* s) {
    /* initial seed must be nonzero, don't use a static variable for the state if multithreaded */
    uint64_t x = s->x;
    x ^= x >> 12;
    x ^= x << 25;
    x ^= x >> 27;
    s->x = x;
    return x * 0x2545f4914f6cdd1dULL;
  }

  uint64_t m(uint64_t a, uint64_t b) {
    int ret;
    struct xorshift64star_state st, *s = &st;

    s->x = a;

    while (b > 0) {
      ret = xorshift64star(s);
      --b;
    }

    return ret;
  }
EOa.c

cat > b.c <<EOb.c
  #include <stdint.h>

  uint64_t m(uint64_t, uint64_t);

  uint64_t f(void) {
    /* A call to module a. */
    return m((45 << 10) + 89, 12);
  }

  uint64_t g(void) {
    /* A call to module a. */
    return m(f() & 0xffff0, 12) & 0xf + 0xf;
  }
EOb.c

cat > c.c <<EOc.c
  #include <inttypes.h>
  #include <stdint.h>
  #include <stdio.h>

  uint64_t f(void);
  uint64_t g(void);
  uint64_t m(uint64_t, uint64_t);

  int main(int argc, char* argv[]) {
    printf("0x%" PRIx64 "\n", m(f(), g()));
    return 0;
  }
EOc.c

ret=0
case "$(rpm --eval '%_arch')" in
arm*) # match ALT armh
    ;;
*)
_clang_call              a.c b.c c.c -o abc && ./abc || ret=$?
    ;;
esac
_clang_call -fuse-ld=lld a.c b.c c.c -o abc && ./abc || ret=$?
rm -rf "$dir"
exit $ret
