Commit a27b1e51 authored by krc's avatar krc

[project @ 2003-08-19 21:51:53 by krc]

Added support for testing generation and compilation of External Core
code. There are two new ways, which are not automatically enabled but can be
invoked from the command line: extcore and optextcore. Invoking either way will
test that ghc is able to generate External Core code for a given test, read the
code back in, and compile it to an executable that produces the expected output
for the test.

The External Core facility has a few limitations which result in certain tests
failing for the "extcore" way.
  - External Core can't represent foreign calls other than static C calls
  - External Core can't correctly represent literals resulting from a
    "foreign label" declaration
  - External Core can't represent declarations of datatypes with no
    constructors
The first of these was already known, and GHC panics if you tried to
generate External Core for a program containing such a call. The second two
cases were not handled properly before now; in another commit, I've changed the
code that emits External Core to panic if either of them arises. Previously,
GHC would happily generate External Core in either case, but would not be able
to compile the resulting code.

There are several tests that exhibit these limitations of External Core, so
they've had to be made "expected failures" when compiling in the extcore or
optextcore ways.
parent 28eab001
......@@ -12,6 +12,9 @@ config.compiler_always_flags = ['-no-recomp', '-dcore-lint']
config.compile_ways = ['normal', 'opt']
config.run_ways = ['normal', 'opt']
# ways that are not enabled by default, but can always be invoked explicitly
config.other_ways = ['extcore','optextcore']
if (ghc_with_native_codegen == 1):
config.compile_ways.append('optasm')
config.run_ways.append('optasm')
......@@ -28,6 +31,8 @@ config.way_flags = { 'normal' : [],
'optasm' : ['-O -fasm'],
'prof' : ['-O -prof -auto-all'],
'unreg' : ['-unreg'],
'ghci' : ['--interactive', '-v0']
'ghci' : ['--interactive', '-v0'],
'extcore' : ['-fext-core'],
'optextcore' : ['-O -fext-core']
}
......@@ -54,13 +54,13 @@ for opt,arg in opts:
config.only.append(arg)
if opt == '--way':
if (arg not in config.run_ways and arg not in config.compile_ways):
if (arg not in config.run_ways and arg not in config.compile_ways and arg not in config.other_ways):
sys.stderr.write("ERROR: requested way \'" +
arg + "\' does not exist\n")
sys.exit(1)
config.run_ways = filter(eq(arg), config.run_ways)
config.compile_ways = filter(eq(arg), config.compile_ways)
config.run_ways = filter(eq(arg), config.run_ways + config.other_ways)
config.compile_ways = filter(eq(arg), config.compile_ways + config.other_ways)
# -----------------------------------------------------------------------------
# The main dude
......
......@@ -437,6 +437,8 @@ def compile_and_run( name, way, extra_hc_opts ):
if way == 'ghci': # interpreted...
return interpreter_run( name, way, extra_hc_opts, 0, '' )
elif way == 'extcore' or way == 'optextcore' :
return extcore_run( name, way, extra_hc_opts, 0, '' )
else: # compiled...
result = simple_build( name, way, extra_hc_opts, 0, '', 1 )
......@@ -452,6 +454,8 @@ def multimod_compile_and_run( name, way, top_mod, extra_hc_opts ):
if way == 'ghci': # interpreted...
return interpreter_run( name, way, extra_hc_opts, 0, top_mod )
elif way == 'extcore' or way == 'optextcore' :
return extcore_run( name, way, extra_hc_opts, 0, top_mod )
else: # compiled...
result = simple_build( name, way, extra_hc_opts, 0, top_mod, 1 )
......@@ -651,6 +655,94 @@ def split_file(in_fn, delimiter, out1_fn, out2_fn):
out2.write(line)
line = infile.readline()
# -----------------------------------------------------------------------------
# Generate External Core for the given program, then compile the resulting Core
# and compare its output to the expected output
def extcore_run( name, way, extra_hc_opts, compile_only, top_mod ):
depsfilename = qualify(name, 'deps')
errname = add_suffix(name, 'comp.stderr')
qerrname = qualify(errname,'')
hcname = qualify(name, 'hc')
oname = qualify(name, 'o')
rm_no_fail( qerrname )
rm_no_fail( qualify(name, '') )
if (top_mod == ''):
srcname = add_suffix(name, 'hs')
else:
srcname = top_mod
qcorefilename = qualify(name, 'hcr')
corefilename = add_suffix(name, 'hcr')
rm_no_fail(qcorefilename)
# Generate External Core
if (top_mod == ''):
to_do = ' ' + srcname + ' '
else:
to_do = ' --make ' + top_mod + ' '
cmd = 'cd ' + testdir + " && '" \
+ config.compiler + "' " \
+ join(config.compiler_always_flags,' ') + ' ' \
+ join(config.way_flags[way],' ') + ' ' \
+ extra_hc_opts + ' ' \
+ testopts.extra_hc_opts \
+ to_do \
+ '>' + errname + ' 2>&1'
result = runCmd(cmd)
exit_code = result >> 8
if exit_code != 0:
if_verbose(1,'Compiling to External Core failed (status ' + `result` + ') errors were:')
if_verbose(1,open(qerrname).read())
return 'fail'
# Compile the resulting files -- if there's more than one module, we need to read the output
# of the previous compilation in order to find the dependencies
if (top_mod == ''):
to_compile = corefilename
else:
result = runCmd('grep Compiling ' + qerrname + ' | awk \'{print $4}\' > ' + depsfilename)
deps = open(depsfilename).read()
deplist = string.replace(deps, '\n',' ');
deplist2 = string.replace(deplist,'.lhs,', '.hcr');
to_compile = string.replace(deplist2,'.hs,', '.hcr');
flags = join(filter(lambda f: f != '-fext-core',config.way_flags[way]),' ')
cmd = 'cd ' + testdir + " && '" \
+ config.compiler + "' " \
+ join(config.compiler_always_flags,' ') + ' ' \
+ to_compile + ' ' \
+ extra_hc_opts + ' ' \
+ testopts.extra_hc_opts + ' ' \
+ flags \
+ ' -fglasgow-exts -o ' + name \
+ '>' + errname + ' 2>&1'
result = runCmd(cmd)
exit_code = result >> 8
if exit_code != 0:
if_verbose(1,'Compiling External Core file(s) failed (status ' + `result` + ') errors were:')
if_verbose(1,open(qerrname).read())
return 'fail'
# Clean up
rm_no_fail ( oname )
rm_no_fail ( hcname )
rm_no_fail ( qcorefilename )
rm_no_fail ( depsfilename )
return simple_run ( name, './'+name, testopts.extra_run_opts, 0 )
# -----------------------------------------------------------------------------
# Utils
......@@ -814,9 +906,10 @@ def findTFiles(path):
# Output a test summary to the specified file object
def summary(t, file):
file.write('\n')
file.write('OVERALL SUMMARY for test run started at ' \
+ t.start_time + '\n\n'\
+ t.start_time + '\n'\
+ string.rjust(`t.total_tests`, 8) \
+ ' total tests, which gave rise to\n' \
+ string.rjust(`t.total_test_cases`, 8) \
......
......@@ -8,7 +8,7 @@ def append(x,y):
return x + y
def concat(xs):
return reduce(append,xs)
return reduce(append,xs,[])
def chop(s):
if s[len(s)-1:] == '\n':
......
......@@ -9,15 +9,20 @@ setTestOpts(f)
test('cc001', normal, compile, [''])
test('cc002', normal, compile, [''])
test('cc003', normal, compile, [''])
test('cc004', normal, compile, [''])
test('cc005', normal, compile, [''])
# Non-static C call
test('cc004', expect_fail_for(['extcore','optextcore']), compile, [''])
# foreign label
test('cc005', expect_fail_for(['extcore','optextcore']), compile, [''])
# Missing:
# test('cc006', normal, compile, [''])
test('cc007', normal, compile, [''])
test('cc008', normal, compile, [''])
test('cc009', normal, compile, [''])
test('cc010', normal, compile, [''])
# foreign label
test('cc008', expect_fail_for(['extcore','optextcore']), compile, [''])
# foreign label
test('cc009', expect_fail_for(['extcore','optextcore']), compile, [''])
# Non-static C call
test('cc010', expect_fail_for(['extcore','optextcore']), compile, [''])
test('cc011', normal, compile, [''])
test('cc012', normal, compile, [''])
......@@ -9,7 +9,8 @@ def f( opts ):
setTestOpts(f)
test('fed001', normal, compile_and_run, [''])
# Doesn't work with External Core due to __labels
test('fed001', expect_fail_for(['extcore','optextcore']), compile_and_run, [''])
# Omit GHCi for these two, as they use foreign export
test('ffi001', omit_ways(['ghci']), compile_and_run, [''])
......@@ -28,13 +29,16 @@ test('ffi004', normal, compile_and_run, [''])
# instead of CPP symbols for the flag arguments to open().
test('ffi005', compose(skip, exit_code(3)), compile_and_run, [''])
test('ffi006', normal, compile_and_run, [''])
test('ffi007', normal, compile_and_run, [''])
test('ffi008', exit_code(1), compile_and_run, [''])
# ffi[006-009] don't work with External Core due to non-static-C foreign calls
test('ffi006', expect_fail_for(['extcore','optextcore']), compile_and_run, [''])
test('ffi007', expect_fail_for(['extcore','optextcore']), compile_and_run, [''])
test('ffi008', compose(expect_fail_for(['extcore','optextcore']), exit_code(1)), compile_and_run, [''])
# expect fail for way optasm, because the native code generator
# doesn't do -ffloat-store and gets different answers when
# optimisation is on.
test('ffi009', expect_fail_for(['optasm']), compile_and_run, [''])
test('ffi009', expect_fail_for(['optasm','extcore', 'optextcore']), compile_and_run, [''])
test('ffi010', normal, compile_and_run, [''])
# Doesn't work with External Core due to __labels
test('ffi010', expect_fail_for(['extcore','optextcore']), compile_and_run, [''])
......@@ -47,6 +47,7 @@ test('cg047', normal, compile_and_run, [''])
test('cg048', normal, compile_and_run, [''])
test('cg049', normal, compile_and_run, ['-funbox-strict-fields'])
test('cg050', normal, compile_and_run, [''])
test('cg051', exit_code(1), compile_and_run, [''])
# Doesn't work with External Core due to datatype declaration with no constructors
test('cg051', (compose (expect_fail_for(['extcore','optextcore']),exit_code(1))), compile_and_run, [''])
test('cg052', only_ways(['opt']), compile_and_run, ['-funbox-strict-fields'])
test('cg053', normal, compile_and_run, [''])
......@@ -14,7 +14,7 @@ test('hTell002', expect_fail_if_platform("i386-unknown-mingw32"), \
test('performGC001', normal, compile_and_run, [''])
# optimisation screws up this test because some of the traces get commoned up
test('trace001', omit_ways(['opt','optasm']), compile_and_run, [''])
test('trace001', omit_ways(['opt','optasm','optextcore']), compile_and_run, [''])
test('hGetBuf001', normal, compile_and_run, [''])
test('hPutBuf001', normal, compile_and_run, [''])
......
# uses a _casm_, so -fasm is out of the question
test('parser.prog002', omit_ways(['optasm']), multimod_compile, \
# non-static C call
test('parser.prog002', compose(expect_fail_for(['extcore','optextcore']),omit_ways(['optasm'])), multimod_compile, \
['Read013', '-fvia-C -v0 -fglasgow-exts -funfold-casms-in-hi-file'])
test('callback', omit_ways(['optasm','ghci']), multimod_compile_and_run, \
test('callback', omit_ways(['optasm','ghci','extcore','optextcore']), multimod_compile_and_run, \
['Main', '-fglasgow-exts -package lang -fvia-C'])
......@@ -23,13 +23,15 @@ test('tcrun017', normal, compile_and_run, [''])
test('tcrun018', normal, compile_and_run, [''])
test('tcrun019', normal, compile_and_run, [''])
test('tcrun020', normal, compile_and_run, [''])
test('tcrun021', normal, compile_and_run, ['-package data'])
# Doesn't work with External Core due to datatype with no constructors
test('tcrun021', expect_fail_for(['extcore','optextcore']), compile_and_run, ['-package data'])
test('tcrun022', normal, compile_and_run, ['-O -fglasgow-exts'])
test('tcrun023', normal, compile_and_run, ['-O'])
test('tcrun024', normal, compile_and_run, ['-O'])
test('tcrun025', normal, multimod_compile_and_run, ['tcrun025',''])
test('tcrun026', normal, compile_and_run, [''])
test('tcrun027', normal, compile_and_run, [''])
test('tcrun028', normal, compile_and_run, [''])
# Doesn't work with External Core due to datatype with no constructors
test('tcrun028', expect_fail_for(['extcore','optextcore']), compile_and_run, [''])
test('tcrun029', normal, compile_and_run, [''])
test('church', normal, compile_and_run, [''])
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