- xs' :: [OffIns]
- xs' = markBackwardTargets $ calculateInstructionOffset xs
-
--- get already calculated jmp-targets and mark the predecessor of the
--- target-instruction as "FallThrough". we just care about backwards
--- jumps here (forward jumps are handled in buildCFG')
-markBackwardTargets :: [OffIns] -> [OffIns]
-markBackwardTargets [] = []
-markBackwardTargets (x:[]) = [x]
-markBackwardTargets insns@(x@((x_off,x_bbend),x_ins):y@((y_off,_),_):xs) =
- x_new:markBackwardTargets (y:xs)
- where
- x_new = if isTarget then checkX y_off else x
- checkX w16 = case x_bbend of
- Just _ -> x -- already marked, don't change
- Nothing -> ((x_off, Just $ FallThrough w16), x_ins) -- mark previous insn
-
- -- look through all remaining insns in the stream if there is a jmp to `y'
- isTarget = case find cmpOffset insns of Just _ -> True; Nothing -> False
- cmpOffset ((_,Just (OneTarget w16)),_) = w16 == y_off
- cmpOffset ((_,Just (TwoTarget _ w16)),_) = w16 == y_off
- cmpOffset _ = False
-
-
-buildCFG' :: MapBB -> [OffIns] -> [OffIns] -> MapBB
-buildCFG' hmap [] _ = hmap
-buildCFG' hmap (((off, entry), _):xs) insns = buildCFG' (insertlist entryi hmap) xs insns
- where
- insertlist :: [BlockID] -> MapBB -> MapBB
- insertlist [] hmap' = hmap'
- insertlist (y:ys) hmap' = insertlist ys newhmap
- where
- newhmap = if M.member y hmap' then hmap' else M.insert y value hmap'
- value = parseBasicBlock y insns
- entryi :: [BlockID]
- entryi = if off == 0 then 0:ys else ys -- also consider the entrypoint
- where
- ys = case entry of
- Just (TwoTarget t1 t2) -> [t1, t2]
- Just (OneTarget t) -> [t]
- Just (FallThrough t) -> [t]
- Just Return -> []
- Nothing -> []