% % (c) The Foo Project, University of Glasgow, 1999 % % @(#) $Docid: Nov. 24th 2003 09:56 Sigbjorn Finne $ % @(#) $Contactid: sof@galois.com $ % Marshalling procedures/function values \begin{code} module MarshallFun ( marshallFun ) where import BasicTypes import Attribute import Literal import LibUtils import CgMonad import qualified AbstractH as Haskell ( HDecl ) import AbsHUtils import CoreIDL import CoreUtils import MarshallType import MarshallServ ( cgServMethod ) import MarshallMethod ( cgMethod ) import MarshallCore import Maybe \end{code} @marshallFun@ performs two major tasks: + generates the marshalling code reqd. to deal with function values / callbacks. + generates the wrapper code needed for exposing Haskell functions (i.e., non COM) to the outside world. As elsewhere, the Haskell code generating code is pig ugly. \begin{code} marshallFun :: Maybe Name -> Id -> Type -> CgM Haskell.HDecl marshallFun mb_mod_nm i (FunTy cc res ps) | exportFun = do h <- setInterfaceFlag StdFFI (cgServMethod i real_result ps False False) return (andDecls [m_decl, e_decl, h]) | otherwise = do h <- setInterfaceFlag StdFFI (cgServMethod i real_result ps False False) d <- setInterfaceFlag StdFFI (cgMethod (i{idName=uw_name}) cc real_result ps Nothing (Just i_name)) let decl_list = imp_decls ++ exp_decls ds <- mapM exportDecl decl_list return (andDecls (ds ++ [d,h])) where exportFun = isJust mb_mod_nm imp_decls = [ (u_name, u_decl) , (i_name, i_decl) , (re_name, re_decl) , (s_name, s_decl) ] exp_decls = [ (m_name, m_decl) , (e_name, e_decl) , (wr_name, wr_decl) ] {- If we're marshalling a function pointer, drop the pointer off the result. -} real_result = res{resultType=res_ty, resultOrigType=res_orig_ty} res_ty = removePtr (resultType res) res_orig_ty = removePtr (resultOrigType res) name = mkVarName (idName i) v_name = mkHaskellVarName (idName i) m_name | not exportFun = qName (prefix marshallPrefix name) | otherwise = qName (appendStr "_proxy" name) e_name | not exportFun = qName (prefix "export_" name) | otherwise = m_name i_name = qName (prefix "import_" name) w_name = mkWrapperName (qName name) wr_name = qName (prefix marshallRefPrefix name) re_name = qName (prefix unmarshallRefPrefix name) uw_name = qName (prefix "unwrap_" name) u_name = qName (prefix unmarshallPrefix name) isPure = not exportFun && (idAttributes i) `hasAttributeWithName` "pure" (ty, mb_c) = toHaskellMethodTy isPure False False Nothing ps real_result base_ty = toHaskellBaseMethodTy True ps real_result -- base_ty is the type sig of the call-ins, i_base_ty is for -- the call-out. They may differ in that the latter can be -- passed ForeignObjs, while the former receives the FO args -- in Addr form. i_base_ty = toHaskellBaseMethodTy False ps real_result m_decl = m_tysig `andDecl` m_def m_tysig = genTypeSig m_name mb_c m_type m_def | not exportFun = funDef m_name [patVar v_name] m_rhs | otherwise = funDef m_name [] m_rhs m_rhs | not exportFun = funApply (var e_name) [funApply (var w_name) [var v_name]] | otherwise = funApply (var w_name) [varName f_name] m_type | exportFun = ty | otherwise = funTy ty (io (tyPtr ty)) wr_decl = wr_tysig `andDecl` wr_def wr_tysig = genTypeSig wr_name mb_c wr_type wr_type = funTy (tyPtr (tyPtr ty)) $ funTy ty $ io_unit wr_def = funDef wr_name [patVar "fptr", patVar v_name] wr_rhs wr_rhs = bind (funApply (var m_name) [var v_name]) (var "ptr") $ funApp w_ptr [var "fptr", var "ptr"] e_decl = fexport cc e_loc e_name e_ty e_prim_ty = funTy base_ty (io (tyPtr ty)) {- Name of the *Haskell* function. -} f_name = case (findAttribute "entry" (idAttributes i)) of Just (Attribute _ (ParamLit (StringLit x) : _)) -> mkQVarName mb_mod_nm x _ -> mkQVarName mb_mod_nm (idName i) (e_loc, e_ty) | exportFun = (Just (idName i), base_ty) | otherwise = (Nothing, e_prim_ty) i_decl = primcst cc i_name (funTy (tyPtr ty) i_base_ty) has_structs c_ty_args c_res_ty u_decl = u_tysig `andDecl` u_def u_tysig = genTypeSig u_name mb_c (funTy (tyPtr ty) (io ty)) u_def = funDef u_name [patVar "fptr"] u_rhs u_rhs = ret (funApply (var uw_name) [funApply (var i_name) [var "fptr"]]) re_decl = re_tysig `andDecl` re_def re_tysig = genTypeSig re_name mb_c (funTy (tyPtr ty) (io ty)) re_def = funDef re_name [] re_rhs re_rhs = var u_name s_name = qName (prefix sizeofPrefix name) s_decl = s_tysig `andDecl` s_def s_tysig = typeSig s_name tyWord32 s_def = funDef s_name [] s_rhs s_rhs = szType addrTy has_structs = any (fst) ls ls@(c_res_ty:c_ty_args) = map (isStruct.toCType) (res_ty:p_tys) where isStruct (Left x) = (False, x) isStruct (Right x) = (True, x) p_tys = map paramType ps w_ptr = prefix marshallRefPrefix (mkQVarName hdirectLib ptrName) marshallFun _ _ _ = error "marshallFun" \end{code}