Add arch-specific decls + type instances + rewriters

This also lets us add 'withArchConstraints' easily.
This commit is contained in:
Tristan Ravitch 2017-10-03 18:59:35 -07:00
parent 8a1195b1c6
commit a851cddebd
3 changed files with 107 additions and 14 deletions

View File

@ -17,6 +17,7 @@ cabal-version: >=1.10
library library
exposed-modules: Data.Macaw.PPC exposed-modules: Data.Macaw.PPC
Data.Macaw.PPC.Arch
Data.Macaw.PPC.Disassemble Data.Macaw.PPC.Disassemble
Data.Macaw.PPC.Eval Data.Macaw.PPC.Eval
Data.Macaw.PPC.Generator Data.Macaw.PPC.Generator
@ -35,6 +36,7 @@ library
semmc-ppc, semmc-ppc,
lens, lens,
macaw-base, macaw-base,
ansi-wl-pprint,
mtl, mtl,
parameterized-utils parameterized-utils
hs-source-dirs: src hs-source-dirs: src

View File

@ -16,9 +16,7 @@ import qualified Data.Macaw.Architecture.Info as MI
import Data.Macaw.CFG import Data.Macaw.CFG
import qualified Data.Macaw.CFG.DemandSet as MDS import qualified Data.Macaw.CFG.DemandSet as MDS
import qualified Data.Macaw.Memory as MM import qualified Data.Macaw.Memory as MM
import qualified Data.Macaw.Types as MT
import qualified Dismantle.PPC as D
import qualified SemMC.Architecture.PPC32 as PPC32 import qualified SemMC.Architecture.PPC32 as PPC32
import qualified SemMC.Architecture.PPC64 as PPC64 import qualified SemMC.Architecture.PPC64 as PPC64
@ -32,10 +30,7 @@ import Data.Macaw.PPC.Eval ( mkInitialAbsState,
import Data.Macaw.PPC.Identify ( identifyCall, import Data.Macaw.PPC.Identify ( identifyCall,
identifyReturn identifyReturn
) )
import Data.Macaw.PPC.Rewrite ( rewriteArchFn, import Data.Macaw.PPC.Arch ( rewriteTermStmt, rewriteStmt, rewritePrimFn )
rewriteArchStmt,
rewriteArchTermStmt
)
archDemandContext :: proxy ppc -> MDS.DemandContext ppc ids archDemandContext :: proxy ppc -> MDS.DemandContext ppc ids
archDemandContext = undefined archDemandContext = undefined
@ -47,7 +42,7 @@ jumpTableEntrySize = undefined
ppc64_linux_info :: MI.ArchitectureInfo PPC64.PPC ppc64_linux_info :: MI.ArchitectureInfo PPC64.PPC
ppc64_linux_info = ppc64_linux_info =
MI.ArchitectureInfo { MI.withArchConstraints = undefined MI.ArchitectureInfo { MI.withArchConstraints = \x -> x
, MI.archAddrWidth = MM.Addr64 , MI.archAddrWidth = MM.Addr64
, MI.archEndianness = MM.BigEndian , MI.archEndianness = MM.BigEndian
, MI.jumpTableEntrySize = jumpTableEntrySize proxy , MI.jumpTableEntrySize = jumpTableEntrySize proxy
@ -59,9 +54,9 @@ ppc64_linux_info =
, MI.postCallAbsState = postCallAbsState proxy , MI.postCallAbsState = postCallAbsState proxy
, MI.identifyCall = identifyCall proxy , MI.identifyCall = identifyCall proxy
, MI.identifyReturn = identifyReturn proxy , MI.identifyReturn = identifyReturn proxy
, MI.rewriteArchFn = rewriteArchFn proxy , MI.rewriteArchFn = rewritePrimFn
, MI.rewriteArchStmt = rewriteArchStmt proxy , MI.rewriteArchStmt = rewriteStmt
, MI.rewriteArchTermStmt = rewriteArchTermStmt proxy , MI.rewriteArchTermStmt = rewriteTermStmt
, MI.archDemandContext = archDemandContext proxy , MI.archDemandContext = archDemandContext proxy
} }
where where
@ -70,7 +65,7 @@ ppc64_linux_info =
ppc32_linux_info :: MI.ArchitectureInfo PPC32.PPC ppc32_linux_info :: MI.ArchitectureInfo PPC32.PPC
ppc32_linux_info = ppc32_linux_info =
MI.ArchitectureInfo { MI.withArchConstraints = undefined MI.ArchitectureInfo { MI.withArchConstraints = \x -> x
, MI.archAddrWidth = MM.Addr32 , MI.archAddrWidth = MM.Addr32
, MI.archEndianness = MM.BigEndian , MI.archEndianness = MM.BigEndian
, MI.jumpTableEntrySize = jumpTableEntrySize proxy , MI.jumpTableEntrySize = jumpTableEntrySize proxy
@ -82,9 +77,9 @@ ppc32_linux_info =
, MI.postCallAbsState = postCallAbsState proxy , MI.postCallAbsState = postCallAbsState proxy
, MI.identifyCall = identifyCall proxy , MI.identifyCall = identifyCall proxy
, MI.identifyReturn = identifyReturn proxy , MI.identifyReturn = identifyReturn proxy
, MI.rewriteArchFn = rewriteArchFn proxy , MI.rewriteArchFn = rewritePrimFn
, MI.rewriteArchStmt = rewriteArchStmt proxy , MI.rewriteArchStmt = rewriteStmt
, MI.rewriteArchTermStmt = rewriteArchTermStmt proxy , MI.rewriteArchTermStmt = rewriteTermStmt
, MI.archDemandContext = archDemandContext proxy , MI.archDemandContext = archDemandContext proxy
} }
where where

View File

@ -0,0 +1,96 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeFamilies #-}
module Data.Macaw.PPC.Arch (
PPCTermStmt(..),
rewriteTermStmt,
PPCStmt(..),
rewriteStmt,
PPCPrimFn(..),
rewritePrimFn
) where
import qualified Text.PrettyPrint.ANSI.Leijen as PP
import qualified Data.Parameterized.TraversableFC as FC
import qualified Data.Macaw.CFG as MC
import Data.Macaw.CFG.Rewriter ( Rewriter, rewriteValue, evalRewrittenArchFn )
import qualified Data.Macaw.Types as MT
import qualified SemMC.Architecture.PPC32 as PPC32
import qualified SemMC.Architecture.PPC64 as PPC64
import Data.Macaw.PPC.PPCReg
data PPCTermStmt ids where
PPCSyscall :: PPCTermStmt ids
type instance MC.ArchTermStmt PPC64.PPC = PPCTermStmt
type instance MC.ArchTermStmt PPC32.PPC = PPCTermStmt
instance MC.PrettyF PPCTermStmt where
prettyF ts =
case ts of
PPCSyscall -> PP.text "ppc_syscall"
rewriteTermStmt :: PPCTermStmt src -> Rewriter ppc src tgt (PPCTermStmt tgt)
rewriteTermStmt s =
case s of
PPCSyscall -> pure PPCSyscall
-- | We currently have no PPC-specific statements. Remove 'None' if we add some.
data PPCStmt ids where
None :: PPCStmt ids
instance MC.PrettyF PPCStmt where
prettyF None = PP.text "None"
type instance MC.ArchStmt PPC64.PPC = PPCStmt
type instance MC.ArchStmt PPC32.PPC = PPCStmt
rewriteStmt :: PPCStmt src -> Rewriter ppc src tgt ()
rewriteStmt _ = return ()
data PPCPrimFn ppc f tp where
IDiv :: proxy ppc
-> f (MT.BVType (MC.RegAddrWidth (MC.ArchReg ppc)))
-> f (MT.BVType (MC.RegAddrWidth (MC.ArchReg ppc)))
-> PPCPrimFn ppc f (MT.BVType (MC.RegAddrWidth (MC.ArchReg ppc)))
instance MT.HasRepr (PPCPrimFn ppc (MC.Value ppc ids)) MT.TypeRepr where
typeRepr f =
case f of
IDiv {} -> undefined
rewritePrimFn :: (PPCWidth ppc, MC.ArchFn ppc ~ PPCPrimFn ppc)
=> PPCPrimFn ppc (MC.Value ppc src) tp
-> Rewriter ppc src tgt (MC.Value ppc tgt tp)
rewritePrimFn f =
case f of
IDiv p lhs rhs -> do
tgtFn <- IDiv p <$> rewriteValue lhs <*> rewriteValue rhs
evalRewrittenArchFn tgtFn
ppPrimFn :: (Applicative m) => (forall u . f u -> m PP.Doc) -> PPCPrimFn ppc f tp -> m PP.Doc
ppPrimFn _pp f =
case f of
IDiv {} -> pure (PP.text "idiv")
instance MC.IsArchFn (PPCPrimFn ppc) where
ppArchFn = ppPrimFn
instance FC.FunctorFC (PPCPrimFn ppc) where
fmapFC = FC.fmapFCDefault
instance FC.FoldableFC (PPCPrimFn ppc) where
foldMapFC = FC.foldMapFCDefault
instance FC.TraversableFC (PPCPrimFn ppc) where
traverseFC go f =
case f of
IDiv p lhs rhs -> IDiv p <$> go lhs <*> go rhs
type instance MC.ArchFn PPC64.PPC = PPCPrimFn PPC64.PPC
type instance MC.ArchFn PPC32.PPC = PPCPrimFn PPC32.PPC