Skip to content

Commit bd481cf

Browse files
committed
Working on type system and full global dependency resolution
1 parent 3284e21 commit bd481cf

15 files changed

Lines changed: 309 additions & 40 deletions

src/main/java/de/mirkosertic/metair/ir/ClassModelFactory.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010

1111
public final class ClassModelFactory {
1212

13+
public static final ClassDesc TEST_CLASS = ClassDesc.of("de.mirkosertic.test", "Test");
14+
1315
private ClassModelFactory() {
1416
}
1517

1618
public static ClassModel createModelFrom(final Consumer<ClassBuilder> consumer) throws IOException {
1719
final File temp = File.createTempFile("code", ".class");
18-
ClassFile.of().buildTo(temp.toPath(), ClassDesc.of("de.mirkosertic.test", "Test"), consumer);
20+
ClassFile.of().buildTo(temp.toPath(), TEST_CLASS, consumer);
1921
return ClassFile.of().parse(temp.toPath());
2022
}
2123
}

src/main/java/de/mirkosertic/metair/ir/MethodAnalyzer.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,6 +1600,8 @@ private void parse_INVOKESPECIAL(final ClassDesc owner, final String methodName,
16001600

16011601
final Value target = outgoing.pop();
16021602

1603+
final ResolvedMethod resolvedMethod = resolverContext.resolveInvokeSpecial(owner, methodName, methodTypeDesc);
1604+
16031605
final Value next = new InvokeSpecial(resolverContext.resolveType(owner), target, methodName, resolverContext.resolveMethodType(methodTypeDesc), arguments.reversed());
16041606
outgoing.control = outgoing.control.controlFlowsTo(next, FlowType.FORWARD);
16051607
outgoing.memory = outgoing.memory.memoryFlowsTo(next);
@@ -1628,6 +1630,8 @@ private void parse_INVOKEVIRTUAL(final ClassDesc owner, final String methodName,
16281630

16291631
final Value target = outgoing.pop();
16301632

1633+
final ResolvedMethod resolvedMethod = resolverContext.resolveInvokeVirtual(owner, methodName, methodTypeDesc);
1634+
16311635
final Invoke invoke = new InvokeVirtual(resolverContext.resolveType(owner), target, methodName, resolverContext.resolveMethodType(methodTypeDesc), arguments.reversed());
16321636

16331637
outgoing.control = outgoing.control.controlFlowsTo(invoke, FlowType.FORWARD);
@@ -1656,6 +1660,8 @@ private void parse_INVOKEINTERFACE(final ClassDesc owner, final String methodNam
16561660

16571661
final Value target = outgoing.pop();
16581662

1663+
final ResolvedMethod resolvedMethod = resolverContext.resolveInvokeInterface(owner, methodName, methodTypeDesc);
1664+
16591665
final Invoke invoke = new InvokeInterface(resolverContext.resolveType(owner), target, methodName, resolverContext.resolveMethodType(methodTypeDesc), arguments.reversed());
16601666

16611667
outgoing.control = outgoing.control.controlFlowsTo(invoke, FlowType.FORWARD);
@@ -1676,6 +1682,8 @@ private void parse_INVOKESTATIC(final ClassDesc owner, final String methodName,
16761682
final Status outgoing = frame.copyIncomingToOutgoing();
16771683
assertMinimumStackSize(outgoing, args.length);
16781684

1685+
final ResolvedMethod resolvedMethod = resolverContext.resolveInvokeStatic(owner, methodName, methodTypeDesc);
1686+
16791687
final RuntimeclassReference runtimeClass = outgoing.control.defineRuntimeclassReference(resolverContext.resolveType(owner));
16801688
final ClassInitialization init = new ClassInitialization(runtimeClass);
16811689

@@ -1949,6 +1957,8 @@ private void parse_GETFIELD(final ClassDesc owner, final ClassDesc fieldType, fi
19491957
final Status outgoing = frame.copyIncomingToOutgoing();
19501958
assertMinimumStackSize(outgoing, 1);
19511959

1960+
resolverContext.resolveMemberField(owner, fieldName, fieldType);
1961+
19521962
final Value v = outgoing.pop();
19531963
final GetField get = new GetField(resolverContext.resolveType(owner), resolverContext.resolveType(fieldType), fieldName, v);
19541964
outgoing.push(get);
@@ -1960,6 +1970,8 @@ private void parse_PUTFIELD(final ClassDesc owner, final ClassDesc fieldType, fi
19601970
final Status outgoing = frame.copyIncomingToOutgoing();
19611971
assertMinimumStackSize(outgoing, 2);
19621972

1973+
resolverContext.resolveMemberField(owner, fieldName, fieldType);
1974+
19631975
final Value v = outgoing.pop();
19641976
final Value target = outgoing.pop();
19651977

@@ -1972,6 +1984,8 @@ private void parse_PUTFIELD(final ClassDesc owner, final ClassDesc fieldType, fi
19721984
private void parse_GETSTATIC(final ClassDesc owner, final ClassDesc fieldType, final String fieldName, final Frame frame) {
19731985
final Status outgoing = frame.copyIncomingToOutgoing();
19741986

1987+
resolverContext.resolveStaticField(owner, fieldName, fieldType);
1988+
19751989
final RuntimeclassReference ri = outgoing.control.defineRuntimeclassReference(resolverContext.resolveType(owner));
19761990
final ClassInitialization init = new ClassInitialization(ri);
19771991

@@ -1988,6 +2002,8 @@ private void parse_PUTSTATIC(final ClassDesc owner, final ClassDesc fieldType, f
19882002
final Status outgoing = frame.copyIncomingToOutgoing();
19892003
assertMinimumStackSize(outgoing, 1);
19902004

2005+
resolverContext.resolveStaticField(owner, fieldName, fieldType);
2006+
19912007
final RuntimeclassReference ri = outgoing.control.defineRuntimeclassReference(resolverContext.resolveType(owner));
19922008
final ClassInitialization init = new ClassInitialization(ri);
19932009

@@ -2004,6 +2020,8 @@ private void parse_PUTSTATIC(final ClassDesc owner, final ClassDesc fieldType, f
20042020
private void parse_NEW(final ClassDesc type, final Frame frame) {
20052021
final Status outgoing = frame.copyIncomingToOutgoing();
20062022

2023+
resolverContext.resolveClass(type);
2024+
20072025
final RuntimeclassReference ri = outgoing.control.defineRuntimeclassReference(resolverContext.resolveType(type));
20082026
final ClassInitialization init = new ClassInitialization(ri);
20092027

src/main/java/de/mirkosertic/metair/ir/NumericCondition.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public enum Operation {
99
public final Operation operation;
1010

1111
NumericCondition(final Operation operation, final Value a, final Value b) {
12-
super(IRType.MetaClass.CD_int);
12+
super(IRType.CD_int);
1313

1414
this.operation = operation;
1515

src/main/java/de/mirkosertic/metair/ir/ReferenceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public enum Operation {
99
public final Operation operation;
1010

1111
ReferenceTest(final Operation operation, final Value a) {
12-
super(IRType.MetaClass.CD_int);
12+
super(IRType.CD_int);
1313

1414
this.operation = operation;
1515

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,112 @@
11
package de.mirkosertic.metair.ir;
22

3-
import java.lang.classfile.ClassFile;
43
import java.lang.classfile.ClassModel;
4+
import java.lang.classfile.FieldModel;
5+
import java.lang.classfile.MethodModel;
6+
import java.lang.constant.MethodTypeDesc;
7+
import java.lang.reflect.AccessFlag;
8+
import java.util.ArrayList;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
512

613
public class ResolvedClass {
714

815
private final ResolverContext resolverContext;
9-
private ClassFile classFile;
1016
private ClassModel classModel;
1117
private boolean loaded;
18+
private ResolvedClass superClass;
19+
private final List<ResolvedClass> interfaces;
20+
private IRType.MetaClass thisType;
21+
private final Map<String, ResolvedField> fields;
1222

1323
public ResolvedClass(final ResolverContext resolverContext) {
1424
this.loaded = false;
1525
this.resolverContext = resolverContext;
26+
this.interfaces = new ArrayList<>();
27+
this.superClass = null;
28+
this.fields = new HashMap<>();
1629
}
1730

1831
public boolean isLoaded() {
1932
return loaded;
2033
}
2134

22-
public void loaded(final ClassFile classFile, final ClassModel classModel) {
23-
this.classFile = classFile;
35+
public void loaded(final ClassModel classModel, final ResolvedClass superClass, final List<ResolvedClass> interfaces) {
2436
this.classModel = classModel;
2537
this.loaded = true;
38+
this.superClass = superClass;
39+
this.interfaces.addAll(interfaces);
40+
41+
this.thisType = IRType.MetaClass.of(classModel.thisClass().asSymbol());
42+
43+
for (final MethodModel methodModel : classModel.methods()) {
44+
if (!methodModel.flags().has(AccessFlag.ABSTRACT) && !methodModel.flags().has(AccessFlag.NATIVE) && "<clinit>".equals(methodModel.methodName().stringValue())) {
45+
// We need to resolve a static class initializers
46+
resolveMethod(methodModel);
47+
}
48+
}
49+
}
50+
51+
public ResolvedMethod resolveMethodForSpecialInvocation(final String methodName, final MethodTypeDesc methodTypeDesc) {
52+
for (final MethodModel methodModel : classModel.methods()) {
53+
if (methodModel.methodName().stringValue().equals(methodName) && methodModel.methodTypeSymbol().equals(methodTypeDesc)) {
54+
return resolveMethod(methodModel);
55+
}
56+
}
57+
throw new IllegalArgumentException("Cannot find method " + methodName + " with type " + TypeUtils.toString(methodTypeDesc));
58+
}
59+
60+
public ResolvedMethod resolveMethodForStaticInvocation(final String methodName, final MethodTypeDesc methodTypeDesc) {
61+
for (final MethodModel methodModel : classModel.methods()) {
62+
if (methodModel.methodName().stringValue().equals(methodName) && methodModel.methodTypeSymbol().equals(methodTypeDesc)) {
63+
return resolveMethod(methodModel);
64+
}
65+
}
66+
throw new IllegalArgumentException("Cannot find method " + methodName + " with type " + TypeUtils.toString(methodTypeDesc));
67+
}
68+
69+
public ResolvedMethod resolveMethod(final MethodModel methodModel) {
70+
return new ResolvedMethod(resolverContext, this, methodModel);
2671
}
2772

2873
public ClassModel classModel() {
2974
return classModel;
3075
}
76+
77+
public IRType.MetaClass thisType() {
78+
return thisType;
79+
}
80+
81+
public ResolvedField resolveStaticField(final String fieldName) {
82+
return fields.computeIfAbsent(fieldName, key -> {
83+
for (final FieldModel fieldModel : classModel.fields()) {
84+
if (fieldModel.flags().has(AccessFlag.STATIC) && fieldName.equals(fieldModel.fieldName().stringValue())) {
85+
final IRType.MetaClass type = resolverContext.resolveType(fieldModel.fieldTypeSymbol());
86+
return new ResolvedField(ResolvedClass.this, key, type, fieldModel);
87+
}
88+
}
89+
// TODO: Check in class hierarchy
90+
if (superClass != null) {
91+
return superClass.resolveStaticField(fieldName);
92+
}
93+
throw new IllegalArgumentException("Cannot find static field " + key + " in class " + TypeUtils.toString(ResolvedClass.this.thisType()));
94+
});
95+
}
96+
97+
public ResolvedField resolveMemberField(final String fieldName) {
98+
return fields.computeIfAbsent(fieldName, key -> {
99+
for (final FieldModel fieldModel : classModel.fields()) {
100+
if (!fieldModel.flags().has(AccessFlag.STATIC) && fieldName.equals(fieldModel.fieldName().stringValue())) {
101+
final IRType.MetaClass type = resolverContext.resolveType(fieldModel.fieldTypeSymbol());
102+
return new ResolvedField(ResolvedClass.this, key, type, fieldModel);
103+
}
104+
}
105+
// TODO: Check in class hierarchy
106+
if (superClass != null) {
107+
return superClass.resolveMemberField(fieldName);
108+
}
109+
throw new IllegalArgumentException("Cannot find field " + key + " in class " + TypeUtils.toString(ResolvedClass.this.thisType()));
110+
});
111+
}
31112
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package de.mirkosertic.metair.ir;
2+
3+
import java.lang.classfile.FieldModel;
4+
5+
public class ResolvedField {
6+
7+
private final ResolvedClass owner;
8+
private final String fieldName;
9+
private final IRType.MetaClass type;
10+
private final FieldModel fieldModel;
11+
12+
public ResolvedField(final ResolvedClass owner, final String fieldName, final IRType.MetaClass type, final FieldModel fieldModel) {
13+
this.owner = owner;
14+
this.fieldName = fieldName;
15+
this.type = type;
16+
this.fieldModel = fieldModel;
17+
}
18+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package de.mirkosertic.metair.ir;
2+
3+
import java.lang.classfile.MethodModel;
4+
5+
public class ResolvedMethod {
6+
7+
private final ResolverContext resolverContext;
8+
private final ResolvedClass owner;
9+
private final MethodModel methodModel;
10+
private MethodAnalyzer analyzer;
11+
12+
public ResolvedMethod(final ResolverContext resolverContext, final ResolvedClass owner, final MethodModel methodModel) {
13+
this.resolverContext = resolverContext;
14+
this.owner = owner;
15+
this.methodModel = methodModel;
16+
}
17+
18+
public MethodModel methodModel() {
19+
return methodModel;
20+
}
21+
22+
public ResolvedClass thisClass() {
23+
return owner;
24+
}
25+
26+
public MethodAnalyzer analyze() {
27+
if (analyzer == null) {
28+
analyzer = new MethodAnalyzer(resolverContext, owner.thisType(), methodModel);
29+
}
30+
return analyzer;
31+
}
32+
}

0 commit comments

Comments
 (0)