module DDC.Core.Llvm.Convert.Exp.PrimCast
(convPrimCast)
where
import DDC.Llvm.Syntax
import DDC.Core.Llvm.Convert.Exp.Atom
import DDC.Core.Llvm.Convert.Type
import DDC.Core.Llvm.Convert.Context
import DDC.Core.Llvm.Convert.Base
import DDC.Core.Salt.Platform
import Data.Sequence (Seq)
import qualified DDC.Core.Exp as C
import qualified DDC.Core.Salt as A
import qualified Data.Sequence as Seq
import qualified Data.Map as Map
convPrimCast
:: Context
-> Maybe Var
-> A.PrimOp
-> [A.Arg]
-> Maybe (ConvertM (Seq AnnotInstr))
convPrimCast ctx mdst p as
= case p of
A.PrimCast A.PrimCastConvert
| [A.RType tDst, A.RType tSrc, xSrc] <- as
, Just vDst <- mdst
-> Just $ do
instr <- convPrimConvert ctx tDst vDst tSrc xSrc
return $ Seq.singleton (annotNil instr)
A.PrimCast A.PrimCastPromote
| [A.RType tDst, A.RType tSrc, xSrc] <- as
, Just vDst <- mdst
, Just mSrc <- mconvArg ctx xSrc
-> Just $ do
xSrc' <- mSrc
instr <- convPrimPromote ctx tDst vDst tSrc xSrc'
return $ Seq.singleton (annotNil instr)
A.PrimCast A.PrimCastTruncate
| [A.RType tDst, A.RType tSrc, xSrc] <- as
, Just vDst <- mdst
, Just mSrc <- mconvArg ctx xSrc
-> Just $ do
xSrc' <- mSrc
instr <- convPrimTruncate ctx tDst vDst tSrc xSrc'
return $ Seq.singleton (annotNil instr)
_ -> Nothing
convPrimConvert
:: Context
-> C.Type A.Name -> Var
-> C.Type A.Name -> A.Arg
-> ConvertM Instr
convPrimConvert ctx tDst vDst tSrc aSrc
| pp <- contextPlatform ctx
, kenv <- contextKindEnv ctx
= do
tSrc' <- convertType pp kenv tSrc
tDst' <- convertType pp kenv tDst
case tSrc' of
TPointer TFunction{}
| tDst' == TInt (8 * platformAddrBytes pp)
, Just mSrc <- mconvArg ctx aSrc
-> do xSrc' <- mSrc
return $ IConv vDst ConvPtrtoint xSrc'
| tDst' == TInt (8 * platformAddrBytes pp)
, A.RExp (A.XVar (C.UName nVar)) <- aSrc
, Just (nSuper, _tsArgs) <- Map.lookup nVar (contextSuperBinds ctx)
, Just mSrc <- mconvArg ctx (A.RExp (A.XVar (C.UName nSuper)))
-> do xSrc' <- mSrc
return $ IConv vDst ConvPtrtoint xSrc'
_ -> throw $ ErrorInvalidConversion tSrc tDst
convPrimPromote
:: Context
-> C.Type A.Name -> Var
-> C.Type A.Name -> Exp
-> ConvertM Instr
convPrimPromote ctx tDst vDst tSrc xSrc
= do
let pp = contextPlatform ctx
let kenv = contextKindEnv ctx
tSrc' <- convertType pp kenv tSrc
tDst' <- convertType pp kenv tDst
case (tDst', tSrc') of
(TInt bitsDst, TInt bitsSrc)
| bitsDst == bitsSrc
-> return $ ISet vDst xSrc
| isUnsignedT tSrc, isUnsignedT tDst
, bitsDst > bitsSrc
-> return $ IConv vDst ConvZext xSrc
| isSignedT tSrc, isSignedT tDst
, bitsDst > bitsSrc
-> return $ IConv vDst ConvSext xSrc
| isUnsignedT tSrc, isSignedT tDst
, bitsDst > bitsSrc
-> return $ IConv vDst ConvZext xSrc
_ -> throw $ ErrorInvalidPromotion tSrc tDst
convPrimTruncate
:: Context
-> C.Type A.Name -> Var
-> C.Type A.Name -> Exp
-> ConvertM Instr
convPrimTruncate ctx tDst vDst tSrc xSrc
= do
let pp = contextPlatform ctx
let kenv = contextKindEnv ctx
tSrc' <- convertType pp kenv tSrc
tDst' <- convertType pp kenv tDst
case (tDst', tSrc') of
(TInt bitsDst, TInt bitsSrc)
| bitsDst == bitsSrc
-> return $ ISet vDst xSrc
| bitsDst < bitsSrc
-> return $ IConv vDst ConvTrunc xSrc
| bitsDst > bitsSrc
, isUnsignedT tSrc, isSignedT tDst
-> return $ IConv vDst ConvZext xSrc
_ -> throw $ ErrorInvalidTruncation tSrc tDst