Start working on signature parsing

This commit is contained in:
Victorious3 2023-04-14 11:38:41 +02:00
parent 02c8dd9804
commit 39bde24df7
4 changed files with 124 additions and 31 deletions

View File

@ -1000,7 +1000,7 @@ public class Codegen {
private void generateConstructor(TargetConstructor constructor) {
MethodVisitor mv = cw.visitMethod(constructor.access() | ACC_PUBLIC, "<init>", constructor.getDescriptor(), constructor.getSignature(), null);
if (constructor.txGenerics() != null)
mv.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(constructor.getTXSignature())));
mv.visitAttribute(new JavaTXSignatureAttribute(constructor.getTXSignature()));
mv.visitCode();
var state = new State(null, mv, 1);
@ -1027,7 +1027,7 @@ public class Codegen {
// TODO The older codegen has set ACC_PUBLIC for all methods, good for testing but bad for everything else
MethodVisitor mv = cw.visitMethod(method.access() | ACC_PUBLIC, method.name(), method.getDescriptor(), method.getSignature(), null);
if (method.txSignature() != null) {
mv.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(method.getTXSignature())));
mv.visitAttribute(new JavaTXSignatureAttribute(method.getTXSignature()));
}
System.out.println(method.getDescriptor());
@ -1060,7 +1060,7 @@ public class Codegen {
clazz.implementingInterfaces().stream().map(TargetType::toSignature).toArray(String[]::new)
);
if (clazz.txGenerics() != null)
cw.visitAttribute(new JavaTXSignatureAttribute(cw.newConst(generateSignature(clazz, clazz.txGenerics()))));
cw.visitAttribute(new JavaTXSignatureAttribute(generateSignature(clazz, clazz.txGenerics())));
clazz.fields().forEach(this::generateField);
clazz.constructors().forEach(this::generateConstructor);

View File

