#!/usr/bin/env python3
"""
This script:
- Builds clang with user-defined flags
- Uses that clang to build an instrumented clang, which can be used to collect
  PGO samples
- Builds a user-defined set of sources (default: clang) to act as a
  "benchmark" to generate a PGO profile
- Builds clang once more with the PGO profile generated above

This is a total of four clean builds of clang (by default). This may take a
while. :)

This scripts duplicates https://llvm.org/docs/AdvancedBuilds.html#multi-stage-pgo
Eventually, it will be updated to instead call the cmake cache mentioned there.
"""

import argparse
import collections
import multiprocessing
import os
import shlex
import shutil
import subprocess
import sys

### User configuration


# If you want to use a different 'benchmark' than building clang, make this
# function do what you want. out_dir is the build directory for clang, so all
# of the clang binaries will live under "${out_dir}/bin/". Using clang in
# ${out_dir} will magically have the profiles go to the right place.
#
# You may assume that out_dir is a freshly-built directory that you can reach
# in to build more things, if you'd like.
def _run_benchmark(env, out_dir, include_debug_info):
    """The 'benchmark' we run to generate profile data."""
    target_dir = env.output_subdir('instrumentation_run')

    # `check-llvm` and `check-clang` are cheap ways to increase coverage. The
    # former lets us touch on the non-x86 backends a bit if configured, and the
    # latter gives us more C to chew on (and will send us through diagnostic
    # paths a fair amount, though the `if (stuff_is_broken) { diag() ... }`
    # branches should still heavily be weighted in the not-taken direction,
    # since we built all of LLVM/etc).
    _build_things_in(env, out_dir, what=['check-llvm', 'check-clang'])

    # Building tblgen gets us coverage; don't skip it. (out_dir may also not
    # have them anyway, but that's less of an issue)
    cmake = _get_cmake_invocation_for_bootstrap_from(
        env, out_dir, skip_tablegens=False)

    if include_debug_info:
        cmake.add_flag('CMAKE_BUILD_TYPE', 'RelWithDebInfo')

    _run_fresh_cmake(env, cmake, target_dir)

    # Just build all the things. The more data we have, the better.
    _build_things_in(env, target_dir, what=['all'])

### Script


class CmakeInvocation:
    _cflags = ['CMAKE_C_FLAGS', 'CMAKE_CXX_FLAGS']
    _ldflags = [
        'CMAKE_EXE_LINKER_FLAGS',
        'CMAKE_MODULE_LINKER_FLAGS',
        'CMAKE_SHARED_LINKER_FLAGS',
    ]

    def __init__(self, cmake, maker, cmake_dir):
        self._prefix = [cmake, '-G', maker, cmake_dir]

        # Map of str -> (list|str).
        self._flags = {}
        for flag in CmakeInvocation._cflags + CmakeInvocation._ldflags:
            self._flags[flag] = []

    def add_new_flag(self, key, value):
        self.add_flag(key, value, allow_overwrites=False)

    def add_flag(self, key, value, allow_overwrites=True):
        if key not in self._flags:
            self._flags[key] = value
            return

        existing_value = self._flags[key]
        if isinstance(existing_value, list):
            existing_value.append(value)
            return

        if not allow_overwrites:
            raise ValueError('Invalid overwrite of %s requested' % key)

        self._flags[key] = value

    def add_cflags(self, flags):
        # No, I didn't intend to append ['-', 'O', '2'] to my flags, thanks :)
        assert not isinstance(flags, str)
        for f in CmakeInvocation._cflags:
            self._flags[f].extend(flags)

    def add_ldflags(self, flags):
        assert not isinstance(flags, str)
        for f in CmakeInvocation._ldflags:
            self._flags[f].extend(flags)

    def to_args(self):
        args = self._prefix.copy()
        for key, value in sorted(self._flags.items()):
            if isinstance(value, list):
                # We preload all of the list-y values (cflags, ...). If we've
                # nothing to add, don't.
                if not value:
                    continue
                value = ' '.join(value)

            arg = '-D' + key
            if value != '':
                arg += '=' + value
            args.append(arg)
        return args


