[project @ 2003-03-27 17:59:09 by sof]
authorsof <unknown>
Thu, 27 Mar 2003 17:59:12 +0000 (17:59 +0000)
committersof <unknown>
Thu, 27 Mar 2003 17:59:12 +0000 (17:59 +0000)
NCG support for f.e.d. stdcall -- Literal.MachLabels now optionally carry
the size (in bytes) of the stack frame it expects, if known. That just
so happens to match what stdcall labels need to be annotated with when
emitting them in the NCG..

ghc/compiler/basicTypes/Literal.lhs
ghc/compiler/coreSyn/MkExternalCore.lhs
ghc/compiler/deSugar/DsForeign.lhs
ghc/compiler/ghci/ByteCodeAsm.lhs
ghc/compiler/ghci/ByteCodeGen.lhs
ghc/compiler/ilxGen/IlxGen.lhs
ghc/compiler/nativeGen/StixPrim.lhs
ghc/compiler/typecheck/TcForeign.lhs

index b8e28d8..32815b9 100644 (file)
@@ -117,6 +117,11 @@ data Literal
        -- string argument is the name of a symbol.  This literal
        -- refers to the *address* of the label.
   | MachLabel   FastString             -- always an Addr#
+               (Maybe Int)             -- the size (in bytes) of the arguments
+                                       -- the label expects. Only applicable with
+                                       -- 'stdcall' labels.
+                                       -- Just x => "@<x>" will be appended to label
+                                       --           name when emitting asm.
 
        -- lit-lits only work for via-C compilation, hence they
        -- are deprecated.  The string is emitted verbatim into
@@ -139,7 +144,7 @@ instance Binary Literal where
     put_ bh (MachWord64 ag)   = do putByte bh 6; put_ bh ag
     put_ bh (MachFloat ah)    = do putByte bh 7; put_ bh ah
     put_ bh (MachDouble ai)   = do putByte bh 8; put_ bh ai
-    put_ bh (MachLabel aj)    = do putByte bh 9; put_ bh aj
+    put_ bh (MachLabel aj mb) = do putByte bh 9; put_ bh aj ; put_ bh mb
     put_ bh (MachLitLit ak _) = do putByte bh 10; put_ bh ak
     get bh = do
            h <- getByte bh
@@ -173,7 +178,8 @@ instance Binary Literal where
                    return (MachDouble ai)
              9 -> do
                    aj <- get bh
-                   return (MachLabel aj)
+                   mb <- get bh
+                   return (MachLabel aj mb)
              10 -> do
                    ak <- get bh
                    return (MachLitLit ak (error "MachLitLit: no type"))
@@ -319,7 +325,7 @@ literalType (MachInt64  _)    = int64PrimTy
 literalType (MachWord64  _)      = word64PrimTy
 literalType (MachFloat _)        = floatPrimTy
 literalType (MachDouble _)       = doublePrimTy
-literalType (MachLabel _)        = addrPrimTy
+literalType (MachLabel _ _)      = addrPrimTy
 literalType (MachLitLit _ ty)    = ty
 \end{code}
 
@@ -335,7 +341,7 @@ literalPrimRep (MachInt64 _)          = Int64Rep
 literalPrimRep (MachWord64 _)    = Word64Rep
 literalPrimRep (MachFloat _)     = FloatRep
 literalPrimRep (MachDouble _)    = DoubleRep
-literalPrimRep (MachLabel _)     = AddrRep
+literalPrimRep (MachLabel _ _)   = AddrRep
 literalPrimRep (MachLitLit _ ty)  = typePrimRep ty
 \end{code}
 
@@ -352,7 +358,7 @@ cmpLit (MachInt64     a)   (MachInt64          b)   = a `compare` b
 cmpLit (MachWord64    a)   (MachWord64    b)   = a `compare` b
 cmpLit (MachFloat     a)   (MachFloat     b)   = a `compare` b
 cmpLit (MachDouble    a)   (MachDouble    b)   = a `compare` b
