Allow conditional lit tests in Subzero, based on build flags.

Adds conditionality to lit tests in two ways:

1) Allows the use of "; REQUIRES: XXX" lines in lit tests. In this
case, the tests defined by the file are only run if all REQUIRES are
met.

2) Allows the conditional running of RUN commands, based on build
flags. This comes in two subforms. There are predefined %ifX commands
that run the command defined by remaining arguments, if the
corresponding %X2i command is applicable. Alternatively, one can use
%if with explicit '--att' arguments to define what conditions should
be checked.

In any case, unlike REQUIRES, the %if commands RUN all the time, but
simply generate empty output, rather then output defined by the
following command, if the condition is not met. These latter tests are
useful when the same input is to be tested under different conditions,
since the REQUIRES form does not allow this.

Note that m2i, p2i, l2i, and lc2i are also conditionally controlled,
so that they do nothing if the build did not construct the appropriate
Subzero translator.

This CL replaces https://codereview.chromium.org/644143002

BUG=None
R=jvoung@chromium.org, stichnot@chromium.org

Review URL: https://codereview.chromium.org/659513005
diff --git a/tests_lit/lit.cfg b/tests_lit/lit.cfg
index 825f7d2..1233a76 100644
--- a/tests_lit/lit.cfg
+++ b/tests_lit/lit.cfg
@@ -1,7 +1,36 @@
+# -*- Python -*-
 # Taken from utils/lit/tests in the LLVM tree and hacked together to support
 # our tests.
-
-# -*- Python -*-
+#
+# 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
@@ -11,6 +40,7 @@
 
 sys.path.insert(0, 'pydir')
 from utils import FindBaseNaCl
+from ifatts import GetFileAttributes
 
 # name: The name of this test suite.
 config.name = 'subzero'
@@ -37,34 +67,39 @@
 # the llvmbintools list.
 llvmbinpath = os.path.abspath(os.environ.get('LLVM_BIN_PATH'))
 
-# Finding Subzero tools
+# Define the location of the llvm2ice tool.
 llvm2icetool = os.path.join(bin_root, 'llvm2ice')
+llvm2icetoolatts = os.path.join(bin_root, 'llvm2ice.build_atts')
 
-# Convert LLVM source to PNaCl bitcode, read using the
-# Subzero bitcode reader, and then translate.
-config.substitutions.append(
-  ('%p2i', ' '.join([os.path.join(pydir, 'run-llvm2ice.py'),
-                     '--llvm2ice', llvm2icetool,
-                     '--llvm-bin-path', llvmbinpath
-                    ])))
+# Add build attributes of llvm2ice tool to the set of available features.
+config.available_features.update(GetFileAttributes(llvm2icetoolatts))
 
-# Convert LLVM source to PNaCl bitcode, read using the PNaCl bitcode reader,
-# convert to ICE using the ICE Converter, and then translate.
-# TODO(kschimpf) Deprecated, remove once p2i working.
-config.substitutions.append(
-  ('%l2i', ' '.join([os.path.join(pydir, 'run-llvm2ice.py'),
-                     '--llvm', '--llvm2ice', llvm2icetool,
-                     '--llvm-bin-path', llvmbinpath
-                    ])))
+# Base command for testing build attributes
+if_atts_base = [os.path.join(pydir, 'ifatts.py'), llvm2icetoolatts]
+if_atts_cmd = if_atts_base + ['--command']
+ifl2i_atts_cmd = if_atts_base + ['--att=allow_llvm_ir', '--command']
+iflc2i_atts_cmd = if_atts_base + ['--att=allow_llvm_ir',
+                                  '--att=allow_llvm_ir_as_input',
+                                  '--command']
 