class Env:
    def __init__(self, llvm_dir, use_make, output_dir, default_cmake_args,
                 dry_run):
        self.llvm_dir = llvm_dir
        self.use_make = use_make
        self.output_dir = output_dir
        self.default_cmake_args = default_cmake_args.copy()
        self.dry_run = dry_run

    def get_default_cmake_args_kv(self):
        return self.default_cmake_args.items()

    def get_cmake_maker(self):
        return 'Ninja' if not self.use_make else 'Unix Makefiles'

    def get_make_command(self):
        if self.use_make:
            return ['make', '-j{}'.format(multiprocessing.cpu_count())]
        return ['ninja']

    def output_subdir(self, name):
        return os.path.join(self.output_dir, name)

    def has_llvm_subproject(self, name):
        if name == 'compiler-rt':
            subdir = '../compiler-rt'
        elif name == 'clang':
            subdir = '../clang'
        else:
            raise ValueError('Unknown subproject: %s' % name)

        return os.path.isdir(os.path.join(self.llvm_dir, subdir))

    # Note that we don't allow capturing stdout/stderr. This works quite nicely
    # with dry_run.
    def run_command(self,
                    cmd,
                    cwd=None,
                    check=False,
                    silent_unless_error=False):
        print(
            'Running `%s` in %s' % (cmd, shlex.quote(cwd or os.getcwd())))

        if self.dry_run:
            return

        if silent_unless_error:
            stdout, stderr = subprocess.PIPE, subprocess.STDOUT
        else:
            stdout, stderr = None, None

        # Don't use subprocess.run because it's >= py3.5 only, and it's not too
        # much extra effort to get what it gives us anyway.
        popen = subprocess.Popen(
            cmd,
            stdin=subprocess.DEVNULL,
            stdout=stdout,
            stderr=stderr,
            cwd=cwd)
        stdout, _ = popen.communicate()
        return_code = popen.wait(timeout=0)

        if not return_code:
            return

        if silent_unless_error:
            print(stdout.decode('utf-8', 'ignore'))

        if check:
            raise subprocess.CalledProcessError(
                returncode=return_code, cmd=cmd, output=stdout, stderr=None)


def _get_default_cmake_invocation(env):
    inv = CmakeInvocation(
        cmake='cmake', maker=env.get_cmake_maker(), cmake_dir=env.llvm_dir)
    for key, value in env.get_default_cmake_args_kv():
        inv.add_new_flag(key, value)
    return inv


def _get_cmake_invocation_for_bootstrap_from(env, out_dir,
                                             skip_tablegens=True):
    clang = os.path.join(out_dir, 'bin', 'clang')
    cmake = _get_default_cmake_invocation(env)
    cmake.add_new_flag('CMAKE_C_COMPILER', clang)
    cmake.add_new_flag('CMAKE_CXX_COMPILER', clang + '++')

    # We often get no value out of building new tblgens; the previous build
    # should have them. It's still correct to build them, just slower.
    def add_tablegen(key, binary):
        path = os.path.join(out_dir, 'bin', binary)

        # Check that this exists, since the user's allowed to specify their own
        # stage1 directory (which is generally where we'll source everything
        # from). Dry runs should hope for the best from our user, as well.
        if env.dry_run or os.path.exists(path):
            cmake.add_new_flag(key, path)

    if skip_tablegens:
        add_tablegen('LLVM_TABLEGEN', 'llvm-tblgen')
        add_tablegen('CLANG_TABLEGEN', 'clang-tblgen')

    return cmake


def _build_things_in(env, target_dir, what):
    cmd = env.get_make_command() + what
    env.run_command(cmd, cwd=target_dir, check=True)


def _run_fresh_cmake(env, cmake, target_dir):
    if not env.dry_run:
        try:
            shutil.rmtree(target_dir)
        except FileNotFoundError:
            pass

        os.makedirs(target_dir, mode=0o755)

    cmake_args = cmake.to_args()
    env.run_command(
        cmake_args, cwd=target_dir, check=True, silent_unless_error=True)


