in compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/wasmCompiler.kt [199:364]
fun linkAndCompileWasmIrToBinary(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 exceptionTagType: ExceptionTagType = when {
configuration.getBoolean(WasmConfigurationKeys.WASM_USE_TRAPS_INSTEAD_OF_EXCEPTIONS) ->
ExceptionTagType.TRAP
isWasmJsTarget -> ExceptionTagType.JS_TAG
else -> ExceptionTagType.WASM_TAG
}
val multimoduleParameters = moduleConfiguration.multimoduleOptions
val wasmCompiledModuleFragment = WasmCompiledModuleFragment(wasmCompiledFileFragments, isWasmJsTarget)
val wasmCommandModuleInitialization = configuration.get(WasmConfigurationKeys.WASM_COMMAND_MODULE) ?: false
val linkedModule = wasmCompiledModuleFragment.linkWasmCompiledFragments(
multimoduleOptions = multimoduleParameters,
exceptionTagType = exceptionTagType,
wasmCommandModuleInitialization = wasmCommandModuleInitialization,
)
val wasmStartFunctionDefined = linkedModule.exports.any { it.name == wasmStartExportName }
val wasmInitializeFunctionDefined = linkedModule.exports.any { it.name == wasmInitializeExportName }
val debuggerParameters = moduleConfiguration.debuggerOptions
val dwarfGeneratorForBinary = runIf(debuggerParameters.generateDwarf) {
DwarfGenerator()
}
val sourceMapGeneratorForBinary = runIf(debuggerParameters.generateSourceMaps) {
SourceMapGenerator("$baseFileName.wasm", configuration)
}
val sourceMapGeneratorForText = runIf(moduleConfiguration.generateWat && debuggerParameters.generateSourceMaps) {
SourceMapGenerator("$baseFileName.wat", configuration)
}
val wat = if (moduleConfiguration.generateWat) {
val watGenerator = WasmIrToText(linkedModule, sourceMapGeneratorForText)
watGenerator.appendWasmModule()
watGenerator.toString()
} else {
null
}
val writer = ByteWriterWithOffsetWrite()
val wasmIrToBinary =
WasmIrToBinary(
writer,
linkedModule,
moduleConfiguration.moduleName,
debuggerParameters.emitNameSection,
DebugInformationGeneratorImpl.createIfNeeded(
sourceMapGenerator = sourceMapGeneratorForBinary,
dwarfGenerator = dwarfGeneratorForBinary,
)
)
wasmIrToBinary.appendWasmModule()
val jsWrapper: String
val dynamicJsModules = mutableListOf<DynamicJsModule>()
if (isWasmJsTarget) {
val jsModuleImports = mutableSetOf<String>()
val jsFuns = mutableSetOf<JsCodeSnippet>()
val jsModuleAndQualifierReferences = mutableSetOf<JsModuleAndQualifierReference>()
wasmCompiledFileFragments.forEach { fragment ->
jsModuleImports.addAll(fragment.jsModuleImports.values.distinct())
jsFuns.addAll(fragment.jsFuns.values)
jsModuleAndQualifierReferences.addAll(fragment.jsModuleAndQualifierReferences)
}
val useJsTag = !configuration.getBoolean(WasmConfigurationKeys.WASM_NO_JS_TAG)
val jsBuiltinsComposed =
wasmCompiledFileFragments.flatMap { fragment ->
fragment.jsBuiltinsPolyfills.values.toList()
}.joinToString("\n")
if (jsBuiltinsComposed.isNotEmpty()) {
dynamicJsModules.add(
DynamicJsModule(
name = "js-builtins",
content = jsBuiltinsComposed
)
)
}
val wholeProgramMode: Boolean
val isStdlibModule: Boolean
val stdlibModule: WasmModuleDependencyImport?
if (multimoduleParameters != null) {
wholeProgramMode = false
val stdlibModuleNameForImport = multimoduleParameters.stdlibModuleNameForImport
isStdlibModule = stdlibModuleNameForImport == null
stdlibModule = multimoduleParameters.dependencyModules.find { it.name == stdlibModuleNameForImport }
} else {
wholeProgramMode = true
isStdlibModule = false
stdlibModule = null
}
val importObject = generateImportObject(
jsModuleImports = jsModuleImports,
jsModuleAndQualifierReferences = jsModuleAndQualifierReferences,
dependencyModules = multimoduleParameters?.dependencyModules ?: emptySet(),
baseFileName = baseFileName,
jsFuns = jsFuns,
stdlibModule = stdlibModule,
isStdlibModule = isStdlibModule,
useJsTag = useJsTag,
wholeProgramMode = wholeProgramMode
)
if (importObject.isNotEmpty()) {
dynamicJsModules.add(
DynamicJsModule(
name = "import-object",
content = importObject
)
)
}
jsWrapper = generateWebAssemblyJsInstanceInitializer(
jsModuleImports = jsModuleImports,
wasmFilePath = "./$baseFileName.wasm",
exports = linkedModule.exports,
useDebuggerCustomFormatters = debuggerParameters.useDebuggerCustomFormatters,
baseFileName = baseFileName,
isStdlibModule = isStdlibModule,
wholeProgramMode = wholeProgramMode,
wasmStartFunctionDefined = wasmStartFunctionDefined,
wasmInitializeFunctionDefined = wasmInitializeFunctionDefined
)
} else {
jsWrapper =
wasmCompiledModuleFragment.generateAsyncWasiWrapper(
wasmFilePath = "./$baseFileName.wasm",
exports = linkedModule.exports,
useDebuggerCustomFormatters = debuggerParameters.useDebuggerCustomFormatters,
wasmStartFunctionDefined = wasmStartFunctionDefined,
wasmInitializeFunctionDefined = wasmInitializeFunctionDefined
)
}
return WasmCompilerResult(
wat = wat,
jsWrapper = jsWrapper.normalizeEmptyLines(),
wasm = writer.getBinaryData(),
debugInformation = DebugInformation(
sourceMapGeneratorForBinary?.generate(),
sourceMapGeneratorForText?.generate(),
),
dts = moduleConfiguration.typeScriptFragment?.raw,
useDebuggerCustomFormatters = debuggerParameters.useDebuggerCustomFormatters,
dynamicJsModules = dynamicJsModules.map { it.copy(content = it.content.normalizeEmptyLines()) },
baseFileName = baseFileName,
)
}