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 ------------------------------------------------------------------------------- -- | Convert a primitive call to LLVM, -- or Nothing if this doesn't look like such an operation. convPrimCast :: Context -- ^ Context of the conversion. -> Maybe Var -- ^ Assign result to this var. -> A.PrimOp -- ^ Primitive to call. -> [A.Arg] -- ^ Arguments to primitive. -> 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 ------------------------------------------------------------------------------- -- | Convert a primitive conversion operator to LLVM, -- or `Nothing` for an invalid conversion. 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 -- Produce the code pointer for a top-level super. TPointer TFunction{} -- Argument is the name of the super itself. | tDst' == TInt (8 * platformAddrBytes pp) , Just mSrc <- mconvArg ctx aSrc -> do xSrc' <- mSrc return $ IConv vDst ConvPtrtoint xSrc' -- Argument is a variable that has been bound to an application of -- a super variable to some type arguments. | 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' -- Conversion is not valid on this platform. _ -> throw $ ErrorInvalidConversion tSrc tDst ------------------------------------------------------------------------------- -- | Convert a primitive promotion operator to LLVM, -- or `Nothing` for an invalid promotion. 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) -- Same sized integers | bitsDst == bitsSrc -> return $ ISet vDst xSrc -- Both Unsigned | isUnsignedT tSrc, isUnsignedT tDst , bitsDst > bitsSrc -> return $ IConv vDst ConvZext xSrc -- Both Signed | isSignedT tSrc, isSignedT tDst , bitsDst > bitsSrc -> return $ IConv vDst ConvSext xSrc -- Unsigned to Signed | isUnsignedT tSrc, isSignedT tDst , bitsDst > bitsSrc -> return $ IConv vDst ConvZext xSrc -- Promotion is not valid on this platform. _ -> throw $ ErrorInvalidPromotion tSrc tDst ------------------------------------------------------------------------------- -- | Convert a primitive truncation to LLVM, -- or `Nothing` for an invalid truncation. 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) -- Same sized integers | bitsDst == bitsSrc -> return $ ISet vDst xSrc -- Destination is smaller | bitsDst < bitsSrc -> return $ IConv vDst ConvTrunc xSrc -- Unsigned to Signed, -- destination is larger | bitsDst > bitsSrc , isUnsignedT tSrc, isSignedT tDst -> return $ IConv vDst ConvZext xSrc -- Truncation is not valid on this platform. _ -> throw $ ErrorInvalidTruncation tSrc tDst