#!/usr/bin/env python3
import argparse
import subprocess
from typing import *
import tempfile
import copy
import os
import shutil
import sys
import re
import configparser
from types import SimpleNamespace
from textwrap import dedent

# USAGE:
# 0. Prepare two BOLT build versions: base and compare.
# 1. Create the config by invoking this script with required options.
#    Save the config as `llvm-bolt-wrapper.ini` next to the script or
#    in the testing directory.
# In the base BOLT build directory:
# 2. Rename `llvm-bolt` to `llvm-bolt.real`
# 3. Create a symlink from this script to `llvm-bolt`
# 4. Create `llvm-bolt-wrapper.ini` and fill it using the example below.
#
# This script will compare binaries produced by base and compare BOLT, and
# report elapsed processing time and max RSS.

# read options from config file llvm-bolt-wrapper.ini in script CWD
#
# [config]
# # mandatory
# base_bolt = /full/path/to/llvm-bolt.real
# cmp_bolt = /full/path/to/other/llvm-bolt
# # optional, default to False
# verbose
# keep_tmp
# no_minimize
# run_sequentially
# compare_output
# skip_binary_cmp
# # optional, defaults to timing.log in CWD
# timing_file = timing1.log

def read_cfg():
    src_dir = os.path.dirname(os.path.abspath(__file__))
    cfg = configparser.ConfigParser(allow_no_value = True)
    cfgs = cfg.read("llvm-bolt-wrapper.ini")
    if not cfgs:
        cfgs = cfg.read(os.path.join(src_dir, "llvm-bolt-wrapper.ini"))
    assert cfgs, f"llvm-bolt-wrapper.ini is not found in {os.getcwd()}"

    def get_cfg(key):
        # if key is not present in config, assume False
        if key not in cfg['config']:
            return False
        # if key is present, but has no value, assume True
        if not cfg['config'][key]:
            return True
        # if key has associated value, interpret the value
        return cfg['config'].getboolean(key)

    d = {
        # BOLT binary locations
        'BASE_BOLT': cfg['config']['base_bolt'],
        'CMP_BOLT': cfg['config']['cmp_bolt'],
        # optional
        'VERBOSE': get_cfg('verbose'),
        'KEEP_TMP': get_cfg('keep_tmp'),
        'NO_MINIMIZE': get_cfg('no_minimize'),
        'RUN_SEQUENTIALLY': get_cfg('run_sequentially'),
        'COMPARE_OUTPUT': get_cfg('compare_output'),
        'SKIP_BINARY_CMP': get_cfg('skip_binary_cmp'),
        'TIMING_FILE': cfg['config'].get('timing_file', 'timing.log'),
    }
    if d['VERBOSE']:
        print(f"Using config {os.path.abspath(cfgs[0])}")
    return SimpleNamespace(**d)

# perf2bolt mode
PERF2BOLT_MODE = ['-aggregate-only', '-ignore-build-id']

# boltdiff mode
BOLTDIFF_MODE = ['-diff-only', '-o', '/dev/null']

# options to suppress binary differences as much as possible
MINIMIZE_DIFFS = ['-bolt-info=0']

# bolt output options that need to be intercepted
BOLT_OUTPUT_OPTS = {
    '-o': 'BOLT output binary',
    '-w': 'BOLT recorded profile',
}

# regex patterns to exclude the line from log comparison
SKIP_MATCH = [
    'BOLT-INFO: BOLT version',
    r'^Args: ',
    r'^BOLT-DEBUG:',
    r'BOLT-INFO:.*data.*output data',
    'WARNING: reading perf data directly',
]

def run_cmd(cmd, out_f, cfg):
    if cfg.VERBOSE:
        print(' '.join(cmd))
    return subprocess.Popen(cmd, stdout=out_f, stderr=subprocess.STDOUT)