def _build_stage1_clang(env):
    target_dir = env.output_subdir('stage1')
    cmake = _get_default_cmake_invocation(env)
    _run_fresh_cmake(env, cmake, target_dir)
    _build_things_in(env, target_dir, what=['clang', 'llvm-profdata', 'profile'])
    return target_dir


def _generate_instrumented_clang_profile(env, stage1_dir, profile_dir,
                                         output_file):
    llvm_profdata = os.path.join(stage1_dir, 'bin', 'llvm-profdata')
    if env.dry_run:
        profiles = [os.path.join(profile_dir, '*.profraw')]
    else:
        profiles = [
            os.path.join(profile_dir, f) for f in os.listdir(profile_dir)
            if f.endswith('.profraw')
        ]
    cmd = [llvm_profdata, 'merge', '-output=' + output_file] + profiles
    env.run_command(cmd, check=True)


def _build_instrumented_clang(env, stage1_dir):
    assert os.path.isabs(stage1_dir)

    target_dir = os.path.join(env.output_dir, 'instrumented')
    cmake = _get_cmake_invocation_for_bootstrap_from(env, stage1_dir)
    cmake.add_new_flag('LLVM_BUILD_INSTRUMENTED', 'IR')

    # libcxx's configure step messes with our link order: we'll link
    # libclang_rt.profile after libgcc, and the former requires atexit from the
    # latter. So, configure checks fail.
    #
    # Since we don't need libcxx or compiler-rt anyway, just disable them.
    cmake.add_new_flag('LLVM_BUILD_RUNTIME', 'No')

    _run_fresh_cmake(env, cmake, target_dir)
    _build_things_in(env, target_dir, what=['clang', 'lld'])

    profiles_dir = os.path.join(target_dir, 'profiles')
    return target_dir, profiles_dir


def _build_optimized_clang(env, stage1_dir, profdata_file):
    if not env.dry_run and not os.path.exists(profdata_file):
        raise ValueError('Looks like the profdata file at %s doesn\'t exist' %
                         profdata_file)

    target_dir = os.path.join(env.output_dir, 'optimized')
    cmake = _get_cmake_invocation_for_bootstrap_from(env, stage1_dir)
    cmake.add_new_flag('LLVM_PROFDATA_FILE', os.path.abspath(profdata_file))

    # We'll get complaints about hash mismatches in `main` in tools/etc. Ignore
    # it.
    cmake.add_cflags(['-Wno-backend-plugin'])
    _run_fresh_cmake(env, cmake, target_dir)
    _build_things_in(env, target_dir, what=['clang'])
    return target_dir


Args = collections.namedtuple('Args', [
    'do_optimized_build',
    'include_debug_info',
    'profile_location',
    'stage1_dir',
])


