{-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses, UndecidableInstances, RankNTypes, NoMonomorphismRestriction #-} {-# OPTIONS_GHC -fno-warn-unused-do-bind -fno-warn-missing-signatures #-} module LLVM.ST ( CUInt, CULLong , IntPredicate(..), FPPredicate(..) , LLVM, MonadLLVM , getContext, liftLL, liftST , MemoryBuffer , createMemoryBufferWithContentsOfFile , createMemoryBufferWithSTDIN , createMemoryBufferWithMemoryRange , createMemoryBufferWithMemoryRangeCopy , run, run2, runLLVM , Context , W.getGlobalContext , W.contextCreate , STPassManager , createPassManager , populateModulePassManager , populateLTOPassManager , runPassManager , ModuleGen, MonadMG , runModuleGen, liftMG , STModule , Module , unsafeFreeze, unsafeThaw , parseBitcode , writeBitcodeToFile , getModule , genModule , verifyModule , showModule , linkModules , STBasicBlock , appendBasicBlock , STValue , Linkage(..) , Attribute(..) , CallingConvention(..) , showValue , typeOf , findGlobal, findFunction , addFunction, genFunction, defineFunction, runCodeGen , getFuncCallConv, setFuncCallConv, setInstrCallConv , getFunctionParams , addParamAttrib, addFuncAttrib, removeAttrib , getLinkage, setLinkage , getTailCall, setTailCall , verifyFunction , getUndef , isConstant, isNull, isUndef, isUnreachable , constInt , constPtrNull , constString, constStruct , STType , TypeKind(..) , typeKind , showType , findType , sizeOf , intType, floatType, doubleType, voidType , functionType, structType, vectorType, arrayType , pointerTypeInSpace, pointerType , structCreateNamed, structSetBody , CodeGen, MonadCG , liftCG , position, positionAtEnd, positionBefore, positionAfter , getEntryBasicBlock, getNextBasicBlock , getFirstInstruction, getNextInstruction, getPreviousInstruction, getLastInstruction , getInsertBlock, getFunction, getParams , getValueName, setValueName , buildTrunc , buildZExt , buildSExt , buildFPToUI , buildFPToSI , buildUIToFP , buildSIToFP , buildFPTrunc , buildFPExt , buildPtrToInt , buildIntToPtr , buildBitCast , buildPointerCast , buildTruncOrBitCast , buildZExtOrBitCast , buildSExtOrBitCast , buildInBoundsGEP , buildAlloca , buildLoad, buildStore , buildCall , buildBr, buildCondBr , buildSwitch, addCase , buildPhi, addIncoming , buildCase, buildIf , buildRet, buildUnreachable , buildAdd , buildSub , buildMul , buildFAdd , buildFMul , buildFPCast , buildFSub , buildUDiv , buildSDiv , buildExactSDiv , buildFDiv , buildURem , buildSRem , buildFRem , buildShl , buildLShr , buildAShr , buildAnd , buildOr , buildXor , buildNeg , buildFNeg , buildNot , buildNSWAdd , buildNSWMul , buildNSWNeg , buildNSWSub , buildNUWAdd , buildNUWMul , buildNUWNeg , buildNUWSub , buildICmp, buildFCmp , buildGlobalString, buildGlobalStringPtr -- , constNeg -- , constNot , constAdd , constSub , constMul -- , constExactSDiv , constFAdd , constFMul -- , constFNeg , constFPCast , constFSub , constUDiv , constSDiv , constFDiv , constURem , constSRem , constFRem , constAnd , constOr , constXor -- , constICmp -- , constFCmp , constShl , constLShr , constAShr , constGEP , constTrunc , constSExt , constZExt , constFPTrunc , constFPExt , constUIToFP , constSIToFP , constFPToUI , constFPToSI , constPtrToInt , constIntToPtr , constBitCast -- , constSelect -- , constExtractElement -- , constInsertElement -- , constShuffleVector -- , constRealOfString -- , constNSWMul -- , constNSWNeg -- , constNSWSub -- , constNUWAdd -- , constNUWMul -- , constNUWNeg -- , constNUWSub ) where import Control.Applicative import Control.Monad.Reader import Control.Monad.ST.Safe import Control.Monad.ST.Unsafe (unsafeIOToST, unsafeSTToIO) import System.IO.Unsafe (unsafePerformIO) import qualified LLVM.Wrapper.Core as W import qualified LLVM.Wrapper.Linker as W import qualified LLVM.Wrapper.BitReader as W import qualified LLVM.Wrapper.BitWriter as W import qualified LLVM.Wrapper.Analysis as W import qualified LLVM.Wrapper.Transforms.PassManagerBuilder as W import LLVM.Wrapper.Core ( MemoryBuffer, Context, BasicBlock, Type, Value, Builder , CUInt, CULLong , TypeKind(..) , Linkage(..) , Attribute(..) , CallingConvention(..) , IntPredicate(..), FPPredicate(..) , createMemoryBufferWithContentsOfFile , createMemoryBufferWithSTDIN , createMemoryBufferWithMemoryRange , createMemoryBufferWithMemoryRangeCopy ) newtype STPassManager c s = STPM W.PassManager deriving Eq newtype Module = PM W.Module deriving Eq newtype STModule c s = STM { unSTM :: W.Module } deriving Eq newtype STBasicBlock c s = STB { unSTB :: BasicBlock } deriving Eq newtype STType c s = STT { unSTT :: Type } deriving Eq newtype STValue c s = STV { unSTV :: Value } deriving Eq writeBitcodeToFile :: Module -> FilePath -> IO () writeBitcodeToFile (PM m) = W.writeBitcodeToFile m -- Note: LLVM will sometimes call exit inside this. Probably not intended behavior. verifyModule :: Module -> Maybe String verifyModule (PM m) = unsafePerformIO (W.verifyModule m) instance Show Module where show (PM m) = unsafePerformIO $ W.dumpModuleToString m newtype LLVM c s a = LL (ReaderT Context (ST s) a) deriving (Functor, Applicative, Monad) class MonadLLVM m where getContext :: m c s Context liftLL :: LLVM c s a -> m c s a liftST :: ST s a -> m c s a instance MonadLLVM LLVM where getContext = LL ask liftLL = id liftST = LL . lift wrap :: MonadLLVM m => IO a -> m c s a wrap = liftLL . LL . lift . unsafeIOToST run :: Context -> (forall c s. LLVM c s (STModule c s)) -> Module run ctx action = runST $ runLLVM ctx (action >>= unsafeFreeze) run2 :: Context -> (forall c s. LLVM c s (STModule c s, a)) -> (Module, a) run2 ctx action = runST $ runLLVM ctx (do (m, x) <- action; m' <- unsafeFreeze m; return (m', x)) runLLVM :: Context -> (forall c. LLVM c s a) -> ST s a runLLVM ctx (LL lm) = runReaderT lm ctx unsafeFreeze :: (Monad (m c s), MonadLLVM m) => STModule c s -> m c s Module unsafeFreeze (STM m) = liftLL $ return (PM m) unsafeThaw :: (Monad (m c s), MonadLLVM m) => Module -> m c s (STModule c s) unsafeThaw (PM m) = liftLL $ return $ STM m showModule :: (Monad (m c s), MonadLLVM m) => STModule c s -> m c s String showModule (STM m) = wrap . W.dumpModuleToString $ m -- Source module is unusable after this linkModules :: (Monad (m c s), MonadLLVM m) => STModule c s -> STModule c s -> m c s (Maybe String) linkModules (STM dest) (STM src) = wrap $ W.linkModules dest src W.DestroySource parseBitcode :: (Functor (m c s), Monad (m c s), MonadLLVM m) => MemoryBuffer -> m c s (Either String (STModule c s)) parseBitcode buf = do ctx <- getContext (fmap . fmap) STM . wrap $ W.parseBitcodeInContext ctx buf sizeOf :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s (STValue c s) sizeOf (STT ty) = wrap . fmap STV $ W.sizeOf ty typeKind :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s TypeKind typeKind (STT t) = wrap $ W.getTypeKind t showType :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s String showType (STT t) = wrap . W.dumpTypeToString $ t showValue :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s String showValue (STV v) = wrap . W.dumpValueToString $ v functionType :: (Monad (m c s), MonadLLVM m) => STType c s -> [STType c s] -> Bool -> m c s (STType c s) functionType (STT ret) args variadic = liftLL $ return $ STT (W.functionType ret (map unSTT args) variadic) intType :: (Monad (m c s), MonadLLVM m) => CUInt -> m c s (STType c s) intType i = do ctx <- getContext wrap . fmap STT $ W.intTypeInContext ctx i doubleType :: (Monad (m c s), MonadLLVM m) => m c s (STType c s) doubleType = do ctx <- getContext wrap . fmap STT $ W.doubleTypeInContext ctx floatType :: (Monad (m c s), MonadLLVM m) => m c s (STType c s) floatType = do ctx <- getContext wrap . fmap STT $ W.floatTypeInContext ctx voidType :: (Monad (m c s), MonadLLVM m) => m c s (STType c s) voidType = do ctx <- getContext wrap . fmap STT $ W.voidTypeInContext ctx structType :: (Monad (m c s), MonadLLVM m) => [STType c s] -> Bool -> m c s (STType c s) structType types packed = do ctx <- getContext wrap . fmap STT $ W.structTypeInContext ctx (map unSTT types) packed structCreateNamed :: (Monad (m c s), MonadLLVM m) => String -> m c s (STType c s) structCreateNamed n = getContext >>= wrap . fmap STT . flip W.structCreateNamedInContext n structSetBody :: (Monad (m c s), MonadLLVM m) => STType c s -> [STType c s] -> Bool -> m c s () structSetBody (STT struct) body packed = wrap $ W.structSetBody struct (map unSTT body) packed vectorType :: (Monad (m c s), MonadLLVM m) => STType c s -> CUInt -> m c s (STType c s) vectorType (STT t) count = return $ STT (W.vectorType t count) arrayType :: (Monad (m c s), MonadLLVM m) => STType c s -> CUInt -> m c s (STType c s) arrayType (STT t) count = return $ STT (W.arrayType t count) pointerTypeInSpace :: (Monad (m c s), MonadLLVM m) => STType c s -> CUInt -> m c s (STType c s) pointerTypeInSpace (STT t) addrSpace = return $ STT (W.pointerType t addrSpace) pointerType :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s (STType c s) pointerType ty = pointerTypeInSpace ty 0 getValueName :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s String getValueName (STV v) = wrap $ W.getValueName v setValueName :: (Monad (m c s), MonadLLVM m) => STValue c s -> String -> m c s () setValueName (STV v) = wrap . W.setValueName v isUnreachable :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool isUnreachable (STV v) = wrap $ W.isUnreachable v isConstant :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool isConstant (STV v) = wrap $ W.isConstant v isNull :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool isNull (STV v) = wrap $ W.isNull v isUndef :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool isUndef (STV v) = wrap $ W.isUndef v getUndef :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s (STValue c s) getUndef = return . STV . W.getUndef . unSTT constInt :: (Monad (m c s), MonadLLVM m) => STType c s -> CULLong -> Bool -> m c s (STValue c s) constInt (STT intTy) value signExtend = return . STV $ W.constInt intTy value signExtend constPtrNull :: (Monad (m c s), MonadLLVM m) => STType c s -> m c s (STValue c s) constPtrNull (STT ty) = wrap . fmap STV $ W.constPointerNull ty constString :: (Monad (m c s), MonadLLVM m) => String -> Bool -> m c s (STValue c s) constString str nullTerminated = do ctx <- getContext wrap . fmap STV $ W.constStringInContext ctx str nullTerminated constStruct :: (Monad (m c s), MonadLLVM m) => [STValue c s] -> Bool -> m c s (STValue c s) constStruct values packed = do ctx <- getContext wrap . fmap STV $ W.constStructInContext ctx (map unSTV values) packed appendBasicBlock :: (Monad (m c s), MonadLLVM m) => String -> STValue c s -> m c s (STBasicBlock c s) appendBasicBlock name (STV func) = do ctx <- getContext wrap . fmap STB $ W.appendBasicBlockInContext ctx func name getFunctionParams :: (Functor (m c s), Monad (m c s), MonadLLVM m) => STValue c s -> m c s [STValue c s] getFunctionParams (STV func) = (fmap . fmap) STV . wrap $ W.getParams func addParamAttrib :: (Monad (m c s), MonadLLVM m) => STValue c s -> Attribute -> m c s () addParamAttrib (STV param) = wrap . W.addAttribute param addFuncAttrib :: (Monad (m c s), MonadLLVM m) => STValue c s -> Attribute -> m c s () addFuncAttrib (STV func) = wrap . W.addFunctionAttr func removeAttrib :: (Monad (m c s), MonadLLVM m) => STValue c s -> Attribute -> m c s () removeAttrib (STV val) = wrap . W.removeAttribute val typeOf :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s (STType c s) typeOf (STV v) = wrap . fmap STT $ W.typeOf v data MGS = MGS { mgModule :: W.Module, mgCtx :: Context } newtype ModuleGen c s a = MG (ReaderT MGS (ST s) a) deriving (Functor, Applicative, Monad) class MonadLLVM m => MonadMG m where liftMG :: ModuleGen c s a -> m c s a instance MonadReader (STModule c s) (ModuleGen c s) where ask = fmap (STM . mgModule) (MG ask) local f (MG mg) = MG (local (\(MGS m ctx) -> MGS (unSTM . f . STM $ m) ctx) mg) instance MonadLLVM ModuleGen where getContext = fmap mgCtx $ MG ask liftLL (LL s) = do ctx <- getContext MG (lift $ runReaderT s ctx) liftST = MG . lift instance MonadMG ModuleGen where liftMG = id -- Internal unsafeMod :: ModuleGen c s W.Module unsafeMod = fmap mgModule $ MG ask getModule :: MonadMG m => m c s (STModule c s) getModule = liftMG ask genModule :: (Monad (m c s), MonadLLVM m) => String -> ModuleGen c s a -> m c s a genModule name (MG mg) = do ctx <- getContext wrap $ do m <- W.moduleCreateWithNameInContext name ctx unsafeSTToIO . runReaderT mg $ MGS m ctx runModuleGen :: (Monad (m c s), MonadLLVM m) => STModule c s -> ModuleGen c s a -> m c s a runModuleGen (STM m) (MG mg) = do ctx <- getContext liftLL $ LL . lift . runReaderT mg $ MGS m ctx createPassManager :: (Functor (m c s), MonadLLVM m) => m c s (STPassManager c s) createPassManager = fmap STPM . wrap $ W.createPassManager populateModulePassManager :: MonadLLVM m => CUInt -> CUInt -> STPassManager c s -> m c s () populateModulePassManager optLevel optSizeLevel (STPM pm) = wrap $ do pmb <- W.passManagerBuilderCreate W.passManagerBuilderSetOptLevel pmb optLevel W.passManagerBuilderSetSizeLevel pmb optSizeLevel W.passManagerBuilderPopulateModulePassManager pmb pm populateLTOPassManager :: MonadLLVM m => CUInt -> CUInt -> Bool -> Bool -> STPassManager c s -> m c s () populateLTOPassManager optLevel optSizeLevel internalize inline (STPM pm) = wrap $ do pmb <- W.passManagerBuilderCreate W.passManagerBuilderSetOptLevel pmb optLevel W.passManagerBuilderSetSizeLevel pmb optSizeLevel W.passManagerBuilderPopulateLTOPassManager pmb pm internalize inline runPassManager :: MonadLLVM m => STPassManager c s -> STModule c s -> m c s Bool runPassManager (STPM pm) (STM m) = wrap $ W.runPassManager pm m findType :: MonadMG m => String -> m c s (Maybe (STType c s)) findType name = liftMG $ unsafeMod >>= ((fmap . fmap) STT . wrap . flip W.getTypeByName name) findGlobal :: MonadMG m => String -> m c s (Maybe (STValue c s)) findGlobal name = liftMG $ unsafeMod >>= ((fmap . fmap) STV . wrap . flip W.getNamedGlobal name) findFunction :: MonadMG m => String -> m c s (Maybe (STValue c s)) findFunction name = liftMG $ unsafeMod >>= ((fmap . fmap) STV . wrap . flip W.getNamedFunction name) addFunction :: MonadMG m => String -> STType c s -> m c s (STValue c s) addFunction name (STT ty) = liftMG $ unsafeMod >>= (\m -> fmap STV . wrap $ W.addFunction m name ty) getLinkage :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Linkage getLinkage (STV v) = wrap (W.getLinkage v) setLinkage :: (Monad (m c s), MonadLLVM m) => STValue c s -> Linkage -> m c s () setLinkage (STV v) = wrap . W.setLinkage v getTailCall :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool getTailCall (STV call) = wrap $ W.isTailCall call setTailCall :: (Monad (m c s), MonadLLVM m) => STValue c s -> Bool -> m c s () setTailCall (STV call) = wrap . W.setTailCall call setFuncCallConv :: (Monad (m c s), MonadLLVM m) => STValue c s -> CallingConvention -> m c s () setFuncCallConv (STV func) = wrap . W.setFunctionCallConv func getFuncCallConv :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s CallingConvention getFuncCallConv (STV func) = wrap $ W.getFunctionCallConv func setInstrCallConv :: (Monad (m c s), MonadLLVM m) => STValue c s -> CallingConvention -> m c s () setInstrCallConv (STV func) = wrap . W.setInstructionCallConv func data CGS = CGS { cgBuilder :: Builder, cgMGS :: MGS } newtype CodeGen c s a = CG { unCG :: ReaderT CGS (ST s) a } deriving (Functor, Applicative, Monad) class MonadMG m => MonadCG m where liftCG :: CodeGen c s a -> m c s a instance MonadLLVM CodeGen where getContext = fmap (mgCtx . cgMGS) $ CG ask liftLL (LL s) = do ctx <- getContext CG (lift $ runReaderT s ctx) liftST = CG . lift instance MonadMG CodeGen where liftMG (MG mg) = do r <- CG ask CG (lift $ runReaderT mg (cgMGS r)) instance MonadCG CodeGen where liftCG = id -- Declare, initialize, and define genFunction :: (Functor (m c s), Monad (m c s), MonadMG m) => String -> STType c s -> CodeGen c s a -> m c s a genFunction name ty cg = do f <- addFunction name ty bb <- appendBasicBlock "entry" f mgs <- liftMG $ MG ask wrap (do b <- W.createBuilderInContext (mgCtx mgs) unsafeSTToIO (runReaderT (unCG (positionAtEnd bb >> cg)) (CGS b mgs))) -- Initialize and define defineFunction :: (Functor (m c s), Monad (m c s), MonadMG m) => STValue c s -> CodeGen c s a -> m c s a defineFunction func cg = do bb <- appendBasicBlock "entry" func mgs <- liftMG $ MG ask wrap (do b <- W.createBuilderInContext (mgCtx mgs) unsafeSTToIO (runReaderT (unCG (positionAtEnd bb >> cg)) (CGS b mgs))) -- Just establish a context runCodeGen :: (Monad (m c s), MonadMG m) => STValue c s -> CodeGen c s a -> ModuleGen c s a runCodeGen (STV func) cg = do bbs <- wrap $ W.getBasicBlocks func let cg' = if null bbs then cg else positionAtEnd (STB (last bbs)) >> cg mgs <- MG ask wrap (do b <- W.createBuilderInContext (mgCtx mgs) unsafeSTToIO (runReaderT (unCG cg') (CGS b mgs))) verifyFunction :: (Monad (m c s), MonadLLVM m) => STValue c s -> m c s Bool verifyFunction (STV f) = wrap (W.verifyFunction f) position :: MonadCG m => STBasicBlock c s -> STValue c s -> m c s () position (STB block) (STV instr) = liftCG $ do b <- fmap cgBuilder $ CG ask wrap $ W.positionBuilder b block instr positionAtEnd :: MonadCG m => STBasicBlock c s -> m c s () positionAtEnd (STB block) = liftCG $ CG ask >>= wrap . flip W.positionAtEnd block . cgBuilder positionBefore :: MonadCG m => STValue c s -> m c s () positionBefore (STV v) = liftCG $ CG ask >>= wrap . flip W.positionBefore v . cgBuilder positionAfter :: MonadCG m => STValue c s -> m c s () positionAfter (STV v) = liftCG $ CG ask >>= (\builder -> wrap $ do block <- W.getInstructionParent v W.positionBuilder builder block v) . cgBuilder getFirstInstruction :: MonadLLVM m => STBasicBlock c s -> m c s (STValue c s) getFirstInstruction (STB b) = wrap . fmap STV . W.getFirstInstruction $ b getLastInstruction :: MonadLLVM m => STBasicBlock c s -> m c s (STValue c s) getLastInstruction (STB b) = wrap . fmap STV . W.getLastInstruction $ b getNextInstruction :: MonadLLVM m => STValue c s -> m c s (STValue c s) getNextInstruction (STV v) = wrap . fmap STV . W.getNextInstruction $ v getPreviousInstruction :: MonadLLVM m => STValue c s -> m c s (STValue c s) getPreviousInstruction (STV v) = wrap . fmap STV . W.getPreviousInstruction $ v getInsertBlock :: MonadCG m => m c s (STBasicBlock c s) getInsertBlock = liftCG $ CG ask >>= wrap . fmap STB . W.getInsertBlock . cgBuilder getEntryBasicBlock :: MonadLLVM m => STValue c s -> m c s (STBasicBlock c s) getEntryBasicBlock (STV f) = liftLL $ wrap . fmap STB . W.getEntryBasicBlock $ f getNextBasicBlock :: MonadLLVM m => STBasicBlock c s -> m c s (Maybe (STBasicBlock c s)) getNextBasicBlock (STB b) = liftLL $ wrap . (fmap . fmap) STB . W.getNextBasicBlock $ b getFunction :: MonadCG m => m c s (STValue c s) getFunction = liftCG $ getInsertBlock >>= (\(STB b) -> wrap . fmap STV $ W.getBasicBlockParent b) getParams :: MonadCG m => m c s [STValue c s] getParams = liftCG $ getFunction >>= getFunctionParams buildInBoundsGEP :: (Monad (m c s), MonadCG m) => String -> STValue c s -> [STValue c s] -> m c s (STValue c s) buildInBoundsGEP name (STV aggPtr) indices = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildInBoundsGEP b aggPtr (map unSTV indices) name constGEP :: (Monad (m c s), MonadCG m) => STValue c s -> [STValue c s] -> m c s (STValue c s) constGEP (STV aggPtr) indices = wrap . fmap STV $ W.constGEP aggPtr (map unSTV indices) buildAlloca :: (Monad (m c s), MonadCG m) => String -> STType c s -> m c s (STValue c s) buildAlloca name (STT ty) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildAlloca b ty name buildLoad :: (Monad (m c s), MonadCG m) => String -> STValue c s -> m c s (STValue c s) buildLoad name (STV ptr) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildLoad b ptr name buildStore :: (Monad (m c s), MonadCG m) => STValue c s -> STValue c s -> m c s (STValue c s) buildStore (STV value) (STV ptr) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildStore b value ptr buildCall :: (Monad (m c s), MonadCG m) => String -> STValue c s -> [STValue c s] -> m c s (STValue c s) buildCall name (STV func) args = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildCall b func (map unSTV args) name buildRet :: (Monad (m c s), MonadCG m) => STValue c s -> m c s (STValue c s) buildRet (STV x) = do b <- liftCG $ CG ask; wrap . fmap STV $ W.buildRet (cgBuilder b) x buildBr :: (Monad (m c s), MonadCG m) => STBasicBlock c s -> m c s (STValue c s) buildBr (STB block) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildBr b block buildCondBr :: (Monad (m c s), MonadCG m) => STValue c s -> STBasicBlock c s -> STBasicBlock c s -> m c s (STValue c s) buildCondBr (STV cond) (STB trueBlock) (STB falseBlock) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildCondBr b cond trueBlock falseBlock buildSwitch :: (Monad (m c s), MonadCG m) => STValue c s -> STBasicBlock c s -> CUInt -> m c s (STValue c s) buildSwitch (STV val) (STB defaultBlock) count = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildSwitch b val defaultBlock count addCase :: (Monad (m c s), MonadCG m) => STValue c s -> STValue c s -> STBasicBlock c b -> m c s () addCase (STV switch) (STV val) (STB block) = wrap $ W.addCase switch val block buildCase :: (Functor (m c s), Monad (m c s), MonadCG m) => STValue c s -> m c s (STValue c s) -> [(STValue c s, m c s (STValue c s))] -> m c s (STValue c s) buildCase value defaultCode alts = do func <- getFunction defBlock <- appendBasicBlock "caseDefault" func switch <- buildSwitch value defBlock (fromIntegral (length alts)) positionAtEnd defBlock defResult <- defaultCode defExit <- getInsertBlock results <- forM alts $ \(val, cg) -> do inBlock <- appendBasicBlock "caseAlt" func addCase switch val inBlock positionAtEnd inBlock result <- cg outBlock <- getInsertBlock return (result, inBlock, outBlock) end <- appendBasicBlock "caseExit" func positionAtEnd defBlock isUnreachable defResult >>= flip unless (void $ buildBr end) forM_ results $ \(result, _, outBlock) -> do unreachable <- isUnreachable result unless unreachable $ void $ positionAtEnd outBlock >> buildBr end positionAtEnd end case results of [] -> return defResult (result, _, _):_ -> do ty <- typeOf result phi <- buildPhi "caseResult" ty inputs <- filterM (\(r, _, _) -> fmap not $ isUnreachable r) ((defResult, defBlock, defExit):results) addIncoming phi (map (\(outVal, _, outBlock) -> (outVal, outBlock)) inputs) return phi buildIf :: (Monad (m c s), MonadCG m) => STType c s -> STValue c s -> m c s (STValue c s) -> m c s (STValue c s) -> m c s (STValue c s) buildIf ty cond whenTrue whenFalse = do func <- getFunction initialBlock <- getInsertBlock trueBlock <- appendBasicBlock "ifTrue" func positionAtEnd trueBlock trueResult <- whenTrue trueExit <- getInsertBlock falseBlock <- appendBasicBlock "ifFalse" func positionAtEnd falseBlock falseResult <- whenFalse falseExit <- getInsertBlock positionAtEnd initialBlock buildCondBr cond trueBlock falseBlock exitBlock <- appendBasicBlock "ifExit" func positionAtEnd trueExit buildBr exitBlock positionAtEnd falseExit buildBr exitBlock positionAtEnd exitBlock phi <- buildPhi "ifResult" ty addIncoming phi [ (trueResult, trueExit) , (falseResult, falseExit)] return phi buildPhi :: (Monad (m c s), MonadCG m) => String -> STType c s -> m c s (STValue c s) buildPhi name (STT ty) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildPhi b ty name addIncoming :: (Monad (m c s), MonadCG m) => STValue c s -> [(STValue c s, STBasicBlock c s)] -> m c s () addIncoming (STV phi) incoming = wrap $ W.addIncoming phi (map (\(a, b) -> (unSTV a, unSTB b)) incoming) buildUnreachable :: (Monad (m c s), MonadCG m) => m c s (STValue c s) buildUnreachable = do b <- liftCG $ CG ask; wrap . fmap STV $ W.buildUnreachable (cgBuilder b) wrapCast :: (Monad (m c s), MonadCG m) => (Builder -> Value -> Type -> String -> IO Value) -> String -> STValue c s -> STType c s -> m c s (STValue c s) wrapCast f n (STV v) (STT t) = do b <- liftCG $ CG ask; wrap . fmap STV $ f (cgBuilder b) v t n buildTrunc = wrapCast W.buildTrunc buildZExt = wrapCast W.buildZExt buildSExt = wrapCast W.buildSExt buildFPToUI = wrapCast W.buildFPToUI buildFPToSI = wrapCast W.buildFPToSI buildUIToFP = wrapCast W.buildUIToFP buildSIToFP = wrapCast W.buildSIToFP buildFPTrunc = wrapCast W.buildFPTrunc buildFPExt = wrapCast W.buildFPExt buildPtrToInt = wrapCast W.buildPtrToInt buildIntToPtr = wrapCast W.buildIntToPtr buildBitCast = wrapCast W.buildBitCast buildPointerCast = wrapCast W.buildPointerCast buildTruncOrBitCast = wrapCast W.buildTruncOrBitCast buildZExtOrBitCast = wrapCast W.buildZExtOrBitCast buildSExtOrBitCast = wrapCast W.buildSExtOrBitCast buildFPCast = wrapCast W.buildFPCast wrapUn :: (Monad (m c s), MonadCG m) => (Builder -> Value -> String -> IO Value) -> String -> STValue c s -> m c s (STValue c s) wrapUn f n (STV x) = do b <- liftCG $ CG ask; wrap . fmap STV $ f (cgBuilder b) x n buildNeg = wrapUn W.buildNeg buildFNeg = wrapUn W.buildFNeg buildNot = wrapUn W.buildNot buildNSWNeg = wrapUn W.buildNSWNeg buildNUWNeg = wrapUn W.buildNUWNeg wrapBin :: (Monad (m c s), MonadCG m) => (Builder -> Value -> Value -> String -> IO Value) -> String -> STValue c s -> STValue c s -> m c s (STValue c s) wrapBin f n (STV l) (STV r) = do b <- liftCG $ CG ask; wrap . fmap STV $ f (cgBuilder b) l r n buildAdd = wrapBin W.buildAdd buildSub = wrapBin W.buildSub buildMul = wrapBin W.buildMul buildNSWAdd = wrapBin W.buildNSWAdd buildNSWSub = wrapBin W.buildNSWSub buildNSWMul = wrapBin W.buildNSWMul buildNUWAdd = wrapBin W.buildNUWAdd buildNUWSub = wrapBin W.buildNUWSub buildNUWMul = wrapBin W.buildNUWMul buildUDiv = wrapBin W.buildUDiv buildSDiv = wrapBin W.buildSDiv buildExactSDiv = wrapBin W.buildExactSDiv buildURem = wrapBin W.buildURem buildSRem = wrapBin W.buildSRem buildFAdd = wrapBin W.buildFAdd buildFSub = wrapBin W.buildFSub buildFMul = wrapBin W.buildFMul buildFDiv = wrapBin W.buildFDiv buildFRem = wrapBin W.buildFRem buildShl = wrapBin W.buildShl buildLShr = wrapBin W.buildLShr buildAShr = wrapBin W.buildAShr buildAnd = wrapBin W.buildAnd buildOr = wrapBin W.buildOr buildXor = wrapBin W.buildXor buildICmp :: (Monad (m c s), MonadCG m) => String -> IntPredicate -> STValue c s -> STValue c s -> m c s (STValue c s) buildICmp name f (STV l) (STV r) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildICmp b f l r name buildFCmp :: (Monad (m c s), MonadCG m) => String -> FPPredicate -> STValue c s -> STValue c s -> m c s (STValue c s) buildFCmp name f (STV l) (STV r) = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildFCmp b f l r name wrapConstBin :: (Monad (m c s), MonadLLVM m) => (Value -> Value -> Value) -> STValue c s -> STValue c s -> m c s (STValue c s) wrapConstBin f (STV l) (STV r) = return . STV $ f l r constAdd = wrapConstBin W.constAdd constSub = wrapConstBin W.constSub constMul = wrapConstBin W.constMul -- constNSWAdd = wrapConstBin W.constNSWAdd -- constNSWSub = wrapConstBin W.constNSWSub -- constNSWMul = wrapConstBin W.constNSWMul -- constNUWAdd = wrapConstBin W.constNUWAdd -- constNUWSub = wrapConstBin W.constNUWSub -- constNUWMul = wrapConstBin W.constNUWMul constUDiv = wrapConstBin W.constUDiv constSDiv = wrapConstBin W.constSDiv --constExactSDiv = wrapConstBin W.constExactSDiv constURem = wrapConstBin W.constURem constSRem = wrapConstBin W.constSRem constFAdd = wrapConstBin W.constFAdd constFSub = wrapConstBin W.constFSub constFMul = wrapConstBin W.constFMul constFDiv = wrapConstBin W.constFDiv constFRem = wrapConstBin W.constFRem constShl = wrapConstBin W.constShl constLShr = wrapConstBin W.constLShr constAShr = wrapConstBin W.constAShr constAnd = wrapConstBin W.constAnd constOr = wrapConstBin W.constOr constXor = wrapConstBin W.constXor buildGlobalString :: (Monad (m c s), MonadCG m) => String -> String -> m c s (STValue c s) buildGlobalString name value = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildGlobalString b value name buildGlobalStringPtr :: (Monad (m c s), MonadCG m) => String -> String -> m c s (STValue c s) buildGlobalStringPtr name value = do b <- liftCG $ fmap cgBuilder (CG ask) wrap . fmap STV $ W.buildGlobalStringPtr b value name wrapConstCast :: (Monad (m c s), MonadLLVM m) => (Value -> Type -> Value) -> STValue c s -> STType c s -> m c s (STValue c s) wrapConstCast f (STV v) (STT t) = liftLL $ return . STV $ f v t constTrunc = wrapConstCast W.constTrunc constZExt = wrapConstCast W.constZExt constSExt = wrapConstCast W.constSExt constFPToUI = wrapConstCast W.constFPToUI constFPToSI = wrapConstCast W.constFPToSI constUIToFP = wrapConstCast W.constUIToFP constSIToFP = wrapConstCast W.constSIToFP constFPTrunc = wrapConstCast W.constFPTrunc constFPExt = wrapConstCast W.constFPExt constPtrToInt = wrapConstCast W.constPtrToInt constIntToPtr = wrapConstCast W.constIntToPtr constBitCast = wrapConstCast W.constBitCast -- constPointerCast = wrapConstCast W.constPointerCast -- constTruncOrBitCast = wrapConstCast W.constTruncOrBitCast -- constZExtOrBitCast = wrapConstCast W.constZExtOrBitCast -- constSExtOrBitCast = wrapConstCast W.constSExtOrBitCast constFPCast = wrapConstCast W.constFPCast