# -*- Python -*-
# Taken from utils/lit/tests in the LLVM tree and hacked together to support
# our tests.
#
# Note: This configuration has simple commands to run Subzero's translator.
# They have the form %X2i (i.e. %p2i, %l2i, and %lc2i) where X is defined
# as follows:
#
#   p : Run Subzero's translator, building ICE from PNaCl bitcode directly.
#   l : Run Subzero's translator, converting the .ll file to a PNaCl bitcode
#       file, reading in the bitcode file and generating LLVM IR, and
#       then convert LLVM IR to ICE IR.
#   lc : Run Subzero's translator, directly parsing the .ll file into LLVM IR,
#        and then convert it to ICE IR.
#
# These commands can be used in RUN lines by FileCheck. If the Subzero
# build being tested lacks any required attributes (e.g., the ability
# to parse .ll files), the command will simply return successfully,
# generating no output. This allows translation tests to be able to
# conditionally test the translator, based on the translator built.
#
# This conditional handling of translation introduces potential problems
# when the output is piped to another command on a RUN line. Executables
# like FileCheck expect non-empty input.
#
# To handle the problem that the pipe is conditional, any command that
# doesn't accept empty input should be prefixed by a corresponding
# %ifX (i.e. %p2i, %ifl, or %ifpc). Note: %p2i should always work, and
# hence %ifp is not necessary (i.e. it is a nop).
#
# If you need to check other build attributes (other than the
# existence of %l2i and %lc2i), you can use the %if command (which is
# a short hand for using pydir/ifatts.py).

import os
import re
import sys

import lit.formats

sys.path.insert(0, 'pydir')
from utils import FindBaseNaCl, shellcmd

# name: The name of this test suite.
config.name = 'subzero'

# testFormat: The test format to use to interpret tests.
config.test_format = lit.formats.ShTest()

# suffixes: A list of file extensions to treat as test files.
config.suffixes = ['.ll', '.test']

# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)
config.test_exec_root = config.test_source_root
config.target_triple = '(unused)'

src_root = os.path.join(FindBaseNaCl(), 'toolchain_build/src/subzero')
bin_root = src_root
config.substitutions.append(('%{src_root}', src_root))
config.substitutions.append(('%{python}', sys.executable))

pydir = os.path.join(bin_root, 'pydir')

# Finding PNaCl binary tools. Tools used in the tests must be listed in the
# pnaclbintools list.
pnaclbinpath = os.path.abspath(os.environ.get('PNACL_BIN_PATH'))

# Define the location of the pnacl-sz tool.
pnacl_sz_tool = os.path.join(bin_root, 'pnacl-sz')
pnacl_sz_atts = shellcmd(' '.join([pnacl_sz_tool, '--build-atts']),
                        echo=False).split()

# Add build attributes of pnacl-sz tool to the set of available features.
config.available_features.update(pnacl_sz_atts)

def if_cond_flag(Value):
  return '--cond=true' if Value else '--cond=false'

# shell conditional commands.
if_atts = [os.path.join(pydir, 'if.py')]
if_atts_cmd = if_atts + ['--have=' + att for att in pnacl_sz_atts]
ifl2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir' in pnacl_sz_atts),
                            '--command']
iflc2i_atts_cmd = if_atts + [if_cond_flag('allow_llvm_ir_as_input'
                                          in pnacl_sz_atts), '--command']

# Base command for running pnacl-sz
pnacl_sz_cmd = [os.path.join(pydir, 'run-pnacl-sz.py'),
                '--echo-cmd',
                '--pnacl-sz', pnacl_sz_tool,
                '--pnacl-bin-path', pnaclbinpath]
if 'FORCEASM' in lit_config.params:
  pnacl_sz_cmd += ['--forceasm']

# Run commands only if corresponding build attributes apply, including
# for each compiler setup.
config.substitutions.append(('%ifp', ' '))
config.substitutions.append(('%iflc', ' '.join(iflc2i_atts_cmd)))
config.substitutions.append(('%ifl', ' '.join(ifl2i_atts_cmd)))
config.substitutions.append(('%if', ' '.join(if_atts_cmd)))

# Translate LLVM source for each compiler setup.
config.substitutions.append(('%p2i', ' '.join(pnacl_sz_cmd)))
config.substitutions.append(('%l2i', ' '.join(ifl2i_atts_cmd + pnacl_sz_cmd
                                              + ['--llvm'])))
config.substitutions.append(('%lc2i', ' '.join(iflc2i_atts_cmd + pnacl_sz_cmd
                                               + ['--llvm-source'])))

config.substitutions.append(('%pnacl_sz', pnacl_sz_tool))

pnaclbintools = [r'\b' + x + r'\b' for x in
                 ['FileCheck',
                  'llvm-as',
                  'llvm-mc',
                  'llvm-readobj',
                  'not',
                  'pnacl-bcdis',
                  'pnacl-bcfuzz',
                  'pnacl-freeze']]

for tool in pnaclbintools:
  # The re.sub() line is adapted from one of LLVM's lit.cfg files.
  # Extract the tool name from the pattern.  This relies on the tool
  # name being surrounded by \b word match operators.  If the
  # pattern starts with "| ", include it in the string to be
  # substituted.
  substitution = re.sub(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_]+)\\b\W*$",
                        r"\2" + pnaclbinpath + "/" + r"\4",
                        tool)
  config.substitutions.append((tool, substitution))

# Add a feature to detect the Python version.
config.available_features.add("python%d.%d" % (sys.version_info[0],
                                               sys.version_info[1]))

# Debugging output
def dbg(s):
  print '[DBG] %s' % s

dbg('bin_root = %s' % bin_root)
dbg('pnaclbinpath = %s' % pnaclbinpath)
dbg("Build attributes = %s" % pnacl_sz_atts)