-# Read LLVM source, convert to ICE using the ICE converter, and then translate.
-# Note: l2i is preferred over lc2i, since it uses PNaCl bitcode.
-# TODO(kschimpf) Deprecated, remove once p2i working.
-config.substitutions.append(
-  ('%lc2i', ' '.join([os.path.join(pydir, 'run-llvm2ice.py'),
-                      '--llvm-source', '--llvm2ice', llvm2icetool,
-                      '--llvm-bin-path', llvmbinpath
-                    ])))
+# Base command for running llvm2ice
+llvm2ice_cmd = [os.path.join(pydir, 'run-llvm2ice.py'),
+                '--llvm2ice', llvm2icetool,
+                '--llvm-bin-path', llvmbinpath]
+
+# 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(llvm2ice_cmd)))
+config.substitutions.append(('%l2i', ' '.join(ifl2i_atts_cmd + llvm2ice_cmd
+                                              + ['--llvm'])))
+config.substitutions.append(('%lc2i', ' '.join(iflc2i_atts_cmd + llvm2ice_cmd
+                                               + ['--llvm-source'])))
 
 config.substitutions.append(('%llvm2ice', llvm2icetool))
 config.substitutions.append(('%szdiff', os.path.join(pydir, 'szdiff.py')))
diff --git a/tests_lit/llvm2ice_tests/addr-opt-multi-def-var.ll b/tests_lit/llvm2ice_tests/addr-opt-multi-def-var.ll
index e5754ae..7e456e8 100644
--- a/tests_lit/llvm2ice_tests/addr-opt-multi-def-var.ll
+++ b/tests_lit/llvm2ice_tests/addr-opt-multi-def-var.ll
@@ -5,6 +5,8 @@
 ; This test depends to some degree on the stability of "--verbose
 ; addropt" output format.
 
+; REQUIRES: x86-32
+; REQUIRES: allow_dump
 ; RUN: %p2i -i %s --args -O2 --verbose addropt | FileCheck %s
 
 declare i32 @_calloc_r(i32, i32, i32)
diff --git a/tests_lit/llvm2ice_tests/align-spill-locations.ll b/tests_lit/llvm2ice_tests/align-spill-locations.ll
index ba7303f..c5121bd 100644
--- a/tests_lit/llvm2ice_tests/align-spill-locations.ll
+++ b/tests_lit/llvm2ice_tests/align-spill-locations.ll
@@ -1,6 +1,7 @@
 ; This checks to ensure that Subzero aligns spill slots.
 
 ; TODO(kschimpf) Find out why lc2i needed.
+; REQUIRES: allow_llvm_ir_as_input
 ; RUN: %lc2i -i %s --args --verbose none \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
 ; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
diff --git a/tests_lit/llvm2ice_tests/ebp_args.ll b/tests_lit/llvm2ice_tests/ebp_args.ll
index 3c2cbc5..3b32409 100644
--- a/tests_lit/llvm2ice_tests/ebp_args.ll
+++ b/tests_lit/llvm2ice_tests/ebp_args.ll
@@ -4,6 +4,7 @@
 ; ebp-based frames.
 
 ; TODO(kschimpf) Find out why lc2i is needed.
+; REQUIRES: allow_llvm_ir_as_input
 ; RUN: %lc2i -i %s --args -Om1 --target=x8632 --verbose none \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
 ; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
diff --git a/tests_lit/llvm2ice_tests/global.ll b/tests_lit/llvm2ice_tests/global.ll
index dd8d55f..c9d08ef 100644
--- a/tests_lit/llvm2ice_tests/global.ll
+++ b/tests_lit/llvm2ice_tests/global.ll
@@ -2,7 +2,8 @@
 ; variables.
 
 ; TODO(kschimpf) find out why lc2i is needed.
-; RUN: %lc2i -i %s --args --verbose inst | FileCheck %s
+; REQUIRES: allow_llvm_ir_as_input
+; RUN: %lc2i -i %s --args --verbose inst | %iflc FileCheck %s
 ; RUN: %lc2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s
 
 ; Note: PNaCl ABI Doesn't allow external globals. Hence, not tested.
