1 {-# LANGUAGE OverloadedStrings #-}
2 module Mate.X86CodeGen where
8 import qualified Data.Map as M
9 import qualified Data.ByteString.Lazy as B
13 import Foreign.C.Types
17 import qualified JVM.Assembler as J
18 import JVM.Assembler hiding (Instruction)
21 import Harpy.X86Disassembler
23 import Mate.BasicBlocks
26 hmap <- parseMethod "./tests/While.class" "f"
29 Nothing -> putStrLn "sorry, no code generation"
31 let ebb = emitFromBB hmap
32 (_, Right ((entry, bbstarts, jumps), disasm)) <- runCodeGen ebb () ()
33 let int_entry = ((fromIntegral $ ptrToIntPtr entry) :: Int)
34 -- TODO(bernhard): patch jumps
36 mapM_ (putStrLn . showAtt) disasm
37 printf "basicblocks addresses:\n"
38 let b = map (\(x,y) -> (x,y + int_entry)) $ M.toList bbstarts
39 mapM_ (\(x,y) -> printf "\tBasicBlock %2d starts at 0x%08x\n" x y) b
40 printf "stuff to patch:\n"
41 let patching = [ (int_entry + topatch
42 , int_entry + (fromJust $ M.lookup bid bbstarts))
43 | (Jump (bid,topatch)) <- jumps]
44 mapM_ (\(x,y) -> printf "\tpatch jmp @ 0x%08x to address 0x%08x\n" x y) patching
46 type EntryPoint = Ptr Word8
47 type EntryPointOffset = Int
48 type PatchInfo = (BlockID, EntryPointOffset)
49 data Jump = Jump PatchInfo
51 type BBStarts = M.Map BlockID Int
53 type CompileInfo = (EntryPoint, BBStarts, [Jump])
55 emitFromBB :: MapBB -> CodeGen e s (CompileInfo, [Instruction])
60 (bbstarts, jumps) <- efBB (0,(hmap M.! 0)) M.empty
65 return ((ep, bbstarts, jumps), d)
67 efBB :: (BlockID, BasicBlock) -> BBStarts -> CodeGen e s (BBStarts, [Jump])
68 efBB (bid, bb) bbstarts =
69 if M.member bid bbstarts then
73 bb_offset <- getCodeOffset
74 let bbstarts' = M.insert bid bb_offset bbstarts
77 let j = Jump (bid, jj)
79 Return -> return (bbstarts', [])
81 (bbstarts'', jumps) <- efBB (t, hmap M.! t) bbstarts'
82 return (bbstarts'', j:jumps)
84 (bbstarts'', jumps) <- efBB (t1, hmap M.! t1) bbstarts'
85 (bbstarts''', jumps') <- efBB (t2, hmap M.! t2) bbstarts''
86 return (bbstarts''', j:(jumps ++ jumps'))
87 -- TODO(bernhard): also use metainformation
88 -- TODO(bernhard): implement `emit' as function which accepts a list of
89 -- instructions, so we can use patterns for optimizations
90 emit :: J.Instruction -> CodeGen e s ()
92 push (Disp (cArgs_ x), ebp)
95 mov (Disp (cArgs_ x), ebp) eax
96 emit IADD = do pop ebx; pop eax; add eax ebx; push eax
97 emit (IINC x imm) = do
98 add (Disp (cArgs x), ebp) (s8_w32 imm)
100 emit (IF cond _) = do
102 cmp eax (0 :: Word32)
103 -- TODO(bernhard): can we use harpy magic here, in order to avoid patching?
105 -- "patch me" after code generation (here we don't know the address yet)
106 C_EQ -> error "not implemented yet"
107 C_NE -> error "not implemented yet"
108 C_LT -> error "not implemented yet"
109 C_GE -> error "not implemented yet"
110 C_GT -> jg (0xaabbccdd :: Word32)
111 C_LE -> error "not implemented yet"
113 emit IRETURN = do pop eax
114 emit _ = do cmovbe eax eax -- dummy
116 cArgs x = (8 + 4 * (fromIntegral x))
117 cArgs_ x = (8 + 4 * case x of I0 -> 0; I1 -> 1; I2 -> 2; I3 -> 3)
119 -- sign extension from w8 to w32 (over s8)
120 -- unfortunately, hs-java is using Word8 everywhere (while
121 -- it should be Int8 actually)
122 s8_w32 :: Word8 -> Word32
123 s8_w32 w8 = fromIntegral s8
124 where s8 = (fromIntegral w8) :: Int8