package org.openrs2.deob.bytecode.analysis import it.unimi.dsi.fastutil.ints.IntOpenHashSet import it.unimi.dsi.fastutil.ints.IntSet import it.unimi.dsi.fastutil.ints.IntSets import org.objectweb.asm.Opcodes import org.objectweb.asm.tree.AbstractInsnNode import org.objectweb.asm.tree.IincInsnNode import org.objectweb.asm.tree.MethodNode import org.objectweb.asm.tree.VarInsnNode public class LiveVariableAnalyzer(owner: String, method: MethodNode) : DataFlowAnalyzer(owner, method, backwards = true) { override fun createInitialSet(): IntSet { return IntSets.EMPTY_SET } override fun join(set1: IntSet, set2: IntSet): IntSet { return set1 union set2 } override fun transfer(set: IntSet, insn: AbstractInsnNode): IntSet { return when (insn) { is VarInsnNode -> when (insn.opcode) { Opcodes.ILOAD, Opcodes.LLOAD, Opcodes.FLOAD, Opcodes.DLOAD, Opcodes.ALOAD -> set.plus(insn.`var`) Opcodes.ISTORE, Opcodes.LSTORE, Opcodes.FSTORE, Opcodes.DSTORE, Opcodes.ASTORE -> set.minus(insn.`var`) else -> set } is IincInsnNode -> set.plus(insn.`var`) else -> set } } private infix fun IntSet.union(other: IntSet): IntSet { if (this == other || other.isEmpty()) { return this } else if (isEmpty()) { return other } val set = IntOpenHashSet(this) set.addAll(other) return set } private fun IntSet.plus(element: Int): IntSet { if (contains(element)) { return this } else if (isEmpty()) { return IntSets.singleton(element) } val newSet = IntOpenHashSet(this) newSet.add(element) return newSet } private fun IntSet.minus(element: Int): IntSet { if (!contains(element)) { return this } else if (size == 1) { return IntSets.EMPTY_SET } val newSet = IntOpenHashSet(this) newSet.remove(element) return newSet } }