void () { final Map<BasicBlock, BasicBlock> subroutines = new LinkedHashMap<>(); for (BasicBlock block : blocks) { if (block.getSeq().getLastInstr().opcode == CodeConstants.opc_jsr) { LinkedList<BasicBlock> stack = new LinkedList<>(); LinkedList<LinkedList<BasicBlock>> stackJsrStacks = new LinkedList<>(); Set<BasicBlock> setVisited = new HashSet<>(); stack.add(block); stackJsrStacks.add(new LinkedList<>()); while (!stack.isEmpty()) { BasicBlock node = stack.removeFirst(); LinkedList<BasicBlock> jsrstack = stackJsrStacks.removeFirst(); setVisited.add(node); switch (node.getSeq().getLastInstr().opcode) { case CodeConstants.opc_jsr -> jsrstack.add(node); case CodeConstants.opc_ret -> { BasicBlock enter = jsrstack.getLast(); BasicBlock exit = blocks.getWithKey(enter.id + 1); // FIXME: find successor in a better way if (exit != null) { if (!node.isSuccessor(exit)) { node.addSuccessor(exit); } jsrstack.removeLast(); subroutines.put(enter, exit); } else { throw new RuntimeException("ERROR: last instruction jsr"); } } } if (!jsrstack.isEmpty()) { for (BasicBlock succ : node.getSuccessors()) { if (!setVisited.contains(succ)) { stack.add(succ); stackJsrStacks.add(new LinkedList<>(jsrstack)); } } } } } } this.subroutines = subroutines; }