Skip to content

Commit 1fce8ae

Browse files
committed
Remove EngineAccess wrapper
1 parent bc5f593 commit 1fce8ae

5 files changed

Lines changed: 81 additions & 151 deletions

File tree

LLVM/Core/Vector.hs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import Data.Function
55
import Data.TypeLevel hiding (Eq, (+), (==), (-), (*), succ, pred, div, mod, divMod, logBase)
66
import LLVM.Core.Type
77
import LLVM.Core.Data
8+
import LLVM.ExecutionEngine (ExecutionEngine)
89
import LLVM.ExecutionEngine.Target
910
import Foreign.Ptr(castPtr)
1011
import Foreign.Storable(Storable(..))
@@ -36,15 +37,17 @@ instance (IsPrimitive a) => MkVector (a, a, a, a, a, a, a, a) D8 a where
3637
fromVector (Vector [a1, a2, a3, a4, a5, a6, a7, a8]) = (a1, a2, a3, a4, a5, a6, a7, a8)
3738
fromVector _ = error "fromVector: impossible"
3839

40+
{-
3941
instance (Storable a, Pos n, IsPrimitive a) => Storable (Vector n a) where
4042
sizeOf a = storeSizeOfType ourTargetData (typeRef a)
4143
alignment a = aBIAlignmentOfType ourTargetData (typeRef a)
4244
peek p = fmap Vector $ peekArray (toNum (undefined :: n)) (castPtr p :: Ptr a)
4345
poke p (Vector vs) = pokeArray (castPtr p :: Ptr a) vs
46+
-}
4447

4548
-- XXX The JITer target data. This isn't really right.
46-
ourTargetData :: TargetData
47-
ourTargetData = unsafePerformIO getTargetData
49+
ourTargetData :: ExecutionEngine -> TargetData
50+
ourTargetData = unsafePerformIO . getTargetData
4851

4952
--------------------------------------
5053

