Split external symbol prototypes (EF_) (Trac #11395)
authorSergei Trofimovich <slyfox@gentoo.org>
Tue, 8 Mar 2016 08:14:08 +0000 (08:14 +0000)
committerSergei Trofimovich <siarheit@google.com>
Tue, 8 Mar 2016 08:14:27 +0000 (08:14 +0000)
Before the patch both Cmm and C symbols were declared
with 'EF_' macro:

    #define EF_(f)    extern StgFunPtr f()

but for Cmm symbols we know exact prototypes.

The patch splits there prototypes in to:

    #define EFF_(f)   void f() /* See Note [External function prototypes] */
    #define EF_(f)    StgFunPtr f(void)

Cmm functions are 'EF_' (External Functions),
C functions are 'EFF_' (External Foreign Functions).

While at it changed external C function prototype
to return 'void' to workaround ghc bug on m68k.
Described in detail in Trac #11395.

This makes simple tests work on m68k-linux target!

Thanks to Michael Karcher for awesome analysis
happening in Trac #11395.

Signed-off-by: Sergei Trofimovich <siarheit@google.com>
Test Plan: ran "hello world" on m68k successfully

Reviewers: simonmar, austin, bgamari

Reviewed By: bgamari

Subscribers: thomie

Differential Revision: https://phabricator.haskell.org/D1975

GHC Trac Issues: #11395

compiler/cmm/CLabel.hs
compiler/cmm/PprC.hs
includes/Stg.h
includes/stg/MiscClosures.h

index 9304d66..15c5ff3 100644 (file)
@@ -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
index c269530..673ac2d 100644 (file)
@@ -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
index 899e685..a8ab5ca 100644 (file)
@@ -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.
 */
 
 
index 5f5e0d6..3fd4128 100644 (file)
@@ -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;