Skip to content

Commit

Permalink
Revert "Simplify handling of ll file generations in test code (emscri…
Browse files Browse the repository at this point in the history
…pten-core#8378)"

This reverts commit 7d65c0c.
  • Loading branch information
VirtualTim authored May 23, 2019
1 parent e5d1d0b commit 843a700
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 90 deletions.
97 changes: 54 additions & 43 deletions tests/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,8 @@ def hardcode_arguments(self, filename, args):
js = open(filename).read()
create_test_file(filename, js.replace('run();', 'run(%s + Module["arguments"]);' % str(args)))

def prep_ll_file(self, output_file, input_file, force_recompile=False, build_ll_hook=None):
# force_recompile = force_recompile or os.path.getsize(filename + '.ll') > 50000
def prep_ll_run(self, filename, ll_file, force_recompile=False, build_ll_hook=None):
# force_recompile = force_recompile or os.path.getsize(filename + '.o.ll') > 50000
# If the file is big, recompile just to get ll_opts
# Recompiling just for dfe in ll_opts is too costly

Expand All @@ -446,44 +446,43 @@ def fix_target(ll_filename):
with open(ll_filename, 'w') as f:
f.write(contents)

output_obj = output_file + '.o'
output_ll = output_file + '.ll'

if force_recompile or build_ll_hook:
if input_file.endswith(('.bc', '.o')):
if input_file != output_obj:
shutil.copy(input_file, output_obj)
Building.llvm_dis(output_obj, output_ll)
if ll_file.endswith(('.bc', '.o')):
if ll_file != filename + '.o':
shutil.copy(ll_file, filename + '.o')
Building.llvm_dis(filename)
else:
shutil.copy(input_file, output_ll)
fix_target(output_ll)
shutil.copy(ll_file, filename + '.o.ll')
fix_target(filename + '.o.ll')

if build_ll_hook:
need_post = build_ll_hook(output_file)
Building.llvm_as(output_ll, output_obj)
shutil.move(output_ll, output_ll + '.pre') # for comparisons later
Building.llvm_dis(output_obj, output_ll)
need_post = build_ll_hook(filename)
Building.llvm_as(filename)
shutil.move(filename + '.o.ll', filename + '.o.ll.pre') # for comparisons later
Building.llvm_dis(filename)
if build_ll_hook and need_post:
build_ll_hook(output_file)
Building.llvm_as(output_ll, output_obj)
shutil.move(output_ll, output_ll + '.post') # for comparisons later
Building.llvm_dis(output_obj, output_ll)
build_ll_hook(filename)
Building.llvm_as(filename)
shutil.move(filename + '.o.ll', filename + '.o.ll.post') # for comparisons later
Building.llvm_dis(filename)

Building.llvm_as(output_ll, output_obj)
Building.llvm_as(filename)
else:
if input_file.endswith('.ll'):
safe_copy(input_file, output_ll)
fix_target(output_ll)
Building.llvm_as(output_ll, output_obj)
if ll_file.endswith('.ll'):
safe_copy(ll_file, filename + '.o.ll')
fix_target(filename + '.o.ll')
Building.llvm_as(filename)
else:
safe_copy(input_file, output_obj)

return output_obj
safe_copy(ll_file, filename + '.o')

def get_emcc_args(self):
# TODO(sbc): We should probably unify Building.COMPILER_TEST_OPTS and self.emcc_args
return self.serialize_settings() + self.emcc_args + Building.COMPILER_TEST_OPTS

# Generate JS from ll
def ll_to_js(self, filename):
Building.emcc(filename + '.o', self.get_emcc_args(), filename + '.o.js')