diff --git a/tests_lit/llvm2ice_tests/globalrelocs.ll b/tests_lit/llvm2ice_tests/globalrelocs.ll
index 3bb34e9..5addbba 100644
--- a/tests_lit/llvm2ice_tests/globalrelocs.ll
+++ b/tests_lit/llvm2ice_tests/globalrelocs.ll
@@ -1,7 +1,7 @@
 ; Tests if we handle global variables with relocation initializers.
 
 ; Test that we handle it in the ICE converter.
-; RUN: %lc2i -i %s --args -verbose inst | FileCheck %s
+; RUN: %lc2i -i %s --args -verbose inst | %iflc FileCheck %s
 
 ; Test that we handle it using Subzero's bitcode reader.
 ; RUN: %p2i -i %s --args -verbose inst | FileCheck %s
diff --git a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
index bd02ee6..536f140 100644
--- a/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
+++ b/tests_lit/llvm2ice_tests/nacl-atomic-intrinsics.ll
@@ -4,15 +4,18 @@
 ; TODO(kschimpf) Find out why lc2i is needed.
 ; RUN: %lc2i -i %s --args -O2 --verbose none \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
-; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
+; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \
+; RUN:   | %iflc FileCheck %s
 ; RUN: %p2i -i %s --args -O2 --verbose none \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
 ; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \
 ; RUN:   | FileCheck --check-prefix=CHECKO2 %s
 ; RUN: %lc2i -i %s --args -Om1 --verbose none \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
-; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - | FileCheck %s
-; RUN: %p2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s
+; RUN:   | llvm-objdump -d --symbolize -x86-asm-syntax=intel - \
+; RUN:   | %iflc FileCheck %s
+; RUN: %p2i -i %s --args --verbose none \
+; RUN:   | FileCheck --check-prefix=ERRORS %s
 
 declare i8 @llvm.nacl.atomic.load.i8(i8*, i32)
 declare i16 @llvm.nacl.atomic.load.i16(i16*, i32)
diff --git a/tests_lit/llvm2ice_tests/phi.ll b/tests_lit/llvm2ice_tests/phi.ll
index 813a435..5fcf789 100644
--- a/tests_lit/llvm2ice_tests/phi.ll
+++ b/tests_lit/llvm2ice_tests/phi.ll
@@ -3,6 +3,7 @@
 ; compare/branch fusing.
 
 ; TODO(kschimpf) Find out why lc2i must be used.
+; REQUIRES: allow_llvm_ir_as_input
 ; RUN: %lc2i -i %s --args -O2 --verbose none --phi-edge-split=0 \
 ; RUN:   | llvm-mc -triple=i686-none-nacl -x86-asm-syntax=intel -filetype=obj \
 ; RUN:   | llvm-objdump -d -symbolize -x86-asm-syntax=intel - | FileCheck %s
diff --git a/tests_lit/llvm2ice_tests/struct-arith.pnacl.ll b/tests_lit/llvm2ice_tests/struct-arith.pnacl.ll
index ac75e92..9755e21 100644
--- a/tests_lit/llvm2ice_tests/struct-arith.pnacl.ll
+++ b/tests_lit/llvm2ice_tests/struct-arith.pnacl.ll
@@ -2,6 +2,7 @@
 ; with struct members.
 
 ; TODO(kschimpf) Find out why lc2i is needed.
+; REQUIRES: allow_llvm_ir_as_input
 ; RUN: %lc2i -i %s --args --verbose inst | FileCheck %s
 ; RUN: %lc2i -i %s --args --verbose none | FileCheck --check-prefix=ERRORS %s
 
diff --git a/tests_lit/reader_tests/binops.ll b/tests_lit/reader_tests/binops.ll
index 5fde67c..785d482 100644
--- a/tests_lit/reader_tests/binops.ll
+++ b/tests_lit/reader_tests/binops.ll
@@ -1,6 +1,8 @@
 ; Tests if we can read binary operators.
 
 ; RUN: %p2i -i %s --insts | FileCheck %s
+; RUN: %l2i -i %s --insts | %ifl FileCheck %s
+; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
 
 ; TODO(kschimpf): add i8/i16. Needs bitcasts.
 