def _parse_args():
    parser = argparse.ArgumentParser(
        description='Builds LLVM and Clang with instrumentation, collects '
        'instrumentation profiles for them, and (optionally) builds things '
        'with these PGO profiles. By default, it\'s assumed that you\'re '
        'running this from your LLVM root, and all build artifacts will be '
        'saved to $PWD/out.')
    parser.add_argument(
        '--cmake-extra-arg',
        action='append',
        default=[],
        help='an extra arg to pass to all cmake invocations. Note that this '
        'is interpreted as a -D argument, e.g. --cmake-extra-arg FOO=BAR will '
        'be passed as -DFOO=BAR. This may be specified multiple times.')
    parser.add_argument(
        '--dry-run',
        action='store_true',
        help='print commands instead of running them')
    parser.add_argument(
        '--llvm-dir',
        default='.',
        help='directory containing an LLVM checkout (default: $PWD)')
    parser.add_argument(
        '--no-optimized-build',
        action='store_true',
        help='disable the final, PGO-optimized build')
    parser.add_argument(
        '--out-dir',
        help='directory to write artifacts to (default: $llvm_dir/out)')
    parser.add_argument(
        '--profile-output',
        help='where to output the profile (default is $out/pgo_profile.prof)')
    parser.add_argument(
        '--stage1-dir',
        help='instead of having an initial build of everything, use the given '
        'directory. It is expected that this directory will have clang, '
        'llvm-profdata, and the appropriate libclang_rt.profile already built')
    parser.add_argument(
        '--use-debug-info-in-benchmark',
        action='store_true',
        help='use a regular build instead of RelWithDebInfo in the benchmark. '
        'This increases benchmark execution time and disk space requirements, '
        'but gives more coverage over debuginfo bits in LLVM and clang.')
    parser.add_argument(
        '--use-make',
        action='store_true',
        default=shutil.which('ninja') is None,
        help='use Makefiles instead of ninja')

    args = parser.parse_args()

    llvm_dir = os.path.abspath(args.llvm_dir)
    if args.out_dir is None:
        output_dir = os.path.join(llvm_dir, 'out')
    else:
        output_dir = os.path.abspath(args.out_dir)

    extra_args = {'CMAKE_BUILD_TYPE': 'Release',
                  'LLVM_ENABLE_PROJECTS': 'clang;compiler-rt;lld'}
    for arg in args.cmake_extra_arg:
        if arg.startswith('-D'):
            arg = arg[2:]
        elif arg.startswith('-'):
            raise ValueError('Unknown not- -D arg encountered; you may need '
                             'to tweak the source...')
        split = arg.split('=', 1)
        if len(split) == 1:
            key, val = split[0], ''
        else:
            key, val = split
        extra_args[key] = val

    env = Env(
        default_cmake_args=extra_args,
        dry_run=args.dry_run,
        llvm_dir=llvm_dir,
        output_dir=output_dir,
        use_make=args.use_make,
    )

    if args.profile_output is not None:
        profile_location = args.profile_output
    else:
        profile_location = os.path.join(env.output_dir, 'pgo_profile.prof')

    result_args = Args(
        do_optimized_build=not args.no_optimized_build,
        include_debug_info=args.use_debug_info_in_benchmark,
        profile_location=profile_location,
        stage1_dir=args.stage1_dir,
    )

    return env, result_args


def _looks_like_llvm_dir(directory):
    """Arbitrary set of heuristics to determine if `directory` is an llvm dir.

    Errs on the side of false-positives."""

    contents = set(os.listdir(directory))
    expected_contents = [
        'CODE_OWNERS.TXT',
        'cmake',
        'docs',
        'include',
        'utils',
    ]

    if not all(c in contents for c in expected_contents):
        return False

    try:
        include_listing = os.listdir(os.path.join(directory, 'include'))
    except NotADirectoryError:
        return False

    return 'llvm' in include_listing


def _die(*args, **kwargs):
    kwargs['file'] = sys.stderr
    print(*args, **kwargs)
    sys.exit(1)


def _main():
    env, args = _parse_args()

    if not _looks_like_llvm_dir(env.llvm_dir):
        _die('Looks like %s isn\'t an LLVM directory; please see --help' %
             env.llvm_dir)
    if not env.has_llvm_subproject('clang'):
        _die('Need a clang checkout at tools/clang')
    if not env.has_llvm_subproject('compiler-rt'):
        _die('Need a compiler-rt checkout at projects/compiler-rt')

    def status(*args):
        print(*args, file=sys.stderr)

    if args.stage1_dir is None:
        status('*** Building stage1 clang...')
        stage1_out = _build_stage1_clang(env)
    else:
        stage1_out = args.stage1_dir

    status('*** Building instrumented clang...')
    instrumented_out, profile_dir = _build_instrumented_clang(env, stage1_out)
    status('*** Running profdata benchmarks...')
    _run_benchmark(env, instrumented_out, args.include_debug_info)
    status('*** Generating profile...')
    _generate_instrumented_clang_profile(env, stage1_out, profile_dir,
                                         args.profile_location)

    print('Final profile:', args.profile_location)
    if args.do_optimized_build:
        status('*** Building PGO-optimized binaries...')
        optimized_out = _build_optimized_clang(env, stage1_out,
                                               args.profile_location)
        print('Final build directory:', optimized_out)


if __name__ == '__main__':
    _main()
