1 {-# LANGUAGE NoMonomorphismRestriction #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE TemplateHaskell #-}
5 -- Purpose of this file is just do test some Intermediate representations and stuff ;-)
7 {- Some important material:
9 - Java HotSpotâ„¢ Client Compiler: www.cdl.uni-saarland.de/ssasem/talks/Christian.Wimmer.pdf
10 - http://www.complang.tuwien.ac.at/andi/185A50
12 - [Poletto:1999] http://dl.acm.org/citation.cfm?doid=330249.330250
13 - [Wimmer:2010] http://dl.acm.org/citation.cfm?id=1772954.1772979
18 module ScratchHS where
21 import qualified Data.Set as Set
23 import Control.Monad.State
26 import Harpy.X86Disassembler
35 import qualified JVM.Assembler as JAsm
38 import Mate.BasicBlocks
40 $(callDecl "callAsWord32" [t|Word32|])
42 data SimpleStack = PushLit Int
48 testP = [PushLit 3, PushLit 2, Mul]
51 data ROp = RMul | RAdd
53 data RegIL = RMov Reg Reg
55 | RBin Reg Reg Reg ROp
57 data MateState = MateState String
59 compileRegIL :: RegIL -> CodeGen (Ptr Int32) MateState ()
60 compileRegIL (RMov t s) = do
62 let (mt,ms) = (eax,eax)
66 entryCode :: CodeGen e s ()
67 entryCode = do push ebp
70 exitCode :: CodeGen e s ()
71 exitCode = do mov esp ebp
77 run :: [RegIL] -> Ptr Int32 -> IO (MateState, Either ErrMsg [Instruction])
78 run program env = let compileAndFeedback = mapM_ compileRegIL program >> disassemble
79 in runCodeGen compileAndFeedback env (MateState "none")
82 -- Allocates a buffer with size n. All zero.
83 emptyMemory :: (Storable a, Num a) => Int -> IO (Ptr a)
84 emptyMemory n = mallocArray n
85 >>= (\ptr -> pokeArray ptr (replicate n 0) >> return ptr)
90 (_, Right code) <- run p' ptr
91 return $ map showIntel code
95 simpleTest = [RMov 0 1]
98 -- Just some class file sand
99 loadMethod methodName classFile = do cls <- parseClassFile classFile
101 return (cls, lookupMethod methodName cls)
104 getFib = do (cls, Just m) <- loadMethod "ackermann" "../tests/Ackermann.class"
107 fibBasicBlocks = do (cls,m) <- getFib
108 hmap <- parseMethod cls "ackermann"
113 {- Thoughs on types and representations
114 - We start from constructing a CFG. What do we need here
115 - ** Fast traversal which is aware of cycles
116 - ** Fast successor, do we need predecessors?
117 - ** Find all paths to current node (including back references)
118 - ** Generic Node type in order to write mentioned operations
119 - generically. There should be no intermediate language "lock in"
120 - i.e. adding another IR should not kill CFG code
121 - Furthermore operations like SSA construction should
122 - not affect the CFG datastructure. Nodes contents should be
123 - interchangable in a way.
124 - ** Some form of unique naming - we would like to identify blocks
125 - and check whether code should be produced for this node
126 - ** Should be Haskell idiomatic - should be composed with
127 - standard haskell infrastructure
128 - ** Convinient printing
130 - From this a inductive type should be appropriate?
134 data G a = Node a (G a) (G a)
138 type LoopCheck a = Set a
141 {- Actually i am not sure about the cata and algebra definition.
143 - check: http://dl.acm.org/citation.cfm?id=128035
146 type TreeAlgebra a r = (a -> r, r -> r -> r)
148 foldG :: TreeAlgebra a r -> r -> G a -> r
149 foldG (f,g) s (Leaf val) = g (f val) s
150 foldG (f,g) s (Node val l r) = g (f val) $ g (foldG (f,g) s l) (foldG (f,g) s r)
152 printG = foldG ((: []), (++)) []
154 loopCheck :: (Ord k) => G a -> (G a -> k) -> State (LoopCheck k) Bool
155 loopCheck g f = do state <- get
156 return $ Set.member (f g) state
158 addNode :: (Ord k) => k -> State (LoopCheck k) ()
159 addNode k = do s <- get
163 foldGM :: (Ord k) => TreeAlgebra a r -> (G a -> k) -> r -> G a -> State (LoopCheck k) r
164 foldGM _ _ s Nil = return s
165 foldGM (f,g) c s k@(Leaf val) = loopCheck k c >>= \p -> if p then return s else return $ g (f val) s
166 foldGM (f,g) c s k@(Node val l r) = loopCheck k c >>= \p -> if p then return s else continue
167 where t = foldGM (f,g) c s
169 continue = do addNode $ c k
172 return $ self $ g left right
175 diamant = let start = Node "a" left right
176 left = Node "l" end Nil
177 right = Node "r" end Nil
178 end = Node "g" start Nil
181 dag = Node "a" (Node "b" (Leaf "c") (Leaf "d")) (Node "b" (Leaf "c") (Leaf "d"))
184 value (Node val _ _) = Just val
185 value (Leaf val ) = Just val
189 printG' :: Ord k => G k -> [k]
190 printG' g = evalState (foldGM ((: []), (++)) (\node -> let (Just v) = value node in v) [] g) Set.empty
195 {- stupid sketch code -}
197 -- actually loop check does not work properly. use monadic version instead
198 foldG' :: (Ord k) => TreeAlgebra a r -> (G a -> k) -> r -> Set k -> G a -> r
199 foldG' (f,g) c s s' Nil = s
200 foldG' (f,g) c s s' k@(Leaf val) = if Set.member (c k) s' then s else g (f val) s
201 foldG' (f,g) c s s' k@(Node val l r) = if Set.member (c k) s' then s
202 else let newState = Set.insert (c k) s'
203 left = foldG' (f,g) c s newState l
204 right = foldG' (f,g) c s newState r
205 in g (f val) $ g left right