[Wasm] Move non-recursive function types out of rec group
This fixes linking with other wasm modules with non-rec types
This commit is contained in:
committed by
teamcity
parent
88f1f74aec
commit
d788adcbb5
+16
-8
@@ -192,21 +192,29 @@ class WasmCompiledModuleFragment(val irBuiltIns: IrBuiltIns) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val typeDeclarations = mutableListOf<WasmTypeDeclaration>()
|
val recGroupTypes = mutableListOf<WasmTypeDeclaration>()
|
||||||
typeDeclarations.addAll(vTableGcTypes.elements)
|
recGroupTypes.addAll(vTableGcTypes.elements)
|
||||||
typeDeclarations.addAll(gcTypes.elements)
|
recGroupTypes.addAll(this.gcTypes.elements)
|
||||||
typeDeclarations.addAll(classITableGcType.elements.distinct())
|
recGroupTypes.addAll(classITableGcType.elements.distinct())
|
||||||
typeDeclarations.sortBy(::wasmTypeDeclarationOrderKey)
|
recGroupTypes.sortBy(::wasmTypeDeclarationOrderKey)
|
||||||
|
|
||||||
val globals = mutableListOf<WasmGlobal>()
|
val globals = mutableListOf<WasmGlobal>()
|
||||||
globals.addAll(globalFields.elements)
|
globals.addAll(globalFields.elements)
|
||||||
globals.addAll(globalVTables.elements)
|
globals.addAll(globalVTables.elements)
|
||||||
globals.addAll(globalClassITables.elements.distinct())
|
globals.addAll(globalClassITables.elements.distinct())
|
||||||
|
|
||||||
|
val allFunctionTypes = canonicalFunctionTypes.values.toList() + tagFuncType + masterInitFunctionType
|
||||||
|
|
||||||
|
// Partition out function types that can't be recursive,
|
||||||
|
// we don't need to put them into a rec group
|
||||||
|
// so that they can be matched with function types from other Wasm modules.
|
||||||
|
val (potentiallyRecursiveFunctionTypes, nonRecursiveFunctionTypes) =
|
||||||
|
allFunctionTypes.partition { it.referencesTypeDeclarations() }
|
||||||
|
recGroupTypes.addAll(potentiallyRecursiveFunctionTypes)
|
||||||
|
|
||||||
val module = WasmModule(
|
val module = WasmModule(
|
||||||
functionTypes = canonicalFunctionTypes.values.toList() + tagFuncType + masterInitFunctionType,
|
functionTypes = nonRecursiveFunctionTypes,
|
||||||
gcTypes = typeDeclarations,
|
recGroupTypes = recGroupTypes,
|
||||||
gcTypesInRecursiveGroup = true,
|
|
||||||
importsInOrder = importedFunctions,
|
importsInOrder = importedFunctions,
|
||||||
importedFunctions = importedFunctions,
|
importedFunctions = importedFunctions,
|
||||||
definedFunctions = functions.elements.filterIsInstance<WasmFunction.Defined>() + masterInitFunction,
|
definedFunctions = functions.elements.filterIsInstance<WasmFunction.Defined>() + masterInitFunction,
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// TARGET_BACKEND: WASM
|
||||||
|
|
||||||
|
/*
|
||||||
|
Here we pass export of another Wasm module to our import directly without JS layer.
|
||||||
|
This enables strict type check without JS conversons.
|
||||||
|
For instance, recursion groups of function types must fully match.
|
||||||
|
|
||||||
|
(module
|
||||||
|
(func (export "addTwo") (param i32 i32) (result i32)
|
||||||
|
local.get 0
|
||||||
|
local.get 1
|
||||||
|
i32.add))
|
||||||
|
*/
|
||||||
|
@JsFun("""
|
||||||
|
(() => {
|
||||||
|
let bytes = [0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3,
|
||||||
|
2, 1, 0, 7, 10, 1, 6, 97, 100, 100, 84, 119, 111, 0, 0, 10, 9, 1,
|
||||||
|
7, 0, 32, 0, 32, 1, 106, 11, 0, 10, 4, 110, 97, 109, 101, 2, 3, 1, 0, 0];
|
||||||
|
let buffer = (new Int8Array(bytes)).buffer;
|
||||||
|
let module = new WebAssembly.Module(buffer);
|
||||||
|
let instance = new WebAssembly.Instance(module);
|
||||||
|
return instance.exports.addTwo;
|
||||||
|
})()
|
||||||
|
""")
|
||||||
|
external fun addTwo(a: Int, b: Int): Int
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
if (addTwo(100, 200) != 300) return "Fail1"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+5
@@ -30,6 +30,11 @@ public class IrCodegenWasmJsInteropWasmTestGenerated extends AbstractIrCodegenWa
|
|||||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxWasmJsInterop"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callingWasmDirectly.kt")
|
||||||
|
public void testCallingWasmDirectly() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/boxWasmJsInterop/callingWasmDirectly.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("defaultValues.kt")
|
@TestMetadata("defaultValues.kt")
|
||||||
public void testDefaultValues() throws Exception {
|
public void testDefaultValues() throws Exception {
|
||||||
runTest("compiler/testData/codegen/boxWasmJsInterop/defaultValues.kt");
|
runTest("compiler/testData/codegen/boxWasmJsInterop/defaultValues.kt");
|
||||||
|
|||||||
@@ -10,9 +10,7 @@ import org.jetbrains.kotlin.wasm.ir.source.location.SourceLocation
|
|||||||
|
|
||||||
class WasmModule(
|
class WasmModule(
|
||||||
val functionTypes: List<WasmFunctionType> = emptyList(),
|
val functionTypes: List<WasmFunctionType> = emptyList(),
|
||||||
val gcTypes: List<WasmTypeDeclaration> = emptyList(),
|
val recGroupTypes: List<WasmTypeDeclaration> = emptyList(),
|
||||||
val gcTypesInRecursiveGroup: Boolean,
|
|
||||||
|
|
||||||
val importsInOrder: List<WasmNamedModuleField> = emptyList(),
|
val importsInOrder: List<WasmNamedModuleField> = emptyList(),
|
||||||
val importedFunctions: List<WasmFunction.Imported> = emptyList(),
|
val importedFunctions: List<WasmFunction.Imported> = emptyList(),
|
||||||
val importedMemories: List<WasmMemory> = emptyList(),
|
val importedMemories: List<WasmMemory> = emptyList(),
|
||||||
|
|||||||
@@ -77,3 +77,15 @@ fun WasmType.getHeapType(): WasmHeapType =
|
|||||||
is WasmExternRef -> WasmHeapType.Simple.Extern
|
is WasmExternRef -> WasmHeapType.Simple.Extern
|
||||||
else -> error("Unknown heap type for type $this")
|
else -> error("Unknown heap type for type $this")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun WasmFunctionType.referencesTypeDeclarations(): Boolean =
|
||||||
|
parameterTypes.any { it.referencesTypeDeclaration() } or resultTypes.any { it.referencesTypeDeclaration() }
|
||||||
|
|
||||||
|
fun WasmType.referencesTypeDeclaration(): Boolean {
|
||||||
|
val heapType = when (this) {
|
||||||
|
is WasmRefNullType -> getHeapType()
|
||||||
|
is WasmRefType -> getHeapType()
|
||||||
|
else -> return false
|
||||||
|
}
|
||||||
|
return heapType is WasmHeapType.Type
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ fun WasmModule.calculateIds() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
functionTypes.calculateIds()
|
functionTypes.calculateIds()
|
||||||
gcTypes.calculateIds(startIndex = functionTypes.size)
|
recGroupTypes.calculateIds(startIndex = functionTypes.size)
|
||||||
importedFunctions.calculateIds()
|
importedFunctions.calculateIds()
|
||||||
importedMemories.calculateIds()
|
importedMemories.calculateIds()
|
||||||
importedTables.calculateIds()
|
importedTables.calculateIds()
|
||||||
|
|||||||
@@ -329,8 +329,7 @@ class WasmBinaryToIR(val b: MyByteReader) {
|
|||||||
|
|
||||||
return WasmModule(
|
return WasmModule(
|
||||||
functionTypes = functionTypes,
|
functionTypes = functionTypes,
|
||||||
gcTypes = gcTypes,
|
recGroupTypes = gcTypes,
|
||||||
gcTypesInRecursiveGroup = false,
|
|
||||||
importsInOrder = importsInOrder,
|
importsInOrder = importsInOrder,
|
||||||
importedFunctions = importedFunctions,
|
importedFunctions = importedFunctions,
|
||||||
importedMemories = importedMemories,
|
importedMemories = importedMemories,
|
||||||
|
|||||||
@@ -35,17 +35,18 @@ class WasmIrToBinary(
|
|||||||
with(module) {
|
with(module) {
|
||||||
// type section
|
// type section
|
||||||
appendSection(1u) {
|
appendSection(1u) {
|
||||||
if (module.gcTypesInRecursiveGroup) {
|
val numRecGroups = if (recGroupTypes.isEmpty()) 0 else 1
|
||||||
appendVectorSize(1)
|
appendVectorSize(functionTypes.size + numRecGroups)
|
||||||
b.writeByte(0x4f)
|
|
||||||
}
|
|
||||||
appendVectorSize(functionTypes.size + gcTypes.size)
|
|
||||||
functionTypes.forEach { appendFunctionTypeDeclaration(it) }
|
functionTypes.forEach { appendFunctionTypeDeclaration(it) }
|
||||||
gcTypes.forEach {
|
if (!recGroupTypes.isEmpty()) {
|
||||||
when (it) {
|
b.writeByte(0x4f)
|
||||||
is WasmStructDeclaration -> appendStructTypeDeclaration(it)
|
appendVectorSize(recGroupTypes.size)
|
||||||
is WasmArrayDeclaration -> appendArrayTypeDeclaration(it)
|
recGroupTypes.forEach {
|
||||||
is WasmFunctionType -> error("Function type in GC types")
|
when (it) {
|
||||||
|
is WasmStructDeclaration -> appendStructTypeDeclaration(it)
|
||||||
|
is WasmArrayDeclaration -> appendArrayTypeDeclaration(it)
|
||||||
|
is WasmFunctionType -> appendFunctionTypeDeclaration(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -172,8 +173,8 @@ class WasmIrToBinary(
|
|||||||
// https://github.com/WebAssembly/extended-name-section/blob/main/document/core/appendix/custom.rst
|
// https://github.com/WebAssembly/extended-name-section/blob/main/document/core/appendix/custom.rst
|
||||||
|
|
||||||
appendSection(4u) {
|
appendSection(4u) {
|
||||||
appendVectorSize(module.gcTypes.size)
|
appendVectorSize(module.recGroupTypes.size)
|
||||||
module.gcTypes.forEach {
|
module.recGroupTypes.forEach {
|
||||||
appendModuleFieldReference(it)
|
appendModuleFieldReference(it)
|
||||||
b.writeString(it.name)
|
b.writeString(it.name)
|
||||||
}
|
}
|
||||||
@@ -190,7 +191,7 @@ class WasmIrToBinary(
|
|||||||
// Experimental fields name section
|
// Experimental fields name section
|
||||||
// https://github.com/WebAssembly/gc/issues/193
|
// https://github.com/WebAssembly/gc/issues/193
|
||||||
appendSection(10u) {
|
appendSection(10u) {
|
||||||
val structDeclarations = module.gcTypes.filterIsInstance<WasmStructDeclaration>()
|
val structDeclarations = module.recGroupTypes.filterIsInstance<WasmStructDeclaration>()
|
||||||
appendVectorSize(structDeclarations.size)
|
appendVectorSize(structDeclarations.size)
|
||||||
structDeclarations.forEach {
|
structDeclarations.forEach {
|
||||||
appendModuleFieldReference(it)
|
appendModuleFieldReference(it)
|
||||||
|
|||||||
@@ -228,13 +228,14 @@ class WasmIrToText : SExpressionBuilder() {
|
|||||||
with(module) {
|
with(module) {
|
||||||
newLineList("module") {
|
newLineList("module") {
|
||||||
functionTypes.forEach { appendFunctionTypeDeclaration(it) }
|
functionTypes.forEach { appendFunctionTypeDeclaration(it) }
|
||||||
gcTypes.forEach {
|
recGroupTypes.forEach {
|
||||||
when (it) {
|
when (it) {
|
||||||
is WasmStructDeclaration ->
|
is WasmStructDeclaration ->
|
||||||
appendStructTypeDeclaration(it)
|
appendStructTypeDeclaration(it)
|
||||||
is WasmArrayDeclaration ->
|
is WasmArrayDeclaration ->
|
||||||
appendArrayTypeDeclaration(it)
|
appendArrayTypeDeclaration(it)
|
||||||
else -> error("Unexpected GC type: $it")
|
is WasmFunctionType ->
|
||||||
|
appendFunctionTypeDeclaration(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
importsInOrder.forEach {
|
importsInOrder.forEach {
|
||||||
|
|||||||
Reference in New Issue
Block a user