fix: much fixes to make things good
Some checks failed
Maven release / build (push) Has been cancelled
Some checks failed
Maven release / build (push) Has been cancelled
This commit is contained in:
parent
54a90cac53
commit
cedcca2f98
2 changed files with 121 additions and 3 deletions
|
@ -2,11 +2,14 @@ package dev.ashhhleyyy.bad;
|
|||
|
||||
import dev.ashhhleyyy.bad.framework.ClassMaker;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.setProperty("ashhhleyyy.bad.framework.dumpClassFiles", "out/bfGenerated");
|
||||
|
||||
System.out.println("Hello world!");
|
||||
|
||||
ClassMaker maker = new ClassMaker("dev/ashhhleyyy/runtime/RuntimeClass_");
|
||||
|
@ -24,10 +27,45 @@ public class Main {
|
|||
bytecode.invokestatic( "java/lang/Integer", "parseInt", "(Ljava/lang/String;I)I");
|
||||
bytecode.ireturn();
|
||||
});
|
||||
|
||||
builder.method(
|
||||
Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC,
|
||||
"iAmALoop",
|
||||
"()V",
|
||||
null,
|
||||
new String[0],
|
||||
bytecode -> {
|
||||
bytecode.startLocal("i", "I", null, 0);
|
||||
bytecode.bipush(0);
|
||||
bytecode.istore(0);
|
||||
LabelNode loopStart = bytecode.label();
|
||||
bytecode.iload(0);
|
||||
bytecode.bipush(10);
|
||||
LabelNode loopBreak = bytecode.if_icmpge();
|
||||
bytecode.getstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
bytecode.ldc("i am a loop");
|
||||
bytecode.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V");
|
||||
|
||||
bytecode.iinc(0, 1);
|
||||
|
||||
bytecode.$goto(loopStart);
|
||||
bytecode.label(loopBreak);
|
||||
bytecode.endLocal("i");
|
||||
|
||||
bytecode.getstatic("java/lang/System", "out", "Ljava/io/PrintStream;");
|
||||
bytecode.ldc("i am not a loop");
|
||||
bytecode.invokevirtual("java/io/PrintStream", "println", "(Ljava/lang/String;)V");
|
||||
|
||||
bytecode.$return();
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Method method = cls.getMethod("toBase10", String.class);
|
||||
int i = (int) method.invoke(null, "10101010");
|
||||
System.out.println(i);
|
||||
|
||||
Method loop = cls.getMethod("iAmALoop");
|
||||
loop.invoke(null);
|
||||
}
|
||||
}
|
|
@ -1,15 +1,20 @@
|
|||
package dev.ashhhleyyy.bad.framework;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.Opcodes;
|
||||
import org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.FieldInsnNode;
|
||||
import org.objectweb.asm.tree.IincInsnNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.IntInsnNode;
|
||||
import org.objectweb.asm.tree.JumpInsnNode;
|
||||
import org.objectweb.asm.tree.LabelNode;
|
||||
import org.objectweb.asm.tree.LdcInsnNode;
|
||||
import org.objectweb.asm.tree.LocalVariableNode;
|
||||
import org.objectweb.asm.tree.MethodInsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import org.objectweb.asm.tree.TypeInsnNode;
|
||||
|
@ -19,13 +24,21 @@ public final class BytecodeBuilder {
|
|||
private final ClassNode classNode;
|
||||
private final MethodNode methodNode;
|
||||
|
||||
private final Map<String, LocalVariableNode> locals;
|
||||
|
||||
private LabelNode currentLabel = null;
|
||||
|
||||
public BytecodeBuilder(ClassNode classNode, MethodNode methodNode) {
|
||||
this.classNode = classNode;
|
||||
this.methodNode = methodNode;
|
||||
this.locals = new HashMap<>();
|
||||
}
|
||||
|
||||
public void add(AbstractInsnNode insn) {
|
||||
this.methodNode.instructions.add(insn);
|
||||
if (!(insn instanceof LabelNode)) {
|
||||
this.currentLabel = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Helpers
|
||||
|
@ -38,6 +51,28 @@ public final class BytecodeBuilder {
|
|||
this.add(new FieldInsnNode(Opcodes.GETFIELD, this.classNode.name, name, desc));
|
||||
}
|
||||
|
||||
// Local variable management
|
||||
|
||||
public void startLocal(String name, String descriptor, String signature, int index) {
|
||||
if (this.locals.containsKey(name)) {
|
||||
throw new IllegalArgumentException("there is already a local called " + name);
|
||||
}
|
||||
LabelNode start = this.label();
|
||||
LocalVariableNode lv = new LocalVariableNode(name, descriptor, signature, start, null, index);
|
||||
this.locals.put(name, lv);
|
||||
}
|
||||
|
||||
public void endLocal(String name) {
|
||||
LocalVariableNode lv = this.locals.get(name);
|
||||
if (lv == null) {
|
||||
throw new IllegalArgumentException("there is no current local variable called " + name);
|
||||
}
|
||||
LabelNode end = this.label();
|
||||
lv.end = end;
|
||||
this.methodNode.localVariables.add(lv);
|
||||
this.locals.remove(name);
|
||||
}
|
||||
|
||||
// Raw instructions
|
||||
|
||||
public void iadd() {
|
||||
|
@ -72,10 +107,22 @@ public final class BytecodeBuilder {
|
|||
this.add(new VarInsnNode(Opcodes.ILOAD, index));
|
||||
}
|
||||
|
||||
public void istore(int index) {
|
||||
this.add(new VarInsnNode(Opcodes.ISTORE, index));
|
||||
}
|
||||
|
||||
public void aload(int index) {
|
||||
this.add(new VarInsnNode(Opcodes.ALOAD, index));
|
||||
}
|
||||
|
||||
public void astore(int index) {
|
||||
this.add(new VarInsnNode(Opcodes.ASTORE, index));
|
||||
}
|
||||
|
||||
public void iinc(int index, int amount) {
|
||||
this.add(new IincInsnNode(index, amount));
|
||||
}
|
||||
|
||||
public void sipush(int operand) {
|
||||
this.add(new IntInsnNode(Opcodes.SIPUSH, operand));
|
||||
}
|
||||
|
@ -92,8 +139,20 @@ public final class BytecodeBuilder {
|
|||
this.add(new TypeInsnNode(Opcodes.ANEWARRAY, type));
|
||||
}
|
||||
|
||||
public void invokedynamic(String owner, String name, String desc) {
|
||||
this.add(new MethodInsnNode(Opcodes.INVOKEDYNAMIC, owner, name, desc));
|
||||
public void getfield(String owner, String name, String desc) {
|
||||
this.add(new FieldInsnNode(Opcodes.GETFIELD, owner, name, desc));
|
||||
}
|
||||
|
||||
public void getstatic(String owner, String name, String desc) {
|
||||
this.add(new FieldInsnNode(Opcodes.GETSTATIC, owner, name, desc));
|
||||
}
|
||||
|
||||
public void invokevirtual(String owner, String name, String desc) {
|
||||
this.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, owner, name, desc));
|
||||
}
|
||||
|
||||
public void invokeinterface(String owner, String name, String desc) {
|
||||
this.add(new MethodInsnNode(Opcodes.INVOKEINTERFACE, owner, name, desc));
|
||||
}
|
||||
|
||||
public void invokespecial(String owner, String name, String desc) {
|
||||
|
@ -104,12 +163,29 @@ public final class BytecodeBuilder {
|
|||
this.add(new MethodInsnNode(Opcodes.INVOKESTATIC, owner, name, desc));
|
||||
}
|
||||
|
||||
private LabelNode getCurrentLabel() {
|
||||
if (this.currentLabel != null) {
|
||||
return this.currentLabel;
|
||||
} else {
|
||||
this.currentLabel = new LabelNode(new Label());
|
||||
return this.currentLabel;
|
||||
}
|
||||
}
|
||||
|
||||
public LabelNode label() {
|
||||
return this.label(new LabelNode(new Label()));
|
||||
return this.label(this.getCurrentLabel());
|
||||
}
|
||||
|
||||
public LabelNode label(LabelNode label) {
|
||||
this.add(label);
|
||||
if (this.currentLabel == null) {
|
||||
this.currentLabel = label;
|
||||
}
|
||||
return label;
|
||||
}
|
||||
|
||||
public LabelNode $goto(LabelNode label) {
|
||||
this.add(new JumpInsnNode(Opcodes.GOTO, label));
|
||||
return label;
|
||||
}
|
||||
|
||||
|
@ -123,6 +199,10 @@ public final class BytecodeBuilder {
|
|||
return label;
|
||||
}
|
||||
|
||||
public LabelNode $goto() {
|
||||
return this.$goto(new LabelNode(new Label()));
|
||||
}
|
||||
|
||||
public LabelNode if_icmpge() {
|
||||
return this.if_icmpge(new LabelNode(new Label()));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue