wasm: move common part of wasm expression generator in order to later reuse it with Wasm GC BE

This commit is contained in:
Alexey Andreev 2024-07-09 20:49:57 +02:00
parent 13a959ce67
commit 172de8e737
13 changed files with 1846 additions and 1523 deletions

View File

@ -554,7 +554,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
generateMethods(classes, context, generator, classGenerator, binaryWriter, module, dwarfClassGen); generateMethods(classes, context, generator, classGenerator, binaryWriter, module, dwarfClassGen);
new WasmInteropFunctionGenerator(classGenerator, functionTypes).generateFunctions(module); new WasmInteropFunctionGenerator(classGenerator, functionTypes).generateFunctions(module);
exceptionHandlingIntrinsic.postProcess(context.callSites); exceptionHandlingIntrinsic.postProcess(context.callSites());
generateIsSupertypeFunctions(tagRegistry, classGenerator, functions); generateIsSupertypeFunctions(tagRegistry, classGenerator, functions);
classGenerator.postProcess(); classGenerator.postProcess();
new WasmSpecialFunctionGenerator(classGenerator, functionTypes, gcIntrinsic.regionSizeExpressions) new WasmSpecialFunctionGenerator(classGenerator, functionTypes, gcIntrinsic.regionSizeExpressions)
@ -821,7 +821,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
} }
var methodGeneratorContext = new MethodGeneratorContextImpl(binaryWriter, var methodGeneratorContext = new MethodGeneratorContextImpl(binaryWriter,
context.getStringPool(), context.getDiagnostics(), context.functions, classGenerator, classes); context.getStringPool(), context.getDiagnostics(), context.functions(), classGenerator, classes);
for (MethodHolder method : methods) { for (MethodHolder method : methods) {
ClassHolder cls = classes.get(method.getOwnerName()); ClassHolder cls = classes.get(method.getOwnerName());
@ -848,7 +848,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
if (implementor.hasModifier(ElementModifier.NATIVE)) { if (implementor.hasModifier(ElementModifier.NATIVE)) {
var methodGenerator = context.getGenerator(method.getReference()); var methodGenerator = context.getGenerator(method.getReference());
if (methodGenerator != null) { if (methodGenerator != null) {
var function = context.functions.forMethod(method); var function = context.functions().forMethod(method);
methodGenerator.apply(method.getReference(), function, methodGeneratorContext); methodGenerator.apply(method.getReference(), function, methodGeneratorContext);
} else if (!isShadowStackMethod(method.getReference())) { } else if (!isShadowStackMethod(method.getReference())) {
if (context.getImportedMethod(method.getReference()) == null) { if (context.getImportedMethod(method.getReference()) == null) {
@ -866,7 +866,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
if (method == implementor) { if (method == implementor) {
generator.generate(method.getReference(), implementor); generator.generate(method.getReference(), implementor);
} else { } else {
generateStub(context.functions, method, implementor); generateStub(context.functions(), method, implementor);
} }
if (dwarfClassGen != null) { if (dwarfClassGen != null) {
var dwarfClass = dwarfClassGen.getClass(method.getOwnerName()); var dwarfClass = dwarfClassGen.getClass(method.getOwnerName());
@ -1203,8 +1203,7 @@ public class WasmTarget implements TeaVMTarget, TeaVMWasmHost {
var block = new WasmBlock(false); var block = new WasmBlock(false);
block.setType(WasmType.INT32); block.setType(WasmType.INT32);
var callSiteId = manager.generateCallSiteId(invocation.getLocation()); var callSiteId = manager.generateCallSiteId(invocation.getLocation());
block.getBody().add(manager.generateRegisterCallSite(callSiteId, callSiteId.generateRegister(block.getBody(), invocation.getLocation());
invocation.getLocation()));
block.getBody().add(arg); block.getBody().add(arg);
arg = block; arg = block;
} }

View File

@ -17,10 +17,9 @@ package org.teavm.backend.wasm.generate;
import org.teavm.backend.wasm.model.expression.WasmExpression; import org.teavm.backend.wasm.model.expression.WasmExpression;
abstract class CachedExpression { public abstract class CachedExpression {
abstract WasmExpression expr(); public abstract WasmExpression expr();
void release() { public void release() {
} }
} }

View File

@ -24,10 +24,10 @@ import org.teavm.backend.wasm.model.expression.WasmInt32Constant;
import org.teavm.backend.wasm.model.expression.WasmSetLocal; import org.teavm.backend.wasm.model.expression.WasmSetLocal;
import org.teavm.model.TextLocation; import org.teavm.model.TextLocation;
class ExpressionCache { public class ExpressionCache {
private TemporaryVariablePool tmpVars; private TemporaryVariablePool tmpVars;
ExpressionCache(TemporaryVariablePool tmpVars) { public ExpressionCache(TemporaryVariablePool tmpVars) {
this.tmpVars = tmpVars; this.tmpVars = tmpVars;
} }
@ -56,7 +56,7 @@ class ExpressionCache {
} }
@Override @Override
WasmExpression expr() { public WasmExpression expr() {
return new WasmGetLocal(localVar); return new WasmGetLocal(localVar);
} }
} }
@ -69,12 +69,12 @@ class ExpressionCache {
} }
@Override @Override
WasmExpression expr() { public WasmExpression expr() {
return new WasmGetLocal(tmpVar); return new WasmGetLocal(tmpVar);
} }
@Override @Override
void release() { public void release() {
tmpVars.release(tmpVar); tmpVars.release(tmpVar);
} }
} }
@ -87,7 +87,7 @@ class ExpressionCache {
} }
@Override @Override
WasmExpression expr() { public WasmExpression expr() {
return new WasmInt32Constant(value); return new WasmInt32Constant(value);
} }
} }

View File

@ -23,15 +23,15 @@ import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmLocal; import org.teavm.backend.wasm.model.WasmLocal;
import org.teavm.backend.wasm.model.WasmType; import org.teavm.backend.wasm.model.WasmType;
class TemporaryVariablePool { public class TemporaryVariablePool {
private WasmFunction function; private WasmFunction function;
private Map<WasmType, Deque<WasmLocal>> temporaryVariablesByType = new HashMap<>(); private Map<WasmType, Deque<WasmLocal>> temporaryVariablesByType = new HashMap<>();
TemporaryVariablePool(WasmFunction function) { public TemporaryVariablePool(WasmFunction function) {
this.function = function; this.function = function;
} }
WasmLocal acquire(WasmType type) { public WasmLocal acquire(WasmType type) {
var stack = temporaryVariablesByType.computeIfAbsent(type, k -> new ArrayDeque<>()); var stack = temporaryVariablesByType.computeIfAbsent(type, k -> new ArrayDeque<>());
WasmLocal variable = stack.pollFirst(); WasmLocal variable = stack.pollFirst();
if (variable == null) { if (variable == null) {
@ -41,7 +41,7 @@ class TemporaryVariablePool {
return variable; return variable;
} }
void release(WasmLocal variable) { public void release(WasmLocal variable) {
var stack = temporaryVariablesByType.get(variable.getType()); var stack = temporaryVariablesByType.get(variable.getType());
stack.push(variable); stack.push(variable);
} }

View File

@ -22,6 +22,7 @@ import java.util.Map;
import org.teavm.backend.lowlevel.generate.NameProvider; import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.WasmFunctionRepository; import org.teavm.backend.wasm.WasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes; import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.common.methods.BaseWasmGenerationContext;
import org.teavm.backend.wasm.generators.WasmMethodGenerator; import org.teavm.backend.wasm.generators.WasmMethodGenerator;
import org.teavm.backend.wasm.intrinsics.WasmIntrinsic; import org.teavm.backend.wasm.intrinsics.WasmIntrinsic;
import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmModule;
@ -42,11 +43,11 @@ import org.teavm.model.classes.VirtualTableProvider;
import org.teavm.model.lowlevel.CallSiteDescriptor; import org.teavm.model.lowlevel.CallSiteDescriptor;
import org.teavm.model.lowlevel.Characteristics; import org.teavm.model.lowlevel.Characteristics;
public class WasmGenerationContext { public class WasmGenerationContext implements BaseWasmGenerationContext {
private ClassReaderSource classSource; private ClassReaderSource classSource;
public final WasmModule module; public final WasmModule module;
public final WasmFunctionTypes functionTypes; private final WasmFunctionTypes functionTypes;
public final WasmFunctionRepository functions; private final WasmFunctionRepository functions;
private Diagnostics diagnostics; private Diagnostics diagnostics;
private VirtualTableProvider vtableProvider; private VirtualTableProvider vtableProvider;
private TagRegistry tagRegistry; private TagRegistry tagRegistry;
@ -59,7 +60,7 @@ public class WasmGenerationContext {
private Map<MethodReference, IntrinsicHolder> intrinsicCache = new HashMap<>(); private Map<MethodReference, IntrinsicHolder> intrinsicCache = new HashMap<>();
private Map<MethodReference, GeneratorHolder> generatorCache = new HashMap<>(); private Map<MethodReference, GeneratorHolder> generatorCache = new HashMap<>();
private WasmTag exceptionTag; private WasmTag exceptionTag;
public final List<CallSiteDescriptor> callSites = new ArrayList<>(); private final List<CallSiteDescriptor> callSites = new ArrayList<>();
public WasmGenerationContext(ClassReaderSource classSource, WasmModule module, WasmFunctionTypes functionTypes, public WasmGenerationContext(ClassReaderSource classSource, WasmModule module, WasmFunctionTypes functionTypes,
WasmFunctionRepository functions, Diagnostics diagnostics, VirtualTableProvider vtableProvider, WasmFunctionRepository functions, Diagnostics diagnostics, VirtualTableProvider vtableProvider,
@ -78,6 +79,25 @@ public class WasmGenerationContext {
this.exceptionTag = exceptionTag; this.exceptionTag = exceptionTag;
} }
@Override
public WasmFunctionRepository functions() {
return functions;
}
@Override
public WasmFunctionTypes functionTypes() {
return functionTypes;
}
@Override
public ClassReaderSource classSource() {
return classSource;
}
public List<CallSiteDescriptor> callSites() {
return callSites;
}
public void addIntrinsic(WasmIntrinsic intrinsic) { public void addIntrinsic(WasmIntrinsic intrinsic) {
intrinsics.add(intrinsic); intrinsics.add(intrinsic);
} }
@ -167,6 +187,7 @@ public class WasmGenerationContext {
return diagnostics; return diagnostics;
} }
@Override
public WasmTag getExceptionTag() { public WasmTag getExceptionTag() {
return exceptionTag; return exceptionTag;
} }

View File

@ -57,7 +57,7 @@ public class WasmGenerator {
MethodHolder method = cls.getMethod(methodReference.getDescriptor()); MethodHolder method = cls.getMethod(methodReference.getDescriptor());
RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod); RegularMethodNode methodAst = decompiler.decompileRegular(bodyMethod);
WasmFunction function = context.functions.forMethod(method); WasmFunction function = context.functions().forMethod(method);
int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0; int firstVariable = method.hasModifier(ElementModifier.STATIC) ? 1 : 0;
for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) { for (int i = firstVariable; i < methodAst.getVariables().size(); ++i) {
VariableNode variable = methodAst.getVariables().get(i); VariableNode variable = methodAst.getVariables().get(i);
@ -97,7 +97,7 @@ public class WasmGenerator {
} }
public WasmFunction generateNative(MethodReader method) { public WasmFunction generateNative(MethodReader method) {
var function = context.functions.forMethod(method); var function = context.functions().forMethod(method);
var importedMethod = context.getImportedMethod(method.getReference()); var importedMethod = context.getImportedMethod(method.getReference());
if (importedMethod != null) { if (importedMethod != null) {

View File

@ -0,0 +1,31 @@
/*
* Copyright 2024 Alexey Andreev.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.teavm.backend.wasm.generate.common.methods;
import org.teavm.backend.wasm.WasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.model.WasmTag;
import org.teavm.model.ClassReaderSource;
public interface BaseWasmGenerationContext {
WasmFunctionRepository functions();
WasmFunctionTypes functionTypes();
WasmTag getExceptionTag();
ClassReaderSource classSource();
}

View File

@ -23,7 +23,7 @@ import java.util.Map;
import org.teavm.backend.lowlevel.generate.NameProvider; import org.teavm.backend.lowlevel.generate.NameProvider;
import org.teavm.backend.wasm.WasmFunctionTypes; import org.teavm.backend.wasm.WasmFunctionTypes;
import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor; import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor;
import org.teavm.backend.wasm.generate.gc.method.WasmGCFunctionProvider; import org.teavm.backend.wasm.generate.gc.methods.WasmGCFunctionProvider;
import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool; import org.teavm.backend.wasm.generate.gc.strings.WasmGCStringPool;
import org.teavm.backend.wasm.model.WasmArray; import org.teavm.backend.wasm.model.WasmArray;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;

View File

@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.teavm.backend.wasm.generate.gc.method; package org.teavm.backend.wasm.generate.gc.methods;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.model.MethodReference; import org.teavm.model.MethodReference;

View File

@ -20,7 +20,7 @@ import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses; import org.teavm.backend.wasm.generate.gc.classes.WasmGCStandardClasses;
import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor; import org.teavm.backend.wasm.generate.gc.initialization.WasmGCInitializerContributor;
import org.teavm.backend.wasm.generate.gc.method.WasmGCFunctionProvider; import org.teavm.backend.wasm.generate.gc.methods.WasmGCFunctionProvider;
import org.teavm.backend.wasm.model.WasmFunction; import org.teavm.backend.wasm.model.WasmFunction;
import org.teavm.backend.wasm.model.WasmGlobal; import org.teavm.backend.wasm.model.WasmGlobal;
import org.teavm.backend.wasm.model.WasmModule; import org.teavm.backend.wasm.model.WasmModule;

View File

@ -15,6 +15,7 @@
*/ */
package org.teavm.backend.wasm.intrinsics; package org.teavm.backend.wasm.intrinsics;
import java.util.List;
import org.teavm.ast.Expr; import org.teavm.ast.Expr;
import org.teavm.backend.wasm.WasmFunctionRepository; import org.teavm.backend.wasm.WasmFunctionRepository;
import org.teavm.backend.wasm.WasmFunctionTypes; import org.teavm.backend.wasm.WasmFunctionTypes;
@ -56,9 +57,11 @@ public interface WasmIntrinsicManager {
boolean isManagedMethodCall(MethodReference method); boolean isManagedMethodCall(MethodReference method);
int generateCallSiteId(TextLocation location); CallSiteIdentifier generateCallSiteId(TextLocation location);
WasmExpression generateRegisterCallSite(int callSite, TextLocation location);
WasmTag getExceptionTag(); WasmTag getExceptionTag();
interface CallSiteIdentifier {
void generateRegister(List<WasmExpression> target, TextLocation location);
}
} }