X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=Mate%2FBasicBlocks.hs;h=af0074980304d46240f287156071856805b21b32;hb=ecec298c7b0723081b1aea7447eae6f04118df34;hp=179560087db79b55ece4054dec80f1369921fcd1;hpb=a6e23e6cdfff068398a0e50bcd757832554effb5;p=mate.git diff --git a/Mate/BasicBlocks.hs b/Mate/BasicBlocks.hs index 1795600..af00749 100644 --- a/Mate/BasicBlocks.hs +++ b/Mate/BasicBlocks.hs @@ -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 -> "" @@ -107,44 +104,48 @@ 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 :: Code -> MapBB testCFG c = buildCFG (codeInstructions c) (codeExceptions c) - -buildCFG :: [Instruction] -> [CodeException] -> MapBB -buildCFG xs excps = execState (mapM (buildCFG' offins) $ alltargets ++ handlerEntries) M.empty where - (offins, targets) = runState (calculateInstructionOffset tryBlocks xs) S.empty - alltargets = S.toList $ S.insert 0 targets - tryBlocks = map (fromIntegral . eStartPC) excps - handlerEntries = map (fromIntegral . eHandlerPC) excps + buildCFG :: [Instruction] -> [CodeException] -> MapBB + buildCFG xs excps = execState (mapM buildCFG' $ alltargets ++ handlerEntries) M.empty + where + (offins, targets) = runState (calculateInstructionOffset tryBlocks xs) S.empty + alltargets = S.toList $ S.insert 0 targets + tryBlocks = map (fromIntegral . eStartPC) excps + handlerEntries = map (fromIntegral . eHandlerPC) excps -buildCFG' :: [OffIns] -> Int -> State MapBB () -buildCFG' insns off = do - let value = parseBasicBlock off insns - modify (M.insert off value) + 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])