module LLVM.Extra.Arithmetic (
add, sub, inc, dec,
mul, square, fdiv,
udiv, urem,
fcmp, icmp,
and, or,
umin, umax,
smin, smax, sabs,
fmin, fmax, fabs,
advanceArrayElementPtr,
sqrt, sin, cos, exp, log, pow,
) where
import qualified LLVM.Core as LLVM
import LLVM.Core
(Ptr, getElementPtr, value, valueOf, Value,
IntPredicate(IntULE, IntSLE, IntUGE, IntSGE),
FPPredicate(FPOLE, FPOGE),
IsIntegerOrPointer,
IsType, IsConst, IsInteger, IsFloating, IsArithmetic, IsFirstClass,
CmpRet,
CodeGenFunction, )
import Data.Word (Word32, )
import Prelude hiding (and, or, sqrt, sin, cos, exp, log, )
add ::
(IsArithmetic a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
add = LLVM.add
sub ::
(IsArithmetic a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
sub = LLVM.sub
inc ::
(IsArithmetic a, IsConst a, Num a) =>
Value a -> CodeGenFunction r (Value a)
inc x = add x (valueOf 1)
dec ::
(IsArithmetic a, IsConst a, Num a) =>
Value a -> CodeGenFunction r (Value a)
dec x = sub x (valueOf 1)
mul ::
(IsArithmetic a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
mul = LLVM.mul
square ::
(IsArithmetic a) =>
Value a -> CodeGenFunction r (Value a)
square x = mul x x
fdiv ::
(IsFloating a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
fdiv = LLVM.fdiv
fcmp ::
(IsFloating a, CmpRet a b) =>
FPPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
fcmp = LLVM.fcmp
icmp ::
(IsIntegerOrPointer a, CmpRet a b) =>
IntPredicate -> Value a -> Value a -> CodeGenFunction r (Value b)
icmp = LLVM.icmp
udiv ::
(IsInteger a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
udiv = LLVM.udiv
urem ::
(IsInteger a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
urem = LLVM.urem
and ::
(IsInteger a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
and = LLVM.and
or ::
(IsInteger a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
or = LLVM.or
umin :: (IsInteger a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
umin = cmpSelect (icmp IntULE)
umax :: (IsInteger a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
umax = cmpSelect (icmp IntUGE)
smin :: (IsInteger a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
smin = cmpSelect (icmp IntSLE)
smax :: (IsInteger a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
smax = cmpSelect (icmp IntSGE)
sabs :: (IsInteger a, CmpRet a Bool) =>
Value a -> CodeGenFunction r (Value a)
sabs x = do
b <- icmp IntSGE x (value LLVM.zero)
LLVM.select b x =<< LLVM.neg x
fmin :: (IsFloating a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
fmin = cmpSelect (fcmp FPOLE)
fmax :: (IsFloating a, CmpRet a Bool) =>
Value a -> Value a -> CodeGenFunction r (Value a)
fmax = cmpSelect (fcmp FPOGE)
fabs :: (IsFloating a, CmpRet a Bool) =>
Value a -> CodeGenFunction r (Value a)
fabs x = do
b <- fcmp FPOGE x (value LLVM.zero)
LLVM.select b x =<< LLVM.neg x
cmpSelect ::
(IsFirstClass a, CmpRet a Bool) =>
(Value a -> Value a -> CodeGenFunction r (Value Bool)) ->
(Value a -> Value a -> CodeGenFunction r (Value a))
cmpSelect f x y =
f x y >>= \b -> LLVM.select b x y
advanceArrayElementPtr ::
Value (Ptr o) ->
CodeGenFunction r (Value (Ptr o))
advanceArrayElementPtr p =
getElementPtr p (valueOf 1 :: Value Word32, ())
valueTypeName ::
(IsType a) =>
Value a -> String
valueTypeName =
LLVM.typeName . (undefined :: Value a -> a)
callIntrinsic1 ::
(IsFirstClass a) =>
String -> Value a -> CodeGenFunction r (Value a)
callIntrinsic1 fn x = do
op <- LLVM.externFunction ("llvm." ++ fn ++ "." ++ valueTypeName x)
r <- LLVM.call op x
LLVM.addAttributes r 0 [LLVM.ReadNoneAttribute]
return r
callIntrinsic2 ::
(IsFirstClass a) =>
String -> Value a -> Value a -> CodeGenFunction r (Value a)
callIntrinsic2 fn x y = do
op <- LLVM.externFunction ("llvm." ++ fn ++ "." ++ valueTypeName x)
r <- LLVM.call op x y
LLVM.addAttributes r 0 [LLVM.ReadNoneAttribute]
return r
sqrt, sin, cos, exp, log ::
(IsFloating a) =>
Value a -> CodeGenFunction r (Value a)
sqrt = callIntrinsic1 "sqrt"
sin = callIntrinsic1 "sin"
cos = callIntrinsic1 "cos"
exp = callIntrinsic1 "exp"
log = callIntrinsic1 "log"
pow ::
(IsFloating a) =>
Value a -> Value a -> CodeGenFunction r (Value a)
pow = callIntrinsic2 "pow"