From 33e73b5df3cc87e0bbf719a841dc1ec3a07d78c5 Mon Sep 17 00:00:00 2001 From: Ian-Woo Kim Date: Sun, 27 Aug 2023 20:28:05 -0700 Subject: [PATCH] FFI safety is now explicitly given (#229) User should now specify unsafe/safe/interruptible explicitly. constructors and destructors are always unsafe (this should be taken granted. C++ library should not call Haskell back inside constructor/destructors). Accessor functions (getter/setter) are also unsafe. On the other hand, calling an instance of std::function (which is hard-coded in FFICXX.Runtime.Function.TH) should be unconditionally safe. * unsafe testing * introduce C FFI Safety * ordinary function safety is handled. * Safety in fficxx-runtime * template haskell gen now handles Safety * Add Safety parameter in TFun. and update stdcxx * update examples with Safety parameter * upgrade template TH code generation with FFISafety * calling std::function should be safe! --- fficxx-multipkg-test/template-dep/Gen.hs | 7 ++- fficxx-multipkg-test/template-member/Gen.hs | 31 ++++++------ fficxx-multipkg-test/template-toplevel/Gen.hs | 15 +++--- fficxx-runtime/fficxx-runtime.cabal | 5 +- .../src/FFICXX/Runtime/Function/TH.hs | 17 ++++--- fficxx-runtime/src/FFICXX/Runtime/TH.hs | 15 ++++-- fficxx-runtime/src/FFICXX/Runtime/Types.hs | 7 +++ fficxx-test/fficxx-test.cabal | 2 +- fficxx/src/FFICXX/Generate/Builder.hs | 2 +- fficxx/src/FFICXX/Generate/Code/HsEnum.hs | 4 +- fficxx/src/FFICXX/Generate/Code/HsFFI.hs | 31 ++++++++---- .../FFICXX/Generate/Code/HsImplementation.hs | 15 ++++-- fficxx/src/FFICXX/Generate/Code/HsTH.hs | 18 +++++-- fficxx/src/FFICXX/Generate/Code/HsTopLevel.hs | 15 +++--- fficxx/src/FFICXX/Generate/Code/Primitive.hs | 25 ++++++---- fficxx/src/FFICXX/Generate/ContentMaker.hs | 12 +++-- fficxx/src/FFICXX/Generate/Dependency.hs | 10 ++-- fficxx/src/FFICXX/Generate/Name.hs | 16 +++---- fficxx/src/FFICXX/Generate/Type/Class.hs | 47 +++++++++++++------ .../src/FFICXX/Generate/Util/GHCExactPrint.hs | 30 +++++++----- stdcxx-gen/Gen.hs | 46 +++++++++++------- 21 files changed, 235 insertions(+), 135 deletions(-) create mode 100644 fficxx-runtime/src/FFICXX/Runtime/Types.hs diff --git a/fficxx-multipkg-test/template-dep/Gen.hs b/fficxx-multipkg-test/template-dep/Gen.hs index 7c4ef7ac..81bf3e6f 100644 --- a/fficxx-multipkg-test/template-dep/Gen.hs +++ b/fficxx-multipkg-test/template-dep/Gen.hs @@ -58,6 +58,7 @@ import FFICXX.Generate.Type.Config import FFICXX.Generate.Type.Module import FFICXX.Generate.Type.PackageInterface import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..)) +import FFICXX.Runtime.Types (FFISafety (..)) import System.Directory (getCurrentDirectory) import System.Environment (getArgs) import System.FilePath (()) @@ -104,7 +105,8 @@ tT1 cabal = tfun_new_alias = Nothing }, TFun - { tfun_ret = Void, + { tfun_safety = FFIUnsafe, + tfun_ret = Void, tfun_name = "method", tfun_oname = "method", tfun_args = [] @@ -126,7 +128,8 @@ tT2 cabal = tfun_new_alias = Nothing }, TFun - { tfun_ret = Void, + { tfun_safety = FFIUnsafe, + tfun_ret = Void, tfun_name = "callT1", tfun_oname = "callT1", tfun_args = diff --git a/fficxx-multipkg-test/template-member/Gen.hs b/fficxx-multipkg-test/template-member/Gen.hs index 4e1d474a..2078fe81 100644 --- a/fficxx-multipkg-test/template-member/Gen.hs +++ b/fficxx-multipkg-test/template-member/Gen.hs @@ -58,6 +58,7 @@ import FFICXX.Generate.Type.Config import FFICXX.Generate.Type.Module import FFICXX.Generate.Type.PackageInterface import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..)) +import FFICXX.Runtime.Types (FFISafety (..)) import System.Directory (getCurrentDirectory) import System.Environment (getArgs) import System.FilePath (()) @@ -109,9 +110,9 @@ string = mempty (Just (ClassAlias {caHaskellName = "CppString", caFFIName = "string"})) [ Constructor [cstring "p"] Nothing, - NonVirtual cstring_ "c_str" [] Nothing, - NonVirtual (cppclassref_ string) "append" [cppclassref string "str"] Nothing, - NonVirtual (cppclassref_ string) "erase" [] Nothing + NonVirtual FFIUnsafe cstring_ "c_str" [] Nothing, + NonVirtual FFIUnsafe (cppclassref_ string) "append" [cppclassref string "str"] Nothing, + NonVirtual FFIUnsafe (cppclassref_ string) "erase" [] Nothing ] [] [] @@ -125,10 +126,10 @@ t_vector = (FormSimple "std::vector") ["tp1"] [ TFunNew [] Nothing, - TFun void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], - TFun void_ "pop_back" "pop_back" [], - TFun (TemplateParam "tp1") "at" "at" [int "n"], - TFun int_ "size" "size" [], + TFun FFIUnsafe void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], + TFun FFIUnsafe void_ "pop_back" "pop_back" [], + TFun FFIUnsafe (TemplateParam "tp1") "at" "at" [int "n"], + TFun FFIUnsafe int_ "size" "size" [], TFunDelete ] [] @@ -142,9 +143,9 @@ t_unique_ptr = ["tp1"] [ TFunNew [] (Just "newUniquePtr0"), TFunNew [Arg (TemplateParamPointer "tp1") "p"] Nothing, - TFun (TemplateParamPointer "tp1") "get" "get" [], - TFun (TemplateParamPointer "tp1") "release" "release" [], - TFun void_ "reset" "reset" [], + TFun FFIUnsafe (TemplateParamPointer "tp1") "get" "get" [], + TFun FFIUnsafe (TemplateParamPointer "tp1") "release" "release" [], + TFun FFIUnsafe void_ "reset" "reset" [], TFunDelete ] [] @@ -190,14 +191,16 @@ classA cabal = class_vars = [], class_tmpl_funcs = [ TemplateMemberFunction - { tmf_params = ["tp1"], + { tmf_safety = FFIUnsafe, + tmf_params = ["tp1"], tmf_ret = void_, tmf_name = "method", tmf_args = [Arg (TemplateParamPointer "tp1") "x"], tmf_alias = Nothing }, TemplateMemberFunction - { tmf_params = ["tp1"], + { tmf_safety = FFIUnsafe, + tmf_params = ["tp1"], tmf_ret = void_, tmf_name = "method2", tmf_args = @@ -227,7 +230,7 @@ classT1 cabal = class_alias = Nothing, class_funcs = [ Constructor [] Nothing, - NonVirtual void_ "print" [] Nothing + NonVirtual FFIUnsafe void_ "print" [] Nothing ], class_vars = [], class_tmpl_funcs = [], @@ -244,7 +247,7 @@ classT2 cabal = class_alias = Nothing, class_funcs = [ Constructor [] Nothing, - NonVirtual void_ "print" [] Nothing + NonVirtual FFIUnsafe void_ "print" [] Nothing ], class_vars = [], class_tmpl_funcs = [], diff --git a/fficxx-multipkg-test/template-toplevel/Gen.hs b/fficxx-multipkg-test/template-toplevel/Gen.hs index 0a87d8ce..fe8b74a2 100644 --- a/fficxx-multipkg-test/template-toplevel/Gen.hs +++ b/fficxx-multipkg-test/template-toplevel/Gen.hs @@ -58,6 +58,7 @@ import FFICXX.Generate.Type.Config import FFICXX.Generate.Type.Module import FFICXX.Generate.Type.PackageInterface import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..)) +import FFICXX.Runtime.Types (FFISafety (..)) import System.Directory (getCurrentDirectory) import System.Environment (getArgs) import System.FilePath (()) @@ -111,10 +112,10 @@ t_vector = (FormSimple "std::vector") ["tp1"] [ TFunNew [] Nothing, - TFun void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], - TFun void_ "pop_back" "pop_back" [], - TFun (TemplateParam "tp1") "at" "at" [int "n"], - TFun int_ "size" "size" [], + TFun FFIUnsafe void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], + TFun FFIUnsafe void_ "pop_back" "pop_back" [], + TFun FFIUnsafe (TemplateParam "tp1") "at" "at" [int "n"], + TFun FFIUnsafe int_ "size" "size" [], TFunDelete ] [] @@ -155,14 +156,16 @@ toplevels :: [TopLevel] toplevels = [ TLOrdinary TopLevelFunction - { toplevelfunc_ret = Void, + { toplevelfunc_safety = FFIUnsafe, + toplevelfunc_ret = Void, toplevelfunc_name = "ordinary", toplevelfunc_args = [], toplevelfunc_alias = Nothing }, TLTemplate ( TopLevelTemplateFunction - { topleveltfunc_params = ["t1"], + { topleveltfunc_safety = FFIUnsafe, + topleveltfunc_params = ["t1"], topleveltfunc_ret = TemplateAppMove (TemplateAppInfo t_vector [TArg_TypeParam "t1"] "std::vector"), topleveltfunc_name = "return_vector", diff --git a/fficxx-runtime/fficxx-runtime.cabal b/fficxx-runtime/fficxx-runtime.cabal index 8f0f4c9e..2fb7b031 100644 --- a/fficxx-runtime/fficxx-runtime.cabal +++ b/fficxx-runtime/fficxx-runtime.cabal @@ -9,7 +9,7 @@ License-file: LICENSE Author: Ian-Woo Kim Maintainer: Ian-Woo Kim Build-Type: Simple -Tested-With: GHC == 9.2.7 || == 9.4.5 || == 9.6.2 +Tested-With: GHC == 9.6.2 Category: FFI Tools Extra-Source-Files: ChangeLog.md @@ -31,8 +31,7 @@ Library FFICXX.Runtime.Function.Template FFICXX.Runtime.Function.TH FFICXX.Runtime.TH - - + FFICXX.Runtime.Types Include-dirs: csrc Install-includes: MacroPatternMatch.h Function.h diff --git a/fficxx-runtime/src/FFICXX/Runtime/Function/TH.hs b/fficxx-runtime/src/FFICXX/Runtime/Function/TH.hs index 47607f47..565a833c 100644 --- a/fficxx-runtime/src/FFICXX/Runtime/Function/TH.hs +++ b/fficxx-runtime/src/FFICXX/Runtime/Function/TH.hs @@ -10,11 +10,13 @@ import FFICXX.Runtime.Function.Template (Function) import FFICXX.Runtime.TH ( FunctionParamInfo (..), con, + mkDelete, mkInstance, mkMember, mkNew, mkTFunc, ) +import FFICXX.Runtime.Types (FFISafety (..)) import Foreign.Ptr (FunPtr) import Language.Haskell.TH (forImpD, safe) import Language.Haskell.TH.Syntax @@ -45,15 +47,15 @@ mkWrapper (typ, suffix) = t_newFunction :: Type -> String -> Q Exp t_newFunction typ suffix = - mkTFunc (typ, suffix, \n -> "Function_new_" <> n, tyf) + mkTFunc FFIUnsafe (typ, suffix, \n -> "Function_new_" <> n, tyf) where tyf _n = let t = pure typ in [t|FunPtr $(t) -> IO (Function $(t))|] -t_call :: Type -> String -> Q Exp -t_call typ suffix = - mkTFunc (typ, suffix, \n -> "Function_call_" <> n, tyf) +t_call :: FFISafety -> Type -> String -> Q Exp +t_call safety typ suffix = + mkTFunc safety (typ, suffix, \n -> "Function_call_" <> n, tyf) where tyf _n = let t = pure typ @@ -61,7 +63,7 @@ t_call typ suffix = t_deleteFunction :: Type -> String -> Q Exp t_deleteFunction typ suffix = - mkTFunc (typ, suffix, \n -> "Function_delete_" <> n, tyf) + mkTFunc FFIUnsafe (typ, suffix, \n -> "Function_delete_" <> n, tyf) where tyf _n = let t = pure typ @@ -73,8 +75,9 @@ genFunctionInstanceFor qtyp param = let suffix = fpinfoSuffix param typ <- qtyp f1 <- mkNew "newFunction" t_newFunction typ suffix - f2 <- mkMember "call" t_call typ suffix - f3 <- mkMember "deleteFunction" t_deleteFunction typ suffix + -- NOTE: The indirected function call should be safe. + f2 <- mkMember "call" (t_call FFISafe) typ suffix + f3 <- mkDelete "deleteFunction" t_deleteFunction typ suffix wrap <- mkWrapper (typ, suffix) addModFinalizer ( addForeignSource diff --git a/fficxx-runtime/src/FFICXX/Runtime/TH.hs b/fficxx-runtime/src/FFICXX/Runtime/TH.hs index f28ee7c9..c86aef8a 100644 --- a/fficxx-runtime/src/FFICXX/Runtime/TH.hs +++ b/fficxx-runtime/src/FFICXX/Runtime/TH.hs @@ -2,9 +2,9 @@ module FFICXX.Runtime.TH where --- import FFICXX.Runtime.CodeGen.Cxx (HeaderName, Namespace) -import Language.Haskell.TH (forImpD, safe, varE) +import FFICXX.Runtime.Types (FFISafety (..)) +import Language.Haskell.TH (forImpD, interruptible, safe, unsafe, varE) import Language.Haskell.TH.Syntax ( Body (NormalB), Callconv (CCall), @@ -54,13 +54,18 @@ con = ConT . mkNameS mkInstance :: Cxt -> Type -> [Dec] -> Dec mkInstance = InstanceD Nothing -mkTFunc :: (types, String, String -> String, types -> Q Type) -> Q Exp -mkTFunc (typs, suffix, nf, tyf) = +mkTFunc :: FFISafety -> (types, String, String -> String, types -> Q Type) -> Q Exp +mkTFunc safety (typs, suffix, nf, tyf) = do let fn = nf suffix let fn' = "c_" <> fn n <- newName fn' - d <- forImpD CCall safe fn n (tyf typs) + let safety_modifier = + case safety of + FFIUnsafe -> unsafe + FFISafe -> safe + FFIInterruptible -> interruptible + d <- forImpD CCall safety_modifier fn n (tyf typs) addTopDecls [d] [|$(varE n)|] diff --git a/fficxx-runtime/src/FFICXX/Runtime/Types.hs b/fficxx-runtime/src/FFICXX/Runtime/Types.hs new file mode 100644 index 00000000..eacff8df --- /dev/null +++ b/fficxx-runtime/src/FFICXX/Runtime/Types.hs @@ -0,0 +1,7 @@ +module FFICXX.Runtime.Types + ( FFISafety (..), + ) +where + +data FFISafety = FFIUnsafe | FFISafe | FFIInterruptible + deriving (Show) diff --git a/fficxx-test/fficxx-test.cabal b/fficxx-test/fficxx-test.cabal index 4362c0ca..9fbb059d 100644 --- a/fficxx-test/fficxx-test.cabal +++ b/fficxx-test/fficxx-test.cabal @@ -1,6 +1,6 @@ Cabal-Version: 3.0 Name: fficxx-test -Version: 0.7.0.1 +Version: 0.8.0.0 Synopsis: test for fficxx Description: test for fficxx (with stdcxx) License: BSD-2-Clause diff --git a/fficxx/src/FFICXX/Generate/Builder.hs b/fficxx/src/FFICXX/Generate/Builder.hs index d58d3bbb..a041578a 100644 --- a/fficxx/src/FFICXX/Generate/Builder.hs +++ b/fficxx/src/FFICXX/Generate/Builder.hs @@ -159,7 +159,7 @@ simpleBuilder cfg sbc = do putStrLn "Generating Enum.hsc" gen (topLevelMod <.> "Enum" <.> "hsc") - (exactPrint (C.buildEnumHsc mempty (topLevelMod <> ".Enum") enums)) + (exactPrint (C.buildEnumHsc (topLevelMod <> ".Enum") enums)) -- putStrLn "Generating RawType.hs" for_ mods $ \m -> diff --git a/fficxx/src/FFICXX/Generate/Code/HsEnum.hs b/fficxx/src/FFICXX/Generate/Code/HsEnum.hs index 2a5e1b1d..3eaa690b 100644 --- a/fficxx/src/FFICXX/Generate/Code/HsEnum.hs +++ b/fficxx/src/FFICXX/Generate/Code/HsEnum.hs @@ -4,12 +4,10 @@ module FFICXX.Generate.Code.HsEnum ) where -import Control.Monad.Reader (Reader) import FFICXX.Generate.Name ( enumDataConstructorNames, enumDataTypeName, ) -import FFICXX.Generate.Type.Annotate (AnnotateMap) import FFICXX.Generate.Type.Class (EnumType (..)) import FFICXX.Generate.Util.GHCExactPrint ( DeclGroup, @@ -31,7 +29,7 @@ import FFICXX.Generate.Util.GHCExactPrint import GHC.Hs (GhcPs) import GHC.Parser.Annotation (DeltaPos (..)) import Language.Haskell.Syntax - ( HsDecl (DocD, TyClD), + ( HsDecl (TyClD), HsLocalBindsLR (..), noExtField, ) diff --git a/fficxx/src/FFICXX/Generate/Code/HsFFI.hs b/fficxx/src/FFICXX/Generate/Code/HsFFI.hs index c27de5df..d21ded53 100644 --- a/fficxx/src/FFICXX/Generate/Code/HsFFI.hs +++ b/fficxx/src/FFICXX/Generate/Code/HsFFI.hs @@ -10,6 +10,7 @@ import FFICXX.Generate.Code.Primitive genericFuncArgs, genericFuncRet, hsFFIFunType, + toGHCSafety, ) import FFICXX.Generate.Dependency ( class_allparents, @@ -29,6 +30,7 @@ import FFICXX.Generate.Type.Class Selfness (NoSelf, Self), TLOrdinary (..), Variable (unVariable), + getFunSafety, isAbstractClass, isNewFunc, isStaticFunc, @@ -45,9 +47,8 @@ import FFICXX.Generate.Util.GHCExactPrint mkImport, ) import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..)) -import GHC.Hs - ( GhcPs, - ) +import FFICXX.Runtime.Types (FFISafety (FFIUnsafe)) +import GHC.Hs (GhcPs) import Language.Haskell.Syntax ( ForeignDecl, ImportDecl, @@ -80,6 +81,7 @@ hsFFIClassFunc headerfilename c f = then Nothing else let hfile = unHdrName headerfilename + safety = getFunSafety f -- TODO: Make this a separate function cname = ffiClassName c <> "_" <> aliasedFuncName c f csig = CFunSig (genericFuncArgs f) (genericFuncRet f) @@ -87,7 +89,7 @@ hsFFIClassFunc headerfilename c f = if (isNewFunc f || isStaticFunc f) then hsFFIFunType (Just (NoSelf, c)) csig else hsFFIFunType (Just (Self, c)) csig - in Just (mkForImpCcall (hfile <> " " <> cname) (hscFuncName c f) typ) + in Just (mkForImpCcall (toGHCSafety safety) (hfile <> " " <> cname) (hscFuncName c f) typ) hsFFIAccessor :: Class -> Variable -> Accessor -> ForeignDecl GhcPs hsFFIAccessor c v a = @@ -97,7 +99,7 @@ hsFFIAccessor c v a = hsFFIFunType (Just (Self, c)) (accessorCFunSig (arg_type (unVariable v)) a) - in mkForImpCcall cname (hscAccessorName c v a) typ + in mkForImpCcall (toGHCSafety FFIUnsafe) cname (hscAccessorName c v a) typ -- import for FFI genImportInFFI :: ClassModule -> [ImportDecl GhcPs] @@ -108,12 +110,23 @@ genImportInFFI = fmap (mkImport . subModuleName) . cmImportedSubmodulesForFFI ---------------------------- genTopLevelFFI :: TopLevelImportHeader -> TLOrdinary -> ForeignDecl GhcPs -genTopLevelFFI header tfn = mkForImpCcall (hfilename <> " TopLevel_" <> fname) cfname typ +genTopLevelFFI header tfn = + mkForImpCcall (toGHCSafety safety) (hfilename <> " TopLevel_" <> fname) cfname typ where - (fname, args, ret) = + (safety, fname, args, ret) = case tfn of - TopLevelFunction {..} -> (fromMaybe toplevelfunc_name toplevelfunc_alias, toplevelfunc_args, toplevelfunc_ret) - TopLevelVariable {..} -> (fromMaybe toplevelvar_name toplevelvar_alias, [], toplevelvar_ret) + TopLevelFunction {..} -> + ( toplevelfunc_safety, + fromMaybe toplevelfunc_name toplevelfunc_alias, + toplevelfunc_args, + toplevelfunc_ret + ) + TopLevelVariable {..} -> + ( FFIUnsafe, + fromMaybe toplevelvar_name toplevelvar_alias, + [], + toplevelvar_ret + ) hfilename = tihHeaderFileName header <.> "h" -- TODO: This must be exposed as a top-level function cfname = "c_" <> toLowers fname diff --git a/fficxx/src/FFICXX/Generate/Code/HsImplementation.hs b/fficxx/src/FFICXX/Generate/Code/HsImplementation.hs index 0e536146..651abe87 100644 --- a/fficxx/src/FFICXX/Generate/Code/HsImplementation.hs +++ b/fficxx/src/FFICXX/Generate/Code/HsImplementation.hs @@ -94,6 +94,7 @@ import FFICXX.Generate.Util.GHCExactPrint ) import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..)) import qualified FFICXX.Runtime.CodeGen.Cxx as R +import FFICXX.Runtime.Types (FFISafety (..)) import GHC.Hs (GhcPs) import Language.Haskell.Syntax (HsDecl, ImportDecl) @@ -186,12 +187,18 @@ genTMFExp c f = mkFun nh sig (tvars_p ++ [p "suffix"]) rhs bstmts | otherwise = [pTuple (fmap p tvars)] lit' = strE (hsTemplateMemberFunctionName c f <> "_") lam = lamE [p "n"] (lit' `app` v "<>" `app` v "n") + safety = + case tmf_safety f of + FFIUnsafe -> "FFIUnsafe" + FFISafe -> "FFISafe" + FFIInterruptible -> "FFIInterruptible" rhs = app (v "mkTFunc") $ - let typs - | nparams == 1 = fmap v tvars - | otherwise = [tupleE (map v tvars)] - in tupleE (typs ++ [v "suffix", lam, v "tyf"]) + app (v safety) $ + let typs + | nparams == 1 = fmap v tvars + | otherwise = [tupleE (map v tvars)] + in tupleE (typs ++ [v "suffix", lam, v "tyf"]) sig' = functionSignatureTMF c f tassgns = fmap diff --git a/fficxx/src/FFICXX/Generate/Code/HsTH.hs b/fficxx/src/FFICXX/Generate/Code/HsTH.hs index d48c7cf7..61d35e24 100644 --- a/fficxx/src/FFICXX/Generate/Code/HsTH.hs +++ b/fficxx/src/FFICXX/Generate/Code/HsTH.hs @@ -34,6 +34,7 @@ import FFICXX.Generate.Type.Class TemplateFunction (..), Types (Void), Variable (..), + getTFunSafety, ) import FFICXX.Generate.Type.Module ( TemplateClassImportHeader (..), @@ -78,6 +79,7 @@ import FFICXX.Generate.Util.GHCExactPrint import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..)) import qualified FFICXX.Runtime.CodeGen.Cxx as R import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim)) +import FFICXX.Runtime.Types (FFISafety (..)) import GHC.Hs (GhcPs) import Language.Haskell.Syntax ( HsDecl, @@ -111,10 +113,16 @@ genTmplImplementation t = nc = ffiTmplFuncName f lit' = strE (prefix <> "_" <> nc) lam = lamE [p "n"] (lit' `app` v "<>" `app` v "n") + safety = + case getTFunSafety f of + FFIUnsafe -> "FFIUnsafe" + FFISafe -> "FFISafe" + FFIInterruptible -> "FFIInterruptible" rhs = app (v "mkTFunc") $ - let typs = if nparams == 1 then map v tvars else [tupleE (map v tvars)] - in tupleE (typs ++ [v "suffix", lam, v "tyf"]) + app (v safety) $ + let typs = if nparams == 1 then map v tvars else [tupleE (map v tvars)] + in tupleE (typs ++ [v "suffix", lam, v "tyf"]) sig' = functionSignatureTT t f tassgns = fmap @@ -221,14 +229,16 @@ genTmplInstance tcih = let Variable (Arg {..}) = vf f_g = TFun - { tfun_ret = arg_type, + { tfun_safety = FFIUnsafe, + tfun_ret = arg_type, tfun_name = tmplAccessorName vf Getter, tfun_oname = tmplAccessorName vf Getter, tfun_args = [] } f_s = TFun - { tfun_ret = Void, + { tfun_safety = FFIUnsafe, + tfun_ret = Void, tfun_name = tmplAccessorName vf Setter, tfun_oname = tmplAccessorName vf Setter, tfun_args = [Arg arg_type "value"] diff --git a/fficxx/src/FFICXX/Generate/Code/HsTopLevel.hs b/fficxx/src/FFICXX/Generate/Code/HsTopLevel.hs index c4254d63..4a79059f 100644 --- a/fficxx/src/FFICXX/Generate/Code/HsTopLevel.hs +++ b/fficxx/src/FFICXX/Generate/Code/HsTopLevel.hs @@ -77,14 +77,12 @@ import FFICXX.Generate.Util.GHCExactPrint cxTuple, doE, eabs, - emodule, ethingall, evar, inapp, lamE, letE, listE, - mkBind1, mkBind1_, mkBindStmt, mkBodyStmt, @@ -106,7 +104,6 @@ import FFICXX.Generate.Util.GHCExactPrint strE, toLocalBinds, tupleE, - tyForall, tyParen, tySplice, tyTupleBoxed, @@ -115,13 +112,13 @@ import FFICXX.Generate.Util.GHCExactPrint tyfun, tylist, typeBracket, - unqual, valBinds, wildcard, ) import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..)) import qualified FFICXX.Runtime.CodeGen.Cxx as R import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim)) +import FFICXX.Runtime.Types (FFISafety (..)) import GHC.Hs (GhcPs) import Language.Haskell.Syntax ( HsDecl (TyClD), @@ -276,10 +273,16 @@ genTLTemplateImplementation t = nc = topleveltfunc_name t lit' = strE (prefix <> "_" <> nc) lam = lamE [p "n"] (lit' `app` v "<>" `app` v "n") + safety = + case topleveltfunc_safety t of + FFIUnsafe -> "FFIUnsafe" + FFISafe -> "FFISafe" + FFIInterruptible -> "FFIInterruptible" rhs = app (v "mkTFunc") $ - let typs = if nparams == 1 then map v tvars else [tupleE (map v tvars)] - in tupleE (typs ++ [v "suffix", lam, v "tyf"]) + app (v safety) $ + let typs = if nparams == 1 then map v tvars else [tupleE (map v tvars)] + in tupleE (typs ++ [v "suffix", lam, v "tyf"]) sig' = let e = error "genTLTemplateImplementation" spls = map (tySplice . parenSplice . mkVar) $ topleveltfunc_params t diff --git a/fficxx/src/FFICXX/Generate/Code/Primitive.hs b/fficxx/src/FFICXX/Generate/Code/Primitive.hs index 3dec48d6..ce9855c6 100644 --- a/fficxx/src/FFICXX/Generate/Code/Primitive.hs +++ b/fficxx/src/FFICXX/Generate/Code/Primitive.hs @@ -39,12 +39,19 @@ import FFICXX.Generate.Type.Class import qualified FFICXX.Generate.Util.GHCExactPrint as Ex import qualified FFICXX.Runtime.CodeGen.Cxx as R import FFICXX.Runtime.TH (IsCPrimitive (CPrim, NonCPrim)) +import FFICXX.Runtime.Types (FFISafety (..)) import GHC.Hs (GhcPs) +import qualified GHC.Types.ForeignCall as GHC (Safety (..)) import Language.Haskell.Syntax ( HsContext, HsType, ) +toGHCSafety :: FFISafety -> GHC.Safety +toGHCSafety FFIUnsafe = GHC.PlayRisky +toGHCSafety FFISafe = GHC.PlaySafe +toGHCSafety FFIInterruptible = GHC.PlayInterruptible + data CFunSig = CFunSig { cArgTypes :: [Arg], cRetType :: Types @@ -780,12 +787,12 @@ cxx2HsType4Tmpl _ _ _ (TemplateParam p) = Ex.tySplice . Ex.parenSplice . Ex.mkVa cxx2HsType4Tmpl _ _ _ (TemplateParamPointer p) = Ex.tySplice . Ex.parenSplice . Ex.mkVar $ p hsFuncXformer :: Function -> String -hsFuncXformer func@(Constructor _ _) = +hsFuncXformer func@(Constructor {}) = let len = length (genericFuncArgs func) in if len > 0 then "xform" <> show (len - 1) else "xformnull" -hsFuncXformer func@(Static _ _ _ _) = +hsFuncXformer func@(Static {}) = let len = length (genericFuncArgs func) in if len > 0 then "xform" <> show (len - 1) @@ -937,14 +944,16 @@ tmplAccessorToTFun v@(Variable (Arg {..})) a = case a of Getter -> TFun - { tfun_ret = arg_type, + { tfun_safety = FFIUnsafe, + tfun_ret = arg_type, tfun_name = tmplAccessorName v Getter, tfun_oname = tmplAccessorName v Getter, tfun_args = [] } Setter -> TFun - { tfun_ret = Void, + { tfun_safety = FFIUnsafe, + tfun_ret = Void, tfun_name = tmplAccessorName v Setter, tfun_oname = tmplAccessorName v Setter, tfun_args = [Arg arg_type "value"] @@ -1075,11 +1084,9 @@ hsFFIFunType msc (CFunSig args ret) = genericFuncRet :: Function -> Types genericFuncRet f = case f of - Constructor _ _ -> self_ - Virtual t _ _ _ -> t - NonVirtual t _ _ _ -> t - Static t _ _ _ -> t - Destructor _ -> void_ + Constructor {} -> self_ + Destructor {} -> void_ + _ -> func_ret f genericFuncArgs :: Function -> [Arg] genericFuncArgs (Destructor _) = [] diff --git a/fficxx/src/FFICXX/Generate/ContentMaker.hs b/fficxx/src/FFICXX/Generate/ContentMaker.hs index 600b095b..6026fa7d 100644 --- a/fficxx/src/FFICXX/Generate/ContentMaker.hs +++ b/fficxx/src/FFICXX/Generate/ContentMaker.hs @@ -499,7 +499,8 @@ buildImplementationHs amap m = Ex.mkImport "System.IO.Unsafe", Ex.mkImport "FFICXX.Runtime.Cast", Ex.mkImport "FFICXX.Runtime.CodeGen.Cxx", -- for template member - Ex.mkImport "FFICXX.Runtime.TH" -- for template member + Ex.mkImport "FFICXX.Runtime.TH", -- for template member + Ex.mkImport "FFICXX.Runtime.Types" -- for template member ] <> genImportInImplementation m <> genExtraImport m @@ -567,7 +568,8 @@ buildTHHs m = Ex.mkImport "Language.Haskell.TH", Ex.mkImport "Language.Haskell.TH.Syntax", Ex.mkImport "FFICXX.Runtime.CodeGen.Cxx", - Ex.mkImport "FFICXX.Runtime.TH" + Ex.mkImport "FFICXX.Runtime.TH", + Ex.mkImport "FFICXX.Runtime.Types" ] <> imports ) @@ -595,11 +597,10 @@ buildModuleHs m = c = cihClass (cmCIH m) buildEnumHsc :: - AnnotateMap -> String -> [EnumType] -> HsModule GhcPs -buildEnumHsc amap modname enums = +buildEnumHsc modname enums = Ex.mkModuleE modname [] Nothing [] body where body = @@ -721,7 +722,8 @@ buildTopLevelTHHs modname tih = Ex.mkImport "Language.Haskell.TH", Ex.mkImport "Language.Haskell.TH.Syntax", Ex.mkImport "FFICXX.Runtime.CodeGen.Cxx", - Ex.mkImport "FFICXX.Runtime.TH" + Ex.mkImport "FFICXX.Runtime.TH", + Ex.mkImport "FFICXX.Runtime.Types" ] ++ concatMap genImportForTLTemplate tfns pkgBody = diff --git a/fficxx/src/FFICXX/Generate/Dependency.hs b/fficxx/src/FFICXX/Generate/Dependency.hs index 0479f980..9a1be453 100644 --- a/fficxx/src/FFICXX/Generate/Dependency.hs +++ b/fficxx/src/FFICXX/Generate/Dependency.hs @@ -155,23 +155,23 @@ data Dep4Func = Dep4Func extractClassDep :: Function -> Dep4Func extractClassDep (Constructor args _) = Dep4Func [] (concatMap classFromArg args) -extractClassDep (Virtual ret _ args _) = +extractClassDep (Virtual _ ret _ args _) = Dep4Func (extractClassFromType ret) (concatMap classFromArg args) -extractClassDep (NonVirtual ret _ args _) = +extractClassDep (NonVirtual _ ret _ args _) = Dep4Func (extractClassFromType ret) (concatMap classFromArg args) -extractClassDep (Static ret _ args _) = +extractClassDep (Static _ ret _ args _) = Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDep (Destructor _) = Dep4Func [] [] extractClassDepForTmplFun :: TemplateFunction -> Dep4Func -extractClassDepForTmplFun (TFun ret _ _ args) = +extractClassDepForTmplFun (TFun _ ret _ _ args) = Dep4Func (extractClassFromType ret) (concatMap classFromArg args) extractClassDepForTmplFun (TFunNew args _) = Dep4Func [] (concatMap classFromArg args) extractClassDepForTmplFun TFunDelete = Dep4Func [] [] -extractClassDepForTmplFun (TFunOp ret _ e) = +extractClassDepForTmplFun (TFunOp _ ret _ e) = Dep4Func (extractClassFromType ret) (concatMap classFromArg $ argsFromOpExp e) extractClassDep4TmplMemberFun :: TemplateMemberFunction -> Dep4Func diff --git a/fficxx/src/FFICXX/Generate/Name.hs b/fficxx/src/FFICXX/Generate/Name.hs index c7eb6aee..60ddd536 100644 --- a/fficxx/src/FFICXX/Generate/Name.hs +++ b/fficxx/src/FFICXX/Generate/Name.hs @@ -98,9 +98,9 @@ aliasedFuncName :: Class -> Function -> String aliasedFuncName c f = case f of Constructor _ a -> fromMaybe (constructorName c) a - Virtual _ str _ a -> fromMaybe str a - NonVirtual _ str _ a -> fromMaybe (nonvirtualName c str) a - Static _ str _ a -> fromMaybe (nonvirtualName c str) a + Virtual _ _ str _ a -> fromMaybe str a + NonVirtual _ _ str _ a -> fromMaybe (nonvirtualName c str) a + Static _ _ str _ a -> fromMaybe (nonvirtualName c str) a Destructor a -> fromMaybe destructorName a hsTmplFuncName :: TemplateClass -> TemplateFunction -> String @@ -156,11 +156,11 @@ cppStaticName c f = class_name c <> "::" <> func_name f cppFuncName :: Class -> Function -> String cppFuncName c f = case f of - Constructor _ _ -> "new" - Virtual _ _ _ _ -> func_name f - NonVirtual _ _ _ _ -> func_name f - Static _ _ _ _ -> cppStaticName c f - Destructor _ -> destructorName + Constructor {} -> "new" + Virtual {} -> func_name f + NonVirtual {} -> func_name f + Static {} -> cppStaticName c f + Destructor {} -> destructorName constructorName :: Class -> String constructorName c = "new" <> (fst . hsClassName) c diff --git a/fficxx/src/FFICXX/Generate/Type/Class.hs b/fficxx/src/FFICXX/Generate/Type/Class.hs index aa1f7fcd..07046e3e 100644 --- a/fficxx/src/FFICXX/Generate/Type/Class.hs +++ b/fficxx/src/FFICXX/Generate/Type/Class.hs @@ -9,6 +9,7 @@ import Data.List (intercalate) import qualified Data.Map as M import Data.Maybe (mapMaybe) import FFICXX.Generate.Type.Cabal (Cabal) +import FFICXX.Runtime.Types (FFISafety (..)) -- | C types data CTypes @@ -128,19 +129,22 @@ data Function func_alias :: Maybe String } | Virtual - { func_ret :: Types, + { func_safety :: FFISafety, + func_ret :: Types, func_name :: String, func_args :: [Arg], func_alias :: Maybe String } | NonVirtual - { func_ret :: Types, + { func_safety :: FFISafety, + func_ret :: Types, func_name :: String, func_args :: [Arg], func_alias :: Maybe String } | Static - { func_ret :: Types, + { func_safety :: FFISafety, + func_ret :: Types, func_name :: String, func_args :: [Arg], func_alias :: Maybe String @@ -156,7 +160,8 @@ newtype Variable = Variable {unVariable :: Arg} -- | Member functions of a template class. data TemplateMemberFunction = TemplateMemberFunction - { tmf_params :: [String], + { tmf_safety :: FFISafety, + tmf_params :: [String], tmf_ret :: Types, tmf_name :: String, tmf_args :: [Arg], @@ -179,7 +184,8 @@ filterTLTemplate = mapMaybe (\case TLTemplate f -> Just f; _ -> Nothing) data TLOrdinary = TopLevelFunction - { toplevelfunc_ret :: Types, + { toplevelfunc_safety :: FFISafety, + toplevelfunc_ret :: Types, toplevelfunc_name :: String, toplevelfunc_args :: [Arg], toplevelfunc_alias :: Maybe String @@ -192,7 +198,8 @@ data TLOrdinary deriving (Show) data TLTemplate = TopLevelTemplateFunction - { topleveltfunc_params :: [String], + { topleveltfunc_safety :: FFISafety, + topleveltfunc_params :: [String], topleveltfunc_ret :: Types, topleveltfunc_name :: String, topleveltfunc_oname :: String, @@ -200,25 +207,30 @@ data TLTemplate = TopLevelTemplateFunction } deriving (Show) +getFunSafety :: Function -> FFISafety +getFunSafety (Constructor {}) = FFIUnsafe +getFunSafety (Destructor {}) = FFIUnsafe +getFunSafety f = func_safety f + isNewFunc :: Function -> Bool -isNewFunc (Constructor _ _) = True +isNewFunc (Constructor {}) = True isNewFunc _ = False isDeleteFunc :: Function -> Bool -isDeleteFunc (Destructor _) = True +isDeleteFunc (Destructor {}) = True isDeleteFunc _ = False isVirtualFunc :: Function -> Bool -isVirtualFunc (Destructor _) = True -isVirtualFunc (Virtual _ _ _ _) = True +isVirtualFunc (Destructor {}) = True +isVirtualFunc (Virtual {}) = True isVirtualFunc _ = False isNonVirtualFunc :: Function -> Bool -isNonVirtualFunc (NonVirtual _ _ _ _) = True +isNonVirtualFunc (NonVirtual {}) = True isNonVirtualFunc _ = False isStaticFunc :: Function -> Bool -isStaticFunc (Static _ _ _ _) = True +isStaticFunc (Static {}) = True isStaticFunc _ = False virtualFuncs :: [Function] -> [Function] @@ -290,7 +302,8 @@ data OpExp data TemplateFunction = TFun - { tfun_ret :: Types, + { tfun_safety :: FFISafety, + tfun_ret :: Types, tfun_name :: String, tfun_oname :: String, tfun_args :: [Arg] @@ -301,12 +314,18 @@ data TemplateFunction } | TFunDelete | TFunOp - { tfun_ret :: Types, + { tfun_safety :: FFISafety, + tfun_ret :: Types, -- | haskell alias for the operator tfun_name :: String, tfun_opexp :: OpExp } +getTFunSafety :: TemplateFunction -> FFISafety +getTFunSafety TFunNew {} = FFIUnsafe +getTFunSafety TFunDelete {} = FFIUnsafe +getTFunSafety f = tfun_safety f + argsFromOpExp :: OpExp -> [Arg] argsFromOpExp OpStar = [] argsFromOpExp OpFPPlus = [] diff --git a/fficxx/src/FFICXX/Generate/Util/GHCExactPrint.hs b/fficxx/src/FFICXX/Generate/Util/GHCExactPrint.hs index f972191b..9f9f9885 100644 --- a/fficxx/src/FFICXX/Generate/Util/GHCExactPrint.hs +++ b/fficxx/src/FFICXX/Generate/Util/GHCExactPrint.hs @@ -140,7 +140,7 @@ import GHC.Parser.Annotation AnnSortKey (..), DeltaPos (..), EpAnn (..), - EpAnnComments (EpaComments, EpaCommentsBalanced), + EpAnnComments (EpaComments), EpaComment (..), EpaCommentTok (..), EpaLocation (..), @@ -155,7 +155,6 @@ import GHC.Parser.Annotation TrailingAnn (..), emptyComments, noAnn, - noSrcSpanA, spanAsAnchor, ) import GHC.Types.Basic @@ -171,7 +170,6 @@ import GHC.Types.ForeignCall ) import GHC.Types.Name.Occurrence ( OccName, - mkOccName, mkTyVarOcc, mkVarOcc, ) @@ -189,19 +187,16 @@ import GHC.Types.SrcLoc RealSrcSpan, SrcSpan (..), mkSrcLoc, - mkSrcSpan, srcLocSpan, ) import qualified Language.Haskell.GHC.ExactPrint as Exact import Language.Haskell.Syntax - ( Anno, - CImportSpec (CFunction), + ( CImportSpec (CFunction), ClsInstDecl (..), ConDecl (..), DataDefnCons (..), DerivClauseTys (..), DocDecl (..), - ExprLStmt, FamEqn (..), ForeignDecl (..), ForeignImport (CImport), @@ -547,11 +542,22 @@ mkImportSrc name = -- NOTE: Unfortunately, the location annotation of GHC API for foreign import is not fully relative, -- i.e. we cannot place correct spaces between "import", "ccall" and "safe", and the generated result -- is not a valid Haskell code. So as a workaround we need to put a place holder in comment. -mkForImpCcall :: String -> String -> HsType GhcPs -> ForeignDecl GhcPs -mkForImpCcall quote fname typ = +mkForImpCcall :: + Safety -> + String -> + String -> + HsType GhcPs -> + ForeignDecl GhcPs +mkForImpCcall safety quote fname typ = ForeignImport (mkRelEpAnn (-1) annos) lid lsigty forImp where quote' = show quote + for_imp_header = + "foreign import ccall " + <> case safety of + PlayRisky -> "unsafe" + PlaySafe -> "safe" + PlayInterruptible -> "interruptible" annos = [ AddEpAnn AnnForeign @@ -561,7 +567,9 @@ mkForImpCcall quote fname typ = (mkRelAnchor 0) ( EpaComment ( EpaBlockComment - ( "{- REPLACE_THIS_LINE |foreign import ccall interruptible \"" + ( "{- REPLACE_THIS_LINE |" + <> for_imp_header + <> " \"" <> quote <> "\"| -}" ) @@ -585,7 +593,7 @@ mkForImpCcall quote fname typ = CImport (L defSrcSpan {- anchor_op = MovedAnchor (SameLine 1) -} (SourceText quote')) (L defSrcSpan {- anchor_op = MovedAnchor (SameLine 1) -} StdCallConv) - (L defSrcSpan {- anchor_op = MovedAnchor (SameLine 1) -} PlayInterruptible) + (L defSrcSpan {- anchor_op = MovedAnchor (SameLine 1) -} safety) Nothing ( CFunction (StaticTarget (SourceText quote) (fromString quote) Nothing True) diff --git a/stdcxx-gen/Gen.hs b/stdcxx-gen/Gen.hs index c563c681..5c3549ef 100644 --- a/stdcxx-gen/Gen.hs +++ b/stdcxx-gen/Gen.hs @@ -51,6 +51,7 @@ import FFICXX.Generate.Type.Config import FFICXX.Generate.Type.Module (TemplateClassImportHeader (..)) import FFICXX.Generate.Type.PackageInterface () import FFICXX.Runtime.CodeGen.Cxx (HeaderName (..), Namespace (..)) +import FFICXX.Runtime.Types (FFISafety (..)) import System.Directory (getCurrentDirectory) import System.FilePath (()) @@ -97,9 +98,9 @@ string = mempty (Just (ClassAlias {caHaskellName = "CppString", caFFIName = "string"})) [ Constructor [cstring "p"] Nothing, - NonVirtual cstring_ "c_str" [] Nothing, - NonVirtual (cppclassref_ string) "append" [cppclassref string "str"] Nothing, - NonVirtual (cppclassref_ string) "erase" [] Nothing + NonVirtual FFIUnsafe cstring_ "c_str" [] Nothing, + NonVirtual FFIUnsafe (cppclassref_ string) "append" [cppclassref string "str"] Nothing, + NonVirtual FFIUnsafe (cppclassref_ string) "erase" [] Nothing ] [] [] @@ -155,6 +156,7 @@ t_map = ["tpk", "tpv"] [ TFunNew [] Nothing, TFun + FFIUnsafe ( TemplateAppRef TemplateAppInfo { tapp_tclass = t_map_iterator, @@ -166,6 +168,7 @@ t_map = "begin" [], TFun + FFIUnsafe ( TemplateAppRef TemplateAppInfo { tapp_tclass = t_map_iterator, @@ -177,6 +180,7 @@ t_map = "end" [], TFun + FFIUnsafe void_ -- until pair is allowed "insert" "insert" @@ -190,7 +194,7 @@ t_map = ) "val" ], - TFun int_ "size" "size" [], + TFun FFIUnsafe int_ "size" "size" [], TFunDelete ] [] @@ -203,7 +207,8 @@ t_map_iterator = (FormNested "std::map" "iterator") ["tpk", "tpv"] [ TFunOp - { tfun_ret = + { tfun_safety = FFIUnsafe, + tfun_ret = TemplateApp TemplateAppInfo { tapp_tclass = t_pair, @@ -214,7 +219,8 @@ t_map_iterator = tfun_opexp = OpStar }, TFunOp - { tfun_ret -- TODO: this should be handled with self + { tfun_safety = FFIUnsafe, + tfun_ret -- TODO: this should be handled with self = TemplateApp TemplateAppInfo @@ -237,6 +243,7 @@ t_vector = ["tp1"] [ TFunNew [] Nothing, TFun + FFIUnsafe ( TemplateAppRef TemplateAppInfo { tapp_tclass = t_vector_iterator, @@ -248,6 +255,7 @@ t_vector = "begin" [], TFun + FFIUnsafe ( TemplateAppRef TemplateAppInfo { tapp_tclass = t_vector_iterator, @@ -258,10 +266,10 @@ t_vector = "end" "end" [], - TFun void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], - TFun void_ "pop_back" "pop_back" [], - TFun (TemplateParam "tp1") "at" "at" [int "n"], - TFun int_ "size" "size" [], + TFun FFIUnsafe void_ "push_back" "push_back" [Arg (TemplateParam "tp1") "x"], + TFun FFIUnsafe void_ "pop_back" "pop_back" [], + TFun FFIUnsafe (TemplateParam "tp1") "at" "at" [int "n"], + TFun FFIUnsafe int_ "size" "size" [], TFunDelete ] [] @@ -274,12 +282,14 @@ t_vector_iterator = (FormNested "std::vector" "iterator") ["tp1"] [ TFunOp - { tfun_ret = TemplateParam "tp1", + { tfun_safety = FFIUnsafe, + tfun_ret = TemplateParam "tp1", tfun_name = "deRef", tfun_opexp = OpStar }, TFunOp - { tfun_ret -- TODO: this should be handled with self + { tfun_safety = FFIUnsafe, + tfun_ret -- TODO: this should be handled with self = TemplateApp TemplateAppInfo @@ -302,9 +312,9 @@ t_unique_ptr = ["tp1"] [ TFunNew [] (Just "newUniquePtr0"), TFunNew [Arg (TemplateParamPointer "tp1") "p"] Nothing, - TFun (TemplateParamPointer "tp1") "get" "get" [], - TFun (TemplateParamPointer "tp1") "release" "release" [], - TFun void_ "reset" "reset" [], + TFun FFIUnsafe (TemplateParamPointer "tp1") "get" "get" [], + TFun FFIUnsafe (TemplateParamPointer "tp1") "release" "release" [], + TFun FFIUnsafe void_ "reset" "reset" [], TFunDelete ] [] @@ -318,9 +328,9 @@ t_shared_ptr = ["tp1"] [ TFunNew [] (Just "newSharedPtr0"), TFunNew [Arg (TemplateParamPointer "tp1") "p"] Nothing, - TFun (TemplateParamPointer "tp1") "get" "get" [], - TFun void_ "reset" "reset" [], - TFun int_ "use_count" "use_count" [], + TFun FFIUnsafe (TemplateParamPointer "tp1") "get" "get" [], + TFun FFIUnsafe void_ "reset" "reset" [], + TFun FFIUnsafe int_ "use_count" "use_count" [], TFunDelete ] []