module LLVM.Internal.InstructionDefs (
astInstructionRecs,
astConstantRecs,
instructionDefs,
ID.InstructionKind(..),
ID.InstructionDef(..),
instrP,
innerJoin,
outerJoin
) where
import LLVM.Prelude
import qualified Language.Haskell.TH as TH
import qualified Language.Haskell.TH.Quote as TH
import Data.Map (Map)
import qualified Data.Map as Map
import qualified LLVM.Internal.FFI.InstructionDefs as ID
import qualified LLVM.AST.Instruction as A
import qualified LLVM.AST.Constant as A.C
$(do
let ctorRecs t = do
#if __GLASGOW_HASKELL__ < 800
TH.TyConI (TH.DataD _ _ _ cons _) <- TH.reify t
#else
TH.TyConI (TH.DataD _ _ _ _ cons _) <- TH.reify t
#endif
TH.dataToExpQ (const Nothing) $ [ (TH.nameBase n, rec) | rec@(TH.RecC n _) <- cons ]
[d|
astInstructionRecs :: Map String TH.Con
astInstructionRecs = Map.fromList $(ctorRecs ''A.Instruction)
astConstantRecs :: Map String TH.Con
astConstantRecs = Map.fromList $(ctorRecs ''A.C.Constant)
|]
)
instructionDefs :: Map String ID.InstructionDef
instructionDefs = Map.fromList [ ((refName . ID.cAPIName $ i), i) | i <- ID.instructionDefs ]
where
refName "AtomicCmpXchg" = "CmpXchg"
refName "PHI" = "Phi"
refName x = x
innerJoin :: Ord k => Map k a -> Map k b -> Map k (a,b)
innerJoin = Map.intersectionWith (,)
outerJoin :: Ord k => Map k a -> Map k b -> Map k (Maybe a, Maybe b)
outerJoin xs ys = Map.unionWith combine
(Map.map (\a -> (Just a, Nothing)) xs)
(Map.map (\b -> (Nothing, Just b)) ys)
where
combine (Just a, Nothing) (Nothing, Just b) = (Just a, Just b)
combine _ _ = error "outerJoin: the impossible happened"
instrP :: TH.QuasiQuoter
instrP = TH.QuasiQuoter {
TH.quoteExp = undefined,
TH.quotePat = let m = Map.fromList [ (ID.cAPIName i, ID.cppOpcode i) | i <- ID.instructionDefs ]
in TH.dataToPatQ (const Nothing) . (m Map.!),
TH.quoteType = undefined,
TH.quoteDec = undefined
}