import os
import platform
import re
import subprocess
import sys

import lit.util
from lit.llvm.subst import FindTool
from lit.llvm.subst import ToolSubst


class LLVMConfig(object):

    def __init__(self, lit_config, config):
        self.lit_config = lit_config
        self.config = config

        features = config.available_features

        self.use_lit_shell = False
        # Tweak PATH for Win32 to decide to use bash.exe or not.
        if sys.platform == 'win32':
            # For tests that require Windows to run.
            features.add('system-windows')

            # Seek sane tools in directories and set to $PATH.
            path = self.lit_config.getToolsPath(config.lit_tools_dir,
                                                config.environment['PATH'],
                                                ['cmp.exe', 'grep.exe', 'sed.exe'])
            if path is not None:
                self.with_environment('PATH', path, append_path=True)
            # Many tools behave strangely if these environment variables aren't set.
            self.with_system_environment(['SystemDrive', 'SystemRoot', 'TEMP', 'TMP'])
            self.use_lit_shell = True

        # Choose between lit's internal shell pipeline runner and a real shell.  If
        # LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
        lit_shell_env = os.environ.get('LIT_USE_INTERNAL_SHELL')
        if lit_shell_env:
            self.use_lit_shell = lit.util.pythonize_bool(lit_shell_env)

        if not self.use_lit_shell:
            features.add('shell')

        # Running on Darwin OS
        if platform.system() == 'Darwin':
            # FIXME: lld uses the first, other projects use the second.
            # We should standardize on the former.
            features.add('system-linker-mach-o')
            features.add('system-darwin')
        elif platform.system() == 'Windows':
            # For tests that require Windows to run.
            features.add('system-windows')
        elif platform.system() == "Linux":
            features.add('system-linux')
        elif platform.system() in ['FreeBSD']:
            features.add('system-freebsd')
        elif platform.system() == "NetBSD":
            features.add('system-netbsd')

        # Native compilation: host arch == default triple arch
        # Both of these values should probably be in every site config (e.g. as
        # part of the standard header.  But currently they aren't)
        host_triple = getattr(config, 'host_triple', None)
        target_triple = getattr(config, 'target_triple', None)
        if host_triple and host_triple == target_triple:
            features.add('native')

        # Sanitizers.
        sanitizers = getattr(config, 'llvm_use_sanitizer', '')
        sanitizers = frozenset(x.lower() for x in sanitizers.split(';'))
        if 'address' in sanitizers:
            features.add('asan')
        if 'memory' in sanitizers:
            features.add('msan')
        if 'undefined' in sanitizers:
            features.add('ubsan')

        have_zlib = getattr(config, 'have_zlib', None)
        if have_zlib:
            features.add('zlib')

        # Check if we should run long running tests.
        long_tests = lit_config.params.get('run_long_tests', None)
        if lit.util.pythonize_bool(long_tests):
            features.add('long_tests')

        if target_triple:
            if re.match(r'^x86_64.*-apple', target_triple):
                host_cxx = getattr(config, 'host_cxx', None)
                if 'address' in sanitizers and self.get_clang_has_lsan(host_cxx, target_triple):
                    self.with_environment(
                        'ASAN_OPTIONS', 'detect_leaks=1', append_path=True)
            if re.match(r'^x86_64.*-linux', target_triple):
                features.add('x86_64-linux')
            if re.match(r'^i.86.*', target_triple):
                features.add('target-x86')
            elif re.match(r'^x86_64.*', target_triple):
                features.add('target-x86_64')
            elif re.match(r'^aarch64.*', target_triple):
                features.add('target-aarch64')

        use_gmalloc = lit_config.params.get('use_gmalloc', None)
        if lit.util.pythonize_bool(use_gmalloc):
            # Allow use of an explicit path for gmalloc library.
            # Will default to '/usr/lib/libgmalloc.dylib' if not set.
            gmalloc_path_str = lit_config.params.get('gmalloc_path',
                                                     '/usr/lib/libgmalloc.dylib')
            if gmalloc_path_str is not None:
                self.with_environment(
                    'DYLD_INSERT_LIBRARIES', gmalloc_path_str)

    def with_environment(self, variable, value, append_path=False):
        if append_path:
            # For paths, we should be able to take a list of them and process all
            # of them.
            paths_to_add = value
            if lit.util.is_string(paths_to_add):
                paths_to_add = [paths_to_add]

            def norm(x):
                return os.path.normcase(os.path.normpath(x))

            current_paths = self.config.environment.get(variable, None)
            if current_paths:
                current_paths = current_paths.split(os.path.pathsep)
                paths = [norm(p) for p in current_paths]
            else:
                paths = []

            # If we are passed a list [a b c], then iterating this list forwards
            # and adding each to the beginning would result in b c a.  So we
            # need to iterate in reverse to end up with the original ordering.
            for p in reversed(paths_to_add):
                # Move it to the front if it already exists, otherwise insert it at the
                # beginning.
                p = norm(p)
                try:
                    paths.remove(p)
                except ValueError:
                    pass
                paths = [p] + paths
            value = os.pathsep.join(paths)
        self.config.environment[variable] = value

    def with_system_environment(self, variables, append_path=False):
        if lit.util.is_string(variables):
            variables = [variables]
        for v in variables:
            value = os.environ.get(v)
            if value:
                self.with_environment(v, value, append_path)

    def clear_environment(self, variables):
        for name in variables:
            if name in self.config.environment:
                del self.config.environment[name]

    def get_process_output(self, command):
        try:
            cmd = subprocess.Popen(
                command, stdout=subprocess.PIPE,
                stderr=subprocess.PIPE, env=self.config.environment)
            stdout, stderr = cmd.communicate()
            stdout = lit.util.to_string(stdout)
            stderr = lit.util.to_string(stderr)
            return (stdout, stderr)
        except OSError:
            self.lit_config.fatal('Could not run process %s' % command)

    def feature_config(self, features):
        # Ask llvm-config about the specified feature.
        arguments = [x for (x, _) in features]
        config_path = os.path.join(self.config.llvm_tools_dir, 'llvm-config')

        output, _ = self.get_process_output([config_path] + arguments)
        lines = output.split('\n')

        for (feature_line, (_, patterns)) in zip(lines, features):
            # We should have either a callable or a dictionary.  If it's a
            # dictionary, grep each key against the output and use the value if
            # it matches.  If it's a callable, it does the entire translation.
            if callable(patterns):
                features_to_add = patterns(feature_line)
                self.config.available_features.update(features_to_add)
            else:
                for (re_pattern, feature) in patterns.items():
                    if re.search(re_pattern, feature_line):
                        self.config.available_features.add(feature)

    # Note that when substituting %clang_cc1 also fill in the include directory of
    # the builtin headers. Those are part of even a freestanding environment, but
    # Clang relies on the driver to locate them.
    def get_clang_builtin_include_dir(self, clang):
        # FIXME: Rather than just getting the version, we should have clang print
        # out its resource dir here in an easy to scrape form.
        clang_dir, _ = self.get_process_output(
            [clang, '-print-file-name=include'])

        if not clang_dir:
            self.lit_config.fatal(
                "Couldn't find the include dir for Clang ('%s')" % clang)

        clang_dir = clang_dir.strip()
        if sys.platform in ['win32'] and not self.use_lit_shell:
            # Don't pass dosish path separator to msys bash.exe.
            clang_dir = clang_dir.replace('\\', '/')
        # Ensure the result is an ascii string, across Python2.5+ - Python3.
        return clang_dir

    # On macOS, LSan is only supported on clang versions 5 and higher
    def get_clang_has_lsan(self, clang, triple):
        if not clang:
            self.lit_config.warning(
                'config.host_cxx is unset but test suite is configured to use sanitizers.')
            return False

        clang_binary = clang.split()[0]
        version_string, _ = self.get_process_output(
            [clang_binary, '--version'])
        if not 'clang' in version_string:
            self.lit_config.warning(
                "compiler '%s' does not appear to be clang, " % clang_binary +
                'but test suite is configured to use sanitizers.')
            return False

        if re.match(r'.*-linux', triple):
            return True

        if re.match(r'^x86_64.*-apple', triple):
            version_regex = re.search(r'version ([0-9]+)\.([0-9]+).([0-9]+)', version_string)
            major_version_number = int(version_regex.group(1))
            minor_version_number = int(version_regex.group(2))
            patch_version_number = int(version_regex.group(3))
            if ('Apple LLVM' in version_string) or ('Apple clang' in version_string):
                # Apple clang doesn't yet support LSan
                return False
            else:
                return major_version_number >= 5

        return False

    def make_itanium_abi_triple(self, triple):
        m = re.match(r'(\w+)-(\w+)-(\w+)', triple)
        if not m:
            self.lit_config.fatal(
                "Could not turn '%s' into Itanium ABI triple" % triple)
        if m.group(3).lower() != 'windows':
            # All non-windows triples use the Itanium ABI.
            return triple
        return m.group(1) + '-' + m.group(2) + '-' + m.group(3) + '-gnu'

    def make_msabi_triple(self, triple):
        m = re.match(r'(\w+)-(\w+)-(\w+)', triple)
        if not m:
            self.lit_config.fatal(
                "Could not turn '%s' into MS ABI triple" % triple)
        isa = m.group(1).lower()
        vendor = m.group(2).lower()
        os = m.group(3).lower()
        if os == 'windows' and re.match(r'.*-msvc$', triple):
            # If the OS is windows and environment is msvc, we're done.
            return triple
        if isa.startswith('x86') or isa == 'amd64' or re.match(r'i\d86', isa):
            # For x86 ISAs, adjust the OS.
            return isa + '-' + vendor + '-windows-msvc'
        # -msvc is not supported for non-x86 targets; use a default.
        return 'i686-pc-windows-msvc'

    def add_tool_substitutions(self, tools, search_dirs=None):
        if not search_dirs:
            search_dirs = [self.config.llvm_tools_dir]

        if lit.util.is_string(search_dirs):
            search_dirs = [search_dirs]

        tools = [x if isinstance(x, ToolSubst) else ToolSubst(x)
                 for x in tools]

        search_dirs = os.pathsep.join(search_dirs)
        substitutions = []

        for tool in tools:
            match = tool.resolve(self, search_dirs)

            # Either no match occurred, or there was an unresolved match that
            # is ignored.
            if not match:
                continue

            subst_key, tool_pipe, command = match

            # An unresolved match occurred that can't be ignored.  Fail without
            # adding any of the previously-discovered substitutions.
            if not command:
                return False

            substitutions.append((subst_key, tool_pipe + command))

        self.config.substitutions.extend(substitutions)
        return True

    def use_default_substitutions(self):
        tool_patterns = [
            ToolSubst('FileCheck', unresolved='fatal'),
            # Handle these specially as they are strings searched for during testing.
            ToolSubst(r'\| \bcount\b', command=FindTool(
                'count'), verbatim=True, unresolved='fatal'),
            ToolSubst(r'\| \bnot\b', command=FindTool('not'), verbatim=True, unresolved='fatal')]

        self.config.substitutions.append(('%python', '"%s"' % (sys.executable)))

        self.add_tool_substitutions(
            tool_patterns, [self.config.llvm_tools_dir])

    def use_llvm_tool(self, name, search_env=None, required=False, quiet=False):
        """Find the executable program 'name', optionally using the specified
        environment variable as an override before searching the
        configuration's PATH."""
        # If the override is specified in the environment, use it without
        # validation.
        if search_env:
            tool = self.config.environment.get(search_env)
            if tool:
                return tool

        # Otherwise look in the path.
        tool = lit.util.which(name, self.config.environment['PATH'])

        if required and not tool:
            message = "couldn't find '{}' program".format(name)
            if search_env:
                message = message + \
                    ', try setting {} in your environment'.format(search_env)
            self.lit_config.fatal(message)

        if tool:
            tool = os.path.normpath(tool)
            if not self.lit_config.quiet and not quiet:
                self.lit_config.note('using {}: {}'.format(name, tool))
        return tool

    def use_clang(self, additional_tool_dirs=[], additional_flags=[], required=True):
        """Configure the test suite to be able to invoke clang.

        Sets up some environment variables important to clang, locates a
        just-built or installed clang, and add a set of standard
        substitutions useful to any test suite that makes use of clang.

        """
        # Clear some environment variables that might affect Clang.
        #
        # This first set of vars are read by Clang, but shouldn't affect tests
        # that aren't specifically looking for these features, or are required
        # simply to run the tests at all.
        #
        # FIXME: Should we have a tool that enforces this?

        # safe_env_vars = ('TMPDIR', 'TEMP', 'TMP', 'USERPROFILE', 'PWD',
        #                  'MACOSX_DEPLOYMENT_TARGET', 'IPHONEOS_DEPLOYMENT_TARGET',
        #                  'VCINSTALLDIR', 'VC100COMNTOOLS', 'VC90COMNTOOLS',
        #                  'VC80COMNTOOLS')
        possibly_dangerous_env_vars = ['COMPILER_PATH', 'RC_DEBUG_OPTIONS',
                                       'CINDEXTEST_PREAMBLE_FILE', 'LIBRARY_PATH',
                                       'CPATH', 'C_INCLUDE_PATH', 'CPLUS_INCLUDE_PATH',
                                       'OBJC_INCLUDE_PATH', 'OBJCPLUS_INCLUDE_PATH',
                                       'LIBCLANG_TIMING', 'LIBCLANG_OBJTRACKING',
                                       'LIBCLANG_LOGGING', 'LIBCLANG_BGPRIO_INDEX',
                                       'LIBCLANG_BGPRIO_EDIT', 'LIBCLANG_NOTHREADS',
                                       'LIBCLANG_RESOURCE_USAGE',
                                       'LIBCLANG_CODE_COMPLETION_LOGGING']
        # Clang/Win32 may refer to %INCLUDE%. vsvarsall.bat sets it.
        if platform.system() != 'Windows':
            possibly_dangerous_env_vars.append('INCLUDE')

        self.clear_environment(possibly_dangerous_env_vars)

        # Tweak the PATH to include the tools dir and the scripts dir.
        # Put Clang first to avoid LLVM from overriding out-of-tree clang builds.
        exe_dir_props = [self.config.name.lower() + '_tools_dir', 'clang_tools_dir', 'llvm_tools_dir']
        paths = [getattr(self.config, pp) for pp in exe_dir_props
                 if getattr(self.config, pp, None)]
        paths = additional_tool_dirs + paths
        self.with_environment('PATH', paths, append_path=True)

        lib_dir_props = [self.config.name.lower() + '_libs_dir', 'clang_libs_dir', 'llvm_shlib_dir', 'llvm_libs_dir']
        paths = [getattr(self.config, pp) for pp in lib_dir_props
                 if getattr(self.config, pp, None)]

        self.with_environment('LD_LIBRARY_PATH', paths, append_path=True)

        # Discover the 'clang' and 'clangcc' to use.

        self.config.clang = self.use_llvm_tool(
            'clang', search_env='CLANG', required=required)

        shl = getattr(self.config, 'llvm_shlib_dir', None)
        pext = getattr(self.config, 'llvm_plugin_ext', None)
        if shl:
            self.config.substitutions.append(('%llvmshlibdir', shl))
        if pext:
            self.config.substitutions.append(('%pluginext', pext))

        builtin_include_dir = self.get_clang_builtin_include_dir(self.config.clang)
        tool_substitutions = [
            ToolSubst('%clang', command=self.config.clang, extra_args=additional_flags),
            ToolSubst('%clang_analyze_cc1', command='%clang_cc1', extra_args=['-analyze', '%analyze', '-setup-static-analyzer']+additional_flags),
            ToolSubst('%clang_cc1', command=self.config.clang, extra_args=['-cc1', '-internal-isystem', builtin_include_dir, '-nostdsysteminc']+additional_flags),
            ToolSubst('%clang_cpp', command=self.config.clang, extra_args=['--driver-mode=cpp']+additional_flags),
            ToolSubst('%clang_cl', command=self.config.clang, extra_args=['--driver-mode=cl']+additional_flags),
            ToolSubst('%clangxx', command=self.config.clang, extra_args=['--driver-mode=g++']+additional_flags),
            ]
        self.add_tool_substitutions(tool_substitutions)

        self.config.substitutions.append(('%itanium_abi_triple',
                                          self.make_itanium_abi_triple(self.config.target_triple)))
        self.config.substitutions.append(('%ms_abi_triple',
                                          self.make_msabi_triple(self.config.target_triple)))
        self.config.substitutions.append(
            ('%resource_dir', builtin_include_dir))

        # The host triple might not be set, at least if we're compiling clang from
        # an already installed llvm.
        if self.config.host_triple and self.config.host_triple != '@LLVM_HOST_TRIPLE@':
            self.config.substitutions.append(('%target_itanium_abi_host_triple',
                                              '--target=%s' % self.make_itanium_abi_triple(self.config.host_triple)))
        else:
            self.config.substitutions.append(
                ('%target_itanium_abi_host_triple', ''))

        # FIXME: Find nicer way to prohibit this.
        self.config.substitutions.append(
            (' clang ', """\"*** Do not use 'clang' in tests, use '%clang'. ***\""""))
        self.config.substitutions.append(
            (' clang\+\+ ', """\"*** Do not use 'clang++' in tests, use '%clangxx'. ***\""""))
        self.config.substitutions.append(
            (' clang-cc ',
             """\"*** Do not use 'clang-cc' in tests, use '%clang_cc1'. ***\""""))
        self.config.substitutions.append(
            (' clang-cl ',
             """\"*** Do not use 'clang-cl' in tests, use '%clang_cl'. ***\""""))
        self.config.substitutions.append(
            (' clang -cc1 -analyze ',
             """\"*** Do not use 'clang -cc1 -analyze' in tests, use '%clang_analyze_cc1'. ***\""""))
        self.config.substitutions.append(
            (' clang -cc1 ',
             """\"*** Do not use 'clang -cc1' in tests, use '%clang_cc1'. ***\""""))
        self.config.substitutions.append(
            (' %clang-cc1 ',
             """\"*** invalid substitution, use '%clang_cc1'. ***\""""))
        self.config.substitutions.append(
            (' %clang-cpp ',
             """\"*** invalid substitution, use '%clang_cpp'. ***\""""))
        self.config.substitutions.append(
            (' %clang-cl ',
             """\"*** invalid substitution, use '%clang_cl'. ***\""""))

    def use_lld(self, additional_tool_dirs=[], required=True):
        """Configure the test suite to be able to invoke lld.

        Sets up some environment variables important to lld, locates a
        just-built or installed lld, and add a set of standard
        substitutions useful to any test suite that makes use of lld.

        """

        # Tweak the PATH to include the tools dir and the scripts dir.
        exe_dir_props = [self.config.name.lower() + '_tools_dir', 'lld_tools_dir', 'llvm_tools_dir']
        paths = [getattr(self.config, pp) for pp in exe_dir_props
                 if getattr(self.config, pp, None)]
        paths = additional_tool_dirs + paths
        self.with_environment('PATH', paths, append_path=True)

        lib_dir_props = [self.config.name.lower() + '_libs_dir', 'lld_libs_dir', 'llvm_libs_dir']
        paths = [getattr(self.config, pp) for pp in lib_dir_props
                 if getattr(self.config, pp, None)]

        self.with_environment('LD_LIBRARY_PATH', paths, append_path=True)

        # Discover the 'clang' and 'clangcc' to use.

        ld_lld = self.use_llvm_tool('ld.lld', required=required)
        lld_link = self.use_llvm_tool('lld-link', required=required)
        ld64_lld = self.use_llvm_tool('ld64.lld', required=required)
        wasm_ld = self.use_llvm_tool('wasm-ld', required=required)

        was_found = ld_lld and lld_link and ld64_lld and wasm_ld
        tool_substitutions = []
        if ld_lld:
            tool_substitutions.append(ToolSubst('ld\.lld', command=ld_lld))
        if lld_link:
            tool_substitutions.append(ToolSubst('lld-link', command=lld_link))
        if ld64_lld:
            tool_substitutions.append(ToolSubst('ld64\.lld', command=ld64_lld))
        if wasm_ld:
            tool_substitutions.append(ToolSubst('wasm-ld', command=wasm_ld))
        self.add_tool_substitutions(tool_substitutions)
        return was_found