def run_bolt(bolt_path, bolt_args, out_f, cfg):
    p2b = os.path.basename(sys.argv[0]) == 'perf2bolt' # perf2bolt mode
    bd = os.path.basename(sys.argv[0]) == 'llvm-boltdiff' # boltdiff mode
    hm = sys.argv[1] == 'heatmap' # heatmap mode
    cmd = ['/usr/bin/time', '-f', '%e %M', bolt_path] + bolt_args
    if p2b:
        # -ignore-build-id can occur at most once, hence remove it from cmd
        if '-ignore-build-id' in cmd:
            cmd.remove('-ignore-build-id')
        cmd += PERF2BOLT_MODE
    elif bd:
        cmd += BOLTDIFF_MODE
    elif not cfg.NO_MINIMIZE and not hm:
        cmd += MINIMIZE_DIFFS
    return run_cmd(cmd, out_f, cfg)

def prepend_dash(args: Mapping[AnyStr, AnyStr]) -> Sequence[AnyStr]:
    '''
    Accepts parsed arguments and returns flat list with dash prepended to
    the option.
    Example: Namespace(o='test.tmp') -> ['-o', 'test.tmp']
    '''
    dashed = [('-'+key,value) for (key,value) in args.items()]
    flattened = list(sum(dashed, ()))
    return flattened

def replace_cmp_path(tmp: AnyStr, args: Mapping[AnyStr, AnyStr]) -> Sequence[AnyStr]:
    '''
    Keeps file names, but replaces the path to a temp folder.
    Example: Namespace(o='abc/test.tmp') -> Namespace(o='/tmp/tmpf9un/test.tmp')
    Except preserve /dev/null.
    '''
    replace_path = lambda x: os.path.join(tmp, os.path.basename(x)) if x != '/dev/null' else '/dev/null'
    new_args = {key: replace_path(value) for key, value in args.items()}
    return prepend_dash(new_args)

def preprocess_args(args: argparse.Namespace) -> Mapping[AnyStr, AnyStr]:
    '''
    Drop options that weren't parsed (e.g. -w), convert to a dict
    '''
    return {key: value for key, value in vars(args).items() if value}

def write_to(txt, filename, mode='w'):
    with open(filename, mode) as f:
        f.write(txt)

def wait(proc, fdesc):
    proc.wait()
    fdesc.close()
    return open(fdesc.name)

def compare_logs(main, cmp, skip_begin=0, skip_end=0, str_input=True):
    '''
    Compares logs but allows for certain lines to be excluded from comparison.
    If str_input is True (default), the input it assumed to be a string,
    which is split into lines. Otherwise the input is assumed to be a file.
    Returns None on success, mismatch otherwise.
    '''
    main_inp = main.splitlines() if str_input else main.readlines()
    cmp_inp = cmp.splitlines() if str_input else cmp.readlines()
    # rewind logs after consumption
    if not str_input:
        main.seek(0)
        cmp.seek(0)
    for lhs, rhs in list(zip(main_inp, cmp_inp))[skip_begin:-skip_end or None]:
        if lhs != rhs:
            # check skip patterns
            for skip in SKIP_MATCH:
                # both lines must contain the pattern
                if re.search(skip, lhs) and re.search(skip, rhs):
                    break
            # otherwise return mismatching lines
            else:
                return (lhs, rhs)
    return None

def fmt_cmp(cmp_tuple):
    if not cmp_tuple:
        return ''
    return f'main:\n{cmp_tuple[0]}\ncmp:\n{cmp_tuple[1]}\n'

def compare_with(lhs, rhs, cmd, skip_begin=0, skip_end=0):
    '''
    Runs cmd on both lhs and rhs and compares stdout.
    Returns tuple (mismatch, lhs_stdout):
        - if stdout matches between two files, mismatch is None,
        - otherwise mismatch is a tuple of mismatching lines.
    '''
    run = lambda binary: subprocess.run(cmd.split() + [binary],
                                        text=True, check=True,
                                        capture_output=True).stdout
    run_lhs = run(lhs)
    run_rhs = run(rhs)
    cmp = compare_logs(run_lhs, run_rhs, skip_begin, skip_end)
    return cmp, run_lhs

