llvm-0.0.2: LLVM/Core/Builder.hs
{-# LANGUAGE
DeriveDataTypeable
, FlexibleContexts
, FunctionalDependencies
, MultiParamTypeClasses
, UndecidableInstances
#-}
module LLVM.Core.Builder
(
Instruction(..)
, BasicBlock(..)
-- * Instruction building
, createBuilder
, positionBefore
, positionAtEnd
-- * Terminators
, retVoid
, ret
, br
, condBr
, switch
, invoke
, unwind
, unreachable
-- * Arithmetic
, add
, sub
, mul
, uDiv
, sDiv
, fDiv
, uRem
, sRem
, fRem
, shl
, lShr
, aShr
, and
, or
, xor
, neg
, not
-- * Memory
, malloc
, arrayMalloc
, alloca
, arrayAlloca
, free
, load
, store
, getElementPtr
-- * Casts
, trunc
, zExt
, sExt
, fpToUI
, fpToSI
, uiToFP
, siToFP
, fpTrunc
, fpExt
, ptrToInt
, intToPtr
, bitCast
-- * Comparisons
, icmp
, fcmp
-- * Miscellaneous instructions
, call
, call_
, extractElement
, insertElement
, phi
, select
, vaArg
, shuffleVector
) where
import Control.Applicative ((<$>))
import Control.Arrow ((***))
import Control.Monad (forM_)
import Data.Typeable (Typeable)
import Foreign.C.String (CString, withCString)
import Foreign.ForeignPtr (FinalizerPtr, ForeignPtr, newForeignPtr,
withForeignPtr)
import Foreign.Marshal.Array (withArray, withArrayLen)
import Prelude hiding (and, not, or)
import qualified LLVM.Core.FFI as FFI
import qualified LLVM.Core.Instruction as I
import qualified LLVM.Core.Type as T
import qualified LLVM.Core.Value as V
import LLVM.Core.Type ((:->)(..))
import LLVM.Core.Value (Instruction(..))
newtype Builder = Builder {
fromBuilder :: ForeignPtr FFI.Builder
}
deriving (Typeable)
newtype BasicBlock = BasicBlock V.AnyValue
deriving (V.DynamicValue, Typeable, V.Value)
withBuilder :: Builder -> (FFI.BuilderRef -> IO a) -> IO a
withBuilder = withForeignPtr . fromBuilder
createBuilder :: IO Builder
createBuilder = do
final <- h2c_builder FFI.disposeBuilder
ptr <- FFI.createBuilder
Builder <$> newForeignPtr final ptr
foreign import ccall "wrapper" h2c_builder
:: (FFI.BuilderRef -> IO ()) -> IO (FinalizerPtr a)
positionBefore :: Builder -> Instruction a -> IO ()
positionBefore bld insn =
withBuilder bld $ \bldPtr ->
FFI.positionBefore bldPtr (V.valueRef insn)
positionAtEnd :: Builder -> BasicBlock -> IO ()
positionAtEnd bld bblk =
withBuilder bld $ \bldPtr ->
FFI.positionAtEnd bldPtr (V.valueRef bblk)
instruction :: IO FFI.ValueRef -> IO (Instruction t)
instruction = fmap (Instruction . V.mkAnyValue)
unary :: (V.Value a)
=> (FFI.BuilderRef -> FFI.ValueRef -> CString -> IO FFI.ValueRef)
-> Builder -> String -> a -> IO (Instruction t)
unary ffi bld name a =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
Instruction . V.mkAnyValue <$>
ffi bldPtr (V.valueRef a) namePtr
binary :: (V.Value a, V.Value b)
=> (FFI.BuilderRef -> FFI.ValueRef -> FFI.ValueRef -> CString
-> IO FFI.ValueRef)
-> Builder -> String -> a -> b -> IO (Instruction t)
binary ffi bld name a b =
withBuilder bld $ \bldPtr ->
withCString name $ instruction . ffi bldPtr (V.valueRef a) (V.valueRef b)
add :: (T.Arithmetic t,
V.Value a, V.TypedValue a t,
V.Value b, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
add = binary FFI.buildAdd
sub :: (T.Arithmetic t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
sub = binary FFI.buildSub
mul :: (T.Arithmetic t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
mul = binary FFI.buildSub
uDiv :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
uDiv = binary FFI.buildUDiv
sDiv :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
sDiv = binary FFI.buildSDiv
fDiv :: (T.Real t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
fDiv = binary FFI.buildFDiv
uRem :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
uRem = binary FFI.buildURem
sRem :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
sRem = binary FFI.buildSRem
fRem :: (T.Real t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
fRem = binary FFI.buildFRem
shl :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
shl = binary FFI.buildShl
lShr :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
lShr = binary FFI.buildLShr
aShr :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
aShr = binary FFI.buildAShr
and :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
and = binary FFI.buildAnd
or :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
or = binary FFI.buildOr
xor :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> a -> b -> IO (Instruction t)
xor = binary FFI.buildAnd
neg :: (T.Arithmetic t, V.TypedValue v t)
=> Builder -> String -> v -> IO (Instruction t)
neg = unary FFI.buildNeg
not :: (T.Arithmetic t, V.TypedValue v t)
=> Builder -> String -> v -> IO (Instruction t)
not = unary FFI.buildNot
typed :: (V.Value v, T.Type s, T.Type t)
=> (FFI.BuilderRef -> FFI.ValueRef -> FFI.TypeRef -> CString
-> IO FFI.ValueRef)
-> Builder -> String -> v -> s -> IO (Instruction t)
typed ffi bld name a t =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
Instruction . V.mkAnyValue <$> ffi bldPtr (V.valueRef a) (T.typeRef t) namePtr
trunc :: (T.Integer s, V.TypedValue v s, T.Integer t)
=> Builder -> String -> v -> s -> IO (Instruction t)
trunc = typed FFI.buildTrunc
zExt :: (T.Integer s, V.TypedValue v s, T.Integer t)
=> Builder -> String -> v -> s -> IO (Instruction t)
zExt = typed FFI.buildZExt
sExt :: (T.Integer s, V.TypedValue v s, T.Integer t)
=> Builder -> String -> v -> s -> IO (Instruction t)
sExt = typed FFI.buildSExt
fpToUI :: (T.Integer s, V.TypedValue v s, T.Real t)
=> Builder -> String -> v -> s -> IO (Instruction t)
fpToUI = typed FFI.buildFPToUI
fpToSI :: (T.Integer s, V.TypedValue v s, T.Real t)
=> Builder -> String -> v -> s -> IO (Instruction t)
fpToSI = typed FFI.buildFPToSI
uiToFP :: (T.Real s, V.TypedValue v s, T.Integer t)
=> Builder -> String -> v -> s -> IO (Instruction t)
uiToFP = typed FFI.buildUIToFP
siToFP :: (T.Real s, V.TypedValue v s, T.Integer t)
=> Builder -> String -> v -> s -> IO (Instruction t)
siToFP = typed FFI.buildSIToFP
fpTrunc :: (T.Real s, V.TypedValue v s, T.Real t)
=> Builder -> String -> v -> s -> IO (Instruction t)
fpTrunc = typed FFI.buildFPTrunc
fpExt :: (T.Real s, V.TypedValue v s, T.Real t)
=> Builder -> String -> v -> s -> IO (Instruction t)
fpExt = typed FFI.buildFPExt
ptrToInt :: (V.TypedValue (T.Pointer s) s, T.Integer t)
=> Builder -> String -> T.Pointer s -> s -> IO (Instruction t)
ptrToInt = typed FFI.buildPtrToInt
intToPtr :: (T.Integer s, V.TypedValue v s, T.Type t)
=> Builder -> String -> v -> t -> IO (Instruction (T.Pointer t))
intToPtr = typed FFI.buildIntToPtr
bitCast :: (V.TypedValue v s, T.Type t)
=> Builder -> String -> v -> s -> IO (Instruction t)
bitCast = typed FFI.buildBitCast
fcmp :: (T.Real t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> I.RealPredicate -> a -> b
-> IO (Instruction T.Int1)
fcmp bld name p = binary (flip FFI.buildFCmp (I.fromRP p)) bld name
icmp :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> I.IntPredicate -> a -> b
-> IO (Instruction T.Int1)
icmp bld name p = binary (flip FFI.buildICmp (I.fromIP p)) bld name
retVoid :: Builder -> IO (Instruction T.Void)
retVoid bld = withBuilder bld $ instruction . FFI.buildRetVoid
ret :: (T.FirstClass t, V.TypedValue v t) => Builder -> v -> IO (Instruction t)
ret bld v =
withBuilder bld $ \bldPtr ->
instruction $ FFI.buildRet bldPtr (V.valueRef v)
br :: Builder -> BasicBlock -> IO (Instruction T.Void)
br bld bblk =
withBuilder bld $ \bldPtr ->
instruction $ FFI.buildBr bldPtr (V.valueRef bblk)
condBr :: (V.TypedValue v T.Int1)
=> Builder -> v -> BasicBlock -> BasicBlock
-> IO (Instruction T.Void)
condBr bld bit true false =
withBuilder bld $ \bldPtr ->
instruction $ FFI.buildCondBr bldPtr (V.valueRef bit)
(V.valueRef true) (V.valueRef false)
unwrap :: (V.Value a, V.Value b) => (a, b) -> (FFI.ValueRef, FFI.ValueRef)
unwrap = V.valueRef *** V.valueRef
switch :: (T.Integer t, V.TypedValue v t)
=> Builder -> v -> BasicBlock -> [(v, BasicBlock)]
-> IO (Instruction T.Void)
switch bld val noMatch cases =
withBuilder bld $ \bldPtr -> do
inst <- FFI.buildSwitch bldPtr (V.valueRef val)
(V.valueRef noMatch) (fromIntegral $ length cases)
forM_ (map unwrap cases) $ uncurry (FFI.addCase inst)
instruction $ return inst
invoke :: (T.DynamicType r, T.Params p, Params p v, T.FirstClass r)
=> Builder -> String -> V.Function r p -> v
-> BasicBlock -> BasicBlock -> IO (Instruction r)
invoke bld name func args thenBlk catchBlk =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
withArrayLen (argList func args) $ \argLen argPtr ->
instruction $ FFI.buildInvoke bldPtr (V.valueRef func) argPtr
(fromIntegral argLen) (V.valueRef thenBlk)
(V.valueRef catchBlk) namePtr
unwind :: Builder -> IO (Instruction T.Void)
unwind bld = withBuilder bld $ instruction . FFI.buildUnwind
unreachable :: Builder -> IO (Instruction T.Void)
unreachable bld = withBuilder bld $ instruction . FFI.buildUnreachable
allocWith :: (T.Type t)
=> (FFI.BuilderRef -> FFI.TypeRef -> CString -> IO FFI.ValueRef)
-> Builder -> String -> t -> IO FFI.ValueRef
allocWith ffi bld name typ =
withBuilder bld $ \bldPtr ->
withCString name $ ffi bldPtr (T.typeRef typ)
arrayAllocWith :: (T.Type t, T.Integer n, V.TypedValue v n)
=> (FFI.BuilderRef -> FFI.TypeRef -> FFI.ValueRef -> CString
-> IO FFI.ValueRef)
-> Builder -> String -> t -> v -> IO FFI.ValueRef
arrayAllocWith ffi bld name typ count =
withBuilder bld $ \bldPtr ->
withCString name $ ffi bldPtr (T.typeRef typ) (V.valueRef count)
malloc :: (T.Type t) => Builder -> String -> t -> IO (Instruction (T.Array t))
malloc bld name typ = instruction $ allocWith FFI.buildMalloc bld name typ
arrayMalloc :: (T.Type t, V.TypedValue v T.Int32)
=> Builder -> String -> t -> v -> IO (Instruction (T.Array t))
arrayMalloc bld name typ count =
instruction $ arrayAllocWith FFI.buildArrayMalloc bld name typ count
alloca :: (T.Type t)
=> Builder -> String -> t -> IO (Instruction (T.Pointer t))
alloca bld name typ = instruction $ allocWith FFI.buildAlloca bld name typ
arrayAlloca :: (T.Type t, V.TypedValue v T.Int32)
=> Builder -> String -> t -> v -> IO (Instruction (T.Pointer t))
arrayAlloca bld name typ count =
instruction $ arrayAllocWith FFI.buildArrayAlloca bld name typ count
free :: (V.TypedValue v (T.Pointer t))
=> Builder -> v -> IO (Instruction T.Void)
free bld ary =
withBuilder bld $ \bldPtr ->
instruction $ FFI.buildFree bldPtr (V.valueRef ary)
load :: (V.TypedValue v (T.Pointer t))
=> Builder -> String -> v -> IO (Instruction t)
load bld name ptr =
withBuilder bld $ \bldPtr ->
instruction $ withCString name $ FFI.buildLoad bldPtr (V.valueRef ptr)
store :: (V.TypedValue v t, V.TypedValue p (T.Pointer t))
=> Builder -> v -> p -> IO (Instruction T.Void)
store bld val ptr =
withBuilder bld $ \bldPtr ->
instruction $ FFI.buildStore bldPtr (V.valueRef val) (V.valueRef ptr)
getElementPtr :: (T.Sequence s e, V.TypedValue p s,
T.Integer t, V.TypedValue i t)
=> Builder -> String -> p -> [i]
-> IO (Instruction (T.Pointer e))
getElementPtr bld name ptr idxs =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
withArrayLen (map V.valueRef idxs) $ \idxLen idxPtr ->
instruction $ FFI.buildGEP bldPtr (V.valueRef ptr) idxPtr
(fromIntegral idxLen) namePtr
argList :: (Params p a, T.Params p, V.TypedValue v (T.Function r p))
=> v -> a -> [FFI.ValueRef]
argList func = map V.valueRef . toAnyList (T.params (V.typeOf func))
callRef :: (T.DynamicType r, T.Params p, Params p v)
=> Builder -> String -> V.Function r p -> v -> IO FFI.ValueRef
callRef bld name func args = do
withBuilder bld $ \bldPtr ->
withArrayLen (argList func args) $ \argLen argPtr ->
withCString name $ \namePtr ->
FFI.buildCall bldPtr (V.valueRef func) argPtr
(fromIntegral argLen) namePtr
class Params t v | t -> v where
toAnyList :: t -> v -> [V.AnyValue]
listValue :: (V.TypedValue v t) => t -> v -> [V.AnyValue]
listValue _ v = [V.anyValue v]
instance (V.TypedValue v a, Params b c) => Params (a :-> b) (v :-> c) where
toAnyList t (a :-> b) = V.anyValue a : toAnyList (T.cdr t) b
instance (V.TypedValue v T.Int32) => Params T.Int32 v where
toAnyList = listValue
instance (T.Type t, V.TypedValue v (T.Pointer t)) => Params (T.Pointer t) v where
toAnyList = listValue
call :: (T.DynamicType r, T.Params p, Params p v, T.FirstClass r)
=> Builder -> String -> V.Function r p -> v
-> IO (Instruction r)
call bld name func args = instruction $ callRef bld name func args
call_ :: (T.DynamicType r, T.Params p, Params p v)
=> Builder -> String -> V.Function r p -> v -> IO ()
call_ bld name func args = callRef bld name func args >> return ()
extractElement :: (V.TypedValue v (T.Vector t),
V.TypedValue i T.Int32)
=> Builder -> String -> v -> i -> IO (Instruction t)
extractElement bld name vec idx =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
instruction $ FFI.buildExtractElement bldPtr (V.valueRef vec)
(V.valueRef idx) namePtr
insertElement :: (V.TypedValue v (T.Vector t),
V.TypedValue e t,
V.TypedValue i T.Int32)
=> Builder -> String -> v -> e -> i -> IO (Instruction t)
insertElement bld name vec elt idx =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
instruction $ FFI.buildInsertElement bldPtr (V.valueRef vec)
(V.valueRef elt) (V.valueRef idx) namePtr
phi :: (V.TypedValue v t)
=> Builder -> String -> t -> [(v, BasicBlock)] -> IO (Instruction t)
phi bld name typ incoming =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr -> do
inst <- FFI.buildPhi bldPtr (T.typeRef typ) namePtr
let (vals, bblks) = unzip . map unwrap $ incoming
withArrayLen vals $ \count valPtr ->
withArray bblks $ \bblkPtr ->
FFI.addIncoming inst valPtr bblkPtr (fromIntegral count)
instruction $ return inst
select :: (V.TypedValue p T.Int1, V.TypedValue a t, V.TypedValue b t)
=> Builder -> String -> p -> a -> b -> IO (Instruction t)
select bld name bit true false =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr -> do
instruction $ FFI.buildSelect bldPtr (V.valueRef bit)
(V.valueRef true) (V.valueRef false) namePtr
vaArg :: (V.Value v, T.Type t)
=> Builder -> String -> v -> t -> IO (Instruction t)
vaArg bld name valist typ =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
instruction $ FFI.buildVAArg bldPtr (V.valueRef valist)
(T.typeRef typ) namePtr
shuffleVector :: (V.TypedValue a (T.Vector t),
V.TypedValue b (T.Vector t),
V.TypedValue m (T.Vector T.Int32))
=> Builder -> String -> a -> b -> m
-> IO (Instruction (T.Vector t))
shuffleVector bld name a b mask =
withBuilder bld $ \bldPtr ->
withCString name $ \namePtr ->
instruction $ FFI.buildShuffleVector bldPtr (V.valueRef a)
(V.valueRef b) (V.valueRef mask) namePtr