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);
}
Aggregations