-cmpLit (MachLabel     a)   (MachLabel      b)   = a `compare` b
+cmpLit (MachLabel     a _) (MachLabel      b _) = a `compare` b
 cmpLit (MachLitLit    a b) (MachLitLit    c d)  = (a `compare` c) `thenCmp` (b `tcCmpType` d)
 cmpLit lit1               lit2                 | litTag lit1 <# litTag lit2 = LT
                                                | otherwise                    = GT
@@ -366,8 +372,8 @@ litTag (MachInt64     _)   = _ILIT(6)
 litTag (MachWord64    _)   = _ILIT(7)
 litTag (MachFloat     _)   = _ILIT(8)
 litTag (MachDouble    _)   = _ILIT(9)
-litTag (MachLabel     _)   = _ILIT(10)
-litTag (MachLitLit    _ _) = _ILIT(11)
+litTag (MachLabel   _ _)   = _ILIT(10)
+litTag (MachLitLit  _ _)   = _ILIT(11)
 \end{code}
 
        Printing
@@ -413,8 +419,12 @@ pprLit lit
       MachAddr p | code_style -> ptext SLIT("(void*)") <> integer p
                 | otherwise  -> ptext SLIT("__addr") <+> integer p
 
-      MachLabel l | code_style -> ptext SLIT("(&") <> ftext l <> char ')'
-                 | otherwise  -> ptext SLIT("__label") <+> pprHsString l
+      MachLabel l mb
+         | code_style -> ptext SLIT("(&") <> ftext l <> char ')'
+        | otherwise  -> ptext SLIT("__label") <+> 
+            case mb of
+              Nothing -> pprHsString l
+              Just x  -> doubleQuotes (text (unpackFS l ++ '@':show x))
 
       MachLitLit s ty | code_style  -> ftext s
                      | otherwise   -> parens (hsep [ptext SLIT("__litlit"), 
@@ -465,7 +475,7 @@ hashLiteral (MachWord i)    = hashInteger i
 hashLiteral (MachWord64 i)     = hashInteger i
 hashLiteral (MachFloat r)      = hashRational r
 hashLiteral (MachDouble r)     = hashRational r
-hashLiteral (MachLabel s)       = hashFS s
+hashLiteral (MachLabel s _)     = hashFS s
 hashLiteral (MachLitLit s _)    = hashFS s
 
 hashRational :: Rational -> Int
index ee9064c..eb3e076 100644 (file)
@@ -135,7 +135,7 @@ make_exp (Var v) =
     FCallId (CCall (CCallSpec (StaticTarget nm) _ _)) -> C.External (unpackFS nm) (make_ty (varType v))
     FCallId _ -> error "MkExternalCore died: can't handle non-static-C foreign call"
     _ -> C.Var (make_var_qid (Var.varName v))
-make_exp (Lit (l@(MachLabel s))) = C.External (unpackFS s) (make_ty (literalType l))
+make_exp (Lit (l@(MachLabel s _))) = C.External (unpackFS s) (make_ty (literalType l))
 make_exp (Lit l) = C.Lit (make_lit l)
 make_exp (App e (Type t)) = C.Appt (make_exp e) (make_ty t)
 make_exp (App e1 e2) = C.App (make_exp e1) (make_exp e2)
index 676519e..9cefb05 100644 (file)
@@ -24,7 +24,7 @@ import Literal                ( Literal(..) )
 import Module          ( moduleString )
 import Name            ( getOccString, NamedThing(..) )
 import OccName         ( encodeFS )
-import Type            ( repType, eqType )
+import Type            ( repType, eqType, typePrimRep )
 import TcType          ( Type, mkFunTys, mkForAllTys, mkTyConApp,
                          mkFunTy, tcSplitTyConApp_maybe, 
                          tcSplitForAllTys, tcSplitFunTys, tcTyConAppArgs,
@@ -39,7 +39,8 @@ import ForeignCall    ( ForeignCall(..), CCallSpec(..),
                        )
 import CStrings                ( CLabelString )
 import TysWiredIn      ( unitTy, stablePtrTyCon )
-import TysPrim         ( addrPrimTy )
+import TysPrim         ( addrPrimTy, mkStablePtrPrimTy, alphaTy )
+import PrimRep          ( getPrimRepSizeInBytes )
 import PrelNames       ( hasKey, ioTyConKey, newStablePtrName, bindIOName )
 import BasicTypes      ( Activation( NeverActive ) )
 import Outputable
@@ -84,7 +85,7 @@ dsForeigns fos
   combine (ForeignStubs acc_h acc_c acc_hdrs acc_feb, acc_f) 
          (ForeignExport id _ (CExport (CExportStatic ext_nm cconv)) depr loc)
     = dsFExport id (idType id) 
-               ext_nm cconv False                 `thenDs` \(h, c) ->
+               ext_nm cconv False                 `thenDs` \(h, c, _) ->
       warnDepr depr loc                                   `thenDs` \_              ->
       returnDs (ForeignStubs (h $$ acc_h) (c $$ acc_c) acc_hdrs (id:acc_feb), 
                acc_f)
@@ -153,7 +154,7 @@ dsCImport id (CLabel cid) _ _ no_hdrs
    returnDs ([(setImpInline no_hdrs id, rhs)], empty, empty)
  where
    (resTy, foRhs) = resultWrapper (idType id)
-   rhs           = foRhs (mkLit (MachLabel cid))
+   rhs           = foRhs (mkLit (MachLabel cid Nothing))
 dsCImport id (CFunction target) cconv safety no_hdrs
   = dsFCall id (CCall (CCallSpec target cconv safety)) no_hdrs
 dsCImport id CWrapper cconv _ _
@@ -256,6 +257,7 @@ dsFExport :: Id                     -- Either the exported Id,
                                --         the first argument's stable pointer
          -> DsM ( SDoc         -- contents of Module_stub.h
                 , SDoc         -- contents of Module_stub.c
+                , [Type]       -- arguments expected by stub function.
                 )
 
 dsFExport fn_id ty ext_name cconv isDyn
@@ -285,13 +287,10 @@ dsFExport fn_id ty ext_name cconv isDyn
      )
                                        `thenDs` \ (res_ty,             -- t
                                                    is_IO_res_ty) ->    -- Bool
-     let
-       (h_stub, c_stub) 
-           = mkFExportCBits ext_name 
-                            (if isDyn then Nothing else Just fn_id)
-                            fe_arg_tys res_ty is_IO_res_ty cconv
-     in
-     returnDs (h_stub, c_stub)
+     returnDs $
+       mkFExportCBits ext_name 
+                      (if isDyn then Nothing else Just fn_id)
+                      fe_arg_tys res_ty is_IO_res_ty cconv
 \end{code}
 
 @foreign export dynamic@ lets you dress up Haskell IO actions
@@ -327,7 +326,7 @@ dsFExportDynamic id cconv
         -- hack: need to get at the name of the C stub we're about to generate.
        fe_nm      = mkFastString (moduleString mod_name ++ "_" ++ toCName fe_id)
      in
-     dsFExport id export_ty fe_nm cconv True   `thenDs` \ (h_code, c_code) ->
+     dsFExport id export_ty fe_nm cconv True   `thenDs` \ (h_code, c_code, stub_args) ->
      newSysLocalDs arg_ty                      `thenDs` \ cback ->
      dsLookupGlobalId newStablePtrName `thenDs` \ newStablePtrId ->
      let
@@ -353,11 +352,16 @@ dsFExportDynamic id cconv
        -}
       adj_args      = [ mkIntLitInt (ccallConvToInt cconv)
                      , Var stbl_value
-                     , mkLit (MachLabel fe_nm)
+                     , mkLit (MachLabel fe_nm mb_sz_args)
                      ]
         -- name of external entry point providing these services.
        -- (probably in the RTS.) 
       adjustor     = FSLIT("createAdjustor")
+      
+      mb_sz_args =
+        case cconv of
+         StdCallConv -> Just (sum (map (getPrimRepSizeInBytes . typePrimRep) stub_args))
+         _ -> Nothing
      in
      dsCCall adjustor adj_args PlayRisky False io_res_ty       `thenDs` \ ccall_adj ->
        -- PlayRisky: the adjustor doesn't allocate in the Haskell heap or do a callback
@@ -403,9 +407,9 @@ mkFExportCBits :: FastString
               -> Type 
                -> Bool         -- True <=> returns an IO type
               -> CCallConv 
-              -> (SDoc, SDoc)
+              -> (SDoc, SDoc, [Type])
 mkFExportCBits c_nm maybe_target arg_htys res_hty is_IO_res_ty cc 
- = (header_bits, c_bits)
+ = (header_bits, c_bits, all_arg_tys)
  where
   -- Create up types and names for the real args
   arg_cnames, arg_ctys :: [SDoc]
@@ -414,18 +418,21 @@ mkFExportCBits c_nm maybe_target arg_htys res_hty is_IO_res_ty cc
 
   -- and also for auxiliary ones; the stable ptr in the dynamic case, and
   -- a slot for the dummy return address in the dynamic + ccall case
-  extra_cnames_and_ctys
+  extra_cnames_and_tys
      = case maybe_target of
-          Nothing -> [(text "the_stableptr", text "StgStablePtr")]
+          Nothing -> [((text "the_stableptr", text "StgStablePtr"), mkStablePtrPrimTy alphaTy)]
           other   -> []
        ++
        case (maybe_target, cc) of
-          (Nothing, CCallConv) -> [(text "original_return_addr", text "void*")]
+          (Nothing, CCallConv) -> [((text "original_return_addr", text "void*"), addrPrimTy)]
           other                -> []
 
   all_cnames_and_ctys :: [(SDoc, SDoc)]
   all_cnames_and_ctys 
-     = extra_cnames_and_ctys ++ zip arg_cnames arg_ctys
+     = map fst extra_cnames_and_tys ++ zip arg_cnames arg_ctys
+
+  all_arg_tys
+     = map snd extra_cnames_and_tys ++ arg_htys
 
   -- stuff to do with the return type of the C function
   res_hty_is_unit = res_hty `eqType` unitTy    -- Look through any newtypes
index 890b424..599eb1c 100644 (file)
@@ -343,15 +343,15 @@ mkBits findLabel st proto_insns
           = do st_I1 <- addToSS st_I0 (getName dcon)
                return (sizeSS st_I0, (st_i0,st_l0,st_p0,st_I1))
 
-       literal st (MachLabel fs)  = litlabel st fs
-       literal st (MachWord w)    = int st (fromIntegral w)
-       literal st (MachInt j)     = int st (fromIntegral j)
-       literal st (MachFloat r)   = float st (fromRational r)
-       literal st (MachDouble r)  = double st (fromRational r)
-       literal st (MachChar c)    = int st c
-       literal st (MachInt64 ii)  = int64 st (fromIntegral ii)
-       literal st (MachWord64 ii) = int64 st (fromIntegral ii)
-       literal st other           = pprPanic "ByteCodeLink.literal" (ppr other)
+       literal st (MachLabel fs _) = litlabel st fs
+       literal st (MachWord w)     = int st (fromIntegral w)
+       literal st (MachInt j)      = int st (fromIntegral j)
+       literal st (MachFloat r)    = float st (fromRational r)
+       literal st (MachDouble r)   = double st (fromRational r)
+       literal st (MachChar c)     = int st c
+       literal st (MachInt64 ii)   = int64 st (fromIntegral ii)
+       literal st (MachWord64 ii)  = int64 st (fromIntegral ii)
+       literal st other            = pprPanic "ByteCodeLink.literal" (ppr other)
 
 
 push_alts WordRep   = bci_PUSH_ALTS_N
index 4ff021d..b0234f0 100644 (file)
@@ -1109,13 +1109,13 @@ pushAtom d p (AnnVar v)
 
 pushAtom d p (AnnLit lit)
    = case lit of
-        MachLabel fs -> code CodePtrRep
-        MachWord w   -> code WordRep
-        MachInt i    -> code IntRep
-        MachFloat r  -> code FloatRep
-        MachDouble r -> code DoubleRep
-        MachChar c   -> code CharRep
-        MachStr s    -> pushStr s
+        MachLabel fs _ -> code CodePtrRep
+        MachWord w     -> code WordRep
+        MachInt i      -> code IntRep
+        MachFloat r    -> code FloatRep
+        MachDouble r   -> code DoubleRep
+        MachChar c     -> code CharRep
+        MachStr s      -> pushStr s
      where
         code rep
            = let size_host_words = getPrimRepSize rep
index 9c71ab1..2a3eb34 100644 (file)
@@ -1121,7 +1121,7 @@ pushLit env (MachFloat f)  = text "ldc.r4" <+> rational f
 pushLit env (MachDouble f) = text "ldc.r8" <+> rational f
 pushLit env (MachLitLit _ _) = trace "WARNING: Cannot compile MachLitLit to ILX in IlxGen.lhs" (text "// MachLitLit!!!  Not valid in ILX!!")
 pushLit env (MachAddr w) = text "ldc.i4" <+> integer w <+> text "conv.i"
-pushLit env (MachLabel l) = trace "WARNING: Cannot compile MachLabel to ILX in IlxGen.lhs" (text "// MachLabel!!!  Not valid in ILX!!")
+pushLit env (MachLabel l _) = trace "WARNING: Cannot compile MachLabel to ILX in IlxGen.lhs" (text "// MachLabel!!!  Not valid in ILX!!")
 
 pprIlxTopVar env v
   | isExternalName n = (nameReference env n) <> pprId (nameModule n) <> text "::" <> singleQuotes (ppr (nameModule n) <> text "_" <> ppr (nameOccName n))
index 82afb77..b151494 100644 (file)
@@ -29,6 +29,7 @@ import ForeignCall    ( ForeignCall(..), CCallSpec(..), CCallTarget(..),
                          CCallConv(..), playSafe, playThreadSafe )
 import Outputable
 import Util             ( notNull )
+import FastString
 import FastTypes
 
 #include "NCG.h"
@@ -187,7 +188,9 @@ amodeToStix (CLit core)
       MachInt i      -> StInt i
       MachWord w     -> case word2IntLit core of MachInt iw -> StInt iw
       MachLitLit s _ -> litLitErr
-      MachLabel l    -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
+                                                       -- dreadful, but rare.
+      MachLabel l (Just x) -> StCLbl (mkForeignLabel (mkFastString (unpackFS l ++ '@':show x)) False)
+      MachLabel l _        -> StCLbl (mkForeignLabel l False{-ToDo: dynamic-})
       MachFloat d    -> StFloat d
       MachDouble d   -> StDouble d
       _ -> panic "amodeToStix:core literal"
index 4439202..bcf44f1 100644 (file)
@@ -113,14 +113,7 @@ tcCheckFIType sig_ty arg_tys res_ty (CImport cconv _ _ _ CWrapper)
        -- valid foreign type.  For legacy reasons ft -> IO (Ptr ft) as well
        -- as ft -> IO Addr is accepted, too.  The use of the latter two forms
        -- is DEPRECATED, though.
-    checkCg (if cconv == StdCallConv
-               then checkC
-               else checkCOrAsmOrInterp)               `thenM_`
-       -- the native code gen can't handle foreign import stdcall "wrapper",
-       -- because it doesn't emit the '@n' suffix on the label of the
-       -- C stub function.  Infrastructure changes are required to make this
-       -- happen; MachLabel will need to carry around information about
-       -- the arity of the foreign call.
+    checkCg checkCOrAsmOrInterp `thenM_`
     case arg_tys of
        [arg1_ty] -> checkForeignArgs isFFIExternalTy arg1_tys                  `thenM_`
                     checkForeignRes nonIOok  isFFIExportResultTy res1_ty       `thenM_`