Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / typecheck / TcForeign.lhs
diff --git a/ghc/compiler/typecheck/TcForeign.lhs b/ghc/compiler/typecheck/TcForeign.lhs
deleted file mode 100644 (file)
index 4be039b..0000000
+++ /dev/null
@@ -1,367 +0,0 @@
-%
-% (c) The AQUA Project, Glasgow University, 1998
-%
-\section[TcForeign]{Typechecking \tr{foreign} declarations}
-
-A foreign declaration is used to either give an externally
-implemented function a Haskell type (and calling interface) or
-give a Haskell function an external calling interface. Either way,
-the range of argument and result types these functions can accommodate
-is restricted to what the outside world understands (read C), and this
-module checks to see if a foreign declaration has got a legal type.
-
-\begin{code}
-module TcForeign 
-       ( 
-         tcForeignImports
-        , tcForeignExports
-       ) where
-
-#include "HsVersions.h"
-
-import HsSyn
-
-import TcRnMonad
-import TcHsType                ( tcHsSigType, UserTypeCtxt(..) )
-import TcExpr          ( tcPolyExpr )                  
-
-import ForeignCall     ( CCallConv(..) )
-import ErrUtils                ( Message )
-import Id              ( Id, mkLocalId, mkExportedLocalId )
-#if alpha_TARGET_ARCH
-import Type            ( typePrimRep )
-import SMRep           ( argMachRep, primRepToCgRep, primRepHint )
-#endif
-import OccName         ( mkForeignExportOcc )
-import Name            ( Name, NamedThing(..), mkExternalName )
-import TcType          ( Type, tcSplitFunTys, tcSplitTyConApp_maybe,
-                         tcSplitForAllTys, 
-                         isFFIArgumentTy, isFFIImportResultTy, 
-                         isFFIExportResultTy, isFFILabelTy,
-                         isFFIExternalTy, isFFIDynArgumentTy,
-                         isFFIDynResultTy, isFFIDotnetTy, isFFIDotnetObjTy,
-                         toDNType
-                       )
-import ForeignCall     ( CExportSpec(..), CCallTarget(..), 
-                         CLabelString, isCLabelString,
-                         isDynamicTarget, withDNTypes, DNKind(..), DNCallSpec(..) ) 
-import PrelNames       ( hasKey, ioTyConKey )
-import DynFlags                ( DynFlags(..), HscTarget(..) )
-import Outputable
-import SrcLoc          ( Located(..), srcSpanStart )
-import Bag             ( consBag )
-
-#if alpha_TARGET_ARCH
-import MachOp          ( machRepByteWidth, MachHint(FloatHint) )
-#endif
-\end{code}
-
-\begin{code}
--- Defines a binding
-isForeignImport :: LForeignDecl name -> Bool
-isForeignImport (L _ (ForeignImport _ _ _ _)) = True
-isForeignImport _                            = False
-
--- Exports a binding
-isForeignExport :: LForeignDecl name -> Bool
-isForeignExport (L _ (ForeignExport _ _ _ _)) = True
-isForeignExport _                            = False
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection{Imports}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-tcForeignImports :: [LForeignDecl Name] -> TcM ([Id], [LForeignDecl Id])
-tcForeignImports decls
-  = mapAndUnzipM (wrapLocSndM tcFImport) (filter isForeignImport decls)
-
-tcFImport :: ForeignDecl Name -> TcM (Id, ForeignDecl Id)
-tcFImport fo@(ForeignImport (L loc nm) hs_ty imp_decl isDeprec)
- = addErrCtxt (foreignDeclCtxt fo)     $
-   tcHsSigType (ForSigCtxt nm) hs_ty   `thenM` \ sig_ty ->
-   let 
-      -- drop the foralls before inspecting the structure
-      -- of the foreign type.
-       (_, t_ty)         = tcSplitForAllTys sig_ty
-       (arg_tys, res_ty) = tcSplitFunTys t_ty
-       id                = mkLocalId nm sig_ty
-               -- Use a LocalId to obey the invariant that locally-defined 
-               -- things are LocalIds.  However, it does not need zonking,
-               -- (so TcHsSyn.zonkForeignExports ignores it).
-   in
-   tcCheckFIType sig_ty arg_tys res_ty imp_decl                `thenM` \ imp_decl' -> 
-   -- can't use sig_ty here because it :: Type and we need HsType Id
-   -- hence the undefined
-   returnM (id, ForeignImport (L loc id) undefined imp_decl' isDeprec)
-\end{code}
-
-
------------- Checking types for foreign import ----------------------
-\begin{code}
-tcCheckFIType _ arg_tys res_ty (DNImport spec)
-  = checkCg checkDotnet  `thenM_`
-    getDOpts            `thenM`  \ dflags ->
-    checkForeignArgs (isFFIDotnetTy dflags) arg_tys    `thenM_`
-    checkForeignRes True{-non IO ok-} (isFFIDotnetTy dflags) res_ty `thenM_`
-    let (DNCallSpec isStatic kind _ _ _ _) = spec in
-    (case kind of
-       DNMethod | not isStatic ->
-         case arg_tys of
-          [] -> addErrTc illegalDNMethodSig
-          _  
-           | not (isFFIDotnetObjTy (last arg_tys)) -> addErrTc illegalDNMethodSig
-           | otherwise -> returnM ()
-       _ -> returnM ()) `thenM_`
-    returnM (DNImport (withDNTypes spec (map toDNType arg_tys) (toDNType res_ty)))
-
-tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport _ _ _ _ (CLabel _))
-  = checkCg checkCOrAsm                `thenM_`
-    check (isFFILabelTy sig_ty) (illegalForeignTyErr empty sig_ty) `thenM_`
-    return idecl
-
-tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv _ _ _ CWrapper)
-  =    -- Foreign wrapper (former f.e.d.)
-       -- The type must be of the form ft -> IO (FunPtr ft), where ft is a
-       -- 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 checkCOrAsmOrInterp `thenM_`
-    checkCConv cconv           `thenM_`
-    (case arg_tys of
-       [arg1_ty] -> checkForeignArgs isFFIExternalTy arg1_tys               `thenM_`
-                    checkForeignRes nonIOok  isFFIExportResultTy res1_ty    `thenM_`
-                    checkForeignRes mustBeIO isFFIDynResultTy    res_ty     `thenM_`
-                    checkFEDArgs arg1_tys
-                 where
-                    (arg1_tys, res1_ty) = tcSplitFunTys arg1_ty
-        other -> addErrTc (illegalForeignTyErr empty sig_ty)   )            `thenM_`
-    return idecl
-
-tcCheckFIType sig_ty arg_tys res_ty idecl@(CImport cconv safety _ _ (CFunction target))
-  | isDynamicTarget target     -- Foreign import dynamic
-  = checkCg checkCOrAsmOrInterp                `thenM_`
-    checkCConv cconv                   `thenM_`
-    case arg_tys of            -- The first arg must be Ptr, FunPtr, or Addr
-      []               -> 
-       check False (illegalForeignTyErr empty sig_ty) `thenM_`
-       return idecl
-      (arg1_ty:arg_tys) -> 
-       getDOpts                                                     `thenM` \ dflags ->
-       check (isFFIDynArgumentTy arg1_ty)
-             (illegalForeignTyErr argument arg1_ty)                 `thenM_`
-        checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys     `thenM_`
-       checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty  `thenM_`
-       return idecl
-  | otherwise          -- Normal foreign import
-  = checkCg (checkCOrAsmOrDotNetOrInterp)                      `thenM_`
-    checkCConv cconv                                           `thenM_`
-    checkCTarget target                                                `thenM_`
-    getDOpts                                                   `thenM` \ dflags ->
-    checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys   `thenM_`
-    checkForeignRes nonIOok (isFFIImportResultTy dflags) res_ty `thenM_`
-    return idecl
-
--- This makes a convenient place to check
--- that the C identifier is valid for C
-checkCTarget (StaticTarget str) 
-  = checkCg checkCOrAsmOrDotNetOrInterp                `thenM_`
-    check (isCLabelString str) (badCName str)
-\end{code}
-
-On an Alpha, with foreign export dynamic, due to a giant hack when
-building adjustor thunks, we only allow 4 integer arguments with
-foreign export dynamic (i.e., 32 bytes of arguments after padding each
-argument to a quadword, excluding floating-point arguments).
-
-The check is needed for both via-C and native-code routes
-
-\begin{code}
-#include "nativeGen/NCG.h"
-#if alpha_TARGET_ARCH
-checkFEDArgs arg_tys
-  = check (integral_args <= 32) err
-  where
-    integral_args = sum [ (machRepByteWidth . argMachRep . primRepToCgRep) prim_rep
-                       | prim_rep <- map typePrimRep arg_tys,
-                         primRepHint prim_rep /= FloatHint ]
-    err = ptext SLIT("On Alpha, I can only handle 32 bytes of non-floating-point arguments to foreign export dynamic")
-#else
-checkFEDArgs arg_tys = returnM ()
-#endif
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Exports}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-tcForeignExports :: [LForeignDecl Name] 
-                -> TcM (LHsBinds TcId, [LForeignDecl TcId])
-tcForeignExports decls
-  = foldlM combine (emptyLHsBinds, []) (filter isForeignExport decls)
-  where
-   combine (binds, fs) fe = 
-       wrapLocSndM tcFExport fe        `thenM` \ (b, f) ->
-       returnM (b `consBag` binds, f:fs)
-
-tcFExport :: ForeignDecl Name -> TcM (LHsBind Id, ForeignDecl Id)
-tcFExport fo@(ForeignExport (L loc nm) hs_ty spec isDeprec) =
-   addErrCtxt (foreignDeclCtxt fo)     $
-
-   tcHsSigType (ForSigCtxt nm) hs_ty   `thenM` \ sig_ty ->
-   tcPolyExpr (nlHsVar nm) sig_ty      `thenM` \ rhs ->
-
-   tcCheckFEType sig_ty spec           `thenM_`
-
-         -- we're exporting a function, but at a type possibly more
-         -- constrained than its declared/inferred type. Hence the need
-         -- to create a local binding which will call the exported function
-         -- at a particular type (and, maybe, overloading).
-
-   newUnique                   `thenM` \ uniq ->
-   getModule                   `thenM` \ mod ->
-   let
-        gnm  = mkExternalName uniq mod (mkForeignExportOcc (getOccName nm)) 
-                             Nothing (srcSpanStart loc)
-       id   = mkExportedLocalId gnm sig_ty
-       bind = L loc (VarBind id rhs)
-   in
-   returnM (bind, ForeignExport (L loc id) undefined spec isDeprec)
-\end{code}
-
------------- Checking argument types for foreign export ----------------------
-
-\begin{code}
-tcCheckFEType sig_ty (CExport (CExportStatic str _))
-  = check (isCLabelString str) (badCName str)          `thenM_`
-    checkForeignArgs isFFIExternalTy arg_tys           `thenM_`
-    checkForeignRes nonIOok isFFIExportResultTy res_ty
-  where
-      -- Drop the foralls before inspecting n
-      -- the structure of the foreign type.
-    (_, t_ty) = tcSplitForAllTys sig_ty
-    (arg_tys, res_ty) = tcSplitFunTys t_ty
-\end{code}
-
-
-
-%************************************************************************
-%*                                                                     *
-\subsection{Miscellaneous}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
------------- Checking argument types for foreign import ----------------------
-checkForeignArgs :: (Type -> Bool) -> [Type] -> TcM ()
-checkForeignArgs pred tys
-  = mappM go tys               `thenM_` 
-    returnM ()
-  where
-    go ty = check (pred ty) (illegalForeignTyErr argument ty)
-
------------- Checking result types for foreign calls ----------------------
--- Check that the type has the form 
---    (IO t) or (t) , and that t satisfies the given predicate.
---
-checkForeignRes :: Bool -> (Type -> Bool) -> Type -> TcM ()
-
-nonIOok  = True
-mustBeIO = False
-
-checkForeignRes non_io_result_ok pred_res_ty ty
- = case tcSplitTyConApp_maybe ty of
-      Just (io, [res_ty]) 
-        | io `hasKey` ioTyConKey && pred_res_ty res_ty 
-       -> returnM ()
-      _   
-        -> check (non_io_result_ok && pred_res_ty ty) 
-                (illegalForeignTyErr result ty)
-\end{code}
-
-\begin{code}
-checkDotnet HscILX = Nothing
-#if defined(mingw32_TARGET_OS)
-checkDotnet HscC   = Nothing
-checkDotnet _      = Just (text "requires C code generation (-fvia-C)")
-#else
-checkDotnet other  = Just (text "requires .NET support (-filx or win32)")
-#endif
-
-checkCOrAsm HscC   = Nothing
-checkCOrAsm HscAsm = Nothing
-checkCOrAsm other  
-   = Just (text "requires via-C or native code generation (-fvia-C)")
-
-checkCOrAsmOrInterp HscC           = Nothing
-checkCOrAsmOrInterp HscAsm         = Nothing
-checkCOrAsmOrInterp HscInterpreted = Nothing
-checkCOrAsmOrInterp other  
-   = Just (text "requires interpreted, C or native code generation")
-
-checkCOrAsmOrDotNetOrInterp HscC           = Nothing
-checkCOrAsmOrDotNetOrInterp HscAsm         = Nothing
-checkCOrAsmOrDotNetOrInterp HscILX         = Nothing
-checkCOrAsmOrDotNetOrInterp HscInterpreted = Nothing
-checkCOrAsmOrDotNetOrInterp other  
-   = Just (text "requires interpreted, C, native or .NET ILX code generation")
-
-checkCg check
- = getDOpts            `thenM` \ dflags ->
-   let target = hscTarget dflags in
-   case target of
-     HscNothing -> returnM ()
-     otherwise  ->
-       case check target of
-        Nothing  -> returnM ()
-        Just err -> addErrTc (text "Illegal foreign declaration:" <+> err)
-\end{code} 
-                          
-Calling conventions
-
-\begin{code}
-checkCConv :: CCallConv -> TcM ()
-checkCConv CCallConv  = return ()
-#if i386_TARGET_ARCH
-checkCConv StdCallConv = return ()
-#else
-checkCConv StdCallConv = addErrTc (text "calling convention not supported on this architecture: stdcall")
-#endif
-\end{code}
-
-Warnings
-
-\begin{code}
-check :: Bool -> Message -> TcM ()
-check True _      = returnM ()
-check _    the_err = addErrTc the_err
-
-illegalForeignTyErr arg_or_res ty
-  = hang (hsep [ptext SLIT("Unacceptable"), arg_or_res, 
-                ptext SLIT("type in foreign declaration:")])
-        4 (hsep [ppr ty])
-
--- Used for 'arg_or_res' argument to illegalForeignTyErr
-argument = text "argument"
-result   = text "result"
-
-badCName :: CLabelString -> Message
-badCName target 
-   = sep [quotes (ppr target) <+> ptext SLIT("is not a valid C identifier")]
-
-foreignDeclCtxt fo
-  = hang (ptext SLIT("When checking declaration:"))
-         4 (ppr fo)
-
-illegalDNMethodSig 
-  = ptext SLIT("'This pointer' expected as last argument")
-
-\end{code}
-