blob: a13b6f7fa35161bd4fb756329d1d69578cf8432d [file] [log] [blame]
/*
* 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()
}