[Wasm] Support exporting functions via @kotlin.js.JsExport
Previously we exported main function only. Extend this feature to arbitrary number of annotated functions. Type restrictions and conversions are similar to imported functions.
This commit is contained in:
+16
-2
@@ -172,7 +172,21 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitGetValue(expression: IrGetValue) {
|
override fun visitGetValue(expression: IrGetValue) {
|
||||||
body.buildGetLocal(context.referenceLocal(expression.symbol))
|
val valueSymbol = expression.symbol
|
||||||
|
body.buildGetLocal(context.referenceLocal(valueSymbol))
|
||||||
|
|
||||||
|
val valueDeclaration = valueSymbol.owner
|
||||||
|
if (valueSymbol.owner is IrValueParameter) {
|
||||||
|
val parent = valueDeclaration.parent
|
||||||
|
if (parent is IrFunction && parent.isExported(backendContext)) {
|
||||||
|
val type = context.transformType(valueDeclaration.type)
|
||||||
|
if (type is WasmRefNullType) {
|
||||||
|
// TODO: Add these casts as IR-2-IR lowering instead
|
||||||
|
generateTypeRTT(valueDeclaration.type)
|
||||||
|
body.buildRefCast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitSetValue(expression: IrSetValue) {
|
override fun visitSetValue(expression: IrSetValue) {
|
||||||
@@ -296,7 +310,7 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
|
|||||||
|
|
||||||
// Return types of imported functions cannot have concrete struct/array references.
|
// Return types of imported functions cannot have concrete struct/array references.
|
||||||
// Non-primitive return types are represented as eqref which need to be casted back to expected type on call site.
|
// Non-primitive return types are represented as eqref which need to be casted back to expected type on call site.
|
||||||
if (function.getWasmImportAnnotation() != null || function.getJsFunAnnotation() != null || function.isExternal) {
|
if (function.getWasmImportAnnotation() != null || function.getJsFunAnnotation() != null || function.isExternal || function.isExported(backendContext)) {
|
||||||
val resT = context.transformResultType(function.returnType)
|
val resT = context.transformResultType(function.returnType)
|
||||||
if (resT is WasmRefNullType) {
|
if (resT is WasmRefNullType) {
|
||||||
generateTypeRTT(function.returnType)
|
generateTypeRTT(function.returnType)
|
||||||
|
|||||||
+9
-9
@@ -71,30 +71,30 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVis
|
|||||||
val watName = declaration.fqNameWhenAvailable.toString()
|
val watName = declaration.fqNameWhenAvailable.toString()
|
||||||
val irParameters = declaration.getEffectiveValueParameters()
|
val irParameters = declaration.getEffectiveValueParameters()
|
||||||
// TODO: Exported types should be transformed in a separate lowering by creating shim functions for each export.
|
// TODO: Exported types should be transformed in a separate lowering by creating shim functions for each export.
|
||||||
|
val isExported = declaration.isExported(context.backendContext)
|
||||||
val resultType =
|
val resultType =
|
||||||
when {
|
when {
|
||||||
declaration.isExported(context.backendContext) -> context.transformExportedResultType(declaration.returnType)
|
isExported -> context.transformExportedResultType(declaration.returnType)
|
||||||
// Unit_getInstance returns true Unit reference instead of "void"
|
// Unit_getInstance returns true Unit reference instead of "void"
|
||||||
declaration == unitGetInstanceFunction -> context.transformType(declaration.returnType)
|
declaration == unitGetInstanceFunction -> context.transformType(declaration.returnType)
|
||||||
else -> context.transformResultType(declaration.returnType)
|
else -> context.transformResultType(declaration.returnType)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isExportedOrImported = isExported || importedName != null
|
||||||
val wasmFunctionType =
|
val wasmFunctionType =
|
||||||
WasmFunctionType(
|
WasmFunctionType(
|
||||||
name = watName,
|
name = watName,
|
||||||
parameterTypes = irParameters.map {
|
parameterTypes = irParameters.map {
|
||||||
val t = context.transformValueParameterType(it)
|
val t = context.transformValueParameterType(it)
|
||||||
if (importedName != null && t is WasmRefNullType) {
|
if (isExportedOrImported && t is WasmRefNullType) {
|
||||||
WasmEqRef
|
WasmRefNullType(WasmHeapType.Simple.Data)
|
||||||
} else {
|
} else {
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
resultTypes = listOfNotNull(
|
resultTypes = listOfNotNull(
|
||||||
run {
|
resultType.let {
|
||||||
if (importedName != null && resultType is WasmRefNullType)
|
if (isExportedOrImported && it is WasmRefNullType) WasmRefNullType(WasmHeapType.Simple.Data) else it
|
||||||
WasmEqRef
|
|
||||||
else
|
|
||||||
resultType
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -377,4 +377,4 @@ fun IrFunction.getEffectiveValueParameters(): List<IrValueParameter> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun IrFunction.isExported(context: WasmBackendContext): Boolean =
|
fun IrFunction.isExported(context: WasmBackendContext): Boolean =
|
||||||
visibility == DescriptorVisibilities.PUBLIC && fqNameWhenAvailable in context.additionalExportedDeclarations
|
fqNameWhenAvailable in context.additionalExportedDeclarations || isJsExport()
|
||||||
Reference in New Issue
Block a user