diff options
author | Michael Sloan <mgsloan@gmail.com> | 2019-03-13 23:04:41 -0700 |
---|---|---|
committer | Matthew Pickering <matthewtpickering@gmail.com> | 2019-05-16 16:32:55 +0100 |
commit | 8952584d467c40e0b06ad7a1bc1ad2198dd0882a (patch) | |
tree | 7960690a578bc471b8e3bea6b8b0eef1c69ceae4 | |
parent | a416ae26a2e45de3d9a76e94fc22aaa53e9e5b12 (diff) | |
download | haskell-8952584d467c40e0b06ad7a1bc1ad2198dd0882a.tar.gz |
Have GHCi use object code for UnboxedTuples modules #15454
The idea is to automatically enable -fobject-code for modules that use
UnboxedTuples, along with all the modules they depend on. When looking
into how to solve this, I was pleased to find that there was already
highly similar logic for enabling code generation when -fno-code is
specified but TemplateHaskell is used.
The state before this patch was that if you used unboxed tuples then you
had to enable `-fobject-code` globally rather than on a per module
basis.
-rw-r--r-- | compiler/main/GhcMake.hs | 65 | ||||
-rw-r--r-- | docs/users_guide/8.10.1-notes.rst | 7 | ||||
-rw-r--r-- | docs/users_guide/ghci.rst | 13 | ||||
-rw-r--r-- | testsuite/tests/ghci/prog014/prog014.stderr | 2 | ||||
-rw-r--r-- | testsuite/tests/ghci/should_fail/T14608.stderr | 3 | ||||
-rw-r--r-- | testsuite/tests/ghci/should_fail/all.T | 1 | ||||
-rw-r--r-- | testsuite/tests/ghci/should_run/T14608.hs (renamed from testsuite/tests/ghci/should_fail/T14608.hs) | 0 | ||||
-rw-r--r-- | testsuite/tests/ghci/should_run/T14608.script (renamed from testsuite/tests/ghci/should_fail/T14608.script) | 0 | ||||
-rw-r--r-- | testsuite/tests/ghci/should_run/all.T | 1 |
9 files changed, 71 insertions, 21 deletions
diff --git a/compiler/main/GhcMake.hs b/compiler/main/GhcMake.hs index fe4c9781e2..ac92f3b42b 100644 --- a/compiler/main/GhcMake.hs +++ b/compiler/main/GhcMake.hs @@ -1430,6 +1430,7 @@ upsweep_mod hsc_env mHscMessage old_hpt (stable_obj, stable_bco) summary mod_ind && (not (isObjectTarget prevailing_target) || not (isObjectTarget local_target)) && not (prevailing_target == HscNothing) + && not (prevailing_target == HscInterpreted) then prevailing_target else local_target @@ -1955,7 +1956,11 @@ downsweep hsc_env old_summaries excl_mods allow_dup_roots then enableCodeGenForTH (defaultObjectTarget (settings dflags)) map0 - else return map0 + else if hscTarget dflags == HscInterpreted + then enableCodeGenForUnboxedTuples + (defaultObjectTarget (settings dflags)) + map0 + else return map0 return $ concat $ nodeMapElts map1 where calcDeps = msDeps @@ -2034,7 +2039,50 @@ downsweep hsc_env old_summaries excl_mods allow_dup_roots enableCodeGenForTH :: HscTarget -> NodeMap [Either ErrMsg ModSummary] -> IO (NodeMap [Either ErrMsg ModSummary]) -enableCodeGenForTH target nodemap = +enableCodeGenForTH = + enableCodeGenWhen condition should_modify TFL_CurrentModule TFL_GhcSession + where + condition = isTemplateHaskellOrQQNonBoot + should_modify (ModSummary { ms_hspp_opts = dflags }) = + hscTarget dflags == HscNothing && + -- Don't enable codegen for TH on indefinite packages; we + -- can't compile anything anyway! See #16219. + not (isIndefinite dflags) + +-- | Update the every ModSummary that is depended on +-- by a module that needs unboxed tuples. We enable codegen to +-- the specified target, disable optimization and change the .hi +-- and .o file locations to be temporary files. +-- +-- This is used used in order to load code that uses unboxed tuples +-- into GHCi while still allowing some code to be interpreted. +enableCodeGenForUnboxedTuples :: HscTarget + -> NodeMap [Either ErrMsg ModSummary] + -> IO (NodeMap [Either ErrMsg ModSummary]) +enableCodeGenForUnboxedTuples = + enableCodeGenWhen condition should_modify TFL_GhcSession TFL_CurrentModule + where + condition ms = + xopt LangExt.UnboxedTuples (ms_hspp_opts ms) && + not (isBootSummary ms) + should_modify (ModSummary { ms_hspp_opts = dflags }) = + hscTarget dflags == HscInterpreted + +-- | Helper used to implement 'enableCodeGenForTH' and +-- 'enableCodeGenForUnboxedTuples'. In particular, this enables +-- unoptimized code generation for all modules that meet some +-- condition (first parameter), or are dependencies of those +-- modules. The second parameter is a condition to check before +-- marking modules for code generation. +enableCodeGenWhen + :: (ModSummary -> Bool) + -> (ModSummary -> Bool) + -> TempFileLifetime + -> TempFileLifetime + -> HscTarget + -> NodeMap [Either ErrMsg ModSummary] + -> IO (NodeMap [Either ErrMsg ModSummary]) +enableCodeGenWhen condition should_modify staticLife dynLife target nodemap = traverse (traverse (traverse enable_code_gen)) nodemap where enable_code_gen ms @@ -2042,18 +2090,15 @@ enableCodeGenForTH target nodemap = { ms_mod = ms_mod , ms_location = ms_location , ms_hsc_src = HsSrcFile - , ms_hspp_opts = dflags@DynFlags - {hscTarget = HscNothing} + , ms_hspp_opts = dflags } <- ms - -- Don't enable codegen for TH on indefinite packages; we - -- can't compile anything anyway! See #16219. - , not (isIndefinite dflags) + , should_modify ms , ms_mod `Set.member` needs_codegen_set = do let new_temp_file suf dynsuf = do - tn <- newTempName dflags TFL_CurrentModule suf + tn <- newTempName dflags staticLife suf let dyn_tn = tn -<.> dynsuf - addFilesToClean dflags TFL_GhcSession [dyn_tn] + addFilesToClean dflags dynLife [dyn_tn] return tn -- We don't want to create .o or .hi files unless we have been asked -- to by the user. But we need them, so we patch their locations in @@ -2076,7 +2121,7 @@ enableCodeGenForTH target nodemap = [ ms | mss <- Map.elems nodemap , Right ms <- mss - , isTemplateHaskellOrQQNonBoot ms + , condition ms ] -- find the set of all transitive dependencies of a list of modules. diff --git a/docs/users_guide/8.10.1-notes.rst b/docs/users_guide/8.10.1-notes.rst index a54783af5c..0b4f66bab4 100644 --- a/docs/users_guide/8.10.1-notes.rst +++ b/docs/users_guide/8.10.1-notes.rst @@ -67,6 +67,13 @@ Compiler `copyByteArray#` calls that were not optimized before, now will be. See :ghc-ticket:`16052`. +- When loading modules that use :extension:`UnboxedTuples` into GHCi, + it will now automatically enable `-fobject-code` for these modules + and all modules they depend on. Before this change, attempting to + load these modules into the interpreter would just fail, and the + only convenient workaround was to enable `-fobject-code` for all + modules. + Runtime system ~~~~~~~~~~~~~~ diff --git a/docs/users_guide/ghci.rst b/docs/users_guide/ghci.rst index d320419f3d..3df5510d74 100644 --- a/docs/users_guide/ghci.rst +++ b/docs/users_guide/ghci.rst @@ -3360,11 +3360,14 @@ The interpreter can't load modules with foreign export declarations! need to go fast, rather than interpreting them with optimisation turned on. -Unboxed tuples don't work with GHCi - That's right. You can always compile a module that uses unboxed - tuples and load it into GHCi, however. (Incidentally the previous - point, namely that :ghc-flag:`-O` is incompatible with GHCi, is because the - bytecode compiler can't deal with unboxed tuples). +Modules using unboxed tuples will automatically enable `-fobject-code` + The interpreter doesn't support unboxed tuples, so GHCi will + automatically compile these modules, and all modules they depend + on, to object code instead of bytecode. + + Incidentally, the previous point, that :ghc-flag:`-O` is + incompatible with GHCi, is because the bytecode compiler can't + deal with unboxed tuples. Concurrent threads don't carry on running when GHCi is waiting for input. This should work, as long as your GHCi was built with the diff --git a/testsuite/tests/ghci/prog014/prog014.stderr b/testsuite/tests/ghci/prog014/prog014.stderr deleted file mode 100644 index 6d7b7fba37..0000000000 --- a/testsuite/tests/ghci/prog014/prog014.stderr +++ /dev/null @@ -1,2 +0,0 @@ -Error: bytecode compiler can't handle some foreign calling conventions - Workaround: use -fobject-code, or compile this module to .o separately. diff --git a/testsuite/tests/ghci/should_fail/T14608.stderr b/testsuite/tests/ghci/should_fail/T14608.stderr deleted file mode 100644 index fe84063af2..0000000000 --- a/testsuite/tests/ghci/should_fail/T14608.stderr +++ /dev/null @@ -1,3 +0,0 @@ -Error: bytecode compiler can't handle unboxed tuples and sums. - Possibly due to foreign import/export decls in source. - Workaround: use -fobject-code, or compile this module to .o separately. diff --git a/testsuite/tests/ghci/should_fail/all.T b/testsuite/tests/ghci/should_fail/all.T index da01a98e3e..7205cfd930 100644 --- a/testsuite/tests/ghci/should_fail/all.T +++ b/testsuite/tests/ghci/should_fail/all.T @@ -1,6 +1,5 @@ test('T10549', [], ghci_script, ['T10549.script']) test('T10549a', [], ghci_script, ['T10549a.script']) -test('T14608', [], ghci_script, ['T14608.script']) test('T15055', normalise_version('ghc'), ghci_script, ['T15055.script']) test('T16013', [], ghci_script, ['T16013.script']) test('T16287', [], ghci_script, ['T16287.script']) diff --git a/testsuite/tests/ghci/should_fail/T14608.hs b/testsuite/tests/ghci/should_run/T14608.hs index 87d5617e5c..87d5617e5c 100644 --- a/testsuite/tests/ghci/should_fail/T14608.hs +++ b/testsuite/tests/ghci/should_run/T14608.hs diff --git a/testsuite/tests/ghci/should_fail/T14608.script b/testsuite/tests/ghci/should_run/T14608.script index c37a742461..c37a742461 100644 --- a/testsuite/tests/ghci/should_fail/T14608.script +++ b/testsuite/tests/ghci/should_run/T14608.script diff --git a/testsuite/tests/ghci/should_run/all.T b/testsuite/tests/ghci/should_run/all.T index 3335ad7ef2..a9e280ad06 100644 --- a/testsuite/tests/ghci/should_run/all.T +++ b/testsuite/tests/ghci/should_run/all.T @@ -36,6 +36,7 @@ test('T13456', [just_ghci, combined_output], ghci_script, ['T13456.script']) test('BinaryArray', normal, compile_and_run, ['']) test('T14125a', just_ghci, ghci_script, ['T14125a.script']) test('T13825-ghci',just_ghci, ghci_script, ['T13825-ghci.script']) +test('T14608', just_ghci, ghci_script, ['T14608.script']) test('T14963a', just_ghci, ghci_script, ['T14963a.script']) test('T14963b', just_ghci, ghci_script, ['T14963b.script']) test('T14963c', [extra_hc_opts("-fdefer-type-errors")], ghci_script, ['T14963c.script']) |