Detect invalid foreign imports in bytecode compiler
authorSylvain HENRY <hsyl20@gmail.com>
Wed, 11 Nov 2015 11:32:08 +0000 (12:32 +0100)
committerBen Gamari <ben@smart-cactus.org>
Wed, 11 Nov 2015 11:32:16 +0000 (12:32 +0100)
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
testsuite/tests/ghci/prog014/Makefile [new file with mode: 0644]
testsuite/tests/ghci/prog014/Primop.hs [new file with mode: 0644]
testsuite/tests/ghci/prog014/dummy.c [new file with mode: 0644]
testsuite/tests/ghci/prog014/prog014.T [new file with mode: 0644]
testsuite/tests/ghci/prog014/prog014.script [new file with mode: 0644]
testsuite/tests/ghci/prog014/prog014.stderr [new file with mode: 0644]
testsuite/tests/ghci/prog014/prog014.stdout [new file with mode: 0644]

index b06d1a4..11a8c6d 100644 (file)
@@ -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 (file)
index 0000000..e053c15
--- /dev/null
@@ -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 (file)
index 0000000..40c1ade
--- /dev/null
@@ -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 (file)
index 0000000..b118cc8
--- /dev/null
@@ -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 (file)
index 0000000..506c8b7
--- /dev/null
@@ -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 (file)
index 0000000..0c8d96e
--- /dev/null
@@ -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 (file)
index 0000000..6d7b7fb
--- /dev/null
@@ -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 (file)
index 0000000..e69de29