Commit b262c5e0 by Karl Schimpf

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
parent 120b4121
......@@ -11,3 +11,9 @@ LEVEL := $(SUBZERO_LEVEL)/../..
# Include LLVM common makefile.
include $(LEVEL)/Makefile.common
CXX.Flags += -std=c++11 -Wextra -Werror -Wno-error=unused-parameter
CPP.Defines += -DALLOW_TEXT_ASM=1 -DALLOW_DUMP=1 -DALLOW_LLVM_CL=1 \
-DALLOW_LLVM_IR=1 -DALLOW_LLVM_IR_AS_INPUT=1
......@@ -45,6 +45,18 @@ else
OPTLEVEL = -O2
endif
# The list of CXX defines that are dependent on build parameters.
CXX_DEFINES =
ifdef MINIMAL
OBJDIR := $(OBJDIR)+Min
CXX_DEFINES += -DALLOW_TEXT_ASM=0 -DALLOW_DUMP=0 -DALLOW_LLVM_CL=0 \
-DALLOW_LLVM_IR=0 -DALLOW_LLVM_IR_AS_INPUT=0
else
CXX_DEFINES += -DALLOW_TEXT_ASM=1 -DALLOW_DUMP=1 -DALLOW_LLVM_CL=1 \
-DALLOW_LLVM_IR=1 -DALLOW_LLVM_IR_AS_INPUT=1
endif
ifdef NOASSERT
ASSERTIONS = -DNDEBUG
else
......@@ -69,8 +81,9 @@ CCACHE := `command -v ccache`
CXX := CCACHE_CPP2=yes $(CCACHE) $(CLANG_PATH)/clang++
CXXFLAGS := $(LLVM_CXXFLAGS) -std=c++11 -Wall -Wextra -Werror -fno-rtti \
-fno-exceptions $(OPTLEVEL) $(ASSERTIONS) -g $(HOST_FLAGS) \
-Wno-error=unused-parameter -I$(LIBCXX_INSTALL_PATH)/include/c++/v1
-fno-exceptions $(OPTLEVEL) $(ASSERTIONS) $(CXX_DEFINES) -g \
$(HOST_FLAGS) -Wno-error=unused-parameter \
-I$(LIBCXX_INSTALL_PATH)/include/c++/v1
LDFLAGS := $(HOST_FLAGS) -L$(LIBCXX_INSTALL_PATH)/lib
SRCS= \
......@@ -103,15 +116,19 @@ OBJS=$(patsubst %.cpp, $(OBJDIR)/%.o, $(SRCS))
# Keep all the first target so it's the default.
all: $(OBJDIR)/llvm2ice make_symlink
make_symlink: $(OBJDIR)/llvm2ice
rm -f llvm2ice
make_symlink: $(OBJDIR)/llvm2ice $(OBJDIR)/llvm2ice.build_atts
rm -rf llvm2ice llvm2ice.build_atts
ln -s $(OBJDIR)/llvm2ice
ln -s $(OBJDIR)/llvm2ice.build_atts
.PHONY: all make_symlink
# TODO(kschimpf): Fix python scripts to directly get build attributes
# rather than generating $(OBJDIR)/llvm2ice.build_atts.
$(OBJDIR)/llvm2ice: $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(LLVM_LDFLAGS) -ldl \
-Wl,-rpath=$(abspath $(LIBCXX_INSTALL_PATH)/lib)
$@ --build-atts > $@.build_atts
# TODO: Be more precise than "*.h" here and elsewhere.
$(OBJS): $(OBJDIR)/%.o: src/%.cpp src/*.h src/*.def
......@@ -149,4 +166,7 @@ format-diff:
$(CLANG_FORMAT_DIFF) -p1 -style=LLVM -i
clean:
rm -rf llvm2ice *.o build/
rm -rf llvm2ice llvm2ice.build_atts *.o $(OBJDIR)
clean-all: clean
rm -rf build/
#!/usr/bin/env python2
import argparse
import os
import sys
from utils import shellcmd
def GetFileAttributes(Filename):
"""Returns the set of names contained in file named Filename.
"""
if not os.path.isfile(Filename):
raise RuntimeError("Can't open: %s" % Filename)
with open(Filename, 'r') as f:
return f.read().split()
def HasFileAttributes(Filename, Attributes):
"""Returns true if the set of names in Attributes also appear
in the set of names contained in file named Filename.
"""
return set(Attributes) <= set(GetFileAttributes(Filename))
def main():
"""Run the specified command only if attributes are defined.
Check if the fset of attributes (i.e. names), contained in FILE,
contains the attributes defined by --att=ATTRIBUTE arguments. If
so, runs in a shell the command defined by the remaining
arguments.
"""
argparser = argparse.ArgumentParser(
description=' ' + main.__doc__,
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
argparser.add_argument('file', metavar='FILE',
help='File defining attributes to check against.')
argparser.add_argument('--att', required=False, default=[],
action='append', metavar='ATTRIBUTE',
help='Attribute to check. May be repeated.')
argparser.add_argument('--echo-cmd', required=False,
action='store_true',
help='Trace the command before running.')
argparser.add_argument('--command', nargs=argparse.REMAINDER,
help='Command to run if attributes found.')
args = argparser.parse_args()
# Quit early if no command to run.
if not args.command:
raise RuntimeError("No command argument(s) specified for ifatts")
if HasFileAttributes(args.file, args.att):
stdout_result = shellcmd(args.command, echo=args.echo_cmd)
if not args.echo_cmd:
sys.stdout.write(stdout_result)
if __name__ == '__main__':
main()
sys.exit(0)
......@@ -18,6 +18,12 @@ namespace Ice {
namespace {
const char *TargetArchName[] = {
#define X(tag, str) str ,
TARGETARCH_TABLE
#undef X
};
// Show tags match between ICETYPE_TABLE and ICETYPE_PROPS_TABLE.
// Define a temporary set of enum values based on ICETYPE_TABLE
......@@ -116,6 +122,14 @@ const TypePropertyFields TypePropertiesTable[] = {
} // end anonymous namespace
const char *targetArchString(const TargetArch Arch) {
size_t Index = static_cast<size_t>(Arch);
if (Index < TargetArch_NUM)
return TargetArchName[Index];
llvm_unreachable("Invalid target arch for targetArchString");
return "???";
}
size_t typeWidthInBytes(Type Ty) {
size_t Index = static_cast<size_t>(Ty);
if (Index < IceType_NUM)
......
......@@ -15,6 +15,14 @@
#ifndef SUBZERO_SRC_ICETYPES_DEF
#define SUBZERO_SRC_ICETYPES_DEF
#define TARGETARCH_TABLE \
/* enum value, printable string */ \
X(Target_X8632, "x86-32") \
X(Target_X8664, "x86-64") \
X(Target_ARM32, "arm32") \
X(Target_ARM64, "arm64") \
//#define X(tag, str)
#define ICETYPE_TABLE \
/* enum value, size, align, # elts, element type, printable string */ \
/* (size and alignment in bytes) */ \
......
......@@ -28,12 +28,18 @@ enum Type {
};
enum TargetArch {
Target_X8632,
Target_X8664,
Target_ARM32,
Target_ARM64
#define X(tag, str) tag,
TARGETARCH_TABLE
#undef X
TargetArch_NUM
};
const char *targetArchString(TargetArch Arch);
inline Ostream &operator<<(Ostream &Stream, TargetArch Arch) {
return Stream << targetArchString(Arch);
}
enum OptLevel {
Opt_m1,
Opt_0,
......
......@@ -16,6 +16,7 @@
#include <fstream>
#include <iostream>
#include "llvm/ADT/STLExtras.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/CommandLine.h"
......@@ -164,12 +165,57 @@ static cl::opt<bool> AlwaysExitSuccess(
"exit-success", cl::desc("Exit with success status, even if errors found"),
cl::init(false));
static cl::opt<bool> GenerateBuildAtts(
"build-atts", cl::desc("Generate list of build attributes associated with "
"this executable."),
cl::init(false));
static int GetReturnValue(int Val) {
if (AlwaysExitSuccess)
return 0;
return Val;
}
static struct {
const char *FlagName;
int FlagValue;
} ConditionalBuildAttributes[] = {
{ "text_asm", ALLOW_TEXT_ASM },
{ "dump", ALLOW_DUMP },
{ "llvm_cl", ALLOW_LLVM_CL },
{ "llvm_ir", ALLOW_LLVM_IR },
{ "llvm_ir_as_input", ALLOW_LLVM_IR_AS_INPUT }
};
// Validates values of build attributes. Prints them to Stream if
// Stream is non-null.
static void ValidateAndGenerateBuildAttributes(raw_os_ostream *Stream) {
if (Stream)
*Stream << TargetArch << "\n";
for (size_t i = 0; i < array_lengthof(ConditionalBuildAttributes); ++i) {
switch (ConditionalBuildAttributes[i].FlagValue) {
case 0:
if (Stream)
*Stream << "no_" << ConditionalBuildAttributes[i].FlagName << "\n";
break;
case 1:
if (Stream)
*Stream << "allow_" << ConditionalBuildAttributes[i].FlagName << "\n";
break;
default: {
std::string Buffer;
raw_string_ostream StrBuf(Buffer);
StrBuf << "Flag " << ConditionalBuildAttributes[i].FlagName
<< " must be defined as 0/1. Found: "
<< ConditionalBuildAttributes[i].FlagValue;
report_fatal_error(StrBuf.str());
}
}
}
}
int main(int argc, char **argv) {
cl::ParseCommandLineOptions(argc, argv);
......@@ -185,6 +231,11 @@ int main(int argc, char **argv) {
raw_os_ostream *Os =
new raw_os_ostream(OutputFilename == "-" ? std::cout : Ofs);
Os->SetUnbuffered();
ValidateAndGenerateBuildAttributes(GenerateBuildAtts ? Os : nullptr);
if (GenerateBuildAtts)
return GetReturnValue(0);
std::ofstream Lfs;
if (LogFilename != "-") {
Lfs.open(LogFilename.c_str(), std::ofstream::out);
......@@ -212,6 +263,7 @@ int main(int argc, char **argv) {
Ice::GlobalContext Ctx(Ls, Os, VMask, TargetArch, OptLevel, TestPrefix,
Flags);
Ice::TimerMarker T(Ice::TimerStack::TT_szmain, &Ctx);
int ErrorStatus = 0;
......
# -*- 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 @@ import lit.formats
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 @@ pydir = os.path.join(bin_root, 'pydir')
# 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')
# 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
])))
# 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
])))
# 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
])))
llvm2icetoolatts = os.path.join(bin_root, 'llvm2ice.build_atts')
# Add build attributes of llvm2ice tool to the set of available features.
config.available_features.update(GetFileAttributes(llvm2icetoolatts))
# 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']
# 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')))
......
......@@ -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)
......
; 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
......
......@@ -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
......
......@@ -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.
......
; 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
......
......@@ -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)
......
......@@ -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
......
......@@ -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
......
; 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.
......
......@@ -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
......
; 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
......
; 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"
......
; 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 \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment