module LLVM.ExecutionEngine.Target(TargetData(..), getTargetData, targetDataFromString, withIntPtrType) where
import qualified LLVM.ExecutionEngine.Engine as EE
import LLVM.Core.Data (WordN)
import qualified LLVM.FFI.Core as FFI
import qualified LLVM.FFI.Target as FFI
import qualified Type.Data.Num.Decimal.Number as Dec
import Type.Base.Proxy (Proxy)
import Foreign.ForeignPtr
(ForeignPtr, newForeignPtr, withForeignPtr, touchForeignPtr)
import Foreign.C.String (withCString)
import Control.Monad (liftM2)
import Control.Applicative ((<$>))
import Data.Typeable (Typeable)
import Data.Maybe (fromMaybe)
import System.IO.Unsafe (unsafePerformIO)
type Type = FFI.TypeRef
data TargetData = TargetData {
abiAlignmentOfType :: Type -> Int,
abiSizeOfType :: Type -> Int,
littleEndian :: Bool,
callFrameAlignmentOfType :: Type -> Int,
intPtrType :: Type,
pointerSize :: Int,
preferredAlignmentOfType :: Type -> Int,
sizeOfTypeInBits :: Type -> Int,
storeSizeOfType :: Type -> Int
}
deriving (Typeable)
withIntPtrType :: (forall n . (Dec.Positive n) => WordN n -> a) -> a
withIntPtrType f =
fromMaybe (error "withIntPtrType: pointer size must be non-negative") $
Dec.reifyPositive (fromIntegral sz) (\ n -> f (g n))
where g :: Proxy n -> WordN n
g _ = error "withIntPtrType: argument used"
sz = pointerSize $ unsafePerformIO getTargetData
unsafeIO :: ForeignPtr a -> IO b -> b
unsafeIO fptr act =
unsafePerformIO $ do x <- act; touchForeignPtr fptr; return x
unsafeIntIO :: (Integral i, Num j) => ForeignPtr a -> IO i -> j
unsafeIntIO fptr = fromIntegral . unsafeIO fptr
makeTargetData :: ForeignPtr a -> FFI.TargetDataRef -> TargetData
makeTargetData fptr r = TargetData {
abiAlignmentOfType = unsafeIntIO fptr . FFI.abiAlignmentOfType r,
abiSizeOfType = unsafeIntIO fptr . FFI.abiSizeOfType r,
littleEndian = unsafeIO fptr (FFI.byteOrder r) /= FFI.bigEndian,
callFrameAlignmentOfType = unsafeIntIO fptr . FFI.callFrameAlignmentOfType r,
intPtrType = unsafeIO fptr $ FFI.intPtrType r,
pointerSize = unsafeIntIO fptr $ FFI.pointerSize r,
preferredAlignmentOfType = unsafeIntIO fptr . FFI.preferredAlignmentOfType r,
sizeOfTypeInBits = unsafeIntIO fptr . FFI.sizeOfTypeInBits r,
storeSizeOfType = unsafeIntIO fptr . FFI.storeSizeOfType r
}
getTargetData :: IO TargetData
getTargetData =
EE.runEngineAccess $
liftM2 makeTargetData
(EE.fromEngine <$> EE.getEngine)
EE.getExecutionEngineTargetData
createTargetData :: String -> IO (ForeignPtr FFI.TargetData)
createTargetData s =
newForeignPtr FFI.ptrDisposeTargetData =<<
withCString s FFI.createTargetData
targetDataFromString :: String -> TargetData
targetDataFromString s = unsafePerformIO $ do
td <- createTargetData s
withForeignPtr td $ return . makeTargetData td