def parse_cmp_offset(cmp_out):
    '''
    Extracts byte number from cmp output:
    file1 file2 differ: byte X, line Y
    '''
    return int(re.search(r'byte (\d+),', cmp_out).groups()[0])

def report_real_time(binary, main_err, cmp_err, cfg):
    '''
    Extracts real time from stderr and appends it to TIMING FILE it as csv:
    "output binary; base bolt; cmp bolt"
    '''
    def get_real_from_stderr(logline):
        return '; '.join(logline.split())
    for line in main_err:
        pass
    main = get_real_from_stderr(line)
    for line in cmp_err:
        pass
    cmp = get_real_from_stderr(line)
    write_to(f"{binary}; {main}; {cmp}\n", cfg.TIMING_FILE, 'a')
    # rewind logs after consumption
    main_err.seek(0)
    cmp_err.seek(0)

def clean_exit(tmp, out, exitcode, cfg):
    # temp files are only cleaned on success
    if not cfg.KEEP_TMP:
        shutil.rmtree(tmp)

    # report stdout and stderr from the main process
    shutil.copyfileobj(out, sys.stdout)
    sys.exit(exitcode)

def find_section(offset, readelf_hdr):
    hdr = readelf_hdr.split('\n')
    section = None
    # extract sections table (parse objdump -hw output)
    for line in hdr[5:-1]:
        cols = line.strip().split()
        # extract section offset
        file_offset = int(cols[5], 16)
        # section size
        size = int(cols[2], 16)
        if offset >= file_offset and offset <= file_offset + size:
            if sys.stdout.isatty(): # terminal supports colors
                print(f"\033[1m{line}\033[0m")
            else:
                print(f">{line}")
            section = cols[1]
        else:
            print(line)
    return section

def main_config_generator():
    parser = argparse.ArgumentParser()
    parser.add_argument('base_bolt', help='Full path to base llvm-bolt binary')
    parser.add_argument('cmp_bolt', help='Full path to cmp llvm-bolt binary')
    parser.add_argument('--verbose', action='store_true',
                        help='Print subprocess invocation cmdline (default False)')
    parser.add_argument('--keep_tmp', action='store_true',
                        help = 'Preserve tmp folder on a clean exit '
                        '(tmp directory is preserved on crash by default)')
    parser.add_argument('--no_minimize', action='store_true',
                        help=f'Do not add `{MINIMIZE_DIFFS}` that is used '
                        'by default to reduce binary differences')
    parser.add_argument('--run_sequentially', action='store_true',
                        help='Run both binaries sequentially (default '
                        'in parallel). Use for timing comparison')
    parser.add_argument('--compare_output', action='store_true',
                        help = 'Compare bolt stdout/stderr (disabled by default)')
    parser.add_argument('--skip_binary_cmp', action='store_true',
                        help = 'Disable output comparison')
    parser.add_argument('--timing_file', help = 'Override path to timing log '
                        'file (default `timing.log` in CWD)')
    args = parser.parse_args()

    print(dedent(f'''\
    [config]
    # mandatory
    base_bolt = {args.base_bolt}
    cmp_bolt = {args.cmp_bolt}'''))
    del args.base_bolt
    del args.cmp_bolt
    d = vars(args)
    if any(d.values()):
        print("# optional")
        for key, value in d.items():
            if value:
                print(key)

