From badf5d54907a5a5e9224c44310f991a52379b4c1 Mon Sep 17 00:00:00 2001 From: Sylvain HENRY Date: Wed, 11 Nov 2015 12:32:08 +0100 Subject: [PATCH] Detect invalid foreign imports in bytecode compiler The bytecode compiler doesn't handle every foreign import calling convention. Instead of crashing during the generation of the foreign call, we display an error. Fix lint warnings Test Plan: prog014 ghci test added Reviewers: austin, hvr, bgamari Reviewed By: bgamari Subscribers: thomie Differential Revision: https://phabricator.haskell.org/D1458 GHC Trac Issues: #10462 --- compiler/ghci/ByteCodeGen.hs | 31 +++++++++++++++------ testsuite/tests/ghci/prog014/Makefile | 11 ++++++++ testsuite/tests/ghci/prog014/Primop.hs | 10 +++++++ testsuite/tests/ghci/prog014/dummy.c | 5 ++++ testsuite/tests/ghci/prog014/prog014.T | 8 ++++++ testsuite/tests/ghci/prog014/prog014.script | 2 ++ testsuite/tests/ghci/prog014/prog014.stderr | 2 ++ testsuite/tests/ghci/prog014/prog014.stdout | 0 8 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 testsuite/tests/ghci/prog014/Makefile create mode 100644 testsuite/tests/ghci/prog014/Primop.hs create mode 100644 testsuite/tests/ghci/prog014/dummy.c create mode 100644 testsuite/tests/ghci/prog014/prog014.T create mode 100644 testsuite/tests/ghci/prog014/prog014.script create mode 100644 testsuite/tests/ghci/prog014/prog014.stderr create mode 100644 testsuite/tests/ghci/prog014/prog014.stdout diff --git a/compiler/ghci/ByteCodeGen.hs b/compiler/ghci/ByteCodeGen.hs index b06d1a4b3f..11a8c6d098 100644 --- a/compiler/ghci/ByteCodeGen.hs +++ b/compiler/ghci/ByteCodeGen.hs @@ -598,7 +598,10 @@ schemeT d s p app -- Case 1 | Just (CCall ccall_spec) <- isFCallId_maybe fn - = generateCCall d s p ccall_spec fn args_r_to_l + = if isSupportedCConv ccall_spec + then generateCCall d s p ccall_spec fn args_r_to_l + else unsupportedCConvException + -- Case 2: Constructor application | Just con <- maybe_saturated_dcon, @@ -1508,13 +1511,25 @@ bcIdUnaryType x = case repType (idType x) of -- See bug #1257 unboxedTupleException :: a -unboxedTupleException - = throwGhcException - (ProgramError - ("Error: bytecode compiler can't handle unboxed tuples.\n"++ - " Possibly due to foreign import/export decls in source.\n"++ - " Workaround: use -fobject-code, or compile this module to .o separately.")) - +unboxedTupleException = throwGhcException (ProgramError + ("Error: bytecode compiler can't handle unboxed tuples.\n"++ + " Possibly due to foreign import/export decls in source.\n"++ + " Workaround: use -fobject-code, or compile this module to .o separately.")) + +-- | Indicate if the calling convention is supported +isSupportedCConv :: CCallSpec -> Bool +isSupportedCConv (CCallSpec _ cconv _) = case cconv of + CCallConv -> True -- we explicitly pattern match on every + StdCallConv -> True -- convention to ensure that a warning + PrimCallConv -> False -- is triggered when a new one is added + JavaScriptCallConv -> False + CApiConv -> False + +-- See bug #10462 +unsupportedCConvException :: a +unsupportedCConvException = throwGhcException (ProgramError + ("Error: bytecode compiler can't handle some foreign calling conventions\n"++ + " Workaround: use -fobject-code, or compile this module to .o separately.")) mkSLIDE :: Word16 -> Word -> OrdList BCInstr mkSLIDE n d diff --git a/testsuite/tests/ghci/prog014/Makefile b/testsuite/tests/ghci/prog014/Makefile new file mode 100644 index 0000000000..e053c15b63 --- /dev/null +++ b/testsuite/tests/ghci/prog014/Makefile @@ -0,0 +1,11 @@ +TOP=../../.. +include $(TOP)/mk/boilerplate.mk +include $(TOP)/mk/test.mk + +clean: + rm -f *.o *.hi + +prog014: clean + '$(TEST_HC)' $(TEST_HC_OPTS) -c dummy.c + +.PHONY: clean prog014 diff --git a/testsuite/tests/ghci/prog014/Primop.hs b/testsuite/tests/ghci/prog014/Primop.hs new file mode 100644 index 0000000000..40c1ade3ee --- /dev/null +++ b/testsuite/tests/ghci/prog014/Primop.hs @@ -0,0 +1,10 @@ +{-# LANGUAGE GHCForeignImportPrim, MagicHash, + UnliftedFFITypes, UnboxedTuples #-} + +import GHC.Exts + +foreign import prim "dummy" + dummy :: Word# -> Word# + +foreign import prim "dummy2" + dummy2 :: Any -> State# RealWorld -> (# State# RealWorld, Word# #) diff --git a/testsuite/tests/ghci/prog014/dummy.c b/testsuite/tests/ghci/prog014/dummy.c new file mode 100644 index 0000000000..b118cc8ee0 --- /dev/null +++ b/testsuite/tests/ghci/prog014/dummy.c @@ -0,0 +1,5 @@ +void dummy() { +} + +void dummy2() { +} diff --git a/testsuite/tests/ghci/prog014/prog014.T b/testsuite/tests/ghci/prog014/prog014.T new file mode 100644 index 0000000000..506c8b76e1 --- /dev/null +++ b/testsuite/tests/ghci/prog014/prog014.T @@ -0,0 +1,8 @@ +test('prog014', + [ extra_run_opts('dummy.o') + , pre_cmd('$MAKE -s --no-print-directory prog014') + , clean_cmd('rm -f dummy.o') + ], + ghci_script, + ['prog014.script']) + diff --git a/testsuite/tests/ghci/prog014/prog014.script b/testsuite/tests/ghci/prog014/prog014.script new file mode 100644 index 0000000000..0c8d96ef99 --- /dev/null +++ b/testsuite/tests/ghci/prog014/prog014.script @@ -0,0 +1,2 @@ +:set editor echo +:l Primop.hs diff --git a/testsuite/tests/ghci/prog014/prog014.stderr b/testsuite/tests/ghci/prog014/prog014.stderr new file mode 100644 index 0000000000..6d7b7fba37 --- /dev/null +++ b/testsuite/tests/ghci/prog014/prog014.stderr @@ -0,0 +1,2 @@ +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/prog014/prog014.stdout b/testsuite/tests/ghci/prog014/prog014.stdout new file mode 100644 index 0000000000..e69de29bb2 -- GitLab