/* * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ package org.jetbrains.kotlin.generators.wasm import org.jetbrains.kotlin.wasm.ir.WasmOp import java.io.File import java.io.FileWriter fun main() { val targetDir = File("libraries/stdlib/wasm/src/generated/wasm/internal/") generateWasmOps(targetDir) generateWasmArrays(targetDir) } private fun FileWriter.generateStandardWasmInternalHeader() { appendLine(File("license/COPYRIGHT_HEADER.txt").readText()) appendLine() appendLine("package kotlin.wasm.internal") appendLine() appendLine("//") appendLine("// NOTE: THIS FILE IS AUTO-GENERATED by the generators/wasm/WasmIntrinsicGenerator.kt") appendLine("//") appendLine() } private fun generateWasmOps(targetDir: File) { FileWriter(targetDir.resolve("_WasmOp.kt")).use { writer -> writer.generateStandardWasmInternalHeader() writer.appendLine( """ @ExcludedFromCodegen @Suppress("unused") @Target(AnnotationTarget.FUNCTION) @Retention(AnnotationRetention.BINARY) internal annotation class WasmOp(val name: String) { companion object { """.trimIndent() ) WasmOp.values().forEach { op -> writer.appendLine(" const val $op = \"$op\"") } writer.appendLine( """ } } """.trimIndent() ) } } private fun generateWasmArrays(targetDir: File) { FileWriter(targetDir.resolve("_WasmArrays.kt")).use { writer -> writer.generateStandardWasmInternalHeader() writer.appendLine(wasmArrayForType("Any", true)) val types = listOf( "Byte", "Char", "Short", "Int", "Long", "Float", "Double" ) types.forEach { primitive -> val isPacked = primitive in setOf( "Byte", "Char", "Short", ) val isUnsigned = primitive == "Char" writer.appendLine( wasmArrayForType( primitive, false, isPacked, isUnsigned ) ) } } } private fun wasmArrayForType( klass: String, isNullable: Boolean, isPacked: Boolean = false, isUnsigned: Boolean = false, ): String { val type = klass + if (isNullable) "?" else "" val name = "Wasm${klass}Array" val getSuffix = when { isPacked && isUnsigned -> "_U" isPacked && !isUnsigned -> "_S" else -> "" } return """ @Suppress("UNUSED_PARAMETER") @WasmArrayOf($klass::class, isNullable = $isNullable) internal class $name(size: Int) { @WasmOp(WasmOp.ARRAY_GET${getSuffix}) fun get(index: Int): $type = implementedAsIntrinsic @WasmOp(WasmOp.ARRAY_SET) fun set(index: Int, value: $type): Unit = implementedAsIntrinsic @WasmOp(WasmOp.ARRAY_LEN) fun len(): Int = implementedAsIntrinsic } @Suppress("NOTHING_TO_INLINE") internal inline fun copyWasmArray(source: $name, destination: $name, sourceIndex: Int, destinationIndex: Int, length: Int) { wasm_array_copy<$name>(destination, destinationIndex, source, sourceIndex, length) } internal inline fun $name.fill(size: Int, init: (Int) -> $type) { var i = 0 while (i < size) { set(i, init(i)) i++ } } """.trimIndent() }