llvm 0.0.2 → 0.4.0.0
raw patch · 41 files changed
+3742/−2950 lines, 41 filesdep +mtlsetup-changednew-uploader
Dependencies added: mtl
Files
- Data/TypeNumbers.hs +56/−0
- INSTALL.txt +18/−44
- LLVM/Core.hs +83/−111
- LLVM/Core/Builder.hs +0/−498
- LLVM/Core/CodeGen.hs +322/−0
- LLVM/Core/CodeGenMonad.hs +66/−0
- LLVM/Core/Constant.hs +0/−338
- LLVM/Core/Data.hs +35/−0
- LLVM/Core/FFI.hsc +0/−628
- LLVM/Core/Instruction.hs +0/−47
- LLVM/Core/Instructions.hs +601/−0
- LLVM/Core/Type.hs +179/−514
- LLVM/Core/Util.hs +313/−0
- LLVM/Core/Utils.hs +0/−41
- LLVM/Core/Value.hs +0/−312
- LLVM/ExecutionEngine.hs +71/−159
- LLVM/ExecutionEngine/Engine.hs +170/−0
- LLVM/ExecutionEngine/FFI.hsc +0/−69
- LLVM/FFI/Analysis.hsc +19/−0
- LLVM/FFI/BitReader.hsc +13/−0
- LLVM/FFI/BitWriter.hsc +12/−0
- LLVM/FFI/Core.hsc +1112/−0
- LLVM/FFI/ExecutionEngine.hsc +110/−0
- LLVM/FFI/Target.hsc +50/−0
- LLVM/FFI/Transforms/Scalar.hsc +29/−0
- Makefile +14/−3
- README.txt +11/−16
- Setup.lhs +1/−1
- configure +26/−11
- configure.ac +12/−3
- examples/BrainF.hs +143/−0
- examples/Fibonacci.hs +88/−49
- examples/HelloJIT.hs +18/−38
- examples/HowToUseJIT.hs +0/−43
- examples/Makefile +18/−3
- llvm.buildinfo.in +1/−1
- llvm.cabal +33/−21
- tests/Makefile +16/−0
- tests/TestValue.hs +69/−0
- tools/IntrinsicMangler.hs +22/−0
- tools/Makefile +11/−0
+ Data/TypeNumbers.hs view
@@ -0,0 +1,56 @@+-- |Type level decimal numbers.+module Data.TypeNumbers(+ IsTypeNumber, typeNumber,+ D0(..),D1(..),D2(..),D3(..),D4(..),D5(..),D6(..),D7(..),D8(..),D9(..),+ End(..)+ ) where++-- |A type level number, i.e., a sequence of type level digits.+class IsTypeNumber ds where+ typeNumber' :: (Num a) => ds -> a -> a++-- |Get the numeric value of a type level number.+-- This function does not evaluate its argument.+typeNumber :: (IsTypeNumber ds, Num a) => ds -> a+typeNumber ds = typeNumber' ds 0++-- |Mark the end of a digit sequence.+data End = End+instance IsTypeNumber End where+ typeNumber' _ a = a++-- |The 'D0' - 'D9' types represent type level digits that form+-- a number by, e.g, @D1 (D0 (D5 End))@.+-- On the value level a slightly more palatable form can be used,+-- @D1$D0$D5$End@.+data D0 a = D0 a+data D1 a = D1 a+data D2 a = D2 a+data D3 a = D3 a+data D4 a = D4 a+data D5 a = D5 a+data D6 a = D6 a+data D7 a = D7 a+data D8 a = D8 a+data D9 a = D9 a++instance (IsTypeNumber ds) => IsTypeNumber (D0 ds) where+ typeNumber' ~(D0 ds) acc = typeNumber' ds (10*acc + 0)+instance (IsTypeNumber ds) => IsTypeNumber (D1 ds) where+ typeNumber' ~(D1 ds) acc = typeNumber' ds (10*acc + 1)+instance (IsTypeNumber ds) => IsTypeNumber (D2 ds) where+ typeNumber' ~(D2 ds) acc = typeNumber' ds (10*acc + 2)+instance (IsTypeNumber ds) => IsTypeNumber (D3 ds) where+ typeNumber' ~(D3 ds) acc = typeNumber' ds (10*acc + 3)+instance (IsTypeNumber ds) => IsTypeNumber (D4 ds) where+ typeNumber' ~(D4 ds) acc = typeNumber' ds (10*acc + 4)+instance (IsTypeNumber ds) => IsTypeNumber (D5 ds) where+ typeNumber' ~(D5 ds) acc = typeNumber' ds (10*acc + 5)+instance (IsTypeNumber ds) => IsTypeNumber (D6 ds) where+ typeNumber' ~(D6 ds) acc = typeNumber' ds (10*acc + 6)+instance (IsTypeNumber ds) => IsTypeNumber (D7 ds) where+ typeNumber' ~(D7 ds) acc = typeNumber' ds (10*acc + 7)+instance (IsTypeNumber ds) => IsTypeNumber (D8 ds) where+ typeNumber' ~(D8 ds) acc = typeNumber' ds (10*acc + 8)+instance (IsTypeNumber ds) => IsTypeNumber (D9 ds) where+ typeNumber' ~(D9 ds) acc = typeNumber' ds (10*acc + 9)
INSTALL.txt view
@@ -9,63 +9,33 @@ Prerequisites ------------- -I'm using GHC 6.8.2 for development. 6.8.1 will probably work. I'll-be happy to accept patches to get things working with 6.6.x, provided-they don't pervert the code much :-)--(My development environment is Fedora 8 x86_64, in case you're-curious.)--Firstly, you'll need the SVN version of LLVM:-- svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm-trunk+Firstly, you'll need to have LLVM. I recommend installing LLVM+version 2.4 which is what it's been tested with. -Build this and install it somewhere. Here's what I do:+Build this and install it somewhere. Follow the LLVM instructions,+or use this: - cd llvn-trunk- ./configure --prefix=$HOME+ cd llvm+ ./configure --prefix=$SOMEWHERE make make install -If you're building the Haskell bindings from the darcs repo (strongly-recommended from now), you'll also need a copy of GNU autoconf.---Using GNU Make-----------------There's a GNU Make Makefile in the top-level directory that builds the-LLVM bindings the way I want them built. In principle, you ought to-be able to simply run something like this:-- make llvm_prefix=/my/llvm/path prefix=/my/preferred/path--These both default to $HOME.+It's a good idea to have $SOMEWHERE/bin is in your path. -Building by hand-------------------If you want to avoid GNU Make, here's a recipe you can follow. Run-these in the root of your darcs repo or unpacked source tarball.--If you're building from darcs, run this once (this is why you need-autoconf installed):-- autoreconf--Configure the package. I'm assuming that LLVM is installed in $HOME,-and that you want the bindings installed in $HOME, too.+Building+--------+It's normal cabal package, but using a configure script as well to+configure LLVM. It can be build and installed with the usual+three steps. - runhaskell Setup configure --prefix=$HOME \- --configure-option --with-llvm-prefix=$HOME --user+Configure the package.+ runhaskell Setup configure --configure-option --with-llvm-prefix=$SOMEWHERE Build.- runhaskell Setup build Install.- runhaskell Setup install @@ -75,3 +45,7 @@ In the examples directory are a few example programs. There's a GNU Make Makefile in there, so running "make" in that directory will build the examples, as will "make examples" in the top-level directory.+Doing "make run" will build and run the examples.++Note: On MacOS X you get a lot of "atom sorting error" warnings. They+seem to be harmless.
LLVM/Core.hs view
@@ -1,117 +1,89 @@-{-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-}--module LLVM.Core- (+-- |The LLVM (Low Level Virtual Machine) is virtual machine at a machine code level.+-- It supports both stand alone code generation and JITing.+-- The Haskell llvm package is a (relatively) high level interface to the LLVM.+-- The high level interface makes it easy to construct LLVM code.+-- There is also an interface to the raw low level LLVM API as exposed by the LLVM C interface.+--+-- LLVM code is organized into modules (type 'Module').+-- Each module contains a number of global variables and functions (type 'Function').+-- Each functions has a number of basic blocks (type 'BasicBlock').+-- Each basic block has a number instructions, where each instruction produces+-- a value (type 'Value').+--+-- Unlike assembly code for a real processor the assembly code for LLVM is+-- in SSA (Static Single Assignment) form. This means that each instruction generates+-- a new bound variable which may not be assigned again.+-- A consequence of this is that where control flow joins from several execution+-- paths there has to be a phi pseudo instruction if you want different variables+-- to be joined into one.+--+-- The definition of several of the LLVM entities ('Module', 'Function', and 'BasicBlock')+-- follow the same pattern. First the entity has to be created using @newX@ (where @X@+-- is one of @Module@, @Function@, or @BasicBlock@), then at some later point it has to+-- given its definition using @defineX@. The reason for splitting the creation and+-- definition is that you often need to be able to refer to an entity before giving+-- it's body, e.g., in two mutually recursive functions.+-- The the @newX@ and @defineX@ function can also be done at the same time by using+-- @createX@. Furthermore, an explicit name can be given to an entity by the+-- @newNamedX@ function; the @newX@ function just generates a fresh name.+module LLVM.Core( -- * Modules- createModule-- -- * Module providers- , createModuleProviderForExistingModule-- -- * Types- , addTypeName- , deleteTypeName-- -- * Values- , addGlobal- , setInitializer-- -- ** Operations on functions- , addFunction- , deleteFunction- , getNamedFunction-+ Module, newModule, newNamedModule, defineModule, destroyModule, createModule,+ ModuleProvider, createModuleProviderForExistingModule,+ PassManager, createPassManager, createFunctionPassManager,+ writeBitcodeToFile,+ -- * Instructions+ module LLVM.Core.Instructions,+ -- * Types classification+ module LLVM.Core.Type,+ -- * Extra types+ module LLVM.Core.Data,+ -- * Values and constants+ Value, ConstValue, valueOf, constOf, value,+ zero, allOnes, undef,+ createString, createStringNul,+ -- * Code generation+ CodeGenFunction, CodeGenModule,+ -- * Functions+ Function, newFunction, newNamedFunction, defineFunction, createFunction,+ TFunction,+ -- * Global variable creation+ Global, newGlobal, newNamedGlobal, defineGlobal, createGlobal,+ TGlobal,+ -- * Globals+ Linkage(..), -- * Basic blocks- , appendBasicBlock- , insertBasicBlock- , deleteBasicBlock+ BasicBlock, newBasicBlock, newNamedBasicBlock, defineBasicBlock, createBasicBlock, getCurrentBasicBlock,+ -- * Debugging+ dumpValue,+ -- * Transformations+ addCFGSimplificationPass, addConstantPropagationPass, addDemoteMemoryToRegisterPass,+ addGVNPass, addInstructionCombiningPass, addPromoteMemoryToRegisterPass, addReassociatePass,+ addTargetData ) where--import Control.Applicative ((<$>))-import Foreign.C.String (withCString)-import Foreign.Marshal.Utils (toBool)-import Foreign.ForeignPtr (FinalizerPtr, newForeignPtr)-import Foreign.Ptr (Ptr, nullPtr)-import Prelude hiding (mod)--import qualified LLVM.Core.FFI as FFI-import qualified LLVM.Core.Builder as B-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V---createModule :: String -> IO T.Module-createModule name =- withCString name $ \namePtr -> do- ptr <- FFI.moduleCreateWithName namePtr- final <- h2c_module FFI.disposeModule- T.Module <$> newForeignPtr final ptr--foreign import ccall "wrapper" h2c_module- :: (FFI.ModuleRef -> IO ()) -> IO (FinalizerPtr a)---createModuleProviderForExistingModule :: T.Module -> IO T.ModuleProvider-createModuleProviderForExistingModule mod =- T.withModule mod $ \modPtr -> do- ptr <- FFI.createModuleProviderForExistingModule modPtr- final <- h2c_moduleProvider FFI.disposeModuleProvider- T.ModuleProvider <$> newForeignPtr final ptr--foreign import ccall "wrapper" h2c_moduleProvider- :: (FFI.ModuleProviderRef -> IO ()) -> IO (FinalizerPtr a)---addTypeName :: (T.Type t) => T.Module -> t -> String -> IO Bool-addTypeName mod typ name =- T.withModule mod $ \modPtr ->- withCString name $ \namePtr ->- toBool <$> FFI.addTypeName modPtr namePtr (T.typeRef typ)- -deleteTypeName :: T.Module -> String -> IO ()-deleteTypeName mod name =- T.withModule mod $ \modPtr ->- withCString name $ FFI.deleteTypeName modPtr--addGlobal :: (T.Type t) => T.Module -> t -> String -> IO (V.GlobalVar t)-addGlobal mod typ name =- T.withModule mod $ \modPtr ->- withCString name $ \namePtr ->- V.GlobalVar . V.mkAnyValue <$> FFI.addGlobal modPtr (T.typeRef typ) namePtr--setInitializer :: V.ConstValue t => V.GlobalVar a -> t -> IO ()-setInitializer global cnst =- FFI.setInitializer (V.valueRef global) (V.valueRef cnst)--addFunction :: (T.Params p) => T.Module -> String -> T.Function r p- -> IO (V.Function r p)-addFunction mod name typ =- T.withModule mod $ \modPtr ->- withCString name $ \namePtr ->- V.Function . V.mkAnyValue <$> FFI.addFunction modPtr namePtr (T.typeRef typ)--deleteFunction :: V.Function r p -> IO ()-deleteFunction = FFI.deleteFunction . V.valueRef--maybePtr :: (Ptr a -> b) -> Ptr a -> Maybe b-maybePtr f ptr | ptr /= nullPtr = Just (f ptr)- | otherwise = Nothing--getNamedFunction :: T.Module -> String -> IO (Maybe (V.Function r p))-getNamedFunction mod name =- T.withModule mod $ \modPtr ->- withCString name $ \namePtr ->- maybePtr (V.Function . V.mkAnyValue) <$> FFI.getNamedFunction modPtr namePtr+import qualified LLVM.FFI.Core as FFI+import LLVM.Core.Util hiding (Function, BasicBlock, createModule, constString, constStringNul)+import LLVM.Core.CodeGen+import LLVM.Core.CodeGenMonad(CodeGenFunction, CodeGenModule)+import LLVM.Core.Data+import LLVM.Core.Instructions+import LLVM.Core.Type -appendBasicBlock :: V.Function r p -> String -> IO B.BasicBlock-appendBasicBlock func name =- withCString name $ \namePtr ->- B.BasicBlock . V.mkAnyValue <$> FFI.appendBasicBlock (V.valueRef func) namePtr+-- |Print a value.+dumpValue :: Value a -> IO ()+dumpValue (Value v) = FFI.dumpValue v -insertBasicBlock :: B.BasicBlock -> String -> IO B.BasicBlock-insertBasicBlock before name =- withCString name $ \namePtr ->- B.BasicBlock . V.mkAnyValue <$> FFI.insertBasicBlock (V.valueRef before) namePtr+{-+dumpType :: forall a . (IsType a) => Value a -> IO ()+dumpType _ = FFI.dumpValue (typeRef (undefined :: a))+-} -deleteBasicBlock :: B.BasicBlock -> IO ()-deleteBasicBlock = FFI.deleteBasicBlock . V.valueRef+-- TODO for types:+-- Enforce free is only called on malloc memory. (Enforce only one free?)+-- Enforce phi nodes a accessor of variables outside the bb+-- Enforce bb terminator+-- Enforce phi first+--+-- TODO:+-- Add Struct, PackedStruct types+-- Get alignment from code gen
− LLVM/Core/Builder.hs
@@ -1,498 +0,0 @@-{-# LANGUAGE- DeriveDataTypeable- , FlexibleContexts- , FunctionalDependencies- , MultiParamTypeClasses- , UndecidableInstances- #-}--module LLVM.Core.Builder- (- Instruction(..)- , BasicBlock(..)-- -- * Instruction building- , createBuilder-- , positionBefore- , positionAtEnd-- -- * Terminators- , retVoid- , ret- , br- , condBr- , switch- , invoke- , unwind- , unreachable-- -- * Arithmetic- , add- , sub- , mul- , uDiv- , sDiv- , fDiv- , uRem- , sRem- , fRem- , shl- , lShr- , aShr- , and- , or- , xor- , neg- , not-- -- * Memory- , malloc- , arrayMalloc- , alloca- , arrayAlloca- , free- , load- , store- , getElementPtr-- -- * Casts- , trunc- , zExt- , sExt- , fpToUI- , fpToSI- , uiToFP- , siToFP- , fpTrunc- , fpExt- , ptrToInt- , intToPtr- , bitCast-- -- * Comparisons- , icmp- , fcmp-- -- * Miscellaneous instructions- , call- , call_- , extractElement- , insertElement- , phi- , select- , vaArg- , shuffleVector- ) where--import Control.Applicative ((<$>))-import Control.Arrow ((***))-import Control.Monad (forM_)-import Data.Typeable (Typeable)-import Foreign.C.String (CString, withCString)-import Foreign.ForeignPtr (FinalizerPtr, ForeignPtr, newForeignPtr,- withForeignPtr)-import Foreign.Marshal.Array (withArray, withArrayLen)-import Prelude hiding (and, not, or)--import qualified LLVM.Core.FFI as FFI-import qualified LLVM.Core.Instruction as I-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V-import LLVM.Core.Type ((:->)(..))-import LLVM.Core.Value (Instruction(..))---newtype Builder = Builder {- fromBuilder :: ForeignPtr FFI.Builder- }- deriving (Typeable)--newtype BasicBlock = BasicBlock V.AnyValue- deriving (V.DynamicValue, Typeable, V.Value)--withBuilder :: Builder -> (FFI.BuilderRef -> IO a) -> IO a-withBuilder = withForeignPtr . fromBuilder--createBuilder :: IO Builder-createBuilder = do- final <- h2c_builder FFI.disposeBuilder- ptr <- FFI.createBuilder- Builder <$> newForeignPtr final ptr--foreign import ccall "wrapper" h2c_builder- :: (FFI.BuilderRef -> IO ()) -> IO (FinalizerPtr a)--positionBefore :: Builder -> Instruction a -> IO ()-positionBefore bld insn =- withBuilder bld $ \bldPtr ->- FFI.positionBefore bldPtr (V.valueRef insn)--positionAtEnd :: Builder -> BasicBlock -> IO ()-positionAtEnd bld bblk =- withBuilder bld $ \bldPtr ->- FFI.positionAtEnd bldPtr (V.valueRef bblk)--instruction :: IO FFI.ValueRef -> IO (Instruction t)-instruction = fmap (Instruction . V.mkAnyValue)--unary :: (V.Value a)- => (FFI.BuilderRef -> FFI.ValueRef -> CString -> IO FFI.ValueRef)- -> Builder -> String -> a -> IO (Instruction t)-unary ffi bld name a =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- Instruction . V.mkAnyValue <$>- ffi bldPtr (V.valueRef a) namePtr--binary :: (V.Value a, V.Value b)- => (FFI.BuilderRef -> FFI.ValueRef -> FFI.ValueRef -> CString- -> IO FFI.ValueRef)- -> Builder -> String -> a -> b -> IO (Instruction t)-binary ffi bld name a b =- withBuilder bld $ \bldPtr ->- withCString name $ instruction . ffi bldPtr (V.valueRef a) (V.valueRef b) --add :: (T.Arithmetic t,- V.Value a, V.TypedValue a t,- V.Value b, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-add = binary FFI.buildAdd--sub :: (T.Arithmetic t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-sub = binary FFI.buildSub--mul :: (T.Arithmetic t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-mul = binary FFI.buildSub--uDiv :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-uDiv = binary FFI.buildUDiv--sDiv :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-sDiv = binary FFI.buildSDiv--fDiv :: (T.Real t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-fDiv = binary FFI.buildFDiv--uRem :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-uRem = binary FFI.buildURem--sRem :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-sRem = binary FFI.buildSRem--fRem :: (T.Real t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-fRem = binary FFI.buildFRem--shl :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-shl = binary FFI.buildShl--lShr :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-lShr = binary FFI.buildLShr--aShr :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-aShr = binary FFI.buildAShr--and :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-and = binary FFI.buildAnd--or :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-or = binary FFI.buildOr--xor :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> a -> b -> IO (Instruction t)-xor = binary FFI.buildAnd--neg :: (T.Arithmetic t, V.TypedValue v t)- => Builder -> String -> v -> IO (Instruction t)-neg = unary FFI.buildNeg--not :: (T.Arithmetic t, V.TypedValue v t)- => Builder -> String -> v -> IO (Instruction t)-not = unary FFI.buildNot--typed :: (V.Value v, T.Type s, T.Type t)- => (FFI.BuilderRef -> FFI.ValueRef -> FFI.TypeRef -> CString- -> IO FFI.ValueRef)- -> Builder -> String -> v -> s -> IO (Instruction t)-typed ffi bld name a t =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- Instruction . V.mkAnyValue <$> ffi bldPtr (V.valueRef a) (T.typeRef t) namePtr--trunc :: (T.Integer s, V.TypedValue v s, T.Integer t)- => Builder -> String -> v -> s -> IO (Instruction t)-trunc = typed FFI.buildTrunc--zExt :: (T.Integer s, V.TypedValue v s, T.Integer t)- => Builder -> String -> v -> s -> IO (Instruction t)-zExt = typed FFI.buildZExt--sExt :: (T.Integer s, V.TypedValue v s, T.Integer t)- => Builder -> String -> v -> s -> IO (Instruction t)-sExt = typed FFI.buildSExt--fpToUI :: (T.Integer s, V.TypedValue v s, T.Real t)- => Builder -> String -> v -> s -> IO (Instruction t)-fpToUI = typed FFI.buildFPToUI--fpToSI :: (T.Integer s, V.TypedValue v s, T.Real t)- => Builder -> String -> v -> s -> IO (Instruction t)-fpToSI = typed FFI.buildFPToSI--uiToFP :: (T.Real s, V.TypedValue v s, T.Integer t)- => Builder -> String -> v -> s -> IO (Instruction t)-uiToFP = typed FFI.buildUIToFP--siToFP :: (T.Real s, V.TypedValue v s, T.Integer t)- => Builder -> String -> v -> s -> IO (Instruction t)-siToFP = typed FFI.buildSIToFP--fpTrunc :: (T.Real s, V.TypedValue v s, T.Real t)- => Builder -> String -> v -> s -> IO (Instruction t)-fpTrunc = typed FFI.buildFPTrunc--fpExt :: (T.Real s, V.TypedValue v s, T.Real t)- => Builder -> String -> v -> s -> IO (Instruction t)-fpExt = typed FFI.buildFPExt--ptrToInt :: (V.TypedValue (T.Pointer s) s, T.Integer t)- => Builder -> String -> T.Pointer s -> s -> IO (Instruction t)-ptrToInt = typed FFI.buildPtrToInt--intToPtr :: (T.Integer s, V.TypedValue v s, T.Type t)- => Builder -> String -> v -> t -> IO (Instruction (T.Pointer t))-intToPtr = typed FFI.buildIntToPtr--bitCast :: (V.TypedValue v s, T.Type t)- => Builder -> String -> v -> s -> IO (Instruction t)-bitCast = typed FFI.buildBitCast--fcmp :: (T.Real t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> I.RealPredicate -> a -> b- -> IO (Instruction T.Int1)-fcmp bld name p = binary (flip FFI.buildFCmp (I.fromRP p)) bld name--icmp :: (T.Integer t, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> I.IntPredicate -> a -> b- -> IO (Instruction T.Int1)-icmp bld name p = binary (flip FFI.buildICmp (I.fromIP p)) bld name--retVoid :: Builder -> IO (Instruction T.Void)-retVoid bld = withBuilder bld $ instruction . FFI.buildRetVoid--ret :: (T.FirstClass t, V.TypedValue v t) => Builder -> v -> IO (Instruction t)-ret bld v =- withBuilder bld $ \bldPtr ->- instruction $ FFI.buildRet bldPtr (V.valueRef v)--br :: Builder -> BasicBlock -> IO (Instruction T.Void)-br bld bblk =- withBuilder bld $ \bldPtr ->- instruction $ FFI.buildBr bldPtr (V.valueRef bblk)--condBr :: (V.TypedValue v T.Int1)- => Builder -> v -> BasicBlock -> BasicBlock- -> IO (Instruction T.Void)-condBr bld bit true false =- withBuilder bld $ \bldPtr ->- instruction $ FFI.buildCondBr bldPtr (V.valueRef bit)- (V.valueRef true) (V.valueRef false)--unwrap :: (V.Value a, V.Value b) => (a, b) -> (FFI.ValueRef, FFI.ValueRef)-unwrap = V.valueRef *** V.valueRef--switch :: (T.Integer t, V.TypedValue v t)- => Builder -> v -> BasicBlock -> [(v, BasicBlock)]- -> IO (Instruction T.Void)-switch bld val noMatch cases =- withBuilder bld $ \bldPtr -> do- inst <- FFI.buildSwitch bldPtr (V.valueRef val)- (V.valueRef noMatch) (fromIntegral $ length cases)- forM_ (map unwrap cases) $ uncurry (FFI.addCase inst)- instruction $ return inst--invoke :: (T.DynamicType r, T.Params p, Params p v, T.FirstClass r)- => Builder -> String -> V.Function r p -> v- -> BasicBlock -> BasicBlock -> IO (Instruction r)-invoke bld name func args thenBlk catchBlk =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- withArrayLen (argList func args) $ \argLen argPtr ->- instruction $ FFI.buildInvoke bldPtr (V.valueRef func) argPtr- (fromIntegral argLen) (V.valueRef thenBlk)- (V.valueRef catchBlk) namePtr--unwind :: Builder -> IO (Instruction T.Void)-unwind bld = withBuilder bld $ instruction . FFI.buildUnwind--unreachable :: Builder -> IO (Instruction T.Void)-unreachable bld = withBuilder bld $ instruction . FFI.buildUnreachable--allocWith :: (T.Type t)- => (FFI.BuilderRef -> FFI.TypeRef -> CString -> IO FFI.ValueRef)- -> Builder -> String -> t -> IO FFI.ValueRef-allocWith ffi bld name typ =- withBuilder bld $ \bldPtr ->- withCString name $ ffi bldPtr (T.typeRef typ)--arrayAllocWith :: (T.Type t, T.Integer n, V.TypedValue v n)- => (FFI.BuilderRef -> FFI.TypeRef -> FFI.ValueRef -> CString- -> IO FFI.ValueRef)- -> Builder -> String -> t -> v -> IO FFI.ValueRef-arrayAllocWith ffi bld name typ count =- withBuilder bld $ \bldPtr ->- withCString name $ ffi bldPtr (T.typeRef typ) (V.valueRef count)--malloc :: (T.Type t) => Builder -> String -> t -> IO (Instruction (T.Array t))-malloc bld name typ = instruction $ allocWith FFI.buildMalloc bld name typ--arrayMalloc :: (T.Type t, V.TypedValue v T.Int32)- => Builder -> String -> t -> v -> IO (Instruction (T.Array t))-arrayMalloc bld name typ count =- instruction $ arrayAllocWith FFI.buildArrayMalloc bld name typ count--alloca :: (T.Type t)- => Builder -> String -> t -> IO (Instruction (T.Pointer t))-alloca bld name typ = instruction $ allocWith FFI.buildAlloca bld name typ--arrayAlloca :: (T.Type t, V.TypedValue v T.Int32)- => Builder -> String -> t -> v -> IO (Instruction (T.Pointer t))-arrayAlloca bld name typ count =- instruction $ arrayAllocWith FFI.buildArrayAlloca bld name typ count--free :: (V.TypedValue v (T.Pointer t))- => Builder -> v -> IO (Instruction T.Void)-free bld ary =- withBuilder bld $ \bldPtr ->- instruction $ FFI.buildFree bldPtr (V.valueRef ary)--load :: (V.TypedValue v (T.Pointer t))- => Builder -> String -> v -> IO (Instruction t)-load bld name ptr =- withBuilder bld $ \bldPtr ->- instruction $ withCString name $ FFI.buildLoad bldPtr (V.valueRef ptr)--store :: (V.TypedValue v t, V.TypedValue p (T.Pointer t))- => Builder -> v -> p -> IO (Instruction T.Void)-store bld val ptr =- withBuilder bld $ \bldPtr ->- instruction $ FFI.buildStore bldPtr (V.valueRef val) (V.valueRef ptr) --getElementPtr :: (T.Sequence s e, V.TypedValue p s,- T.Integer t, V.TypedValue i t)- => Builder -> String -> p -> [i]- -> IO (Instruction (T.Pointer e))-getElementPtr bld name ptr idxs =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- withArrayLen (map V.valueRef idxs) $ \idxLen idxPtr ->- instruction $ FFI.buildGEP bldPtr (V.valueRef ptr) idxPtr- (fromIntegral idxLen) namePtr--argList :: (Params p a, T.Params p, V.TypedValue v (T.Function r p))- => v -> a -> [FFI.ValueRef]-argList func = map V.valueRef . toAnyList (T.params (V.typeOf func))--callRef :: (T.DynamicType r, T.Params p, Params p v)- => Builder -> String -> V.Function r p -> v -> IO FFI.ValueRef-callRef bld name func args = do- withBuilder bld $ \bldPtr ->- withArrayLen (argList func args) $ \argLen argPtr ->- withCString name $ \namePtr ->- FFI.buildCall bldPtr (V.valueRef func) argPtr- (fromIntegral argLen) namePtr--class Params t v | t -> v where- toAnyList :: t -> v -> [V.AnyValue]--listValue :: (V.TypedValue v t) => t -> v -> [V.AnyValue]-listValue _ v = [V.anyValue v]--instance (V.TypedValue v a, Params b c) => Params (a :-> b) (v :-> c) where- toAnyList t (a :-> b) = V.anyValue a : toAnyList (T.cdr t) b--instance (V.TypedValue v T.Int32) => Params T.Int32 v where- toAnyList = listValue--instance (T.Type t, V.TypedValue v (T.Pointer t)) => Params (T.Pointer t) v where- toAnyList = listValue--call :: (T.DynamicType r, T.Params p, Params p v, T.FirstClass r)- => Builder -> String -> V.Function r p -> v- -> IO (Instruction r)-call bld name func args = instruction $ callRef bld name func args--call_ :: (T.DynamicType r, T.Params p, Params p v)- => Builder -> String -> V.Function r p -> v -> IO ()-call_ bld name func args = callRef bld name func args >> return ()--extractElement :: (V.TypedValue v (T.Vector t),- V.TypedValue i T.Int32)- => Builder -> String -> v -> i -> IO (Instruction t)-extractElement bld name vec idx =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- instruction $ FFI.buildExtractElement bldPtr (V.valueRef vec)- (V.valueRef idx) namePtr--insertElement :: (V.TypedValue v (T.Vector t),- V.TypedValue e t,- V.TypedValue i T.Int32)- => Builder -> String -> v -> e -> i -> IO (Instruction t)-insertElement bld name vec elt idx =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- instruction $ FFI.buildInsertElement bldPtr (V.valueRef vec)- (V.valueRef elt) (V.valueRef idx) namePtr--phi :: (V.TypedValue v t)- => Builder -> String -> t -> [(v, BasicBlock)] -> IO (Instruction t)-phi bld name typ incoming =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr -> do- inst <- FFI.buildPhi bldPtr (T.typeRef typ) namePtr- let (vals, bblks) = unzip . map unwrap $ incoming- withArrayLen vals $ \count valPtr ->- withArray bblks $ \bblkPtr ->- FFI.addIncoming inst valPtr bblkPtr (fromIntegral count)- instruction $ return inst--select :: (V.TypedValue p T.Int1, V.TypedValue a t, V.TypedValue b t)- => Builder -> String -> p -> a -> b -> IO (Instruction t)-select bld name bit true false =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr -> do- instruction $ FFI.buildSelect bldPtr (V.valueRef bit)- (V.valueRef true) (V.valueRef false) namePtr--vaArg :: (V.Value v, T.Type t)- => Builder -> String -> v -> t -> IO (Instruction t)-vaArg bld name valist typ =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- instruction $ FFI.buildVAArg bldPtr (V.valueRef valist)- (T.typeRef typ) namePtr--shuffleVector :: (V.TypedValue a (T.Vector t),- V.TypedValue b (T.Vector t),- V.TypedValue m (T.Vector T.Int32))- => Builder -> String -> a -> b -> m- -> IO (Instruction (T.Vector t))-shuffleVector bld name a b mask =- withBuilder bld $ \bldPtr ->- withCString name $ \namePtr ->- instruction $ FFI.buildShuffleVector bldPtr (V.valueRef a)- (V.valueRef b) (V.valueRef mask) namePtr
+ LLVM/Core/CodeGen.hs view
@@ -0,0 +1,322 @@+{-# LANGUAGE ScopedTypeVariables, MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, TypeSynonymInstances, UndecidableInstances, FlexibleContexts #-}+module LLVM.Core.CodeGen(+ -- * Module creation+ newModule, newNamedModule, defineModule, createModule,+ -- * Globals+ Linkage(..),+ -- * Function creation+ Function, newFunction, newNamedFunction, defineFunction, createFunction,+ FunctionArgs,+ TFunction,+ -- * Global variable creation+ Global, newGlobal, newNamedGlobal, defineGlobal, createGlobal, TGlobal,+ -- * Values+ Value(..), ConstValue(..),+ IsConst(..), valueOf, value,+ zero, allOnes, undef,+ createString, createStringNul,+ -- * Basic blocks+ BasicBlock(..), newBasicBlock, newNamedBasicBlock, defineBasicBlock, createBasicBlock, getCurrentBasicBlock,+ -- * Misc+ withCurrentBuilder+ ) where+import Control.Monad(liftM, when)+import Data.Int+import Data.Word+import Data.TypeNumbers+import LLVM.Core.CodeGenMonad+import qualified LLVM.FFI.Core as FFI+import qualified LLVM.Core.Util as U+import LLVM.Core.Type+import LLVM.Core.Data++--------------------------------------++-- | Create a new module.+newModule :: IO U.Module+newModule = newNamedModule "_module" -- XXX should generate a name++-- | Create a new explicitely named module.+newNamedModule :: String -- ^ module name+ -> IO U.Module+newNamedModule = U.createModule++-- | Give the body for a module.+defineModule :: U.Module -- ^ module that is defined+ -> CodeGenModule a -- ^ module body+ -> IO a+defineModule = runCodeGenModule++-- | Create a new module with the given body.+createModule :: CodeGenModule a -- ^ module body+ -> IO a+createModule cgm = newModule >>= \ m -> defineModule m cgm++--------------------------------------++newtype Value a = Value { unValue :: FFI.ValueRef }++newtype ConstValue a = ConstValue FFI.ValueRef++class (IsType a) => IsConst a where+ constOf :: a -> ConstValue a++instance IsConst Bool where constOf = constEnum (typeRef True)+--instance IsConst Char where constOf = constEnum (typeRef (0::Word8)) -- XXX Unicode+instance IsConst Word8 where constOf = constI False+instance IsConst Word16 where constOf = constI False+instance IsConst Word32 where constOf = constI False+instance IsConst Word64 where constOf = constI False+instance IsConst Int8 where constOf = constI True+instance IsConst Int16 where constOf = constI True+instance IsConst Int32 where constOf = constI True+instance IsConst Int64 where constOf = constI True+instance IsConst Float where constOf = constF+instance IsConst Double where constOf = constF+--instance IsConst FP128 where constOf = constF++{-+instance IsConst (Array n a) where+ constOf (Array xs) = + withArrayLen xs $ \ len ptr ->+ constArray (typeRef (undefined :: a)) ??? len+-}++constEnum :: (Enum a) => FFI.TypeRef -> a -> ConstValue a+constEnum t i = ConstValue $ FFI.constInt t (fromIntegral $ fromEnum i) 0++constI :: (IsType a, Integral a) => Bool -> a -> ConstValue a+constI signed i = ConstValue $ FFI.constInt (typeRef i) (fromIntegral i)+ (fromIntegral $ fromEnum signed)++constF :: (IsType a, Real a) => a -> ConstValue a+constF i = ConstValue $ FFI.constReal (typeRef i) (realToFrac i)++valueOf :: (IsConst a) => a -> Value a+valueOf = value . constOf++value :: ConstValue a -> Value a+value (ConstValue a) = Value a++-- Not unsafe, just generates a constant.+zero :: forall a . (IsType a) => ConstValue a+zero = ConstValue $ FFI.constNull $ typeRef (undefined :: a)++-- Not unsafe, just generates a constant.+allOnes :: forall a . (IsInteger a) => ConstValue a+allOnes = ConstValue $ FFI.constAllOnes $ typeRef (undefined :: a)++-- Not unsafe, just generates a constant.+undef :: forall a . (IsType a) => ConstValue a+undef = ConstValue $ FFI.getUndef $ typeRef (undefined :: a)++{-+createString :: String -> ConstValue (DynamicArray Word8)+createString = ConstValue . U.constString++constStringNul :: String -> ConstValue (DynamicArray Word8)+constStringNul = ConstValue . U.constStringNul+-}++--------------------------------------++type FunctionRef = FFI.ValueRef++-- |A function is simply a pointer to the function.+type Function a = Value (Ptr a)++-- | Create a new named function.+newNamedFunction :: forall a . (IsFunction a)+ => Linkage+ -> String -- ^ Function name+ -> CodeGenModule (Function a)+newNamedFunction linkage name = do+ modul <- getModule+ let typ = typeRef (undefined :: a)+ liftIO $ liftM Value $ U.addFunction modul (fromIntegral $ fromEnum linkage) name typ++-- | Create a new function. Use 'newNamedFunction' to create a function with external linkage, since+-- it needs a known name.+newFunction :: forall a . (IsFunction a)+ => Linkage+ -> CodeGenModule (Function a)+newFunction linkage = genMSym "fun" >>= newNamedFunction linkage++-- | Define a function body. The basic block returned by the function is the function entry point.+defineFunction :: forall f g r . (FunctionArgs f g (CodeGenFunction r ()))+ => Function f -- ^ Function to define (created by 'newFunction').+ -> g -- ^ Function body.+ -> CodeGenModule ()+defineFunction (Value fn) body = do+ bld <- liftIO $ U.createBuilder+ let body' = do+ l <- newBasicBlock+ defineBasicBlock l+ applyArgs fn body :: CodeGenFunction r ()+ runCodeGenFunction bld fn body'+ return ()++-- | Create a new function with the given body.+createFunction :: (IsFunction f, FunctionArgs f g (CodeGenFunction r ()))+ => Linkage+ -> g -- ^ Function body.+ -> CodeGenModule (Function f)+createFunction linkage body = do+ f <- newFunction linkage+ defineFunction f body+ return f++-- XXX This is ugly, it must be possible to make it simpler+-- Convert a function of type f = t1->t2->...-> IO r to+-- g = Value t1 -> Value t2 -> ... CodeGenFunction r ()+class FunctionArgs f g r | f -> g r, g r -> f where+ apArgs :: Int -> FunctionRef -> g -> r++applyArgs :: (FunctionArgs f g r) => FunctionRef -> g -> r+applyArgs = apArgs 0++instance (FunctionArgs b b' r) => FunctionArgs (a -> b) (Value a -> b') r where+ apArgs n f g = apArgs (n+1) f (g $ Value $ U.getParam f n)++-- XXX instances for all IsFirstClass functions,+-- because Haskell can't deal with the context and the FD+type FA a = CodeGenFunction a ()+instance FunctionArgs (IO Float) (FA Float) (FA Float) where apArgs _ _ g = g+instance FunctionArgs (IO Double) (FA Double) (FA Double) where apArgs _ _ g = g+instance FunctionArgs (IO FP128) (FA FP128) (FA FP128) where apArgs _ _ g = g+instance (IsTypeNumber n) => + FunctionArgs (IO (IntN n)) (FA (IntN n)) (FA (IntN n)) where apArgs _ _ g = g+instance (IsTypeNumber n) =>+ FunctionArgs (IO (WordN n)) (FA (WordN n)) (FA (WordN n)) where apArgs _ _ g = g+instance FunctionArgs (IO Bool) (FA Bool) (FA Bool) where apArgs _ _ g = g+instance FunctionArgs (IO Int8) (FA Int8) (FA Int8) where apArgs _ _ g = g+instance FunctionArgs (IO Int16) (FA Int16) (FA Int16) where apArgs _ _ g = g+instance FunctionArgs (IO Int32) (FA Int32) (FA Int32) where apArgs _ _ g = g+instance FunctionArgs (IO Int64) (FA Int64) (FA Int64) where apArgs _ _ g = g+instance FunctionArgs (IO Word8) (FA Word8) (FA Word8) where apArgs _ _ g = g+instance FunctionArgs (IO Word16) (FA Word16) (FA Word16) where apArgs _ _ g = g+instance FunctionArgs (IO Word32) (FA Word32) (FA Word32) where apArgs _ _ g = g+instance FunctionArgs (IO Word64) (FA Word64) (FA Word64) where apArgs _ _ g = g+instance FunctionArgs (IO ()) (FA ()) (FA ()) where apArgs _ _ g = g+instance (IsTypeNumber n, IsPrimitive a) =>+ FunctionArgs (IO (Vector n a)) (FA (Vector n a)) (FA (Vector n a)) where apArgs _ _ g = g+instance (IsType a) => + FunctionArgs (IO (Ptr a)) (FA (Ptr a)) (FA (Ptr a)) where apArgs _ _ g = g++--------------------------------------++-- |A basic block is a sequence of non-branching instructions, terminated by a control flow instruction.+newtype BasicBlock = BasicBlock FFI.BasicBlockRef++createBasicBlock :: CodeGenFunction r BasicBlock+createBasicBlock = do+ b <- newBasicBlock+ defineBasicBlock b+ return b++newBasicBlock :: CodeGenFunction r BasicBlock+newBasicBlock = genFSym >>= newNamedBasicBlock++newNamedBasicBlock :: String -> CodeGenFunction r BasicBlock+newNamedBasicBlock name = do+ fn <- getFunction+ liftIO $ liftM BasicBlock $ U.appendBasicBlock fn name++defineBasicBlock :: BasicBlock -> CodeGenFunction r ()+defineBasicBlock (BasicBlock l) = do+ bld <- getBuilder+ liftIO $ U.positionAtEnd bld l++getCurrentBasicBlock :: CodeGenFunction r BasicBlock+getCurrentBasicBlock = do+ bld <- getBuilder+ liftIO $ liftM BasicBlock $ U.getInsertBlock bld++--------------------------------------++withCurrentBuilder :: (FFI.BuilderRef -> IO a) -> CodeGenFunction r a+withCurrentBuilder body = do+ bld <- getBuilder+ liftIO $ U.withBuilder bld body++--------------------------------------++-- Mark all block terminating instructions. Not used yet.+--data Terminate = Terminate++--------------------------------------++type Global a = Value (Ptr a)++-- | Create a new named global variable.+newNamedGlobal :: forall a . (IsType a)+ => Bool -- ^Constant?+ -> Linkage -- ^Visibility+ -> String -- ^Name+ -> TGlobal a+newNamedGlobal isConst linkage name = do+ modul <- getModule+ let typ = typeRef (undefined :: a)+ liftIO $ liftM Value $ do g <- U.addGlobal modul (fromIntegral $ fromEnum linkage) name typ+ when isConst $ FFI.setGlobalConstant g 1+ return g++-- | Create a new global variable.+newGlobal :: forall a . (IsType a) => Bool -> Linkage -> TGlobal a+newGlobal isConst linkage = genMSym "glb" >>= newNamedGlobal isConst linkage++-- | Give a global variable a (constant) value.+defineGlobal :: Global a -> ConstValue a -> CodeGenModule ()+defineGlobal (Value g) (ConstValue v) =+ liftIO $ FFI.setInitializer g v++-- | Create and define a global variable.+createGlobal :: (IsType a) => Bool -> Linkage -> ConstValue a -> TGlobal a+createGlobal isConst linkage con = do+ g <- newGlobal isConst linkage+ defineGlobal g con+ return g++type TFunction a = CodeGenModule (Function a)+type TGlobal a = CodeGenModule (Global a)++-- Special string creators+createString :: String -> TGlobal (Array n Word8)+createString s = string (length s) (U.constString s)++createStringNul :: String -> TGlobal (Array n Word8)+createStringNul s = string (length s + 1) (U.constStringNul s)++string :: Int -> FFI.ValueRef -> TGlobal (Array n Word8)+string n s = do+ modul <- getModule+ name <- genMSym "str"+ let typ = FFI.arrayType (typeRef (undefined :: Word8)) (fromIntegral n)+ liftIO $ liftM Value $ do g <- U.addGlobal modul (fromIntegral $ fromEnum InternalLinkage) name typ+ FFI.setGlobalConstant g 1+ FFI.setInitializer g s+ return g++--------------------------------------++-- |An enumeration for the kinds of linkage for global values.+data Linkage+ = ExternalLinkage -- ^Externally visible function+ | LinkOnceLinkage -- ^Keep one copy of function when linking (inline)+ | WeakLinkage -- ^Keep one copy of named function when linking (weak)+ | AppendingLinkage -- ^Special purpose, only applies to global arrays+ | InternalLinkage -- ^Rename collisions when linking (static functions)+ | DLLImportLinkage -- ^Function to be imported from DLL+ | DLLExportLinkage -- ^Function to be accessible from DLL+ | ExternalWeakLinkage -- ^ExternalWeak linkage description+ | GhostLinkage -- ^Stand-in functions for streaming fns from BC files + deriving (Show, Eq, Ord, Enum)++{-+-- |An enumeration for the kinds of visibility of global values.+data VisibilityTypes+ = DefaultVisibility -- ^The GV is visible+ | HiddenVisibility -- ^The GV is hidden+ | ProtectedVisibility -- ^The GV is protected+ deriving (Show, Eq, Ord, Enum)+-}
+ LLVM/Core/CodeGenMonad.hs view
@@ -0,0 +1,66 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module LLVM.Core.CodeGenMonad(+ -- * Module code generation+ CodeGenModule, runCodeGenModule, genMSym, getModule,+ -- * Function code generation+ CodeGenFunction, runCodeGenFunction, genFSym, getFunction, getBuilder,+ -- * Reexport+ liftIO+ ) where+import Control.Monad.State++import LLVM.Core.Util(Module, Builder, Function)++--------------------------------------++data CGMState = CGMState {+ cgm_module :: Module,+ cgm_next :: !Int+ }+newtype CodeGenModule a = CGM (StateT CGMState IO a)+ deriving (Monad, MonadState CGMState, MonadIO)++genMSym :: String -> CodeGenModule String+genMSym prefix = do+ s <- get+ let n = cgm_next s+ put (s { cgm_next = n + 1 })+ return $ "_" ++ prefix ++ show n++getModule :: CodeGenModule Module+getModule = gets cgm_module++runCodeGenModule :: Module -> CodeGenModule a -> IO a+runCodeGenModule m (CGM body) = do+ let cgm = CGMState { cgm_module = m, cgm_next = 1 }+ evalStateT body cgm++--------------------------------------++data CGFState r = CGFState { + cgf_builder :: Builder,+ cgf_function :: Function,+ cgf_next :: !Int+ }+newtype CodeGenFunction r a = CGF (StateT (CGFState r) IO a)+ deriving (Monad, MonadState (CGFState r), MonadIO)++genFSym :: CodeGenFunction a String+genFSym = do+ s <- get+ let n = cgf_next s+ put (s { cgf_next = n + 1 })+ return $ "_L" ++ show n++getFunction :: CodeGenFunction a Function+getFunction = gets cgf_function++getBuilder :: CodeGenFunction a Builder+getBuilder = gets cgf_builder++runCodeGenFunction :: Builder -> Function -> CodeGenFunction r a -> CodeGenModule a+runCodeGenFunction bld fn (CGF body) = do+ let cgf = CGFState { cgf_builder = bld,+ cgf_function = fn,+ cgf_next = 1 }+ liftIO $ evalStateT body cgf
− LLVM/Core/Constant.hs
@@ -1,338 +0,0 @@-{-# LANGUAGE- DeriveDataTypeable- , FlexibleContexts- , FunctionalDependencies- , MultiParamTypeClasses- #-}--module LLVM.Core.Constant- (- -- * Constant expressions- ConstExpr(..)-- -- ** Arithmetic- , neg- , not- , add- , sub- , mul- , udiv- , sdiv- , fdiv- , urem- , srem- , frem- , and- , or- , xor- , shl- , lshr- , ashr-- -- ** Memory- , gep-- -- ** Conversions- , trunc- , sExt- , zExt- , fpTrunc- , fpExt- , uiToFP- , siToFP- , fpToUI- , fpToSI- , ptrToInt- , intToPtr- , bitCast-- -- ** Comparisons- , icmp- , fcmp-- -- ** Miscellaneous operations- , select- , extractElement- , insertElement- , shuffleVector-- -- * Constant values- , Const(..)-- -- ** Scalar constants- , constInt- , constWord- , constReal-- -- ** Composite constants- , constString- , constStringNul- ) where--import Data.Int (Int8, Int16, Int32, Int64)-import Data.Typeable (Typeable)-import Data.Word (Word8, Word16, Word32, Word64)-import Foreign.C.String (withCStringLen)-import Foreign.Marshal.Utils (fromBool)-import Prelude hiding (and, const, not, or)-import qualified Prelude as Prelude-import System.IO.Unsafe (unsafePerformIO)--import qualified LLVM.Core.FFI as FFI-import qualified LLVM.Core.Instruction as I-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V---newtype ConstExpr t = ConstExpr V.AnyValue- deriving (V.ConstValue, V.DynamicValue, Typeable, V.Value)--unary :: (V.ConstValue v) =>- (FFI.ValueRef -> FFI.ValueRef) -> v -> ConstExpr t-unary ffi = ConstExpr . V.mkAnyValue . ffi . V.valueRef--neg :: (V.ConstValue v, V.Arithmetic v, T.Arithmetic t) => v -> ConstExpr t-neg = unary FFI.constNeg--not :: (V.ConstValue v, T.Integer t, V.TypedValue v t) => v -> ConstExpr t-not = unary FFI.constNot--binary :: (V.ConstValue a, V.ConstValue b)- => (FFI.ValueRef -> FFI.ValueRef -> FFI.ValueRef) -> a -> b- -> ConstExpr t-binary ffi a b = ConstExpr . V.mkAnyValue $ ffi (V.valueRef a) (V.valueRef b)--add :: (T.Arithmetic t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-add = binary FFI.constAdd--sub :: (T.Arithmetic t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-sub = binary FFI.constSub--mul :: (T.Arithmetic t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-mul = binary FFI.constMul--udiv :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-udiv = binary FFI.constUDiv--sdiv :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-sdiv = binary FFI.constSDiv--fdiv :: (T.Real t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-fdiv = binary FFI.constFDiv--urem :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-urem = binary FFI.constURem--srem :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-srem = binary FFI.constURem--frem :: (T.Real t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-frem = binary FFI.constFRem--and :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-and = binary FFI.constAnd--or :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-or = binary FFI.constOr--xor :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-xor = binary FFI.constXor--icmp :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => I.IntPredicate -> a -> b -> ConstExpr T.Int1-icmp p = binary (FFI.constICmp (I.fromIP p))--fcmp :: (T.Real t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => I.RealPredicate -> a -> b -> ConstExpr T.Int1-fcmp p = binary (FFI.constFCmp (I.fromRP p))--shl :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-shl = binary FFI.constShl--lshr :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-lshr = binary FFI.constLShr--ashr :: (T.Integer t, V.ConstValue a, V.TypedValue a t,- V.ConstValue b, V.TypedValue b t)- => a -> b -> ConstExpr t-ashr = binary FFI.constAShr--gep :: (V.ConstValue v, T.Integer t, V.TypedValue v t)- => a -> b -> ConstExpr t-gep = undefined--typed :: (V.ConstValue v, T.Type s, V.ConstValue w, V.DynamicValue w)- => (FFI.ValueRef -> FFI.TypeRef -> FFI.ValueRef) -> v -> s -> w-typed ffi a b = V.fromAnyValue . V.mkAnyValue $ ffi (V.valueRef a) (T.typeRef b)--trunc :: (V.ConstValue v, T.Integer s, V.TypedValue v s,- V.ConstValue w, V.DynamicValue w, T.Integer t, V.TypedValue w t)- => v -> t -> w-trunc = typed FFI.constTrunc--sExt :: (V.ConstValue v, T.Integer t, V.TypedValue v t)- => v -> t -> ConstExpr t-sExt = typed FFI.constSExt--zExt :: (V.ConstValue v, T.Integer t, V.TypedValue v t)- => v -> t -> ConstExpr t-zExt = typed FFI.constZExt--fpTrunc :: (V.ConstValue v, V.Real v, T.Real t)- => v -> t -> ConstExpr t-fpTrunc = typed FFI.constFPTrunc--fpExt :: (V.ConstValue v, V.Real v, T.Real t)- => v -> t -> ConstExpr t-fpExt = typed FFI.constFPExt---- XXX How to express the inability to cast from scalar to vector?--uiToFP :: (V.ConstValue v, T.Integer s, V.TypedValue v s, T.Real t)- => v -> s -> ConstExpr t-uiToFP = typed FFI.constUIToFP--siToFP :: (V.ConstValue v, V.Integer v, T.Integer s, T.Real t)- => v -> s -> ConstExpr t-siToFP = typed FFI.constSIToFP--fpToUI :: (V.ConstValue v, V.Real v, T.Real s, T.Integer t)- => v -> s -> ConstExpr t-fpToUI = typed FFI.constFPToUI--fpToSI :: (V.ConstValue v, V.Real v, T.Real s, T.Integer t)- => v -> s -> ConstExpr t-fpToSI = typed FFI.constFPToSI--ptrToInt :: (V.ConstValue v, T.Integer t)- => v -> T.Pointer a -> ConstExpr t-ptrToInt = typed FFI.constPtrToInt--intToPtr :: (V.ConstValue v, T.Integer t)- => v -> t -> ConstExpr (T.Pointer a)-intToPtr = typed FFI.constIntToPtr---- XXX How to express pointer/non-pointer and bit-width constraints?-bitCast :: (V.ConstValue v, T.Type t,- V.ConstValue w, V.DynamicValue w)- => v -> t -> w-bitCast = typed FFI.constBitCast--select :: (V.TypedValue k T.Int1,- V.ConstValue a, V.TypedValue a t, V.ConstValue b, V.TypedValue b t)- => k -> a -> b -> ConstExpr t-select k = binary (FFI.constSelect (V.valueRef k))--extractElement :: (V.ConstValue v, V.TypedValue v (T.Vector a),- V.ConstValue i, V.Integer i) => v -> i -> ConstExpr a-extractElement = binary FFI.constExtractElement--ternary :: (V.ConstValue a, V.ConstValue b, V.ConstValue c)- => (FFI.ValueRef -> FFI.ValueRef -> FFI.ValueRef -> FFI.ValueRef)- -> a -> b -> c -> ConstExpr t-ternary ffi a b c = ConstExpr . V.mkAnyValue $- ffi (V.valueRef a) (V.valueRef b) (V.valueRef c)--insertElement :: (V.ConstValue v, V.TypedValue v (T.Vector a),- V.ConstValue e, V.TypedValue e a,- V.ConstValue i, V.Integer i)- => v -> e -> i -> ConstExpr (T.Vector a)-insertElement = ternary FFI.constInsertElement--shuffleVector :: (V.ConstValue v1, V.TypedValue v1 (T.Vector a),- V.ConstValue v2, V.TypedValue v2 (T.Vector a),- V.ConstValue m, V.TypedValue m (T.Vector T.Int32))- => v1 -> v2 -> m -> ConstExpr (T.Vector a)-shuffleVector = ternary FFI.constShuffleVector--constWord :: (T.Integer t, Integral a) => (b -> t) -> a -> V.ConstInt t-constWord typ val =- V.ConstInt . V.mkAnyValue $ FFI.constInt (T.typeRef (typ undefined))- (fromIntegral val) 0--constInt :: (T.Integer t, Integral a) => (b -> t) -> a -> V.ConstInt t-constInt typ val =- V.ConstInt . V.mkAnyValue $ FFI.constInt (T.typeRef (typ undefined))- (fromIntegral val) 1--constReal :: (T.Real t, RealFloat a) => (b -> t) -> a -> V.ConstReal t-constReal typ val = V.ConstReal . V.mkAnyValue $ FFI.constReal- (T.typeRef (typ undefined)) (realToFrac val)--constStringInternal :: Bool -> String -> V.ConstArray T.Int8-constStringInternal nulTerm s = unsafePerformIO $- withCStringLen s $ \(sPtr, sLen) ->- return . V.ConstArray . V.mkAnyValue $- FFI.constString sPtr (fromIntegral sLen) (fromBool (Prelude.not nulTerm))--constString :: String -> V.ConstArray T.Int8-constString = constStringInternal False--constStringNul :: String -> V.ConstArray T.Int8-constStringNul = constStringInternal True--class V.ConstValue t => Const a t | a -> t where- const :: a -> t--instance Const String (V.ConstArray T.Int8) where- const = constStringNul--instance Const Float (V.ConstReal T.Float) where- const = constReal T.float . fromRational . toRational--instance Const Double (V.ConstReal T.Double) where- const = constReal T.double--instance Const Int8 (V.ConstInt T.Int8) where- const = constInt T.int8 . fromIntegral--instance Const Int16 (V.ConstInt T.Int16) where- const = constInt T.int16 . fromIntegral--instance Const Int32 (V.ConstInt T.Int32) where- const = constInt T.int32 . fromIntegral--instance Const Int64 (V.ConstInt T.Int64) where- const = constInt T.int64--instance Const Word8 (V.ConstInt T.Int8) where- const = constWord T.int8 . fromIntegral--instance Const Word16 (V.ConstInt T.Int16) where- const = constWord T.int16 . fromIntegral--instance Const Word32 (V.ConstInt T.Int32) where- const = constWord T.int32 . fromIntegral--instance Const Word64 (V.ConstInt T.Int64) where- const = constWord T.int64 . fromIntegral
+ LLVM/Core/Data.hs view
@@ -0,0 +1,35 @@+module LLVM.Core.Data(IntN(..), WordN(..), FP128(..),+ Array(..), Vector(..), Ptr(..)) where+import Data.TypeNumbers++-- TODO:+-- Make instances IntN, WordN to actually do the right thing.+-- Make FP128 do the right thing+-- Make Array functions.++-- |Variable sized signed integer.+-- The /n/ parameter should belong to @IsTypeNumber@.+newtype (IsTypeNumber n) => IntN n = IntN Integer+ deriving (Show)++-- |Variable sized unsigned integer.+-- The /n/ parameter should belong to @IsTypeNumber@.+newtype (IsTypeNumber n) => WordN n = WordN Integer+ deriving (Show)++-- |128 bit floating point.+newtype FP128 = FP128 Rational+ deriving (Show)++-- |Fixed sized arrays, the array size is encoded in the /n/ parameter.+newtype (IsTypeNumber n) => Array n a = Array [a]+ deriving (Show)++-- XXX Power of 2 size constraint not enforced+-- |Fixed sized vector, the array size is encoded in the /n/ parameter.+newtype Vector n a = Vector (Array n a)+ deriving (Show)++-- |Pointer type.+newtype Ptr a = Ptr a+ deriving (Show)
− LLVM/Core/FFI.hsc
@@ -1,628 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-}--module LLVM.Core.FFI- (- -- * Modules- Module- , ModuleRef- , moduleCreateWithName- , disposeModule-- -- * Module providers- , ModuleProvider- , ModuleProviderRef- , createModuleProviderForExistingModule- , disposeModuleProvider-- -- * Types- , Type- , TypeRef- , addTypeName- , deleteTypeName- , getElementType-- -- ** Integer types- , int1Type- , int8Type- , int16Type- , int32Type- , int64Type- , integerType-- -- ** Real types- , floatType- , doubleType- , x86FP80Type- , fp128Type- , ppcFP128Type-- -- ** Function types- , functionType- , isFunctionVarArg- , getReturnType- , countParamTypes- , getParamTypes-- -- ** Other types- , voidType-- -- ** Array, pointer, and vector types- , arrayType- , pointerType- , vectorType-- -- * Values- , Value- , ValueRef- , addGlobal- , deleteGlobal- , setInitializer- , typeOf- , getValueName- , setValueName- , dumpValue-- -- ** Functions- , addFunction- , deleteFunction- , getNamedFunction- , countParams- , getParam- , getParams- - -- * Constants-- -- ** Scalar constants- , constInt- , constReal-- -- ** Composite constants- , constString-- -- ** Constant expressions- , constNeg- , constNot- , constAdd- , constSub- , constMul- , 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-- -- * Basic blocks- , BasicBlock- , BasicBlockRef- , appendBasicBlock- , insertBasicBlock- , deleteBasicBlock- , getEntryBasicBlock-- -- * Instruction building- , Builder- , BuilderRef- , createBuilder- , disposeBuilder- , positionBefore- , positionAtEnd-- -- ** Terminators- , buildRetVoid- , buildRet- , buildBr- , buildCondBr- , buildSwitch- , buildInvoke- , buildUnwind- , buildUnreachable-- -- ** Arithmetic- , buildAdd- , buildSub- , buildMul- , buildUDiv- , buildSDiv- , buildFDiv- , buildURem- , buildSRem- , buildFRem- , buildShl- , buildLShr- , buildAShr- , buildAnd- , buildOr- , buildXor- , buildNeg- , buildNot-- -- ** Memory- , buildMalloc- , buildArrayMalloc- , buildAlloca- , buildArrayAlloca- , buildFree- , buildLoad- , buildStore- , buildGEP-- -- ** Casts- , buildTrunc- , buildZExt- , buildSExt- , buildFPToUI- , buildFPToSI- , buildUIToFP- , buildSIToFP- , buildFPTrunc- , buildFPExt- , buildPtrToInt- , buildIntToPtr- , buildBitCast-- -- ** Comparisons- , buildICmp- , buildFCmp-- -- ** Miscellaneous instructions- , buildPhi- , buildCall- , buildSelect- , buildVAArg- , buildExtractElement- , buildInsertElement- , buildShuffleVector-- -- ** Other helpers- , addCase- , addIncoming- ) where--import Foreign.C.String (CString)-import Foreign.C.Types (CDouble, CInt, CUInt, CULLong)-import Foreign.Ptr (Ptr)--#include <llvm-c/Core.h>--data Module-type ModuleRef = Ptr Module--foreign import ccall unsafe "LLVMModuleCreateWithName" moduleCreateWithName- :: CString -> IO ModuleRef--foreign import ccall unsafe "LLVMDisposeModule" disposeModule- :: ModuleRef -> IO ()---data ModuleProvider-type ModuleProviderRef = Ptr ModuleProvider--foreign import ccall unsafe "LLVMCreateModuleProviderForExistingModule"- createModuleProviderForExistingModule- :: ModuleRef -> IO ModuleProviderRef--foreign import ccall unsafe "LLVMDisposeModuleProvider" disposeModuleProvider- :: ModuleProviderRef -> IO ()---data Type-type TypeRef = Ptr Type--foreign import ccall unsafe "LLVMInt1Type" int1Type :: TypeRef--foreign import ccall unsafe "LLVMInt8Type" int8Type :: TypeRef--foreign import ccall unsafe "LLVMInt16Type" int16Type :: TypeRef--foreign import ccall unsafe "LLVMInt32Type" int32Type :: TypeRef--foreign import ccall unsafe "LLVMInt64Type" int64Type :: TypeRef---- | An integer type of the given width.-foreign import ccall unsafe "LLVMIntType" integerType- :: CUInt -- ^ width in bits- -> TypeRef--foreign import ccall unsafe "LLVMFloatType" floatType :: TypeRef--foreign import ccall unsafe "LLVMDoubleType" doubleType :: TypeRef--foreign import ccall unsafe "LLVMX86FP80Type" x86FP80Type :: TypeRef--foreign import ccall unsafe "LLVMFP128Type" fp128Type :: TypeRef--foreign import ccall unsafe "LLVMPPCFP128Type" ppcFP128Type :: TypeRef--foreign import ccall unsafe "LLVMVoidType" voidType :: TypeRef---- | Create a function type.-foreign import ccall unsafe "LLVMFunctionType" functionType- :: TypeRef -- ^ return type- -> Ptr TypeRef -- ^ array of argument types- -> CUInt -- ^ number of elements in array- -> CInt -- ^ non-zero if function is varargs- -> TypeRef---- | Indicate whether a function takes varargs.-foreign import ccall unsafe "LLVMIsFunctionVarArg" isFunctionVarArg- :: TypeRef -> CInt---- | Give a function's return type.-foreign import ccall unsafe "LLVMGetReturnType" getReturnType- :: TypeRef -> TypeRef---- | Give the number of fixed parameters that a function takes.-foreign import ccall unsafe "LLVMCountParamTypes" countParamTypes- :: TypeRef -> CUInt---- | Fill out an array with the types of a function's fixed--- parameters.-foreign import ccall unsafe "LLVMGetParamTypes" getParamTypes- :: TypeRef -> Ptr TypeRef -> IO ()--foreign import ccall unsafe "LLVMArrayType" arrayType- :: TypeRef -- ^ element type- -> CUInt -- ^ element count- -> TypeRef--foreign import ccall unsafe "LLVMPointerType" pointerType- :: TypeRef -- ^ pointed-to type- -> CUInt -- ^ address space- -> TypeRef--foreign import ccall unsafe "LLVMVectorType" vectorType- :: TypeRef -- ^ element type- -> CUInt -- ^ element count- -> TypeRef--foreign import ccall unsafe "LLVMAddTypeName" addTypeName- :: ModuleRef -> CString -> TypeRef -> IO CInt--foreign import ccall unsafe "LLVMDeleteTypeName" deleteTypeName- :: ModuleRef -> CString -> IO ()---- | Give the type of a sequential type's elements.-foreign import ccall unsafe "LLVMGetElementType" getElementType- :: TypeRef -> TypeRef---data Value-type ValueRef = Ptr Value--foreign import ccall unsafe "LLVMAddGlobal" addGlobal- :: ModuleRef -> TypeRef -> CString -> IO ValueRef--foreign import ccall unsafe "LLVMDeleteGlobal" deleteGlobal- :: ValueRef -> IO ()--foreign import ccall unsafe "LLVMSetInitializer" setInitializer- :: ValueRef -> ValueRef -> IO ()--foreign import ccall unsafe "LLVMTypeOf" typeOf- :: ValueRef -> IO TypeRef--foreign import ccall unsafe "LLVMGetValueName" getValueName- :: ValueRef -> IO CString--foreign import ccall unsafe "LLVMSetValueName" setValueName- :: ValueRef -> CString -> IO ()--foreign import ccall unsafe "LLVMDumpValue" dumpValue- :: ValueRef -> IO ()--foreign import ccall unsafe "LLVMGetNamedFunction" getNamedFunction- :: ModuleRef -> CString -> IO ValueRef--foreign import ccall unsafe "LLVMAddFunction" addFunction- :: ModuleRef -> CString -> TypeRef -> IO ValueRef--foreign import ccall unsafe "LLVMDeleteFunction" deleteFunction- :: ValueRef -> IO ()--foreign import ccall unsafe "LLVMCountParams" countParams- :: ValueRef -> CUInt--foreign import ccall unsafe "LLVMGetParam" getParam- :: ValueRef -> CUInt -> ValueRef--foreign import ccall unsafe "LLVMGetParams" getParams- :: ValueRef -> Ptr ValueRef -> IO ()--foreign import ccall unsafe "LLVMConstInt" constInt- :: TypeRef -> CULLong -> CInt -> ValueRef--foreign import ccall unsafe "LLVMConstReal" constReal- :: TypeRef -> CDouble -> ValueRef--foreign import ccall unsafe "LLVMConstString" constString- :: CString -> CUInt -> CInt -> ValueRef--foreign import ccall unsafe "LLVMConstNeg" constNeg- :: ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstNot" constNot- :: ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstAdd" constAdd- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstSub" constSub- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstMul" constMul- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstUDiv" constUDiv- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstSDiv" constSDiv- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstFDiv" constFDiv- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstURem" constURem- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstSRem" constSRem- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstFRem" constFRem- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstAnd" constAnd- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstOr" constOr- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstXor" constXor- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstICmp" constICmp- :: CInt -> ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstFCmp" constFCmp- :: CInt -> ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstShl" constShl- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstLShr" constLShr- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstAShr" constAShr- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstGEP" constGEP- :: ValueRef -> Ptr ValueRef -> CUInt -> ValueRef--foreign import ccall unsafe "LLVMConstTrunc" constTrunc- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstSExt" constSExt- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstZExt" constZExt- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstFPTrunc" constFPTrunc- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstFPExt" constFPExt- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstUIToFP" constUIToFP- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstSIToFP" constSIToFP- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstFPToUI" constFPToUI- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstFPToSI" constFPToSI- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstPtrToInt" constPtrToInt- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstIntToPtr" constIntToPtr- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstBitCast" constBitCast- :: ValueRef -> TypeRef -> ValueRef--foreign import ccall unsafe "LLVMConstSelect" constSelect- :: ValueRef -> ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstExtractElement" constExtractElement- :: ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstInsertElement" constInsertElement- :: ValueRef -> ValueRef -> ValueRef -> ValueRef--foreign import ccall unsafe "LLVMConstShuffleVector" constShuffleVector- :: ValueRef -> ValueRef -> ValueRef -> ValueRef--type BasicBlock = Value-type BasicBlockRef = Ptr BasicBlock--foreign import ccall unsafe "LLVMAppendBasicBlock" appendBasicBlock- :: ValueRef -> CString -> IO BasicBlockRef--foreign import ccall unsafe "LLVMInsertBasicBlock" insertBasicBlock- :: BasicBlockRef -> CString -> IO BasicBlockRef--foreign import ccall unsafe "LLVMDeleteBasicBlock" deleteBasicBlock- :: BasicBlockRef -> IO ()--foreign import ccall unsafe "LLVMGetEntryBasicBlock" getEntryBasicBlock- :: ValueRef -> IO BasicBlockRef--data Builder-type BuilderRef = Ptr Builder--foreign import ccall unsafe "LLVMCreateBuilder" createBuilder- :: IO BuilderRef--foreign import ccall unsafe "LLVMDisposeBuilder" disposeBuilder- :: BuilderRef -> IO ()--foreign import ccall unsafe "LLVMPositionBuilderBefore" positionBefore- :: BuilderRef -> ValueRef -> IO ()--foreign import ccall unsafe "LLVMPositionBuilderAtEnd" positionAtEnd- :: BuilderRef -> BasicBlockRef -> IO ()--foreign import ccall unsafe "LLVMBuildRetVoid" buildRetVoid- :: BuilderRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildRet" buildRet- :: BuilderRef -> ValueRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildBr" buildBr- :: BuilderRef -> BasicBlockRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildCondBr" buildCondBr- :: BuilderRef -> ValueRef -> BasicBlockRef -> BasicBlockRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSwitch" buildSwitch- :: BuilderRef -> ValueRef -> BasicBlockRef -> CUInt -> IO ValueRef-foreign import ccall unsafe "LLVMBuildInvoke" buildInvoke- :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt- -> BasicBlockRef -> BasicBlockRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildUnwind" buildUnwind- :: BuilderRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildUnreachable" buildUnreachable- :: BuilderRef -> IO ValueRef--foreign import ccall unsafe "LLVMBuildAdd" buildAdd- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSub" buildSub- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildMul" buildMul- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildUDiv" buildUDiv- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSDiv" buildSDiv- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFDiv" buildFDiv- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildURem" buildURem- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSRem" buildSRem- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFRem" buildFRem- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildShl" buildShl- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildLShr" buildLShr- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildAShr" buildAShr- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildAnd" buildAnd- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildOr" buildOr- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildXor" buildXor- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildNeg" buildNeg- :: BuilderRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildNot" buildNot- :: BuilderRef -> ValueRef -> CString -> IO ValueRef---- Memory-foreign import ccall unsafe "LLVMBuildMalloc" buildMalloc- :: BuilderRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildArrayMalloc" buildArrayMalloc- :: BuilderRef -> TypeRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildAlloca" buildAlloca- :: BuilderRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildArrayAlloca" buildArrayAlloca- :: BuilderRef -> TypeRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFree" buildFree- :: BuilderRef -> ValueRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildLoad" buildLoad- :: BuilderRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildStore" buildStore- :: BuilderRef -> ValueRef -> ValueRef -> IO ValueRef-foreign import ccall unsafe "LLVMBuildGEP" buildGEP- :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt -> CString- -> IO ValueRef---- Casts-foreign import ccall unsafe "LLVMBuildTrunc" buildTrunc- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildZExt" buildZExt- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSExt" buildSExt- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFPToUI" buildFPToUI- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFPToSI" buildFPToSI- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildUIToFP" buildUIToFP- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSIToFP" buildSIToFP- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFPTrunc" buildFPTrunc- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFPExt" buildFPExt- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildPtrToInt" buildPtrToInt- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildIntToPtr" buildIntToPtr- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildBitCast" buildBitCast- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef---- Comparisons-foreign import ccall unsafe "LLVMBuildICmp" buildICmp- :: BuilderRef -> CInt -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildFCmp" buildFCmp- :: BuilderRef -> CInt -> ValueRef -> ValueRef -> CString -> IO ValueRef---- Miscellaneous instructions-foreign import ccall unsafe "LLVMBuildPhi" buildPhi- :: BuilderRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildCall" buildCall- :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildSelect" buildSelect- :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildVAArg" buildVAArg- :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildExtractElement" buildExtractElement- :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildInsertElement" buildInsertElement- :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef-foreign import ccall unsafe "LLVMBuildShuffleVector" buildShuffleVector- :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef--foreign import ccall unsafe "LLVMAddCase" addCase- :: ValueRef -> ValueRef -> BasicBlockRef -> IO ()--foreign import ccall unsafe "LLVMAddIncoming" addIncoming- :: ValueRef -> Ptr ValueRef -> Ptr ValueRef -> CUInt -> IO ()
− LLVM/Core/Instruction.hs
@@ -1,47 +0,0 @@-module LLVM.Core.Instruction- (- IntPredicate(..)- , RealPredicate(..)- , fromIP- , fromRP- ) where--import Foreign.C.Types (CInt)--data IntPredicate =- IntEQ -- ^ equal- | IntNE -- ^ not equal- | IntUGT -- ^ unsigned greater than- | IntUGE -- ^ unsigned greater or equal- | IntULT -- ^ unsigned less than- | IntULE -- ^ unsigned less or equal- | IntSGT -- ^ signed greater than- | IntSGE -- ^ signed greater or equal- | IntSLT -- ^ signed less than- | IntSLE -- ^ signed less or equal- deriving (Eq, Ord, Enum, Show)--fromIP :: IntPredicate -> CInt-fromIP ip = fromIntegral (fromEnum ip + 32)--data RealPredicate =- RealFalse -- ^ Always false (always folded)- | RealOEQ -- ^ True if ordered and equal- | RealOGT -- ^ True if ordered and greater than- | RealOGE -- ^ True if ordered and greater than or equal- | RealOLT -- ^ True if ordered and less than- | RealOLE -- ^ True if ordered and less than or equal- | RealONE -- ^ True if ordered and operands are unequal- | RealORD -- ^ True if ordered (no nans)- | RealUNO -- ^ True if unordered: isnan(X) | isnan(Y)- | RealUEQ -- ^ True if unordered or equal- | RealUGT -- ^ True if unordered or greater than- | RealUGE -- ^ True if unordered, greater than, or equal- | RealULT -- ^ True if unordered or less than- | RealULE -- ^ True if unordered, less than, or equal- | RealUNE -- ^ True if unordered or not equal- | RealT -- ^ Always true (always folded)- deriving (Eq, Ord, Enum, Show)--fromRP :: RealPredicate -> CInt-fromRP = fromIntegral . fromEnum
+ LLVM/Core/Instructions.hs view
@@ -0,0 +1,601 @@+{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances, TypeSynonymInstances, ScopedTypeVariables, OverlappingInstances, FlexibleContexts #-}+module LLVM.Core.Instructions(+ -- * Terminator instructions+ ret,+ condBr,+ br,+ switch,+ invoke,+ unwind,+ unreachable,+ -- * Arithmetic binary operations+ -- | Arithmetic operations with the normal semantics.+ -- The u instractions are unsigned, the s instructions are signed.+ add, sub, mul,+ udiv, sdiv, fdiv, urem, srem, frem,+ -- * Logical binary operations+ -- |Logical instructions with the normal semantics.+ shl, lshr, ashr, and, or, xor,+ -- * Vector operations+ extractelement,+ insertelement,+ shufflevector,+ -- * Memory access+ malloc, arrayMalloc,+ alloca, arrayAlloca,+ free,+ load,+ store,+ getElementPtr,+ -- * Conversions+ trunc, zext, sext,+ fptrunc, fpext,+ fptoui, fptosi,+ uitofp, sitofp,+ ptrtoint, inttoptr,+ bitcast,+ -- * Comparison+ IntPredicate(..), RealPredicate(..),+ icmp, fcmp,+ select,+ -- * Other+ phi, addPhiInputs,+ call,+ -- * Classes and types+ Terminate,+ Ret, CallArgs, ABinOp, CmpOp, FunctionArgs, IsConst,+ AllocArg,+ GetElementPtr, IsIndexArg+ ) where+import Prelude hiding (and, or)+import Control.Monad(liftM)+import Data.Int+import Data.Word+--import Data.TypeNumbers+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++-- TODO:+-- Add vector version of arithmetic+-- Add rest of instructions+-- Use Terminate to ensure bb termination (how?)+-- more intrinsics are needed to, e.g., create an empty vector++type Terminate = ()+terminate :: Terminate+terminate = ()++--------------------------------------++-- |Acceptable arguments to the 'ret' instruction.+class Ret a r where+ ret' :: a -> CodeGenFunction r Terminate++-- | Return from the current function with the given value. Use () as the return value for what would be a void function is C.+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++--------------------------------------++-- | Branch to the first basic block if the boolean is true, otherwise to the second basic block.+condBr :: Value Bool -- ^ Boolean to branch upon.+ -> BasicBlock -- ^ Target for true.+ -> BasicBlock -- ^ Target for false.+ -> CodeGenFunction r Terminate+condBr (Value b) (BasicBlock t1) (BasicBlock t2) = do+ withCurrentBuilder $ \ bldPtr -> FFI.buildCondBr bldPtr b t1 t2+ return terminate++--------------------------------------++-- | Unconditionally branch to the given basic block.+br :: BasicBlock -- ^ Branch target.+ -> CodeGenFunction r Terminate+br (BasicBlock t) = do+ withCurrentBuilder $ \ bldPtr -> FFI.buildBr bldPtr t+ return terminate++--------------------------------------++-- | Branch table instruction.+switch :: (IsInteger a)+ => Value a -- ^ Value to branch upon.+ -> BasicBlock -- ^ Default branch target.+ -> [(ConstValue a, BasicBlock)] -- ^ Labels and corresponding branch targets.+ -> 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 the call stack until a function call performed with 'invoke' is reached.+-- I.e., throw a non-local exception.+unwind :: CodeGenFunction r Terminate+unwind = do+ withCurrentBuilder FFI.buildUnwind+ return terminate++-- |Inform the code generator that this code can never be reached.+unreachable :: CodeGenFunction r Terminate+unreachable = do+ withCurrentBuilder FFI.buildUnreachable+ return terminate++--------------------------------------++-- XXX Vector ops not implemented++type FFIBinOp = FFI.BuilderRef -> FFI.ValueRef -> FFI.ValueRef -> U.CString -> IO FFI.ValueRef+type FFIConstBinOp = FFI.ValueRef -> FFI.ValueRef -> FFI.ValueRef++-- |Acceptable arguments to arithmetic binary instructions.+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 = abinop FFI.constAdd FFI.buildAdd+sub :: (IsArithmetic c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)+sub = abinop FFI.constSub FFI.buildSub+mul :: (IsArithmetic c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)+mul = abinop FFI.constMul FFI.buildMul++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++-- | Floating point division.+fdiv :: (IsFloating c, ABinOp a b (v c)) => a -> b -> CodeGenFunction r (v c)+fdiv = abinop FFI.constFDiv FFI.buildFDiv+-- | Floating point remainder.+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++--instance (IsConst a) => ABinOp a a (ConstValue a) where+-- abinop cop op a1 a2 = abinop cop op (constOf a1) (constOf 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++--------------------------------------++-- | Get a value from a vector.+extractelement :: Value (Vector n a) -- ^ Vector+ -> Value Word32 -- ^ Index into the vector+ -> CodeGenFunction r (Value a)+extractelement (Value vec) (Value i) =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $ FFI.buildExtractElement bldPtr vec i++-- | Insert a value into a vector, nondescructive.+insertelement :: Value (Vector n a) -- ^ Vector+ -> Value a -- ^ Value to insert+ -> Value Word32 -- ^ Index into the vector+ -> 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++-- | Permute vector.+shufflevector :: Value (Vector n a)+ -> Value (Vector n a)+ -> ConstValue (Vector n Word32)+ -> CodeGenFunction r (Value (Vector n a))+shufflevector (Value a) (Value b) (ConstValue mask) =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $ FFI.buildShuffleVector bldPtr a b mask+++--------------------------------------++-- XXX should allows constants++-- XXX size a > size b not enforced+-- | Truncate a value to a shorter bit width.+trunc :: (IsInteger a, IsInteger b) => Value a -> CodeGenFunction r (Value b)+trunc = convert FFI.buildTrunc++-- XXX size a < size b not enforced+-- | Zero extend a value to a wider width.+zext :: (IsInteger a, IsInteger b) => Value a -> CodeGenFunction r (Value b)+zext = convert FFI.buildZExt++-- XXX size a < size b not enforced+-- | Sign extend a value to wider width.+sext :: (IsInteger a, IsInteger b) => Value a -> CodeGenFunction r (Value b)+sext = convert FFI.buildSExt++-- XXX size a > size b not enforced+-- | Truncate a floating point value.+fptrunc :: (IsFloating a, IsFloating b) => Value a -> CodeGenFunction r (Value b)+fptrunc = convert FFI.buildFPTrunc++-- XXX size a < size b not enforced+-- | Extend a floating point value.+fpext :: (IsFloating a, IsFloating b) => Value a -> CodeGenFunction r (Value b)+fpext = convert FFI.buildFPExt++-- | Convert a floating point value to an unsigned integer.+fptoui :: (IsFloating a, IsInteger b) => Value a -> CodeGenFunction r (Value b)+fptoui = convert FFI.buildFPToUI++-- | Convert a floating point value to a signed integer.+fptosi :: (IsFloating a, IsInteger b) => Value a -> CodeGenFunction r (Value b)+fptosi = convert FFI.buildFPToSI++-- | Convert an unsigned integer to a floating point value.+uitofp :: (IsInteger a, IsFloating b) => Value a -> CodeGenFunction r (Value b)+uitofp = convert FFI.buildUIToFP++-- | Convert a signed integer to a floating point value.+sitofp :: (IsInteger a, IsFloating b) => Value a -> CodeGenFunction r (Value b)+sitofp = convert FFI.buildSIToFP++-- | Convert a pointer to an integer.+ptrtoint :: (IsInteger b) => Value (Ptr a) -> CodeGenFunction r (Value b)+ptrtoint = convert FFI.buildPtrToInt++-- | Convert an integer to a pointer.+inttoptr :: (IsInteger a, IsType b) => Value (Ptr a) -> CodeGenFunction r (Value (Ptr b))+inttoptr = convert FFI.buildIntToPtr++-- XXX a and b must use the same space, and there are also pointer restrictions+-- | Convert between to values of the same size by just copying the bit pattern.+bitcast :: (IsFirstClass a, IsFirstClass b) => Value a -> CodeGenFunction r (Value b)+bitcast = 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 IntPredicate =+ IntEQ -- ^ equal+ | IntNE -- ^ not equal+ | IntUGT -- ^ unsigned greater than+ | IntUGE -- ^ unsigned greater or equal+ | IntULT -- ^ unsigned less than+ | IntULE -- ^ unsigned less or equal+ | IntSGT -- ^ signed greater than+ | IntSGE -- ^ signed greater or equal+ | IntSLT -- ^ signed less than+ | IntSLE -- ^ signed less or equal+ deriving (Eq, Ord, Enum, Show)++data RealPredicate =+ RealFalse -- ^ Always false (always folded)+ | RealOEQ -- ^ True if ordered and equal+ | RealOGT -- ^ True if ordered and greater than+ | RealOGE -- ^ True if ordered and greater than or equal+ | RealOLT -- ^ True if ordered and less than+ | RealOLE -- ^ True if ordered and less than or equal+ | RealONE -- ^ True if ordered and operands are unequal+ | RealORD -- ^ True if ordered (no nans)+ | RealUNO -- ^ True if unordered: isnan(X) | isnan(Y)+ | RealUEQ -- ^ True if unordered or equal+ | RealUGT -- ^ True if unordered or greater than+ | RealUGE -- ^ True if unordered, greater than, or equal+ | RealULT -- ^ True if unordered or less than+ | RealULE -- ^ True if unordered, less than, or equal+ | RealUNE -- ^ True if unordered or not equal+ | RealT -- ^ Always true (always folded)+ deriving (Eq, Ord, Enum, Show)++-- |Acceptable operands to comparison instructions.+class CmpOp a b c | a b -> c where+ cmpop :: FFIBinOp -> a -> b -> CodeGenFunction r (Value Bool)++instance CmpOp (Value a) (Value a) a where+ cmpop op (Value a1) (Value a2) = buildBinOp op a1 a2++instance (IsConst a) => CmpOp a (Value a) a where+ cmpop op a1 a2 = cmpop op (valueOf a1) a2++instance (IsConst a) => CmpOp (Value a) a a where+ cmpop op a1 a2 = cmpop op a1 (valueOf a2)++-- | Compare integers.+icmp :: (IsInteger c, CmpOp a b c) =>+ IntPredicate -> a -> b -> CodeGenFunction r (Value Bool)+icmp p = cmpop (flip FFI.buildICmp (fromIntegral (fromEnum p + 32)))++-- | Compare floating point values.+fcmp :: (IsFloating c, CmpOp a b c) =>+ RealPredicate -> a -> b -> CodeGenFunction r (Value Bool)+fcmp p = cmpop (flip FFI.buildFCmp (fromIntegral (fromEnum p)))++--------------------------------------++-- XXX could do const song and dance+-- | Select between two values depending on a boolean.+select :: (IsFirstClass a) => Value Bool -> 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++-- |Acceptable arguments to 'call'.+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 b b') => CallArgs (a -> b) (ConstValue a -> b') where+-- doCall mkCall args f (ConstValue 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 a function with the given arguments. The 'call' instruction is variadic, i.e., the number of arguments+-- it takes depends on the type of /f/.+call :: (CallArgs f g) => Function f -> g+call (Value f) = doCall (U.makeCall f) [] (undefined :: f)++-- | Call a function with exception handling.+invoke :: (CallArgs f g)+ => BasicBlock -- ^Normal return point.+ -> BasicBlock -- ^Exception return point.+ -> Function f -- ^Function to call.+ -> g+invoke (BasicBlock norm) (BasicBlock expt) (Value f) =+ doCall (U.makeInvoke norm expt f) [] (undefined :: f)++--------------------------------------++-- XXX could do const song and dance+-- |Join several variables (virtual registers) from different basic blocks into one.+-- All of the variables in the list are joined. See also 'addPhiInputs'.+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++-- |Add additional inputs to an existing phi node.+-- The reason for this instruction is that sometimes the structure of the code+-- makes it impossible to have all variables in scope at the point where you need the phi node.+addPhiInputs :: forall a r . (IsFirstClass a)+ => Value a -- ^Must be a variable from a call to 'phi'.+ -> [(Value a, BasicBlock)] -- ^Variables to add.+ -> CodeGenFunction r ()+addPhiInputs (Value inst) incoming =+ liftIO $ U.addPhiIns inst [ (v, b) | (Value v, BasicBlock b) <- incoming ]+ ++--------------------------------------++-- | Acceptable argument to array memory allocation.+class AllocArg a where+ getAllocArg :: a -> FFI.ValueRef+instance AllocArg (Value Word32) where+ getAllocArg (Value v) = v+instance AllocArg (ConstValue Word32) where+ getAllocArg = unConst+instance AllocArg Word32 where+ getAllocArg = unConst . constOf++-- XXX What's the type returned by malloc+-- | Allocate heap memory.+malloc :: forall a r . (IsSized a) => CodeGenFunction r (Value (Ptr a))+malloc =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $ FFI.buildMalloc bldPtr (typeRef (undefined :: a))++-- XXX What's the type returned by arrayMalloc?+-- | Allocate heap (array) memory.+arrayMalloc :: forall a r s . (IsSized a, AllocArg s) =>+ s -> CodeGenFunction r (Value (Ptr a)) -- XXX+arrayMalloc s =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $+ FFI.buildArrayMalloc bldPtr (typeRef (undefined :: a)) (getAllocArg s)++-- XXX What's the type returned by malloc+-- | Allocate stack memory.+alloca :: forall a r . (IsSized a) => CodeGenFunction r (Value (Ptr a))+alloca =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $ FFI.buildAlloca bldPtr (typeRef (undefined :: a))++-- XXX What's the type returned by arrayAlloca?+-- | Allocate stack (array) memory.+arrayAlloca :: forall a r s . (IsSized a, AllocArg s) =>+ s -> CodeGenFunction r (Value (Ptr a))+arrayAlloca s =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $+ FFI.buildArrayAlloca bldPtr (typeRef (undefined :: a)) (getAllocArg s)++-- XXX What's the type of free?+-- | Free heap memory.+free :: Value (Ptr a) -> CodeGenFunction r (Value ())+free (Value a) =+ liftM Value $+ withCurrentBuilder $ \ bldPtr -> FFI.buildFree bldPtr a++-- | Load a value from memory.+load :: Value (Ptr a) -- ^ Address to load from.+ -> CodeGenFunction r (Value a)+load (Value p) =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withEmptyCString $ FFI.buildLoad bldPtr p++-- | Store a value in memory+store :: Value a -- ^ Value to store.+ -> Value (Ptr a) -- ^ Address to store to.+ -> CodeGenFunction r (Value ())+store (Value v) (Value p) =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ FFI.buildStore bldPtr v p++{-+-- XXX type is wrong+-- | Address arithmetic. See LLVM description.+-- (The type isn't as accurate as it should be.)+getElementPtr :: (IsInteger i) =>+ Value (Ptr a) -> [Value i] -> CodeGenFunction r (Value (Ptr b))+getElementPtr (Value ptr) ixs =+ liftM Value $+ withCurrentBuilder $ \ bldPtr ->+ U.withArrayLen [ v | Value v <- ixs ] $ \ idxLen idxPtr ->+ U.withEmptyCString $+ FFI.buildGEP bldPtr ptr idxPtr (fromIntegral idxLen)+-}++-- |Acceptable arguments to 'getElementPointer'.+class GetElementPtr optr ixs nptr | optr ixs -> nptr {-, ixs nptr -> optr, nptr optr -> ixs-} where+ getIxList :: optr -> ixs -> [FFI.ValueRef]++-- |Acceptable single index to 'getElementPointer'.+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++-- End of indexing+instance GetElementPtr a () a where+ getIxList _ () = []++-- Index in Array+instance (GetElementPtr o i n, IsIndexArg a) => GetElementPtr (Array k o) (a, i) n where+ getIxList ~(Array (a:_)) (v, i) = getArg v : getIxList a i++-- Index in Vector+instance (GetElementPtr o i n, IsIndexArg a) => GetElementPtr (Vector k o) (a, i) n where+ getIxList ~(Vector (Array (a:_))) (v, i) = getArg v : getIxList a i++-- | Address arithmetic. See LLVM description.+-- The index is a nested tuple of the form @(i1,(i2,( ... ())))@.+-- (This is without a doubt the most confusing LLVM instruction, but the types help.)+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)
LLVM/Core/Type.hs view
@@ -1,547 +1,212 @@-{-# LANGUAGE- DeriveDataTypeable- , ExistentialQuantification- , FunctionalDependencies- , MultiParamTypeClasses- #-}--module LLVM.Core.Type- (- Module(..)- , withModule- , ModuleProvider(..)- , withModuleProvider-- -- * Types- , Type(..)- , TypeValue(..)- , AnyType- , HasAnyType(..)- , DynamicType(..)- , mkAnyType-- -- ** Integer types- , Arithmetic- , FirstClass- , Integer- , integer- , Int1(..)- , int1- , Int8(..)- , int8- , Int16(..)- , int16- , Int32(..)- , int32- , Int64(..)- , int64- , IntWidth(..)-- -- ** Real types- , Real- , Float(..)- , float- , Double(..)- , double-- -- *** Machine-specific real types- , X86Float80(..)- , x86Float80- , Float128(..)- , float128- , PPCFloat128(..)- , ppcFloat128-- -- ** Array, pointer, and vector types- , Sequence(..)- , elementTypeDyn- , Array(..)- , array- , arrayElementType- , Pointer(..)- , AddressSpace- , addressSpace- , fromAddressSpace- , genericAddressSpace- , pointerIn- , pointer- , pointerElementType- , Vector(..)- , vector- , vectorElementType-- -- ** Function-related types- , Function(..)- , function- , params- , functionVarArg- , isFunctionVarArg- , getReturnType- , getParamTypes-- -- *** Type hackery- , functionParams- , Params(..)- , (:->)(..)- , car- , cdr-- -- ** Other types- , Void(..)+{-# LANGUAGE ScopedTypeVariables, EmptyDataDecls, FlexibleInstances, IncoherentInstances #-}+-- |The LLVM type system is captured with a number of Haskell type classes.+-- In general, an LLVM type @T@ is represented as @Value T@, where @T@ is some Haskell type.+-- The various types @T@ are classified by various type classes, e.g., 'IsFirstClass' for+-- those types that are LLVM first class types (passable as arguments etc).+-- All valid LLVM types belong to the 'IsType' class.+module LLVM.Core.Type(+ -- * Type classifier+ IsType(..),+ -- ** Special type classifiers+ IsArithmetic,+ IsInteger,+ IsFloating,+ IsPrimitive,+ IsFirstClass,+ IsSized,+ IsFunction,+-- IsFunctionRet,+ IsSequence ) where--import Control.Applicative ((<$>))-import Data.Typeable (Typeable)-import Foreign.ForeignPtr (ForeignPtr, withForeignPtr)-import Foreign.Marshal.Array (allocaArray, peekArray, withArrayLen)-import Foreign.Marshal.Utils (fromBool, toBool)-import Prelude hiding (Double, Float, Integer, Real, mod)-import System.IO.Unsafe (unsafePerformIO)--import qualified LLVM.Core.FFI as FFI--import Debug.Trace---newtype Module = Module {- fromModule :: ForeignPtr FFI.Module- }- deriving (Typeable)--withModule :: Module -> (FFI.ModuleRef -> IO a) -> IO a-withModule mod = withForeignPtr (fromModule mod)--newtype ModuleProvider = ModuleProvider {- fromModuleProvider :: ForeignPtr FFI.ModuleProvider- }- deriving (Typeable)--withModuleProvider :: ModuleProvider -> (FFI.ModuleProviderRef -> IO a)- -> IO a-withModuleProvider prov = withForeignPtr (fromModuleProvider prov)--class Type a where- typeRef :: a -> FFI.TypeRef- anyType :: a -> AnyType--class Type t => TypeValue t where- typeValue :: a -> t--class Type a => Arithmetic a-class Arithmetic a => Integer a-class Arithmetic a => Real a--class FirstClass a-instance FirstClass AnyType--class HasAnyType a where- fromAnyType :: AnyType -> a--instance Type FFI.TypeRef where- anyType = AnyType- typeRef = id--data AnyType = forall a. Type a => AnyType a- deriving (Typeable)--instance Eq AnyType where- a == b = typeRef a == typeRef b--instance Show AnyType where- show a = "AnyType " ++ show (typeRef a)--mkAnyType :: Type a => a -> AnyType-mkAnyType = AnyType--instance Type AnyType where- typeRef (AnyType a) = typeRef a- anyType = id--instance HasAnyType AnyType where- fromAnyType = id--class Params a where- toAnyList :: a -> [AnyType]- fromAnyList :: [AnyType] -> (a, [AnyType])--instance Integer AnyType--newtype Int1 = Int1 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show Int1 where- show _ = "Int1"--newtype Int8 = Int8 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show Int8 where- show _ = "Int8"--newtype Int16 = Int16 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show Int16 where- show _ = "Int16"--newtype Int32 = Int32 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show Int32 where- show _ = "Int32"--newtype Int64 = Int64 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show Int64 where- show _ = "Int64"--newtype IntWidth a = IntWidth AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Integer, Type, Typeable)--instance Show (IntWidth a) where- show _ = "IntWidth"--instance Real AnyType-instance Arithmetic AnyType--newtype Float = Float AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Real, Type, Typeable)--instance Show Float where- show _ = "Float"--newtype Double = Double AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Real, Type, Typeable)--instance Show Double where- show _ = "Double"--newtype X86Float80 = X86Float80 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Real, Type, Typeable)--instance Show X86Float80 where- show _ = "X86Float80"--newtype Float128 = Float128 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Real, Type, Typeable)--instance Show Float128 where- show _ = "Float128"--newtype PPCFloat128 = PPCFloat128 AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Real, Type, Typeable)--instance Show PPCFloat128 where- show _ = "PPCFloat128"--class (Type a, Type t) => Sequence a t | a -> t where- elementType :: a -> t--instance Sequence AnyType AnyType where- elementType = elementTypeDyn--newtype Array a = Array AnyType- deriving (HasAnyType, Type, Typeable)--arrayElementType :: Array a -> a-arrayElementType _ = undefined--instance Type a => Sequence (Array a) a where- elementType = arrayElementType--instance (Show a) => Show (Array a) where- show a = "Array " ++ show (arrayElementType a)--newtype Pointer a = Pointer AnyType- deriving (FirstClass, HasAnyType, Type, Typeable)--pointerElementType :: Pointer a -> a-pointerElementType _ = undefined--instance Type a => Sequence (Pointer a) a where- elementType = pointerElementType--instance (Show a) => Show (Pointer a) where- show a = "Pointer " ++ show (pointerElementType a)--newtype Vector a = Vector AnyType- deriving (Arithmetic, FirstClass, HasAnyType, Type, Typeable)--vectorElementType :: Vector a -> a-vectorElementType _ = undefined--instance Type a => Sequence (Vector a) a where- elementType = vectorElementType--instance (Show a) => Show (Vector a) where- show a = "Vector " ++ show (vectorElementType a)--newtype Void = Void AnyType- deriving (HasAnyType, Type, Typeable)--instance Show Void where- show _ = "Void"--class Type a => DynamicType a where- toAnyType :: a -- ^ not inspected- -> AnyType--data Function r p = Function {- fromNewFunction :: AnyType- }- deriving (Typeable)--instance HasAnyType (Function r p) where- fromAnyType = Function--instance Type (Function r p) where- typeRef = typeRef . fromNewFunction- anyType = fromNewFunction--instance (Show r, Show p, Params p) => Show (Function r p) where- show a = "Function " ++ show (functionResult a) ++ " " ++ show (params a)--functionParams :: Function r p -> p-functionParams _ = undefined--functionResult :: Function r p -> r-functionResult _ = undefined--instance (DynamicType r, Params p) => DynamicType (Function r p) where- toAnyType f = let parms = toAnyList . functionParams $ f- ret = toAnyType . functionResult $ f- in functionType False ret parms--instance DynamicType AnyType where- toAnyType = id--data a :-> b = a :-> b-infixr 6 :->--car :: (a :-> b) -> a-car _ = undefined--cdr :: (a :-> b) -> b-cdr _ = undefined--instance (Show a, Show b) => Show (a :-> b) where- show a = show (car a) ++ " :-> " ++ show (cdr a)--int1 :: a -> Int1-int1 _ = Int1 $ mkAnyType FFI.int1Type--fromAny :: HasAnyType a => [AnyType] -> (a, [AnyType])-fromAny e | trace ("eee " ++ show (length e) ) False = undefined-fromAny (x:xs) = (fromAnyType x,xs)-fromAny _ = error "LLVM.Core.Type.fromAny: empty list"--instance Params () where- toAnyList _ = []- fromAnyList _ = error "fromAnyList ()"--instance Params Int1 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance TypeValue Int1 where- typeValue = int1--instance DynamicType Int1 where- toAnyType = mkAnyType . int1--int8 :: a -> Int8-int8 _ = Int8 $ mkAnyType FFI.int8Type--instance Params Int8 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance Params AnyType where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance DynamicType Int8 where- toAnyType = mkAnyType . int8--int16 :: a -> Int16-int16 _ = Int16 $ mkAnyType FFI.int16Type--instance Params Int16 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance DynamicType Int16 where- toAnyType = mkAnyType . int16--int32 :: a -> Int32-int32 _ = Int32 $ mkAnyType FFI.int32Type--instance Params Int32 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance DynamicType Int32 where- toAnyType = mkAnyType . int32--int64 :: a -> Int64-int64 _ = Int64 $ mkAnyType FFI.int64Type--instance Params Int64 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance DynamicType Int64 where- toAnyType = mkAnyType . int64--integer :: Int -> b -> IntWidth a-integer width _ = IntWidth . mkAnyType . FFI.integerType $ fromIntegral width---- Not possible:------ instance Params (IntWidth a) where--- toAnyList a = [toAnyType a]------ instance DynamicType (IntWidth a) where--- toAnyType _ = mkAnyType integerType--float :: a -> Float-float _ = Float $ mkAnyType FFI.floatType--instance Params Float where- toAnyList a = [toAnyType a]- fromAnyList = fromAny--instance DynamicType Float where- toAnyType = mkAnyType . float--double :: a -> Double-double _ = Double $ mkAnyType FFI.doubleType--instance Params Double where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+import Data.Int+import Data.Word+import Data.TypeNumbers+import LLVM.Core.Util(functionType)+import LLVM.Core.Data+import qualified LLVM.FFI.Core as FFI -instance DynamicType Double where- toAnyType = mkAnyType . double+-- TODO:+-- Move IntN, WordN to a special module that implements those types+-- properly in Haskell.+-- Also more Array and Vector to a Haskell module to implement them.+-- Add Label?+-- Add structures (using tuples, maybe nested). -x86Float80 :: a -> X86Float80-x86Float80 _ = X86Float80 $ mkAnyType FFI.x86FP80Type+-- |The 'IsType' class classifies all types that have an LLVM representation.+class IsType a where+ typeRef :: a -> FFI.TypeRef -- ^The argument is never evaluated -instance Params X86Float80 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+-- |Arithmetic types, i.e., integral and floating types.+class IsType a => IsArithmetic a -instance DynamicType X86Float80 where- toAnyType = mkAnyType . x86Float80+-- |Integral types.+class IsArithmetic a => IsInteger a -float128 :: a -> Float128-float128 _ = Float128 $ mkAnyType FFI.fp128Type+-- |Floating types.+class IsArithmetic a => IsFloating a -instance Params Float128 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+-- |Primitive types.+class IsType a => IsPrimitive a -instance DynamicType Float128 where- toAnyType = mkAnyType . float128+-- |First class types, i.e., the types that can be passed as arguments, etc.+class IsType a => IsFirstClass a -ppcFloat128 :: a -> PPCFloat128-ppcFloat128 _ = PPCFloat128 $ mkAnyType FFI.ppcFP128Type+-- XXX use kind annotation+-- |Sequence types, i.e., vectors and arrays+class IsSequence c where dummy__ :: c a -> a; dummy__ = undefined -instance Params PPCFloat128 where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+-- |Types with a fixed size.+class (IsType a) => IsSized a -instance DynamicType PPCFloat128 where- toAnyType = mkAnyType . ppcFloat128+-- |Function type.+class (IsType a) => IsFunction a where+ funcType :: [FFI.TypeRef] -> a -> FFI.TypeRef -void :: a -> Void-void _ = Void $ mkAnyType FFI.voidType+-- Only make instances for types that make sense in Haskell+-- (i.e., some floating types are excluded). -instance Params Void where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+-- Floating point types.+instance IsType Float where typeRef _ = FFI.floatType+instance IsType Double where typeRef _ = FFI.doubleType+instance IsType FP128 where typeRef _ = FFI.fp128Type -instance DynamicType Void where- toAnyType = mkAnyType . void+-- Void type+instance IsType () where typeRef _ = FFI.voidType -instance (DynamicType a, HasAnyType a, Params b) => Params (a :-> b) where- toAnyList a = toAnyType (car a) : toAnyList (cdr a)- fromAnyList (x:xs) = let (y,ys) = fromAnyList xs- in (fromAnyType x :-> y,ys)- fromAnyList _ = error "LLVM.Core.Type.fromAnyList(:->): empty list"+-- Label type+--data Label+--instance IsType Label where typeRef _ = FFI.labelType -functionType :: Bool -> AnyType -> [AnyType] -> AnyType-functionType varargs retType paramTypes = unsafePerformIO $- withArrayLen (map typeRef paramTypes) $ \len ptr ->- return . mkAnyType $ FFI.functionType (typeRef retType) ptr- (fromIntegral len) (fromBool varargs)+-- Variable size integer types+instance (IsTypeNumber n) => IsType (IntN n)+ where typeRef _ = FFI.integerType (typeNumber (undefined :: n)) -params :: Params p => Function r p -> p-params f = case fromAnyList . toAnyList . functionParams $ f of- (p, []) -> p- _ -> error "LLVM.Core.Type.newParams: incompletely consumed params"+instance (IsTypeNumber n) => IsType (WordN n)+ where typeRef _ = FFI.integerType (typeNumber (undefined :: n)) -function :: (DynamicType r, Params p) => r -> p -> Function r p-function r p = Function . functionType False (toAnyType r) $ toAnyList p+-- Fixed size integer types.+instance IsType Bool where typeRef _ = FFI.int1Type+instance IsType Word8 where typeRef _ = FFI.int8Type+instance IsType Word16 where typeRef _ = FFI.int16Type+instance IsType Word32 where typeRef _ = FFI.int32Type+instance IsType Word64 where typeRef _ = FFI.int64Type+instance IsType Int8 where typeRef _ = FFI.int8Type+instance IsType Int16 where typeRef _ = FFI.int16Type+instance IsType Int32 where typeRef _ = FFI.int32Type+instance IsType Int64 where typeRef _ = FFI.int64Type -instance DynamicType p => Params (Function r p) where- toAnyList a = [toAnyType (functionParams a)]- fromAnyList = fromAny- -functionVarArg :: (DynamicType r, Params p) => r -> p -> Function r p-functionVarArg r p = Function . functionType True (toAnyType r) $ toAnyList p- -isFunctionVarArg :: Function r p -> Bool-isFunctionVarArg = toBool . FFI.isFunctionVarArg . typeRef+-- Sequence types+instance (IsTypeNumber n, IsSized a) => IsType (Array n a)+ where typeRef _ = FFI.arrayType (typeRef (undefined :: a))+ (typeNumber (undefined :: n)) -getReturnType :: (Params p) => Function r p -> AnyType-getReturnType = mkAnyType . FFI.getReturnType . typeRef+instance (IsTypeNumber n, IsPrimitive a) => IsType (Vector n a)+ where typeRef _ = FFI.arrayType (typeRef (undefined :: a))+ (typeNumber (undefined :: n)) -getParamTypes :: (Params p) => Function r p -> [AnyType]-getParamTypes typ = unsafePerformIO $ do- let typ' = typeRef typ- count = FFI.countParamTypes typ'- len = fromIntegral count- allocaArray len $ \ptr -> do- FFI.getParamTypes typ' ptr- map mkAnyType <$> peekArray len ptr+instance (IsType a) => IsType (Ptr a) where+ typeRef ~(Ptr a) = FFI.pointerType (typeRef a) 0 -array :: (DynamicType t) => t -> Int -> Array t-array typ len = Array . mkAnyType $ FFI.arrayType (typeRef (toAnyType typ)) (fromIntegral len)+-- Functions.+instance (IsFirstClass a, IsFunction b) => IsType (a->b) where+ typeRef = funcType [] -instance (DynamicType t) => DynamicType (Array t) where- toAnyType = mkAnyType . flip array 0 . toAnyType . arrayElementType+instance (IsFirstClass a) => IsType (IO a) where+ typeRef = funcType [] -newtype AddressSpace = AddressSpace {- fromAddressSpace :: Int- }- deriving (Eq, Ord, Show, Read)+--- Instances to classify types+instance IsArithmetic Float+instance IsArithmetic Double+instance IsArithmetic FP128+instance (IsTypeNumber n) => IsArithmetic (IntN n)+instance (IsTypeNumber n) => IsArithmetic (WordN n)+instance IsArithmetic Bool+instance IsArithmetic Int8+instance IsArithmetic Int16+instance IsArithmetic Int32+instance IsArithmetic Int64+instance IsArithmetic Word8+instance IsArithmetic Word16+instance IsArithmetic Word32+instance IsArithmetic Word64 -addressSpace :: Int -> AddressSpace-addressSpace = AddressSpace+instance IsFloating Float+instance IsFloating Double+instance IsFloating FP128 -genericAddressSpace :: AddressSpace-genericAddressSpace = addressSpace 0+instance (IsTypeNumber n) => IsInteger (IntN n)+instance (IsTypeNumber n) => IsInteger (WordN n)+instance IsInteger Bool+instance IsInteger Int8+instance IsInteger Int16+instance IsInteger Int32+instance IsInteger Int64+instance IsInteger Word8+instance IsInteger Word16+instance IsInteger Word32+instance IsInteger Word64 -pointerIn :: (DynamicType t) => t -> AddressSpace -> Pointer t-pointerIn typ space = Pointer . mkAnyType $ FFI.pointerType (typeRef (toAnyType typ)) (fromIntegral . fromAddressSpace $ space)+instance IsFirstClass Float+instance IsFirstClass Double+instance IsFirstClass FP128+instance (IsTypeNumber n) => IsFirstClass (IntN n)+instance (IsTypeNumber n) => IsFirstClass (WordN n)+instance IsFirstClass Bool+instance IsFirstClass Int8+instance IsFirstClass Int16+instance IsFirstClass Int32+instance IsFirstClass Int64+instance IsFirstClass Word8+instance IsFirstClass Word16+instance IsFirstClass Word32+instance IsFirstClass Word64+instance (IsTypeNumber n, IsPrimitive a) => IsFirstClass (Vector n a)+instance (IsType a) => IsFirstClass (Ptr a)+instance IsFirstClass () -- XXX This isn't right, but () can be returned -pointer :: (DynamicType t) => t -> Pointer t-pointer typ = pointerIn typ genericAddressSpace+instance (IsTypeNumber n) => IsSequence (Array n)+--instance (IsTypeNumber n, IsPrimitive a) => IsSequence (Vector n) a -instance (DynamicType t) => DynamicType (Pointer t) where- toAnyType = mkAnyType . pointer . toAnyType . pointerElementType+instance IsSized Float+instance IsSized Double+instance IsSized FP128+instance (IsTypeNumber n) => IsSized (IntN n)+instance (IsTypeNumber n) => IsSized (WordN n)+instance IsSized Bool+instance IsSized Int8+instance IsSized Int16+instance IsSized Int32+instance IsSized Int64+instance IsSized Word8+instance IsSized Word16+instance IsSized Word32+instance IsSized Word64+instance (IsTypeNumber n, IsSized a) => IsSized (Array n a)+instance (IsTypeNumber n, IsPrimitive a) => IsSized (Vector n a)+instance (IsType a) => IsSized (Ptr a) -instance (DynamicType t) => Params (Pointer t) where- toAnyList a = [toAnyType a]- fromAnyList = fromAny+instance IsPrimitive Float+instance IsPrimitive Double+instance IsPrimitive FP128+instance (IsTypeNumber n) => IsPrimitive (IntN n)+instance (IsTypeNumber n) => IsPrimitive (WordN n)+instance IsPrimitive Bool+instance IsPrimitive Int8+instance IsPrimitive Int16+instance IsPrimitive Int32+instance IsPrimitive Int64+instance IsPrimitive Word8+instance IsPrimitive Word16+instance IsPrimitive Word32+instance IsPrimitive Word64+--instance IsPrimitive Label+instance IsPrimitive () -vector :: (DynamicType t) => t -> Int -> Vector t-vector typ len = Vector . mkAnyType $ FFI.vectorType (typeRef (toAnyType typ)) (fromIntegral len)+-- Functions.+instance (IsFirstClass a, IsFunction b) => IsFunction (a->b) where+ funcType ts _ = funcType (typeRef (undefined :: a) : ts) (undefined :: b)+instance (IsFirstClass a) => IsFunction (IO a) where+ funcType ts _ = functionType False (typeRef (undefined :: a)) (reverse ts) -instance (DynamicType t) => DynamicType (Vector t) where- toAnyType = mkAnyType . flip vector 0 . toAnyType . vectorElementType+-- XXX Structures not implemented. Tuples is probably an easy way. -elementTypeDyn :: Type a => a -> AnyType-elementTypeDyn = mkAnyType . FFI.getElementType . typeRef
+ LLVM/Core/Util.hs view
@@ -0,0 +1,313 @@+{-# LANGUAGE ForeignFunctionInterface #-}+module LLVM.Core.Util(+ -- * Module handling+ Module(..), withModule, createModule, destroyModule, writeBitcodeToFile,+ -- * Module provider handling+ ModuleProvider(..), withModuleProvider, createModuleProviderForExistingModule,+ -- * Pass manager handling+ PassManager(..), withPassManager, createPassManager, createFunctionPassManager,+ runFunctionPassManager, initializeFunctionPassManager, finalizeFunctionPassManager,+ -- * Instruction builder+ Builder(..), withBuilder, createBuilder, positionAtEnd, getInsertBlock,+ -- * Basic blocks+ BasicBlock,+ appendBasicBlock,+ -- * Functions+ Function,+ addFunction, getParam,+ -- * Globals+ addGlobal,+ constString, constStringNul,+ -- * Instructions+ makeCall, makeInvoke,+ -- * Misc+ CString, withArrayLen,+ withEmptyCString,+ functionType, buildEmptyPhi, addPhiIns,+ -- * Transformation passes+ addCFGSimplificationPass, addConstantPropagationPass, addDemoteMemoryToRegisterPass,+ addGVNPass, addInstructionCombiningPass, addPromoteMemoryToRegisterPass, addReassociatePass,+ addTargetData+ ) where+import Control.Monad(liftM, when)+import Foreign.C.String (withCString, withCStringLen, CString)+import Foreign.ForeignPtr (ForeignPtr, FinalizerPtr, newForeignPtr, withForeignPtr)+import Foreign.Marshal.Array (withArrayLen, withArray)+import Foreign.Marshal.Utils (fromBool)+import System.IO.Unsafe (unsafePerformIO)++import qualified LLVM.FFI.Core as FFI+import qualified LLVM.FFI.Target as FFI+import qualified LLVM.FFI.BitWriter as FFI+import qualified LLVM.FFI.Transforms.Scalar as FFI++type Type = FFI.TypeRef++-- unsafePerformIO just to wrap the non-effecting withArrayLen call+functionType :: Bool -> Type -> [Type] -> Type+functionType varargs retType paramTypes = unsafePerformIO $+ withArrayLen paramTypes $ \ len ptr ->+ return $ FFI.functionType retType ptr (fromIntegral len)+ (fromBool varargs)++--------------------------------------+-- Handle modules+{-+newtype Module = Module {+ fromModule :: ForeignPtr FFI.Module+ }+-- deriving (Typeable)++withModule :: Module -> (FFI.ModuleRef -> IO a) -> IO a+withModule modul = withForeignPtr (fromModule modul)++createModule :: String -> IO Module+createModule name =+ withCString name $ \namePtr -> do+ ptr <- FFI.moduleCreateWithName namePtr+ final <- h2c_module FFI.disposeModule+ liftM Module $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_module+ :: (FFI.ModuleRef -> IO ()) -> IO (FinalizerPtr a)+-}++-- Don't use a finalizer for the module, but instead provide an+-- explicit destructor. This is because handing a module to+-- a module provider changes ownership of the module to the provider,+-- and we don't want to free it by mistake.++-- | Type of top level modules.+newtype Module = Module {+ fromModule :: FFI.ModuleRef+ }++withModule :: Module -> (FFI.ModuleRef -> IO a) -> IO a+withModule modul f = f (fromModule modul)++createModule :: String -> IO Module+createModule name =+ withCString name $ \ namePtr -> do+ liftM Module $ FFI.moduleCreateWithName namePtr++-- | Free all storage related to a module. *Note*, this is a dangerous call, since referring+-- to the module after this call is an error. The reason for the explicit call to free+-- the module instead of an automatic lifetime management is that modules have a+-- somewhat complicated ownership. Handing a module to a module provider changes+-- the ownership of the module, and the module provider will free the module when necessary.+destroyModule :: Module -> IO ()+destroyModule = FFI.disposeModule . fromModule++-- |Write a module to a file.+writeBitcodeToFile :: String -> Module -> IO ()+writeBitcodeToFile name mdl =+ withCString name $ \ namePtr ->+ withModule mdl $ \ mdlPtr -> do+ rc <- FFI.writeBitcodeToFile mdlPtr namePtr+ when (rc /= 0) $+ ioError $ userError $ "writeBitcodeToFile: return code " ++ show rc+ return ()++--------------------------------------+-- Handle module providers++-- | A module provider is used by the code generator to get access to a module.+newtype ModuleProvider = ModuleProvider {+ fromModuleProvider :: ForeignPtr FFI.ModuleProvider+ }++withModuleProvider :: ModuleProvider -> (FFI.ModuleProviderRef -> IO a)+ -> IO a+withModuleProvider = withForeignPtr . fromModuleProvider++-- | Turn a module into a module provider.+createModuleProviderForExistingModule :: Module -> IO ModuleProvider+createModuleProviderForExistingModule modul =+ withModule modul $ \modulPtr -> do+ ptr <- FFI.createModuleProviderForExistingModule modulPtr+ final <- h2c_moduleProvider FFI.disposeModuleProvider+ liftM ModuleProvider $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_moduleProvider+ :: (FFI.ModuleProviderRef -> IO ()) -> IO (FinalizerPtr a)+++--------------------------------------+-- Handle instruction builders++newtype Builder = Builder {+ fromBuilder :: ForeignPtr FFI.Builder+ }++withBuilder :: Builder -> (FFI.BuilderRef -> IO a) -> IO a+withBuilder = withForeignPtr . fromBuilder++createBuilder :: IO Builder+createBuilder = do+ final <- h2c_builder FFI.disposeBuilder+ ptr <- FFI.createBuilder+ liftM Builder $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_builder+ :: (FFI.BuilderRef -> IO ()) -> IO (FinalizerPtr a)++positionAtEnd :: Builder -> FFI.BasicBlockRef -> IO ()+positionAtEnd bld bblk =+ withBuilder bld $ \ bldPtr ->+ FFI.positionAtEnd bldPtr bblk++getInsertBlock :: Builder -> IO FFI.BasicBlockRef+getInsertBlock bld =+ withBuilder bld $ \ bldPtr ->+ FFI.getInsertBlock bldPtr++--------------------------------------++type BasicBlock = FFI.BasicBlockRef++appendBasicBlock :: Function -> String -> IO BasicBlock+appendBasicBlock func name =+ withCString name $ \ namePtr ->+ FFI.appendBasicBlock func namePtr++--------------------------------------++type Function = FFI.ValueRef++addFunction :: Module -> FFI.Linkage -> String -> Type -> IO Function+addFunction modul linkage name typ =+ withModule modul $ \ modulPtr ->+ withCString name $ \ namePtr -> do+ f <- FFI.addFunction modulPtr namePtr typ+ FFI.setLinkage f linkage+ return f++getParam :: Function -> Int -> Value+getParam f = FFI.getParam f . fromIntegral++--------------------------------------++addGlobal :: Module -> FFI.Linkage -> String -> Type -> IO Value+addGlobal modul linkage name typ =+ withModule modul $ \ modulPtr ->+ withCString name $ \ namePtr -> do+ v <- FFI.addGlobal modulPtr typ namePtr+ FFI.setLinkage v linkage+ return v++-- unsafePerformIO is safe because it's only used for the withCStringLen conversion+constStringInternal :: Bool -> String -> Value+constStringInternal nulTerm s = unsafePerformIO $+ withCStringLen s $ \(sPtr, sLen) ->+ return $ FFI.constString sPtr (fromIntegral sLen) (fromBool (not nulTerm))++constString :: String -> Value+constString = constStringInternal False++constStringNul :: String -> Value+constStringNul = constStringInternal True++--------------------------------------++type Value = FFI.ValueRef++makeCall :: Function -> FFI.BuilderRef -> [Value] -> IO Value+makeCall func bldPtr args = do+{-+ print "makeCall"+ FFI.dumpValue func+ mapM_ FFI.dumpValue args+ print "----------------------"+-}+ withArrayLen args $ \ argLen argPtr ->+ withEmptyCString $ + FFI.buildCall bldPtr func argPtr+ (fromIntegral argLen)++makeInvoke :: BasicBlock -> BasicBlock -> Function -> FFI.BuilderRef ->+ [Value] -> IO Value+makeInvoke norm expt func bldPtr args =+ withArrayLen args $ \ argLen argPtr ->+ withEmptyCString $ + FFI.buildInvoke bldPtr func argPtr (fromIntegral argLen) norm expt++--------------------------------------++buildEmptyPhi :: FFI.BuilderRef -> Type -> IO Value+buildEmptyPhi bldPtr typ = do+ withEmptyCString $ FFI.buildPhi bldPtr typ++withEmptyCString :: (CString -> IO a) -> IO a+withEmptyCString = withCString "" ++addPhiIns :: Value -> [(Value, BasicBlock)] -> IO ()+addPhiIns inst incoming = do+ let (vals, bblks) = unzip incoming+ withArrayLen vals $ \ count valPtr ->+ withArray bblks $ \ bblkPtr ->+ FFI.addIncoming inst valPtr bblkPtr (fromIntegral count)++--------------------------------------++-- | Manage compile passes.+newtype PassManager = PassManager {+ fromPassManager :: ForeignPtr FFI.PassManager+ }++withPassManager :: PassManager -> (FFI.PassManagerRef -> IO a)+ -> IO a+withPassManager = withForeignPtr . fromPassManager++-- | Create a pass manager.+createPassManager :: IO PassManager+createPassManager = do+ ptr <- FFI.createPassManager+ final <- h2c_passManager FFI.disposePassManager+ liftM PassManager $ newForeignPtr final ptr++-- | Create a pass manager for a module.+createFunctionPassManager :: ModuleProvider -> IO PassManager+createFunctionPassManager modul =+ withModuleProvider modul $ \modulPtr -> do+ ptr <- FFI.createFunctionPassManager modulPtr+ final <- h2c_passManager FFI.disposePassManager+ liftM PassManager $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_passManager+ :: (FFI.PassManagerRef -> IO ()) -> IO (FinalizerPtr a)++-- | Add a control flow graph simplification pass to the manager.+addCFGSimplificationPass :: PassManager -> IO ()+addCFGSimplificationPass pm = withPassManager pm FFI.addCFGSimplificationPass++-- | Add a constant propagation pass to the manager.+addConstantPropagationPass :: PassManager -> IO ()+addConstantPropagationPass pm = withPassManager pm FFI.addConstantPropagationPass++addDemoteMemoryToRegisterPass :: PassManager -> IO ()+addDemoteMemoryToRegisterPass pm = withPassManager pm FFI.addDemoteMemoryToRegisterPass++-- | Add a global value numbering pass to the manager.+addGVNPass :: PassManager -> IO ()+addGVNPass pm = withPassManager pm FFI.addGVNPass++addInstructionCombiningPass :: PassManager -> IO ()+addInstructionCombiningPass pm = withPassManager pm FFI.addInstructionCombiningPass++addPromoteMemoryToRegisterPass :: PassManager -> IO ()+addPromoteMemoryToRegisterPass pm = withPassManager pm FFI.addPromoteMemoryToRegisterPass++addReassociatePass :: PassManager -> IO ()+addReassociatePass pm = withPassManager pm FFI.addReassociatePass++addTargetData :: FFI.TargetDataRef -> PassManager -> IO ()+addTargetData td pm = withPassManager pm $ FFI.addTargetData td++runFunctionPassManager :: PassManager -> Function -> IO Int+runFunctionPassManager pm fcn = liftM fromIntegral $ withPassManager pm $ \ pmref -> FFI.runFunctionPassManager pmref fcn++initializeFunctionPassManager :: PassManager -> IO Int+initializeFunctionPassManager pm = liftM fromIntegral $ withPassManager pm FFI.initializeFunctionPassManager++finalizeFunctionPassManager :: PassManager -> IO Int+finalizeFunctionPassManager pm = liftM fromIntegral $ withPassManager pm FFI.finalizeFunctionPassManager
− LLVM/Core/Utils.hs
@@ -1,41 +0,0 @@-module LLVM.Core.Utils- (- defineGlobal- , declareFunction- , defineFunction- ) where--import Prelude hiding (mod)--import qualified LLVM.Core as Core-import qualified LLVM.Core.Builder as B-import qualified LLVM.Core.Constant as C-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V---defineGlobal :: (V.ConstValue a, V.TypedValue a t) => T.Module -> String -> a- -> IO (V.GlobalVar t)-defineGlobal mod name val = do- global <- Core.addGlobal mod (V.typeOf val) name- Core.setInitializer global val- return global--declareFunction :: (T.DynamicType r, T.Params p)- => T.Module -> String -> T.Function r p- -> IO (V.Function r p)-declareFunction mod name typ = do- maybeFunc <- Core.getNamedFunction mod name- case maybeFunc of- Nothing -> Core.addFunction mod name typ- Just func -> return $ let t = V.typeOf func- in if T.elementTypeDyn t /= T.toAnyType typ- then C.bitCast func (T.pointer typ)- else func--defineFunction :: T.Params p => T.Module -> String -> T.Function r p- -> IO (V.Function r p, B.BasicBlock)-defineFunction mod name typ = do- func <- Core.addFunction mod name typ- bblk <- Core.appendBasicBlock func "entry"- return (func, bblk)
− LLVM/Core/Value.hs
@@ -1,312 +0,0 @@-{-# LANGUAGE- DeriveDataTypeable- , ExistentialQuantification- , FunctionalDependencies- , MultiParamTypeClasses- , UndecidableInstances- #-}--module LLVM.Core.Value- (- -- * Values-- -- * Opaque wrapper for LLVM's basic value type- AnyValue- , DynamicValue(..)- , mkAnyValue- , typeOfDyn-- -- ** Type classes- , Value(..)- , Params(..)- , ConstValue- , GlobalValue- , GlobalVariable- , Arithmetic- , Integer- , Real- , Vector-- , Global(..)- , GlobalVar(..)- , Function(..)- , TypedValue(..)- , Argument(..)-- , Instruction(..)-- -- * Constants- , ConstInt(..)- , ConstReal(..)- , ConstArray(..)-- -- ** Useful functions- , params- , getName- , setName- , dumpValue- ) where--import Control.Applicative ((<$>))-import Data.Typeable (Typeable)-import Foreign.C.String (peekCString, withCString)-import Foreign.Marshal.Array (allocaArray, peekArray)-import Foreign.Ptr (nullPtr)-import Prelude hiding (Integer, Real)-import System.IO.Unsafe (unsafePerformIO)--import qualified LLVM.Core.FFI as FFI-import LLVM.Core.Type ((:->)(..))-import qualified LLVM.Core.Type as T---- import Debug.Trace---class Value a where- valueRef :: a -> FFI.ValueRef- anyValue :: a -> AnyValue--class DynamicValue a where- fromAnyValue :: AnyValue -> a--class Params t v | t -> v where- fromAnyList :: t -> [AnyValue] -> (v, [AnyValue])---- | Recover the type of a value in a manner that preserves static--- type safety.-class (T.Type t, Value v) => TypedValue v t | v -> t where- typeOf :: v -- ^ value is not inspected- -> t--data AnyValue = forall a. Value a => AnyValue a- deriving (Typeable)--instance DynamicValue AnyValue where- fromAnyValue = id--instance Value FFI.ValueRef where- valueRef = id- anyValue = AnyValue--mkAnyValue :: Value a => a -> AnyValue-mkAnyValue = AnyValue--class Value a => ConstValue a-class Value a => Arithmetic a-class Arithmetic a => Integer a-class Arithmetic a => Real a-class Arithmetic a => Vector a-class ConstValue a => GlobalValue a-class GlobalValue a => GlobalVariable a--instance Value AnyValue where- valueRef (AnyValue a) = valueRef a- anyValue = id--instance ConstValue AnyValue-instance GlobalValue AnyValue-instance GlobalVariable AnyValue-instance Arithmetic AnyValue-instance Integer AnyValue-instance Real AnyValue--getName :: Value v => v -> IO String-getName v = do- namePtr <- FFI.getValueName (valueRef v)- if namePtr == nullPtr- then return []- else peekCString namePtr--setName :: Value v => v -> String -> IO ()-setName v name = withCString name (FFI.setValueName (valueRef v))--dumpValue :: Value v => v -> IO ()-dumpValue = FFI.dumpValue . valueRef--newtype Instruction a = Instruction AnyValue- deriving (DynamicValue, Typeable, Value)--newtype Global t = Global AnyValue- deriving (ConstValue, DynamicValue, GlobalValue, Typeable, Value)--newtype GlobalVar t = GlobalVar AnyValue- deriving (ConstValue, DynamicValue, GlobalValue, GlobalVariable,- Typeable, Value)--fromAny :: (DynamicValue v, TypedValue v t, T.Type t) => t -> [AnyValue] -> (v, [AnyValue])-fromAny _ (x:xs) = (fromAnyValue x,xs)-fromAny _ _ = error "LLVM.Core.Value.fromAny: empty list"--globalVarType :: GlobalVar t -> t-globalVarType _ = undefined--instance T.Type t => TypedValue (GlobalVar t) t where- typeOf = globalVarType--data Function r p = Function {- fromFunction :: AnyValue- }- deriving (Typeable)--instance ConstValue (Function r p)-instance GlobalValue (Function r p)-instance GlobalVariable (Function r p)--instance DynamicValue (Function r p) where- fromAnyValue = Function--instance Value (Function r p) where- valueRef = valueRef . anyValue- anyValue = fromFunction--newtype Argument t = Argument AnyValue- deriving (DynamicValue, Typeable, Value)--instance (T.DynamicType r, T.Params p) => TypedValue (Function r p) (T.Function r p) where- typeOf _ = T.function undefined undefined--instance (Params b c) => Params (a :-> b) (Argument a :-> c) where- fromAnyList t (x:xs) = let (y,ys) = fromAnyList (T.cdr t) xs- in (Argument x :-> y,ys)- fromAnyList _ _ = error "LLVM.Core.Value.fromAnyList(:->): empty list"--newtype ConstInt t = ConstInt AnyValue- deriving (Arithmetic, ConstValue, DynamicValue, Integer, Typeable, Value)--instance TypedValue (ConstInt T.Int1) T.Int1 where- typeOf = T.int1--instance TypedValue (Argument T.Int1) T.Int1 where- typeOf = T.int1--instance TypedValue (Instruction T.Int1) T.Int1 where- typeOf = T.int1--instance Params T.Int1 (Argument T.Int1) where- fromAnyList = fromAny--instance TypedValue (ConstInt T.Int8) T.Int8 where- typeOf = T.int8--instance TypedValue (Argument T.Int8) T.Int8 where- typeOf = T.int8--instance TypedValue (Instruction T.Int8) T.Int8 where- typeOf = T.int8--instance Params T.Int8 (Argument T.Int8) where- fromAnyList = fromAny--instance TypedValue (ConstInt T.Int16) T.Int16 where- typeOf = T.int16--instance TypedValue (Argument T.Int16) T.Int16 where- typeOf = T.int16--instance Params T.Int16 (Argument T.Int16) where- fromAnyList = fromAny--instance TypedValue (ConstInt T.Int32) T.Int32 where- typeOf = T.int32--instance TypedValue (Argument T.Int32) T.Int32 where- typeOf = T.int32--instance TypedValue (Instruction T.Int32) T.Int32 where- typeOf = T.int32--instance Params T.Int32 (Argument T.Int32) where- fromAnyList = fromAny--instance TypedValue (ConstInt T.Int64) T.Int64 where- typeOf = T.int64--instance TypedValue (Argument T.Int64) T.Int64 where- typeOf = T.int64--instance TypedValue (Instruction T.Int64) T.Int64 where- typeOf = T.int64--instance Params T.Int64 (Argument T.Int64) where- fromAnyList = fromAny--newtype ConstArray t = ConstArray AnyValue- deriving (ConstValue, DynamicValue, Typeable, Value)--instance (T.DynamicType a) => TypedValue (ConstArray a) (T.Array a) where- typeOf _ = T.array undefined 0--instance (T.DynamicType t) => TypedValue (Instruction (T.Array t)) (T.Array t) where- typeOf _ = T.array undefined 0--instance (T.DynamicType t) => TypedValue (Instruction (T.Pointer t)) (T.Pointer t) where- typeOf _ = T.pointer undefined--instance (T.DynamicType t) => Params (T.Pointer t) (Instruction (T.Pointer t)) where- fromAnyList = fromAny--newtype ConstReal t = ConstReal AnyValue- deriving (Arithmetic, ConstValue, DynamicValue, Real, Typeable, Value)--instance TypedValue (ConstReal T.Float) T.Float where- typeOf = T.float--instance TypedValue (Argument T.Float) T.Float where- typeOf = T.float--instance Params T.Float (Argument T.Float) where- fromAnyList = fromAny--instance TypedValue (ConstReal T.Double) T.Double where- typeOf = T.double--instance TypedValue (Argument T.Double) T.Double where- typeOf = T.double--instance Params T.Double (Argument T.Double) where- fromAnyList = fromAny--instance TypedValue (ConstReal T.X86Float80) T.X86Float80 where- typeOf = T.x86Float80--instance TypedValue (Argument T.X86Float80) T.X86Float80 where- typeOf = T.x86Float80--instance Params T.X86Float80 (Argument T.X86Float80) where- fromAnyList = fromAny--instance TypedValue (ConstReal T.Float128) T.Float128 where- typeOf = T.float128--instance TypedValue (Argument T.Float128) T.Float128 where- typeOf = T.float128--instance Params T.Float128 (Argument T.Float128) where- fromAnyList = fromAny--instance TypedValue (ConstReal T.PPCFloat128) T.PPCFloat128 where- typeOf = T.ppcFloat128--instance TypedValue (Argument T.PPCFloat128) T.PPCFloat128 where- typeOf = T.ppcFloat128--instance Params T.PPCFloat128 (Argument T.PPCFloat128) where- fromAnyList = fromAny--countParams :: Function r p -> Int-countParams = fromIntegral . FFI.countParams . valueRef--listParams :: Function r p -> [AnyValue]-listParams f = unsafePerformIO $ do- let len = countParams f- allocaArray len $ \ptr -> do- FFI.getParams (valueRef f) ptr- map mkAnyValue <$> peekArray len ptr--params :: (T.DynamicType r, T.Params p, Params p v) => Function r p -> v-params f = case fromAnyList (T.params (typeOf f)) (listParams f) of- (p, []) -> p- _ -> error "LLVM.Core.Value.params: incompletely consumed params"--typeOfDyn :: Value a => a -> T.AnyType-typeOfDyn val = unsafePerformIO $ T.mkAnyType <$> FFI.typeOf (valueRef val)
LLVM/ExecutionEngine.hs view
@@ -1,173 +1,85 @@-{-# LANGUAGE- DeriveDataTypeable- , FunctionalDependencies- , MultiParamTypeClasses- #-}--module LLVM.ExecutionEngine- (- -- * Execution engines- ExecutionEngine- , createExecutionEngine- , runStaticConstructors- , runStaticDestructors- , runFunction-- -- * Generic values- , GenericValue- , Generic(..)+{-# LANGUAGE FlexibleInstances, UndecidableInstances, MultiParamTypeClasses, FunctionalDependencies #-}+ -- |An 'ExecutionEngine' is JIT compiler that is used to generate code for an LLVM module.+module LLVM.ExecutionEngine(+ -- * Execution engine+ ExecutionEngine,+ createExecutionEngine,+ runStaticConstructors,+ runStaticDestructors,+ -- * Translation+ Translatable, Generic,+ generateFunction,+ -- * Unsafe type conversion+ Unsafe,+ unsafePurify,+ -- * Simplified interface.+ simpleFunction,+ unsafeGenerateFunction ) where--import Control.Applicative ((<$>))-import Control.Exception (ioError)-import Data.Int (Int8, Int16, Int32, Int64)-import Data.Typeable (Typeable)-import Data.Word (Word8, Word16, Word32, Word64)-import Foreign.ForeignPtr (FinalizerPtr, ForeignPtr, newForeignPtr,- withForeignPtr)-import Foreign.C.String (peekCString)-import Foreign.Marshal.Alloc (alloca, free)-import Foreign.Marshal.Array (withArrayLen)-import Foreign.Marshal.Utils (fromBool, toBool)-import Foreign.Ptr (Ptr)-import Foreign.Storable (peek)-import System.IO.Error (userError) import System.IO.Unsafe (unsafePerformIO) -import qualified LLVM.ExecutionEngine.FFI as FFI-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V--newtype ExecutionEngine = ExecutionEngine {- fromExecutionEngine :: ForeignPtr FFI.ExecutionEngine- }--withExecutionEngine :: ExecutionEngine -> (Ptr FFI.ExecutionEngine -> IO a)- -> IO a-withExecutionEngine ee = withForeignPtr (fromExecutionEngine ee)--createExecutionEngine :: T.ModuleProvider -> IO ExecutionEngine-createExecutionEngine prov =- T.withModuleProvider prov $ \provPtr ->- alloca $ \eePtr ->- alloca $ \errPtr -> do- ret <- FFI.createExecutionEngine eePtr provPtr errPtr- if ret == 1- then do err <- peek errPtr- errStr <- peekCString err- free err- ioError . userError $ errStr- else do ptr <- peek eePtr- final <- h2c_ee FFI.disposeExecutionEngine- ExecutionEngine <$> newForeignPtr final ptr--foreign import ccall "wrapper" h2c_ee- :: (Ptr FFI.ExecutionEngine -> IO ()) -> IO (FinalizerPtr a)--runStaticConstructors :: ExecutionEngine -> IO ()-runStaticConstructors ee = withExecutionEngine ee FFI.runStaticConstructors--runStaticDestructors :: ExecutionEngine -> IO ()-runStaticDestructors ee = withExecutionEngine ee FFI.runStaticDestructors---newtype GenericValue t = GenericValue {- fromGenericValue :: ForeignPtr FFI.GenericValue- }- deriving (Typeable)--withGenericValue :: GenericValue t -> (FFI.GenericValueRef -> IO a) -> IO a-withGenericValue = withForeignPtr . fromGenericValue--createGenericValueWith :: IO FFI.GenericValueRef -> IO (GenericValue t)-createGenericValueWith f = do- final <- h2c_genericValue FFI.disposeGenericValue- ptr <- f- GenericValue <$> newForeignPtr final ptr--foreign import ccall "wrapper" h2c_genericValue- :: (FFI.GenericValueRef -> IO ()) -> IO (FinalizerPtr a)--withAll :: [GenericValue t] -> (Int -> Ptr FFI.GenericValueRef -> IO a) -> IO a-withAll ps a = go [] ps- where go ptrs (x:xs) = withGenericValue x $ \ptr -> go (ptr:ptrs) xs- go ptrs _ = withArrayLen (reverse ptrs) a- -runFunction :: ExecutionEngine -> V.Function r p -> [GenericValue t]- -> IO (GenericValue r)-runFunction ee func args =- withExecutionEngine ee $ \eePtr ->- withAll args $ \argLen argPtr ->- createGenericValueWith $ FFI.runFunction eePtr (V.valueRef func)- (fromIntegral argLen) argPtr--class Generic a t | a -> t where- createGeneric :: a -> IO (GenericValue t)- fromGeneric :: GenericValue t -> a--toGenericInt :: (Integral a, T.Type t) => (b -> t) -> Bool -> a -> IO (GenericValue t)-toGenericInt typf signed val = createGenericValueWith $- FFI.createGenericValueOfInt (T.typeRef (typf undefined))- (fromIntegral val) (fromBool signed)--fromGenericInt :: (Integral a, T.Type t) => Bool -> GenericValue t -> a-fromGenericInt signed val = unsafePerformIO $- withGenericValue val $ \ref ->- return . fromIntegral $ FFI.genericValueToInt ref (fromBool signed)--instance Generic Bool T.Int1 where- createGeneric = toGenericInt T.int1 False . fromBool- fromGeneric = toBool . fromGenericInt False--instance Generic Int8 T.Int8 where- createGeneric = toGenericInt T.int8 True . fromIntegral- fromGeneric = fromIntegral . fromGenericInt True--instance Generic Int16 T.Int16 where- createGeneric = toGenericInt T.int16 True . fromIntegral- fromGeneric = fromIntegral . fromGenericInt True+import LLVM.ExecutionEngine.Engine+import LLVM.FFI.Core(ValueRef)+import LLVM.Core.CodeGen(Value(..))+import LLVM.Core+import LLVM.Core.Util(runFunctionPassManager, initializeFunctionPassManager, finalizeFunctionPassManager) -instance Generic Int32 T.Int32 where- createGeneric = toGenericInt T.int32 True . fromIntegral- fromGeneric = fromIntegral . fromGenericInt True+-- |Class of LLVM function types that can be translated to the corresponding+-- Haskell type.+class Translatable f where+ translate :: ExecutionEngine -> [GenericValue] -> ValueRef -> f -instance Generic Int T.Int32 where- createGeneric = toGenericInt T.int32 True . fromIntegral- fromGeneric = fromIntegral . fromGenericInt True+instance (Generic a, Translatable b) => Translatable (a -> b) where+ translate ee args f = \ arg -> translate ee (toGeneric arg : args) f -instance Generic Int64 T.Int64 where- createGeneric = toGenericInt T.int64 True . fromIntegral- fromGeneric = fromIntegral . fromGenericInt True+instance (Generic a) => Translatable (IO a) where+ translate ee args f = fmap fromGeneric $ runFunction ee f $ reverse args -instance Generic Word8 T.Int8 where- createGeneric = toGenericInt T.int8 False . fromIntegral- fromGeneric = fromIntegral . fromGenericInt False+-- |Generate a Haskell function from an LLVM function.+generateFunction :: (Translatable f) =>+ ExecutionEngine -> Value (Ptr f) -> f+generateFunction ee (Value f) = translate ee [] f -instance Generic Word16 T.Int16 where- createGeneric = toGenericInt T.int16 False . fromIntegral- fromGeneric = fromIntegral . fromGenericInt False+class Unsafe a b | a -> b where+ unsafePurify :: a -> b -- ^Remove the IO from a function return type. This is unsafe in general. -instance Generic Word32 T.Int32 where- createGeneric = toGenericInt T.int32 False . fromIntegral- fromGeneric = fromIntegral . fromGenericInt False+instance (Unsafe b b') => Unsafe (a->b) (a->b') where+ unsafePurify f = unsafePurify . f -instance Generic Word64 T.Int64 where- createGeneric = toGenericInt T.int64 False . fromIntegral- fromGeneric = fromIntegral . fromGenericInt False+instance Unsafe (IO a) a where+ unsafePurify = unsafePerformIO -toGenericReal :: (Real a, T.Type t) => t -> a -> IO (GenericValue t)-toGenericReal typ val = createGenericValueWith $- FFI.createGenericValueOfFloat (T.typeRef typ) (realToFrac val)+-- |Translate a function to Haskell code. This is a simplified interface to+-- the execution engine and module mechanism.+simpleFunction :: (Translatable f) => CodeGenModule (Function f) -> IO f+simpleFunction bld = do+ m <- newModule+ func <- defineModule m bld+-- dumpValue func+ prov <- createModuleProviderForExistingModule m+ ee <- createExecutionEngine prov -fromGenericReal :: (Fractional a, T.Type t) => GenericValue t -> a-fromGenericReal val = unsafePerformIO $- withGenericValue val $ \ref ->- return . realToFrac $ FFI.genericValueToFloat ref+ pm <- createFunctionPassManager prov+ td <- getExecutionEngineTargetData ee+ addTargetData td pm+ addInstructionCombiningPass pm+ addReassociatePass pm+ addGVNPass pm+ addCFGSimplificationPass pm+ addPromoteMemoryToRegisterPass pm+ initializeFunctionPassManager pm+-- print ("rc1", rc1)+ runFunctionPassManager pm (unValue func)+-- print ("rc2", rc2)+ finalizeFunctionPassManager pm+-- print ("rc3", rc3)+-- dumpValue func -instance Generic Float T.Float where- createGeneric = toGenericReal undefined- fromGeneric = fromGenericReal+ return $ generateFunction ee func -instance Generic Double T.Double where- createGeneric = toGenericReal undefined- fromGeneric = fromGenericReal+-- | Combine 'simpleFunction' and 'unsafePurify'.+unsafeGenerateFunction :: (Unsafe t a, Translatable t) =>+ CodeGenModule (Function t) -> a+unsafeGenerateFunction bld = unsafePerformIO $ do+ fun <- simpleFunction bld+ return $ unsafePurify fun
+ LLVM/ExecutionEngine/Engine.hs view
@@ -0,0 +1,170 @@+{-# LANGUAGE ForeignFunctionInterface, FlexibleInstances, UndecidableInstances, OverlappingInstances #-}+module LLVM.ExecutionEngine.Engine(+ ExecutionEngine,+ createExecutionEngine, runStaticConstructors, runStaticDestructors,+ getExecutionEngineTargetData,+ runFunction,+ GenericValue, Generic(..)+ ) where+import Control.Monad+import Data.Int+import Data.Word+import Foreign.Marshal.Alloc (alloca, free)+import Foreign.Marshal.Array (withArrayLen)+import Foreign.ForeignPtr (FinalizerPtr, ForeignPtr, newForeignPtr,+ withForeignPtr)+import Foreign.Marshal.Utils (fromBool)+import Foreign.C.String (peekCString)+import Foreign.Ptr (Ptr)+import Foreign.Storable (peek)+import System.IO.Unsafe (unsafePerformIO)++import LLVM.Core.Util(ModuleProvider, withModuleProvider)+import qualified LLVM.FFI.ExecutionEngine as FFI+import qualified LLVM.FFI.Target as FFI+import LLVM.Core.Util(Function)+import LLVM.Core.Type(IsFirstClass, IsType(..))++-- |The type of the JITer.+newtype ExecutionEngine = ExecutionEngine {+ fromExecutionEngine :: ForeignPtr FFI.ExecutionEngine+ }++withExecutionEngine :: ExecutionEngine -> (Ptr FFI.ExecutionEngine -> IO a)+ -> IO a+withExecutionEngine = withForeignPtr . fromExecutionEngine++-- |Create an execution engine for a module provider.+createExecutionEngine :: ModuleProvider -> IO ExecutionEngine+createExecutionEngine prov =+ withModuleProvider prov $ \provPtr ->+ alloca $ \eePtr ->+ alloca $ \errPtr -> do+ ret <- FFI.createExecutionEngine eePtr provPtr errPtr+ if ret == 1+ then do err <- peek errPtr+ errStr <- peekCString err+ free err+ ioError . userError $ errStr+ else do ptr <- peek eePtr+ final <- h2c_ee FFI.disposeExecutionEngine+ liftM ExecutionEngine $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_ee+ :: (Ptr FFI.ExecutionEngine -> IO ()) -> IO (FinalizerPtr a)++runStaticConstructors :: ExecutionEngine -> IO ()+runStaticConstructors ee = withExecutionEngine ee FFI.runStaticConstructors++runStaticDestructors :: ExecutionEngine -> IO ()+runStaticDestructors ee = withExecutionEngine ee FFI.runStaticDestructors++getExecutionEngineTargetData :: ExecutionEngine -> IO FFI.TargetDataRef+getExecutionEngineTargetData ee = withExecutionEngine ee FFI.getExecutionEngineTargetData++--------------------------------------++newtype GenericValue = GenericValue {+ fromGenericValue :: ForeignPtr FFI.GenericValue+ }++withGenericValue :: GenericValue -> (FFI.GenericValueRef -> IO a) -> IO a+withGenericValue = withForeignPtr . fromGenericValue++createGenericValueWith :: IO FFI.GenericValueRef -> IO GenericValue+createGenericValueWith f = do+ final <- h2c_genericValue FFI.disposeGenericValue+ ptr <- f+ liftM GenericValue $ newForeignPtr final ptr++foreign import ccall "wrapper" h2c_genericValue+ :: (FFI.GenericValueRef -> IO ()) -> IO (FinalizerPtr a)++withAll :: [GenericValue] -> (Int -> Ptr FFI.GenericValueRef -> IO a) -> IO a+withAll ps a = go [] ps+ where go ptrs (x:xs) = withGenericValue x $ \ptr -> go (ptr:ptrs) xs+ go ptrs _ = withArrayLen (reverse ptrs) a+ +runFunction :: ExecutionEngine -> LLVM.Core.Util.Function -> [GenericValue]+ -> IO GenericValue+runFunction ee func args =+ withExecutionEngine ee $ \eePtr ->+ withAll args $ \argLen argPtr ->+ createGenericValueWith $ FFI.runFunction eePtr func+ (fromIntegral argLen) argPtr++class Generic a where+ toGeneric :: a -> GenericValue+ fromGeneric :: GenericValue -> a++instance Generic () where+ toGeneric _ = error "toGeneric ()"+ fromGeneric _ = ()++toGenericInt :: (Integral a, IsFirstClass a) => Bool -> a -> GenericValue+toGenericInt signed val = unsafePerformIO $ createGenericValueWith $+ FFI.createGenericValueOfInt (typeRef val) (fromIntegral val) (fromBool signed)++fromGenericInt :: (Integral a, IsFirstClass a) => Bool -> GenericValue -> a+fromGenericInt signed val = unsafePerformIO $+ withGenericValue val $ \ref ->+ return . fromIntegral $ FFI.genericValueToInt ref (fromBool signed)++--instance Generic Bool where+-- toGeneric = toGenericInt False . fromBool+-- fromGeneric = toBool . fromGenericInt False++instance Generic Int8 where+ toGeneric = toGenericInt True+ fromGeneric = fromGenericInt True++instance Generic Int16 where+ toGeneric = toGenericInt True+ fromGeneric = fromGenericInt True++instance Generic Int32 where+ toGeneric = toGenericInt True+ fromGeneric = fromGenericInt True++{-+instance Generic Int where+ toGeneric = toGenericInt True+ fromGeneric = fromGenericInt True+-}++instance Generic Int64 where+ toGeneric = toGenericInt True+ fromGeneric = fromGenericInt True++instance Generic Word8 where+ toGeneric = toGenericInt False+ fromGeneric = fromGenericInt False++instance Generic Word16 where+ toGeneric = toGenericInt False+ fromGeneric = fromGenericInt False++instance Generic Word32 where+ toGeneric = toGenericInt False+ fromGeneric = fromGenericInt False++instance Generic Word64 where+ toGeneric = toGenericInt False+ fromGeneric = fromGenericInt False++toGenericReal :: (Real a, IsFirstClass a) => a -> GenericValue+toGenericReal val = unsafePerformIO $ createGenericValueWith $+ FFI.createGenericValueOfFloat (typeRef val) (realToFrac val)++fromGenericReal :: (Fractional a, IsFirstClass a) => GenericValue -> a+fromGenericReal val = unsafePerformIO $+ withGenericValue val $ \ ref ->+ return . realToFrac $ FFI.genericValueToFloat ref++instance Generic Float where+ toGeneric = toGenericReal+ fromGeneric = fromGenericReal++instance Generic Double where+ toGeneric = toGenericReal+ fromGeneric = fromGenericReal
− LLVM/ExecutionEngine/FFI.hsc
@@ -1,69 +0,0 @@-{-# LANGUAGE EmptyDataDecls #-}--module LLVM.ExecutionEngine.FFI- (- -- * Execution engines- ExecutionEngine- , createExecutionEngine- , disposeExecutionEngine- , runStaticConstructors- , runStaticDestructors- , runFunction-- -- * Generic values- , GenericValue- , GenericValueRef- , createGenericValueOfInt- , genericValueToInt- , createGenericValueOfFloat- , genericValueToFloat- , disposeGenericValue- ) where--import Foreign.C.String (CString)-import Foreign.C.Types (CDouble, CInt, CUInt, CULLong)-import Foreign.Ptr (Ptr)--import LLVM.Core.FFI (ModuleProviderRef, TypeRef, ValueRef)--#include <llvm-c/ExecutionEngine.h>--data ExecutionEngine-type ExecutionEngineRef = Ptr ExecutionEngine--foreign import ccall unsafe "LLVMCreateExecutionEngine" createExecutionEngine- :: Ptr ExecutionEngineRef -> ModuleProviderRef -> Ptr CString- -> IO CInt--foreign import ccall unsafe "LLVMDisposeExecutionEngine" disposeExecutionEngine- :: ExecutionEngineRef -> IO ()--foreign import ccall unsafe "LLVMRunStaticConstructors" runStaticConstructors- :: ExecutionEngineRef -> IO ()--foreign import ccall unsafe "LLVMRunStaticDestructors" runStaticDestructors- :: ExecutionEngineRef -> IO ()---data GenericValue-type GenericValueRef = Ptr GenericValue--foreign import ccall unsafe "LLVMCreateGenericValueOfInt"- createGenericValueOfInt :: TypeRef -> CULLong -> CInt- -> IO GenericValueRef--foreign import ccall unsafe "LLVMGenericValueToInt" genericValueToInt- :: GenericValueRef -> CInt -> CULLong--foreign import ccall unsafe "LLVMCreateGenericValueOfFloat"- createGenericValueOfFloat :: TypeRef -> CDouble -> IO GenericValueRef--foreign import ccall unsafe "LLVMGenericValueToFloat" genericValueToFloat- :: GenericValueRef -> CDouble--foreign import ccall unsafe "LLVMDisposeGenericValue" disposeGenericValue- :: GenericValueRef -> IO ()--foreign import ccall unsafe "LLVMRunFunction" runFunction- :: ExecutionEngineRef -> ValueRef -> CUInt- -> Ptr GenericValueRef -> IO GenericValueRef
+ LLVM/FFI/Analysis.hsc view
@@ -0,0 +1,19 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.Analysis where+import Foreign.C.String(CString)+import Foreign.C.Types(CInt)+import Foreign.Ptr(Ptr)++import LLVM.FFI.Core++type VerifierFailureAction = CInt++foreign import ccall unsafe "LLVMVerifyFunction" verifyFunction+ :: ValueRef -> VerifierFailureAction -> IO CInt+foreign import ccall unsafe "LLVMVerifyModule" verifyModule+ :: ModuleRef -> VerifierFailureAction -> (Ptr CString) -> IO CInt+foreign import ccall unsafe "LLVMViewFunctionCFG" viewFunctionCFG+ :: ValueRef -> IO ()+foreign import ccall unsafe "LLVMViewFunctionCFGOnly" viewFunctionCFGOnly+ :: ValueRef -> IO ()
+ LLVM/FFI/BitReader.hsc view
@@ -0,0 +1,13 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.BitReader where+import Foreign.C.String(CString)+import Foreign.C.Types(CInt)+import Foreign.Ptr(Ptr)++import LLVM.FFI.Core++foreign import ccall unsafe "LLVMGetBitcodeModuleProvider" getBitcodeModuleProvider+ :: MemoryBufferRef -> (Ptr ModuleProviderRef) -> (Ptr CString) -> IO CInt+foreign import ccall unsafe "LLVMParseBitcode" parseBitcode+ :: MemoryBufferRef -> (Ptr ModuleRef) -> (Ptr CString) -> IO CInt
+ LLVM/FFI/BitWriter.hsc view
@@ -0,0 +1,12 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.BitWriter where+import Foreign.C.String(CString)+import Foreign.C.Types(CInt)++import LLVM.FFI.Core++foreign import ccall unsafe "LLVMWriteBitcodeToFile" writeBitcodeToFile+ :: ModuleRef -> CString -> IO CInt+foreign import ccall unsafe "LLVMWriteBitcodeToFileHandle" writeBitcodeToFileHandle+ :: ModuleRef -> CInt -> IO CInt
+ LLVM/FFI/Core.hsc view
@@ -0,0 +1,1112 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++-- |+-- Module: LLVM.FFI.Core+-- Copyright: Bryan O'Sullivan 2007, 2008+-- License: BSD-style (see the file LICENSE)+--+-- Maintainer: bos@serpentine.com+-- Stability: experimental+-- Portability: requires GHC 6.8, LLVM+--+-- This module provides direct access to the LLVM C bindings.++module LLVM.FFI.Core+ (+ -- * Modules+ Module+ , ModuleRef+ , moduleCreateWithName+ , disposeModule++ , getDataLayout+ , setDataLayout++ , getTarget+ , setTarget++ -- * Module providers+ , ModuleProvider+ , ModuleProviderRef+ , createModuleProviderForExistingModule+ , disposeModuleProvider++ -- * Types+ , Type+ , TypeRef+ , addTypeName+ , deleteTypeName++ , getTypeKind++ -- ** Integer types+ , int1Type+ , int8Type+ , int16Type+ , int32Type+ , int64Type+ , integerType+ , getIntTypeWidth++ -- ** Real types+ , floatType+ , doubleType+ , x86FP80Type+ , fp128Type+ , ppcFP128Type++ -- ** Function types+ , functionType+ , isFunctionVarArg+ , getReturnType+ , countParamTypes+ , getParamTypes++ -- ** Other types+ , voidType+ , labelType+ , opaqueType++ -- ** Array, pointer, and vector types+ , arrayType+ , pointerType+ , vectorType+ , getElementType+ , getArrayLength+ , getPointerAddressSpace+ , getVectorSize++ -- ** Struct types+ , structType+ , countStructElementTypes+ , getStructElementTypes+ , isPackedStruct++ -- * Type handles+ , createTypeHandle+ , refineType+ , resolveTypeHandle+ , disposeTypeHandle++ -- * Values+ , Value+ , ValueRef+ , typeOf+ , getValueName+ , setValueName+ , dumpValue++ -- ** Constants+ , constNull+ , constAllOnes+ , getUndef+ , isConstant+ , isNull+ , isUndef++ -- ** Global variables, functions, and aliases (globals)+ , Linkage+ , Visibility+ , isDeclaration+ , getLinkage+ , setLinkage+ , getSection+ , setSection+ , getVisibility+ , setVisibility+ , getAlignment+ , setAlignment+ + -- ** Global variables+ , addGlobal+ , getNamedGlobal+ , deleteGlobal+ , getInitializer+ , setInitializer+ , isThreadLocal+ , setThreadLocal+ , isGlobalConstant+ , setGlobalConstant+ , getFirstGlobal+ , getNextGlobal+ , getPreviousGlobal+ , getLastGlobal+ , getGlobalParent++ -- ** Functions+ , addFunction+ , getNamedFunction+ , deleteFunction+ , countParams+ , getParams+ , getParam+ , getIntrinsicID+ , getGC+ , setGC+ , getFirstFunction+ , getNextFunction+ , getPreviousFunction+ , getLastFunction+ , getFirstParam+ , getNextParam+ , getPreviousParam+ , getLastParam+ , getParamParent+ , isTailCall+ , setTailCall++ -- ** Phi nodes+ , addIncoming+ , countIncoming+ , getIncomingValue+ , getIncomingBlock++ -- ** Calling conventions+ , CallingConvention(..)+ , fromCallingConvention+ , toCallingConvention+ , getFunctionCallConv+ , setFunctionCallConv+ , getInstructionCallConv+ , setInstructionCallConv++ -- * Constants++ -- ** Scalar constants+ , constInt+ , constReal++ -- ** Composite constants+ , constArray+ , constString+ , constStruct+ , constVector++ -- ** Constant expressions+ , sizeOf+ , constNeg+ , constNot+ , constAdd+ , constSub+ , constMul+ , 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++ -- * Basic blocks+ , BasicBlock+ , BasicBlockRef+ , basicBlockAsValue+ , valueIsBasicBlock+ , valueAsBasicBlock+ , countBasicBlocks+ , getBasicBlocks+ , getEntryBasicBlock+ , appendBasicBlock+ , insertBasicBlock+ , deleteBasicBlock+ , getFirstBasicBlock+ , getNextBasicBlock+ , getPreviousBasicBlock+ , getLastBasicBlock+ , getInsertBlock+ , getBasicBlockParent++ -- * Instruction building+ , Builder+ , BuilderRef+ , createBuilder+ , disposeBuilder+ , positionBuilder+ , positionBefore+ , positionAtEnd+ , getFirstInstruction+ , getNextInstruction+ , getPreviousInstruction+ , getLastInstruction+ , getInstructionParent++ -- ** Terminators+ , buildRetVoid+ , buildRet+ , buildBr+ , buildCondBr+ , buildSwitch+ , buildInvoke+ , buildUnwind+ , buildUnreachable++ -- ** Arithmetic+ , buildAdd+ , buildSub+ , buildMul+ , buildUDiv+ , buildSDiv+ , buildFDiv+ , buildURem+ , buildSRem+ , buildFRem+ , buildShl+ , buildLShr+ , buildAShr+ , buildAnd+ , buildOr+ , buildXor+ , buildNeg+ , buildNot++ -- ** Memory+ , buildMalloc+ , buildArrayMalloc+ , buildAlloca+ , buildArrayAlloca+ , buildFree+ , buildLoad+ , buildStore+ , buildGEP++ -- ** Casts+ , buildTrunc+ , buildZExt+ , buildSExt+ , buildFPToUI+ , buildFPToSI+ , buildUIToFP+ , buildSIToFP+ , buildFPTrunc+ , buildFPExt+ , buildPtrToInt+ , buildIntToPtr+ , buildBitCast++ -- ** Comparisons+ , buildICmp+ , buildFCmp++ -- ** Miscellaneous instructions+ , buildPhi+ , buildCall+ , buildSelect+ , buildVAArg+ , buildExtractElement+ , buildInsertElement+ , buildShuffleVector++ -- ** Other helpers+ , addCase++ -- * Memory buffers+ , MemoryBuffer+ , MemoryBufferRef+ , createMemoryBufferWithContentsOfFile+ , createMemoryBufferWithSTDIN+ , disposeMemoryBuffer++ -- * Error handling+ , disposeMessage++ -- * Parameter passing+ , addInstrAttribute+ , addAttribute+ , removeInstrAttribute+ , removeAttribute+ , setInstrParamAlignment+ , setParamAlignment++ -- * Pass manager+ , PassManager+ , PassManagerRef+ , createFunctionPassManager+ , createPassManager+ , disposePassManager+ , finalizeFunctionPassManager+ , initializeFunctionPassManager+ , runFunctionPassManager+ , runPassManager++ , dumpModule+ ) where++import Foreign.C.String (CString)+import Foreign.C.Types (CDouble, CInt, CUInt, CULLong)+import Foreign.Ptr (Ptr)++#include <llvm-c/Core.h>++data Module+type ModuleRef = Ptr Module++foreign import ccall unsafe "LLVMModuleCreateWithName" moduleCreateWithName+ :: CString -> IO ModuleRef++foreign import ccall unsafe "LLVMDisposeModule" disposeModule+ :: ModuleRef -> IO ()++foreign import ccall unsafe "LLVMGetDataLayout" getDataLayout+ :: ModuleRef -> IO CString++foreign import ccall unsafe "LLVMSetDataLayout" setDataLayout+ :: ModuleRef -> CString -> IO ()+++data ModuleProvider+type ModuleProviderRef = Ptr ModuleProvider++foreign import ccall unsafe "LLVMCreateModuleProviderForExistingModule"+ createModuleProviderForExistingModule+ :: ModuleRef -> IO ModuleProviderRef++foreign import ccall unsafe "LLVMDisposeModuleProvider" disposeModuleProvider+ :: ModuleProviderRef -> IO ()+++data Type+type TypeRef = Ptr Type++foreign import ccall unsafe "LLVMInt1Type" int1Type :: TypeRef++foreign import ccall unsafe "LLVMInt8Type" int8Type :: TypeRef++foreign import ccall unsafe "LLVMInt16Type" int16Type :: TypeRef++foreign import ccall unsafe "LLVMInt32Type" int32Type :: TypeRef++foreign import ccall unsafe "LLVMInt64Type" int64Type :: TypeRef++-- | An integer type of the given width.+foreign import ccall unsafe "LLVMIntType" integerType+ :: CUInt -- ^ width in bits+ -> TypeRef++foreign import ccall unsafe "LLVMFloatType" floatType :: TypeRef++foreign import ccall unsafe "LLVMDoubleType" doubleType :: TypeRef++foreign import ccall unsafe "LLVMX86FP80Type" x86FP80Type :: TypeRef++foreign import ccall unsafe "LLVMFP128Type" fp128Type :: TypeRef++foreign import ccall unsafe "LLVMPPCFP128Type" ppcFP128Type :: TypeRef++foreign import ccall unsafe "LLVMVoidType" voidType :: TypeRef++-- | Create a function type.+foreign import ccall unsafe "LLVMFunctionType" functionType+ :: TypeRef -- ^ return type+ -> Ptr TypeRef -- ^ array of argument types+ -> CUInt -- ^ number of elements in array+ -> CInt -- ^ non-zero if function is varargs+ -> TypeRef++-- | Indicate whether a function takes varargs.+foreign import ccall unsafe "LLVMIsFunctionVarArg" isFunctionVarArg+ :: TypeRef -> CInt++-- | Give a function's return type.+foreign import ccall unsafe "LLVMGetReturnType" getReturnType+ :: TypeRef -> TypeRef++-- | Give the number of fixed parameters that a function takes.+foreign import ccall unsafe "LLVMCountParamTypes" countParamTypes+ :: TypeRef -> CUInt++-- | Fill out an array with the types of a function's fixed+-- parameters.+foreign import ccall unsafe "LLVMGetParamTypes" getParamTypes+ :: TypeRef -> Ptr TypeRef -> IO ()++foreign import ccall unsafe "LLVMArrayType" arrayType+ :: TypeRef -- ^ element type+ -> CUInt -- ^ element count+ -> TypeRef++foreign import ccall unsafe "LLVMPointerType" pointerType+ :: TypeRef -- ^ pointed-to type+ -> CUInt -- ^ address space+ -> TypeRef++foreign import ccall unsafe "LLVMVectorType" vectorType+ :: TypeRef -- ^ element type+ -> CUInt -- ^ element count+ -> TypeRef++foreign import ccall unsafe "LLVMAddTypeName" addTypeName+ :: ModuleRef -> CString -> TypeRef -> IO CInt++foreign import ccall unsafe "LLVMDeleteTypeName" deleteTypeName+ :: ModuleRef -> CString -> IO ()++-- | Give the type of a sequential type's elements.+foreign import ccall unsafe "LLVMGetElementType" getElementType+ :: TypeRef -> TypeRef+++data Value+type ValueRef = Ptr Value++foreign import ccall unsafe "LLVMAddGlobal" addGlobal+ :: ModuleRef -> TypeRef -> CString -> IO ValueRef++foreign import ccall unsafe "LLVMDeleteGlobal" deleteGlobal+ :: ValueRef -> IO ()++foreign import ccall unsafe "LLVMSetInitializer" setInitializer+ :: ValueRef -> ValueRef -> IO ()++foreign import ccall unsafe "LLVMGetNamedGlobal" getNamedGlobal+ :: ModuleRef -> CString -> IO ValueRef++foreign import ccall unsafe "LLVMGetInitializer" getInitializer+ :: ValueRef -> IO ValueRef++foreign import ccall unsafe "LLVMIsThreadLocal" isThreadLocal+ :: ValueRef -> IO CInt++foreign import ccall unsafe "LLVMSetThreadLocal" setThreadLocal+ :: ValueRef -> CInt -> IO ()++foreign import ccall unsafe "LLVMIsGlobalConstant" isGlobalConstant+ :: ValueRef -> IO CInt++foreign import ccall unsafe "LLVMSetGlobalConstant" setGlobalConstant+ :: ValueRef -> CInt -> IO ()++foreign import ccall unsafe "LLVMTypeOf" typeOf+ :: ValueRef -> IO TypeRef++foreign import ccall unsafe "LLVMGetValueName" getValueName+ :: ValueRef -> IO CString++foreign import ccall unsafe "LLVMSetValueName" setValueName+ :: ValueRef -> CString -> IO ()++foreign import ccall unsafe "LLVMDumpValue" dumpValue+ :: ValueRef -> IO ()++foreign import ccall unsafe "LLVMConstAllOnes" constAllOnes+ :: TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstArray" constArray+ :: TypeRef -> Ptr ValueRef -> CUInt -> ValueRef++foreign import ccall unsafe "LLVMConstNull" constNull+ :: TypeRef -> ValueRef++foreign import ccall unsafe "LLVMIsConstant" isConstant+ :: ValueRef -> IO CInt++foreign import ccall unsafe "LLVMGetUndef" getUndef+ :: TypeRef -> ValueRef++foreign import ccall unsafe "LLVMIsNull" isNull+ :: ValueRef -> IO CInt++foreign import ccall unsafe "LLVMIsUndef" isUndef+ :: ValueRef -> IO CInt++foreign import ccall unsafe "LLVMGetNamedFunction" getNamedFunction+ :: ModuleRef -- ^ module+ -> CString -- ^ name+ -> IO ValueRef -- ^ function (@nullPtr@ if not found)++foreign import ccall unsafe "LLVMAddFunction" addFunction+ :: ModuleRef -- ^ module+ -> CString -- ^ name+ -> TypeRef -- ^ type+ -> IO ValueRef++foreign import ccall unsafe "LLVMDeleteFunction" deleteFunction+ :: ValueRef -- ^ function+ -> IO ()++foreign import ccall unsafe "LLVMCountParams" countParams+ :: ValueRef -- ^ function+ -> CUInt++foreign import ccall unsafe "LLVMGetParam" getParam+ :: ValueRef -- ^ function+ -> CUInt -- ^ offset into array+ -> ValueRef++foreign import ccall unsafe "LLVMGetParams" getParams+ :: ValueRef -- ^ function+ -> Ptr ValueRef -- ^ array to fill out+ -> IO ()++foreign import ccall unsafe "LLVMGetIntrinsicID" getIntrinsicID+ :: ValueRef -- ^ function+ -> CUInt++data CallingConvention = C+ | Fast+ | Cold+ | X86StdCall+ | X86FastCall+ deriving (Eq, Show)++fromCallingConvention :: CallingConvention -> CUInt+fromCallingConvention C = (#const LLVMCCallConv)+fromCallingConvention Fast = (#const LLVMFastCallConv)+fromCallingConvention Cold = (#const LLVMColdCallConv)+fromCallingConvention X86StdCall = (#const LLVMX86FastcallCallConv)+fromCallingConvention X86FastCall = (#const LLVMX86StdcallCallConv)++toCallingConvention :: CUInt -> CallingConvention+toCallingConvention c | c == (#const LLVMCCallConv) = C+toCallingConvention c | c == (#const LLVMFastCallConv) = Fast+toCallingConvention c | c == (#const LLVMColdCallConv) = Cold+toCallingConvention c | c == (#const LLVMX86StdcallCallConv) = X86StdCall+toCallingConvention c | c == (#const LLVMX86FastcallCallConv) = X86FastCall+toCallingConvention c = error $ "LLVM.Core.FFI.toCallingConvention: " +++ "unsupported calling convention" ++ show c++foreign import ccall unsafe "LLVMGetFunctionCallConv" getFunctionCallConv+ :: ValueRef -- ^ function+ -> IO CUInt++foreign import ccall unsafe "LLVMSetFunctionCallConv" setFunctionCallConv+ :: ValueRef -- ^ function+ -> CUInt+ -> IO ()++foreign import ccall unsafe "LLVMGetGC" getGC+ :: ValueRef -> IO CString++foreign import ccall unsafe "LLVMSetGC" setGC+ :: ValueRef -> CString -> IO ()++foreign import ccall unsafe "LLVMIsDeclaration" isDeclaration+ :: ValueRef -> IO CInt++type Linkage = CUInt++foreign import ccall unsafe "LLVMGetLinkage" getLinkage+ :: ValueRef -> IO Linkage++foreign import ccall unsafe "LLVMSetLinkage" setLinkage+ :: ValueRef -> Linkage -> IO ()++foreign import ccall unsafe "LLVMGetSection" getSection+ :: ValueRef -> IO CString++foreign import ccall unsafe "LLVMSetSection" setSection+ :: ValueRef -> CString -> IO ()++type Visibility = CUInt++foreign import ccall unsafe "LLVMGetVisibility" getVisibility+ :: ValueRef -> IO Visibility++foreign import ccall unsafe "LLVMSetVisibility" setVisibility+ :: ValueRef -> Visibility -> IO ()++foreign import ccall unsafe "LLVMGetAlignment" getAlignment+ :: ValueRef -> IO CUInt++foreign import ccall unsafe "LLVMSetAlignment" setAlignment+ :: ValueRef -> CUInt -> IO ()+++foreign import ccall unsafe "LLVMConstInt" constInt+ :: TypeRef -> CULLong -> CInt -> ValueRef++foreign import ccall unsafe "LLVMConstReal" constReal+ :: TypeRef -> CDouble -> ValueRef++foreign import ccall unsafe "LLVMConstString" constString+ :: CString -> CUInt -> CInt -> ValueRef++foreign import ccall unsafe "LLVMConstStruct" constStruct+ :: Ptr ValueRef -> CUInt -> CInt -> ValueRef++foreign import ccall unsafe "LLVMConstVector" constVector+ :: Ptr ValueRef -> CUInt -> ValueRef++foreign import ccall unsafe "LLVMConstNeg" constNeg+ :: ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstNot" constNot+ :: ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstAdd" constAdd+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstSub" constSub+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstMul" constMul+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstUDiv" constUDiv+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstSDiv" constSDiv+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstFDiv" constFDiv+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstURem" constURem+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstSRem" constSRem+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstFRem" constFRem+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstAnd" constAnd+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstOr" constOr+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstXor" constXor+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstICmp" constICmp+ :: CInt -> ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstFCmp" constFCmp+ :: CInt -> ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstShl" constShl+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstLShr" constLShr+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstAShr" constAShr+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstGEP" constGEP+ :: ValueRef -> Ptr ValueRef -> CUInt -> ValueRef++foreign import ccall unsafe "LLVMConstTrunc" constTrunc+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstSExt" constSExt+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstZExt" constZExt+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstFPTrunc" constFPTrunc+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstFPExt" constFPExt+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstUIToFP" constUIToFP+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstSIToFP" constSIToFP+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstFPToUI" constFPToUI+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstFPToSI" constFPToSI+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstPtrToInt" constPtrToInt+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstIntToPtr" constIntToPtr+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstBitCast" constBitCast+ :: ValueRef -> TypeRef -> ValueRef++foreign import ccall unsafe "LLVMConstSelect" constSelect+ :: ValueRef -> ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstExtractElement" constExtractElement+ :: ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstInsertElement" constInsertElement+ :: ValueRef -> ValueRef -> ValueRef -> ValueRef++foreign import ccall unsafe "LLVMConstShuffleVector" constShuffleVector+ :: ValueRef -> ValueRef -> ValueRef -> ValueRef++type BasicBlock = Value+type BasicBlockRef = Ptr BasicBlock++foreign import ccall unsafe "LLVMBasicBlockAsValue" basicBlockAsValue+ :: BasicBlockRef -> ValueRef++foreign import ccall unsafe "LLVMValueIsBasicBlock" valueIsBasicBlock+ :: ValueRef -> Bool++foreign import ccall unsafe "LLVMValueAsBasicBlock" valueAsBasicBlock+ :: ValueRef -- ^ basic block+ -> BasicBlockRef++foreign import ccall unsafe "LLVMCountBasicBlocks" countBasicBlocks+ :: ValueRef -- ^ function+ -> IO CUInt++foreign import ccall unsafe "LLVMGetBasicBlocks" getBasicBlocks+ :: ValueRef -- ^ function+ -> Ptr BasicBlockRef -- ^ array to fill out+ -> IO ()++foreign import ccall unsafe "LLVMGetEntryBasicBlock" getEntryBasicBlock+ :: ValueRef -- ^ function+ -> IO BasicBlockRef++foreign import ccall unsafe "LLVMAppendBasicBlock" appendBasicBlock+ :: ValueRef -- ^ function+ -> CString -- ^ name for label+ -> IO BasicBlockRef++foreign import ccall unsafe "LLVMInsertBasicBlock" insertBasicBlock+ :: BasicBlockRef -- ^ insert before this one+ -> CString -- ^ name for label+ -> IO BasicBlockRef++foreign import ccall unsafe "LLVMDeleteBasicBlock" deleteBasicBlock+ :: BasicBlockRef -> IO ()++data Builder+type BuilderRef = Ptr Builder++foreign import ccall unsafe "LLVMCreateBuilder" createBuilder+ :: IO BuilderRef++foreign import ccall unsafe "LLVMDisposeBuilder" disposeBuilder+ :: BuilderRef -> IO ()++foreign import ccall unsafe "LLVMPositionBuilderBefore" positionBefore+ :: BuilderRef -> ValueRef -> IO ()++foreign import ccall unsafe "LLVMPositionBuilderAtEnd" positionAtEnd+ :: BuilderRef -> BasicBlockRef -> IO ()++foreign import ccall unsafe "LLVMBuildRetVoid" buildRetVoid+ :: BuilderRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildRet" buildRet+ :: BuilderRef -> ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildBr" buildBr+ :: BuilderRef -> BasicBlockRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildCondBr" buildCondBr+ :: BuilderRef -> ValueRef -> BasicBlockRef -> BasicBlockRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSwitch" buildSwitch+ :: BuilderRef -> ValueRef -> BasicBlockRef -> CUInt -> IO ValueRef+foreign import ccall unsafe "LLVMBuildInvoke" buildInvoke+ :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt+ -> BasicBlockRef -> BasicBlockRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildUnwind" buildUnwind+ :: BuilderRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildUnreachable" buildUnreachable+ :: BuilderRef -> IO ValueRef++foreign import ccall unsafe "LLVMBuildAdd" buildAdd+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSub" buildSub+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildMul" buildMul+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildUDiv" buildUDiv+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSDiv" buildSDiv+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFDiv" buildFDiv+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildURem" buildURem+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSRem" buildSRem+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFRem" buildFRem+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildShl" buildShl+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildLShr" buildLShr+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildAShr" buildAShr+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildAnd" buildAnd+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildOr" buildOr+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildXor" buildXor+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildNeg" buildNeg+ :: BuilderRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildNot" buildNot+ :: BuilderRef -> ValueRef -> CString -> IO ValueRef++-- Memory+foreign import ccall unsafe "LLVMBuildMalloc" buildMalloc+ :: BuilderRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildArrayMalloc" buildArrayMalloc+ :: BuilderRef -> TypeRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildAlloca" buildAlloca+ :: BuilderRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildArrayAlloca" buildArrayAlloca+ :: BuilderRef -> TypeRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFree" buildFree+ :: BuilderRef -> ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildLoad" buildLoad+ :: BuilderRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildStore" buildStore+ :: BuilderRef -> ValueRef -> ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMBuildGEP" buildGEP+ :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt -> CString+ -> IO ValueRef++-- Casts+foreign import ccall unsafe "LLVMBuildTrunc" buildTrunc+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildZExt" buildZExt+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSExt" buildSExt+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFPToUI" buildFPToUI+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFPToSI" buildFPToSI+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildUIToFP" buildUIToFP+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSIToFP" buildSIToFP+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFPTrunc" buildFPTrunc+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFPExt" buildFPExt+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildPtrToInt" buildPtrToInt+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildIntToPtr" buildIntToPtr+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildBitCast" buildBitCast+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef++-- Comparisons+foreign import ccall unsafe "LLVMBuildICmp" buildICmp+ :: BuilderRef -> CInt -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildFCmp" buildFCmp+ :: BuilderRef -> CInt -> ValueRef -> ValueRef -> CString -> IO ValueRef++-- Miscellaneous instructions+foreign import ccall unsafe "LLVMBuildPhi" buildPhi+ :: BuilderRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildCall" buildCall+ :: BuilderRef -> ValueRef -> Ptr ValueRef -> CUInt -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildSelect" buildSelect+ :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildVAArg" buildVAArg+ :: BuilderRef -> ValueRef -> TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildExtractElement" buildExtractElement+ :: BuilderRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildInsertElement" buildInsertElement+ :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMBuildShuffleVector" buildShuffleVector+ :: BuilderRef -> ValueRef -> ValueRef -> ValueRef -> CString -> IO ValueRef++foreign import ccall unsafe "LLVMAddCase" addCase+ :: ValueRef -> ValueRef -> BasicBlockRef -> IO ()++foreign import ccall unsafe "LLVMCountIncoming" countIncoming+ :: ValueRef -> IO CUInt+foreign import ccall unsafe "LLVMAddIncoming" addIncoming+ :: ValueRef -> Ptr ValueRef -> Ptr ValueRef -> CUInt -> IO ()+foreign import ccall unsafe "LLVMGetIncomingValue" getIncomingValue+ :: ValueRef -> CUInt -> IO ValueRef+foreign import ccall unsafe "LLVMGetIncomingBlock" getIncomingBlock+ :: ValueRef -> CUInt -> IO BasicBlockRef+ +foreign import ccall unsafe "LLVMGetInstructionCallConv" getInstructionCallConv+ :: ValueRef -> IO CUInt+foreign import ccall unsafe "LLVMSetInstructionCallConv" setInstructionCallConv+ :: ValueRef -> CUInt -> IO ()++foreign import ccall unsafe "LLVMStructType" structType+ :: (Ptr TypeRef) -> CUInt -> CInt -> IO TypeRef+foreign import ccall unsafe "LLVMCountStructElementTypes"+ countStructElementTypes :: TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMGetStructElementTypes" getStructElementTypes+ :: TypeRef -> (Ptr TypeRef) -> IO ()+foreign import ccall unsafe "LLVMIsPackedStruct" isPackedStruct+ :: TypeRef -> IO CInt++data MemoryBuffer+type MemoryBufferRef = Ptr MemoryBuffer++data TypeHandle+type TypeHandleRef = Ptr TypeHandle++type TypeKind = CUInt++foreign import ccall unsafe "LLVMCreateMemoryBufferWithContentsOfFile" createMemoryBufferWithContentsOfFile+ :: CString -> Ptr MemoryBufferRef -> Ptr CString -> IO CInt+foreign import ccall unsafe "LLVMCreateMemoryBufferWithSTDIN" createMemoryBufferWithSTDIN+ :: Ptr MemoryBufferRef -> Ptr CString -> IO CInt+foreign import ccall unsafe "LLVMCreateTypeHandle" createTypeHandle+ :: TypeRef -> IO TypeHandleRef+foreign import ccall unsafe "LLVMDisposeMemoryBuffer" disposeMemoryBuffer+ :: MemoryBufferRef -> IO ()+foreign import ccall unsafe "LLVMDisposeMessage" disposeMessage+ :: CString -> IO ()+foreign import ccall unsafe "LLVMDisposeTypeHandle" disposeTypeHandle+ :: TypeHandleRef -> IO ()+foreign import ccall unsafe "LLVMGetArrayLength" getArrayLength+ :: TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMGetIntTypeWidth" getIntTypeWidth+ :: TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMGetPointerAddressSpace" getPointerAddressSpace+ :: TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMGetTarget" getTarget+ :: ModuleRef -> IO CString+foreign import ccall unsafe "LLVMGetTypeKind" getTypeKind+ :: TypeRef -> IO TypeKind+foreign import ccall unsafe "LLVMGetVectorSize" getVectorSize+ :: TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMRefineType" refineType+ :: TypeRef -> TypeRef -> IO ()+foreign import ccall unsafe "LLVMResolveTypeHandle" resolveTypeHandle+ :: TypeHandleRef -> IO TypeRef+foreign import ccall unsafe "LLVMSetTarget" setTarget+ :: ModuleRef -> CString -> IO ()+foreign import ccall unsafe "LLVMSizeOf" sizeOf+ :: TypeRef -> IO ValueRef++{-+typedef enum {+ LLVMZExtAttribute = 1<<0,+ LLVMSExtAttribute = 1<<1,+ LLVMNoReturnAttribute = 1<<2,+ LLVMInRegAttribute = 1<<3,+ LLVMStructRetAttribute = 1<<4,+ LLVMNoUnwindAttribute = 1<<5,+ LLVMNoAliasAttribute = 1<<6,+ LLVMByValAttribute = 1<<7,+ LLVMNestAttribute = 1<<8,+ LLVMReadNoneAttribute = 1<<9,+ LLVMReadOnlyAttribute = 1<<10+} LLVMAttribute;+-}+type Attribute = CInt++data PassManager+type PassManagerRef = Ptr PassManager++foreign import ccall unsafe "LLVMConstRealOfString" constRealOfString+ :: TypeRef -> CString -> IO ValueRef+foreign import ccall unsafe "LLVMCreateFunctionPassManager" createFunctionPassManager+ :: ModuleProviderRef -> IO PassManagerRef+foreign import ccall unsafe "LLVMCreatePassManager" createPassManager+ :: IO PassManagerRef+foreign import ccall unsafe "LLVMDisposePassManager" disposePassManager+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMDumpModule" dumpModule+ :: ModuleRef -> IO ()+foreign import ccall unsafe "LLVMFinalizeFunctionPassManager" finalizeFunctionPassManager+ :: PassManagerRef -> IO CInt+foreign import ccall unsafe "LLVMGetBasicBlockParent" getBasicBlockParent+ :: BasicBlockRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetFirstBasicBlock" getFirstBasicBlock+ :: ValueRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetFirstFunction" getFirstFunction+ :: ModuleRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetFirstGlobal" getFirstGlobal+ :: ModuleRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetFirstInstruction" getFirstInstruction+ :: BasicBlockRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetFirstParam" getFirstParam+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetGlobalParent" getGlobalParent+ :: ValueRef -> IO ModuleRef+foreign import ccall unsafe "LLVMGetInsertBlock" getInsertBlock+ :: BuilderRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetInstructionParent" getInstructionParent+ :: ValueRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetLastBasicBlock" getLastBasicBlock+ :: ValueRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetLastFunction" getLastFunction+ :: ModuleRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetLastGlobal" getLastGlobal+ :: ModuleRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetLastInstruction" getLastInstruction+ :: BasicBlockRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetLastParam" getLastParam+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetNextBasicBlock" getNextBasicBlock+ :: BasicBlockRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetNextFunction" getNextFunction+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetNextGlobal" getNextGlobal+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetNextInstruction" getNextInstruction+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetNextParam" getNextParam+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetParamParent" getParamParent+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetPreviousBasicBlock" getPreviousBasicBlock+ :: BasicBlockRef -> IO BasicBlockRef+foreign import ccall unsafe "LLVMGetPreviousFunction" getPreviousFunction+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetPreviousGlobal" getPreviousGlobal+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetPreviousInstruction" getPreviousInstruction+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMGetPreviousParam" getPreviousParam+ :: ValueRef -> IO ValueRef+foreign import ccall unsafe "LLVMInitializeFunctionPassManager" initializeFunctionPassManager+ :: PassManagerRef -> IO CInt+foreign import ccall unsafe "LLVMLabelType" labelType+ :: IO TypeRef+foreign import ccall unsafe "LLVMOpaqueType" opaqueType+ :: IO TypeRef+foreign import ccall unsafe "LLVMPositionBuilder" positionBuilder+ :: BuilderRef -> BasicBlockRef -> ValueRef -> IO ()+foreign import ccall unsafe "LLVMRunFunctionPassManager" runFunctionPassManager+ :: PassManagerRef -> ValueRef -> IO CInt+foreign import ccall unsafe "LLVMRunPassManager" runPassManager+ :: PassManagerRef -> ModuleRef -> IO CInt+foreign import ccall unsafe "LLVMSetInstrParamAlignment" setInstrParamAlignment+ :: ValueRef -> CUInt -> CUInt -> IO ()+foreign import ccall unsafe "LLVMSetParamAlignment" setParamAlignment+ :: ValueRef -> CUInt -> IO ()+foreign import ccall unsafe "LLVMAddAttribute" addAttribute+ :: ValueRef -> Attribute -> IO ()+foreign import ccall unsafe "LLVMAddInstrAttribute" addInstrAttribute+ :: ValueRef -> CUInt -> Attribute -> IO ()+foreign import ccall unsafe "LLVMIsTailCall" isTailCall+ :: ValueRef -> IO CInt+foreign import ccall unsafe "LLVMRemoveAttribute" removeAttribute+ :: ValueRef -> Attribute -> IO ()+foreign import ccall unsafe "LLVMRemoveInstrAttribute" removeInstrAttribute+ :: ValueRef -> CUInt -> Attribute -> IO ()+foreign import ccall unsafe "LLVMSetTailCall" setTailCall+ :: ValueRef -> CInt -> IO ()
+ LLVM/FFI/ExecutionEngine.hsc view
@@ -0,0 +1,110 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.ExecutionEngine+ (+ -- * Execution engines+ ExecutionEngine+ , createExecutionEngine+ , disposeExecutionEngine+ , createInterpreter+ , createJITCompiler+ , addModuleProvider+ , removeModuleProvider+ , findFunction+ , freeMachineCodeForFunction+ , runStaticConstructors+ , runStaticDestructors+ , runFunction+ , runFunctionAsMain+ , getExecutionEngineTargetData+ , addGlobalMapping++ -- * Generic values+ , GenericValue+ , GenericValueRef+ , createGenericValueOfInt+ , genericValueToInt+ , genericValueIntWidth+ , createGenericValueOfFloat+ , genericValueToFloat+ , createGenericValueOfPointer+ , genericValueToPointer+ , disposeGenericValue+ ) where++import Foreign.C.String (CString)+import Foreign.C.Types (CDouble, CInt, CUInt, CULLong)+import Foreign.Ptr (Ptr)++import LLVM.FFI.Core (ModuleRef, ModuleProviderRef, TypeRef, ValueRef)+import LLVM.FFI.Target(TargetDataRef)++data ExecutionEngine+type ExecutionEngineRef = Ptr ExecutionEngine++foreign import ccall unsafe "LLVMCreateExecutionEngine" createExecutionEngine+ :: Ptr ExecutionEngineRef -> ModuleProviderRef -> Ptr CString+ -> IO CInt++foreign import ccall unsafe "LLVMDisposeExecutionEngine" disposeExecutionEngine+ :: ExecutionEngineRef -> IO ()++foreign import ccall unsafe "LLVMRunStaticConstructors" runStaticConstructors+ :: ExecutionEngineRef -> IO ()++foreign import ccall unsafe "LLVMRunStaticDestructors" runStaticDestructors+ :: ExecutionEngineRef -> IO ()+++data GenericValue+type GenericValueRef = Ptr GenericValue++foreign import ccall unsafe "LLVMCreateGenericValueOfInt"+ createGenericValueOfInt :: TypeRef -> CULLong -> CInt+ -> IO GenericValueRef++foreign import ccall unsafe "LLVMGenericValueToInt" genericValueToInt+ :: GenericValueRef -> CInt -> CULLong++foreign import ccall unsafe "LLVMCreateGenericValueOfFloat"+ createGenericValueOfFloat :: TypeRef -> CDouble -> IO GenericValueRef++foreign import ccall unsafe "LLVMGenericValueToFloat" genericValueToFloat+ :: GenericValueRef -> CDouble++foreign import ccall unsafe "LLVMDisposeGenericValue" disposeGenericValue+ :: GenericValueRef -> IO ()++foreign import ccall unsafe "LLVMRunFunction" runFunction+ :: ExecutionEngineRef -> ValueRef -> CUInt+ -> Ptr GenericValueRef -> IO GenericValueRef++foreign import ccall unsafe "LLVMAddModuleProvider" addModuleProvider+ :: ExecutionEngineRef -> ModuleProviderRef -> IO ()+foreign import ccall unsafe "LLVMCreateGenericValueOfPointer"+ createGenericValueOfPointer :: Ptr a -> IO GenericValueRef+foreign import ccall unsafe "LLVMCreateInterpreter" createInterpreter+ :: Ptr ExecutionEngineRef -> ModuleProviderRef -> Ptr CString -> IO CInt+foreign import ccall unsafe "LLVMCreateJITCompiler" createJITCompiler+ :: Ptr ExecutionEngineRef -> ModuleProviderRef -> Ptr CString -> IO CInt+foreign import ccall unsafe "LLVMFindFunction" findFunction+ :: ExecutionEngineRef -> CString -> Ptr ValueRef -> IO CInt+foreign import ccall unsafe "LLVMFreeMachineCodeForFunction"+ freeMachineCodeForFunction :: ExecutionEngineRef -> ValueRef -> IO ()+foreign import ccall unsafe "LLVMGenericValueIntWidth" genericValueIntWidth+ :: GenericValueRef -> IO CUInt+foreign import ccall unsafe "LLVMGenericValueToPointer" genericValueToPointer+ :: GenericValueRef -> IO (Ptr a)+foreign import ccall unsafe "LLVMRemoveModuleProvider" removeModuleProvider+ :: ExecutionEngineRef -> ModuleProviderRef -> Ptr ModuleRef -> Ptr CString+ -> IO CInt+foreign import ccall unsafe "LLVMRunFunctionAsMain" runFunctionAsMain+ :: ExecutionEngineRef -> ValueRef -> CUInt+ -> Ptr CString -- ^ argv+ -> Ptr CString -- ^ envp+ -> IO CInt++foreign import ccall unsafe "LLVMGetExecutionEngineTargetData" getExecutionEngineTargetData+ :: ExecutionEngineRef -> IO TargetDataRef+foreign import ccall unsafe "LLVMAddGlobalMapping" addGlobalMapping+ :: ExecutionEngineRef -> ValueRef -> Ptr () -> IO ()
+ LLVM/FFI/Target.hsc view
@@ -0,0 +1,50 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.Target where+import Foreign.C.String (CString)+import Foreign.C.Types (CInt, CUInt, CULLong)+import Foreign.Ptr (Ptr)++import LLVM.FFI.Core++-- enum { LLVMBigEndian, LLVMLittleEndian };+type ByteOrdering = CInt;++data TargetData+type TargetDataRef = Ptr TargetData++foreign import ccall unsafe "LLVMABIAlignmentOfType" aBIAlignmentOfType+ :: TargetDataRef -> TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMABISizeOfType" aBISizeOfType+ :: TargetDataRef -> TypeRef -> IO CULLong+foreign import ccall unsafe "LLVMAddTargetData" addTargetData+ :: TargetDataRef -> PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMByteOrder" byteOrder+ :: TargetDataRef -> IO ByteOrdering+foreign import ccall unsafe "LLVMCallFrameAlignmentOfType" callFrameAlignmentOfType+ :: TargetDataRef -> TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMCopyStringRepOfTargetData" copyStringRepOfTargetData+ :: TargetDataRef -> IO CString+foreign import ccall unsafe "LLVMCreateTargetData" createTargetData+ :: CString -> IO TargetDataRef+foreign import ccall unsafe "LLVMDisposeTargetData" disposeTargetData+ :: TargetDataRef -> IO ()+foreign import ccall unsafe "LLVMElementAtOffset" elementAtOffset+ :: TargetDataRef -> TypeRef -> CULLong -> IO CUInt+foreign import ccall unsafe "LLVMIntPtrType" intPtrType+ :: TargetDataRef -> IO TypeRef+foreign import ccall unsafe "LLVMInvalidateStructLayout" invalidateStructLayout+ :: TargetDataRef -> TypeRef -> IO ()+foreign import ccall unsafe "LLVMOffsetOfElement" offsetOfElement+ :: TargetDataRef -> TypeRef -> CUInt -> IO CULLong+foreign import ccall unsafe "LLVMPointerSize" pointerSize+ :: TargetDataRef -> IO CUInt+foreign import ccall unsafe "LLVMPreferredAlignmentOfGlobal" preferredAlignmentOfGlobal+ :: TargetDataRef -> ValueRef -> IO CUInt+foreign import ccall unsafe "LLVMPreferredAlignmentOfType" preferredAlignmentOfType+ :: TargetDataRef -> TypeRef -> IO CUInt+foreign import ccall unsafe "LLVMSizeOfTypeInBits" sizeOfTypeInBits+ :: TargetDataRef -> TypeRef -> IO CULLong+foreign import ccall unsafe "LLVMStoreSizeOfType" storeSizeOfType+ :: TargetDataRef -> TypeRef -> IO CULLong+
+ LLVM/FFI/Transforms/Scalar.hsc view
@@ -0,0 +1,29 @@+{-# LANGUAGE ForeignFunctionInterface, EmptyDataDecls #-}++module LLVM.FFI.Transforms.Scalar(+ addCFGSimplificationPass+ , addConstantPropagationPass+ , addDemoteMemoryToRegisterPass+ , addGVNPass+ , addInstructionCombiningPass+ , addPromoteMemoryToRegisterPass+ , addReassociatePass+ ) where++import LLVM.FFI.Core++foreign import ccall unsafe "LLVMAddCFGSimplificationPass" addCFGSimplificationPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddConstantPropagationPass" addConstantPropagationPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddDemoteMemoryToRegisterPass" addDemoteMemoryToRegisterPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddGVNPass" addGVNPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddInstructionCombiningPass" addInstructionCombiningPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddPromoteMemoryToRegisterPass" addPromoteMemoryToRegisterPass+ :: PassManagerRef -> IO ()+foreign import ccall unsafe "LLVMAddReassociatePass" addReassociatePass+ :: PassManagerRef -> IO ()+
Makefile view
@@ -1,8 +1,9 @@ ghc := ghc ghcflags := -Wall -Werror -llvm_prefix ?= $(HOME)-prefix ?= $(HOME)+LLVMLIB=/usr/local+llvm_prefix ?= $(LLVMLIB)+prefix ?= $(LLVMLIB) _lib := $(shell test -d /usr/lib64 && echo lib64 || echo lib) ifeq ($(prefix),$(HOME))@@ -29,6 +30,13 @@ examples: $(MAKE) -C examples +.PHONY: tests+tests:+ $(MAKE) -C tests++doc haddock: dist/setup-config+ ./setup haddock+ sdist: dist/setup-config ./setup sdist @@ -37,8 +45,11 @@ ./setup install clean:- -rm -f Setup.hi Setup.hi+ -$(MAKE) -C examples clean+ -$(MAKE) -C tests clean+ -rm -f Setup.hi Setup.o -./setup clean+ -rm setup distclean: clean -rm -f setup configure
README.txt view
@@ -11,29 +11,24 @@ Package status - what to expect ------------------------------- -This package is under heavy development. I've released it quite early-in order to solicit comments and help from interested parties.--The bindings are currently incomplete, so there are some severe limits-on what you can do. Adding new functions is generally easy, though,-so don't be afraid to get your hands dirty.+This package is still under development. -Also, the type safety of various functions is a bit dubious. The-underlying C bindings to LLVM throw away almost all type information,-so we have to reconstruct types in Haskell. I'm still working on-straightening things out.+The high level bindings are currently incomplete, so there are some+limits on what you can do. Adding new functions is generally easy,+though, so don't be afraid to get your hands dirty. -Please expect the sands to shift under your feet quite rapidly for a-little while as I add functionality, improve the interfaces, and-generally flesh the bindings out to be thoroughly useful.+The high level interface is mostly safe, but the type system does not+protect against anything that can go wrong, so take care.+And, of course, there's no way to guarantee anything about the+generated code. Jump in and help! ----------------- -I welcome your comments and contributions. You can send email to me-at <bos@serpentine.com>. If you want to send patches, please get a-copy of the darcs repository:+We welcome your comments and contributions. You can send email to us+at <bos@serpentine.com> or <lennart@augustsson.net>. If you want to+send patches, please get a copy of the darcs repository: darcs get http://darcs.serpentine.com/llvm
Setup.lhs view
@@ -1,3 +1,3 @@ #!/usr/bin/env runhaskell > import Distribution.Simple-> main = defaultMainWithHooks defaultUserHooks+> main = defaultMainWithHooks autoconfUserHooks
configure view
@@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles.-# Generated by GNU Autoconf 2.61 for Haskell LLVM bindings 0.0.2.+# Generated by GNU Autoconf 2.61 for Haskell LLVM bindings 0.4.0.0. # # Report bugs to <bos@serpentine.com>. #@@ -574,8 +574,8 @@ # Identity of this package. PACKAGE_NAME='Haskell LLVM bindings' PACKAGE_TARNAME='llvm'-PACKAGE_VERSION='0.0.2'-PACKAGE_STRING='Haskell LLVM bindings 0.0.2'+PACKAGE_VERSION='0.4.0.0'+PACKAGE_STRING='Haskell LLVM bindings 0.4.0.0' PACKAGE_BUGREPORT='bos@serpentine.com' ac_unique_file="LLVM/ExecutionEngine.hs"@@ -666,7 +666,10 @@ CPP GREP EGREP-llvm_cppflags llvm_engine_libs llvm_includedir llvm_ldflags+llvm_cppflags+llvm_engine_libs+llvm_includedir+llvm_ldflags LIBOBJS LTLIBOBJS' ac_subst_files=''@@ -1184,7 +1187,7 @@ # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF-\`configure' configures Haskell LLVM bindings 0.0.2 to adapt to many kinds of systems.+\`configure' configures Haskell LLVM bindings 0.4.0.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1245,13 +1248,14 @@ if test -n "$ac_init_help"; then case $ac_init_help in- short | recursive ) echo "Configuration of Haskell LLVM bindings 0.0.2:";;+ short | recursive ) echo "Configuration of Haskell LLVM bindings 0.4.0.0:";; esac cat <<\_ACEOF Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)+ --with-compiler use the given Haskell compiler --with-llvm-prefix use the version of LLVM at the given location --with-llvm-bindir use LLVM binaries at the given location @@ -1331,7 +1335,7 @@ test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF-Haskell LLVM bindings configure 0.0.2+Haskell LLVM bindings configure 0.4.0.0 generated by GNU Autoconf 2.61 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,@@ -1345,7 +1349,7 @@ This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by Haskell LLVM bindings $as_me 0.0.2, which was+It was created by Haskell LLVM bindings $as_me 0.4.0.0, which was generated by GNU Autoconf 2.61. Invocation command line was $ $0 $@@@ -2313,11 +2317,19 @@ +# Check whether --with-compiler was given.+if test "${with_compiler+set}" = set; then+ withval=$with_compiler; compiler="$withval"+else+ compiler=ghc+fi++ # Check whether --with-llvm_prefix was given. if test "${with_llvm_prefix+set}" = set; then withval=$with_llvm_prefix; llvm_prefix="$withval" else- llvm_prefix=/usr/local+ llvm_prefix="$prefix" fi @@ -3927,6 +3939,9 @@ +++ cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure@@ -4353,7 +4368,7 @@ # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log="-This file was extended by Haskell LLVM bindings $as_me 0.0.2, which was+This file was extended by Haskell LLVM bindings $as_me 0.4.0.0, which was generated by GNU Autoconf 2.61. Invocation command line was CONFIG_FILES = $CONFIG_FILES@@ -4396,7 +4411,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF ac_cs_version="\\-Haskell LLVM bindings config.status 0.0.2+Haskell LLVM bindings config.status 0.4.0.0 configured by $0, generated by GNU Autoconf 2.61, with options \\"`echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
configure.ac view
@@ -1,4 +1,4 @@-AC_INIT([Haskell LLVM bindings], [0.0.2], [bos@serpentine.com], [llvm])+AC_INIT([Haskell LLVM bindings], [0.4.0.0], [bos@serpentine.com], [llvm]) AC_CONFIG_SRCDIR([LLVM/ExecutionEngine.hs]) @@ -6,11 +6,17 @@ AC_PROG_CXX +AC_ARG_WITH(compiler,+ [AS_HELP_STRING([--with-compiler],+ [use the given Haskell compiler])],+ compiler="$withval",+ compiler=ghc)dnl+ AC_ARG_WITH(llvm_prefix, [AS_HELP_STRING([--with-llvm-prefix], [use the version of LLVM at the given location])], llvm_prefix="$withval",- llvm_prefix=/usr/local)dnl+ llvm_prefix="$prefix")dnl AC_ARG_WITH(llvm_bindir, [AS_HELP_STRING([--with-llvm-bindir],@@ -42,6 +48,9 @@ AC_CHECK_LIB(LLVMCore, LLVMModuleCreateWithName, [], [AC_MSG_ERROR(could not find LLVM C bindings)]) -AC_SUBST([llvm_cppflags llvm_engine_libs llvm_includedir llvm_ldflags])+AC_SUBST([llvm_cppflags])+AC_SUBST([llvm_engine_libs])+AC_SUBST([llvm_includedir])+AC_SUBST([llvm_ldflags]) AC_OUTPUT
+ examples/BrainF.hs view
@@ -0,0 +1,143 @@+module BrainF where+-- BrainF compiler example +--+-- The BrainF language has 8 commands:+-- Command Equivalent C Action+-- ------- ------------ ------+-- , *h=getchar(); Read a character from stdin, 255 on EOF+-- . putchar(*h); Write a character to stdout+-- - --*h; Decrement tape+-- + ++*h; Increment tape+-- < --h; Move head left+-- > ++h; Move head right+-- [ while(*h) { Start loop+-- ] } End loop+--+import Control.Monad(when)+import Control.Monad.Trans+import Data.Word+import Data.Int+import System.Environment(getArgs)++import LLVM.Core+import LLVM.ExecutionEngine++main :: IO ()+main = do+ aargs <- getArgs+ let (args, debug) = if take 1 aargs == ["-"] then (tail aargs, True) else (aargs, False)+ let text = "+++++++++++++++++++++++++++++++++" ++ -- constant 33+ ">++++" ++ -- next cell, loop counter, constant 4+ "[>++++++++++" ++ -- loop, loop counter, constant 10+ "[" ++ -- loop+ "<<.+>>-" ++ -- back to 33, print, increment, forward, decrement loop counter+ "]<-" ++ -- back to 4, decrement loop counter+ "]" +++ "++++++++++."+ prog <- if length args == 1 then readFile (head args) else return text++ bfprog <- simpleFunction $ brainCompile debug prog 65536+ when (prog == text) $+ putStrLn "Should print '!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGH' on the next line:"+ bfprog++brainCompile :: Bool -> String -> Word32 -> CodeGenModule (Function (IO ()))+brainCompile debug instrs wmemtotal = do+ -- LLVM functions+ memset <- newNamedFunction ExternalLinkage "llvm.memset.i32"+ :: TFunction (Ptr Word8 -> Word8 -> Word32 -> Word32 -> IO ())+ getchar <- newNamedFunction ExternalLinkage "getchar"+ :: TFunction (IO Int32)+ putchar <- newNamedFunction ExternalLinkage "putchar"+ :: TFunction (Int32 -> IO Int32)++ -- Generate code, first argument is the list of commands,+ -- second argument is a stack of loop contexts, and the+ -- third argument is the current register for the head and+ -- the current basic block.+ -- A loop context is a triple of the phi node, the loop top label,+ -- and the loop exit label.+ let generate [] [] _ =+ return ()+ generate [] (_:_) _ = error "Missing ]"+ generate (']':_) [] _ = error "Missing ["+ generate (']':is) ((cphi, loop, exit) : bs) (cur, bb) = do+ -- The loop has terminated, add the phi node at the top,+ -- branch to the top, and set up the exit label.+ addPhiInputs cphi [(cur, bb)]+ br loop+ defineBasicBlock exit+ generate is bs (cphi, exit)+ + generate ('[':is) bs curbb = do+ -- Start a new loop.+ loop <- newBasicBlock -- loop top+ body <- newBasicBlock -- body of the loop+ exit <- newBasicBlock -- loop exit label+ br loop++ defineBasicBlock loop+ cur <- phi [curbb] -- will get one more input from the loop terminator.+ val <- load cur -- load head byte.+ eqz <- icmp IntEQ val (0::Word8) -- test if it is 0.+ condBr eqz exit body -- and branch accordingly.+ + defineBasicBlock body+ generate is ((cur, loop, exit) : bs) (cur, body)+ + generate (i:is) bs (curhead, bb) = do+ -- A simple command, with no new basic blocks.+ -- Just update which register the head is in.+ curhead' <- gen curhead i+ generate is bs (curhead', bb)++ gen cur ',' = do+ -- Read a character.+ char32 <- call getchar+ char8 <- trunc char32+ store char8 cur+ return cur+ gen cur '.' = do+ -- Write a character.+ char8 <- load cur+ char32 <- zext char8+ call putchar char32+ return cur+ gen cur '-' = do+ -- Decrement byte at head.+ val <- load cur+ val' <- sub val (1 :: Word8)+ store val' cur+ return cur+ gen cur '+' = do+ -- Increment byte at head.+ val <- load cur+ val' <- add val (1 :: Word8)+ store val' cur+ return cur+ gen cur '<' =+ -- Decrement head.+ getElementPtr cur ((-1) :: Word32, ())+ gen cur '>' =+ -- Increment head.+ getElementPtr cur (1 :: Word32, ())+ gen _ c = error $ "Bad character in program: " ++ show c+++ brainf <- createFunction InternalLinkage $ do+ ptr_arr <- arrayMalloc wmemtotal+ call memset ptr_arr (valueOf 0) (valueOf wmemtotal) (valueOf 0)+-- _ptr_arrmax <- getElementPtr ptr_arr (wmemtotal, ())+ -- Start head in the middle.+ curhead <- getElementPtr ptr_arr (wmemtotal `div` 2, ())++ bb <- getCurrentBasicBlock+ generate instrs [] (curhead, bb)++ free ptr_arr+ ret ()++ when (debug) $+ liftIO $ dumpValue brainf++ return brainf
examples/Fibonacci.hs view
@@ -1,61 +1,100 @@-{-# LANGUAGE TypeOperators #-}+module Fibonacci where+import Prelude hiding(and, or)+import System.Environment(getArgs)+import Control.Monad(forM_)+import Data.Word -module Fibonacci (main) where+import LLVM.Core+import LLVM.ExecutionEngine -import Control.Monad (forM_)-import Data.Int (Int32)-import System.Environment (getArgs)+-- Our module will have these two functions.+data Mod = Mod {+ mfib :: Function (Word32 -> IO Word32),+ mplus :: Function (Word32 -> Word32 -> IO Word32)+ } -import qualified LLVM.Core as Core-import qualified LLVM.Core.Builder as B-import qualified LLVM.Core.Constant as C-import qualified LLVM.Core.Instruction as I-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V-import qualified LLVM.Core.Utils as U-import qualified LLVM.ExecutionEngine as EE+main :: IO ()+main = do+ args <- getArgs+ let args' = if null args then ["10"] else args -buildFib :: T.Module -> IO (V.Function T.Int32 T.Int32)-buildFib m = do- let one = C.const (1::Int32)- two = C.const (2::Int32)- (fib, entry) <- U.defineFunction m "fib" (T.function undefined undefined)- bld <- B.createBuilder- exit <- Core.appendBasicBlock fib "return"- recurse <- Core.appendBasicBlock fib "recurse"- let arg = V.params fib+ -- Create a module,+ m <- newNamedModule "fib"+ -- and define its contents.+ fns <- defineModule m buildMod - B.positionAtEnd bld entry- test <- B.icmp bld "" I.IntSLE arg two- B.condBr bld test exit recurse+ -- Show the code for the two functions, just for fun.+ --dumpValue $ mfib fns+ --dumpValue $ mplus fns+ -- Write the code to a file for later perusal.+ -- Can be disassembled with llvm-dis.+ writeBitcodeToFile "Fibonacci.bc" m - B.positionAtEnd bld exit- B.ret bld one+ -- Create a JIT execution engine for the module.+ ee <- createModuleProviderForExistingModule m >>= createExecutionEngine - B.positionAtEnd bld recurse- x1 <- B.sub bld "" arg one- fibx1 <- B.call bld "" fib x1+ -- Generate code for mfib, and then throw away the IO in the type.+ -- The result is an ordinary Haskell function.+ let fib = unsafePurify $ generateFunction ee $ mfib fns - x2 <- B.sub bld "" arg two- fibx2 <- B.call bld "" fib x2+ -- Run fib for the arguments.+ forM_ args' $ \num -> do+ putStrLn $ "fib " ++ num ++ " = " ++ show (fib (read num))+ return () - B.add bld "" fibx1 fibx2 >>= B.ret bld- return fib+buildMod :: CodeGenModule Mod+buildMod = do+ -- Add two numbers in a cumbersome way.+ plus <- createFunction InternalLinkage $ \ x y -> do+ -- Create three additional basic blocks, need to be created before being referred to.+ l1 <- newBasicBlock+ l2 <- newBasicBlock+ l3 <- newBasicBlock -main :: IO ()-main = do- args <- getArgs- let args' = if null args then ["10"] else args+ -- Test if x is even/odd.+ a <- and x (1 :: Word32)+ c <- icmp IntEQ a (0 :: Word32)+ condBr c l1 l2 - m <- Core.createModule "fib"- fib <- buildFib m- V.dumpValue fib+ -- Do x+y if even.+ defineBasicBlock l1+ r1 <- add x y+ br l3 - prov <- Core.createModuleProviderForExistingModule m- ee <- EE.createExecutionEngine prov- - forM_ args' $ \num -> do- putStr $ "fib " ++ num ++ " = "- parm <- EE.createGeneric (read num :: Int)- gv <- EE.runFunction ee fib [parm]- print (EE.fromGeneric gv :: Int)+ -- Do y+x if odd.+ defineBasicBlock l2+ r2 <- add y x+ br l3++ defineBasicBlock l3+ -- Join the two execution paths with a phi instruction.+ r <- phi [(r1, l1), (r2, l2)]+ ret r++ -- The usual doubly recursive Fibonacci.+ -- Use new&define so the name fib is defined in the body for recursive calls.+ fib <- newNamedFunction ExternalLinkage "fib"+ defineFunction fib $ \ arg -> do+ -- Create the two basic blocks.+ recurse <- newBasicBlock+ exit <- newBasicBlock++ -- Test if arg > 2+ test <- icmp IntUGT arg (2::Word32)+ condBr test recurse exit++ -- Just return 1 if not > 2+ defineBasicBlock exit+ ret (1::Word32)++ -- Recurse if > 2, using the cumbersome plus to add the results.+ defineBasicBlock recurse+ x1 <- sub arg (1::Word32)+ fibx1 <- call fib x1+ x2 <- sub arg (2::Word32)+ fibx2 <- call fib x2+ r <- call plus fibx1 fibx2+ ret r++ -- Return the two functions.+ return $ Mod fib plus
examples/HelloJIT.hs view
@@ -1,44 +1,24 @@-{-# LANGUAGE TypeOperators #-} module HelloJIT (main) where -import Data.Int (Int32)-import Prelude hiding (mod)--import qualified LLVM.Core as Core-import qualified LLVM.Core.Builder as B-import qualified LLVM.Core.Constant as C-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V-import qualified LLVM.Core.Utils as U-import qualified LLVM.ExecutionEngine as EE-+import Data.Word -buildModule :: IO (T.Module, V.Function T.Int32 ())-buildModule = do- mod <- Core.createModule "hello"- greetz <- U.defineGlobal mod "greeting" (C.const "hello jit!")- let t = T.function (undefined :: T.Int32) (undefined :: T.Pointer T.Int8)- putStrLn $ "type of puts: " ++ show t- puts <- U.declareFunction mod "puts" t- (func, entry) <- U.defineFunction mod "main"- (T.function (undefined :: T.Int32) ())- bld <- B.createBuilder- B.positionAtEnd bld entry- let zero = C.const (0::Int32)- tmp <- B.getElementPtr bld "tmp" greetz [zero, zero]- B.call_ bld "" puts tmp- B.ret bld zero- return (mod, func)+import LLVM.Core+import LLVM.ExecutionEngine -execute :: T.Module -> V.Function T.Int32 () -> IO ()-execute mod func = do- prov <- Core.createModuleProviderForExistingModule mod- ee <- EE.createExecutionEngine prov- EE.runStaticConstructors ee- gv <- EE.runFunction ee func []- print (EE.fromGeneric gv :: Int32)- EE.runStaticDestructors ee- return ()+bldGreet :: CodeGenModule (Function (IO ()))+bldGreet = do+ puts <- newNamedFunction ExternalLinkage "puts" :: TFunction (Ptr Word8 -> IO Word32)+ greetz <- createStringNul "Hello, JIT!"+ func <- createFunction ExternalLinkage $ do+ tmp <- getElementPtr greetz (0::Word32, (0::Word32, ()))+ call puts tmp -- Throw away return value.+ ret ()+ return func main :: IO ()-main = buildModule >>= uncurry execute+main = do+ greet <- simpleFunction bldGreet+ greet+ greet+ greet+ return ()
− examples/HowToUseJIT.hs
@@ -1,43 +0,0 @@-{-# LANGUAGE TypeOperators #-}--module HowToUseJIT (main) where--import LLVM.Core.Type ((:->)(..))-import qualified LLVM.Core as Core-import qualified LLVM.Core.Builder as B-import qualified LLVM.Core.Constant as C-import qualified LLVM.Core.Type as T-import qualified LLVM.Core.Value as V-import qualified LLVM.Core.Utils as U-import qualified LLVM.ExecutionEngine as EE-import Data.Int (Int32)--main :: IO ()-main = do- m <- Core.createModule "test"- let t = T.function (undefined :: T.Int32) (undefined :: T.Int32 :-> T.Int32)-- (add1, addEntry) <- U.defineFunction m "add1" t- let a :-> b = V.params add1- V.setName a "a"-- bld <- B.createBuilder- B.positionAtEnd bld addEntry- v1 <- B.add bld "" (C.const (1::Int32)) a- v2 <- B.add bld "" v1 b- B.ret bld v2- V.dumpValue add1-- (foo, fooEntry) <- U.defineFunction m "foo" (T.function (undefined :: T.Int32) ())- B.positionAtEnd bld fooEntry- c <- B.call bld "wibble" add1 (C.const (1::Int32) :-> C.const (10::Int32))- B.ret bld c- V.dumpValue foo-- prov <- Core.createModuleProviderForExistingModule m- ee <- EE.createExecutionEngine prov- EE.runStaticConstructors ee- gv <- EE.runFunction ee foo []- EE.runStaticDestructors ee- print (EE.fromGeneric gv :: Int32)- return ()
examples/Makefile view
@@ -1,11 +1,26 @@ ghc := ghc-ghcflags := -Wall -Werror-examples := Fibonacci HelloJIT HowToUseJIT+ghcflags := -Wall+examples := HelloJIT Fibonacci BrainF all: $(examples) %: %.hs $(ghc) $(ghcflags) --make -o $@ -main-is $(basename $<).main $< +%.run: %+ ./$<++run: $(examples:%=%.run)++N=40+fastfib: Fibonacci+ @rm -f Fib.bc Fib.s+ time ./Fibonacci $(N)+ opt -std-compile-opts Fibonacci.bc -o Fib.bc+ llc Fib.bc+ $(CC) mainfib.c Fib.s -o Fib+ time ./Fib $(N)+ @echo Have a look at Fib.s if you like to see clever code.+ clean:- -rm -f *.o *.hi $(examples)+ rm -f $(examples) *.o *.hi *.s *.bc Fib
llvm.buildinfo.in view
@@ -1,4 +1,4 @@ ghc-options: @llvm_cppflags@ -pgml @CXX@ ld-options: @llvm_ldflags@ @llvm_engine_libs@ -lstdc++ include-dirs: @llvm_includedir@-extra-libraries: LLVMCore LLVMTarget LLVMSupport LLVMSystem+extra-libraries: LLVMAnalysis LLVMBitWriter LLVMBitReader LLVMCore LLVMTarget LLVMSupport LLVMSystem
llvm.cabal view
@@ -1,13 +1,19 @@ name: llvm-version: 0.0.2+version: 0.4.0.0 license: BSD3 license-file: LICENSE synopsis: Bindings to the LLVM compiler toolkit description: Bindings to the LLVM compiler toolkit author: Bryan O'Sullivan+author: Lennart Augustsson maintainer: Bryan O'Sullivan <bos@serpentine.com>-category: Compilers/Interpreters-cabal-version: >= 1.2.1+maintainer: Lennart Augustsson <lennart@augustsson.net>+homepage: http://www.serpentine.com/blog/software/llvm/+stability: experimental+category: Compilers/Interpreters, Code Generation+tested-with: GHC == 6.8.2, GHC == 6.10.1+cabal-version: >= 1.2.3+build-type: Configure extra-source-files: INSTALL.txt@@ -16,10 +22,14 @@ README.txt configure configure.ac+ examples/BrainF.hs examples/Fibonacci.hs examples/HelloJIT.hs- examples/HowToUseJIT.hs examples/Makefile+ tests/Makefile+ tests/TestValue.hs+ tools/Makefile+ tools/IntrinsicMangler.hs llvm.buildinfo.in extra-tmp-files:@@ -40,25 +50,27 @@ build-depends: base >= 2.0 && < 2.2 cpp-options: -DBYTESTRING_IN_BASE else- build-depends: base < 2.0 || >= 2.2, bytestring >= 0.9 + build-depends: base < 2.0 || >= 2.2, bytestring >= 0.9, mtl - extensions:- EmptyDataDecls- FlexibleInstances- ForeignFunctionInterface- GeneralizedNewtypeDeriving- TypeOperators- TypeSynonymInstances- ghc-options: -Wall -Werror+ ghc-options: -Wall exposed-modules:+ Data.TypeNumbers LLVM.Core- LLVM.Core.FFI- LLVM.Core.Builder- LLVM.Core.Constant- LLVM.Core.Instruction- LLVM.Core.Type- LLVM.Core.Utils- LLVM.Core.Value LLVM.ExecutionEngine- LLVM.ExecutionEngine.FFI+ LLVM.FFI.Analysis+ LLVM.FFI.BitReader+ LLVM.FFI.BitWriter+ LLVM.FFI.Core+ LLVM.FFI.ExecutionEngine+ LLVM.FFI.Target+ LLVM.FFI.Transforms.Scalar++ other-modules:+ LLVM.Core.CodeGen+ LLVM.Core.CodeGenMonad+ LLVM.Core.Data+ LLVM.Core.Instructions+ LLVM.Core.Type+ LLVM.Core.Util+ LLVM.ExecutionEngine.Engine
+ tests/Makefile view
@@ -0,0 +1,16 @@+ghc := ghc+ghcflags := -Wall -Werror+tests := TestType TestValue++all: $(tests:%=%.out)++%.out: %.test+ ./$< > $@ 2>&1; s=$$?; cat $@; \+ if [ $$s != 0 ]; then mv $@ $(basename $@).err; exit 1; fi++.PRECIOUS: %.test+%.test: %.hs+ $(ghc) $(ghcflags) --make -o $@ -main-is $(basename $<).main $<++clean:+ -rm -f *.o *.hi $(tests:%=%.test) $(tests:%=%.out)
+ tests/TestValue.hs view
@@ -0,0 +1,69 @@+module TestValue (main) where+ +import qualified LLVM.Core as Core+import qualified LLVM.Core.Type as T+import qualified LLVM.Core.Value as V+ +testArguments :: (T.DynamicType r, T.Params p, V.Params p v, V.Value v)+ => T.Module -> String -> IO (V.Function r p)+testArguments m name = do+ func <- Core.addFunction m name (T.function undefined undefined)+ V.dumpValue func+ let arg = V.params func+ V.dumpValue arg+ return func+ +voidArguments :: T.Module -> IO ()+voidArguments m = do+ func <- Core.addFunction m "void" (T.function (undefined :: T.Void) ())+ V.dumpValue func+ return () ++type F a = V.Function a a+type P a = V.Function (T.Pointer a) (T.Pointer a)+type V a = V.Function (T.Vector a) (T.Vector a)++arguments :: T.Module -> IO ()+arguments m = do+ voidArguments m++ testArguments m "int1" :: IO (F T.Int1)+ testArguments m "int8" :: IO (F T.Int8)+ testArguments m "int16" :: IO (F T.Int16)+ testArguments m "int32" :: IO (F T.Int32)+ testArguments m "int64" :: IO (F T.Int64)+ testArguments m "float" :: IO (F T.Float)+ testArguments m "double" :: IO (F T.Double)+ testArguments m "float128" :: IO (F T.Float128)+ testArguments m "x86Float80" :: IO (F T.X86Float80)+ testArguments m "ppcFloat128" :: IO (F T.PPCFloat128)++ testArguments m "ptrInt1" :: IO (P T.Int1)+ testArguments m "ptrInt8" :: IO (P T.Int8)+ testArguments m "ptrInt16" :: IO (P T.Int16)+ testArguments m "ptrInt32" :: IO (P T.Int32)+ testArguments m "ptrInt64" :: IO (P T.Int64)+ testArguments m "ptrFloat" :: IO (P T.Float)+ testArguments m "ptrDouble" :: IO (P T.Double)+ testArguments m "ptrFloat128" :: IO (P T.Float128)+ testArguments m "ptrX86Float80" :: IO (P T.X86Float80)+ testArguments m "ptrPpcFloat128" :: IO (P T.PPCFloat128)++ testArguments m "vecInt1" :: IO (V T.Int1)+ testArguments m "vecInt8" :: IO (V T.Int8)+ testArguments m "vecInt16" :: IO (V T.Int16)+ testArguments m "vecInt32" :: IO (V T.Int32)+ testArguments m "vecInt64" :: IO (V T.Int64)+ testArguments m "vecFloat" :: IO (V T.Float)+ testArguments m "vecDouble" :: IO (V T.Double)+ testArguments m "vecFloat128" :: IO (V T.Float128)+ testArguments m "vecX86Float80" :: IO (V T.X86Float80)+ testArguments m "vecPpcFloat128" :: IO (V T.PPCFloat128)++ return ()++main :: IO ()+main = do+ m <- Core.createModule "m"+ arguments m+ return ()
+ tools/IntrinsicMangler.hs view
@@ -0,0 +1,22 @@+module IntrinsicMangler (main) where++import Control.Monad (forM_)+import qualified Data.ByteString.Char8 as C+import Data.Maybe (catMaybes)+import Text.Regex.Posix ((=~~))++maybeName :: C.ByteString -> Maybe C.ByteString+maybeName line = do+ ((_:name:_):_) <- line =~~ "^[ \t]*([a-z0-9_]+),[ \t]*//[ \t]*llvm\\."+ return name++main :: IO ()+main = do+ input <- (catMaybes . map maybeName . C.lines) `fmap` C.getContents++ putStrLn "-- automatically generated file - do not edit!"+ putStrLn "module LLVM.Core.Intrinsics (Intrinsic(..)) where"+ putStrLn "data Intrinsic ="+ putStrLn " NotIntrinsic"+ forM_ input $ C.putStrLn . (C.append (C.pack " | I_"))+ putStrLn " deriving (Eq, Ord, Enum, Show)"
+ tools/Makefile view
@@ -0,0 +1,11 @@+ghc := ghc+ghcflags := -O -Wall -Werror+tools := DiffFFI FunctionMangler IntrinsicMangler++all: $(tools)++%: %.hs+ $(ghc) $(ghcflags) --make -o $@ -main-is $(basename $<).main $<++clean:+ -rm -f *.o *.hi $(tools)