#!/bin/bash
#set -x

if [ $# -gt 2 ]; then
  TOOLS_DIR="$1"
  SOURCE_DIR="$2"
  MAIN_SOURCE_FILE="$3"
else
  echo "Usage: bench <path to llvm binaries> <path to c-sources> <main source file> [<override sysroot>]"
  exit 1
fi

if [ $# -gt 3 ]; then
  SYS_ROOT="$4"
else
  SYS_ROOT="/"
fi

function check_tool ()
{
  if [ -e "${TOOLS_DIR}/$1" ]; then
    echo "Found: $1"
  else
    echo "!!! Cannot find required tool, please provide it in the LLVM binaries folder: $1"
  fi
}

check_tool lli
check_tool SpeculativeJIT
check_tool ThinLtoJIT

SKIP_BITCODE_GEN=0
if [[ -e bc-default || -e bc-thinlto || -e ll-default || -e ll-thinlto ]]; then
  echo "Skipping bitcode generation: output directories existing"
  echo "Please clean up manually: rm -R bc-default bc-thinlto ll-default ll-thinlto"
  SKIP_BITCODE_GEN=1
else
  check_tool clang
  check_tool llvm-dis
  check_tool llvm-lto
  mkdir bc-default
  mkdir bc-thinlto
  mkdir ll-default
  mkdir ll-thinlto
fi

ROOT_DIR=$(pwd)
ALL_BITCODE_FILES=""

MAIN_FILE_BASENAME=$(basename "${MAIN_SOURCE_FILE%.c*}")
LLI_EXTRA_MODULES=""

for f in ${SOURCE_DIR}/*.c* ; do
  BASE_NAME=$(basename "${f%.c*}")

  if [ ${SKIP_BITCODE_GEN} -eq 0 ]; then
    echo "Compile: $f -> ${BASE_NAME}.bc"

    ${TOOLS_DIR}/clang -c -I ${SOURCE_DIR} ${CFLAGS} -isysroot ${SYS_ROOT} -emit-llvm \
                       -o "bc-default/${BASE_NAME}.bc" "$f"
    ${TOOLS_DIR}/clang -c -I ${SOURCE_DIR} ${CFLAGS} -isysroot ${SYS_ROOT} -flto=thin \
                       -o "bc-thinlto/${BASE_NAME}.bc" "$f"

    echo "Disassemble ${BASE_NAME}.bc -> ${BASE_NAME}.ll"
    ${TOOLS_DIR}/llvm-dis bc-default/${BASE_NAME}.bc -o ll-default/${BASE_NAME}.ll
    ${TOOLS_DIR}/llvm-dis bc-thinlto/${BASE_NAME}.bc -o ll-thinlto/${BASE_NAME}.ll
  fi

  ALL_BITCODE_FILES="${ALL_BITCODE_FILES} ${BASE_NAME}.bc"
  if [ "${BASE_NAME}" != "${MAIN_FILE_BASENAME}" ]; then
    LLI_EXTRA_MODULES="${LLI_EXTRA_MODULES} -extra-module=${BASE_NAME}.bc"
  fi
done

if [ ${SKIP_BITCODE_GEN} -eq 0 ]; then
  echo "Link global index file: index.thinlto.bc"
  cd ${ROOT_DIR}/bc-thinlto
  ${TOOLS_DIR}/llvm-lto --thinlto -o ${ROOT_DIR}/bc-thinlto/index ${ALL_BITCODE_FILES}

  echo "Disassemble global index file: index.thinlto.ll"
  cd ${ROOT_DIR}/ll-thinlto
  ${TOOLS_DIR}/llvm-dis -o index.thinlto.ll ${ROOT_DIR}/bc-thinlto/index.thinlto.bc
fi

set -x
cd ${ROOT_DIR}/bc-default
time (${TOOLS_DIR}/clang -o ${MAIN_FILE_BASENAME} -O0 ${LDFLAGS} ${ALL_BITCODE_FILES} && ./${MAIN_FILE_BASENAME} ${EXEC_ARGS} 1>/dev/null)
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=mcjit "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-mcjit "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy -compile-threads=8 "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy -per-module-lazy "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy -per-module-lazy -compile-threads=8 "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy -per-module-lazy -compile-threads=8 -O1 "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/lli ${LLI_EXTRA_MODULES} -jit-kind=orc-lazy -per-module-lazy -compile-threads=8 -O0 "${MAIN_FILE_BASENAME}.bc" ${EXEC_ARGS} 1>/dev/null
time ${TOOLS_DIR}/SpeculativeJIT -num-threads=8 ${ALL_BITCODE_FILES} --args ${EXEC_ARGS} 1>/dev/null

cd ${ROOT_DIR}/bc-thinlto
#time (${TOOLS_DIR}/clang -flto=thin -o test ${ALL_BITCODE_FILES} && ./test ${EXEC_ARGS} 1>/dev/null)
time ${TOOLS_DIR}/ThinLtoJIT index.thinlto.bc --args ${EXEC_ARGS} 1>/dev/null
