[Wasm] split wasmModule linking and compiling it into binary
diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt
index 43e36f7..47e4add 100644
--- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt
+++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt
@@ -44,6 +44,7 @@
 import org.jetbrains.kotlin.wasm.ir.WasmBinaryData
 import org.jetbrains.kotlin.wasm.ir.WasmBinaryData.Companion.writeTo
 import org.jetbrains.kotlin.wasm.ir.WasmExport
+import org.jetbrains.kotlin.wasm.ir.WasmModule
 import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToBinary
 import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToText
 import org.jetbrains.kotlin.wasm.ir.debug.DebugInformationGeneratorImpl
@@ -196,11 +197,26 @@
     val multimoduleOptions: MultimoduleCompileOptions?,
 )
 
+data class WasmCompilerResultWithLinkedModule(
+    val linkedModule: WasmModule,
+    val compilerResult: WasmCompilerResult,
+)
+
+fun linkAndCompileWasmIrToBinaryWithLinkedModule(moduleConfiguration: WasmIrModuleConfiguration): WasmCompilerResultWithLinkedModule {
+    val linkedModule = linkWasmModule(moduleConfiguration)
+    val compilerResult = compileWasmIrToBinary(linkedModule, moduleConfiguration)
+    return WasmCompilerResultWithLinkedModule(linkedModule, compilerResult)
+}
+
 fun linkAndCompileWasmIrToBinary(moduleConfiguration: WasmIrModuleConfiguration): WasmCompilerResult {
+    val linkedModule = linkWasmModule(moduleConfiguration)
+    return compileWasmIrToBinary(linkedModule, moduleConfiguration)
+}
+
+fun linkWasmModule(moduleConfiguration: WasmIrModuleConfiguration): WasmModule {
     val wasmCompiledFileFragments = moduleConfiguration.wasmCompiledFileFragments
 
     val configuration = moduleConfiguration.configuration
-    val baseFileName = moduleConfiguration.baseFileName
 
     val isWasmJsTarget = configuration.get(WasmConfigurationKeys.WASM_TARGET) != WasmTarget.WASI
 
@@ -217,11 +233,22 @@
 
     val wasmCommandModuleInitialization = configuration.get(WasmConfigurationKeys.WASM_COMMAND_MODULE) ?: false
 
-    val linkedModule = wasmCompiledModuleFragment.linkWasmCompiledFragments(
+    return wasmCompiledModuleFragment.linkWasmCompiledFragments(
         multimoduleOptions = multimoduleParameters,
         exceptionTagType = exceptionTagType,
         wasmCommandModuleInitialization = wasmCommandModuleInitialization,
     )
+}
+
+fun compileWasmIrToBinary(linkedModule: WasmModule, moduleConfiguration: WasmIrModuleConfiguration): WasmCompilerResult {
+    val wasmCompiledFileFragments = moduleConfiguration.wasmCompiledFileFragments
+
+    val configuration = moduleConfiguration.configuration
+    val baseFileName = moduleConfiguration.baseFileName
+
+    val isWasmJsTarget = configuration.get(WasmConfigurationKeys.WASM_TARGET) != WasmTarget.WASI
+
+    val multimoduleParameters = moduleConfiguration.multimoduleOptions
 
     val wasmStartFunctionDefined = linkedModule.exports.any { it.name == wasmStartExportName }
     val wasmInitializeFunctionDefined = linkedModule.exports.any { it.name == wasmInitializeExportName }
@@ -339,7 +366,7 @@
 
     } else {
         jsWrapper =
-            wasmCompiledModuleFragment.generateAsyncWasiWrapper(
+            generateAsyncWasiWrapper(
                 wasmFilePath = "./$baseFileName.wasm",
                 exports = linkedModule.exports,
                 useDebuggerCustomFormatters = debuggerParameters.useDebuggerCustomFormatters,
@@ -364,7 +391,7 @@
 }
 
 //language=js
-fun WasmCompiledModuleFragment.generateAsyncWasiWrapper(
+fun generateAsyncWasiWrapper(
     wasmFilePath: String,
     exports: List<WasmExport<*>>,
     useDebuggerCustomFormatters: Boolean,
diff --git a/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringFacade.kt b/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringFacade.kt
index 30b03c1..3d30389 100644
--- a/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringFacade.kt
+++ b/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringFacade.kt
@@ -9,15 +9,12 @@
 import org.jetbrains.kotlin.backend.wasm.WasmIrModuleConfiguration
 import org.jetbrains.kotlin.backend.wasm.WasmCompilerResult
 import org.jetbrains.kotlin.backend.wasm.compileToLoweredIr
-import org.jetbrains.kotlin.backend.wasm.linkAndCompileWasmIrToBinary
 import org.jetbrains.kotlin.backend.wasm.dce.eliminateDeadDeclarations
 import org.jetbrains.kotlin.backend.wasm.ic.IrFactoryImplForWasmIC
-import org.jetbrains.kotlin.backend.wasm.ir2wasm.ExceptionTagType
-import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledFileFragment
-import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledModuleFragment
 import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleFragmentGenerator
 import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmModuleMetadataCache
-import org.jetbrains.kotlin.config.CompilerConfiguration
+import org.jetbrains.kotlin.backend.wasm.linkAndCompileWasmIrToBinary
+import org.jetbrains.kotlin.backend.wasm.linkAndCompileWasmIrToBinaryWithLinkedModule
 import org.jetbrains.kotlin.config.perfManager
 import org.jetbrains.kotlin.config.phaseConfig
 import org.jetbrains.kotlin.config.phaser.PhaseConfig
@@ -27,7 +24,6 @@
 import org.jetbrains.kotlin.ir.backend.js.dce.dumpDeclarationIrSizesIfNeed
 import org.jetbrains.kotlin.js.config.JSConfigurationKeys
 import org.jetbrains.kotlin.name.FqName
-import org.jetbrains.kotlin.platform.wasm.WasmTarget
 import org.jetbrains.kotlin.psi.KtNamedFunction
 import org.jetbrains.kotlin.test.DebugMode
 import org.jetbrains.kotlin.test.backend.ir.IrBackendInput
@@ -127,13 +123,7 @@
             multimoduleOptions = null,
         )
 
-        val compilerResult = linkAndCompileWasmIrToBinary(parameters)
-
-        val linkedModule = getLinkedModule(
-            parameters,
-            allModules.map { codeGenerator.generateModuleAsSingleFileFragment(it) },
-            configuration
-        )
+        val (linkedModule, compilerResult) = linkAndCompileWasmIrToBinaryWithLinkedModule(parameters)
 
         val dceDumpNameCache = DceDumpNameCache()
         eliminateDeadDeclarations(allModules, backendContext, dceDumpNameCache)
@@ -204,30 +194,4 @@
     } ?: return null
 
     return fileWithBoxFunction.packageFqName.asString().takeIf { it.isNotEmpty() }
-}
-
-internal fun getLinkedModule(moduleConfiguration: WasmIrModuleConfiguration, wasmCompiledFileFragments: List<WasmCompiledFileFragment>, configuration: CompilerConfiguration): WasmModule {
-    val isWasmJsTarget = configuration.get(WasmConfigurationKeys.WASM_TARGET) != WasmTarget.WASI
-
-    val wasmCompiledModuleFragment = WasmCompiledModuleFragment(
-        wasmCompiledFileFragments,
-        isWasmJsTarget,
-    )
-
-    val multimoduleParameters = moduleConfiguration.multimoduleOptions
-
-    val exceptionTagType: ExceptionTagType = when {
-        configuration.getBoolean(WasmConfigurationKeys.WASM_USE_TRAPS_INSTEAD_OF_EXCEPTIONS) ->
-            ExceptionTagType.TRAP
-        isWasmJsTarget -> ExceptionTagType.JS_TAG
-        else -> ExceptionTagType.WASM_TAG
-    }
-
-    val wasmCommandModuleInitialization = configuration.get(WasmConfigurationKeys.WASM_COMMAND_MODULE) ?: false
-
-    return wasmCompiledModuleFragment.linkWasmCompiledFragments(
-        multimoduleOptions = multimoduleParameters,
-        exceptionTagType = exceptionTagType,
-        wasmCommandModuleInitialization = wasmCommandModuleInitialization
-    )
 }
\ No newline at end of file
diff --git a/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringSingleModuleFacade.kt b/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringSingleModuleFacade.kt
index fd25191..162e4ea 100644
--- a/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringSingleModuleFacade.kt
+++ b/wasm/wasm.tests/testFixtures/org/jetbrains/kotlin/wasm/test/converters/WasmLoweringSingleModuleFacade.kt
@@ -6,7 +6,7 @@
 package org.jetbrains.kotlin.wasm.test.converters
 
 import org.jetbrains.kotlin.backend.wasm.compileToLoweredIr
-import org.jetbrains.kotlin.backend.wasm.linkAndCompileWasmIrToBinary
+import org.jetbrains.kotlin.backend.wasm.linkAndCompileWasmIrToBinaryWithLinkedModule
 import org.jetbrains.kotlin.cli.pipeline.web.wasm.compileWasmLoweredFragmentsForSingleModule
 import org.jetbrains.kotlin.config.perfManager
 import org.jetbrains.kotlin.ir.backend.js.MainModule
@@ -26,6 +26,7 @@
 import org.jetbrains.kotlin.test.services.moduleStructure
 import org.jetbrains.kotlin.util.PhaseType
 import org.jetbrains.kotlin.wasm.config.WasmConfigurationKeys
+import org.jetbrains.kotlin.wasm.ir.WasmModule
 import org.jetbrains.kotlin.wasm.test.PrecompileSetup
 import org.jetbrains.kotlin.wasm.test.handlers.getWasmTestOutputDirectory
 import org.jetbrains.kotlin.wasm.test.precompiledKotlinTestOutputName
@@ -115,13 +116,7 @@
             generateDwarf = generateDwarf,
         )
 
-        val compileResult = linkAndCompileWasmIrToBinary(wasmIrToCompile)
-
-        val linkedModule = getLinkedModule(
-            wasmIrToCompile,
-            wasmIrToCompile.wasmCompiledFileFragments,
-            configuration
-        )
+        val (linkedModule, compileResult) = linkAndCompileWasmIrToBinaryWithLinkedModule(wasmIrToCompile)
 
         return BinaryArtifacts.Wasm(
             linkedModule,