{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses #-} module LLVM.General.Internal.Global where import LLVM.General.Prelude import Control.Monad.State import Control.Monad.AnyCont import Foreign.Ptr import qualified Data.Map as Map import qualified LLVM.General.Internal.FFI.PtrHierarchy as FFI import qualified LLVM.General.Internal.FFI.LLVMCTypes as FFI import qualified LLVM.General.Internal.FFI.GlobalValue as FFI import LLVM.General.Internal.Coding import LLVM.General.Internal.DecodeAST import LLVM.General.Internal.EncodeAST import qualified LLVM.General.AST.Linkage as A.L import qualified LLVM.General.AST.Visibility as A.V import qualified LLVM.General.AST.COMDAT as A.COMDAT import qualified LLVM.General.AST.DLL as A.DLL import qualified LLVM.General.AST.ThreadLocalStorage as A.TLS genCodingInstance [t| A.L.Linkage |] ''FFI.Linkage [ (FFI.linkageExternal, A.L.External), (FFI.linkageAvailableExternally, A.L.AvailableExternally), (FFI.linkageLinkOnceAny, A.L.LinkOnce), (FFI.linkageLinkOnceODR, A.L.LinkOnceODR), (FFI.linkageWeakAny, A.L.Weak), (FFI.linkageWeakODR, A.L.WeakODR), (FFI.linkageAppending, A.L.Appending), (FFI.linkageInternal, A.L.Internal), (FFI.linkagePrivate, A.L.Private), (FFI.linkageExternalWeak, A.L.ExternWeak), (FFI.linkageCommon, A.L.Common) ] getLinkage :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST A.L.Linkage getLinkage g = liftIO $ decodeM =<< FFI.getLinkage (FFI.upCast g) setLinkage :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> A.L.Linkage -> EncodeAST () setLinkage g l = liftIO . FFI.setLinkage (FFI.upCast g) =<< encodeM l genCodingInstance [t| A.V.Visibility |] ''FFI.Visibility [ (FFI.visibilityDefault, A.V.Default), (FFI.visibilityHidden, A.V.Hidden), (FFI.visibilityProtected, A.V.Protected) ] getVisibility :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST A.V.Visibility getVisibility g = liftIO $ decodeM =<< FFI.getVisibility (FFI.upCast g) setVisibility :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> A.V.Visibility -> EncodeAST () setVisibility g v = liftIO . FFI.setVisibility (FFI.upCast g) =<< encodeM v genCodingInstance [t| Maybe A.DLL.StorageClass |] ''FFI.DLLStorageClass [ (FFI.dllStorageClassDefault, Nothing), (FFI.dllStorageClassDLLImport, Just A.DLL.Import), (FFI.dllStorageClassDLLExport, Just A.DLL.Export) ] getDLLStorageClass :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe A.DLL.StorageClass) getDLLStorageClass g = liftIO $ decodeM =<< FFI.getDLLStorageClass (FFI.upCast g) setDLLStorageClass :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe A.DLL.StorageClass -> EncodeAST () setDLLStorageClass g sc = liftIO . FFI.setDLLStorageClass (FFI.upCast g) =<< encodeM sc getSection :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe String) getSection g = liftIO $ do s <- decodeM =<< FFI.getSection (FFI.upCast g) return $ if (s == "") then Nothing else Just s setSection :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe String -> EncodeAST () setSection g s = scopeAnyCont $ do s <- encodeM (maybe "" id s) liftIO $ FFI.setSection (FFI.upCast g) s genCodingInstance [t| A.COMDAT.SelectionKind |] ''FFI.COMDATSelectionKind [ (FFI.comdatSelectionKindAny, A.COMDAT.Any), (FFI.comdatSelectionKindExactMatch, A.COMDAT.ExactMatch), (FFI.comdatSelectionKindLargest, A.COMDAT.Largest), (FFI.comdatSelectionKindNoDuplicates, A.COMDAT.NoDuplicates), (FFI.comdatSelectionKindSameSize, A.COMDAT.SameSize) ] instance DecodeM DecodeAST (String, A.COMDAT.SelectionKind) (Ptr FFI.COMDAT) where decodeM c = return (,) `ap` (decodeM $ FFI.getCOMDATName c) `ap` (decodeM =<< liftIO (FFI.getCOMDATSelectionKind c)) getCOMDATName :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe String) getCOMDATName g = do c <- liftIO $ FFI.getCOMDAT (FFI.upCast g) if c == nullPtr then return Nothing else do cds <- gets comdats liftM Just $ case Map.lookup c cds of Just (name, _) -> return name Nothing -> do cd@(name, _) <- decodeM c modify $ \s -> s { comdats = Map.insert c cd cds } return name setCOMDAT :: FFI.DescendentOf FFI.GlobalObject v => Ptr v -> Maybe String -> EncodeAST () setCOMDAT _ Nothing = return () setCOMDAT g (Just name) = do cd <- referCOMDAT name liftIO $ FFI.setCOMDAT (FFI.upCast g) cd setAlignment :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Word32 -> EncodeAST () setAlignment g i = liftIO $ FFI.setAlignment (FFI.upCast g) (fromIntegral i) getAlignment :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST Word32 getAlignment g = liftIO $ fromIntegral <$> FFI.getAlignment (FFI.upCast g) genCodingInstance [t| Maybe A.TLS.Model |] ''FFI.ThreadLocalMode [ (FFI.threadLocalModeNotThreadLocal, Nothing), (FFI.threadLocalModeGeneralDynamicTLSModel, Just A.TLS.GeneralDynamic), (FFI.threadLocalModeLocalDynamicTLSModel, Just A.TLS.LocalDynamic), (FFI.threadLocalModeInitialExecTLSModel, Just A.TLS.InitialExec), (FFI.threadLocalModeLocalExecTLSModel, Just A.TLS.LocalExec) ] getThreadLocalMode :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> DecodeAST (Maybe A.TLS.Model) getThreadLocalMode g = liftIO $ decodeM =<< FFI.getThreadLocalMode (FFI.upCast g) setThreadLocalMode :: FFI.DescendentOf FFI.GlobalValue v => Ptr v -> Maybe A.TLS.Model -> EncodeAST () setThreadLocalMode g m = liftIO . FFI.setThreadLocalMode (FFI.upCast g) =<< encodeM m