LLVM/ExecutionEngine.hs

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
-- |An 'ExecutionEngine' is JIT compiler that is used to generate code for an LLVM module.
33
module LLVM.ExecutionEngine(
44
-- * Execution engine
5-
EngineAccess,
6-
runEngineAccess,
5+
ExecutionEngine,
6+
createExecutionEngine,
7+
destroyExecutionEngine,
8+
touchExecutionEngine,
79
addModule,
810
removeModule,
9-
{-
1011
runStaticConstructors,
1112
runStaticDestructors,
12-
-}
1313
getPointerToFunction,
1414
addFunctionValue,
1515
addGlobalMappings,
@@ -31,11 +31,11 @@ import System.IO.Unsafe (unsafePerformIO)
3131

3232
import LLVM.ExecutionEngine.Engine
3333
import LLVM.FFI.Core(ValueRef)
34-
import LLVM.Core.CodeGen(Value(..))
35-
import LLVM.Core
34+
import LLVM.Core.CodeGen
35+
import LLVM.Core.CodeGenMonad
3636
import LLVM.ExecutionEngine.Target
37-
--import LLVM.Core.Util(runFunctionPassManager, initializeFunctionPassManager, finalizeFunctionPassManager)
3837
import Control.Monad (liftM2, )
38+
import Foreign.Ptr (Ptr)
3939

4040
-- |Class of LLVM function types that can be translated to the corresponding
4141
-- Haskell type.
@@ -54,9 +54,10 @@ instance (Generic a) => Translatable (IO a) where
5454
-- If you want to compile the function once and call it a lot of times
5555
-- then you should better use 'getPointerToFunction'.
5656
generateFunction :: (Translatable f) =>
57-
Value (Ptr f) -> EngineAccess f
58-
generateFunction (Value f) = do
59-
run <- getRunFunction
57+
ExecutionEngine ->
58+
Value (Ptr f) -> IO f
59+
generateFunction ee (Value f) = do
60+
run <- getRunFunction ee
6061
return $ translate run [] f
6162

6263
class Unsafe a b | a -> b where
@@ -71,14 +72,13 @@ instance Unsafe (IO a) a where
7172
-- |Translate a function to Haskell code. This is a simplified interface to
7273
-- the execution engine and module mechanism.
7374
-- It is based on 'generateFunction', so see there for limitations.
74-
simpleFunction :: (Translatable f) => CodeGenModule (Function f) -> IO f
75-
simpleFunction bld = do
75+
simpleFunction :: (Translatable f) => ExecutionEngine -> CodeGenModule (Function f) -> IO f
76+
simpleFunction ee bld = do
7677
m <- newModule
7778
(func, mappings) <- defineModule m (liftM2 (,) bld getGlobalMappings)
78-
runEngineAccess $ do
79-
addModule m
80-
addGlobalMappings mappings
81-
generateFunction func
79+
addModule ee m
80+
addGlobalMappings ee mappings
81+
generateFunction ee func
8282

8383
{-
8484
m <- newModule
@@ -106,7 +106,7 @@ simpleFunction bld = do
106106

107107
-- | Combine 'simpleFunction' and 'unsafePurify'.
108108
unsafeGenerateFunction :: (Unsafe t a, Translatable t) =>
109-
CodeGenModule (Function t) -> a
110-
unsafeGenerateFunction bld = unsafePerformIO $ do
111-
fun <- simpleFunction bld
109+
ExecutionEngine -> CodeGenModule (Function t) -> a
110+
unsafeGenerateFunction ee bld = unsafePerformIO $ do
111+
fun <- simpleFunction ee bld
112112
return $ unsafePurify fun

LLVM/ExecutionEngine/Engine.hs

Lines changed: 45 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
1-
{-# LANGUAGE ForeignFunctionInterface, FlexibleInstances, UndecidableInstances, OverlappingInstances, ScopedTypeVariables, GeneralizedNewtypeDeriving, DeriveDataTypeable #-}
1+
{-# LANGUAGE ForeignFunctionInterface, FlexibleInstances, UndecidableInstances, OverlappingInstances, ScopedTypeVariables, GeneralizedNewtypeDeriving #-}
22
module LLVM.ExecutionEngine.Engine(
3-
EngineAccess,
4-
runEngineAccess,
5-
{-
63
ExecutionEngine,
7-
-}
8-
createExecutionEngine, addModule, removeModule,
9-
{- runStaticConstructors, runStaticDestructors, -}
4+
createExecutionEngine, destroyExecutionEngine, touchExecutionEngine,
5+
addModule, removeModule,
6+
runStaticConstructors, runStaticDestructors,
107
getExecutionEngineTargetData,
118
getPointerToFunction,
129
addFunctionValue, addGlobalMappings,
@@ -16,14 +13,11 @@ module LLVM.ExecutionEngine.Engine(
1613
GenericValue, Generic(..)
1714
) where
1815
import Control.Monad.State
19-
import Control.Applicative (Applicative, )
20-
import Control.Concurrent.MVar
21-
import Data.Typeable
2216
import Data.Int
2317
import Data.Word
2418
import Foreign.Marshal.Alloc (alloca, free)
2519
import Foreign.Marshal.Array (withArrayLen)
26-
import Foreign.ForeignPtr (ForeignPtr, newForeignPtr, withForeignPtr)
20+
import Foreign.ForeignPtr (ForeignPtr, finalizeForeignPtr, newForeignPtr, touchForeignPtr, withForeignPtr)
2721
import Foreign.Marshal.Utils (fromBool)
2822
import Foreign.C.String (peekCString)
2923
import Foreign.Ptr (Ptr, FunPtr, castFunPtrToPtr)
@@ -33,14 +27,13 @@ import Foreign.Storable (peek)
3327
import Foreign.StablePtr (StablePtr, castStablePtrToPtr, castPtrToStablePtr, )
3428
import System.IO.Unsafe (unsafePerformIO)
3529

36-
import LLVM.Core.Util(Module, createModule)
30+
import LLVM.Core.Util (Module)
3731
import qualified LLVM.FFI.ExecutionEngine as FFI
3832
import qualified LLVM.FFI.Target as FFI
3933
import qualified LLVM.FFI.Core as FFI(ValueRef)
4034
import qualified LLVM.Core.Util as U
4135
import LLVM.Core.Type(IsFirstClass, typeRef)
4236

43-
{-
4437
-- |The type of the JITer.
4538
newtype ExecutionEngine = ExecutionEngine {
4639
fromExecutionEngine :: ForeignPtr FFI.ExecutionEngine
@@ -52,20 +45,26 @@ withExecutionEngine = withForeignPtr . fromExecutionEngine
5245

5346
-- |Create an execution engine for a module provider.
5447
-- Warning, do not call this function more than once.
55-
createExecutionEngine :: ModuleProvider -> IO ExecutionEngine
56-
createExecutionEngine prov =
57-
withModuleProvider prov $ \provPtr ->
48+
createExecutionEngine :: Module -> IO ExecutionEngine
49+
createExecutionEngine m =
50+
U.withModule m $ \mPtr ->
5851
alloca $ \eePtr ->
5952
alloca $ \errPtr -> do
60-
ret <- FFI.createExecutionEngine eePtr provPtr errPtr
61-
if ret == 1
53+
ret <- FFI.createExecutionEngineForModule eePtr mPtr errPtr
54+
if ret
6255
then do err <- peek errPtr
6356
errStr <- peekCString err
6457
free err
6558
ioError . userError $ errStr
6659
else do ptr <- peek eePtr
6760
liftM ExecutionEngine $ newForeignPtr FFI.ptrDisposeExecutionEngine ptr
6861

62+
destroyExecutionEngine :: ExecutionEngine -> IO ()
63+
destroyExecutionEngine = finalizeForeignPtr . fromExecutionEngine
64+
65+
touchExecutionEngine :: ExecutionEngine -> IO ()
66+
touchExecutionEngine = touchForeignPtr . fromExecutionEngine
67+
6968
runStaticConstructors :: ExecutionEngine -> IO ()
7069
runStaticConstructors ee = withExecutionEngine ee FFI.runStaticConstructors
7170

@@ -75,70 +74,6 @@ runStaticDestructors ee = withExecutionEngine ee FFI.runStaticDestructors
7574
getExecutionEngineTargetData :: ExecutionEngine -> IO FFI.TargetDataRef
7675
getExecutionEngineTargetData ee = withExecutionEngine ee FFI.getExecutionEngineTargetData
7776

78-
getPointerToFunction :: ExecutionEngine -> Function f -> IO (FunPtr f)
79-
getPointerToFunction ee (Value f) =
80-
withExecutionEngine ee $ \ eePtr ->
81-
FFI.getPointerToGlobal eePtr f
82-
-}
83-
84-
-- This global variable holds the one and only execution engine.
85-
-- It may be missing, but it never dies.
86-
-- XXX We could provide a destructor, what about functions obtained by runFunction?
87-
{-# NOINLINE theEngine #-}
88-
theEngine :: MVar (Maybe (Ptr FFI.ExecutionEngine))
89-
theEngine = unsafePerformIO $ newMVar Nothing
90-
91-
createExecutionEngine :: Module -> IO (Ptr FFI.ExecutionEngine)
92-
createExecutionEngine m =
93-
U.withModule m $ \ mPtr ->
94-
alloca $ \eePtr ->
95-
alloca $ \errPtr -> do
96-
failed <- FFI.createJITCompilerForModule eePtr mPtr 2 errPtr
97-
if failed
98-
then do
99-
err <- peek errPtr
100-
errStr <- peekCString err
101-
free err
102-
ioError . userError $ errStr
103-
else
104-
peek eePtr
105-
106-
getTheEngine :: IO (Ptr FFI.ExecutionEngine)
107-
getTheEngine = do
108-
mee <- takeMVar theEngine
109-
case mee of
110-
Just ee -> do putMVar theEngine mee; return ee
111-
Nothing -> do
112-
m <- createModule "__empty__"
113-
ee <- createExecutionEngine m
114-
putMVar theEngine (Just ee)
115-
return ee
116-
117-
data EAState = EAState {
118-
ea_engine :: Ptr FFI.ExecutionEngine,
119-
ea_modules :: [Module]
120-
}
121-
deriving (Show, Typeable)
122-
123-
newtype EngineAccess a = EA (StateT EAState IO a)
124-
deriving (Functor, Applicative, Monad, MonadState EAState, MonadIO)
125-
126-
-- |The LLVM execution engine is encapsulated so it cannot be accessed directly.
127-
-- The reason is that (currently) there must only ever be one engine,
128-
-- so access to it is wrapped in a monad.
129-
runEngineAccess :: EngineAccess a -> IO a
130-
runEngineAccess (EA body) = do
131-
eePtr <- getTheEngine
132-
let ea = EAState { ea_engine = eePtr, ea_modules = [] }
133-
(a, _ea') <- runStateT body ea
134-
-- XXX should remove module providers again
135-
return a
136-
137-
getExecutionEngineTargetData :: EngineAccess FFI.TargetDataRef
138-
getExecutionEngineTargetData = do
139-
eePtr <- gets ea_engine
140-
liftIO $ FFI.getExecutionEngineTargetData eePtr
141-
14277
{- |
14378
In contrast to 'generateFunction' this compiles a function once.
14479
Thus it is faster for many calls to the same function.
@@ -148,43 +83,40 @@ If the function calls back into Haskell code,
14883
you also have to set the function addresses
14984
using 'addFunctionValue' or 'addGlobalMappings'.
15085
-}
151-
getPointerToFunction :: Function f -> EngineAccess (FunPtr f)
152-
getPointerToFunction (Value f) = do
153-
eePtr <- gets ea_engine
154-
liftIO $ FFI.getPointerToGlobal eePtr f
86+
getPointerToFunction :: ExecutionEngine -> Function f -> IO (FunPtr f)
87+
getPointerToFunction ee (Value f) =
88+
withExecutionEngine ee $ \ eePtr ->
89+
FFI.getPointerToGlobal eePtr f
15590

15691
{- |
15792
Tell LLVM the address of an external function
15893
if it cannot resolve a name automatically.
15994
Alternatively you may declare the function
16095
with 'staticFunction' instead of 'externFunction'.
16196
-}
162-
addFunctionValue :: Function f -> FunPtr f -> EngineAccess ()
163-
addFunctionValue (Value g) f =
164-
addFunctionValueCore g (castFunPtrToPtr f)
97+
addFunctionValue :: ExecutionEngine -> Function f -> FunPtr f -> IO ()
98+
addFunctionValue ee (Value g) f =
99+
addFunctionValueCore ee g (castFunPtrToPtr f)
165100

166101
{- |
167102
Pass a list of global mappings to LLVM
168103
that can be obtained from 'LLVM.Core.getGlobalMappings'.
169104
-}
170-
addGlobalMappings :: GlobalMappings -> EngineAccess ()
171-
addGlobalMappings (GlobalMappings gms) =
172-
mapM_ (uncurry addFunctionValueCore) gms
173-
174-
addFunctionValueCore :: U.Function -> Ptr () -> EngineAccess ()
175-
addFunctionValueCore g f = do
176-
eePtr <- gets ea_engine
177-
liftIO $ FFI.addGlobalMapping eePtr g f
178-
179-
addModule :: Module -> EngineAccess ()
180-
addModule m = do
181-
eePtr <- gets ea_engine
105+
addGlobalMappings :: ExecutionEngine -> GlobalMappings -> IO ()
106+
addGlobalMappings ee (GlobalMappings gms) =
107+
mapM_ (uncurry (addFunctionValueCore ee)) gms
108+
109+
addFunctionValueCore :: ExecutionEngine -> U.Function -> Ptr () -> IO ()
110+
addFunctionValueCore ee g f = withExecutionEngine ee $ \eePtr ->
111+
FFI.addGlobalMapping eePtr g f
112+
113+
addModule :: ExecutionEngine -> Module -> IO ()
114+
addModule ee m = withExecutionEngine ee $ \eePtr ->
182115
liftIO $ U.withModule m $ \ mPtr -> do
183116
FFI.addModule eePtr mPtr
184117

185-
removeModule :: Module -> EngineAccess ()
186-
removeModule m = do
187-
eePtr <- gets ea_engine
118+
removeModule :: ExecutionEngine -> Module -> IO ()
119+
removeModule ee m = withExecutionEngine ee $ \eePtr ->
188120
liftIO $ U.withModule m $ \ mPtr ->
189121
alloca $ \ unused1 ->
190122
alloca $ \ unused2 -> do
@@ -195,10 +127,9 @@ removeModule m = do
195127
-- Freeing code might have to be done from a (C) finalizer, so it has to done from C.
196128
-- The function c_freeFunctionObject take these pointers as arguments and frees the function.
197129
type FreePointers = (Ptr FFI.ExecutionEngine, FFI.ValueRef)
198-
getFreePointers :: Function f -> EngineAccess FreePointers
199-
getFreePointers (Value f) = do
200-
ea <- get
201-
return (ea_engine ea, f)
130+
getFreePointers :: ExecutionEngine -> Function f -> IO FreePointers
131+
getFreePointers ee (Value f) = withExecutionEngine ee $ \eePtr ->
132+
return (eePtr, f)
202133

203134
foreign import ccall c_freeFunctionObject :: Ptr FFI.ExecutionEngine -> FFI.ValueRef -> IO ()
204135

@@ -221,15 +152,13 @@ withAll ps a = go [] ps
221152
where go ptrs (x:xs) = withGenericValue x $ \ptr -> go (ptr:ptrs) xs
222153
go ptrs _ = withArrayLen (reverse ptrs) a
223154

224-
runFunction :: U.Function -> [GenericValue] -> EngineAccess GenericValue
225-
runFunction func args = do
226-
eePtr <- gets ea_engine
227-
liftIO $ withAll args $ \argLen argPtr ->
228-
createGenericValueWith $ FFI.runFunction eePtr func
155+
runFunction :: ExecutionEngine -> U.Function -> [GenericValue] -> IO GenericValue
156+
runFunction ee func args = withExecutionEngine ee $ \eePtr ->
157+
withAll args $ \argLen argPtr ->
158+
createGenericValueWith $ FFI.runFunction eePtr func
229159
(fromIntegral argLen) argPtr
230-
getRunFunction :: EngineAccess (U.Function -> [GenericValue] -> IO GenericValue)
231-
getRunFunction = do
232-
eePtr <- gets ea_engine
160+
getRunFunction :: ExecutionEngine -> IO (U.Function -> [GenericValue] -> IO GenericValue)
161+
getRunFunction ee = withExecutionEngine ee $ \eePtr -> do
233162
return $ \ func args ->
234163
withAll args $ \argLen argPtr ->
235164
createGenericValueWith $ FFI.runFunction eePtr func

LLVM/ExecutionEngine/Target.hs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import Foreign.C.String
66
import System.IO.Unsafe(unsafePerformIO)
77

88
import LLVM.Core.Data(WordN)
9-
import LLVM.ExecutionEngine.Engine(runEngineAccess, getExecutionEngineTargetData)
9+
import LLVM.ExecutionEngine.Engine(ExecutionEngine, getExecutionEngineTargetData)
1010

1111
import qualified LLVM.FFI.Core as FFI
1212
import qualified LLVM.FFI.Target as FFI
@@ -29,15 +29,15 @@ data TargetData = TargetData {
2929
}
3030
deriving (Typeable)
3131

32-
withIntPtrType :: (forall n . (Nat n) => WordN n -> a) -> a
33-
withIntPtrType f = reifyIntegral sz (\ n -> f (g n))
32+
withIntPtrType :: ExecutionEngine -> (forall n . (Nat n) => WordN n -> a) -> a
33+
withIntPtrType ee f = reifyIntegral sz (\ n -> f (g n))
3434
where g :: n -> WordN n
3535
g _ = error "withIntPtrType: argument used"
36-
sz = pointerSize $ unsafePerformIO getTargetData
36+
sz = pointerSize $ unsafePerformIO (getTargetData ee)
3737

3838
-- Gets the target data for the JIT target.
39-
getEngineTargetDataRef :: IO FFI.TargetDataRef
40-
getEngineTargetDataRef = runEngineAccess getExecutionEngineTargetData
39+
getEngineTargetDataRef :: ExecutionEngine -> IO FFI.TargetDataRef
40+
getEngineTargetDataRef = getExecutionEngineTargetData
4141

4242
-- Normally the TargetDataRef never changes, so the operation
4343
-- are really pure functions.
@@ -54,8 +54,8 @@ makeTargetData r = TargetData {
5454
storeSizeOfType = fromIntegral . FFI.storeSizeOfType r
5555
}
5656

57-
getTargetData :: IO TargetData
58-
getTargetData = fmap makeTargetData getEngineTargetDataRef
57+
getTargetData :: ExecutionEngine -> IO TargetData
58+
getTargetData ee = fmap makeTargetData (getEngineTargetDataRef ee)
5959

6060
targetDataFromString :: String -> TargetData
6161
targetDataFromString s = makeTargetData $ unsafePerformIO $ withCString s FFI.createTargetData

0 commit comments

Comments
 (0)