diff --git a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt index aa70ecaa5f1..ab5237a271e 100644 --- a/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt +++ b/compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/K2JSCompilerArguments.kt @@ -232,6 +232,9 @@ class K2JSCompilerArguments : CommonCompilerArguments() { @Argument(value = "-Xwasm", description = "Use experimental WebAssembly compiler backend") var wasm: Boolean by FreezableVar(false) + @Argument(value = "-Xwasm-debug-info", description = "Add debug info to WebAssembly compiled module") + var wasmDebug: Boolean by FreezableVar(false) + override fun configureLanguageFeatures(collector: MessageCollector): MutableMap { return super.configureLanguageFeatures(collector).apply { if (extensionFunctionsInExternals) { diff --git a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt index e8d35649653..3a4f2a51e4b 100644 --- a/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt +++ b/compiler/cli/cli-js/src/org/jetbrains/kotlin/cli/js/K2JsIrCompiler.kt @@ -310,7 +310,8 @@ class K2JsIrCompiler : CLICompiler() { module, PhaseConfig(wasmPhases), IrFactoryImpl, - exportedDeclarations = setOf(FqName("main")) + exportedDeclarations = setOf(FqName("main")), + emitNameSection = arguments.wasmDebug, ) val outputWasmFile = outputFile.withReplacedExtensionOrNull(outputFile.extension, "wasm")!! outputWasmFile.writeBytes(res.wasm) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index 2eae331fc1d..89cd5a0e9c9 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -5,14 +5,10 @@ package org.jetbrains.kotlin.backend.wasm -import com.intellij.openapi.project.Project -import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledModuleFragment import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleFragmentGenerator -import org.jetbrains.kotlin.backend.wasm.ir2wasm.generateStringLiteralsSupport -import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.ir.backend.js.MainModule import org.jetbrains.kotlin.ir.backend.js.ModulesStructure import org.jetbrains.kotlin.ir.backend.js.loadIr @@ -21,7 +17,6 @@ import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator import org.jetbrains.kotlin.ir.util.noUnboundLeft import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi2ir.generators.generateTypicalIrProviderList import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToBinary import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToText import java.io.ByteArrayOutputStream @@ -32,7 +27,8 @@ fun compileWasm( depsDescriptors: ModulesStructure, phaseConfig: PhaseConfig, irFactory: IrFactory, - exportedDeclarations: Set = emptySet() + exportedDeclarations: Set = emptySet(), + emitNameSection: Boolean = false, ): WasmCompilerResult { val mainModule = depsDescriptors.mainModule val configuration = depsDescriptors.compilerConfiguration @@ -76,7 +72,7 @@ fun compileWasm( val js = compiledWasmModule.generateJs() val os = ByteArrayOutputStream() - WasmIrToBinary(os, linkedModule).appendWasmModule() + WasmIrToBinary(os, linkedModule, moduleDescriptor.name.asString(), emitNameSection).appendWasmModule() val byteArray = os.toByteArray() return WasmCompilerResult( diff --git a/compiler/testData/cli/js/jsExtraHelp.out b/compiler/testData/cli/js/jsExtraHelp.out index 33654c4829f..511f8af39ab 100644 --- a/compiler/testData/cli/js/jsExtraHelp.out +++ b/compiler/testData/cli/js/jsExtraHelp.out @@ -36,6 +36,7 @@ where advanced options include: -Xrepositories= Paths to additional places where libraries could be found -Xtyped-arrays Translate primitive arrays to JS typed arrays -Xwasm Use experimental WebAssembly compiler backend + -Xwasm-debug-info Add debug info to WebAssembly compiled module -Xallow-kotlin-package Allow compiling code in package 'kotlin' and allow not requiring kotlin.stdlib in module-info -Xallow-result-return-type Allow compiling code when `kotlin.Result` is used as a return type -Xbuiltins-from-sources Compile builtIns from sources diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt index 45db2f9201f..d507d3623ee 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt @@ -15,8 +15,6 @@ import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.* -import org.jetbrains.kotlin.ir.backend.js.MainModule -import org.jetbrains.kotlin.ir.backend.js.ModulesStructure import org.jetbrains.kotlin.ir.backend.js.loadKlib import org.jetbrains.kotlin.ir.backend.js.prepareAnalyzedSourceModule import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName @@ -171,7 +169,8 @@ abstract class BasicWasmBoxTest( sourceModule, phaseConfig = phaseConfig, irFactory = IrFactoryImpl, - exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))) + exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction))), + emitNameSection = true, ) outputWatFile.write(compilerResult.wat) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt index 41c6a656191..c161d060a60 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.wasm.ir.* import java.io.ByteArrayOutputStream import java.io.OutputStream -class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) { +class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule, val moduleName: String, val emitNameSection: Boolean) { var b: ByteWriter = ByteWriter.OutputStream(outputStream) fun appendWasmModule() { @@ -109,6 +109,38 @@ class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) { appendVectorSize(data.size) data.forEach { appendData(it) } } + + //text section (should be placed after data) + if (emitNameSection) { + appendTextSection(definedFunctions) + } + } + } + + private fun appendTextSection(definedFunctions: List) { + appendSection(0u) { + b.writeString("name") + appendSection(0u) { + b.writeString(moduleName) + } + appendSection(1u) { + appendVectorSize(definedFunctions.size) + definedFunctions.forEach { + appendModuleFieldReference(it) + b.writeString(it.name) + } + } + appendSection(2u) { + appendVectorSize(definedFunctions.size) + definedFunctions.forEach { + appendModuleFieldReference(it) + appendVectorSize(it.locals.size) + it.locals.forEach { local -> + b.writeVarUInt32(local.id) + b.writeString(local.name) + } + } + } } } diff --git a/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt b/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt index fd88c76be3b..e575e896efc 100644 --- a/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt +++ b/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt @@ -228,7 +228,7 @@ fun testWasmFile(wasmFile: File, dirName: String) { fun WasmModule.toBinaryFormat(): ByteArray { val os = ByteArrayOutputStream() - WasmIrToBinary(os, this).appendWasmModule() + WasmIrToBinary(os, this, "", emitNameSection = false).appendWasmModule() return os.toByteArray() }