Commit 9738a9ea by Jim Stichnoth

Subzero: Update tests and build scripts for sandboxing.

Spec2k now runs sandboxed, using all filetypes (asm, iasm, obj). The new build-runtime.py script builds the native and sandboxed runtimes in build/runtime/ . The various Subzero driver scripts are updated to use that. Fixes a stack frame bug in sandboxed mode when the integrated assembler is used. The stack adjustment for setting up a function call wasn't being rolled back for the second emitIAS() pass, so stack variables passed as arguments to the callee were being copied from the wrong stack slot. Notes: 1. The hybrid Subzero/llc bisection debugging builds probably do not work as intended for -filetype=obj since the ELF emitter doesn't yet support -ffunction-sections. (This was also true for non-sandboxed hybrid builds.) 2. The cross tests have not yet been adapted for testing sandboxing. I'd prefer to first make progress on https://code.google.com/p/nativeclient/issues/detail?id=4085 in order to avoid blindly doubling the number of tests. BUG= https://code.google.com/p/nativeclient/issues/detail?id=4079 R=jvoung@chromium.org Review URL: https://codereview.chromium.org/944333002
parent c53f7a6a
...@@ -146,7 +146,7 @@ UNITTEST_OBJS = $(patsubst %.cpp, $(OBJDIR)/unittest/%.o, $(UNITTEST_SRCS)) ...@@ -146,7 +146,7 @@ UNITTEST_OBJS = $(patsubst %.cpp, $(OBJDIR)/unittest/%.o, $(UNITTEST_SRCS))
UNITTEST_LIB_OBJS = $(filter-out $(OBJDIR)/llvm2ice.o,$(OBJS)) UNITTEST_LIB_OBJS = $(filter-out $(OBJDIR)/llvm2ice.o,$(OBJS))
# Keep all the first target so it's the default. # Keep all the first target so it's the default.
all: $(OBJDIR)/llvm2ice make_symlink all: $(OBJDIR)/llvm2ice make_symlink runtime
# Creates symbolic link so that testing is easier. Also runs # Creates symbolic link so that testing is easier. Also runs
# llvm2ice to verify that the defines flags have valid values, # llvm2ice to verify that the defines flags have valid values,
...@@ -157,10 +157,8 @@ make_symlink: $(OBJDIR)/llvm2ice ...@@ -157,10 +157,8 @@ make_symlink: $(OBJDIR)/llvm2ice
@echo "Build Attributes:" @echo "Build Attributes:"
@$(OBJDIR)/llvm2ice --build-atts @$(OBJDIR)/llvm2ice --build-atts
.PHONY: all make_symlink bloat .PHONY: all make_symlink runtime bloat
# TODO(kschimpf): Fix python scripts to directly get build attributes
# rather than generating $(OBJDIR)/llvm2ice.build_atts.
$(OBJDIR)/llvm2ice: $(OBJS) $(OBJDIR)/llvm2ice: $(OBJS)
$(CXX) $(LDFLAGS) -o $@ $^ $(LLVM_LDFLAGS) \ $(CXX) $(LDFLAGS) -o $@ $^ $(LLVM_LDFLAGS) \
-Wl,-rpath=$(abspath $(LIBCXX_INSTALL_PATH)/lib) -Wl,-rpath=$(abspath $(LIBCXX_INSTALL_PATH)/lib)
...@@ -191,6 +189,19 @@ $(OBJDIR): ...@@ -191,6 +189,19 @@ $(OBJDIR):
$(OBJDIR)/unittest: $(OBJDIR) $(OBJDIR)/unittest: $(OBJDIR)
@mkdir -p $@ @mkdir -p $@
RT_SRC := runtime/szrt.c runtime/szrt_ll.ll
RT_OBJ := build/runtime/szrt_native_x8632.o build/runtime/szrt_sb_x8632.o
runtime: $(RT_OBJ)
# Use runtime.is.built so that build-runtime.py is invoked only once
# even in a parallel build.
.INTERMEDIATE: runtime.is.built
$(RT_OBJ): runtime.is.built
runtime.is.built: $(RT_SRC)
@echo ================ Building Subzero runtime ================
./pydir/build-runtime.py -v
check-lit: $(OBJDIR)/llvm2ice make_symlink check-lit: $(OBJDIR)/llvm2ice make_symlink
LLVM_BIN_PATH=$(LLVM_BIN_PATH) \ LLVM_BIN_PATH=$(LLVM_BIN_PATH) \
BINUTILS_BIN_PATH=$(BINUTILS_BIN_PATH) \ BINUTILS_BIN_PATH=$(BINUTILS_BIN_PATH) \
...@@ -200,10 +211,10 @@ check-unit: $(OBJDIR)/run_unittests ...@@ -200,10 +211,10 @@ check-unit: $(OBJDIR)/run_unittests
$(OBJDIR)/run_unittests $(OBJDIR)/run_unittests
ifdef MINIMAL ifdef MINIMAL
check: check-lit check-unit check: check-lit check-unit runtime
@echo "Crosstests ignored, minimal build" @echo "Crosstests ignored, minimal build"
else else
check: check-lit check-unit check: check-lit check-unit runtime
(cd crosstest; ./runtests.sh) (cd crosstest; ./runtests.sh)
endif endif
......
#!/usr/bin/env python2
import argparse
import os
import shutil
import tempfile
from utils import shellcmd
from utils import FindBaseNaCl
def Translate(ll_files, extra_args, obj, verbose):
"""Translate a set of input bitcode files into a single object file.
Use pnacl-llc to translate textual bitcode input ll_files into object file
obj, using extra_args as the architectural flags.
"""
shellcmd(['cat'] + ll_files + ['|',
'pnacl-llc',
'-externalize',
'-filetype=obj',
'-bitcode-format=llvm',
'-o', obj
] + extra_args, echo=verbose)
shellcmd(['objcopy',
'--localize-symbol=nacl_tp_tdb_offset',
'--localize-symbol=nacl_tp_tls_offset',
obj
], echo=verbose)
def main():
"""Build the Subzero runtime support library for all architectures.
"""
argparser = argparse.ArgumentParser(
description=' ' + main.__doc__,
formatter_class=argparse.RawTextHelpFormatter)
argparser.add_argument('--verbose', '-v', dest='verbose',
action='store_true',
help='Display some extra debugging output')
args = argparser.parse_args()
nacl_root = FindBaseNaCl()
os.environ['PATH'] = (
'{root}/toolchain/linux_x86/pnacl_newlib/bin{sep}' +
'{path}'
).format(root=nacl_root, sep=os.pathsep, path=os.environ['PATH'])
srcdir = (
'{root}/toolchain_build/src/subzero/runtime'
).format(root=nacl_root)
rtdir = (
'{root}/toolchain_build/src/subzero/build/runtime'
).format(root=nacl_root)
try:
tempdir = tempfile.mkdtemp()
if os.path.exists(rtdir) and not os.path.isdir(rtdir):
os.remove(rtdir)
if not os.path.exists(rtdir):
os.makedirs(rtdir)
# Compile srcdir/szrt.c to tempdir/szrt.ll
shellcmd(['pnacl-clang',
'-O2',
'-c',
'{srcdir}/szrt.c'.format(srcdir=srcdir),
'-o', '{dir}/szrt.tmp.bc'.format(dir=tempdir)
], echo=args.verbose)
shellcmd(['pnacl-opt',
'-pnacl-abi-simplify-preopt',
'-pnacl-abi-simplify-postopt',
'-pnaclabi-allow-debug-metadata',
'{dir}/szrt.tmp.bc'.format(dir=tempdir),
'-S',
'-o', '{dir}/szrt.ll'.format(dir=tempdir)
], echo=args.verbose)
ll_files = ['{dir}/szrt.ll'.format(dir=tempdir),
'{srcdir}/szrt_ll.ll'.format(srcdir=srcdir)]
# Translate tempdir/szrt.ll and srcdir/szrt_ll.ll to szrt_native_x8632.o
Translate(ll_files,
['-mtriple=i386-unknown-linux-gnu', '-mcpu=pentium4m'],
'{rtdir}/szrt_native_x8632.o'.format(rtdir=rtdir),
args.verbose)
# Translate tempdir/szrt.ll and srcdir/szrt_ll.ll to szrt_sb_x8632.o
Translate(ll_files,
['-mtriple=i686-none-nacl-gnu', '-mcpu=pentium4m'],
'{rtdir}/szrt_sb_x8632.o'.format(rtdir=rtdir),
args.verbose)
finally:
try:
shutil.rmtree(tempdir)
except OSError as exc:
if exc.errno != errno.ENOENT: # ENOENT - no such file or directory
raise # re-raise exception
if __name__ == '__main__':
main()
...@@ -24,8 +24,8 @@ if __name__ == '__main__': ...@@ -24,8 +24,8 @@ if __name__ == '__main__':
that calls the test functions with a variety of interesting inputs that calls the test functions with a variety of interesting inputs
and compares their results. and compares their results.
""" """
# arch_map maps a Subzero target string to an llvm-mc -arch string. # arch_map maps a Subzero target string to an llvm-mc -triple string.
arch_map = { 'x8632':'x86', 'x8664':'x86-64', 'arm':'arm' } arch_map = { 'x8632':'i686', 'x8664':'x86_64', 'arm':'armv7a' }
desc = 'Build a cross-test that compares Subzero and llc translation.' desc = 'Build a cross-test that compares Subzero and llc translation.'
argparser = argparse.ArgumentParser(description=desc) argparser = argparse.ArgumentParser(description=desc)
argparser.add_argument('--test', required=True, action='append', argparser.add_argument('--test', required=True, action='append',
...@@ -113,7 +113,7 @@ if __name__ == '__main__': ...@@ -113,7 +113,7 @@ if __name__ == '__main__':
bitcode]) bitcode])
if args.filetype != 'obj': if args.filetype != 'obj':
shellcmd(['llvm-mc', shellcmd(['llvm-mc',
'-arch=' + arch_map[args.target], '-triple=' + arch_map[args.target],
'-filetype=obj', '-filetype=obj',
'-o=' + obj_sz, '-o=' + obj_sz,
asm_sz]) asm_sz])
...@@ -144,12 +144,9 @@ if __name__ == '__main__': ...@@ -144,12 +144,9 @@ if __name__ == '__main__':
else: else:
objs.append(bitcode) objs.append(bitcode)
# Use 'clang szrt.c' -or- 'clang++ szrt.cpp'
objs.append(( objs.append((
'{root}/toolchain_build/src/subzero/runtime/szrt.{ext}' '{root}/toolchain_build/src/subzero/build/runtime/' +
).format(root=nacl_root, ext='c' if pure_c else 'cpp')) 'szrt_native_x8632.o'
objs.append((
'{root}/toolchain_build/src/subzero/runtime/szrt_i686.ll'
).format(root=nacl_root)) ).format(root=nacl_root))
linker = 'clang' if pure_c else 'clang++' linker = 'clang' if pure_c else 'clang++'
shellcmd([linker, '-g', '-m32', args.driver] + shellcmd([linker, '-g', '-m32', args.driver] +
......
...@@ -83,6 +83,8 @@ def AddOptionalArgs(argparser): ...@@ -83,6 +83,8 @@ def AddOptionalArgs(argparser):
argparser.add_argument('--filetype', default='iasm', dest='filetype', argparser.add_argument('--filetype', default='iasm', dest='filetype',
choices=['obj', 'asm', 'iasm'], choices=['obj', 'asm', 'iasm'],
help='Output file type. Default %(default)s.') help='Output file type. Default %(default)s.')
argparser.add_argument('--sandbox', dest='sandbox', action='store_true',
help='Enabled sandboxing in the translator')
argparser.add_argument('--verbose', '-v', dest='verbose', argparser.add_argument('--verbose', '-v', dest='verbose',
action='store_true', action='store_true',
help='Display some extra debugging output') help='Display some extra debugging output')
...@@ -150,10 +152,12 @@ def ProcessPexe(args, pexe, exe): ...@@ -150,10 +152,12 @@ def ProcessPexe(args, pexe, exe):
pexe = pipes.quote(pexe) pexe = pipes.quote(pexe)
nacl_root = FindBaseNaCl() nacl_root = FindBaseNaCl()
path_addition = (
'{root}/toolchain/linux_x86/pnacl_newlib/bin'
).format(root=nacl_root)
os.environ['PATH'] = ( os.environ['PATH'] = (
'{root}/toolchain/linux_x86/pnacl_newlib/bin{sep}' + '{dir}{sep}{path}'
'{path}' ).format(dir=path_addition, sep=os.pathsep, path=os.environ['PATH'])
).format(root=nacl_root, sep=os.pathsep, path=os.environ['PATH'])
obj_llc = pexe_base + '.llc.o' obj_llc = pexe_base + '.llc.o'
obj_sz = pexe_base + '.sz.o' obj_sz = pexe_base + '.sz.o'
asm_sz = pexe_base + '.sz.s' asm_sz = pexe_base + '.sz.s'
...@@ -168,9 +172,8 @@ def ProcessPexe(args, pexe, exe): ...@@ -168,9 +172,8 @@ def ProcessPexe(args, pexe, exe):
llvm2ice = ( llvm2ice = (
'{root}/toolchain_build/src/subzero/llvm2ice' '{root}/toolchain_build/src/subzero/llvm2ice'
).format(root=nacl_root) ).format(root=nacl_root)
llcbin = ( llcbin = 'llc'
'{root}/toolchain/linux_x86/pnacl_newlib/bin/llc' gold = 'le32-nacl-ld.gold'
).format(root=nacl_root)
opt_level = args.optlevel opt_level = args.optlevel
opt_level_map = { 'm1':'0', '-1':'0', '0':'0', '1':'1', '2':'2' } opt_level_map = { 'm1':'0', '-1':'0', '0':'0', '1':'1', '2':'2' }
hybrid = args.include or args.exclude hybrid = args.include or args.exclude
...@@ -180,19 +183,22 @@ def ProcessPexe(args, pexe, exe): ...@@ -180,19 +183,22 @@ def ProcessPexe(args, pexe, exe):
NewerThanOrNotThere(llcbin, obj_llc)): NewerThanOrNotThere(llcbin, obj_llc)):
# Only run pnacl-translate in hybrid mode. # Only run pnacl-translate in hybrid mode.
shellcmd(['pnacl-translate', shellcmd(['pnacl-translate',
'-split-module=1',
'-ffunction-sections', '-ffunction-sections',
'-fdata-sections', '-fdata-sections',
'-c', '-c',
'-arch', 'x86-32-linux', '-arch', 'x86-32' if args.sandbox else 'x86-32-linux',
'-O' + opt_level_map[opt_level], '-O' + opt_level_map[opt_level],
'--pnacl-driver-append-LLC_FLAGS_EXTRA=-externalize', '--pnacl-driver-append-LLC_FLAGS_EXTRA=-externalize',
'-o', obj_llc] + '-o', obj_llc] +
(['--pnacl-driver-verbose'] if args.verbose else []) +
args.llc_args + args.llc_args +
[pexe], [pexe],
echo=args.verbose) echo=args.verbose)
shellcmd(( if not args.sandbox:
'objcopy --redefine-sym _start=_user_start {obj}' shellcmd((
).format(obj=obj_llc), echo=args.verbose) 'objcopy --redefine-sym _start=_user_start {obj}'
).format(obj=obj_llc), echo=args.verbose)
# Generate llc syms file for consistency, even though it's not used. # Generate llc syms file for consistency, even though it's not used.
shellcmd(( shellcmd((
'nm {obj} | sed -n "s/.* [a-zA-Z] //p" > {sym}' 'nm {obj} | sed -n "s/.* [a-zA-Z] //p" > {sym}'
...@@ -210,16 +216,20 @@ def ProcessPexe(args, pexe, exe): ...@@ -210,16 +216,20 @@ def ProcessPexe(args, pexe, exe):
(['-externalize', (['-externalize',
'-ffunction-sections', '-ffunction-sections',
'-fdata-sections'] if hybrid else []) + '-fdata-sections'] if hybrid else []) +
(['-sandbox'] if args.sandbox else []) +
args.sz_args + args.sz_args +
[pexe], [pexe],
echo=args.verbose) echo=args.verbose)
if args.filetype != 'obj': if args.filetype != 'obj':
shellcmd(( shellcmd((
'llvm-mc -arch=x86 -filetype=obj -o {obj} {asm}' 'llvm-mc -triple={triple} -filetype=obj -o {obj} {asm}'
).format(asm=asm_sz, obj=obj_sz), echo=args.verbose) ).format(asm=asm_sz, obj=obj_sz,
shellcmd(( triple='i686-nacl' if args.sandbox else 'i686'),
'objcopy --redefine-sym _start=_user_start {obj}' echo=args.verbose)
).format(obj=obj_sz), echo=args.verbose) if not args.sandbox:
shellcmd((
'objcopy --redefine-sym _start=_user_start {obj}'
).format(obj=obj_sz), echo=args.verbose)
if hybrid: if hybrid:
shellcmd(( shellcmd((
'nm {obj} | sed -n "s/.* [a-zA-Z] //p" > {sym}' 'nm {obj} | sed -n "s/.* [a-zA-Z] //p" > {sym}'
...@@ -266,29 +276,46 @@ def ProcessPexe(args, pexe, exe): ...@@ -266,29 +276,46 @@ def ProcessPexe(args, pexe, exe):
'objcopy -w --localize-symbol="*" {partial}' 'objcopy -w --localize-symbol="*" {partial}'
).format(partial=obj_partial), echo=args.verbose) ).format(partial=obj_partial), echo=args.verbose)
shellcmd(( shellcmd((
'objcopy --globalize-symbol=_user_start {partial}' 'objcopy --globalize-symbol={start} {partial}'
).format(partial=obj_partial), echo=args.verbose) ).format(partial=obj_partial,
start='_start' if args.sandbox else '_user_start'),
echo=args.verbose)
# Run the linker regardless of hybrid mode. # Run the linker regardless of hybrid mode.
linker = ( linker = (
'{root}/../third_party/llvm-build/Release+Asserts/bin/clang' '{root}/../third_party/llvm-build/Release+Asserts/bin/clang'
).format(root=nacl_root) ).format(root=nacl_root)
shellcmd(( if args.sandbox:
'{ld} -m32 {partial} -o {exe} -O{opt_level} ' + linklib = ('{root}/toolchain/linux_x86/pnacl_newlib/translator/' +
# Keep the rest of this command line (except szrt.c) in sync 'x86-32/lib').format(root=nacl_root)
# with RunHostLD() in pnacl-translate.py. shellcmd((
'{root}/toolchain/linux_x86/pnacl_newlib/translator/x86-32-linux/lib/' + '{gold} -nostdlib --no-fix-cortex-a8 --eh-frame-hdr -z text ' +
'{{unsandboxed_irt,irt_random,irt_query_list}}.o ' + '--build-id --entry=__pnacl_start -static ' +
'{root}/toolchain_build/src/subzero/runtime/szrt.c ' + '{linklib}/crtbegin.o {partial} ' +
'{root}/toolchain_build/src/subzero/runtime/szrt_i686.ll ' + '{root}/toolchain_build/src/subzero/build/runtime/' +
'-lpthread -lrt' 'szrt_sb_x8632.o ' +
).format(ld=linker, partial=obj_partial, exe=exe, '{linklib}/libpnacl_irt_shim_dummy.a --start-group ' +
opt_level=opt_level_map[opt_level], root=nacl_root), '{linklib}/libgcc.a {linklib}/libcrt_platform.a ' +
echo=args.verbose) '--end-group {linklib}/crtend.o --undefined=_start ' +
'-o {exe}'
).format(gold=gold, linklib=linklib, partial=obj_partial, exe=exe,
root=nacl_root),
echo=args.verbose)
else:
shellcmd((
'{ld} -m32 {partial} -o {exe} ' +
# Keep the rest of this command line (except szrt_native_x8632.o) in
# sync with RunHostLD() in pnacl-translate.py.
'{root}/toolchain/linux_x86/pnacl_newlib/translator/x86-32-linux/' +
'lib/{{unsandboxed_irt,irt_random,irt_query_list}}.o ' +
'{root}/toolchain_build/src/subzero/build/runtime/' +
'szrt_native_x8632.o -lpthread -lrt'
).format(ld=linker, partial=obj_partial, exe=exe, root=nacl_root),
echo=args.verbose)
# Put the extra verbose printing at the end. # Put the extra verbose printing at the end.
if args.verbose: if args.verbose:
print 'PATH={path}'.format(path=os.environ['PATH']) print 'PATH: {path}'.format(path=path_addition)
if hybrid: if hybrid:
print 'include={regex}'.format(regex=re_include_str) print 'include={regex}'.format(regex=re_include_str)
print 'exclude={regex}'.format(regex=re_exclude_str) print 'exclude={regex}'.format(regex=re_exclude_str)
......
...@@ -14,6 +14,8 @@ def main(): ...@@ -14,6 +14,8 @@ def main():
Afterwards, the executables can be run from the Afterwards, the executables can be run from the
native_client/tests/spec2k/ directory as: native_client/tests/spec2k/ directory as:
'./run_all.sh RunBenchmarks SetupGccX8632Opt {train|ref} ...' './run_all.sh RunBenchmarks SetupGccX8632Opt {train|ref} ...'
-- or --
'./run_all.sh RunBenchmarks SetupPnaclX8632Opt {train|ref} ...'
""" """
nacl_root = FindBaseNaCl() nacl_root = FindBaseNaCl()
# Use the same default ordering as spec2k/run_all.sh. # Use the same default ordering as spec2k/run_all.sh.
...@@ -31,6 +33,7 @@ def main(): ...@@ -31,6 +33,7 @@ def main():
print 'Unknown component{s}: '.format(s='s' if len(bad) > 1 else '') + \ print 'Unknown component{s}: '.format(s='s' if len(bad) > 1 else '') + \
' '.join(x for x in bad) ' '.join(x for x in bad)
sys.exit(1) sys.exit(1)
suffix = 'pnacl.opt.x8632' if args.sandbox else 'gcc.opt.x8632'
for comp in args.comps: for comp in args.comps:
name = os.path.splitext(comp)[1] or comp name = os.path.splitext(comp)[1] or comp
if name[0] == '.': if name[0] == '.':
...@@ -40,8 +43,9 @@ def main(): ...@@ -40,8 +43,9 @@ def main():
'{name}.opt.stripped.pexe' '{name}.opt.stripped.pexe'
).format(root=nacl_root, comp=comp, name=name), ).format(root=nacl_root, comp=comp, name=name),
('{root}/tests/spec2k/{comp}/' + ('{root}/tests/spec2k/{comp}/' +
'{name}.gcc.opt.x8632' '{name}.{suffix}'
).format(root=nacl_root, comp=comp, name=name)) ).format(root=nacl_root, comp=comp, name=name,
suffix=suffix))
if __name__ == '__main__': if __name__ == '__main__':
main() main()
...@@ -7,17 +7,37 @@ ...@@ -7,17 +7,37 @@
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// This file implements the runtime helper routines that are needed by // This file implements wrappers for particular bitcode instructions
// Subzero. This needs to be compiled by some non-Subzero compiler. // that are too uncommon and complex for a particular target to bother
// implementing directly in Subzero target lowering. This needs to be
// compiled by some non-Subzero compiler.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
uint32_t cvtftoui32(float value) { return (uint32_t)value; } // TODO(stichnot): The various NaN cross tests try to map Subzero's
// undefined behavior to the same as llc's undefined behavior, as
// observed by the cross tests. This will have to be kept up to date
// with any future changes to llc, and may also have to be different
// for different targets. It would be better to find a more
// appropriate set of llc options when building the Subzero runtime.
//
// We test for NaN using "value==value" instead of using isnan(value)
// to avoid an external dependency on fpclassify().
uint32_t cvtftoui32(float value) {
if (value == value) // NaNaN
return (uint32_t)value;
return 0x80000000;
}
uint32_t cvtdtoui32(double value) { return (uint32_t)value; } uint32_t cvtdtoui32(double value) {
if (value == value) // NaNaN
return (uint32_t)value;
return 0x80000000;
}
int64_t cvtftosi64(float value) { return (int64_t)value; } int64_t cvtftosi64(float value) { return (int64_t)value; }
......
//===- subzero/runtime/szrt.cpp - Subzero runtime source ------------------===//
//
// The Subzero Code Generator
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file is a C++ wrapper to szrt.c since clang++ complains about
// .c files.
//
//===----------------------------------------------------------------------===//
extern "C" {
#include "szrt.c"
}
target triple = "i386-unknown-linux-gnu" ;;===- subzero/runtime/szrt_ll.ll - Subzero runtime source ----------------===;;
;;
;; The Subzero Code Generator
;;
;; This file is distributed under the University of Illinois Open Source
;; License. See LICENSE.TXT for details.
;;
;;===----------------------------------------------------------------------===;;
;;
;; This file implements wrappers for particular bitcode instructions that are
;; too uncommon and complex for a particular target to bother implementing
;; directly in Subzero target lowering. This needs to be compiled by some
;; non-Subzero compiler.
;;
;;===----------------------------------------------------------------------===;;
define <4 x float> @Sz_uitofp_v4i32(<4 x i32> %a) { define <4 x float> @Sz_uitofp_v4i32(<4 x i32> %a) {
entry: entry:
......
...@@ -901,8 +901,9 @@ class BundleEmitHelper { ...@@ -901,8 +901,9 @@ class BundleEmitHelper {
BundleEmitHelper &operator=(const BundleEmitHelper &) = delete; BundleEmitHelper &operator=(const BundleEmitHelper &) = delete;
public: public:
BundleEmitHelper(Assembler *Asm, const InstList &Insts) BundleEmitHelper(Assembler *Asm, TargetLowering *Target,
: Asm(Asm), End(Insts.end()), BundleLockStart(End), const InstList &Insts)
: Asm(Asm), Target(Target), End(Insts.end()), BundleLockStart(End),
BundleSize(1 << Asm->getBundleAlignLog2Bytes()), BundleSize(1 << Asm->getBundleAlignLog2Bytes()),
BundleMaskLo(BundleSize - 1), BundleMaskHi(~BundleMaskLo), BundleMaskLo(BundleSize - 1), BundleMaskHi(~BundleMaskLo),
SizeSnapshotPre(0), SizeSnapshotPost(0) {} SizeSnapshotPre(0), SizeSnapshotPost(0) {}
...@@ -948,6 +949,7 @@ public: ...@@ -948,6 +949,7 @@ public:
BundleLockStart = I; BundleLockStart = I;
SizeSnapshotPre = Asm->getBufferSize(); SizeSnapshotPre = Asm->getBufferSize();
Asm->setPreliminary(true); Asm->setPreliminary(true);
Target->snapshotEmitState();
assert(isInBundleLockRegion()); assert(isInBundleLockRegion());
} }
// Update bookkeeping when the bundle_unlock instruction is // Update bookkeeping when the bundle_unlock instruction is
...@@ -989,10 +991,12 @@ public: ...@@ -989,10 +991,12 @@ public:
assert(isInBundleLockRegion()); assert(isInBundleLockRegion());
Asm->setBufferSize(SizeSnapshotPre); Asm->setBufferSize(SizeSnapshotPre);
Asm->setPreliminary(false); Asm->setPreliminary(false);
Target->rollbackEmitState();
} }
private: private:
Assembler *const Asm; Assembler *const Asm;
TargetLowering *const Target;
// End is a sentinel value such that BundleLockStart==End implies // End is a sentinel value such that BundleLockStart==End implies
// that we are not in a bundle_lock region. // that we are not in a bundle_lock region.
const InstList::const_iterator End; const InstList::const_iterator End;
...@@ -1047,7 +1051,7 @@ void CfgNode::emitIAS(Cfg *Func) const { ...@@ -1047,7 +1051,7 @@ void CfgNode::emitIAS(Cfg *Func) const {
// of label bindings, label links, and relocation fixups. Instead, // of label bindings, label links, and relocation fixups. Instead,
// the first pass just disables all mutation of that state. // the first pass just disables all mutation of that state.
BundleEmitHelper Helper(Asm, Insts); BundleEmitHelper Helper(Asm, Func->getTarget(), Insts);
InstList::const_iterator End = Insts.end(); InstList::const_iterator End = Insts.end();
// Retrying indicates that we had to roll back to the bundle_lock // Retrying indicates that we had to roll back to the bundle_lock
// instruction to apply padding before the bundle_lock sequence. // instruction to apply padding before the bundle_lock sequence.
......
...@@ -105,7 +105,7 @@ TargetLowering::TargetLowering(Cfg *Func) ...@@ -105,7 +105,7 @@ TargetLowering::TargetLowering(Cfg *Func)
: Func(Func), Ctx(Func->getContext()), : Func(Func), Ctx(Func->getContext()),
RandomizeRegisterAllocation(CLRandomizeRegisterAllocation), RandomizeRegisterAllocation(CLRandomizeRegisterAllocation),
HasComputedFrame(false), CallsReturnsTwice(false), StackAdjustment(0), HasComputedFrame(false), CallsReturnsTwice(false), StackAdjustment(0),
Context() {} Context(), SnapshotStackAdjustment(0) {}
std::unique_ptr<Assembler> TargetLowering::createAssembler(TargetArch Target, std::unique_ptr<Assembler> TargetLowering::createAssembler(TargetArch Target,
Cfg *Func) { Cfg *Func) {
......
...@@ -192,6 +192,17 @@ public: ...@@ -192,6 +192,17 @@ public:
llvm::SmallVectorImpl<int32_t> &Permutation, llvm::SmallVectorImpl<int32_t> &Permutation,
const llvm::SmallBitVector &ExcludeRegisters) const = 0; const llvm::SmallBitVector &ExcludeRegisters) const = 0;
// Save/restore any mutable state for the situation where code
// emission needs multiple passes, such as sandboxing or relaxation.
// Subclasses may provide their own implementation, but should be
// sure to also call the parent class's methods.
virtual void snapshotEmitState() {
SnapshotStackAdjustment = StackAdjustment;
}
virtual void rollbackEmitState() {
StackAdjustment = SnapshotStackAdjustment;
}
virtual void emitVariable(const Variable *Var) const = 0; virtual void emitVariable(const Variable *Var) const = 0;
// Performs target-specific argument lowering. // Performs target-specific argument lowering.
...@@ -239,6 +250,9 @@ protected: ...@@ -239,6 +250,9 @@ protected:
// natural location, as arguments are pushed for a function call. // natural location, as arguments are pushed for a function call.
int32_t StackAdjustment; int32_t StackAdjustment;
LoweringContext Context; LoweringContext Context;
private:
int32_t SnapshotStackAdjustment;
}; };
// TargetDataLowering is used for "lowering" data including initializers // TargetDataLowering is used for "lowering" data including initializers
......
...@@ -4118,9 +4118,7 @@ TargetX8632::eliminateNextVectorSextInstruction(Variable *SignExtendedResult) { ...@@ -4118,9 +4118,7 @@ TargetX8632::eliminateNextVectorSextInstruction(Variable *SignExtendedResult) {
} }
} }
void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { void TargetX8632::lowerUnreachable(const InstUnreachable * /*Inst*/) { _ud2(); }
_ud2();
}
// Turn an i64 Phi instruction into a pair of i32 Phi instructions, to // Turn an i64 Phi instruction into a pair of i32 Phi instructions, to
// preserve integrity of liveness analysis. Undef values are also // preserve integrity of liveness analysis. Undef values are also
......
...@@ -230,3 +230,23 @@ entry: ...@@ -230,3 +230,23 @@ entry:
; CHECK: 40: {{.*}} nop ; CHECK: 40: {{.*}} nop
; CHECK: 5b: {{.*}} and [[REG]],0xffffffe0 ; CHECK: 5b: {{.*}} and [[REG]],0xffffffe0
; CHECK-NEXT: 5e: {{.*}} call [[REG]] ; CHECK-NEXT: 5e: {{.*}} call [[REG]]
; Stack adjustment state during an argument push sequence gets
; properly checkpointed and restored during the two passes, as
; observed by the stack adjustment for accessing stack-allocated
; variables.
define void @checkpoint_restore_stack_adjustment(i32 %arg) {
entry:
call void @call_target()
; bundle boundary
call void @checkpoint_restore_stack_adjustment(i32 %arg)
ret void
}
; CHECK-LABEL: checkpoint_restore_stack_adjustment
; CHECK: call
; CHECK: sub esp,0x10
; The address of %arg should be [esp+0x20], not [esp+0x30].
; CHECK-NEXT: mov [[REG:.*]],DWORD PTR [esp+0x20]
; CHECK-NEXT: mov DWORD PTR [esp],[[REG]]
; CHECK: call
; CHECK: add esp,0x10
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