Skip to content

Commit

Permalink
Introduce concept of 'weak' cast.
Browse files Browse the repository at this point in the history
Use weak casts to maintain proper typing within methods during various operations on IR. At generation level, ignore weak casts, except for Wasm GC BE, which turns weak casts into platform casts.
  • Loading branch information
konsoletyper committed Aug 18, 2024
1 parent 8b52741 commit a97e657
Show file tree
Hide file tree
Showing 33 changed files with 84 additions and 136 deletions.
10 changes: 10 additions & 0 deletions core/src/main/java/org/teavm/ast/CastExpr.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
public class CastExpr extends Expr {
private Expr value;
private ValueType target;
private boolean weak;

public Expr getValue() {
return value;
Expand All @@ -38,6 +39,14 @@ public void setTarget(ValueType target) {
this.target = target;
}

public boolean isWeak() {
return weak;
}

public void setWeak(boolean weak) {
this.weak = weak;
}

@Override
public void acceptVisitor(ExprVisitor visitor) {
visitor.visit(this);
Expand All @@ -48,6 +57,7 @@ protected Expr clone(Map<Expr, Expr> cache) {
CastExpr copy = new CastExpr();
copy.value = value.clone(cache);
copy.target = target;
copy.weak = weak;
return copy;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ public void visit(CastInstruction insn) {
expr.setVariableIndex(insn.getReceiver().getIndex());
expr.setValue(Expr.var(insn.getValue().getIndex()));
expr.setTarget(insn.getTargetType());
expr.setWeak(insn.isWeak());
assign(expr, insn.getReceiver());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1056,6 +1056,11 @@ public void visit(InstanceOfExpr expr) {

@Override
public void visit(CastExpr expr) {
if (expr.isWeak()) {
expr.getValue().acceptVisitor(this);
return;
}

if (expr.getTarget() instanceof ValueType.Object) {
String className = ((ValueType.Object) expr.getTarget()).getClassName();
if (!context.getCharacteristics().isManaged(className)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -878,7 +878,7 @@ public void visit(UnaryExpr expr) {

@Override
public void visit(CastExpr expr) {
if (context.isStrict()) {
if (context.isStrict() && !expr.isWeak()) {
if (expr.getLocation() != null) {
pushLocation(expr.getLocation());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,15 @@
import org.teavm.model.Program;
import org.teavm.model.ValueType;
import org.teavm.model.analysis.BaseTypeInference;
import org.teavm.model.instructions.InvocationType;

public class PreciseTypeInference extends BaseTypeInference<PreciseValueType> {
public static final PreciseValueType OBJECT_TYPE = new PreciseValueType(ValueType.object("java.lang.Object"),
false);
private ClassHierarchy hierarchy;
private WasmGCMethodReturnTypes returnTypes;

public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy,
WasmGCMethodReturnTypes returnTypes) {
public PreciseTypeInference(Program program, MethodReference reference, ClassHierarchy hierarchy) {
super(program, reference);
this.hierarchy = hierarchy;
this.returnTypes = returnTypes;
}

@Override
Expand Down Expand Up @@ -108,14 +104,6 @@ protected PreciseValueType arrayType(PreciseValueType preciseValueType) {
return new PreciseValueType(ValueType.arrayOf(preciseValueType.valueType), false);
}

@Override
protected PreciseValueType methodReturnType(InvocationType invocationType, MethodReference methodRef) {
if (invocationType == InvocationType.SPECIAL) {
return new PreciseValueType(returnTypes.returnTypeOf(methodRef), false);
}
return super.methodReturnType(invocationType, methodRef);
}

@Override
protected PreciseValueType arrayUnwrapType(PreciseValueType type) {
return new PreciseValueType(type.valueType, true);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,9 @@
public class WasmGCVariableCategoryProvider implements VariableCategoryProvider {
private ClassHierarchy hierarchy;
private PreciseTypeInference inference;
private WasmGCMethodReturnTypes returnTypes;

public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy, WasmGCMethodReturnTypes returnTypes) {
public WasmGCVariableCategoryProvider(ClassHierarchy hierarchy) {
this.hierarchy = hierarchy;
this.returnTypes = returnTypes;
}

public PreciseTypeInference getTypeInference() {
Expand All @@ -36,7 +34,7 @@ public PreciseTypeInference getTypeInference() {

@Override
public Object[] getCategories(Program program, MethodReference method) {
inference = new PreciseTypeInference(program, method, hierarchy, returnTypes);
inference = new PreciseTypeInference(program, method, hierarchy);
inference.setPhisSkipped(true);
inference.setBackPropagation(true);
var result = new Object[program.variableCount()];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,11 @@ protected abstract void generateThrow(WasmExpression expression, TextLocation lo

@Override
public void visit(CastExpr expr) {
if (expr.isWeak()) {
acceptWithType(expr.getValue(), expr.getTarget());
result = generateCast(result, mapType(expr.getTarget()));
return;
}
var block = new WasmBlock(false);
var wasmTargetType = mapType(expr.getTarget());
block.setType(wasmTargetType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.util.function.Predicate;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
import org.teavm.backend.wasm.generate.WasmNameProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassGenerator;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
Expand Down Expand Up @@ -47,7 +46,6 @@ public class WasmGCDeclarationsGenerator {
public final WasmFunctionTypes functionTypes;
private final WasmGCClassGenerator classGenerator;
private final WasmGCMethodGenerator methodGenerator;
private final WasmGCMethodReturnTypes returnTypes;

public WasmGCDeclarationsGenerator(
WasmModule module,
Expand All @@ -64,7 +62,6 @@ public WasmGCDeclarationsGenerator(
var virtualTables = createVirtualTableProvider(classes, virtualMethods);
functionTypes = new WasmFunctionTypes(module);
var names = new WasmNameProvider();
returnTypes = new WasmGCMethodReturnTypes(dependencyInfo, hierarchy);
methodGenerator = new WasmGCMethodGenerator(
module,
hierarchy,
Expand All @@ -74,7 +71,6 @@ public WasmGCDeclarationsGenerator(
functionTypes,
names,
diagnostics,
returnTypes,
customGenerators,
intrinsics
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@
import java.util.Set;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
Expand Down Expand Up @@ -57,7 +56,6 @@ public class WasmGCGenerationContext implements BaseWasmGenerationContext {
private WasmGCSupertypeFunctionProvider supertypeFunctions;
private WasmGCCustomGeneratorProvider customGenerators;
private WasmGCIntrinsicProvider intrinsics;
private WasmGCMethodReturnTypes returnTypes;
private WasmFunction npeMethod;
private WasmFunction aaiobeMethod;
private WasmFunction cceMethod;
Expand All @@ -70,8 +68,7 @@ public WasmGCGenerationContext(WasmModule module, VirtualTableProvider virtualTa
ClassHierarchy hierarchy, BaseWasmFunctionRepository functions,
WasmGCSupertypeFunctionProvider supertypeFunctions, WasmGCClassInfoProvider classInfoProvider,
WasmGCStandardClasses standardClasses, WasmGCStringProvider strings,
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics,
WasmGCMethodReturnTypes returnTypes) {
WasmGCCustomGeneratorProvider customGenerators, WasmGCIntrinsicProvider intrinsics) {
this.module = module;
this.virtualTables = virtualTables;
this.typeMapper = typeMapper;
Expand All @@ -85,7 +82,6 @@ public WasmGCGenerationContext(WasmModule module, VirtualTableProvider virtualTa
this.strings = strings;
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
this.returnTypes = returnTypes;
}

public WasmGCClassInfoProvider classInfoProvider() {
Expand Down Expand Up @@ -186,10 +182,6 @@ public WasmGCIntrinsicProvider intrinsics() {
return intrinsics;
}

public WasmGCMethodReturnTypes returnTypes() {
return returnTypes;
}

public Collection<String> getInterfaceImplementors(String className) {
if (interfaceImplementors == null) {
fillInterfaceImplementors();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ protected WasmExpression mapFirstArgumentForCall(WasmExpression argument, WasmFu

@Override
protected WasmExpression forceType(WasmExpression expression, ValueType type) {
return forceType(expression, mapType(context.returnTypes().returnTypeOf(currentMethod)));
return forceType(expression, mapType(currentMethod.getReturnType()));
}

private WasmExpression forceType(WasmExpression expression, WasmType expectedType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.BaseWasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.gc.WasmGCMethodReturnTypes;
import org.teavm.backend.wasm.gc.WasmGCVariableCategoryProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCClassInfoProvider;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
Expand Down Expand Up @@ -78,7 +77,6 @@ public class WasmGCMethodGenerator implements BaseWasmFunctionRepository {
private WasmGCClassInfoProvider classInfoProvider;
private WasmGCStandardClasses standardClasses;
private WasmGCStringProvider strings;
private WasmGCMethodReturnTypes returnTypes;

public WasmGCMethodGenerator(
WasmModule module,
Expand All @@ -89,7 +87,6 @@ public WasmGCMethodGenerator(
WasmFunctionTypes functionTypes,
NameProvider names,
Diagnostics diagnostics,
WasmGCMethodReturnTypes returnTypes,
WasmGCCustomGeneratorProvider customGenerators,
WasmGCIntrinsicProvider intrinsics
) {
Expand All @@ -101,7 +98,6 @@ public WasmGCMethodGenerator(
this.functionTypes = functionTypes;
this.names = names;
this.diagnostics = diagnostics;
this.returnTypes = returnTypes;
this.customGenerators = customGenerators;
this.intrinsics = intrinsics;
}
Expand Down Expand Up @@ -146,7 +142,7 @@ public WasmFunction forStaticMethod(MethodReference methodReference) {
}

private WasmFunction createStaticFunction(MethodReference methodReference) {
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
var returnType = typeMapper.mapType(methodReference.getReturnType());
var parameterTypes = new WasmType[methodReference.parameterCount()];
for (var i = 0; i < parameterTypes.length; ++i) {
parameterTypes[i] = typeMapper.mapType(methodReference.parameterType(i));
Expand All @@ -173,7 +169,7 @@ public WasmFunction forInstanceMethod(MethodReference methodReference) {
}

private WasmFunction createInstanceFunction(MethodReference methodReference) {
var returnType = typeMapper.mapType(returnTypes.returnTypeOf(methodReference));
var returnType = typeMapper.mapType(methodReference.getReturnType());
var parameterTypes = new WasmType[methodReference.parameterCount() + 1];
parameterTypes[0] = typeMapper.mapType(ValueType.object(methodReference.getClassName()));
for (var i = 0; i < methodReference.parameterCount(); ++i) {
Expand Down Expand Up @@ -213,7 +209,7 @@ private void generateCustomMethodBody(WasmGCCustomGenerator customGenerator, Met

private void generateRegularMethodBody(MethodHolder method, WasmFunction function) {
var decompiler = getDecompiler();
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy, returnTypes);
var categoryProvider = new WasmGCVariableCategoryProvider(hierarchy);
var allocator = new RegisterAllocator(categoryProvider);
allocator.allocateRegisters(method.getReference(), method.getProgram(), friendlyToDebugger);
var ast = decompiler.decompileRegular(method);
Expand Down Expand Up @@ -302,8 +298,7 @@ private WasmGCGenerationContext getGenerationContext() {
standardClasses,
strings,
customGenerators,
intrinsics,
returnTypes
intrinsics
);
}
return context;
Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/teavm/cache/AstIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -714,6 +714,7 @@ public void visit(CastExpr expr) {
output.writeUnsigned(23);
output.writeUnsigned(symbolTable.lookup(expr.getTarget().toString()));
writeExpr(expr.getValue());
output.writeUnsigned(expr.isWeak() ? 1 : 0);
} catch (IOException e) {
throw new IOExceptionWrapper(e);
}
Expand Down Expand Up @@ -1106,6 +1107,7 @@ private Expr readExpr(VarDataInput input) throws IOException {
expr.setLocation(lastReadLocation);
expr.setTarget(ValueType.parse(symbolTable.at(input.readUnsigned())));
expr.setValue(readExpr(input));
expr.setWeak(input.readUnsigned() != 0);
return expr;
}
case 24: {
Expand Down
4 changes: 3 additions & 1 deletion core/src/main/java/org/teavm/cache/ProgramIO.java
Original file line number Diff line number Diff line change
Expand Up @@ -451,12 +451,13 @@ public void assign(VariableReader receiver, VariableReader assignee) {
}

@Override
public void cast(VariableReader receiver, VariableReader value, ValueType targetType) {
public void cast(VariableReader receiver, VariableReader value, ValueType targetType, boolean weak) {
try {
output.writeUnsigned(25);
output.writeUnsigned(receiver.getIndex());
output.writeUnsigned(symbolTable.lookup(targetType.toString()));
output.writeUnsigned(value.getIndex());
output.writeUnsigned(weak ? 1 : 0);
} catch (IOException e) {
throw new IOExceptionWrapper(e);
}
Expand Down Expand Up @@ -988,6 +989,7 @@ private Instruction readInstruction(int insnType, Program program, VarDataInput
insn.setReceiver(program.variableAt(input.readUnsigned()));
insn.setTargetType(parseValueType(symbolTable.at(input.readUnsigned())));
insn.setValue(program.variableAt(input.readUnsigned()));
insn.setWeak(input.readUnsigned() != 0);
return insn;
}
case 26: {
Expand Down
Loading

0 comments on commit a97e657

Please sign in to comment.