Search in sources :

Example 1 with IndexedList

use of org.mapleir.stdlib.util.IndexedList in project maple-ir by LLVM-but-worse.

the class ControlFlowGraphDumper method linearize.

private void linearize() {
    if (cfg.getEntries().size() != 1)
        throw new IllegalStateException("CFG doesn't have exactly 1 entry");
    BasicBlock entry = cfg.getEntries().iterator().next();
    // Build bundle graph
    Map<BasicBlock, BlockBundle> bundles = new HashMap<>();
    Map<BlockBundle, List<BlockBundle>> bunches = new HashMap<>();
    // Build bundles
    List<BasicBlock> topoorder = new SimpleDfs<>(cfg, entry, SimpleDfs.TOPO).getTopoOrder();
    for (BasicBlock b : topoorder) {
        if (// Already in a bundle
        bundles.containsKey(b))
            continue;
        if (// Look for heads of bundles only
        b.getIncomingImmediateEdge() != null)
            continue;
        BlockBundle bundle = new BlockBundle();
        while (b != null) {
            bundle.add(b);
            bundles.put(b, bundle);
            b = b.getImmediate();
        }
        List<BlockBundle> bunch = new ArrayList<>();
        bunch.add(bundle);
        bunches.put(bundle, bunch);
    }
    // Group bundles by exception ranges
    for (ExceptionRange<BasicBlock> range : cfg.getRanges()) {
        BlockBundle prevBundle = null;
        for (BasicBlock b : range.getNodes()) {
            BlockBundle curBundle = bundles.get(b);
            if (prevBundle == null) {
                prevBundle = curBundle;
                continue;
            }
            if (curBundle != prevBundle) {
                List<BlockBundle> bunchA = bunches.get(prevBundle);
                List<BlockBundle> bunchB = bunches.get(curBundle);
                if (bunchA != bunchB) {
                    bunchA.addAll(bunchB);
                    for (BlockBundle bundle : bunchB) {
                        bunches.put(bundle, bunchA);
                    }
                }
                prevBundle = curBundle;
            }
        }
    }
    // Rebuild bundles
    bundles.clear();
    for (Map.Entry<BlockBundle, List<BlockBundle>> e : bunches.entrySet()) {
        BlockBundle bundle = e.getKey();
        if (bundles.containsKey(bundle.getFirst()))
            continue;
        BlockBundle bunch = new BlockBundle();
        e.getValue().forEach(bunch::addAll);
        for (BasicBlock b : bunch) bundles.put(b, bunch);
    }
    // Connect bundle graph
    BundleGraph bundleGraph = new BundleGraph();
    BlockBundle entryBundle = bundles.get(entry);
    bundleGraph.addVertex(entryBundle);
    for (BasicBlock b : topoorder) {
        for (FlowEdge<BasicBlock> e : cfg.getEdges(b)) {
            if (e instanceof ImmediateEdge)
                continue;
            BlockBundle src = bundles.get(b);
            bundleGraph.addEdge(src, new FastGraphEdgeImpl<>(src, bundles.get(e.dst())));
        }
    }
    // Linearize & flatten
    order = new IndexedList<>();
    // for efficiency
    Set<BlockBundle> bundlesSet = new HashSet<>(bundles.values());
    ControlFlowGraphDumper.linearize(bundlesSet, bundleGraph, entryBundle).forEach(order::addAll);
}
Also used : ImmediateEdge(org.mapleir.flowgraph.edges.ImmediateEdge) BasicBlock(org.mapleir.ir.cfg.BasicBlock) IndexedList(org.mapleir.stdlib.util.IndexedList)

Aggregations

ImmediateEdge (org.mapleir.flowgraph.edges.ImmediateEdge)1 BasicBlock (org.mapleir.ir.cfg.BasicBlock)1 IndexedList (org.mapleir.stdlib.util.IndexedList)1