def main():
    cfg = read_cfg()
    # intercept output arguments
    parser = argparse.ArgumentParser(add_help=False)
    for option, help in BOLT_OUTPUT_OPTS.items():
        parser.add_argument(option, help=help)
    args, unknownargs = parser.parse_known_args()
    args = preprocess_args(args)
    cmp_args = copy.deepcopy(args)
    tmp = tempfile.mkdtemp()
    cmp_args = replace_cmp_path(tmp, cmp_args)

    # reconstruct output arguments: prepend dash
    args = prepend_dash(args)

    # run both BOLT binaries
    main_f = open(os.path.join(tmp, 'main_bolt.stdout'), 'w')
    cmp_f = open(os.path.join(tmp, 'cmp_bolt.stdout'), 'w')
    main_bolt = run_bolt(cfg.BASE_BOLT, unknownargs + args, main_f, cfg)
    if cfg.RUN_SEQUENTIALLY:
        main_out = wait(main_bolt, main_f)
        cmp_bolt = run_bolt(cfg.CMP_BOLT, unknownargs + cmp_args, cmp_f, cfg)
    else:
        cmp_bolt = run_bolt(cfg.CMP_BOLT, unknownargs + cmp_args, cmp_f, cfg)
        main_out = wait(main_bolt, main_f)
    cmp_out = wait(cmp_bolt, cmp_f)

    # check exit code
    if main_bolt.returncode != cmp_bolt.returncode:
        print(tmp)
        exit("exitcode mismatch")

    # compare logs, skip_end=1 skips the line with time
    out = compare_logs(main_out, cmp_out, skip_end=1, str_input=False) if cfg.COMPARE_OUTPUT else None
    if out:
        print(tmp)
        print(fmt_cmp(out))
        write_to(fmt_cmp(out), os.path.join(tmp, 'summary.txt'))
        exit("logs mismatch")

    if os.path.basename(sys.argv[0]) == 'llvm-boltdiff': # boltdiff mode
        # no output binary to compare, so just exit
        clean_exit(tmp, main_out, main_bolt.returncode, cfg)

    # compare binaries (using cmp)
    main_binary = args[args.index('-o')+1]
    cmp_binary = cmp_args[cmp_args.index('-o')+1]
    if main_binary == '/dev/null':
        assert cmp_binary == '/dev/null'
        cfg.SKIP_BINARY_CMP = True

    # report binary timing as csv: output binary; base bolt real; cmp bolt real
    report_real_time(main_binary, main_out, cmp_out, cfg)

    # check if files exist
    main_exists = os.path.exists(main_binary)
    cmp_exists = os.path.exists(cmp_binary)
    if main_exists and cmp_exists:
        # proceed to comparison
        pass
    elif not main_exists and not cmp_exists:
        # both don't exist, assume it's intended, skip comparison
        clean_exit(tmp, main_out, main_bolt.returncode, cfg)
    elif main_exists:
        assert not cmp_exists
        exit(f"{cmp_binary} doesn't exist")
    else:
        assert not main_exists
        exit(f"{main_binary} doesn't exist")

    if not cfg.SKIP_BINARY_CMP:
        cmp_proc = subprocess.run(['cmp', '-b', main_binary, cmp_binary],
                                  capture_output=True, text=True)
        if cmp_proc.returncode:
            # check if output is an ELF file (magic bytes)
            with open(main_binary, 'rb') as f:
                magic = f.read(4)
                if magic != b'\x7fELF':
                    exit("output mismatch")
            # check if ELF headers match
            mismatch, _ = compare_with(main_binary, cmp_binary, 'readelf -We')
            if mismatch:
                print(fmt_cmp(mismatch))
                write_to(fmt_cmp(mismatch), os.path.join(tmp, 'headers.txt'))
                exit("headers mismatch")
            # if headers match, compare sections (skip line with filename)
            mismatch, hdr = compare_with(main_binary, cmp_binary, 'objdump -hw',
                                         skip_begin=2)
            assert not mismatch
            # check which section has the first mismatch
            mismatch_offset = parse_cmp_offset(cmp_proc.stdout)
            section = find_section(mismatch_offset, hdr)
            exit(f"binary mismatch @{hex(mismatch_offset)} ({section})")

    clean_exit(tmp, main_out, main_bolt.returncode, cfg)

if __name__ == "__main__":
    # config generator mode if the script is launched as is
    if os.path.basename(__file__) == "llvm-bolt-wrapper.py":
        main_config_generator()
    else:
        # llvm-bolt interceptor mode otherwise
        main()
