mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 08:14:09 -08:00
wasm gc: fix issues in disassembler
This commit is contained in:
parent
8ba4f9c30b
commit
0b11a9ce90
|
@ -15,6 +15,7 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.disasm;
|
package org.teavm.backend.wasm.disasm;
|
||||||
|
|
||||||
|
import com.carrotsearch.hppc.IntArrayList;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -23,6 +24,8 @@ import java.nio.file.Files;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import org.teavm.backend.wasm.parser.AddressListener;
|
import org.teavm.backend.wasm.parser.AddressListener;
|
||||||
import org.teavm.backend.wasm.parser.CodeSectionParser;
|
import org.teavm.backend.wasm.parser.CodeSectionParser;
|
||||||
|
import org.teavm.backend.wasm.parser.FunctionSectionListener;
|
||||||
|
import org.teavm.backend.wasm.parser.FunctionSectionParser;
|
||||||
import org.teavm.backend.wasm.parser.GlobalSectionParser;
|
import org.teavm.backend.wasm.parser.GlobalSectionParser;
|
||||||
import org.teavm.backend.wasm.parser.ImportSectionListener;
|
import org.teavm.backend.wasm.parser.ImportSectionListener;
|
||||||
import org.teavm.backend.wasm.parser.ImportSectionParser;
|
import org.teavm.backend.wasm.parser.ImportSectionParser;
|
||||||
|
@ -30,11 +33,14 @@ import org.teavm.backend.wasm.parser.ModuleParser;
|
||||||
import org.teavm.backend.wasm.parser.NameSectionListener;
|
import org.teavm.backend.wasm.parser.NameSectionListener;
|
||||||
import org.teavm.backend.wasm.parser.NameSectionParser;
|
import org.teavm.backend.wasm.parser.NameSectionParser;
|
||||||
import org.teavm.backend.wasm.parser.TypeSectionParser;
|
import org.teavm.backend.wasm.parser.TypeSectionParser;
|
||||||
|
import org.teavm.backend.wasm.parser.WasmHollowFunctionType;
|
||||||
import org.teavm.common.AsyncInputStream;
|
import org.teavm.common.AsyncInputStream;
|
||||||
import org.teavm.common.ByteArrayAsyncInputStream;
|
import org.teavm.common.ByteArrayAsyncInputStream;
|
||||||
|
|
||||||
public final class Disassembler {
|
public final class Disassembler {
|
||||||
private DisassemblyWriter writer;
|
private DisassemblyWriter writer;
|
||||||
|
private WasmHollowFunctionType[] functionTypes;
|
||||||
|
private int[] functionTypeRefs;
|
||||||
|
|
||||||
public Disassembler(DisassemblyWriter writer) {
|
public Disassembler(DisassemblyWriter writer) {
|
||||||
this.writer = writer;
|
this.writer = writer;
|
||||||
|
@ -104,6 +110,7 @@ public final class Disassembler {
|
||||||
writer.setAddressOffset(pos);
|
writer.setAddressOffset(pos);
|
||||||
var sectionParser = new TypeSectionParser(typeWriter);
|
var sectionParser = new TypeSectionParser(typeWriter);
|
||||||
sectionParser.parse(writer.addressListener, bytes);
|
sectionParser.parse(writer.addressListener, bytes);
|
||||||
|
functionTypes = typeWriter.getFunctionTypes();
|
||||||
writer.flush();
|
writer.flush();
|
||||||
};
|
};
|
||||||
} else if (code == 2) {
|
} else if (code == 2) {
|
||||||
|
@ -111,19 +118,35 @@ public final class Disassembler {
|
||||||
var parser = new ImportSectionParser(importListener);
|
var parser = new ImportSectionParser(importListener);
|
||||||
parser.parse(AddressListener.EMPTY, bytes);
|
parser.parse(AddressListener.EMPTY, bytes);
|
||||||
};
|
};
|
||||||
|
} else if (code == 3) {
|
||||||
|
return bytes -> {
|
||||||
|
var signatures = new IntArrayList();
|
||||||
|
for (var i = 0; i < importListener.count; ++i) {
|
||||||
|
signatures.add(0);
|
||||||
|
}
|
||||||
|
var parser = new FunctionSectionParser(new FunctionSectionListener() {
|
||||||
|
@Override
|
||||||
|
public void function(int index, int typeIndex) {
|
||||||
|
signatures.add(typeIndex);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
parser.parse(AddressListener.EMPTY, bytes);
|
||||||
|
functionTypeRefs = signatures.toArray();
|
||||||
|
};
|
||||||
} else if (code == 6) {
|
} else if (code == 6) {
|
||||||
return bytes -> {
|
return bytes -> {
|
||||||
writer.write("(; global section size: " + bytes.length + " ;)").eol();
|
writer.write("(; global section size: " + bytes.length + " ;)").eol();
|
||||||
var globalWriter = new DisassemblyGlobalSectionListener(writer, nameProvider);
|
var globalWriter = new DisassemblyGlobalSectionListener(writer, nameProvider);
|
||||||
writer.setAddressOffset(pos);
|
writer.setAddressOffset(pos);
|
||||||
var sectionParser = new GlobalSectionParser(globalWriter);
|
var sectionParser = new GlobalSectionParser(globalWriter);
|
||||||
sectionParser.setFunctionIndexOffset(importListener.count);
|
|
||||||
sectionParser.parse(writer.addressListener, bytes);
|
sectionParser.parse(writer.addressListener, bytes);
|
||||||
writer.flush();
|
writer.flush();
|
||||||
};
|
};
|
||||||
} else if (code == 10) {
|
} else if (code == 10) {
|
||||||
return bytes -> {
|
return bytes -> {
|
||||||
var disassembler = new DisassemblyCodeSectionListener(writer, nameProvider);
|
var disassembler = new DisassemblyCodeSectionListener(writer, nameProvider);
|
||||||
|
disassembler.setFunctionTypes(functionTypes);
|
||||||
|
disassembler.setFunctionTypeRefs(functionTypeRefs);
|
||||||
writer.setAddressOffset(pos);
|
writer.setAddressOffset(pos);
|
||||||
writer.write("(; code section size: " + bytes.length + " ;)").eol();
|
writer.write("(; code section size: " + bytes.length + " ;)").eol();
|
||||||
var sectionParser = new CodeSectionParser(disassembler);
|
var sectionParser = new CodeSectionParser(disassembler);
|
||||||
|
|
|
@ -17,17 +17,29 @@ package org.teavm.backend.wasm.disasm;
|
||||||
|
|
||||||
import org.teavm.backend.wasm.parser.CodeListener;
|
import org.teavm.backend.wasm.parser.CodeListener;
|
||||||
import org.teavm.backend.wasm.parser.CodeSectionListener;
|
import org.teavm.backend.wasm.parser.CodeSectionListener;
|
||||||
|
import org.teavm.backend.wasm.parser.WasmHollowFunctionType;
|
||||||
import org.teavm.backend.wasm.parser.WasmHollowType;
|
import org.teavm.backend.wasm.parser.WasmHollowType;
|
||||||
|
|
||||||
public class DisassemblyCodeSectionListener extends BaseDisassemblyListener implements CodeSectionListener {
|
public class DisassemblyCodeSectionListener extends BaseDisassemblyListener implements CodeSectionListener {
|
||||||
private int currentFunctionId;
|
private int currentFunctionId;
|
||||||
|
private int currentFunctionParameterCount;
|
||||||
private DisassemblyCodeListener codeListener;
|
private DisassemblyCodeListener codeListener;
|
||||||
|
private WasmHollowFunctionType[] functionTypes;
|
||||||
|
private int[] functionTypeRefs;
|
||||||
|
|
||||||
public DisassemblyCodeSectionListener(DisassemblyWriter writer, NameProvider nameProvider) {
|
public DisassemblyCodeSectionListener(DisassemblyWriter writer, NameProvider nameProvider) {
|
||||||
super(writer, nameProvider);
|
super(writer, nameProvider);
|
||||||
codeListener = new DisassemblyCodeListener(writer, nameProvider);
|
codeListener = new DisassemblyCodeListener(writer, nameProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFunctionTypes(WasmHollowFunctionType[] functionTypes) {
|
||||||
|
this.functionTypes = functionTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFunctionTypeRefs(int[] functionTypeRefs) {
|
||||||
|
this.functionTypeRefs = functionTypeRefs;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean functionStart(int index, int size) {
|
public boolean functionStart(int index, int size) {
|
||||||
currentFunctionId = index;
|
currentFunctionId = index;
|
||||||
|
@ -37,7 +49,38 @@ public class DisassemblyCodeSectionListener extends BaseDisassemblyListener impl
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
writer.write(" $").write(name);
|
writer.write(" $").write(name);
|
||||||
}
|
}
|
||||||
writer.endLinkTarget().indent().eol();
|
writer.endLinkTarget();
|
||||||
|
|
||||||
|
var typeRef = functionTypeRefs[index];
|
||||||
|
writer.write(" (type ");
|
||||||
|
writeTypeRef(typeRef);
|
||||||
|
writer.write(")");
|
||||||
|
writer.indent().eol();
|
||||||
|
|
||||||
|
var type = typeRef < functionTypes.length ? functionTypes[typeRef] : null;
|
||||||
|
if (type != null) {
|
||||||
|
currentFunctionParameterCount = type.parameterTypes.length;
|
||||||
|
for (var i = 0; i < type.parameterTypes.length; ++i) {
|
||||||
|
writer.write("(param ");
|
||||||
|
writer.startLinkTarget("l" + index + "." + i).write(" (; " + i + " ;)");
|
||||||
|
var paramName = nameProvider.local(index, i);
|
||||||
|
if (paramName != null) {
|
||||||
|
writer.write(" $").write(paramName);
|
||||||
|
}
|
||||||
|
writer.endLinkTarget();
|
||||||
|
writer.write(" ");
|
||||||
|
writeType(type.parameterTypes[i]);
|
||||||
|
writer.write(")").eol();
|
||||||
|
}
|
||||||
|
for (var i = 0; i < type.returnTypes.length; ++i) {
|
||||||
|
writer.write("(result ");
|
||||||
|
writeType(type.returnTypes[i]);
|
||||||
|
writer.write(")").eol();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
currentFunctionParameterCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +94,7 @@ public class DisassemblyCodeSectionListener extends BaseDisassemblyListener impl
|
||||||
writer.address();
|
writer.address();
|
||||||
for (int i = 0; i < count; ++i) {
|
for (int i = 0; i < count; ++i) {
|
||||||
writer.write("(local ");
|
writer.write("(local ");
|
||||||
var id = i + start;
|
var id = i + start + currentFunctionParameterCount;
|
||||||
writer.startLinkTarget("l" + currentFunctionId + "." + id).write("(; " + id + " ;)");
|
writer.startLinkTarget("l" + currentFunctionId + "." + id).write("(; " + id + " ;)");
|
||||||
var name = nameProvider.local(currentFunctionId, id);
|
var name = nameProvider.local(currentFunctionId, id);
|
||||||
if (name != null) {
|
if (name != null) {
|
||||||
|
|
|
@ -15,7 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package org.teavm.backend.wasm.disasm;
|
package org.teavm.backend.wasm.disasm;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import org.teavm.backend.wasm.parser.TypeSectionListener;
|
import org.teavm.backend.wasm.parser.TypeSectionListener;
|
||||||
|
import org.teavm.backend.wasm.parser.WasmHollowFunctionType;
|
||||||
import org.teavm.backend.wasm.parser.WasmHollowStorageType;
|
import org.teavm.backend.wasm.parser.WasmHollowStorageType;
|
||||||
import org.teavm.backend.wasm.parser.WasmHollowType;
|
import org.teavm.backend.wasm.parser.WasmHollowType;
|
||||||
|
|
||||||
|
@ -25,6 +28,9 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
||||||
private int currentTypeIndex;
|
private int currentTypeIndex;
|
||||||
private int fieldIndex;
|
private int fieldIndex;
|
||||||
private boolean needsFieldIndex;
|
private boolean needsFieldIndex;
|
||||||
|
private List<WasmHollowFunctionType> functionTypes = new ArrayList<>();
|
||||||
|
private List<WasmHollowType> parameterTypes = new ArrayList<>();
|
||||||
|
private List<WasmHollowType> resultTypes = new ArrayList<>();
|
||||||
|
|
||||||
public DisassemblyTypeSectionListener(DisassemblyWriter writer, NameProvider nameProvider) {
|
public DisassemblyTypeSectionListener(DisassemblyWriter writer, NameProvider nameProvider) {
|
||||||
super(writer, nameProvider);
|
super(writer, nameProvider);
|
||||||
|
@ -42,6 +48,7 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startType(int index, boolean open, int[] supertypes) {
|
public void startType(int index, boolean open, int[] supertypes) {
|
||||||
|
functionTypes.add(null);
|
||||||
currentTypeIndex = index;
|
currentTypeIndex = index;
|
||||||
writer.address().write("(type ");
|
writer.address().write("(type ");
|
||||||
writer.startLinkTarget("t" + index).write("(; ").write(String.valueOf(index)).write(" ;) ");
|
writer.startLinkTarget("t" + index).write("(; ").write(String.valueOf(index)).write(" ;) ");
|
||||||
|
@ -119,6 +126,11 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resultType(WasmHollowType type) {
|
public void resultType(WasmHollowType type) {
|
||||||
|
if (emittingReturn) {
|
||||||
|
resultTypes.add(type);
|
||||||
|
} else {
|
||||||
|
parameterTypes.add(type);
|
||||||
|
}
|
||||||
writer.address().write("(").write(emittingReturn ? "result" : "param").write(" ");
|
writer.address().write("(").write(emittingReturn ? "result" : "param").write(" ");
|
||||||
writeType(type);
|
writeType(type);
|
||||||
writer.write(")").eol();
|
writer.write(")").eol();
|
||||||
|
@ -126,6 +138,11 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void endFuncType() {
|
public void endFuncType() {
|
||||||
|
var type = new WasmHollowFunctionType(parameterTypes.toArray(new WasmHollowType[0]),
|
||||||
|
resultTypes.toArray(new WasmHollowType[0]));
|
||||||
|
functionTypes.set(currentTypeIndex, type);
|
||||||
|
parameterTypes.clear();
|
||||||
|
resultTypes.clear();
|
||||||
emittingReturn = false;
|
emittingReturn = false;
|
||||||
writer.outdent().write(")").eol();
|
writer.outdent().write(")").eol();
|
||||||
}
|
}
|
||||||
|
@ -139,4 +156,8 @@ public class DisassemblyTypeSectionListener extends BaseDisassemblyListener impl
|
||||||
}
|
}
|
||||||
writer.write(")").eol();
|
writer.write(")").eol();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public WasmHollowFunctionType[] getFunctionTypes() {
|
||||||
|
return functionTypes.toArray(new WasmHollowFunctionType[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,16 +31,11 @@ import org.teavm.backend.wasm.model.expression.WasmSignedType;
|
||||||
public class CodeParser extends BaseSectionParser {
|
public class CodeParser extends BaseSectionParser {
|
||||||
private CodeListener codeListener;
|
private CodeListener codeListener;
|
||||||
private final List<Block> blockStack = new ArrayList<>();
|
private final List<Block> blockStack = new ArrayList<>();
|
||||||
private int functionIndexOffset;
|
|
||||||
|
|
||||||
public void setCodeListener(CodeListener codeListener) {
|
public void setCodeListener(CodeListener codeListener) {
|
||||||
this.codeListener = codeListener;
|
this.codeListener = codeListener;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionIndexOffset(int functionIndexOffset) {
|
|
||||||
this.functionIndexOffset = functionIndexOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseContent() {
|
protected void parseContent() {
|
||||||
parseCode();
|
parseCode();
|
||||||
|
@ -104,7 +99,7 @@ public class CodeParser extends BaseSectionParser {
|
||||||
codeListener.opcode(Opcode.RETURN);
|
codeListener.opcode(Opcode.RETURN);
|
||||||
break;
|
break;
|
||||||
case 0x10:
|
case 0x10:
|
||||||
codeListener.call(readLEB() + functionIndexOffset);
|
codeListener.call(readLEB());
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
codeListener.indirectCall(readLEB(), readLEB());
|
codeListener.indirectCall(readLEB(), readLEB());
|
||||||
|
@ -598,7 +593,7 @@ public class CodeParser extends BaseSectionParser {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD2:
|
case 0xD2:
|
||||||
codeListener.functionReference(readLEB() + functionIndexOffset);
|
codeListener.functionReference(readLEB());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xD3:
|
case 0xD3:
|
||||||
|
|
|
@ -49,7 +49,6 @@ public class CodeSectionParser extends BaseSectionParser {
|
||||||
var codeListener = listener.code();
|
var codeListener = listener.code();
|
||||||
if (codeListener != null) {
|
if (codeListener != null) {
|
||||||
codeParser.setCodeListener(codeListener);
|
codeParser.setCodeListener(codeListener);
|
||||||
codeParser.setFunctionIndexOffset(functionIndexOffset);
|
|
||||||
codeParser.parse(reader);
|
codeParser.parse(reader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 konsoletyper.
|
||||||
|
*
|
||||||
|
* 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.parser;
|
||||||
|
|
||||||
|
public interface FunctionSectionListener {
|
||||||
|
void function(int index, int typeIndex);
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 konsoletyper.
|
||||||
|
*
|
||||||
|
* 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.parser;
|
||||||
|
|
||||||
|
public class FunctionSectionParser extends BaseSectionParser {
|
||||||
|
private final FunctionSectionListener listener;
|
||||||
|
|
||||||
|
public FunctionSectionParser(FunctionSectionListener listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void parseContent() {
|
||||||
|
var count = reader.readLEB();
|
||||||
|
for (var i = 0; i < count; ++i) {
|
||||||
|
reportAddress();
|
||||||
|
var typeIndex = reader.readLEB();
|
||||||
|
listener.function(i, typeIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,17 +18,12 @@ package org.teavm.backend.wasm.parser;
|
||||||
public class GlobalSectionParser extends BaseSectionParser {
|
public class GlobalSectionParser extends BaseSectionParser {
|
||||||
private final GlobalSectionListener listener;
|
private final GlobalSectionListener listener;
|
||||||
private CodeParser codeParser;
|
private CodeParser codeParser;
|
||||||
private int functionIndexOffset;
|
|
||||||
|
|
||||||
public GlobalSectionParser(GlobalSectionListener listener) {
|
public GlobalSectionParser(GlobalSectionListener listener) {
|
||||||
this.listener = listener;
|
this.listener = listener;
|
||||||
codeParser = new CodeParser();
|
codeParser = new CodeParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFunctionIndexOffset(int functionIndexOffset) {
|
|
||||||
this.functionIndexOffset = functionIndexOffset;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void parseContent() {
|
protected void parseContent() {
|
||||||
var count = readLEB();
|
var count = readLEB();
|
||||||
|
@ -41,7 +36,6 @@ public class GlobalSectionParser extends BaseSectionParser {
|
||||||
codeListener = CodeListener.EMPTY;
|
codeListener = CodeListener.EMPTY;
|
||||||
}
|
}
|
||||||
codeParser.setCodeListener(codeListener);
|
codeParser.setCodeListener(codeListener);
|
||||||
codeParser.setFunctionIndexOffset(functionIndexOffset);
|
|
||||||
if (!codeParser.parseSingleExpression(reader)) {
|
if (!codeParser.parseSingleExpression(reader)) {
|
||||||
throw new ParseException("Error parsing global initializer", reader.ptr);
|
throw new ParseException("Error parsing global initializer", reader.ptr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2024 konsoletyper.
|
||||||
|
*
|
||||||
|
* 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.parser;
|
||||||
|
|
||||||
|
public class WasmHollowFunctionType {
|
||||||
|
public final WasmHollowType[] parameterTypes;
|
||||||
|
public final WasmHollowType[] returnTypes;
|
||||||
|
|
||||||
|
public WasmHollowFunctionType(WasmHollowType[] parameterTypes, WasmHollowType[] returnTypes) {
|
||||||
|
this.parameterTypes = parameterTypes;
|
||||||
|
this.returnTypes = returnTypes;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user