1 {-# LANGUAGE OverloadedStrings #-}
2 module Mate.BasicBlocks where
6 import System.Environment
7 import qualified Data.Map as M
8 import qualified Data.ByteString.Lazy as B
18 type Name = String -- use "virtual register id" instead?
19 data Type = JInt | JFloat -- add more
20 type Variable = (Type,Name)
22 -- Represents a CFG node
23 data BasicBlock = BasicBlock {
25 outputs :: [Variable],
26 code :: [Instruction] }
28 -- Represents a Control-Flow-Graph as
29 -- Adjacency list (add matrix representation if appropriate)
30 type CFList = [(BasicBlock, [BasicBlock])]
36 [clspath] -> parseFile clspath "fib" -- TODO
37 _ -> error "Synopsis: dump-class File.class"
40 parseFile :: String -> B.ByteString -> IO ()
41 parseFile clspath method = do
42 --clsFile <- decodeFile clspath
43 --putStrLn $ showListIx $ M.assocs $ constsPool (clsFile :: Class Pointers)
44 cls <- parseClassFile clspath
46 let mainmethod = lookupMethod method cls -- "main|([Ljava/lang/String;)V" cf
47 mapM_ putStrLn (testCFG mainmethod)
49 test_01 = parseFile "./tests/Fib.class" "fib"
50 test_02 = parseFile "./tests/While.class" "f"
51 test_03 = parseFile "./tests/While.class" "g"
54 testCFG :: Maybe (Method Resolved) -> [String]
55 testCFG (Just m) = case attrByName m "Code" of
56 Nothing -> error "no code"
57 Just bytecode -> let code = decodeMethod bytecode
58 instructions = codeInstructions code
59 in buildCFG instructions
60 testCFG _ = error "no method to build cfg"
63 buildCFG :: [Instruction] -> [String]
64 buildCFG xs = map (\(x,y) -> show x ++ ", " ++ show y) xs'
66 xs' = calculateInstructionOffset xs
68 type Offset = (Int, Maybe Int16) -- (offset in bytecode, offset to jump target)
70 calculateInstructionOffset :: [Instruction] -> [(Offset, Instruction)]
71 calculateInstructionOffset = cio' (0, Nothing)
73 newoffset :: Instruction -> Int -> Offset
74 newoffset x off = (off + (fromIntegral $ B.length $ encodeInstructions [x]), Nothing)
75 cio' :: Offset -> [Instruction] -> [(Offset, Instruction)]
77 -- TODO(bernhard): add more instruction with offset (IF_ACMP, JSR, ...)
78 -- TODO(bernhard): beautiful code please (BCP)
79 cio' (off,_) (x@(IF _ w16):xs) = ((off, Just $ fromIntegral w16), x):(cio' (newoffset x off) xs)
80 cio' (off,_) (x@(IF_ICMP _ w16):xs) = ((off, Just $ fromIntegral w16), x):(cio' (newoffset x off) xs)
81 cio' (off,_) (x@(GOTO w16):xs) = ((off, Just $ fromIntegral w16), x):(cio' (newoffset x off) xs)
82 cio' (off,_) (x:xs) = ((off, Nothing), x):(cio' (newoffset x off) xs)