# Build JavaScript code from source code
def build(self, src, dirname, filename, main_file=None,
additional_files=[], libraries=[], includes=[], build_ll_hook=None,
Expand All @@ -502,7 +501,7 @@ def build(self, src, dirname, filename, main_file=None,
# copy whole directory, and use a specific main .cpp file
# (rmtree() fails on Windows if the current working directory is inside the tree.)
if os.getcwd().startswith(os.path.abspath(dirname)):
os.chdir(os.path.join(dirname, '..'))
os.chdir(os.path.join(dirname, '..'))
shutil.rmtree(dirname)
shutil.copytree(src, dirname)
shutil.move(os.path.join(dirname, main_file), filename)
Expand Down Expand Up @@ -540,10 +539,10 @@ def build(self, src, dirname, filename, main_file=None,
self.fail("Linkage error")

# Finalize
self.prep_ll_file(filename, object_file, build_ll_hook=build_ll_hook)
self.prep_ll_run(filename, object_file, build_ll_hook=build_ll_hook)

# BC => JS
Building.emcc(object_file, self.get_emcc_args(), object_file + '.js')
self.ll_to_js(filename)
else:
# "fast", new path: just call emcc and go straight to JS
all_files = [filename] + additional_files + libraries
Expand Down Expand Up @@ -975,23 +974,15 @@ def do_run(self, src, expected_output, args=[], output_nicerizer=None,
basename = 'src.c'
Building.COMPILER = to_cc(Building.COMPILER)

if no_build:
if src:
js_file = src
else:
js_file = basename + '.o.js'
else:
dirname = self.get_dir()
filename = os.path.join(dirname, basename)
self.build(src, dirname, filename, main_file=main_file,
additional_files=additional_files, libraries=libraries,
includes=includes,
dirname = self.get_dir()
filename = os.path.join(dirname, basename)
if not no_build:
self.build(src, dirname, filename, main_file=main_file, additional_files=additional_files, libraries=libraries, includes=includes,
build_ll_hook=build_ll_hook, post_build=post_build)
js_file = filename + '.o.js'
self.assertExists(js_file)

# Run in both JavaScript engines, if optimizing - significant differences there (typed arrays)
js_engines = self.filtered_js_engines(js_engines)
js_file = filename + '.o.js'
if len(js_engines) == 0:
self.skipTest('No JS engine present to run this test with. Check %s and the paths therein.' % EM_CONFIG)
if len(js_engines) > 1 and not self.use_all_engines:
Expand All @@ -1014,12 +1005,32 @@ def do_run(self, src, expected_output, args=[], output_nicerizer=None,
print('(test did not pass in JS engine: %s)' % engine)
raise

# shutil.rmtree(dirname) # TODO: leave no trace in memory. But for now nice for debugging

if self.save_JS:
global test_index
self.hardcode_arguments(js_file, args)
shutil.copyfile(js_file, os.path.join(TEMP_DIR, str(test_index) + '.js'))
test_index += 1

# No building - just process an existing .ll file (or .bc, which we turn into .ll)
def do_ll_run(self, ll_file, expected_output=None, args=[], js_engines=None,
output_nicerizer=None, force_recompile=False,
build_ll_hook=None, assert_returncode=None):
filename = os.path.join(self.get_dir(), 'src.cpp')

self.prep_ll_run(filename, ll_file, force_recompile, build_ll_hook)

self.ll_to_js(filename)

self.do_run(None,
expected_output,
args,
no_build=True,
js_engines=js_engines,
output_nicerizer=output_nicerizer,
assert_returncode=assert_returncode)

def get_freetype_library(self):
self.set_setting('DEAD_FUNCTIONS', self.get_setting('DEAD_FUNCTIONS') + ['_inflateEnd', '_inflate', '_inflateReset', '_inflateInit2_'])

Expand Down
78 changes: 33 additions & 45 deletions tests/test_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ def test_cube2hash(self):
for text, output in [('fleefl', '892BDB6FD3F62E863D63DA55851700FDE3ACF30204798CE9'),
('fleefl2', 'AA2CC5F96FC9D540CA24FDAF1F71E2942753DB83E8A81B61'),
('64bitisslow', '64D8470573635EC354FEE7B7F87C566FCAF1EFB491041670')]:
self.do_run('src.cpp.o.js', 'hash value: ' + output, [text], no_build=True)
self.do_run('', 'hash value: ' + output, [text], no_build=True)

def test_unaligned(self):
self.skipTest('LLVM marks the reads of s as fully aligned, making this test invalid')
Expand Down Expand Up @@ -592,17 +592,6 @@ def test_getgep(self):
# Generated code includes getelementptr (getelementptr, 0, 1), i.e., GEP as the first param to GEP
self.do_run_in_out_file_test('tests', 'core', 'test_getgep')

# No compiling from C/C++ - just process an existing .o/.ll/.bc file.
def do_run_object(self, obj_file, expected_output=None, **kwargs):
js_file = os.path.basename(obj_file) + '.js'
Building.emcc(obj_file, self.get_emcc_args(), js_file)
self.do_run(js_file, expected_output, no_build=True, **kwargs)

def do_ll_run(self, filename, expected_output=None, **kwargs):
output_base = os.path.basename(filename)
objfile = self.prep_ll_file(output_base, filename)
self.do_run_object(objfile, expected_output, **kwargs)

def test_multiply_defined_symbols(self):
create_test_file('a1.c', 'int f() { return 1; }')
create_test_file('a2.c', 'void x() {}')
Expand All @@ -628,7 +617,7 @@ def test_multiply_defined_symbols(self):

Building.link_to_object(['main.c.o', 'liba.a', 'libb.a'], 'all.o')

self.do_run_object('all.o', 'result: 1')
self.do_ll_run('all.o', 'result: 1')

def test_if(self):
self.do_run_in_out_file_test('tests', 'core', 'test_if')
Expand Down Expand Up @@ -1076,9 +1065,9 @@ def test_exceptions_3(self):
print('0')
self.do_run(src, 'Caught C string: a c string\nDone.', ['0'])
print('1')
self.do_run(None, 'Caught exception: std::exception\nDone.', ['1'], no_build=True)
self.do_run(src, 'Caught exception: std::exception\nDone.', ['1'], no_build=True)
print('2')
self.do_run(None, 'Caught exception: Hello\nDone.', ['2'], no_build=True)
self.do_run(src, 'Caught exception: Hello\nDone.', ['2'], no_build=True)

def test_exceptions_white_list(self):
self.set_setting('DISABLE_EXCEPTION_CATCHING', 2)
Expand Down Expand Up @@ -5280,11 +5269,9 @@ def test_constglobalunion(self):

def test_fannkuch(self):
results = [(1, 0), (2, 1), (3, 2), (4, 4), (5, 7), (6, 10), (7, 16), (8, 22)]
src = open(path_from_root('tests', 'fannkuch.cpp')).read()
self.build(src, self.get_dir(), 'fannkuch.cpp')
for i, j in results:
print(i, j)
self.do_run('fannkuch.cpp.o.js', 'Pfannkuchen(%d) = %d.' % (i, j), [str(i)], no_build=True)
src = open(path_from_root('tests', 'fannkuch.cpp')).read()
self.do_run(src, 'Pfannkuchen(%d) = %d.' % (i, j), [str(i)], no_build=i > 1)

def test_raytrace(self):
# TODO: Should we remove this test?
Expand All @@ -5300,19 +5287,17 @@ def test_fasta(self):
(50, '''GGCCGGGCGCGGTGGCTCACGCCTGTAATCCCAGCACTTTGGGAGGCCGAGGCGGGCGGA*TCACCTGAGGTCAGGAGTTCGAGACCAGCCTGGCCAACAT*cttBtatcatatgctaKggNcataaaSatgtaaaDcDRtBggDtctttataattcBgtcg**tactDtDagcctatttSVHtHttKtgtHMaSattgWaHKHttttagacatWatgtRgaaa**NtactMcSMtYtcMgRtacttctWBacgaa**agatactctgggcaacacacatacttctctcatgttgtttcttcggacctttcataacct**ttcctggcacatggttagctgcacatcacaggattgtaagggtctagtggttcagtgagc**ggaatatcattcgtcggtggtgttaatctatctcggtgtagcttataaatgcatccgtaa**gaatattatgtttatttgtcggtacgttcatggtagtggtgtcgccgatttagacgtaaa**ggcatgtatg*''')]

old = self.emcc_args
orig_src = open(path_from_root('tests', 'fasta.cpp')).read()

def test(extra_args):
self.emcc_args = old + extra_args
for precision in [0, 1, 2]:
self.set_setting('PRECISE_F32', precision)
for t in ['float', 'double']:
print(precision, t)
src = orig_src.replace('double', t)
self.build(src, self.get_dir(), 'fasta.cpp')
for arg, output in results:
self.do_run('fasta.cpp.o.js', output, [str(arg)], lambda x, err: x.replace('\n', '*'), no_build=True)
shutil.copyfile('fasta.cpp.o.js', '%d_%s.js' % (precision, t))
src = open(path_from_root('tests', 'fasta.cpp')).read().replace('double', t)
for i, j in results:
self.do_run(src, j, [str(i)], lambda x, err: x.replace('\n', '*'), no_build=i > 1)
shutil.copyfile('src.cpp.o.js', '%d_%s.js' % (precision, t))

test([])

Expand All @@ -5332,12 +5317,12 @@ def test_dlmalloc(self):

src = open(path_from_root('system', 'lib', 'dlmalloc.c')).read() + '\n\n\n' + open(path_from_root('tests', 'dlmalloc_test.c')).read()
self.do_run(src, '*1,0*', ['200', '1'])
self.do_run(None, '*400,0*', ['400', '400'], no_build=True)
self.do_run(src, '*400,0*', ['400', '400'], no_build=True)

# Linked version
src = open(path_from_root('tests', 'dlmalloc_test.c')).read()
self.do_run(src, '*1,0*', ['200', '1'])
self.do_run(None, '*400,0*', ['400', '400'], no_build=True)
self.do_run(src, '*400,0*', ['400', '400'], no_build=True)

# TODO: do this in other passes too, passing their opts into emcc
if self.emcc_args == []:
Expand All @@ -5346,8 +5331,8 @@ def test_dlmalloc(self):
try_delete('src.cpp.o.js')
run_process([PYTHON, EMCC, path_from_root('tests', 'dlmalloc_test.c'), '-s', 'TOTAL_MEMORY=128MB', '-o', 'src.cpp.o.js'], stdout=PIPE, stderr=self.stderr_redirect)

self.do_run(None, '*1,0*', ['200', '1'], no_build=True)
self.do_run(None, '*400,0*', ['400', '400'], no_build=True)
self.do_run('x', '*1,0*', ['200', '1'], no_build=True)
self.do_run('x', '*400,0*', ['400', '400'], no_build=True)

# The same for new and all its variants
src = open(path_from_root('tests', 'new.cpp')).read()
Expand Down Expand Up @@ -5604,7 +5589,7 @@ def test_freetype(self):
includes=[path_from_root('tests', 'freetype', 'include')])

print('[issue 324 case 3]')
self.do_run(None,
self.do_run('',
open(path_from_root('tests', 'freetype', 'ref_4.txt')).read(),
['font.ttf', 'ea', '40', '32', '0'],
no_build=True)
Expand Down Expand Up @@ -5836,12 +5821,12 @@ def test_python(self):
print('lto:', lto)
if lto == 1:
self.emcc_args += ['--llvm-lto', '1']
self.do_run_object(bitcode, pyoutput, args=['-S', '-c', pyscript])
self.do_ll_run(bitcode, pyoutput, args=['-S', '-c', pyscript])

def test_lifetime(self):
self.do_ll_run(path_from_root('tests', 'lifetime.ll'), 'hello, world!\n')
if '-O1' in self.emcc_args or '-O2' in self.emcc_args:
assert 'a18' not in open('lifetime.ll.o.js').read(), 'lifetime stuff and their vars must be culled'
assert 'a18' not in open('src.cpp.o.js').read(), 'lifetime stuff and their vars must be culled'

# Test cases in separate files. Note that these files may contain invalid .ll!
# They are only valid enough for us to read for test purposes, not for llvm-as
Expand Down Expand Up @@ -5995,12 +5980,12 @@ def test_autodebug_bitcode(self):

# Autodebug the code
def do_autodebug(filename):
Building.llvm_dis(filename + '.o', filename + '.ll')
output = run_process([PYTHON, AUTODEBUGGER, filename + '.ll', filename + '.auto.ll'], stdout=PIPE, stderr=self.stderr_redirect).stdout
Building.llvm_dis(filename)
output = run_process([PYTHON, AUTODEBUGGER, filename + '.o.ll', filename + '.o.ll.ll'], stdout=PIPE, stderr=self.stderr_redirect).stdout
assert 'Success.' in output, output
# rebuild .bc
# TODO: use code in do_autodebug_post for this
self.prep_ll_file(filename, filename + '.auto.ll', force_recompile=True)
self.prep_ll_run(filename, filename + '.o.ll.ll', force_recompile=True)

# Run a test that should work, generating some code
test_path = path_from_root('tests', 'core', 'test_structs')
Expand All @@ -6013,7 +5998,7 @@ def do_autodebug(filename):
do_autodebug(filename)

# Compare to each other, and to expected output
self.do_ll_run(filename + '.auto.ll', 'AD:-1,1')
self.do_ll_run(filename + '.o.ll.ll', 'AD:-1,1')

# Test using build_ll_hook
src = '''
Expand Down Expand Up @@ -6198,28 +6183,31 @@ def test_dead_functions(self):
}
'''

def test(expected, args=[], no_build=False):
self.do_run(src, expected, args=args, no_build=no_build)
return open('src.cpp.o.js').read()

# Sanity check that it works and the dead function is emitted
self.do_run(src, '*1*', args=['x'])
js = open('src.cpp.o.js').read()
js = test('*1*', ['x'])
if self.run_name in ['default', 'asm1', 'asm2g']:
assert 'function _unused($' in js
self.do_run(None, '*2*', no_build=True)
test('*2*', no_build=True)

# Kill off the dead function, and check a code path using it aborts
self.set_setting('DEAD_FUNCTIONS', ['_unused'])
self.do_run(src, '*2*')
self.do_run(None, 'abort(', args=['x'], no_build=True)
test('*2*')
test('abort(', args=['x'], no_build=True)

# Kill off a library function, check code aborts
self.set_setting('DEAD_FUNCTIONS', ['_printf'])
self.do_run(src, 'abort(')
self.do_run(None, 'abort(', args=['x'], no_build=True)
test('abort(')
test('abort(', args=['x'], no_build=True)

def test_response_file(self):
response_data = '-o %s/response_file.o.js %s' % (self.get_dir(), path_from_root('tests', 'hello_world.cpp'))
create_test_file('rsp_file', response_data.replace('\\', '\\\\'))
run_process([PYTHON, EMCC, "@rsp_file"] + self.emcc_args)
self.do_run('response_file.o.js', 'hello, world', no_build=True)
self.do_run('', 'hello, world', basename='response_file', no_build=True)

def test_linker_response_file(self):
objfile = 'response_file.o'
Expand All @@ -6230,7 +6218,7 @@ def test_linker_response_file(self):
response_data = objfile + ' --export=foo'
create_test_file('rsp_file', response_data.replace('\\', '\\\\'))
run_process([PYTHON, EMCC, "-Wl,@rsp_file", '-o', 'response_file.o.js'] + self.emcc_args)
self.do_run('response_file.o.js', 'hello, world', no_build=True)
self.do_run('', 'hello, world', basename='response_file', no_build=True)

def test_exported_response(self):
src = r'''
Expand Down
Loading

0 comments on commit 843a700

Please sign in to comment.