basicblock: store length of basiblock (i.e. bytes of instructionstream)
authorBernhard Urban <lewurm@gmail.com>
Sun, 9 Sep 2012 12:24:01 +0000 (14:24 +0200)
committerBernhard Urban <lewurm@gmail.com>
Sun, 9 Sep 2012 16:00:08 +0000 (18:00 +0200)
Mate/BasicBlocks.hs
Mate/Types.hs

index 5b68cfb7b87bd04c7e74f4d37665d81e200f9d02..af0074980304d46240f287156071856805b21b32 100644 (file)
@@ -36,13 +36,10 @@ type BBState = S.Set Target
 type AnalyseState = State BBState [OffIns]
 
 
-noException :: B.ByteString
-noException = B.empty
-
 emptyBasicBlock :: BasicBlock
 emptyBasicBlock = BasicBlock
                     { code = []
-                    , exception = noException
+                    , bblength = 0
                     , successor = Return }
 
 printMapBB :: MapBB -> IO ()
@@ -57,7 +54,7 @@ printMapBB hmap = do
       printMapBB' [] _ = return ()
       printMapBB' (i:is) hmap' = case M.lookup i hmap' of
         Just bb -> do
-          printfBb $ "Block " ++ show i ++ "\n"
+          printfBb $ "Block " ++ show i ++ ". len: " ++ (show $ bblength bb) ++ "\n"
           mapM_ (printfBb . flip (++) "\n" . (++) "\t" . show) $ code bb
           printfBb $ case successor bb of
             Return -> ""
@@ -98,7 +95,7 @@ parseMethod cls methodname sig = do
                 (error $ "codeseg " ++ (show . toString) methodname ++ " not found")
                 (attrByName method "Code")
   let decoded = decodeMethod codeseg
-  let mapbb = testCFG cls decoded
+  let mapbb = testCFG decoded
   let locals = fromIntegral (codeMaxLocals decoded)
   let stacks = fromIntegral (codeStackSize decoded)
   let codelen = fromIntegral (codeLength decoded)
@@ -107,24 +104,25 @@ parseMethod cls methodname sig = do
   let nametype = methodNameType methoddirect
   let argscount = methodGetArgsCount nametype + (if isStatic then 0 else 1)
 
-  -- TODO: remove ;-)
-  -- small example how to get information about
-  -- exceptions of a method
-  let (Just m) = lookupMethodSig methodname sig cls
-  case attrByName m "Code" of
-    Nothing ->
-      printfBb $ printf "exception: no handler for this method\n"
-    Just exceptionstream ->
-      printfBb $ printf "exception: \"%s\"\n" (show $ codeExceptions $ decodeMethod exceptionstream)
-  -- [/remove]
+  let exceptionMap :: ExceptionMap
+      exceptionMap = foldl f M.empty $ codeExceptions decoded
+        where
+          f emap ce =
+            if M.member key emap
+              then M.adjust (value:) key emap
+              else M.insert key [value] emap
+              where
+                key = (&&&) eStartPC eEndPC ce
+                value = (&&&) (buildClassID cls . eCatchType) eHandlerPC ce
+
   let msig = methodSignature method
   printfBb $ printf "BB: analysing \"%s\"\n" $ toString (methodname `B.append` ": " `B.append` encode msig)
   printMapBB mapbb
-  return $ RawMethod mapbb locals stacks argscount codelen
+  return $ RawMethod mapbb exceptionMap locals stacks argscount codelen
 
 
-testCFG :: Class Direct -> Code -> MapBB
-testCFG cls c = buildCFG (codeInstructions c) (codeExceptions c)
+testCFG :: Code -> MapBB
+testCFG c = buildCFG (codeInstructions c) (codeExceptions c)
   where
     buildCFG :: [Instruction] -> [CodeException] -> MapBB
     buildCFG xs excps = execState (mapM buildCFG' $ alltargets ++ handlerEntries) M.empty
@@ -134,28 +132,20 @@ testCFG cls c = buildCFG (codeInstructions c) (codeExceptions c)
       tryBlocks = map (fromIntegral . eStartPC) excps
       handlerEntries = map (fromIntegral . eHandlerPC) excps
 
-      exceptionMap :: M.Map (Word16, Word16) [(B.ByteString, Word16)]
-      exceptionMap = foldl f M.empty excps
-        where
-          f emap ce =
-            if M.member key emap
-              then M.adjust (value:) key emap
-              else M.insert key [value] emap
-              where
-                key = (&&&) eStartPC eEndPC ce
-                value = (&&&) (buildClassID cls . eCatchType) eHandlerPC ce
-
       buildCFG' :: Int -> State MapBB ()
       buildCFG' off = do
         let value = parseBasicBlock off offins
         modify (M.insert off value)
 
 parseBasicBlock :: Int -> [OffIns] -> BasicBlock
-parseBasicBlock i insns = emptyBasicBlock { code = insonly, successor = endblock }
+parseBasicBlock i insns = emptyBasicBlock
+          { code = insonly
+          , bblength = lastoff - i + (insnLength lastins)
+          , successor = endblock }
   where
     (lastblock, is) = takeWhilePlusOne validins omitins insns
     (_, _, insonly) = unzip3 is
-    (_, Just endblock, _) = fromJust lastblock
+    (lastoff, Just endblock, lastins) = fromJust lastblock
 
     -- also take last (non-matched) element and return it
     takeWhilePlusOne :: (a -> Bool) -> (a -> Bool) -> [a] -> (Maybe a, [a])
index de17e3780aa4cf8c695e72ce4a6891fb505a64e8..bff97df650a9b87d0679c643e010dd199c71a259 100644 (file)
@@ -4,6 +4,7 @@ module Mate.Types
   , BasicBlock(..)
   , BBEnd(..)
   , MapBB
+  , ExceptionMap
   , RawMethod(..)
   , TrapMap, MethodMap, ClassMap, FieldMap
   , StringMap, VirtualMap, InterfaceMap
@@ -23,6 +24,7 @@ module Mate.Types
 
 import Data.Int
 import Data.Functor
+import Data.Word
 import qualified Data.Map as M
 import qualified Data.ByteString.Lazy as B
 
@@ -42,7 +44,7 @@ type BlockID = Int
 -- Represents a CFG node
 data BasicBlock = BasicBlock {
   code :: [Instruction],
-  exception :: B.ByteString,
+  bblength :: Int,
   successor :: BBEnd }
 
 -- describes (leaving) edges of a CFG node
@@ -54,9 +56,11 @@ data BBEnd
   deriving Show
 
 type MapBB = M.Map BlockID BasicBlock
+type ExceptionMap = M.Map (Word16, Word16) [(B.ByteString, Word16)]
 
 data RawMethod = RawMethod {
   rawMapBB :: MapBB,
+  rawExcpMap :: ExceptionMap,
   rawLocals :: Int,
   rawStackSize :: Int,
   rawArgCount :: NativeWord,