Skip to content

Instantly share code, notes, and snippets.

@jediminer543
Created August 24, 2022 22:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jediminer543/e25e0fe667d891d9c3199685a06e3a11 to your computer and use it in GitHub Desktop.
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
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