Created
August 24, 2022 22:32
-
-
Save jediminer543/e25e0fe667d891d9c3199685a06e3a11 to your computer and use it in GitHub Desktop.
A utility class for asm stuff; part of a larger project not on git yet
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.jmt.alan.util; | |
import java.util.HashMap; | |
import java.util.Map; | |
import org.objectweb.asm.Opcodes; | |
import org.objectweb.asm.Type; | |
import org.objectweb.asm.tree.AbstractInsnNode; | |
import org.objectweb.asm.tree.FieldInsnNode; | |
import org.objectweb.asm.tree.InsnList; | |
import org.objectweb.asm.tree.InvokeDynamicInsnNode; | |
import org.objectweb.asm.tree.LabelNode; | |
import org.objectweb.asm.tree.LdcInsnNode; | |
import org.objectweb.asm.tree.MethodInsnNode; | |
public class ASMUtil { | |
public static InsnList cloneInsnList(InsnList il) { | |
Map<LabelNode, LabelNode> labelMap = new HashMap<>(); | |
InsnList out = new InsnList(); | |
il.forEach(i -> { | |
if (i instanceof LabelNode) { | |
LabelNode ln = (LabelNode) i; | |
LabelNode nln = new LabelNode(); | |
labelMap.put(ln, nln); | |
out.add(nln); | |
} else { | |
out.add(i.clone(labelMap)); | |
} | |
}); | |
return out; | |
} | |
public static Map<LabelNode, LabelNode> getLabelMap(InsnList il) { | |
Map<LabelNode, LabelNode> labelMap = new HashMap<>(); | |
il.forEach(i -> { | |
if (i instanceof LabelNode) { | |
LabelNode ln = (LabelNode) i; | |
LabelNode nln = new LabelNode(); | |
labelMap.put(ln, nln); | |
} | |
}); | |
return labelMap; | |
} | |
/** | |
* Returns true if the last result in the Instruction list returns a Type 2 value | |
* | |
* This is needed because of how java handles values. | |
* | |
* @param il | |
* @return | |
*/ | |
public static boolean isType2(InsnList il) { | |
AbstractInsnNode ain = il.getLast(); | |
switch (ain.getOpcode()) { | |
// May be type 2 depending on context | |
case Opcodes.LDC: | |
LdcInsnNode lin = (LdcInsnNode) ain; | |
if (lin.cst instanceof Double || lin.cst instanceof Long) | |
return true; | |
return false; | |
case Opcodes.DUP2: | |
case Opcodes.DUP2_X1: | |
case Opcodes.DUP2_X2: | |
// Annoyingly depends on previous insn so recurse | |
InsnList tmp = cloneInsnList(il); | |
tmp.remove(tmp.getLast()); | |
return isType2(tmp); | |
case Opcodes.GETSTATIC: | |
case Opcodes.GETFIELD: | |
FieldInsnNode fin = (FieldInsnNode) ain; | |
Type t = Type.getType(fin.desc); | |
if (t.getSort() == Type.LONG || t.getSort() == Type.DOUBLE) { | |
return true; | |
} else { | |
return false; | |
} | |
case Opcodes.INVOKEVIRTUAL: | |
case Opcodes.INVOKESPECIAL: | |
case Opcodes.INVOKESTATIC: | |
case Opcodes.INVOKEINTERFACE: | |
MethodInsnNode min = (MethodInsnNode) ain; | |
Type rt = Type.getReturnType(min.desc); | |
if (rt.getSort() == Type.LONG || rt.getSort() == Type.DOUBLE) { | |
return true; | |
} else { | |
return false; | |
} | |
case Opcodes.INVOKEDYNAMIC: | |
InvokeDynamicInsnNode idin = (InvokeDynamicInsnNode) ain; | |
Type dt = Type.getReturnType(idin.desc); | |
if (dt.getSort() == Type.LONG || dt.getSort() == Type.DOUBLE) { | |
return true; | |
} else { | |
return false; | |
} | |
// Automatically Type 2 | |
case Opcodes.DCONST_0: | |
case Opcodes.DCONST_1: | |
case Opcodes.LCONST_0: | |
case Opcodes.LCONST_1: | |
case Opcodes.LLOAD: | |
case Opcodes.DLOAD: | |
case Opcodes.LALOAD: | |
case Opcodes.DALOAD: | |
case Opcodes.LADD: | |
case Opcodes.DADD: | |
case Opcodes.LSUB: | |
case Opcodes.DSUB: | |
case Opcodes.LMUL: | |
case Opcodes.DMUL: | |
case Opcodes.LDIV: | |
case Opcodes.DDIV: | |
case Opcodes.LREM: | |
case Opcodes.DREM: | |
case Opcodes.LNEG: | |
case Opcodes.DNEG: | |
case Opcodes.LSHL: | |
case Opcodes.LSHR: | |
case Opcodes.LUSHR: | |
case Opcodes.LAND: | |
case Opcodes.LOR: | |
case Opcodes.LXOR: | |
case Opcodes.I2L: | |
case Opcodes.I2D: | |
case Opcodes.L2D: | |
case Opcodes.F2L: | |
case Opcodes.F2D: | |
case Opcodes.D2L: | |
return true; | |
default: | |
return false; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment