summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compiler/cmm/CLabel.hs8
-rw-r--r--compiler/cmm/PprC.hs5
-rw-r--r--includes/Stg.h20
-rw-r--r--includes/stg/MiscClosures.h15
4 files changed, 40 insertions, 8 deletions
diff --git a/compiler/cmm/CLabel.hs b/compiler/cmm/CLabel.hs
index 9304d66323..15c5ff3481 100644
--- a/compiler/cmm/CLabel.hs
+++ b/compiler/cmm/CLabel.hs
@@ -88,8 +88,9 @@ module CLabel (
mkForeignLabel,
addLabelSize,
- foreignLabelStdcallInfo,
+ foreignLabelStdcallInfo,
+ isForeignLabel,
mkCCLabel, mkCCSLabel,
DynamicLinkerLabelInfo(..),
@@ -492,6 +493,11 @@ addLabelSize (ForeignLabel str _ src fod) sz
addLabelSize label _
= label
+-- | Whether label is a non-haskell label (defined in C code)
+isForeignLabel :: CLabel -> Bool
+isForeignLabel (ForeignLabel _ _ _ _) = True
+isForeignLabel _lbl = False
+
-- | Get the label size field from a ForeignLabel
foreignLabelStdcallInfo :: CLabel -> Maybe Int
foreignLabelStdcallInfo (ForeignLabel _ info _ _) = info
diff --git a/compiler/cmm/PprC.hs b/compiler/cmm/PprC.hs
index c269530409..673ac2d5bd 100644
--- a/compiler/cmm/PprC.hs
+++ b/compiler/cmm/PprC.hs
@@ -264,7 +264,7 @@ pprStmt stmt =
-- We also need to cast mem primops to prevent conflicts with GCC
-- builtins (see bug #5967).
| Just _align <- machOpMemcpyishAlign op
- = (text ";EF_(" <> fn <> char ')' <> semi) $$
+ = (text ";EFF_(" <> fn <> char ')' <> semi) $$
pprForeignCall fn cconv hresults hargs
| otherwise
= pprCall fn cconv hresults hargs
@@ -1005,7 +1005,8 @@ pprExternDecl _in_srt lbl
hcat [ visibility, label_type lbl,
lparen, ppr lbl, text ");" ]
where
- label_type lbl | isCFunctionLabel lbl = text "F_"
+ label_type lbl | isForeignLabel lbl && isCFunctionLabel lbl = text "FF_"
+ | isCFunctionLabel lbl = text "F_"
| otherwise = text "I_"
visibility
diff --git a/includes/Stg.h b/includes/Stg.h
index 899e685635..a8ab5ca8e8 100644
--- a/includes/Stg.h
+++ b/includes/Stg.h
@@ -222,11 +222,21 @@ typedef StgFunPtr F_;
#define II_(X) static StgWordArray (X) GNU_ATTRIBUTE(aligned (8))
#define IF_(f) static StgFunPtr GNUC3_ATTRIBUTE(used) f(void)
#define FN_(f) StgFunPtr f(void)
-#define EF_(f) extern StgFunPtr f() /* See Note [External function prototypes] */
+#define EF_(f) StgFunPtr f(void) /* External Cmm functions */
+#define EFF_(f) void f() /* See Note [External function prototypes] */
-/* Note [External function prototypes] See Trac #8965
+/* Note [External function prototypes] See Trac #8965, #11395
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The external-function macro EF_(F) used to be defined as
+In generated C code we need to distinct between two types
+of external symbols:
+1. Cmm functions declared by 'EF_' macro (External Functions)
+2. C functions declared by 'EFF_' macro (External Foreign Functions)
+
+Cmm functions are simple as they are internal to GHC.
+
+C functions are trickier:
+
+The external-function macro EFF_(F) used to be defined as
extern StgFunPtr f(void)
i.e a function of zero arguments. On most platforms this doesn't
matter very much: calls to these functions put the parameters in the
@@ -249,6 +259,10 @@ unspecified argument list rather than a void argument list. This is no
worse for platforms that don't care either way, and allows a successful
bootstrap of GHC 7.8 on little-endian Linux ppc64 (which uses the ELFv2
ABI).
+
+Another case is m68k ABI where 'void*' return type is returned by 'a0'
+register while 'long' return type is returned by 'd0'. Thus we trick
+external prototype return neither of these types to workaround #11395.
*/
diff --git a/includes/stg/MiscClosures.h b/includes/stg/MiscClosures.h
index 5f5e0d6a1d..3fd412820b 100644
--- a/includes/stg/MiscClosures.h
+++ b/includes/stg/MiscClosures.h
@@ -490,8 +490,19 @@ extern StgWord RTS_VAR(CCS_LIST); /* registered CCS list */
extern StgWord CCS_SYSTEM[];
extern unsigned int RTS_VAR(CC_ID); /* global ids */
extern unsigned int RTS_VAR(CCS_ID);
-RTS_FUN_DECL(enterFunCCS);
-RTS_FUN_DECL(pushCostCentre);
+
+// Calls to these rts functions are generated directly
+// by codegen (see compiler/codeGen/StgCmmProf.hs)
+// and don't require (don't emit) forward declarations.
+//
+// In unregisterised mode (when building via .hc files)
+// the calls are ordinary C calls. Functions must be in
+// scope and must match prototype assumed by
+// 'compiler/codeGen/StgCmmProf.hs'
+// as opposed to real prototype declared in
+// 'includes/rts/prof/CCS.h'
+void enterFunCCS (void *reg, void *ccsfn);
+void * pushCostCentre (void *ccs, void *cc);
// Capability.c
extern unsigned int n_capabilities;