module LLVM.Core.Instructions(
ret,
condBr,
br,
switch,
invoke, invokeWithConv,
unwind,
unreachable,
add, sub, mul, neg,
iadd, isub, imul, ineg,
fadd, fsub, fmul, fneg,
idiv, irem,
udiv, sdiv, fdiv, urem, srem, frem,
shl, lshr, ashr, and, or, xor, inv,
extractelement,
insertelement,
shufflevector,
extractvalue,
insertvalue,
malloc, arrayMalloc,
alloca, arrayAlloca,
free,
load,
store,
getElementPtr, getElementPtr0,
trunc, zext, sext,
fptrunc, fpext,
fptoui, fptosi,
uitofp, sitofp,
ptrtoint, inttoptr,
bitcast, bitcastUnify,
CmpPredicate(..), IntPredicate(..), FPPredicate(..),
CmpRet,
cmp, pcmp, icmp, fcmp,
select,
phi, addPhiInputs,
call, callWithConv,
Terminate,
Ret, CallArgs, ABinOp, CmpOp, FunctionArgs, FunctionRet, IsConst,
AllocArg,
GetElementPtr, IsIndexArg, GetValue
) where
import Prelude hiding (and, or)
import Data.Typeable
import Control.Monad(liftM)
import Data.Int
import Data.Word
import Foreign.Ptr (FunPtr, )
import Foreign.C(CInt, CUInt)
import Data.TypeLevel((:<:), (:>:), (:==:), D0, d1, toNum, Succ)
import qualified LLVM.FFI.Core as FFI
import LLVM.Core.Data
import LLVM.Core.Type
import LLVM.Core.CodeGenMonad
import LLVM.Core.CodeGen
import qualified LLVM.Core.Util as U
type Terminate = ()
terminate :: Terminate
terminate = ()
class Ret a r where
ret' :: a -> CodeGenFunction r Terminate
ret :: (Ret a r) => a -> CodeGenFunction r Terminate
ret = ret'
instance (IsFirstClass a, IsConst a) => Ret a a where
ret' = ret . valueOf
instance Ret (Value a) a where
ret' (Value a) = do
withCurrentBuilder_ $ \ bldPtr -> FFI.buildRet bldPtr a
return terminate
instance Ret () () where
ret' _ = do
withCurrentBuilder_ $ FFI.buildRetVoid
return terminate
withCurrentBuilder_ :: (FFI.BuilderRef -> IO a) -> CodeGenFunction r ()
withCurrentBuilder_ p = withCurrentBuilder p >> return ()
condBr :: Value Bool
-> BasicBlock
-> BasicBlock
-> CodeGenFunction r Terminate
condBr (Value b) (BasicBlock t1) (BasicBlock t2) = do
withCurrentBuilder_ $ \ bldPtr -> FFI.buildCondBr bldPtr b t1 t2
return terminate
br :: BasicBlock
-> CodeGenFunction r Terminate
br (BasicBlock t) = do
withCurrentBuilder_ $ \ bldPtr -> FFI.buildBr bldPtr t
return terminate
switch :: (IsInteger a)
=> Value a
-> BasicBlock
-> [(ConstValue a, BasicBlock)]
-> CodeGenFunction r Terminate
switch (Value val) (BasicBlock dflt) arms = do
withCurrentBuilder_ $ \ bldPtr -> do
inst <- FFI.buildSwitch bldPtr val dflt (fromIntegral $ length arms)
sequence_ [ FFI.addCase inst c b | (ConstValue c, BasicBlock b) <- arms ]
return terminate
unwind :: CodeGenFunction r Terminate
unwind = do
withCurrentBuilder_ FFI.buildUnwind
return terminate
unreachable :: CodeGenFunction r Terminate
unreachable = do
withCurrentBuilder_ FFI.buildUnreachable
return terminate
type FFIBinOp = FFI.BuilderRef -> FFI.ValueRef -> FFI.ValueRef -> U.CString -> IO FFI.ValueRef
type FFIConstBinOp = FFI.ValueRef -> FFI.ValueRef -> FFI.ValueRef
withArithmeticType ::
(IsArithmetic c) =>
(ArithmeticType c -> a -> CodeGenFunction r (v c)) ->
(a -> CodeGenFunction r (v c))
withArithmeticType f = f arithmeticType
class ABinOp a b c | a b -> c where
abinop :: FFIConstBinOp -> FFIBinOp -> a -> b -> CodeGenFunction r c
add :: (IsArithmetic c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
add =
curry $ withArithmeticType $ \typ -> uncurry $ case typ of
IntegerType -> abinop FFI.constAdd FFI.buildAdd
FloatingType -> abinop FFI.constFAdd FFI.buildFAdd
sub :: (IsArithmetic c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
sub =
curry $ withArithmeticType $ \typ -> uncurry $ case typ of
IntegerType -> abinop FFI.constSub FFI.buildSub
FloatingType -> abinop FFI.constFSub FFI.buildFSub
mul :: (IsArithmetic c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
mul =
curry $ withArithmeticType $ \typ -> uncurry $ case typ of
IntegerType -> abinop FFI.constMul FFI.buildMul
FloatingType -> abinop FFI.constFMul FFI.buildFMul
iadd :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
iadd = abinop FFI.constAdd FFI.buildAdd
isub :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
isub = abinop FFI.constSub FFI.buildSub
imul :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
imul = abinop FFI.constMul FFI.buildMul
idiv ::
forall a b c r v. (IsInteger c, ABinOp a b (v c)) =>
a -> b -> CodeGenFunction r (v c)
idiv =
if isSigned (undefined :: c)
then abinop FFI.constSDiv FFI.buildSDiv
else abinop FFI.constUDiv FFI.buildUDiv
irem ::
forall a b c r v. (IsInteger c, ABinOp a b (v c)) =>
a -> b -> CodeGenFunction r (v c)
irem =
if isSigned (undefined :: c)
then abinop FFI.constSRem FFI.buildSRem
else abinop FFI.constURem FFI.buildURem
udiv :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
udiv = abinop FFI.constUDiv FFI.buildUDiv
sdiv :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
sdiv = abinop FFI.constSDiv FFI.buildSDiv
urem :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
urem = abinop FFI.constURem FFI.buildURem
srem :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
srem = abinop FFI.constSRem FFI.buildSRem
fadd :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
fadd = abinop FFI.constFAdd FFI.buildFAdd
fsub :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
fsub = abinop FFI.constFSub FFI.buildFSub
fmul :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
fmul = abinop FFI.constFMul FFI.buildFMul
fdiv :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
fdiv = abinop FFI.constFDiv FFI.buildFDiv
frem :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
frem = abinop FFI.constFRem FFI.buildFRem
shl :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
shl = abinop FFI.constShl FFI.buildShl
lshr :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
lshr = abinop FFI.constLShr FFI.buildLShr
ashr :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
ashr = abinop FFI.constAShr FFI.buildAShr
and :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
and = abinop FFI.constAnd FFI.buildAnd
or :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
or = abinop FFI.constOr FFI.buildOr
xor :: (IsInteger c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)
xor = abinop FFI.constXor FFI.buildXor
instance ABinOp (Value a) (Value a) (Value a) where
abinop _ op (Value a1) (Value a2) = buildBinOp op a1 a2
instance ABinOp (ConstValue a) (Value a) (Value a) where
abinop _ op (ConstValue a1) (Value a2) = buildBinOp op a1 a2
instance ABinOp (Value a) (ConstValue a) (Value a) where
abinop _ op (Value a1) (ConstValue a2) = buildBinOp op a1 a2
instance ABinOp (ConstValue a) (ConstValue a) (ConstValue a) where
abinop cop _ (ConstValue a1) (ConstValue a2) =
return $ ConstValue $ cop a1 a2
instance (IsConst a) => ABinOp (Value a) a (Value a) where
abinop cop op a1 a2 = abinop cop op a1 (constOf a2)
instance (IsConst a) => ABinOp a (Value a) (Value a) where
abinop cop op a1 a2 = abinop cop op (constOf a1) a2
buildBinOp :: FFIBinOp -> FFI.ValueRef -> FFI.ValueRef -> CodeGenFunction r (Value a)
buildBinOp op a1 a2 =
liftM Value $
withCurrentBuilder $ \ bld ->
U.withEmptyCString $ op bld a1 a2
type FFIUnOp = FFI.BuilderRef -> FFI.ValueRef -> U.CString -> IO FFI.ValueRef
buildUnOp :: FFIUnOp -> FFI.ValueRef -> CodeGenFunction r (Value a)
buildUnOp op a =
liftM Value $
withCurrentBuilder $ \ bld ->
U.withEmptyCString $ op bld a
neg :: forall r a. (IsArithmetic a) => Value a -> CodeGenFunction r (Value a)
neg =
withArithmeticType $ \typ -> case typ of
IntegerType -> \(Value x) -> buildUnOp FFI.buildNeg x
FloatingType -> abinop FFI.constFSub FFI.buildFSub (value zero :: Value a)
ineg :: (IsInteger a) => Value a -> CodeGenFunction r (Value a)
ineg (Value x) = buildUnOp FFI.buildNeg x
fneg :: forall r a. (IsFloating a) => Value a -> CodeGenFunction r (Value a)
fneg = fsub (value zero :: Value a)
inv :: (IsInteger a) => Value a -> CodeGenFunction r (Value a)
inv (Value x) = buildUnOp FFI.buildNot x
extractelement :: (Pos n)
=> Value (Vector n a)
-> Value Word32
-> CodeGenFunction r (Value a)
extractelement (Value vec) (Value i) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ FFI.buildExtractElement bldPtr vec i
insertelement :: (Pos n)
=> Value (Vector n a)
-> Value a
-> Value Word32
-> CodeGenFunction r (Value (Vector n a))
insertelement (Value vec) (Value e) (Value i) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ FFI.buildInsertElement bldPtr vec e i
shufflevector :: (Pos n, Pos m)
=> Value (Vector n a)
-> Value (Vector n a)
-> ConstValue (Vector m Word32)
-> CodeGenFunction r (Value (Vector m a))
shufflevector (Value a) (Value b) (ConstValue mask) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ FFI.buildShuffleVector bldPtr a b mask
class GetValue agg ix el | agg ix -> el where
getIx :: agg -> ix -> CUInt
instance (GetField as i a, Nat i) => GetValue (Struct as) i a where
getIx _ n = toNum n
instance (IsFirstClass a, Nat n) => GetValue (Array n a) Word32 a where
getIx _ n = fromIntegral n
instance (IsFirstClass a, Nat n) => GetValue (Array n a) Word64 a where
getIx _ n = fromIntegral n
extractvalue :: forall r agg i a.
GetValue agg i a
=> Value agg
-> i
-> CodeGenFunction r (Value a)
extractvalue (Value agg) i =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $
FFI.buildExtractValue bldPtr agg (getIx (undefined::agg) i)
insertvalue :: forall r agg i a.
GetValue agg i a
=> Value agg
-> Value a
-> i
-> CodeGenFunction r (Value agg)
insertvalue (Value agg) (Value e) i =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $
FFI.buildInsertValue bldPtr agg e (getIx (undefined::agg) i)
trunc :: (IsInteger a, IsInteger b, IsPrimitive a, IsPrimitive b, IsSized a sa, IsSized b sb, sa :>: sb)
=> Value a -> CodeGenFunction r (Value b)
trunc = convert FFI.buildTrunc
zext :: (IsInteger a, IsInteger b, IsPrimitive a, IsPrimitive b, IsSized a sa, IsSized b sb, sa :<: sb)
=> Value a -> CodeGenFunction r (Value b)
zext = convert FFI.buildZExt
sext :: (IsInteger a, IsInteger b, IsPrimitive a, IsPrimitive b, IsSized a sa, IsSized b sb, sa :<: sb)
=> Value a -> CodeGenFunction r (Value b)
sext = convert FFI.buildSExt
fptrunc :: (IsFloating a, IsFloating b, IsPrimitive a, IsPrimitive b, IsSized a sa, IsSized b sb, sa :>: sb)
=> Value a -> CodeGenFunction r (Value b)
fptrunc = convert FFI.buildFPTrunc
fpext :: (IsFloating a, IsFloating b, IsPrimitive a, IsPrimitive b, IsSized a sa, IsSized b sb, sa :<: sb)
=> Value a -> CodeGenFunction r (Value b)
fpext = convert FFI.buildFPExt
fptoui :: (IsFloating a, IsInteger b, NumberOfElements n a, NumberOfElements n b) => Value a -> CodeGenFunction r (Value b)
fptoui = convert FFI.buildFPToUI
fptosi :: (IsFloating a, IsInteger b, NumberOfElements n a, NumberOfElements n b) => Value a -> CodeGenFunction r (Value b)
fptosi = convert FFI.buildFPToSI
uitofp :: (IsInteger a, IsFloating b, NumberOfElements n a, NumberOfElements n b) => Value a -> CodeGenFunction r (Value b)
uitofp = convert FFI.buildUIToFP
sitofp :: (IsInteger a, IsFloating b, NumberOfElements n a, NumberOfElements n b) => Value a -> CodeGenFunction r (Value b)
sitofp = convert FFI.buildSIToFP
ptrtoint :: (IsInteger b, IsPrimitive b) => Value (Ptr a) -> CodeGenFunction r (Value b)
ptrtoint = convert FFI.buildPtrToInt
inttoptr :: (IsInteger a, IsType b) => Value a -> CodeGenFunction r (Value (Ptr b))
inttoptr = convert FFI.buildIntToPtr
bitcast :: (IsFirstClass a, IsFirstClass b, IsSized a sa, IsSized b sb, sa :==: sb)
=> Value a -> CodeGenFunction r (Value b)
bitcast = convert FFI.buildBitCast
bitcastUnify :: (IsFirstClass a, IsFirstClass b, IsSized a s, IsSized b s)
=> Value a -> CodeGenFunction r (Value b)
bitcastUnify = convert FFI.buildBitCast
type FFIConvert = FFI.BuilderRef -> FFI.ValueRef -> FFI.TypeRef -> U.CString -> IO FFI.ValueRef
convert :: forall a b r . (IsType b) => FFIConvert -> Value a -> CodeGenFunction r (Value b)
convert conv (Value a) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ conv bldPtr a (typeRef (undefined :: b))
data CmpPredicate =
CmpEQ
| CmpNE
| CmpGT
| CmpGE
| CmpLT
| CmpLE
deriving (Eq, Ord, Enum, Show, Typeable)
uintFromCmpPredicate :: CmpPredicate -> IntPredicate
uintFromCmpPredicate p =
case p of
CmpEQ -> IntEQ
CmpNE -> IntNE
CmpGT -> IntUGT
CmpGE -> IntUGE
CmpLT -> IntULT
CmpLE -> IntULE
sintFromCmpPredicate :: CmpPredicate -> IntPredicate
sintFromCmpPredicate p =
case p of
CmpEQ -> IntEQ
CmpNE -> IntNE
CmpGT -> IntSGT
CmpGE -> IntSGE
CmpLT -> IntSLT
CmpLE -> IntSLE
fpFromCmpPredicate :: CmpPredicate -> FPPredicate
fpFromCmpPredicate p =
case p of
CmpEQ -> FPOEQ
CmpNE -> FPONE
CmpGT -> FPOGT
CmpGE -> FPOGE
CmpLT -> FPOLT
CmpLE -> FPOLE
data IntPredicate =
IntEQ
| IntNE
| IntUGT
| IntUGE
| IntULT
| IntULE
| IntSGT
| IntSGE
| IntSLT
| IntSLE
deriving (Eq, Ord, Enum, Show, Typeable)
fromIntPredicate :: IntPredicate -> CInt
fromIntPredicate p = fromIntegral (fromEnum p + 32)
data FPPredicate =
FPFalse
| FPOEQ
| FPOGT
| FPOGE
| FPOLT
| FPOLE
| FPONE
| FPORD
| FPUNO
| FPUEQ
| FPUGT
| FPUGE
| FPULT
| FPULE
| FPUNE
| FPT
deriving (Eq, Ord, Enum, Show, Typeable)
fromFPPredicate :: FPPredicate -> CInt
fromFPPredicate p = fromIntegral (fromEnum p)
class CmpOp a b c d | a b -> c where
cmpop :: FFIBinOp -> a -> b -> CodeGenFunction r (Value d)
instance CmpOp (Value a) (Value a) a d where
cmpop op (Value a1) (Value a2) = buildBinOp op a1 a2
instance (IsConst a) => CmpOp a (Value a) a d where
cmpop op a1 a2 = cmpop op (valueOf a1) a2
instance (IsConst a) => CmpOp (Value a) a a d where
cmpop op a1 a2 = cmpop op a1 (valueOf a2)
class CmpRet c d | c -> d where
cmpBld :: c -> CmpPredicate -> FFIBinOp
instance CmpRet Float Bool where cmpBld _ = fcmpBld
instance CmpRet Double Bool where cmpBld _ = fcmpBld
instance CmpRet FP128 Bool where cmpBld _ = fcmpBld
instance CmpRet Bool Bool where cmpBld _ = ucmpBld
instance CmpRet Word8 Bool where cmpBld _ = ucmpBld
instance CmpRet Word16 Bool where cmpBld _ = ucmpBld
instance CmpRet Word32 Bool where cmpBld _ = ucmpBld
instance CmpRet Word64 Bool where cmpBld _ = ucmpBld
instance CmpRet Int8 Bool where cmpBld _ = scmpBld
instance CmpRet Int16 Bool where cmpBld _ = scmpBld
instance CmpRet Int32 Bool where cmpBld _ = scmpBld
instance CmpRet Int64 Bool where cmpBld _ = scmpBld
instance CmpRet (Ptr a) Bool where cmpBld _ = ucmpBld
instance (CmpRet a b, IsPrimitive a, Pos n) =>
CmpRet (Vector n a) (Vector n b)
where cmpBld _ = cmpBld (undefined :: a)
cmp :: forall a b c d r.
(CmpOp a b c d, CmpRet c d) =>
CmpPredicate -> a -> b -> CodeGenFunction r (Value d)
cmp p = cmpop (cmpBld (undefined :: c) p)
ucmpBld :: CmpPredicate -> FFIBinOp
ucmpBld p = flip FFI.buildICmp (fromIntPredicate (uintFromCmpPredicate p))
scmpBld :: CmpPredicate -> FFIBinOp
scmpBld p = flip FFI.buildICmp (fromIntPredicate (sintFromCmpPredicate p))
fcmpBld :: CmpPredicate -> FFIBinOp
fcmpBld p = flip FFI.buildFCmp (fromFPPredicate (fpFromCmpPredicate p))
_ucmp :: (IsInteger c, CmpOp a b c d, CmpRet c d) =>
CmpPredicate -> a -> b -> CodeGenFunction r (Value d)
_ucmp p = cmpop (flip FFI.buildICmp (fromIntPredicate (uintFromCmpPredicate p)))
_scmp :: (IsInteger c, CmpOp a b c d, CmpRet c d) =>
CmpPredicate -> a -> b -> CodeGenFunction r (Value d)
_scmp p = cmpop (flip FFI.buildICmp (fromIntPredicate (sintFromCmpPredicate p)))
pcmp :: (CmpOp a b (Ptr c) d, CmpRet (Ptr c) d) =>
IntPredicate -> a -> b -> CodeGenFunction r (Value d)
pcmp p = cmpop (flip FFI.buildICmp (fromIntPredicate p))
icmp :: (IsIntegerOrPointer c, CmpOp a b c d, CmpRet c d) =>
IntPredicate -> a -> b -> CodeGenFunction r (Value d)
icmp p = cmpop (flip FFI.buildICmp (fromIntPredicate p))
fcmp :: (IsFloating c, CmpOp a b c d, CmpRet c d) =>
FPPredicate -> a -> b -> CodeGenFunction r (Value d)
fcmp p = cmpop (flip FFI.buildFCmp (fromFPPredicate p))
select :: (IsFirstClass a, CmpRet a b) => Value b -> Value a -> Value a -> CodeGenFunction r (Value a)
select (Value cnd) (Value thn) (Value els) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $
FFI.buildSelect bldPtr cnd thn els
type Caller = FFI.BuilderRef -> [FFI.ValueRef] -> IO FFI.ValueRef
class CallArgs f g | f -> g, g -> f where
doCall :: Caller -> [FFI.ValueRef] -> f -> g
instance (CallArgs b b') => CallArgs (a -> b) (Value a -> b') where
doCall mkCall args f (Value arg) = doCall mkCall (arg : args) (f (undefined :: a))
instance CallArgs (IO a) (CodeGenFunction r (Value a)) where
doCall = doCallDef
doCallDef :: Caller -> [FFI.ValueRef] -> b -> CodeGenFunction r (Value a)
doCallDef mkCall args _ =
withCurrentBuilder $ \ bld ->
liftM Value $ mkCall bld (reverse args)
call :: (CallArgs f g) => Function f -> g
call (Value f) = doCall (U.makeCall f) [] (undefined :: f)
invoke :: (CallArgs f g)
=> BasicBlock
-> BasicBlock
-> Function f
-> g
invoke (BasicBlock norm) (BasicBlock expt) (Value f) =
doCall (U.makeInvoke norm expt f) [] (undefined :: f)
callWithConv :: (CallArgs f g) => FFI.CallingConvention -> Function f -> g
callWithConv cc (Value f) = doCall (U.makeCallWithCc cc f) [] (undefined :: f)
invokeWithConv :: (CallArgs f g)
=> FFI.CallingConvention
-> BasicBlock
-> BasicBlock
-> Function f
-> g
invokeWithConv cc (BasicBlock norm) (BasicBlock expt) (Value f) =
doCall (U.makeInvokeWithCc cc norm expt f) [] (undefined :: f)
phi :: forall a r . (IsFirstClass a) => [(Value a, BasicBlock)] -> CodeGenFunction r (Value a)
phi incoming =
liftM Value $
withCurrentBuilder $ \ bldPtr -> do
inst <- U.buildEmptyPhi bldPtr (typeRef (undefined :: a))
U.addPhiIns inst [ (v, b) | (Value v, BasicBlock b) <- incoming ]
return inst
addPhiInputs :: forall a r . (IsFirstClass a)
=> Value a
-> [(Value a, BasicBlock)]
-> CodeGenFunction r ()
addPhiInputs (Value inst) incoming =
liftIO $ U.addPhiIns inst [ (v, b) | (Value v, BasicBlock b) <- incoming ]
class AllocArg a where
getAllocArg :: a -> Value Word32
instance AllocArg (Value Word32) where
getAllocArg = id
instance AllocArg (ConstValue Word32) where
getAllocArg = value
instance AllocArg Word32 where
getAllocArg = valueOf
malloc :: forall a r s . (IsSized a s) => CodeGenFunction r (Value (Ptr a))
malloc = arrayMalloc (1::Word32)
foreign import ccall "&aligned_malloc_sizeptr"
alignedMalloc :: FunPtr (Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8))
foreign import ccall "&aligned_free"
alignedFree :: FunPtr (Ptr Word8 -> IO ())
arrayMalloc :: forall a n r s . (IsSized a n, AllocArg s) =>
s -> CodeGenFunction r (Value (Ptr a))
arrayMalloc s = do
func <- staticFunction alignedMalloc
size <- sizeOfArray (undefined :: a) (getAllocArg s)
alignment <- alignOf (undefined :: a)
bitcastUnify =<<
call
(func :: Function (Ptr Word8 -> Ptr Word8 -> IO (Ptr Word8)))
size
alignment
alloca :: forall a r s . (IsSized a s) => CodeGenFunction r (Value (Ptr a))
alloca =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ FFI.buildAlloca bldPtr (typeRef (undefined :: a))
arrayAlloca :: forall a n r s . (IsSized a n, AllocArg s) =>
s -> CodeGenFunction r (Value (Ptr a))
arrayAlloca s =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $
FFI.buildArrayAlloca bldPtr (typeRef (undefined :: a)) (case getAllocArg s of Value v -> v)
free :: (IsType a) => Value (Ptr a) -> CodeGenFunction r ()
free ptr = do
func <- staticFunction alignedFree
_ <- call (func :: Function (Ptr Word8 -> IO ())) =<< bitcastUnify ptr
return ()
_sizeOf :: forall a r s . (IsSized a s) => a -> CodeGenFunction r (Value Word64)
_sizeOf a =
liftIO $ liftM Value $
FFI.sizeOf (typeRef a)
_alignOf :: forall a r s . (IsSized a s) => a -> CodeGenFunction r (Value Word64)
_alignOf a =
liftIO $ liftM Value $
FFI.alignOf (typeRef a)
sizeOfArray :: forall a r s . (IsSized a s) => a -> Value Word32 -> CodeGenFunction r (Value (Ptr Word8))
sizeOfArray _ len =
bitcastUnify =<<
getElementPtr (value zero :: Value (Ptr a)) (len, ())
alignOf :: forall a r s . (IsSized a s) => a -> CodeGenFunction r (Value (Ptr Word8))
alignOf _ =
bitcastUnify =<<
getElementPtr0 (value zero :: Value (Ptr (Struct (Bool, (a, ()))))) (d1, ())
load :: Value (Ptr a)
-> CodeGenFunction r (Value a)
load (Value p) =
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withEmptyCString $ FFI.buildLoad bldPtr p
store :: Value a
-> Value (Ptr a)
-> CodeGenFunction r ()
store (Value v) (Value p) = do
withCurrentBuilder_ $ \ bldPtr ->
FFI.buildStore bldPtr v p
return ()
class GetElementPtr optr ixs nptr | optr ixs -> nptr where
getIxList :: optr -> ixs -> [FFI.ValueRef]
class IsIndexArg a where
getArg :: a -> FFI.ValueRef
instance IsIndexArg (Value Word32) where
getArg (Value v) = v
instance IsIndexArg (Value Word64) where
getArg (Value v) = v
instance IsIndexArg (Value Int32) where
getArg (Value v) = v
instance IsIndexArg (Value Int64) where
getArg (Value v) = v
instance IsIndexArg (ConstValue Word32) where
getArg = unConst
instance IsIndexArg (ConstValue Word64) where
getArg = unConst
instance IsIndexArg (ConstValue Int32) where
getArg = unConst
instance IsIndexArg (ConstValue Int64) where
getArg = unConst
instance IsIndexArg Word32 where
getArg = unConst . constOf
instance IsIndexArg Word64 where
getArg = unConst . constOf
instance IsIndexArg Int32 where
getArg = unConst . constOf
instance IsIndexArg Int64 where
getArg = unConst . constOf
unConst :: ConstValue a -> FFI.ValueRef
unConst (ConstValue v) = v
instance GetElementPtr a () a where
getIxList _ () = []
instance (GetElementPtr o i n, IsIndexArg a, Nat k) => GetElementPtr (Array k o) (a, i) n where
getIxList _ (v, i) = getArg v : getIxList (undefined :: o) i
instance (GetElementPtr o i n, IsIndexArg a, Pos k) => GetElementPtr (Vector k o) (a, i) n where
getIxList _ (v, i) = getArg v : getIxList (undefined :: o) i
instance (GetElementPtr o i n, GetField fs a o, Nat a) => GetElementPtr (Struct fs) (a, i) n where
getIxList _ (v, i) = unConst (constOf (toNum v :: Word32)) : getIxList (undefined :: o) i
instance (GetElementPtr o i n, GetField fs a o, Nat a) => GetElementPtr (PackedStruct fs) (a, i) n where
getIxList _ (v, i) = unConst (constOf (toNum v :: Word32)) : getIxList (undefined :: o) i
class GetField as i a | as i -> a
instance GetField (a, as) D0 a
instance (GetField as i b, Succ i i') => GetField (a, as) i' b
getElementPtr :: forall a o i n r . (GetElementPtr o i n, IsIndexArg a) =>
Value (Ptr o) -> (a, i) -> CodeGenFunction r (Value (Ptr n))
getElementPtr (Value ptr) (a, ixs) =
let ixl = getArg a : getIxList (undefined :: o) ixs in
liftM Value $
withCurrentBuilder $ \ bldPtr ->
U.withArrayLen ixl $ \ idxLen idxPtr ->
U.withEmptyCString $
FFI.buildGEP bldPtr ptr idxPtr (fromIntegral idxLen)
getElementPtr0 :: (GetElementPtr o i n) =>
Value (Ptr o) -> i -> CodeGenFunction r (Value (Ptr n))
getElementPtr0 p i = getElementPtr p (0::Word32, i)