diff --git a/tests_lit/reader_tests/extern_globals.ll b/tests_lit/reader_tests/extern_globals.ll
index a43bfb6..cde5778 100644
--- a/tests_lit/reader_tests/extern_globals.ll
+++ b/tests_lit/reader_tests/extern_globals.ll
@@ -7,6 +7,7 @@
 ; allow externally defined global variables. Hence, this test can only
 ; work if we read LLVM IR source, and convert to to ICE.
 
+; REQUIRES: allow_llvm_ir_as_input
 ; RUN: %lc2i -i %s --insts --args --allow-uninitialized-globals | FileCheck %s
 ; RUN: %lc2i -i %s --insts --args --allow-uninitialized-globals \
 ; RUN:       -prefix Subzero_ | FileCheck --check-prefix=CROSS %s
diff --git a/tests_lit/reader_tests/globalinit.pnacl.ll b/tests_lit/reader_tests/globalinit.pnacl.ll
index 956e399..6f70735 100644
--- a/tests_lit/reader_tests/globalinit.pnacl.ll
+++ b/tests_lit/reader_tests/globalinit.pnacl.ll
@@ -1,8 +1,8 @@
 ; Test of global initializers.
 
-; Check that we generate proper global initializers.
-; RUN: %l2i -i %s --insts | FileCheck %s
 ; RUN: %p2i -i %s --insts | FileCheck %s
+; RUN: %l2i -i %s --insts | %ifl FileCheck %s
+; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
 
 @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
 ; CHECK: @PrimitiveInit = internal global [4 x i8] c"\1B\00\00\00", align 4
diff --git a/tests_lit/reader_tests/globalrelocs.ll b/tests_lit/reader_tests/globalrelocs.ll
index 8dda67e..6634890 100644
--- a/tests_lit/reader_tests/globalrelocs.ll
+++ b/tests_lit/reader_tests/globalrelocs.ll
@@ -1,10 +1,8 @@
 ; Tests if we handle global variables with relocation initializers.
 
-; Test that we handle it in the ICE converter.
-; RUN: %lc2i -i %s --insts | FileCheck %s
-
-; Test that we handle it using Subzero's bitcode reader.
 ; RUN: %p2i -i %s --insts | FileCheck %s
+; RUN: %l2i -i %s --insts | %ifl FileCheck %s
+; RUN: %lc2i -i %s --insts | %iflc FileCheck %s
 
 @bytes = internal global [7 x i8] c"abcdefg"
 ; CHECK: @bytes = internal global [7 x i8] c"abcdefg"
diff --git a/tests_lit/reader_tests/unnamed.ll b/tests_lit/reader_tests/unnamed.ll
index c2dc676..87dccd6 100644
--- a/tests_lit/reader_tests/unnamed.ll
+++ b/tests_lit/reader_tests/unnamed.ll
@@ -1,14 +1,12 @@
 ; Tests that we name unnamed global addresses.
 
-; Check that the ICE converter handles renaming correctly.
-; RUN: %l2i --no-local-syms -i %s --insts | FileCheck %s
+; Check that Subzero's bitcode reader handles renaming correctly.
+; RUN: %p2i --no-local-syms -i %s --insts | FileCheck %s
+; RUN: %l2i --no-local-syms -i %s --insts | %ifl FileCheck %s
 
 ; RUN: %l2i --no-local-syms -i %s --insts --args --exit-success \
 ; RUN:      -default-function-prefix=h -default-global-prefix=g \
-; RUN:      | FileCheck --check-prefix=BAD %s
-
-; Check that Subzero's bitcode reader handles renaming correctly.
-; RUN: %p2i --no-local-syms -i %s --insts | FileCheck %s
+; RUN:      | %ifl FileCheck --check-prefix=BAD %s
 
 ; RUN: %p2i --no-local-syms -i %s --insts --args --exit-success \
 ; RUN:      -default-function-prefix=h -default-global-prefix=g \