2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
4 \section[Foreign]{Foreign calls}
8 -- The above warning supression flag is a temporary kludge.
9 -- While working on this module you are encouraged to remove it and fix
10 -- any warnings in the module. See
11 -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings
16 Safety(..), playSafe, playThreadSafe,
18 CExportSpec(..), CLabelString, isCLabelString, pprCLabelString,
20 CCallTarget(..), isDynamicTarget,
21 CCallConv(..), defaultCCallConv, ccallConvToInt, ccallConvAttribute,
23 DNCallSpec(..), DNKind(..), DNType(..),
27 #include "HsVersions.h"
29 import FastString ( FastString, unpackFS )
30 import Char ( isAlphaNum )
36 %************************************************************************
38 \subsubsection{Data types}
40 %************************************************************************
46 deriving( Eq ) -- We compare them when seeing if an interface
47 -- has changed (for versioning purposes)
48 {-! derive: Binary !-}
50 -- We may need more clues to distinguish foreign calls
51 -- but this simple printer will do for now
52 instance Outputable ForeignCall where
53 ppr (CCall cc) = ppr cc
54 ppr (DNCall dn) = ppr dn
60 = PlaySafe -- Might invoke Haskell GC, or do a call back, or
61 -- switch threads, etc. So make sure things are
62 -- tidy before the call
63 Bool -- => True, external function is also re-entrant.
64 -- [if supported, RTS arranges for the external call
65 -- to be executed by a separate OS thread, i.e.,
66 -- _concurrently_ to the execution of other Haskell threads.]
68 | PlayRisky -- None of the above can happen; the call will return
69 -- without interacting with the runtime system at all
71 -- Show used just for Show Lex.Token, I think
72 {-! derive: Binary !-}
74 instance Outputable Safety where
75 ppr (PlaySafe False) = ptext SLIT("safe")
76 ppr (PlaySafe True) = ptext SLIT("threadsafe")
77 ppr PlayRisky = ptext SLIT("unsafe")
79 playSafe :: Safety -> Bool
80 playSafe PlaySafe{} = True
81 playSafe PlayRisky = False
83 playThreadSafe :: Safety -> Bool
84 playThreadSafe (PlaySafe x) = x
85 playThreadSafe _ = False
89 %************************************************************************
91 \subsubsection{Calling C}
93 %************************************************************************
97 = CExportStatic -- foreign export ccall foo :: ty
98 CLabelString -- C Name of exported function
100 {-! derive: Binary !-}
103 = CCallSpec CCallTarget -- What to call
104 CCallConv -- Calling convention to use.
107 {-! derive: Binary !-}
114 = StaticTarget CLabelString -- An "unboxed" ccall# to `fn'.
115 | DynamicTarget -- First argument (an Addr#) is the function pointer
117 {-! derive: Binary !-}
119 isDynamicTarget :: CCallTarget -> Bool
120 isDynamicTarget DynamicTarget = True
121 isDynamicTarget other = False
125 Stuff to do with calling convention:
127 ccall: Caller allocates parameters, *and* deallocates them.
129 stdcall: Caller allocates parameters, callee deallocates.
130 Function name has @N after it, where N is number of arg bytes
133 ToDo: The stdcall calling convention is x86 (win32) specific,
134 so perhaps we should emit a warning if it's being used on other
138 data CCallConv = CCallConv | StdCallConv | CmmCallConv
140 {-! derive: Binary !-}
142 instance Outputable CCallConv where
143 ppr StdCallConv = ptext SLIT("stdcall")
144 ppr CCallConv = ptext SLIT("ccall")
145 ppr CmmCallConv = ptext SLIT("C--")
147 defaultCCallConv :: CCallConv
148 defaultCCallConv = CCallConv
150 ccallConvToInt :: CCallConv -> Int
151 ccallConvToInt StdCallConv = 0
152 ccallConvToInt CCallConv = 1
155 Generate the gcc attribute corresponding to the given
156 calling convention (used by PprAbsC):
159 ccallConvAttribute :: CCallConv -> String
160 ccallConvAttribute StdCallConv = "__attribute__((__stdcall__))"
161 ccallConvAttribute CCallConv = ""
165 type CLabelString = FastString -- A C label, completely unencoded
167 pprCLabelString :: CLabelString -> SDoc
168 pprCLabelString lbl = ftext lbl
170 isCLabelString :: CLabelString -> Bool -- Checks to see if this is a valid C label
172 = all ok (unpackFS lbl)
174 ok c = isAlphaNum c || c == '_' || c == '.'
175 -- The '.' appears in e.g. "foo.so" in the
176 -- module part of a ExtName. Maybe it should be separate
180 Printing into C files:
183 instance Outputable CExportSpec where
184 ppr (CExportStatic str _) = pprCLabelString str
186 instance Outputable CCallSpec where
187 ppr (CCallSpec fun cconv safety)
188 = hcat [ ifPprDebug callconv, ppr_fun fun ]
190 callconv = text "{-" <> ppr cconv <> text "-}"
192 gc_suf | playSafe safety = text "_GC"
195 ppr_fun DynamicTarget = text "__dyn_ccall" <> gc_suf <+> text "\"\""
196 ppr_fun (StaticTarget fn) = text "__ccall" <> gc_suf <+> pprCLabelString fn
200 %************************************************************************
202 \subsubsection{.NET interop}
204 %************************************************************************
208 DNCallSpec Bool -- True => static method/field
209 DNKind -- what type of access
211 String -- fully qualified method/field name.
212 [DNType] -- argument types.
213 DNType -- result type.
215 {-! derive: Binary !-}
222 {-! derive: Binary !-}
244 {-! derive: Binary !-}
246 withDNTypes :: DNCallSpec -> [DNType] -> DNType -> DNCallSpec
247 withDNTypes (DNCallSpec isStatic k assem nm _ _) argTys resTy
248 = DNCallSpec isStatic k assem nm argTys resTy
250 instance Outputable DNCallSpec where
251 ppr (DNCallSpec isStatic kind ass nm _ _ )
253 (if isStatic then text "static" else empty) <+>
254 (text (case kind of { DNMethod -> "method" ; DNField -> "field"; DNConstructor -> "ctor" })) <+>
255 (if null ass then char ' ' else char '[' <> text ass <> char ']') <>
262 %************************************************************************
266 %************************************************************************
269 {-* Generated by DrIFT-v1.0 : Look, but Don't Touch. *-}
270 instance Binary ForeignCall where
271 put_ bh (CCall aa) = do
274 put_ bh (DNCall ab) = do
285 instance Binary Safety where
286 put_ bh (PlaySafe aa) = do
289 put_ bh PlayRisky = do
296 _ -> do return PlayRisky
298 instance Binary CExportSpec where
299 put_ bh (CExportStatic aa ab) = do
305 return (CExportStatic aa ab)
307 instance Binary CCallSpec where
308 put_ bh (CCallSpec aa ab ac) = do
316 return (CCallSpec aa ab ac)
318 instance Binary CCallTarget where
319 put_ bh (StaticTarget aa) = do
322 put_ bh DynamicTarget = do
328 return (StaticTarget aa)
329 _ -> do return DynamicTarget
331 instance Binary CCallConv where
332 put_ bh CCallConv = do
334 put_ bh StdCallConv = do
339 0 -> do return CCallConv
340 _ -> do return StdCallConv
342 instance Binary DNCallSpec where
343 put_ bh (DNCallSpec isStatic kind ass nm _ _) = do
353 return (DNCallSpec isStatic kind ass nm [] undefined)
355 instance Binary DNKind where
356 put_ bh DNMethod = do
360 put_ bh DNConstructor = do
365 0 -> do return DNMethod
366 1 -> do return DNField
367 _ -> do return DNConstructor
369 instance Binary DNType where
376 put_ bh DNDouble = do
392 put_ bh DNWord16 = do
394 put_ bh DNWord32 = do
396 put_ bh DNWord64 = do
402 put_ bh DNObject = do
404 put_ bh DNString = do
421 11 -> return DNWord16
422 12 -> return DNWord32
423 13 -> return DNWord64
426 16 -> return DNObject
427 17 -> return DNString
429 -- Imported from other files :-