@ -3,10 +3,13 @@ package de.dhbwstuttgart.bytecode;
import org.objectweb.asm.*;
public class JavaTXSignatureAttribute extends Attribute {
final int signature;
public String signature;
protected JavaTXSignatureAttribute(int signature) {
public JavaTXSignatureAttribute() {
super("JavaTXSignature");
}
protected JavaTXSignatureAttribute(String signature) {
this();
this.signature = signature;
}
@ -14,13 +17,14 @@ public class JavaTXSignatureAttribute extends Attribute {
protected Attribute read(ClassReader classReader, int offset, int length, char[] charBuffer, int codeAttributeOffset, Label[] labels) {
var data = new byte[length];
System.arraycopy(classReader.b, offset, data, 0, length);
return new JavaTXSignatureAttribute(data[0] << 8 | data[1]);
var constantPoolOffset = data[0] << 8 | data[1];
return new JavaTXSignatureAttribute((String) classReader.readConst(constantPoolOffset, charBuffer));
}
@Override
protected ByteVector write(ClassWriter classWriter, byte[] code, int codeLength, int maxStack, int maxLocals) {
var data = new ByteVector();
data.putShort(this.signature);
data.putShort(classWriter.newConst(this.signature));
return data;
}
}

View File

@ -1,19 +1,16 @@
package de.dhbwstuttgart.syntaxtree.factory;
import java.io.IOException;
import java.lang.reflect.*;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import de.dhbwstuttgart.exceptions.NotImplementedException;
import de.dhbwstuttgart.bytecode.JavaTXSignatureAttribute;
import de.dhbwstuttgart.parser.NullToken;
import de.dhbwstuttgart.parser.SyntaxTreeGenerator.GenericContext;
import de.dhbwstuttgart.parser.scope.JavaClassName;
import de.dhbwstuttgart.parser.scope.JavaClassRegistry;
import de.dhbwstuttgart.syntaxtree.Field;
import de.dhbwstuttgart.syntaxtree.Method;
import de.dhbwstuttgart.syntaxtree.type.*;
@ -21,8 +18,11 @@ import de.dhbwstuttgart.syntaxtree.type.Void;
import de.dhbwstuttgart.syntaxtree.*;
import de.dhbwstuttgart.syntaxtree.statement.Block;
import de.dhbwstuttgart.syntaxtree.statement.Statement;
import de.dhbwstuttgart.syntaxtree.type.WildcardType;
import de.dhbwstuttgart.util.Pair;
import org.antlr.v4.runtime.Token;
import org.objectweb.asm.*;
import org.objectweb.asm.signature.SignatureReader;
import org.objectweb.asm.signature.SignatureVisitor;
/**
* Anmerkung:
@ -32,21 +32,73 @@ import org.antlr.v4.runtime.Token;
public class ASTFactory {
public static ClassOrInterface createClass(java.lang.Class jreClass){
// TODO Inner classes
var methodSignatures = new HashMap<Pair<String, String>, String>();
String classSignature = null;
// Load class with asm to figure out if there's a JavaTX signature
try {
var bytes = Files.readAllBytes(Path.of(jreClass.getProtectionDomain().getCodeSource().getLocation().getPath()));
var classReader = new ClassReader(bytes);
var classVisitor = new ClassVisitor(Opcodes.ASM7) {
String classSignature;
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
classSignature = ((JavaTXSignatureAttribute) attribute).signature;
}
super.visitAttribute(attribute);
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
classSignature = signature;
super.visit(version, access, name, signature, superName, interfaces);
}
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
methodSignatures.put(new Pair<>(name, descriptor), signature);
return new MethodVisitor(Opcodes.ASM7) {
@Override
public void visitAttribute(Attribute attribute) {
if (attribute.type.equals("JavaTXSignature")) {
methodSignatures.put(new Pair<>(name, descriptor), ((JavaTXSignatureAttribute) attribute).signature);
}
super.visitAttribute(attribute);
}
};
}
};
classReader.accept(classVisitor, new Attribute[]{new JavaTXSignatureAttribute()}, ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
classSignature = classVisitor.classSignature;
} catch (IOException e) {
// Skip
}
JavaClassName name = new JavaClassName(jreClass.getName());
List<Method> methoden = new ArrayList<>();
List<de.dhbwstuttgart.syntaxtree.Constructor> konstruktoren = new ArrayList<>();
for(java.lang.reflect.Constructor constructor : jreClass.getConstructors()){
createConstructor(constructor, jreClass).map(c -> konstruktoren.add(c));
var signature = methodSignatures.get(new Pair<>(constructor.getName(), org.objectweb.asm.Type.getConstructorDescriptor(constructor)));
createConstructor(constructor, signature, jreClass).map(c -> konstruktoren.add(c));
}
Set<java.lang.reflect.Method> allMethods = new HashSet<>(Arrays.asList(jreClass.getMethods()));
Set<java.lang.reflect.Method> allDeclaredMethods = new HashSet<>(Arrays.asList(jreClass.getDeclaredMethods()));
Set<java.lang.reflect.Method> allInheritedMethods = new HashSet<>(allMethods);
allInheritedMethods.removeAll(allDeclaredMethods);
for(java.lang.reflect.Method method : allDeclaredMethods){
methoden.add(createMethod(method, jreClass, false));
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, false));
}
for(java.lang.reflect.Method method : allInheritedMethods){
methoden.add(createMethod(method, jreClass, true));
var signature = methodSignatures.get(new Pair<>(method.getName(), org.objectweb.asm.Type.getMethodDescriptor(method)));
methoden.add(createMethod(method, signature, jreClass, true));
}
List<Field> felder = new ArrayList<>();
for(java.lang.reflect.Field field : jreClass.getDeclaredFields()){
@ -72,7 +124,8 @@ public class ASTFactory {
for(Type jreInterface : jreClass.getGenericInterfaces()){
implementedInterfaces.add((RefType) createType(jreInterface));
}
GenericDeclarationList genericDeclarationList = createGenerics(jreClass.getTypeParameters(), jreClass, null);
GenericDeclarationList genericDeclarationList = createGenerics(classSignature, jreClass, null);
Token offset = new NullToken(); //Braucht keinen Offset, da diese Klasse nicht aus einem Quellcode geparst wurde
@ -87,7 +140,7 @@ public class ASTFactory {
// return createClass(classType).getType();
//}
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, Class inClass) {
private static Optional<de.dhbwstuttgart.syntaxtree.Constructor> createConstructor(Constructor constructor, String signature, Class inClass) {
String name = constructor.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType = createType(inClass);
Parameter[] jreParams = constructor.getParameters();
@ -101,7 +154,7 @@ public class ASTFactory {
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(constructor.getTypeParameters(), inClass, constructor.getName());
GenericDeclarationList gtvDeclarations = createGenerics(signature, inClass, constructor.getName());
Token offset = new NullToken();
int modifier = constructor.getModifiers();
@ -112,7 +165,7 @@ public class ASTFactory {
return Optional.of(new de.dhbwstuttgart.syntaxtree.Constructor(modifier, name,returnType, parameterList, block, gtvDeclarations, offset /*, new ArrayList<>() geloescht PL 2018-11-24 */));
}
public static Method createMethod(java.lang.reflect.Method jreMethod, java.lang.Class inClass, Boolean isInherited){
public static Method createMethod(java.lang.reflect.Method jreMethod, String signature, java.lang.Class inClass, Boolean isInherited){
String name = jreMethod.getName();
RefTypeOrTPHOrWildcardOrGeneric returnType;
Type jreRetType;
@ -133,18 +186,53 @@ public class ASTFactory {
}
ParameterList parameterList = new ParameterList(params, new NullToken());
Block block = new Block(new ArrayList<Statement>(), new NullToken());
GenericDeclarationList gtvDeclarations = createGenerics(jreMethod.getTypeParameters(), inClass, jreMethod.getName());
GenericDeclarationList gtvDeclarations = createGenerics(signature, inClass, jreMethod.getName());
Token offset = new NullToken();
return new Method(jreMethod.getModifiers(), name,returnType, parameterList, block, gtvDeclarations, offset, isInherited);
}
public static GenericDeclarationList createGenerics(TypeVariable[] typeParameters, Class context, String methodName){
List<de.dhbwstuttgart.syntaxtree.GenericTypeVar> gtvs = new ArrayList<>();
for(TypeVariable jreTV : typeParameters){
de.dhbwstuttgart.syntaxtree.GenericTypeVar gtv = createGeneric(jreTV, jreTV.getName(), context, methodName);
gtvs.add(gtv);
}
public static GenericDeclarationList createGenerics(String signature, Class context, String methodName){
var gtvs = new ArrayList<GenericTypeVar>();
var signatureVisitor = new SignatureVisitor(Opcodes.ASM7) {
List<RefTypeOrTPHOrWildcardOrGeneric> bounds = new ArrayList<>();
Stack<RefTypeOrTPHOrWildcardOrGeneric> bound = new Stack<>();
@Override
public void visitFormalTypeParameter(String name) {
bounds = new ArrayList<>();
gtvs.add(new GenericTypeVar(name, bounds, new NullToken(), new NullToken()));
}
@Override
public void visitTypeVariable(String name) {
((RefType) bound.peek()).getParaList().add(new GenericRefType(name, new NullToken()));
}
@Override
public void visitClassType(String name) {
var currentBound = new RefType(new JavaClassName(name), new ArrayList<>(), new NullToken());
bound.push(currentBound);
}
@Override
public SignatureVisitor visitTypeArgument(char wildcard) {
return this;
}
@Override
public void visitEnd() {
var last = bound.pop();
if (bound.empty()) bounds.add(last);
else {
((RefType) bound.peek()).getParaList().add(last);
}
}
};
var sr = new SignatureReader(signature);
sr.accept(signatureVisitor);
return new GenericDeclarationList(gtvs,new NullToken());
}

View File

@ -16,6 +16,7 @@ import de.dhbwstuttgart.target.tree.expression.TargetExpression;
import de.dhbwstuttgart.target.tree.type.*;
import de.dhbwstuttgart.typeinference.constraints.Pair;
import de.dhbwstuttgart.typeinference.result.*;
import org.objectweb.asm.Attribute;
import java.util.*;
import java.util.stream.Collectors;