[WASM] Initial infrastructure

- New module ":compiler:backend.wasm"
    - Initial compiler infra (driver, phaser, context)
    - Subset of Wasm AST
    - Skeleton of IR -> Wasm AST
    - Wasm AST -> WAT transformer

- Testing infra

- SpiderMonkey jsshell tool
This commit is contained in:
Svyatoslav Kuzmich
2019-08-07 14:27:18 +03:00
parent 812083ee05
commit 6e6ffa12a6
106 changed files with 6418 additions and 584 deletions
+9
View File
@@ -0,0 +1,9 @@
<component name="ProjectDictionaryState">
<dictionary name="skuzmich">
<words>
<w>anyref</w>
<w>ushr</w>
<w>wasm</w>
</words>
</dictionary>
</component>
+6 -16
View File
@@ -23,28 +23,14 @@
</component>
<component name="IdProvider" IDEtalkID="71A301FF1940049D6D82F12C40F1E1D5" />
<component name="JavadocGenerationManager">
<option name="OUTPUT_DIRECTORY" />
<option name="OPTION_SCOPE" value="protected" />
<option name="OPTION_HIERARCHY" value="true" />
<option name="OPTION_NAVIGATOR" value="true" />
<option name="OPTION_INDEX" value="true" />
<option name="OPTION_SEPARATE_INDEX" value="true" />
<option name="OPTION_DOCUMENT_TAG_USE" value="false" />
<option name="OPTION_DOCUMENT_TAG_AUTHOR" value="false" />
<option name="OPTION_DOCUMENT_TAG_VERSION" value="false" />
<option name="OPTION_DOCUMENT_TAG_DEPRECATED" value="true" />
<option name="OPTION_DEPRECATED_LIST" value="true" />
<option name="OTHER_OPTIONS" value="" />
<option name="HEAP_SIZE" />
<option name="LOCALE" />
<option name="OPEN_IN_BROWSER" value="true" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="org.jetbrains.annotations.Nullable" />
<option name="myDefaultNotNull" value="org.jetbrains.annotations.NotNull" />
<option name="myNullables">
<value>
<list size="9">
<list size="11">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
@@ -54,12 +40,14 @@
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
<item index="9" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="9">
<list size="11">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="javax.validation.constraints.NotNull" />
@@ -69,6 +57,8 @@
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
<item index="9" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
<item index="10" class="java.lang.String" itemvalue="com.android.annotations.NonNull" />
</list>
</value>
</option>
+6 -1
View File
@@ -3,7 +3,6 @@ import org.gradle.plugins.ide.idea.model.IdeaModel
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import proguard.gradle.ProGuardTask
import org.gradle.kotlin.dsl.*
buildscript {
extra["defaultSnapshotVersion"] = "1.3-SNAPSHOT"
@@ -212,6 +211,7 @@ extra["compilerModules"] = arrayOf(
":compiler:ir.backend.common",
":compiler:backend.jvm",
":compiler:backend.js",
":compiler:backend.wasm",
":compiler:ir.serialization.common",
":compiler:ir.serialization.js",
":kotlin-util-io",
@@ -506,6 +506,10 @@ tasks {
dependsOn(":js:js.tests:runMocha")
}
register("wasmCompilerTest") {
dependsOn(":js:js.tests:wasmTest")
}
register("firCompilerTest") {
dependsOn(":compiler:fir:psi2fir:test")
dependsOn(":compiler:fir:resolve:test")
@@ -527,6 +531,7 @@ tasks {
register("compilerTest") {
dependsOn("jvmCompilerTest")
dependsOn("jsCompilerTest")
dependsOn("wasmCompilerTest")
dependsOn("firCompilerTest")
dependsOn("scriptingTest")
@@ -19,7 +19,7 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.utils.DFS
private fun sortDependencies(dependencies: Collection<IrModuleFragment>): Collection<IrModuleFragment> {
fun sortDependencies(dependencies: Collection<IrModuleFragment>): Collection<IrModuleFragment> {
val mapping = dependencies.map { it.descriptor to it }.toMap()
return DFS.topologicalOrder(dependencies) { m ->
@@ -23,7 +23,7 @@ object JsAnnotations {
}
@Suppress("UNCHECKED_CAST")
private fun IrConstructorCall.getSingleConstStringArgument() =
fun IrConstructorCall.getSingleConstStringArgument() =
(getValueArgument(0) as IrConst<String>).value
fun IrAnnotationContainer.getJsModule(): String? =
@@ -23,7 +23,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
class NameTable<T>(
val parent: NameTable<T>? = null,
private val reserved: MutableSet<String> = mutableSetOf()
private val reserved: MutableSet<String> = mutableSetOf(),
val sanitizer: (String) -> String = ::sanitizeName
) {
var finished = false
val names = mutableMapOf<T, String>()
@@ -41,9 +42,10 @@ class NameTable<T>(
reserved.add(name)
}
fun declareFreshName(declaration: T, suggestedName: String) {
val freshName = findFreshName(sanitizeName(suggestedName))
fun declareFreshName(declaration: T, suggestedName: String): String {
val freshName = findFreshName(sanitizer(suggestedName))
declareStableName(declaration, freshName)
return freshName
}
private fun findFreshName(suggestedName: String): String {
+26
View File
@@ -0,0 +1,26 @@
plugins {
kotlin("jvm")
id("jps-compatible")
}
dependencies {
compile(project(":compiler:util"))
compile(project(":compiler:frontend"))
compile(project(":compiler:backend-common"))
compile(project(":compiler:ir.tree"))
compile(project(":compiler:ir.psi2ir"))
compile(project(":compiler:ir.backend.common"))
compile(project(":compiler:ir.serialization.common"))
compile(project(":compiler:ir.serialization.js"))
compile(project(":js:js.ast"))
compile(project(":js:js.frontend"))
compile(project(":compiler:backend.js"))
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
}
sourceSets {
"main" { projectDefault() }
"test" {}
}
@@ -0,0 +1,91 @@
/*
* Copyright 2010-2019 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.backend.wasm
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.backend.js.JsDeclarationFactory
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.JsSharedVariablesManager
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
class WasmBackendContext(
val module: ModuleDescriptor,
override val irBuiltIns: IrBuiltIns,
symbolTable: SymbolTable,
irModuleFragment: IrModuleFragment,
val additionalExportedDeclarations: Set<FqName>,
override val configuration: CompilerConfiguration
) : CommonBackendContext {
override val builtIns = module.builtIns
override var inVerbosePhase: Boolean = false
// Place to store declarations excluded from code generation
val excludedDeclarations: IrPackageFragment by lazy {
IrExternalPackageFragmentImpl(
DescriptorlessExternalPackageFragmentSymbol(),
FqName("kotlin")
)
}
override val declarationFactory = JsDeclarationFactory()
val objectToGetInstanceFunction = mutableMapOf<IrClassSymbol, IrSimpleFunction>()
override val internalPackageFqn = FqName("kotlin.wasm")
private val internalPackageFragment = IrExternalPackageFragmentImpl(
IrExternalPackageFragmentSymbolImpl(
EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.wasm.internal"))
)
)
override val sharedVariablesManager = JsSharedVariablesManager(irBuiltIns, internalPackageFragment)
val wasmSymbols: WasmSymbols = WasmSymbols(this@WasmBackendContext, symbolTable)
override val ir = object : Ir<WasmBackendContext>(this, irModuleFragment) {
override val symbols: Symbols<WasmBackendContext> = wasmSymbols
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
}
override fun log(message: () -> String) {
/*TODO*/
if (inVerbosePhase) print(message())
}
override fun report(element: IrElement?, irFile: IrFile?, message: String, isError: Boolean) {
/*TODO*/
print(message)
}
}
class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
override val descriptor: PackageFragmentDescriptor
get() = error("Operation is unsupported")
private var _owner: IrExternalPackageFragment? = null
override val owner get() = _owner!!
override val isBound get() = _owner != null
override fun bind(owner: IrExternalPackageFragment) {
_owner = owner
}
}
@@ -0,0 +1,414 @@
/*
* Copyright 2010-2019 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.backend.wasm
import org.jetbrains.kotlin.backend.common.*
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.lower.inline.FunctionInlining
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.wasm.lower.BuiltInsLowering
import org.jetbrains.kotlin.backend.wasm.lower.WasmBlockDecomposerLowering
import org.jetbrains.kotlin.backend.wasm.lower.excludeDeclarationsFromCodegen
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ReturnableBlockLowering
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment) = moduleFragment.files.forEach { runOnFilePostfix(it) }
private fun validationCallback(context: WasmBackendContext, module: IrModuleFragment) {
val validatorConfig = IrValidatorConfig(
abortOnError = true,
ensureAllNodesAreDifferent = true,
checkTypes = false,
checkDescriptors = false
)
module.accept(IrValidator(context, validatorConfig), null)
module.accept(CheckDeclarationParentsVisitor, null)
}
val validationAction = makeVerifyAction(::validationCallback)
private fun makeWasmModulePhase(
lowering: (WasmBackendContext) -> FileLoweringPass,
name: String,
description: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = makeIrModulePhase<WasmBackendContext>(lowering, name, description, prerequisite, actions = setOf(validationAction, defaultDumper))
private fun makeCustomWasmModulePhase(
op: (WasmBackendContext, IrModuleFragment) -> Unit,
description: String,
name: String,
prerequisite: Set<AnyNamedPhase> = emptySet()
) = namedIrModulePhase(
name,
description,
prerequisite,
actions = setOf(defaultDumper, validationAction),
nlevels = 0,
lower = object : SameTypeCompilerPhase<WasmBackendContext, IrModuleFragment> {
override fun invoke(
phaseConfig: PhaseConfig,
phaserState: PhaserState<IrModuleFragment>,
context: WasmBackendContext,
input: IrModuleFragment
): IrModuleFragment {
op(context, input)
return input
}
}
)
private val validateIrBeforeLowering = makeCustomWasmModulePhase(
{ context, module -> validationCallback(context, module) },
name = "ValidateIrBeforeLowering",
description = "Validate IR before lowering"
)
private val validateIrAfterLowering = makeCustomWasmModulePhase(
{ context, module -> validationCallback(context, module) },
name = "ValidateIrAfterLowering",
description = "Validate IR after lowering"
)
private val expectDeclarationsRemovingPhase = makeWasmModulePhase(
::ExpectDeclarationsRemoveLowering,
name = "ExpectDeclarationsRemoving",
description = "Remove expect declaration from module fragment"
)
private val lateinitLoweringPhase = makeWasmModulePhase(
::LateinitLowering,
name = "LateinitLowering",
description = "Insert checks for lateinit field references"
)
// TODO make all lambda-related stuff work with IrFunctionExpression and drop this phase
private val provisionalFunctionExpressionPhase = makeWasmModulePhase(
{ ProvisionalFunctionExpressionLowering() },
name = "FunctionExpression",
description = "Transform IrFunctionExpression to a local function reference"
)
private val arrayConstructorPhase = makeWasmModulePhase(
::ArrayConstructorLowering,
name = "ArrayConstructor",
description = "Transform `Array(size) { index -> value }` into a loop"
)
private val functionInliningPhase = makeCustomWasmModulePhase(
{ context, module ->
FunctionInlining(context).inline(module)
module.patchDeclarationParents()
},
name = "FunctionInliningPhase",
description = "Perform function inlining",
prerequisite = setOf(expectDeclarationsRemovingPhase)
)
private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeWasmModulePhase(
{ RemoveInlineFunctionsWithReifiedTypeParametersLowering() },
name = "RemoveInlineFunctionsWithReifiedTypeParametersLowering",
description = "Remove Inline functions with reified parameters from context",
prerequisite = setOf(functionInliningPhase)
)
private val tailrecLoweringPhase = makeWasmModulePhase(
::TailrecLowering,
name = "TailrecLowering",
description = "Replace `tailrec` callsites with equivalent loop"
)
private val enumClassConstructorLoweringPhase = makeWasmModulePhase(
::EnumClassConstructorLowering,
name = "EnumClassConstructorLowering",
description = "Transform Enum Class into regular Class"
)
private val sharedVariablesLoweringPhase = makeWasmModulePhase(
::SharedVariablesLowering,
name = "SharedVariablesLowering",
description = "Box captured mutable variables"
)
private val localDelegatedPropertiesLoweringPhase = makeWasmModulePhase(
{ LocalDelegatedPropertiesLowering() },
name = "LocalDelegatedPropertiesLowering",
description = "Transform Local Delegated properties"
)
private val localDeclarationsLoweringPhase = makeWasmModulePhase(
::LocalDeclarationsLowering,
name = "LocalDeclarationsLowering",
description = "Move local declarations into nearest declaration container",
prerequisite = setOf(sharedVariablesLoweringPhase, localDelegatedPropertiesLoweringPhase)
)
private val localClassExtractionPhase = makeWasmModulePhase(
::LocalClassPopupLowering,
name = "LocalClassExtractionPhase",
description = "Move local declarations into nearest declaration container",
prerequisite = setOf(localDeclarationsLoweringPhase)
)
private val innerClassesLoweringPhase = makeWasmModulePhase(
::InnerClassesLowering,
name = "InnerClassesLowering",
description = "Capture outer this reference to inner class"
)
private val innerClassConstructorCallsLoweringPhase = makeWasmModulePhase(
::InnerClassConstructorCallsLowering,
name = "InnerClassConstructorCallsLowering",
description = "Replace inner class constructor invocation"
)
private val defaultArgumentStubGeneratorPhase = makeWasmModulePhase(
::DefaultArgumentStubGenerator,
name = "DefaultArgumentStubGenerator",
description = "Generate synthetic stubs for functions with default parameter values"
)
private val defaultParameterInjectorPhase = makeWasmModulePhase(
{ context -> DefaultParameterInjector(context, skipExternalMethods = true) },
name = "DefaultParameterInjector",
description = "Replace callsite with default parameters with corresponding stub function",
prerequisite = setOf(innerClassesLoweringPhase)
)
private val defaultParameterCleanerPhase = makeWasmModulePhase(
::DefaultParameterCleaner,
name = "DefaultParameterCleaner",
description = "Clean default parameters up"
)
//private val jsDefaultCallbackGeneratorPhase = makeJsModulePhase(
// ::JsDefaultCallbackGenerator,
// name = "JsDefaultCallbackGenerator",
// description = "Build binding for super calls with default parameters"
//)
//private val varargLoweringPhase = makeJsModulePhase(
// ::VarargLowering,
// name = "VarargLowering",
// description = "Lower vararg arguments"
//)
private val propertiesLoweringPhase = makeWasmModulePhase(
{ context -> PropertiesLowering(context, skipExternalProperties = true, generateAnnotationFields = true) },
name = "PropertiesLowering",
description = "Move fields and accessors out from its property"
)
private val primaryConstructorLoweringPhase = makeWasmModulePhase(
::PrimaryConstructorLowering,
name = "PrimaryConstructorLowering",
description = "Creates primary constructor if it doesn't exist"
)
private val initializersLoweringPhase = makeCustomWasmModulePhase(
{ context, module -> InitializersLowering(context, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).lower(module) },
name = "InitializersLowering",
description = "Merge init block and field initializers into [primary] constructor",
prerequisite = setOf(primaryConstructorLoweringPhase)
)
private val excludeDeclarationsFromCodegenPhase = makeCustomWasmModulePhase(
{ context, module ->
excludeDeclarationsFromCodegen(context, module)
},
name = "ExcludeDeclarationsFromCodegen",
description = "Move excluded declarations to separate place"
)
private val returnableBlockLoweringPhase = makeWasmModulePhase(
::ReturnableBlockLowering,
name = "ReturnableBlockLowering",
description = "Replace returnable block with do-while loop",
prerequisite = setOf(functionInliningPhase)
)
private val bridgesConstructionPhase = makeWasmModulePhase(
::BridgesConstruction,
name = "BridgesConstruction",
description = "Generate bridges"
)
private val inlineClassLoweringPhase = makeCustomWasmModulePhase(
{ context, module ->
InlineClassLowering(context).run {
inlineClassDeclarationLowering.runOnFilesPostfix(module)
inlineClassUsageLowering.lower(module)
}
},
name = "InlineClassLowering",
description = "Handle inline classes"
)
//private val autoboxingTransformerPhase = makeJsModulePhase(
// ::AutoboxingTransformer,
// name = "AutoboxingTransformer",
// description = "Insert box/unbox intrinsics"
//)
private val blockDecomposerLoweringPhase = makeCustomWasmModulePhase(
{ context, module ->
WasmBlockDecomposerLowering(context).lower(module)
module.patchDeclarationParents()
},
name = "BlockDecomposerLowering",
description = "Transform statement-like-expression nodes into pure-statement to make it easily transform into JS"
)
//private val classReferenceLoweringPhase = makeJsModulePhase(
// ::ClassReferenceLowering,
// name = "ClassReferenceLowering",
// description = "Handle class references"
//)
//
//private val primitiveCompanionLoweringPhase = makeJsModulePhase(
// ::PrimitiveCompanionLowering,
// name = "PrimitiveCompanionLowering",
// description = "Replace common companion object access with platform one"
//)
//
//private val constLoweringPhase = makeJsModulePhase(
// ::ConstLowering,
// name = "ConstLowering",
// description = "Wrap Long and Char constants into constructor invocation"
//)
//
//private val callsLoweringPhase = makeJsModulePhase(
// ::CallsLowering,
// name = "CallsLowering",
// description = "Handle intrinsics"
//)
//
//private val testGenerationPhase = makeJsModulePhase(
// ::TestGenerator,
// name = "TestGenerationLowering",
// description = "Generate invocations to kotlin.test suite and test functions"
//)
//
private val staticMembersLoweringPhase = makeWasmModulePhase(
::StaticMembersLowering,
name = "StaticMembersLowering",
description = "Move static member declarations to top-level"
)
private val builtInsLoweringPhase = makeWasmModulePhase(
::BuiltInsLowering,
name = "BuiltInsLowering",
description = "Lower IR buildins"
)
private val objectDeclarationLoweringPhase = makeCustomWasmModulePhase(
{ context, module -> ObjectUsageLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectDeclarationLowering",
description = "Create lazy object instance generator functions"
)
private val objectUsageLoweringPhase = makeCustomWasmModulePhase(
{ context, module -> ObjectUsageLowering(context, context.objectToGetInstanceFunction).lower(module) },
name = "ObjectUsageLowering",
description = "Transform IrGetObjectValue into instance generator call"
)
val wasmPhases = namedIrModulePhase<WasmBackendContext>(
name = "IrModuleLowering",
description = "IR module lowering",
lower = validateIrBeforeLowering then
excludeDeclarationsFromCodegenPhase then
expectDeclarationsRemovingPhase then
provisionalFunctionExpressionPhase then
// TODO: Need some helpers from stdlib
// arrayConstructorPhase then
functionInliningPhase then
lateinitLoweringPhase then
tailrecLoweringPhase then
enumClassConstructorLoweringPhase then
sharedVariablesLoweringPhase then
localDelegatedPropertiesLoweringPhase then
localDeclarationsLoweringPhase then
localClassExtractionPhase then
innerClassesLoweringPhase then
innerClassConstructorCallsLoweringPhase then
propertiesLoweringPhase then
primaryConstructorLoweringPhase then
initializersLoweringPhase then
// Common prefix ends
builtInsLoweringPhase then
// TODO: Commonize enumEntryToGetInstanceFunction
// Commonize array literal creation
// Extract external enum lowering to JS part
//
// enumClassLoweringPhase then
// enumUsageLoweringPhase then
// TODO: Requires stdlib
// suspendFunctionsLoweringPhase then
returnableBlockLoweringPhase then
// TODO: Callable reference lowering is too JS specific.
// Should we reuse JVM or Native lowering?
// callableReferenceLoweringPhase then
defaultArgumentStubGeneratorPhase then
defaultParameterInjectorPhase then
defaultParameterCleanerPhase then
// TODO: Investigate
// jsDefaultCallbackGeneratorPhase then
removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then
// TODO: Varargs are too platform-specific. Reimplement.
// varargLoweringPhase then
// TODO: Investigate exception proposal
// multipleCatchesLoweringPhase then
bridgesConstructionPhase then
// TODO: Reimplement
// typeOperatorLoweringPhase then
// TODO: Reimplement
// secondaryConstructorLoweringPhase then
// secondaryFactoryInjectorLoweringPhase then
// TODO: Reimplement
// classReferenceLoweringPhase then
inlineClassLoweringPhase then
// TODO: Commonize box/unbox intrinsics
// autoboxingTransformerPhase then
blockDecomposerLoweringPhase then
// TODO: Reimplement
// constLoweringPhase then
objectDeclarationLoweringPhase then
objectUsageLoweringPhase then
staticMembersLoweringPhase then
validateIrAfterLowering
)
@@ -0,0 +1,121 @@
/*
* Copyright 2010-2019 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.backend.wasm
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.SimpleType
class WasmSymbols(
context: WasmBackendContext,
private val symbolTable: ReferenceSymbolTable
) : Symbols<WasmBackendContext>(context, symbolTable) {
override val ThrowNullPointerException
get() = TODO()
override val ThrowNoWhenBranchMatchedException
get() = TODO()
override val ThrowTypeCastException
get() = TODO()
override val ThrowUninitializedPropertyAccessException
get() = TODO()
override val defaultConstructorMarker
get() = TODO()
override val stringBuilder
get() = TODO()
override val copyRangeTo: Map<ClassDescriptor, IrSimpleFunctionSymbol>
get() = TODO()
override val coroutineImpl
get() = TODO()
override val coroutineSuspendedGetter
get() = TODO()
override val getContinuation
get() = TODO()
override val coroutineContextGetter by lazy {
context.excludedDeclarations.addFunction {
name = Name.identifier("coroutineContextGetter\$Stub")
}.symbol
}
override val suspendCoroutineUninterceptedOrReturn
get() = TODO()
override val coroutineGetContext
get() = TODO()
override val returnIfSuspended
get() = TODO()
private val wasmInternalPackage = context.module.getPackage(FqName("kotlin.wasm.internal"))
val equalityFunctions = mapOf(
context.irBuiltIns.booleanType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.byteType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.shortType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.charType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.intType to getInternalFunction("wasm_i32_eq"),
context.irBuiltIns.longType to getInternalFunction("wasm_i64_eq"),
context.irBuiltIns.floatType to getInternalFunction("wasm_f32_eq"),
context.irBuiltIns.doubleType to getInternalFunction("wasm_f64_eq")
)
private fun wasmString(simpleType: SimpleType): String = with(context.irBuiltIns) {
when (simpleType) {
bool, byte, short, char, int -> "i32"
float -> "f32"
double -> "f64"
long -> "i64"
else -> error("Unkonow primitive type")
}
}
val irBuiltInsToWasmIntrinsics = context.irBuiltIns.run {
mapOf(
lessFunByOperandType to "lt",
lessOrEqualFunByOperandType to "le",
greaterOrEqualFunByOperandType to "ge",
greaterFunByOperandType to "gt"
).map { (typeToBuiltIn, wasmOp) ->
typeToBuiltIn.map { (type, builtin) ->
val wasmType = wasmString(type)
val markSign = if (wasmType == "i32" || wasmType == "i64") "_s" else ""
builtin to getInternalFunction("wasm_${wasmType}_$wasmOp$markSign")
}
}.flatten().toMap()
}
val stringGetLiteral = getInternalFunction("stringLiteral")
private fun findClass(memberScope: MemberScope, name: Name): ClassDescriptor =
memberScope.getContributedClassifier(name, NoLookupLocation.FROM_BACKEND) as ClassDescriptor
private fun findFunctions(memberScope: MemberScope, name: Name): List<SimpleFunctionDescriptor> =
memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).toList()
private fun findProperty(memberScope: MemberScope, name: Name): List<PropertyDescriptor> =
memberScope.getContributedVariables(name, NoLookupLocation.FROM_BACKEND).toList()
internal fun getClass(fqName: FqName): ClassDescriptor =
findClass(context.module.getPackage(fqName.parent()).memberScope, fqName.shortName())
internal fun getProperty(fqName: FqName): PropertyDescriptor =
findProperty(context.module.getPackage(fqName.parent()).memberScope, fqName.shortName()).single()
internal fun getInternalFunction(name: String): IrSimpleFunctionSymbol {
val tmp = findFunctions(wasmInternalPackage.memberScope, Name.identifier(name)).single()
return symbolTable.referenceSimpleFunction(tmp)
}
private fun getIrClass(fqName: FqName): IrClassSymbol = symbolTable.referenceClass(getClass(fqName))
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2019 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.backend.wasm.ast
// TODO: Abstract out S-expression part of dumping?
fun WasmInstruction.toWat(ident: String = ""): String =
"$ident($mnemonic${immediate.toWat()}${operands.joinToString("") { " " + it.toWat("") }})"
fun WasmImmediate.toWat(): String = when (this) {
WasmImmediate.None -> ""
is WasmImmediate.DeclarationReference -> " $$name"
// SpiderMonkey jsshell won't parse Uppercase letters in literals
is WasmImmediate.LiteralValue<*> -> " $value".toLowerCase()
}
fun wasmModuleToWat(module: WasmModule): String =
"(module\n${module.fields.joinToString("") { wasmModuleFieldToWat(it) + "\n" }})"
fun wasmFunctionToWat(function: WasmFunction): String {
val watId = "$${function.name}"
val watImport = function.importPair?.let { importPair ->
" (import ${toWasString(importPair.module)} ${toWasString(importPair.name)})"
} ?: ""
val watLocals = function.locals.joinToString("") { " " + wasmLocalToWat(it) + "\n" }
val watParameters = function.parameters.joinToString("") { " " + wasmParameterToWat(it, function.importPair == null) }
val watResult = function.returnType?.let { type -> " (result ${type.mnemonic})" } ?: ""
val watBody = function.instructions.joinToString("") { it.toWat(" ") + "\n" }
return " (func $watId$watImport$watParameters$watResult\n$watLocals$watBody )"
}
fun wasmParameterToWat(parameter: WasmParameter, includeName: Boolean): String {
val name = if (includeName) " $${parameter.name}" else ""
return "(param$name ${parameter.type.mnemonic})"
}
fun wasmLocalToWat(local: WasmLocal): String =
local.run { "(local $$name ${type.mnemonic})" }
fun wasmGlobalToWat(global: WasmGlobal): String {
val watMut = if (global.isMutable) "mut " else ""
val watInit = global.init?.toWat("") ?: ""
return global.run { " (global $$name ($watMut${type.mnemonic}) $watInit)" }
}
fun wasmExportToWat(export: WasmExport): String =
export.run { " (export \"$exportedName\" (${kind.keyword} $$wasmName))" }
fun wasmModuleFieldToWat(moduleField: WasmModuleField): String =
when (moduleField) {
is WasmFunction -> wasmFunctionToWat(moduleField)
is WasmGlobal -> wasmGlobalToWat(moduleField)
is WasmExport -> wasmExportToWat(moduleField)
is WasmModuleFieldList -> moduleField.fields.joinToString("") { wasmModuleFieldToWat(it) + "\n" }
}
fun toWasString(s: String): String {
// TODO: escape characters according to
// https://webassembly.github.io/spec/core/text/values.html#strings
return "\"" + s + "\""
}
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2019 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.backend.wasm.ast
import org.jetbrains.kotlin.backend.wasm.utils.WasmImportPair
class WasmModule(
val fields: List<WasmModuleField>
)
sealed class WasmModuleField
class WasmModuleFieldList(
val fields: List<WasmModuleField>
) : WasmModuleField()
class WasmFunction(
val name: String,
val parameters: List<WasmParameter>,
val returnType: WasmValueType?,
val locals: List<WasmLocal>,
val instructions: List<WasmInstruction>,
val importPair: WasmImportPair?
) : WasmModuleField()
class WasmParameter(
val name: String,
val type: WasmValueType
)
class WasmLocal(
val name: String,
val type: WasmValueType
)
class WasmGlobal(
val name: String,
val type: WasmValueType,
val isMutable: Boolean,
val init: WasmInstruction?
) : WasmModuleField()
class WasmExport(
val wasmName: String,
val exportedName: String,
val kind: Kind
) : WasmModuleField() {
enum class Kind(val keyword: String) {
FUNCTION("func"),
GLOBAL("global")
}
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2019 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.backend.wasm.ast
sealed class WasmImmediate {
object None : WasmImmediate()
class DeclarationReference(val name: String) : WasmImmediate()
class LiteralValue<T : Number>(val value: T) : WasmImmediate()
}
sealed class WasmInstruction(
val mnemonic: String,
val immediate: WasmImmediate = WasmImmediate.None,
val operands: List<WasmInstruction> = emptyList()
)
class WasmSimpleInstruction(mnemonic: String, operands: List<WasmInstruction>) :
WasmInstruction(mnemonic, operands = operands)
class WasmNop : WasmInstruction("nop")
class WasmReturn(values: List<WasmInstruction>) :
WasmInstruction("return", operands = values)
class WasmDrop(instructions: List<WasmInstruction>) :
WasmInstruction("drop", operands = instructions)
class WasmCall(name: String, operands: List<WasmInstruction>) :
WasmInstruction("call", WasmImmediate.DeclarationReference(name), operands)
class WasmGetLocal(name: String) :
WasmInstruction("get_local", WasmImmediate.DeclarationReference(name))
class WasmGetGlobal(name: String) :
WasmInstruction("get_global", WasmImmediate.DeclarationReference(name))
class WasmSetGlobal(name: String, value: WasmInstruction) :
WasmInstruction("set_global", WasmImmediate.DeclarationReference(name), listOf(value))
class WasmSetLocal(name: String, value: WasmInstruction) :
WasmInstruction("set_local", WasmImmediate.DeclarationReference(name), listOf(value))
class WasmIf(condition: WasmInstruction, thenInstructions: WasmThen?, elseInstruction: WasmElse?) :
WasmInstruction("if", operands = listOfNotNull(condition, thenInstructions, elseInstruction))
class WasmThen(inst: WasmInstruction) :
WasmInstruction("then", operands = listOf(inst))
class WasmElse(inst: WasmInstruction) :
WasmInstruction("else", operands = listOf(inst))
class WasmBlock(instructions: List<WasmInstruction>) :
WasmInstruction("block", operands = instructions)
sealed class WasmConst<KotlinType : Number, WasmType : WasmValueType>(value: KotlinType, type: WasmType) :
WasmInstruction(type.mnemonic + ".const", WasmImmediate.LiteralValue<KotlinType>(value))
class WasmI32Const(value: Int) : WasmConst<Int, WasmI32>(value, WasmI32)
class WasmI64Const(value: Long) : WasmConst<Long, WasmI64>(value, WasmI64)
class WasmF32Const(value: Float) : WasmConst<Float, WasmF32>(value, WasmF32)
class WasmF64Const(value: Double) : WasmConst<Double, WasmF64>(value, WasmF64)
@@ -0,0 +1,15 @@
/*
* Copyright 2010-2019 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.backend.wasm.ast
sealed class WasmValueType(val mnemonic: String)
object WasmI32 : WasmValueType("i32")
object WasmI64 : WasmValueType("i64")
object WasmF32 : WasmValueType("f32")
object WasmF64 : WasmValueType("f64")
object WasmAnyRef : WasmValueType("anyref")
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.utils.TODO
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface BaseTransformer<out R, in D> : IrElementVisitor<R, D> {
override fun visitElement(element: IrElement, data: D): R {
TODO(element)
}
}
@@ -0,0 +1,123 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.wasm.ast.*
import org.jetbrains.kotlin.backend.wasm.utils.getWasmImportAnnotation
import org.jetbrains.kotlin.backend.wasm.utils.getWasmInstructionAnnotation
import org.jetbrains.kotlin.backend.wasm.utils.hasExcludedFromCodegenAnnotation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.isAnnotationClass
import org.jetbrains.kotlin.ir.util.isFakeOverride
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
class DeclarationTransformer : BaseTransformer<WasmModuleField?, WasmCodegenContext> {
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: WasmCodegenContext): WasmModuleField? {
if (declaration.hasExcludedFromCodegenAnnotation())
return null
if (declaration.getWasmInstructionAnnotation() != null)
return null
if (declaration.isFakeOverride)
return null
// Virtual functions are not supported yet
if (declaration.origin == IrDeclarationOrigin.BRIDGE)
return null
// Collect local variables
val localNames = wasmNameTable<IrValueDeclaration>()
val wasmName = data.getGlobalName(declaration)
val irParameters = declaration.run {
listOfNotNull(dispatchReceiverParameter, extensionReceiverParameter) + valueParameters
}
val wasmParameters = irParameters.map { parameter ->
val name = localNames.declareFreshName(parameter, parameter.name.asString())
WasmParameter(name, data.transformType(parameter.type))
}
val wasmReturnType = when {
declaration.returnType.isUnit() -> null
else -> data.transformType(declaration.returnType)
}
val importedName = declaration.getWasmImportAnnotation()
if (importedName != null) {
data.imports.add(
WasmFunction(
name = wasmName,
parameters = wasmParameters,
returnType = wasmReturnType,
locals = emptyList(),
instructions = emptyList(),
importPair = importedName
)
)
return null
}
val body = declaration.body
?: error("Function ${declaration.fqNameWhenAvailable} without a body")
data.localNames = localNames.names
val locals = mutableListOf<WasmLocal>()
body.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitVariable(declaration: IrVariable) {
val name = localNames.declareFreshName(declaration, declaration.name.asString())
locals += WasmLocal(name, data.transformType(declaration.type))
super.visitVariable(declaration)
}
})
return WasmFunction(
name = wasmName,
parameters = wasmParameters,
returnType = wasmReturnType,
locals = locals,
instructions = bodyToWasmInstructionList(body, data),
importPair = null
)
}
override fun visitConstructor(declaration: IrConstructor, data: WasmCodegenContext): WasmModuleField? {
TODO()
}
override fun visitClass(declaration: IrClass, data: WasmCodegenContext): WasmModuleField? {
if (declaration.isAnnotationClass) return null
if (declaration.hasExcludedFromCodegenAnnotation()) return null
val wasmMembers = declaration.declarations.mapNotNull { member ->
when (member) {
is IrSimpleFunction -> this.visitSimpleFunction(member, data)
else -> null
}
}
return WasmModuleFieldList(wasmMembers)
}
override fun visitField(declaration: IrField, data: WasmCodegenContext): WasmModuleField {
return WasmGlobal(
name = data.getGlobalName(declaration),
type = data.transformType(declaration.type),
isMutable = true,
// TODO: move non-constexpr initializers out
init = declaration.initializer?.let {
expressionToWasmInstruction(it.expression, data)
}
)
}
}
@@ -0,0 +1,206 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
import org.jetbrains.kotlin.backend.wasm.ast.*
import org.jetbrains.kotlin.backend.wasm.utils.getWasmInstructionAnnotation
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.isUnit
import org.jetbrains.kotlin.ir.util.dump
class ExpressionTransformer : BaseTransformer<WasmInstruction, WasmCodegenContext> {
override fun visitVararg(expression: IrVararg, data: WasmCodegenContext): WasmInstruction {
TODO("Support arrays")
}
override fun visitExpressionBody(body: IrExpressionBody, data: WasmCodegenContext): WasmInstruction =
body.expression.accept(this, data)
override fun visitFunctionReference(expression: IrFunctionReference, data: WasmCodegenContext): WasmInstruction {
TODO("?")
}
override fun <T> visitConst(expression: IrConst<T>, data: WasmCodegenContext): WasmInstruction {
return when (val kind = expression.kind) {
is IrConstKind.Null -> TODO()
is IrConstKind.String -> {
val value = kind.valueOf(expression)
val index = data.stringLiterals.size
data.stringLiterals.add(value)
val funName = data.getGlobalName(data.backendContext.wasmSymbols.stringGetLiteral.owner)
val operand = WasmI32Const(index)
WasmCall(funName, listOf(operand))
}
is IrConstKind.Boolean -> WasmI32Const(if (kind.valueOf(expression)) 1 else 0)
is IrConstKind.Byte -> WasmI32Const(kind.valueOf(expression).toInt())
is IrConstKind.Short -> WasmI32Const(kind.valueOf(expression).toInt())
is IrConstKind.Int -> WasmI32Const(kind.valueOf(expression))
is IrConstKind.Long -> WasmI64Const(kind.valueOf(expression))
is IrConstKind.Char -> WasmI32Const(kind.valueOf(expression).toInt())
is IrConstKind.Float -> WasmF32Const(kind.valueOf(expression))
is IrConstKind.Double -> WasmF64Const(kind.valueOf(expression))
}
}
override fun visitStringConcatenation(expression: IrStringConcatenation, data: WasmCodegenContext): WasmInstruction {
TODO("Implement kotlin.String")
}
override fun visitGetField(expression: IrGetField, data: WasmCodegenContext): WasmInstruction {
val fieldName = data.getGlobalName(expression.symbol.owner)
if (expression.receiver != null)
TODO("Support member fields")
return WasmGetGlobal(fieldName)
}
override fun visitGetValue(expression: IrGetValue, data: WasmCodegenContext): WasmInstruction =
WasmGetLocal(data.getLocalName(expression.symbol.owner))
override fun visitGetObjectValue(expression: IrGetObjectValue, data: WasmCodegenContext): WasmInstruction {
TODO("IrGetObjectValue")
}
override fun visitSetField(expression: IrSetField, data: WasmCodegenContext): WasmInstruction {
val fieldName = data.getGlobalName(expression.symbol.owner)
if (expression.receiver != null)
TODO("Support member fields")
val value = expression.value.accept(this, data)
return WasmSetGlobal(fieldName, value)
}
override fun visitSetVariable(expression: IrSetVariable, data: WasmCodegenContext): WasmInstruction {
val fieldName = data.getLocalName(expression.symbol.owner)
val value = expression.value.accept(this, data)
return WasmSetLocal(fieldName, value)
}
override fun visitConstructorCall(expression: IrConstructorCall, data: WasmCodegenContext): WasmInstruction {
TODO("IrConstructorCall")
}
override fun visitCall(expression: IrCall, data: WasmCodegenContext): WasmInstruction {
val function = expression.symbol.owner.realOverrideTarget
require(function is IrSimpleFunction) { "Only IrSimpleFunction could be called via IrCall" }
val valueArgs = (0 until expression.valueArgumentsCount).mapNotNull { expression.getValueArgument(it) }
val irArguments = listOfNotNull(expression.dispatchReceiver, expression.extensionReceiver) + valueArgs
val wasmArguments = irArguments.map { expressionToWasmInstruction(it, data) }
val wasmInstruction = function.getWasmInstructionAnnotation()
if (wasmInstruction != null) {
if (wasmInstruction == "nop") {
return wasmArguments.single()
}
return WasmSimpleInstruction(wasmInstruction, wasmArguments)
}
val name = data.getGlobalName(function)
return WasmCall(name, wasmArguments)
}
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: WasmCodegenContext): WasmInstruction {
val wasmArgument = expressionToWasmInstruction(expression.argument, data)
when (expression.operator) {
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> return wasmArgument
}
TODO("IrTypeOperatorCall:\n ${expression.dump()}")
}
override fun visitGetEnumValue(expression: IrGetEnumValue, data: WasmCodegenContext): WasmInstruction {
TODO("IrGetEnumValue")
}
override fun visitBlockBody(body: IrBlockBody, data: WasmCodegenContext): WasmInstruction {
TODO()
}
override fun visitContainerExpression(expression: IrContainerExpression, data: WasmCodegenContext): WasmInstruction {
val expressions = expression.statements.map { it.accept(this, data) }
if (!expression.type.isUnit())
return WasmBlock(expressions + listOf(WasmDrop(emptyList())))
return WasmBlock(expressions)
}
override fun visitExpression(expression: IrExpression, data: WasmCodegenContext): WasmInstruction {
return expressionToWasmInstruction(expression, data)
}
override fun visitBreak(jump: IrBreak, data: WasmCodegenContext): WasmInstruction {
TODO()
}
override fun visitContinue(jump: IrContinue, data: WasmCodegenContext): WasmInstruction {
TODO()
}
override fun visitReturn(expression: IrReturn, data: WasmCodegenContext): WasmInstruction {
if (expression.value.type.isUnit()) return WasmReturn(emptyList())
return WasmReturn(listOf(expressionToWasmInstruction(expression.value, data)))
}
override fun visitThrow(expression: IrThrow, data: WasmCodegenContext): WasmInstruction {
TODO("IrThrow")
}
override fun visitVariable(declaration: IrVariable, data: WasmCodegenContext): WasmInstruction {
val init = declaration.initializer ?: return WasmNop()
val varName = data.getLocalName(declaration)
return WasmSetLocal(varName, expressionToWasmInstruction(init, data))
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: WasmCodegenContext): WasmInstruction {
TODO("IrDelegatingConstructorCall")
}
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: WasmCodegenContext): WasmInstruction {
TODO("IrInstanceInitializerCall")
}
override fun visitTry(aTry: IrTry, data: WasmCodegenContext): WasmInstruction {
TODO("IrTry")
}
override fun visitWhen(expression: IrWhen, data: WasmCodegenContext): WasmInstruction {
return expression.branches.foldRight(null) { br: IrBranch, inst: WasmInstruction? ->
val body = expressionToWasmInstruction(br.result, data)
if (isElseBranch(br)) body
else {
val condition = expressionToWasmInstruction(br.condition, data)
WasmIf(condition, WasmThen(body), inst?.let { WasmElse(inst) })
}
}!!
}
override fun visitWhileLoop(loop: IrWhileLoop, data: WasmCodegenContext): WasmInstruction {
TODO("IrWhileLoop")
}
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: WasmCodegenContext): WasmInstruction {
TODO("IrDoWhileLoop")
}
override fun visitSyntheticBody(body: IrSyntheticBody, data: WasmCodegenContext): WasmInstruction {
TODO("IrSyntheticBody")
}
override fun visitDynamicMemberExpression(expression: IrDynamicMemberExpression, data: WasmCodegenContext): WasmInstruction =
error("Dynamic operators are not supported for WASM target")
override fun visitDynamicOperatorExpression(expression: IrDynamicOperatorExpression, data: WasmCodegenContext): WasmInstruction =
error("Dynamic operators are not supported for WASM target")
}
fun expressionToWasmInstruction(expression: IrExpression, context: WasmCodegenContext): WasmInstruction {
return expression.accept(ExpressionTransformer(), context)
}
@@ -0,0 +1,82 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.WasmCompilerResult
import org.jetbrains.kotlin.backend.wasm.ast.WasmExport
import org.jetbrains.kotlin.backend.wasm.ast.WasmModule
import org.jetbrains.kotlin.backend.wasm.ast.wasmModuleToWat
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment
import org.jetbrains.kotlin.ir.backend.js.utils.sanitizeName
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.js.backend.ast.JsArrayLiteral
import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsNameRef
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral
import org.jetbrains.kotlin.utils.addIfNotNull
class IrModuleToWasm(private val backendContext: WasmBackendContext) {
fun generateModule(module: IrModuleFragment): WasmCompilerResult {
val nameTable = generateWatTopLevelNames(module.files)
val context = WasmCodegenContext(nameTable, backendContext)
val irDeclarations = module.files.flatMap { it.declarations }
val wasmDeclarations = irDeclarations.mapNotNull { it.accept(DeclarationTransformer(), context) }
val exports = generateExports(module, context)
val wasmModule = WasmModule(context.imports + wasmDeclarations + exports)
val wat = wasmModuleToWat(wasmModule)
return WasmCompilerResult(wat, generateStringLiteralsSupport(context.stringLiterals))
}
private fun generateStringLiteralsSupport(literals: List<String>): String {
return JsBlock(
jsAssignment(
JsNameRef("stringLiterals", "runtime"),
JsArrayLiteral(literals.map { JsStringLiteral(it) })
).makeStmt()
).toString()
}
private fun generateExports(module: IrModuleFragment, context: WasmCodegenContext): List<WasmExport> {
val exports = mutableListOf<WasmExport>()
for (file in module.files) {
for (declaration in file.declarations) {
exports.addIfNotNull(generateExport(declaration, context))
}
}
return exports
}
private fun generateExport(declaration: IrDeclaration, context: WasmCodegenContext): WasmExport? {
if (declaration !is IrDeclarationWithVisibility ||
declaration !is IrDeclarationWithName ||
declaration !is IrSimpleFunction ||
declaration.visibility != Visibilities.PUBLIC
) {
return null
}
if (!declaration.isExported(context))
return null
val internalName = context.getGlobalName(declaration)
val exportedName = sanitizeName(declaration.name.identifier)
return WasmExport(
wasmName = internalName,
exportedName = exportedName,
kind = WasmExport.Kind.FUNCTION
)
}
}
fun IrFunction.isExported(context: WasmCodegenContext): Boolean =
fqNameWhenAvailable in context.backendContext.additionalExportedDeclarations
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
fun <T> wasmNameTable() = NameTable<T>(sanitizer = ::sanitizeWatIdentifier)
fun generateWatTopLevelNames(packages: List<IrPackageFragment>): Map<IrDeclarationWithName, String> {
val names = wasmNameTable<IrDeclarationWithName>()
fun nameTopLevelDecl(declaration: IrDeclarationWithName) {
val suggestedName = declaration.fqNameWhenAvailable?.toString()
?: "fqname???" + declaration.name.asString()
names.declareFreshName(declaration, suggestedName)
}
for (p in packages) {
p.acceptChildrenVoid(object : IrElementVisitorVoid {
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction) {
nameTopLevelDecl(declaration)
super.visitSimpleFunction(declaration)
}
override fun visitField(declaration: IrField) {
if (declaration.isTopLevel)
nameTopLevelDecl(declaration)
super.visitField(declaration)
}
})
}
return names.names
}
fun sanitizeWatIdentifier(ident: String): String {
if (ident.isEmpty())
return "_"
if (ident.all(::isValidWatIdentifier))
return ident
return ident.map { if (isValidWatIdentifier(it)) it else "_" }.joinToString("")
}
// https://webassembly.github.io/spec/core/text/values.html#text-id
fun isValidWatIdentifier(c: Char): Boolean =
c in '0'..'9' || c in 'A'..'Z' || c in 'a'..'z'
// TODO: SpiderMonkey js shell can't parse some of the
// permitted identifiers: '?', '<'
// || c in "!#$%&*+-./:<=>?@\\^_`|~"
|| c in "$.@_"
@@ -0,0 +1,35 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.wasm.ast.WasmInstruction
import org.jetbrains.kotlin.backend.wasm.ast.WasmNop
import org.jetbrains.kotlin.backend.wasm.ast.WasmSetLocal
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.*
class StatementTransformer : BaseTransformer<WasmInstruction, WasmCodegenContext> {
override fun visitVariable(declaration: IrVariable, data: WasmCodegenContext): WasmInstruction {
val init = declaration.initializer ?: return WasmNop()
val varName = data.getLocalName(declaration)
return WasmSetLocal(varName, expressionToWasmInstruction(init, data))
}
override fun visitExpression(expression: IrExpression, data: WasmCodegenContext): WasmInstruction {
return expressionToWasmInstruction(expression, data)
}
}
fun statementToWasmInstruction(statement: IrStatement, context: WasmCodegenContext): WasmInstruction {
return statement.accept(StatementTransformer(), context)
}
fun bodyToWasmInstructionList(body: IrBody, context: WasmCodegenContext): List<WasmInstruction> {
if (body is IrBlockBody) {
return body.statements.map { statementToWasmInstruction(it, context) }
} else TODO()
}
@@ -0,0 +1,27 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.wasm.ast.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.render
fun WasmCodegenContext.transformType(irType: IrType): WasmValueType =
when {
irType.isBoolean() -> WasmI32
irType.isByte() -> WasmI32
irType.isShort() -> WasmI32
irType.isInt() -> WasmI32
irType.isLong() -> WasmI64
irType.isChar() -> WasmI32
irType.isFloat() -> WasmF32
irType.isDouble() -> WasmF64
irType.isString() -> WasmAnyRef
irType.isAny() || irType.isNullableAny() -> WasmAnyRef
else ->
TODO("Unsupported type: ${irType.render()}")
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 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.backend.wasm.codegen
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.ast.WasmModuleField
import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
class WasmCodegenContext(
private val topLevelNames: Map<IrDeclarationWithName, String>,
val backendContext: WasmBackendContext
) {
val imports = mutableListOf<WasmModuleField>()
var localNames: Map<IrValueDeclaration, String> = emptyMap()
val stringLiterals = mutableListOf<String>()
fun getGlobalName(declaration: IrDeclarationWithName): String =
topLevelNames[declaration]
?: error("Can't find name for ${declaration.fqNameWhenAvailable}")
fun getLocalName(declaration: IrValueDeclaration): String =
localNames[declaration]
?: error("Can't find local name for ${declaration.fqNameWhenAvailable}")
}
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2019 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.backend.wasm
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
import org.jetbrains.kotlin.backend.wasm.codegen.IrModuleToWasm
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.loadIr
import org.jetbrains.kotlin.ir.backend.js.sortDependencies
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.library.KotlinLibrary
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
data class WasmCompilerResult(val wat: String, val js: String)
fun compileWasm(
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
phaseConfig: PhaseConfig,
allDependencies: List<KotlinLibrary>,
friendDependencies: List<KotlinLibrary>,
exportedDeclarations: Set<FqName> = emptySet()
): WasmCompilerResult {
val (moduleFragment, dependencyModules, irBuiltIns, symbolTable, deserializer) =
loadIr(project, files, configuration, allDependencies, friendDependencies)
val moduleDescriptor = moduleFragment.descriptor
val context = WasmBackendContext(moduleDescriptor, irBuiltIns, symbolTable, moduleFragment, exportedDeclarations, configuration)
// Load declarations referenced during `context` initialization
dependencyModules.forEach {
ExternalDependenciesGenerator(
it.descriptor,
symbolTable,
irBuiltIns,
deserializer = deserializer
).generateUnboundSymbolsAsDependencies()
}
// Since modules should be initialized in the correct topological order we sort them
val irFiles = sortDependencies(dependencyModules).flatMap { it.files } + moduleFragment.files
moduleFragment.files.clear()
moduleFragment.files += irFiles
// Create stubs
ExternalDependenciesGenerator(
moduleDescriptor = moduleDescriptor,
symbolTable = symbolTable,
irBuiltIns = irBuiltIns
).generateUnboundSymbolsAsDependencies()
moduleFragment.patchDeclarationParents()
wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment)
return IrModuleToWasm(context).generateModule(moduleFragment)
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2019 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.backend.wasm.lower
import org.jetbrains.kotlin.ir.backend.js.lower.AbstractBlockDecomposerLowering
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.ir.expressions.IrExpression
class WasmBlockDecomposerLowering(val context: WasmBackendContext) : AbstractBlockDecomposerLowering(context) {
override fun unreachableExpression(): IrExpression = TODO()
}
@@ -0,0 +1,48 @@
/*
* Copyright 2010-2019 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.backend.wasm.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
private val irBuiltins = context.irBuiltIns
private val symbols = context.wasmSymbols
fun transformCall(call: IrCall): IrExpression {
when (val symbol = call.symbol) {
irBuiltins.eqeqSymbol, irBuiltins.eqeqeqSymbol, in irBuiltins.ieee754equalsFunByOperandType.values -> {
val type = call.getValueArgument(0)!!.type
val newSymbol = symbols.equalityFunctions[type]
?: error("Unsupported equality operator with type: ${type.render()}")
return irCall(call, newSymbol)
}
in symbols.irBuiltInsToWasmIntrinsics.keys -> {
val newSymbol = symbols.irBuiltInsToWasmIntrinsics[symbol]!!
return irCall(call, newSymbol)
}
}
return call
}
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
val newExpression = transformCall(expression)
newExpression.transformChildrenVoid(this)
return newExpression
}
})
}
}
@@ -0,0 +1,124 @@
/*
* Copyright 2010-2019 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.backend.wasm.lower
import org.jetbrains.kotlin.backend.common.ir.addChild
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.utils.hasExcludedFromCodegenAnnotation
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.name.FqName
private val BODILESS_BUILTIN_CLASSES = listOf(
"kotlin.Nothing",
"kotlin.Array",
"kotlin.Any",
"kotlin.ByteArray",
"kotlin.CharArray",
"kotlin.ShortArray",
"kotlin.IntArray",
"kotlin.LongArray",
"kotlin.FloatArray",
"kotlin.DoubleArray",
"kotlin.BooleanArray",
"kotlin.Boolean",
"kotlin.Function",
"kotlin.Throwable",
"kotlin.Suppress",
"kotlin.SinceKotlin",
"kotlin.Deprecated",
"kotlin.ReplaceWith",
"kotlin.DeprecationLevel",
"kotlin.UnsafeVariance",
"kotlin.reflect.KType",
"kotlin.reflect.KTypeProjection",
"kotlin.reflect.Companion",
"kotlin.reflect.KTypeParameter",
"kotlin.reflect.KDeclarationContainer",
"kotlin.reflect.KProperty",
"kotlin.reflect.KProperty0",
"kotlin.reflect.KProperty1",
"kotlin.reflect.KProperty2",
"kotlin.reflect.KMutableProperty0",
"kotlin.reflect.KMutableProperty",
"kotlin.reflect.KMutableProperty1",
"kotlin.reflect.KMutableProperty2",
"kotlin.reflect.Accessor",
"kotlin.reflect.Getter",
"kotlin.reflect.KFunction",
"kotlin.reflect.KVariance",
"kotlin.reflect.KVisibility",
"kotlin.reflect.KClass",
"kotlin.reflect.KCallable",
"kotlin.reflect.KClassifier",
"kotlin.reflect.KParameter",
"kotlin.reflect.Kind",
"kotlin.reflect.KAnnotatedElement",
"kotlin.annotation.Target",
"kotlin.annotation.AnnotationTarget",
"kotlin.annotation.Retention",
"kotlin.annotation.AnnotationRetention",
"kotlin.annotation.MustBeDocumented",
"kotlin.Unit",
"kotlin.collections.BooleanIterator",
"kotlin.collections.CharIterator",
"kotlin.collections.ByteIterator",
"kotlin.collections.ShortIterator",
"kotlin.collections.IntIterator",
"kotlin.collections.FloatIterator",
"kotlin.collections.LongIterator",
"kotlin.collections.DoubleIterator",
"kotlin.internal.PlatformDependent",
"kotlin.CharSequence",
"kotlin.Annotation",
"kotlin.Comparable",
"kotlin.collections.Collection",
"kotlin.collections.Iterable",
"kotlin.collections.List",
"kotlin.collections.Map",
"kotlin.collections.Set",
"kotlin.collections.MutableCollection",
"kotlin.collections.MutableIterable",
"kotlin.collections.MutableSet",
"kotlin.collections.MutableList",
"kotlin.collections.MutableMap",
"kotlin.collections.Entry",
"kotlin.collections.MutableEntry",
"kotlin.Number",
"kotlin.Enum",
"kotlin.collections.Iterator",
"kotlin.collections.ListIterator",
"kotlin.collections.MutableIterator",
"kotlin.collections.MutableListIterator"
).map { FqName(it) }.toSet()
fun excludeDeclarationsFromCodegen(context: WasmBackendContext, module: IrModuleFragment) {
fun isExcluded(declaration: IrDeclaration): Boolean {
if (declaration is IrDeclarationWithName && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES)
return true
if (declaration.hasExcludedFromCodegenAnnotation())
return true
val parentFile = declaration.parent as? IrFile
if (parentFile?.hasExcludedFromCodegenAnnotation() == true)
return true
return false
}
for (file in module.files) {
val it = file.declarations.iterator()
while (it.hasNext()) {
val d = it.next() as? IrDeclarationWithName ?: continue
if (isExcluded(d)) {
it.remove()
context.excludedDeclarations.addChild(d)
}
}
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2019 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.backend.wasm.utils
import org.jetbrains.kotlin.ir.backend.js.utils.getSingleConstStringArgument
import org.jetbrains.kotlin.ir.declarations.IrAnnotationContainer
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.ir.util.getAnnotation
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
fun IrAnnotationContainer.hasExcludedFromCodegenAnnotation(): Boolean =
hasAnnotation(FqName("kotlin.wasm.internal.ExcludedFromCodegen"))
fun IrAnnotationContainer.getWasmInstructionAnnotation(): String? =
getAnnotation(FqName("kotlin.wasm.internal.WasmInstruction"))?.getSingleConstStringArgument()
class WasmImportPair(val module: String, val name: String)
@Suppress("UNCHECKED_CAST")
fun IrAnnotationContainer.getWasmImportAnnotation(): WasmImportPair? =
getAnnotation(FqName("kotlin.wasm.internal.WasmImport"))?.let {
WasmImportPair(
(it.getValueArgument(0) as IrConst<String>).value,
(it.getValueArgument(1) as IrConst<String>).value
)
}
@@ -189,9 +189,7 @@ val generateReducedRuntimeKLib by eagerTask<NoDebugJavaExec> {
)
}
val generateWasmRuntimeKLib by task<NoDebugJavaExec> {
dependsOn(reducedRuntimeSources)
val generateWasmRuntimeKLib by eagerTask<NoDebugJavaExec> {
buildKLib(sources = listOf("$rootDir/libraries/stdlib/wasm"),
dependencies = emptyList(),
outPath = "$buildDir/wasmRuntime/klib",
@@ -12,7 +12,8 @@ enum class TargetBackend(
JVM,
JVM_IR(JVM),
JS,
JS_IR(JS);
JS_IR(JS),
WASM;
val compatibleWith get() = compatibleWithTargetBackend ?: ANY
}
+71 -6
View File
@@ -1,15 +1,18 @@
import com.moowork.gradle.node.NodeExtension
import com.moowork.gradle.node.npm.NpmTask
import de.undercouch.gradle.tasks.download.Download
import org.gradle.internal.os.OperatingSystem
plugins {
kotlin("jvm")
id("jps-compatible")
id("com.moowork.node").version("1.2.0")
id("de.undercouch.download")
}
node {
download = true
version = "10.16.2"
}
val antLauncherJar by configurations.creating
@@ -27,6 +30,7 @@ dependencies {
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
testCompileOnly(intellijDep()) { includeJars("openapi", "idea", "idea_rt", "util") }
testCompile(project(":compiler:backend.js"))
testCompile(project(":compiler:backend.wasm"))
testCompile(projectTests(":compiler:ir.serialization.js"))
testCompile(project(":js:js.translator"))
testCompile(project(":js:js.serializer"))
@@ -65,7 +69,7 @@ sourceSets {
}
fun Test.setUpBoxTests(jsEnabled: Boolean, jsIrEnabled: Boolean) {
fun Test.setUpJsBoxTests(jsEnabled: Boolean, jsIrEnabled: Boolean) {
dependsOn(":dist")
if (jsEnabled) dependsOn(testJsRuntime)
if (jsIrEnabled) {
@@ -74,14 +78,20 @@ fun Test.setUpBoxTests(jsEnabled: Boolean, jsIrEnabled: Boolean) {
dependsOn(":compiler:ir.serialization.js:generateKotlinTestKLib")
}
exclude("org/jetbrains/kotlin/js/test/wasm/semantics/*")
if (jsEnabled && !jsIrEnabled) exclude("org/jetbrains/kotlin/js/test/ir/semantics/*")
if (!jsEnabled && jsIrEnabled) include("org/jetbrains/kotlin/js/test/ir/semantics/*")
jvmArgs("-da:jdk.nashorn.internal.runtime.RecompilableScriptFunctionData") // Disable assertion which fails due to a bug in nashorn (KT-23637)
workingDir = rootDir
if (findProperty("kotlin.compiler.js.ir.tests.skip")?.toString()?.toBoolean() == true) {
exclude("org/jetbrains/kotlin/js/test/ir/semantics/*")
}
setUpBoxTests()
}
fun Test.setUpBoxTests() {
workingDir = rootDir
doFirst {
systemProperty("kotlin.ant.classpath", antLauncherJar.asPath)
systemProperty("kotlin.ant.launcher.class", "org.apache.tools.ant.Main")
@@ -96,19 +106,19 @@ fun Test.setUpBoxTests(jsEnabled: Boolean, jsIrEnabled: Boolean) {
}
projectTest(parallel = true) {
setUpBoxTests(jsEnabled = true, jsIrEnabled = true)
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = true)
}
projectTest("jsTest", true) {
setUpBoxTests(jsEnabled = true, jsIrEnabled = false)
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = false)
}
projectTest("jsIrTest", true) {
setUpBoxTests(jsEnabled = false, jsIrEnabled = true)
setUpJsBoxTests(jsEnabled = false, jsIrEnabled = true)
}
projectTest("quickTest", true) {
setUpBoxTests(jsEnabled = true, jsIrEnabled = false)
setUpJsBoxTests(jsEnabled = true, jsIrEnabled = false)
systemProperty("kotlin.js.skipMinificationTest", "true")
}
@@ -136,3 +146,58 @@ val runMocha by task<NpmTask> {
val check by tasks
check.dependsOn(this)
}
enum class OsName { WINDOWS, MAC, LINUX, UNKNOWN }
enum class OsArch { X86_32, X86_64, UNKNOWN }
data class OsType(val name: OsName, val arch: OsArch)
val currentOsType = run {
val gradleOs = OperatingSystem.current()
val osName = when {
gradleOs.isMacOsX -> OsName.MAC
gradleOs.isWindows -> OsName.WINDOWS
gradleOs.isLinux -> OsName.LINUX
else -> OsName.UNKNOWN
}
val osArch = when (System.getProperty("sun.arch.data.model")) {
"32" -> OsArch.X86_32
"64" -> OsArch.X86_64
else -> OsArch.UNKNOWN
}
OsType(osName, osArch)
}
val jsShellDirectory = "https://archive.mozilla.org/pub/firefox/nightly/2019/08/2019-08-11-09-56-40-mozilla-central"
val jsShellSuffix = when (currentOsType) {
OsType(OsName.LINUX, OsArch.X86_32) -> "linux-i686"
OsType(OsName.LINUX, OsArch.X86_64) -> "linux-x86_64"
OsType(OsName.MAC, OsArch.X86_64) -> "mac"
OsType(OsName.WINDOWS, OsArch.X86_32) -> "win32"
OsType(OsName.WINDOWS, OsArch.X86_64) -> "win64"
else -> error("unsupported os type $currentOsType")
}
val jsShellLocation = "$jsShellDirectory/jsshell-$jsShellSuffix.zip"
val downloadedTools = File(buildDir, "tools")
val downloadJsShell by task<Download> {
src(jsShellLocation)
dest(File(downloadedTools, "jsshell-$jsShellSuffix.zip"))
}
val unzipJsShell by task<Copy> {
dependsOn(downloadJsShell)
from(zipTree(downloadJsShell.get().dest))
val unpackedDir = File(downloadedTools, "jsshell-$jsShellSuffix")
into(unpackedDir)
}
projectTest("wasmTest", true) {
dependsOn(unzipJsShell)
dependsOn(":compiler:ir.serialization.js:generateWasmRuntimeKLib")
include("org/jetbrains/kotlin/js/test/wasm/semantics/*")
val jsShellExecutablePath = File(unzipJsShell.get().destinationDir, "js").absolutePath
systemProperty("javascript.engine.path.SpiderMonkey", jsShellExecutablePath)
setUpBoxTests()
}
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.js.test.AbstractDceTest
import org.jetbrains.kotlin.js.test.AbstractJsLineNumberTest
import org.jetbrains.kotlin.js.test.ir.semantics.*
import org.jetbrains.kotlin.js.test.semantics.*
import org.jetbrains.kotlin.js.test.wasm.semantics.AbstractIrWasmBoxWasmTest
import org.jetbrains.kotlin.test.TargetBackend
fun main(args: Array<String>) {
@@ -42,6 +43,14 @@ fun main(args: Array<String>) {
testClass<AbstractJsLineNumberTest> {
model("lineNumbers/", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS)
}
testClass<AbstractIrWasmBoxWasmTest> {
model("wasmBox", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.WASM)
}
testClass<AbstractIrWasmBoxJsTest> {
model("wasmBox", pattern = "^([^_](.+))\\.kt$", targetBackend = TargetBackend.JS_IR)
}
}
testGroup("js/js.tests/test", "compiler/testData", testRunnerMethodName = "runTest0") {
@@ -0,0 +1,194 @@
/*
* Copyright 2010-2019 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.js.test
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.StandardFileSystems
import com.intellij.openapi.vfs.VirtualFileManager
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.common.phaser.toPhaseMap
import org.jetbrains.kotlin.backend.wasm.compileWasm
import org.jetbrains.kotlin.backend.wasm.wasmPhases
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.config.CommonConfigurationKeys
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.loadKlib
import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.js.test.engines.SpiderMonkeyEngine
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.KotlinTestWithEnvironment
import java.io.Closeable
import java.io.File
private val wasmRuntimeKlib =
loadKlib("compiler/ir/serialization.js/build/wasmRuntime/klib")
abstract class BasicWasmBoxTest(
private val pathToTestDir: String,
testGroupOutputDirPrefix: String,
pathToRootOutputDir: String = TEST_DATA_DIR_PATH
) : KotlinTestWithEnvironment() {
private val testGroupOutputDirForCompilation = File(pathToRootOutputDir + "out/" + testGroupOutputDirPrefix)
private val spiderMonkey by lazy { SpiderMonkeyEngine() }
fun doTest(filePath: String) {
val file = File(filePath)
val outputDir = getOutputDir(file)
val fileContent = KotlinTestUtils.doLoadFile(file)
TestFileFactoryImpl().use { testFactory ->
val inputFiles: MutableList<TestFile> = KotlinTestUtils.createTestFiles(file.name, fileContent, testFactory, true, "")
val testPackage = testFactory.testPackage
val outputFileBase = outputDir.absolutePath + "/" + getTestName(true)
val outputWatFile = outputFileBase + ".wat"
val outputJsFile = outputFileBase + ".js"
val kotlinFiles = inputFiles.filter { it.fileName.endsWith(".kt") }
val psiFiles = createPsiFiles(kotlinFiles.map { File(it.fileName).canonicalPath }.sorted())
val config = createConfig()
translateFiles(
psiFiles.map(TranslationUnit::SourceFile),
File(outputWatFile),
File(outputJsFile),
config,
testPackage,
TEST_FUNCTION
)
spiderMonkey.runFile(outputJsFile)
}
}
private fun getOutputDir(file: File, testGroupOutputDir: File = testGroupOutputDirForCompilation): File {
val stopFile = File(pathToTestDir)
return generateSequence(file.parentFile) { it.parentFile }
.takeWhile { it != stopFile }
.map { it.name }
.toList().asReversed()
.fold(testGroupOutputDir, ::File)
}
private fun translateFiles(
units: List<TranslationUnit>,
outputWatFile: File,
outputJsFile: File,
config: JsConfig,
testPackage: String?,
testFunction: String
) {
val filesToCompile = units.map { (it as TranslationUnit.SourceFile).file }
val debugMode = false
val phaseConfig = if (debugMode) {
val allPhasesSet = wasmPhases.toPhaseMap().values.toSet()
val dumpOutputDir = File(outputWatFile.parent, outputWatFile.nameWithoutExtension + "-irdump")
println("\n ------ Dumping phases to file://$dumpOutputDir")
PhaseConfig(
wasmPhases,
dumpToDirectory = dumpOutputDir.path,
toDumpStateAfter = allPhasesSet,
toValidateStateAfter = allPhasesSet,
dumpOnlyFqName = null
)
} else {
PhaseConfig(wasmPhases)
}
val compilerResult = compileWasm(
project = config.project,
files = filesToCompile,
configuration = config.configuration,
phaseConfig = phaseConfig,
allDependencies = listOf(wasmRuntimeKlib),
friendDependencies = emptyList(),
exportedDeclarations = setOf(FqName.fromSegments(listOfNotNull(testPackage, testFunction)))
)
outputWatFile.write(compilerResult.wat)
val runtime = File("libraries/stdlib/wasm/runtime/runtime.js").readText()
val testRunner = """
const wat = read(String.raw`${outputWatFile.absoluteFile}`);
const wasmBinary = wasmTextToBinary(wat);
const wasmModule = new WebAssembly.Module(wasmBinary);
const wasmInstance = new WebAssembly.Instance(wasmModule, { runtime });
const actualResult = wasmInstance.exports.$testFunction();
if (actualResult !== "OK")
throw `Wrong box result '${'$'}{actualResult}'; Expected "OK"`;
""".trimIndent()
outputJsFile.write(runtime + "\n" + compilerResult.js + "\n" + testRunner)
}
private fun createPsiFile(fileName: String): KtFile {
val psiManager = PsiManager.getInstance(project)
val fileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL)
val file = fileSystem.findFileByPath(fileName) ?: error("File not found: $fileName")
return psiManager.findFile(file) as KtFile
}
private fun createPsiFiles(fileNames: List<String>): List<KtFile> = fileNames.map(this::createPsiFile)
private fun createConfig(): JsConfig {
val configuration = environment.configuration.copy()
configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE)
return JsConfig(project, configuration, null, null)
}
private inner class TestFileFactoryImpl : KotlinTestUtils.TestFileFactoryNoModules<TestFile>(), Closeable {
override fun create(fileName: String, text: String, directives: MutableMap<String, String>): TestFile {
val ktFile = KtPsiFactory(project).createFile(text)
val boxFunction = ktFile.declarations.find { it is KtNamedFunction && it.name == TEST_FUNCTION }
if (boxFunction != null) {
testPackage = ktFile.packageFqName.asString()
if (testPackage?.isEmpty() == true) {
testPackage = null
}
}
val temporaryFile = File(tmpDir, "WASM_TEST/$fileName")
KotlinTestUtils.mkdirs(temporaryFile.parentFile)
temporaryFile.writeText(text, Charsets.UTF_8)
return TestFile(temporaryFile.absolutePath)
}
var testPackage: String? = null
val tmpDir = KotlinTestUtils.tmpDir("wasm-tests")
override fun close() {
FileUtil.delete(tmpDir)
}
}
private class TestFile(val fileName: String)
override fun createEnvironment() =
KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
companion object {
const val TEST_DATA_DIR_PATH = "js/js.translator/testData/"
const val TEST_MODULE = "WASM_TESTS"
private const val TEST_FUNCTION = "box"
}
}
private fun File.write(text: String) {
parentFile.mkdirs()
writeText(text)
}
@@ -0,0 +1,44 @@
/*
* Copyright 2010-2019 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.js.test.engines
import java.io.BufferedReader
import java.io.InputStreamReader
import kotlin.test.fail
class ExternalTool(val path: String) {
fun run(vararg arguments: String) {
val command = arrayOf(path, *arguments)
val process = ProcessBuilder(*command)
.redirectErrorStream(true)
.start()
val commandString = command.joinToString(" ") { escapeShellArgument(it) }
println(commandString)
// Print process output
val input = BufferedReader(InputStreamReader(process.inputStream))
while (true) println(input.readLine() ?: break)
val exitValue = process.waitFor()
if (exitValue != 0) {
fail("Command \"$commandString\" terminated with exit code $exitValue")
}
}
}
private fun escapeShellArgument(arg: String): String =
"'${arg.replace("'", "'\\''")}'"
class SpiderMonkeyEngine(
jsShellPath: String = System.getProperty("javascript.engine.path.SpiderMonkey")
) {
private val jsShell = ExternalTool(jsShellPath)
fun runFile(file: String) {
jsShell.run(file)
}
}
@@ -0,0 +1,548 @@
/*
* Copyright 2010-2019 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.js.test.ir.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("js/js.translator/testData/wasmBox")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IrWasmBoxJsTestGenerated extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInWasmBox() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("basicTypes.kt")
public void testBasicTypes() throws Exception {
runTest("js/js.translator/testData/wasmBox/basicTypes.kt");
}
@TestMetadata("primitivesOperatos.kt")
public void testPrimitivesOperatos() throws Exception {
runTest("js/js.translator/testData/wasmBox/primitivesOperatos.kt");
}
@TestMetadata("js/js.translator/testData/wasmBox/number")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Number extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInNumber() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/number"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("assignmentIntOverflow.kt")
public void testAssignmentIntOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/assignmentIntOverflow.kt");
}
@TestMetadata("byteAndShortConversions.kt")
public void testByteAndShortConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/byteAndShortConversions.kt");
}
@TestMetadata("conversionsWithTruncation.kt")
public void testConversionsWithTruncation() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/conversionsWithTruncation.kt");
}
@TestMetadata("conversionsWithoutTruncation.kt")
public void testConversionsWithoutTruncation() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/conversionsWithoutTruncation.kt");
}
@TestMetadata("division.kt")
public void testDivision() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/division.kt");
}
@TestMetadata("doubleConversions.kt")
public void testDoubleConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/doubleConversions.kt");
}
@TestMetadata("hexadecimalConstant.kt")
public void testHexadecimalConstant() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/hexadecimalConstant.kt");
}
@TestMetadata("incDecOptimization.kt")
public void testIncDecOptimization() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/incDecOptimization.kt");
}
@TestMetadata("intConversions.kt")
public void testIntConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intConversions.kt");
}
@TestMetadata("intDivFloat.kt")
public void testIntDivFloat() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intDivFloat.kt");
}
@TestMetadata("intIncDecOverflow.kt")
public void testIntIncDecOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intIncDecOverflow.kt");
}
@TestMetadata("intOverflow.kt")
public void testIntOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intOverflow.kt");
}
@TestMetadata("kt2342.kt")
public void testKt2342() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/kt2342.kt");
}
@TestMetadata("longBinaryOperations.kt")
public void testLongBinaryOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longBinaryOperations.kt");
}
@TestMetadata("longBitOperations.kt")
public void testLongBitOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longBitOperations.kt");
}
@TestMetadata("longCompareToIntrinsic.kt")
public void testLongCompareToIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longCompareToIntrinsic.kt");
}
@TestMetadata("longEqualsIntrinsic.kt")
public void testLongEqualsIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longEqualsIntrinsic.kt");
}
@TestMetadata("longHashCode.kt")
public void testLongHashCode() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longHashCode.kt");
}
@TestMetadata("longUnaryOperations.kt")
public void testLongUnaryOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longUnaryOperations.kt");
}
@TestMetadata("mixedTypesOverflow.kt")
public void testMixedTypesOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/mixedTypesOverflow.kt");
}
@TestMetadata("numberCompareTo.kt")
public void testNumberCompareTo() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberCompareTo.kt");
}
@TestMetadata("numberConversions.kt")
public void testNumberConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberConversions.kt");
}
@TestMetadata("numberEquals.kt")
public void testNumberEquals() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberEquals.kt");
}
@TestMetadata("numberIncDec.kt")
public void testNumberIncDec() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberIncDec.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PassedCommonTests extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInPassedCommonTests() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class BoxingOptimization extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInBoxingOptimization() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("explicitEqualsOnDouble.kt")
public void testExplicitEqualsOnDouble() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization/explicitEqualsOnDouble.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/classes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Classes extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/classes"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("kt2482.kt")
public void testKt2482() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/classes/kt2482.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/constants")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Constants extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInConstants() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/constants"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("float.kt")
public void testFloat() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/constants/float.kt");
}
@TestMetadata("long.kt")
public void testLong() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/constants/long.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ControlStructures extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInControlStructures() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("ifConst1.kt")
public void testIfConst1() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/ifConst1.kt");
}
@TestMetadata("ifConst2.kt")
public void testIfConst2() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/ifConst2.kt");
}
@TestMetadata("kt1899.kt")
public void testKt1899() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/kt1899.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExtensionProperties extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInExtensionProperties() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties/topLevel.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/functions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Functions extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/functions"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("kt2280.kt")
public void testKt2280() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/functions/kt2280.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ieee754")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Ieee754 extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInIeee754() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ieee754"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("lessDouble_properIeeeAndNewInference.kt")
public void testLessDouble_properIeeeAndNewInference() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ieee754/lessDouble_properIeeeAndNewInference.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ir")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Ir extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInIr() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ir"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClosureConversion extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInClosureConversion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("closureConversion1.kt")
public void testClosureConversion1() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion1.kt");
}
@TestMetadata("closureConversion3.kt")
public void testClosureConversion3() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion3.kt");
}
@TestMetadata("closureConversion4.kt")
public void testClosureConversion4() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion4.kt");
}
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/labels")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Labels extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInLabels() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/labels"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("propertyAccessor.kt")
public void testPropertyAccessor() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/labels/propertyAccessor.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LazyCodegen extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInLazyCodegen() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Optimizations extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInOptimizations() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("negateConstantCompare.kt")
public void testNegateConstantCompare() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations/negateConstantCompare.kt");
}
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class OperatorConventions extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInOperatorConventions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("annotatedAssignment.kt")
public void testAnnotatedAssignment() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions/annotatedAssignment.kt");
}
@TestMetadata("infixFunctionOverBuiltinMember.kt")
public void testInfixFunctionOverBuiltinMember() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions/infixFunctionOverBuiltinMember.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PrimitiveTypes extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInPrimitiveTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("ea35963.kt")
public void testEa35963() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/ea35963.kt");
}
@TestMetadata("incrementByteCharShort.kt")
public void testIncrementByteCharShort() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/incrementByteCharShort.kt");
}
@TestMetadata("kt1634.kt")
public void testKt1634() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt1634.kt");
}
@TestMetadata("kt3078.kt")
public void testKt3078() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt3078.kt");
}
@TestMetadata("kt6590_identityEquals.kt")
public void testKt6590_identityEquals() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt6590_identityEquals.kt");
}
@TestMetadata("kt737.kt")
public void testKt737() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt737.kt");
}
@TestMetadata("kt828.kt")
public void testKt828() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt828.kt");
}
@TestMetadata("kt877.kt")
public void testKt877() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt877.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PublishedApi extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInPublishedApi() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi/topLevel.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnaryOp extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInUnaryOp() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("intrinsic.kt")
public void testIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp/intrinsic.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/when")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class When extends AbstractIrWasmBoxJsTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
}
public void testAllFilesPresentInWhen() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/when"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("noElseNoMatch.kt")
public void testNoElseNoMatch() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/when/noElseNoMatch.kt");
}
}
}
}
@@ -15,6 +15,11 @@ abstract class AbstractIrJsCodegenBoxTest : BasicIrBoxTest(
"codegen/irBox/"
)
abstract class AbstractIrWasmBoxJsTest : BasicIrBoxTest(
BasicBoxTest.TEST_DATA_DIR_PATH + "wasmBox/",
"irWasmBox/"
)
abstract class BorrowedIrInlineTest(relativePath: String) : BasicIrBoxTest(
"compiler/testData/codegen/boxInline/$relativePath",
"codegen/irBoxInline/$relativePath"
@@ -0,0 +1,553 @@
/*
* Copyright 2010-2019 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.js.test.wasm.semantics;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("js/js.translator/testData/wasmBox")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class IrWasmBoxWasmTestGenerated extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInWasmBox() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("basicTypes.kt")
public void testBasicTypes() throws Exception {
runTest("js/js.translator/testData/wasmBox/basicTypes.kt");
}
@TestMetadata("primitivesOperatos.kt")
public void testPrimitivesOperatos() throws Exception {
runTest("js/js.translator/testData/wasmBox/primitivesOperatos.kt");
}
@TestMetadata("js/js.translator/testData/wasmBox/number")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Number extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInNumber() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/number"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("assignmentIntOverflow.kt")
public void testAssignmentIntOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/assignmentIntOverflow.kt");
}
@TestMetadata("byteAndShortConversions.kt")
public void testByteAndShortConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/byteAndShortConversions.kt");
}
@TestMetadata("conversionsWithTruncation.kt")
public void testConversionsWithTruncation() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/conversionsWithTruncation.kt");
}
@TestMetadata("conversionsWithoutTruncation.kt")
public void testConversionsWithoutTruncation() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/conversionsWithoutTruncation.kt");
}
@TestMetadata("division.kt")
public void testDivision() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/division.kt");
}
@TestMetadata("doubleConversions.kt")
public void testDoubleConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/doubleConversions.kt");
}
@TestMetadata("hashCode.kt")
public void testHashCode() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/hashCode.kt");
}
@TestMetadata("hexadecimalConstant.kt")
public void testHexadecimalConstant() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/hexadecimalConstant.kt");
}
@TestMetadata("incDecOptimization.kt")
public void testIncDecOptimization() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/incDecOptimization.kt");
}
@TestMetadata("intConversions.kt")
public void testIntConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intConversions.kt");
}
@TestMetadata("intDivFloat.kt")
public void testIntDivFloat() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intDivFloat.kt");
}
@TestMetadata("intIncDecOverflow.kt")
public void testIntIncDecOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intIncDecOverflow.kt");
}
@TestMetadata("intOverflow.kt")
public void testIntOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/intOverflow.kt");
}
@TestMetadata("kt2342.kt")
public void testKt2342() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/kt2342.kt");
}
@TestMetadata("longBinaryOperations.kt")
public void testLongBinaryOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longBinaryOperations.kt");
}
@TestMetadata("longBitOperations.kt")
public void testLongBitOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longBitOperations.kt");
}
@TestMetadata("longCompareToIntrinsic.kt")
public void testLongCompareToIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longCompareToIntrinsic.kt");
}
@TestMetadata("longEqualsIntrinsic.kt")
public void testLongEqualsIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longEqualsIntrinsic.kt");
}
@TestMetadata("longHashCode.kt")
public void testLongHashCode() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longHashCode.kt");
}
@TestMetadata("longUnaryOperations.kt")
public void testLongUnaryOperations() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/longUnaryOperations.kt");
}
@TestMetadata("mixedTypesOverflow.kt")
public void testMixedTypesOverflow() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/mixedTypesOverflow.kt");
}
@TestMetadata("numberCompareTo.kt")
public void testNumberCompareTo() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberCompareTo.kt");
}
@TestMetadata("numberConversions.kt")
public void testNumberConversions() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberConversions.kt");
}
@TestMetadata("numberEquals.kt")
public void testNumberEquals() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberEquals.kt");
}
@TestMetadata("numberIncDec.kt")
public void testNumberIncDec() throws Exception {
runTest("js/js.translator/testData/wasmBox/number/numberIncDec.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PassedCommonTests extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInPassedCommonTests() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class BoxingOptimization extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInBoxingOptimization() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("explicitEqualsOnDouble.kt")
public void testExplicitEqualsOnDouble() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/boxingOptimization/explicitEqualsOnDouble.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/classes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Classes extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInClasses() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/classes"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("kt2482.kt")
public void testKt2482() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/classes/kt2482.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/constants")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Constants extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInConstants() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/constants"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("float.kt")
public void testFloat() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/constants/float.kt");
}
@TestMetadata("long.kt")
public void testLong() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/constants/long.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ControlStructures extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInControlStructures() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("ifConst1.kt")
public void testIfConst1() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/ifConst1.kt");
}
@TestMetadata("ifConst2.kt")
public void testIfConst2() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/ifConst2.kt");
}
@TestMetadata("kt1899.kt")
public void testKt1899() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/controlStructures/kt1899.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ExtensionProperties extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInExtensionProperties() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/extensionProperties/topLevel.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/functions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Functions extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInFunctions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/functions"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("kt2280.kt")
public void testKt2280() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/functions/kt2280.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ieee754")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Ieee754 extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInIeee754() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ieee754"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("lessDouble_properIeeeAndNewInference.kt")
public void testLessDouble_properIeeeAndNewInference() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ieee754/lessDouble_properIeeeAndNewInference.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ir")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Ir extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInIr() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ir"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ClosureConversion extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInClosureConversion() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("closureConversion1.kt")
public void testClosureConversion1() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion1.kt");
}
@TestMetadata("closureConversion3.kt")
public void testClosureConversion3() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion3.kt");
}
@TestMetadata("closureConversion4.kt")
public void testClosureConversion4() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/ir/closureConversion/closureConversion4.kt");
}
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/labels")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Labels extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInLabels() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/labels"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("propertyAccessor.kt")
public void testPropertyAccessor() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/labels/propertyAccessor.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class LazyCodegen extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInLazyCodegen() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Optimizations extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInOptimizations() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("negateConstantCompare.kt")
public void testNegateConstantCompare() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/lazyCodegen/optimizations/negateConstantCompare.kt");
}
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class OperatorConventions extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInOperatorConventions() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("annotatedAssignment.kt")
public void testAnnotatedAssignment() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions/annotatedAssignment.kt");
}
@TestMetadata("infixFunctionOverBuiltinMember.kt")
public void testInfixFunctionOverBuiltinMember() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/operatorConventions/infixFunctionOverBuiltinMember.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PrimitiveTypes extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInPrimitiveTypes() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("ea35963.kt")
public void testEa35963() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/ea35963.kt");
}
@TestMetadata("incrementByteCharShort.kt")
public void testIncrementByteCharShort() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/incrementByteCharShort.kt");
}
@TestMetadata("kt1634.kt")
public void testKt1634() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt1634.kt");
}
@TestMetadata("kt3078.kt")
public void testKt3078() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt3078.kt");
}
@TestMetadata("kt6590_identityEquals.kt")
public void testKt6590_identityEquals() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt6590_identityEquals.kt");
}
@TestMetadata("kt737.kt")
public void testKt737() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt737.kt");
}
@TestMetadata("kt828.kt")
public void testKt828() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt828.kt");
}
@TestMetadata("kt877.kt")
public void testKt877() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/primitiveTypes/kt877.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class PublishedApi extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInPublishedApi() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("topLevel.kt")
public void testTopLevel() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/publishedApi/topLevel.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class UnaryOp extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInUnaryOp() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("intrinsic.kt")
public void testIntrinsic() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/unaryOp/intrinsic.kt");
}
}
@TestMetadata("js/js.translator/testData/wasmBox/passedCommonTests/when")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class When extends AbstractIrWasmBoxWasmTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
}
public void testAllFilesPresentInWhen() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/wasmBox/passedCommonTests/when"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.WASM, true);
}
@TestMetadata("noElseNoMatch.kt")
public void testNoElseNoMatch() throws Exception {
runTest("js/js.translator/testData/wasmBox/passedCommonTests/when/noElseNoMatch.kt");
}
}
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2019 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.js.test.wasm.semantics
import org.jetbrains.kotlin.js.test.BasicBoxTest
import org.jetbrains.kotlin.js.test.BasicWasmBoxTest
abstract class AbstractIrWasmBoxWasmTest : BasicWasmBoxTest(BasicBoxTest.TEST_DATA_DIR_PATH + "wasmBox", "wasmBox/")
abstract class AbstractIrCodegenBoxWasmTest : BasicWasmBoxTest(
"compiler/testData/codegen/box/",
"codegen/wasmBox/"
)
+44
View File
@@ -0,0 +1,44 @@
fun foo(
x1: Int,
x2: Long,
x3: Float,
x4: Double
): Int {
var mtmp1: Int = 0
var mtmp2: Long = 0L
var mtmp3: Float = 0f
var mtmp4: Double = 0.0
val tmp1 = x1
val tmp2 = x2
val tmp3 = x3
val tmp4 = x4
mtmp1 = x1
mtmp2 = x2
mtmp3 = x3
mtmp4 = x4
return mtmp1
}
var g1: Int = 0
var g2: Long = 0L
var g3: Float = 0f
var g4: Double = 0.0
fun fooUnit() {
g1 = 10
g2 = 10L
g3 = 10f
g4 = 10.0
g1 = g1
g2 = g2
g3 = g3
g4 = g4
}
fun box(): String {
fooUnit()
val res = foo(42, 100L, 100f, 100.0)
if (res == 42)
return "OK"
return "Fail"
}
@@ -0,0 +1,26 @@
// EXPECTED_REACHABLE_NODES: 1282
package foo
fun bigValue() = 0x7FFFFFFC
fun mediumValue() = 0x12345
fun box(): String {
var v = bigValue()
v += 1
if (v != 0x7FFFFFFD) return "fail1"
v = bigValue()
v += 8
if (v != -0x7FFFFFFC) return "fail2"
v = mediumValue()
v *= 0x23456
if (v != -2112496338) return "fail3"
v = bigValue()
v *= bigValue()
if (v != 16) return "fail4"
return "OK"
}
@@ -0,0 +1,46 @@
// EXPECTED_REACHABLE_NODES: 1284
package foo
fun testShortConversions(c: Short): Boolean {
if (c.toDouble() != 3.0) {
return false
}
if (c.toFloat() != 3.toFloat()) {
return false
}
if (c.toByte() != 3.toByte()) {
return false
}
if (c.toInt() != 3) {
return false
}
if (c.toShort() != 3.toShort()) {
return false
}
return true
}
fun testByteConversions(c: Byte): Boolean {
if (c.toDouble() != 3.0) {
return false
}
if (c.toFloat() != 3.toFloat()) {
return false
}
if (c.toByte() != 3.toByte()) {
return false
}
if (c.toInt() != 3) {
return false
}
if (c.toShort() != 3.toShort()) {
return false
}
return true
}
fun box(): String {
if (!testShortConversions(3)) return "fail: testShortConversions"
if (!testByteConversions(3)) return "fail: testByteConversions"
return "OK"
}
@@ -0,0 +1,51 @@
// EXPECTED_REACHABLE_NODES: 1227
package foo
// TODO: Floats to ints
fun box(): String {
// assertEquals(65, 321.0.toByte())
// assertEquals(-56, 200.0.toByte())
//
// assertEquals(65, 321.0f.toByte())
// assertEquals(-56, 200.0f.toByte())
assertEquals(65, 321L.toByte())
assertEquals(-56, 200L.toByte())
assertEquals(65, 321.toByte())
assertEquals(-56, 200.toByte())
assertEquals(65, (321.toShort()).toByte())
assertEquals(-56, (200.toShort()).toByte())
// assertEquals(-1, 65535.0.toShort())
// assertEquals(-1, 65535.0f.toShort())
assertEquals(-1, 65535L.toShort())
assertEquals(-1, 65535.toShort())
// assertEquals(65535, 65535.2.toInt())
// assertEquals(23, 23.6f.toInt())
// assertEquals(-12, -12.4.toShort())
// assertEquals(-12, -12.4.toByte())
assertEquals('\u0419', (-654311).toChar())
// assertEquals('\u0419', (-654311.0).toChar())
// assertEquals('\u0419', (-654311.0f).toChar())
// TODO: Long.toString
val longX: Long = 9223372034707292481L
// assertEquals("9223372034707292481", longX.toString())
assertEquals(-2147483327, longX.toInt())
assertEquals(321, longX.toShort())
assertEquals(65, longX.toByte())
assertEquals('\u0141', longX.toChar())
val intX: Int = longX.toInt()
assertEquals(321, intX.toShort())
assertEquals(65, intX.toByte())
return "OK"
}
@@ -0,0 +1,81 @@
// EXPECTED_REACHABLE_NODES: 1293
package foo
//fun testForNumber(numberX: Number) {
// assertEquals(true, 65.0 == numberX.toDouble())
// assertEquals(true, 65.0f == numberX.toFloat())
// assertEquals(true, 65L == numberX.toLong())
// assertEquals(true, 65 == numberX.toInt())
// assertEquals(true, 65.toShort() == numberX.toShort())
// assertEquals(true, 65.toByte() == numberX.toByte())
// assertEquals(true, 'A' == numberX.toChar())
//}
fun box(): String {
// TODO: Number is not supported yet
// testForNumber(65.0)
// testForNumber(65.0f)
// testForNumber(65L)
// testForNumber(65)
// testForNumber(65.toShort())
// testForNumber(65.toByte())
var doubleX: Double = 65.0
assertEquals(true, 65.0 == doubleX.toDouble())
assertEquals(true, 65.0f == doubleX.toFloat())
// TODO: Float to integer convertions are not supported yet
// assertEquals(true, 65L == doubleX.toLong())
// assertEquals(true, 65 == doubleX.toInt())
// assertEquals(true, 65.toShort() == doubleX.toShort())
// assertEquals(true, 65.toByte() == doubleX.toByte())
// assertEquals(true, 'A' == doubleX.toChar())
var floatX: Float = 65.0f
assertEquals(true, 65.0 == floatX.toDouble())
assertEquals(true, 65.0f == floatX.toFloat())
// TODO: Float to integer convertions are not supported yet
// assertEquals(true, 65L == floatX.toLong())
// assertEquals(true, 65 == floatX.toInt())
// assertEquals(true, 65.toShort() == floatX.toShort())
// assertEquals(true, 65.toByte() == floatX.toByte())
// assertEquals(true, 'A' == floatX.toChar())
val longX: Long = 65L
assertEquals(true, 65.0 == longX.toDouble())
assertEquals(true, 65.0f == longX.toFloat())
assertEquals(true, 65L == longX.toLong())
assertEquals(true, 65 == longX.toInt())
assertEquals(true, 65.toShort() == longX.toShort())
assertEquals(true, 65.toByte() == longX.toByte())
assertEquals(true, 'A' == longX.toChar())
val intX: Int = 65
assertEquals(true, 65.0 == intX.toDouble())
assertEquals(true, 65.0f == intX.toFloat())
assertEquals(true, 65L == intX.toLong())
assertEquals(true, 65 == intX.toInt())
assertEquals(true, 65.toShort() == intX.toShort())
assertEquals(true, 65.toByte() == intX.toByte())
assertEquals(true, 'A' == intX.toChar())
val shortX: Short = 65.toShort()
assertEquals(true, 65.0 == shortX.toDouble())
assertEquals(true, 65.0f == shortX.toFloat())
assertEquals(true, 65L == shortX.toLong())
assertEquals(true, 65 == shortX.toInt())
assertEquals(true, 65.toShort() == shortX.toShort())
assertEquals(true, 65.toByte() == shortX.toByte())
assertEquals(true, 'A' == shortX.toChar())
val byteX: Byte = 65.toByte()
assertEquals(true, 65.0 == byteX.toDouble())
assertEquals(true, 65.0f == byteX.toFloat())
assertEquals(true, 65L == byteX.toLong())
assertEquals(true, 65 == byteX.toInt())
assertEquals(true, 65.toShort() == byteX.toShort())
assertEquals(true, 65.toByte() == byteX.toByte())
assertEquals(true, 'A' == byteX.toChar())
return "OK"
}
+45
View File
@@ -0,0 +1,45 @@
// EXPECTED_REACHABLE_NODES: 1280
package foo
fun box(): String {
if (3 / 4 != 0) {
return "fail11"
}
if (-5 / 4 != -1) {
return "fail2"
}
if ((3.0 / 4.0 - 0.75) > 0.01) {
return "fail3"
}
if ((-10.0 / 4.0 + 2.5) > 0.01) {
return "fail44"
}
val i1: Int = 5
val i2: Int = 2
if (i1 / i2 != 2) {
return "fail55"
}
val i3: Short = 5
val i4: Short = 2
if (i3 / i4 != 2) {
return "fail6"
}
val i5: Byte = 5
val i6: Byte = 2
if (i5 / i6 != 2) {
return "fail7"
}
val f1: Double = 5.0
val f2: Double = 2.0
if ((f1 / f2 - 2.5) > 0.01) {
return "fail8"
}
val f3: Float = 5.0.toFloat()
val f4: Float = 2.0.toFloat()
if ((f3 / f4 - 2.5.toFloat()) > 0.01) {
return "fail9"
}
return "OK"
}
@@ -0,0 +1,77 @@
// EXPECTED_REACHABLE_NODES: 1222
// IGNORE_BACKEND: WASM
// TODO: Support floating-point to integer conversions
package foo
fun box(): String {
val c: Double = 3.6
if (c.toDouble() != 3.6) {
return "fail1"
}
if (c.toFloat() != 3.6.toFloat()) {
return "fail2"
}
if (c.toByte() != 3.toByte()) {
return "fail3"
}
if (c.toInt() != 3) {
return "fail4"
}
if (c.toShort() != 3.toShort()) {
return "fail5"
}
val cn: Double = -3.6
if (cn.toDouble() != -3.6) {
return "fail6"
}
if (cn.toFloat() != -3.6.toFloat()) {
return "fail7"
}
if (cn.toByte() != (-3).toByte()) {
return "fail8"
}
if (cn.toInt() != -3) {
return "fail9"
}
if (cn.toShort() != (-3).toShort()) {
return "fail10"
}
val f: Float = 3.6.toFloat()
if (f.toDouble() != 3.6) {
return "fail11"
}
if (f.toFloat() != 3.6.toFloat()) {
return "fail12"
}
if (f.toByte() != 3.toByte()) {
return "fail13"
}
if (f.toInt() != 3) {
return "fail14"
}
if (f.toShort() != 3.toShort()) {
return "fail15"
}
val fn: Float = -3.6.toFloat()
if (fn.toDouble() != -3.6) {
return "fail16"
}
if (fn.toFloat() != -3.6.toFloat()) {
return "fail17"
}
if (fn.toByte() != (-3).toByte()) {
return "fail18"
}
if (fn.toInt() != -3) {
return "fail19"
}
if (fn.toShort() != (-3).toShort()) {
return "fail20"
}
return "OK"
}
+23
View File
@@ -0,0 +1,23 @@
// TARGET_BACKEND: WASM
// EXPECTED_REACHABLE_NODES: 1280
// NOTE: Hash codes are the same as in Native and JVM
fun box(): String {
var value = (3).hashCode()
if (value != 3) return "fail1"
value = (3.14).hashCode()
if (value != 300063655) return "fail2"
value = (3.14159).hashCode()
if (value != -1340954729) return "fail3"
value = (1e80).hashCode()
if (value != 24774576) return "fail4"
value = (1e81).hashCode()
if (value != -1007271154) return "fail5"
return "OK"
}
@@ -0,0 +1,7 @@
// EXPECTED_REACHABLE_NODES: 1219
package foo
fun box(): String {
val i = 0x80000000 + 0x8000000
return "OK"
}
@@ -0,0 +1,21 @@
// EXPECTED_REACHABLE_NODES: 1283
// CHECK_VARS_COUNT: function=test count=1
// TODO: Support classes
fun test(): String {
var i = 23
var x = ++i
if (x != 24) return "fail1:"
i++
if (i != 25) return "fail2:"
// a.i++, used as expression, requires temporary variable
return "OK"
}
fun box(): String = test()
@@ -0,0 +1,29 @@
// EXPECTED_REACHABLE_NODES: 1282
package foo
fun box(): String {
val c: Int = 3
if (c.toDouble() != 3.0) {
return "fail1"
}
if (c.toFloat() != 3.toFloat()) {
return "fail2"
}
if (c.toByte() != 3.toByte()) {
return "fail3"
}
if (c.toInt() != 3) {
return "fail4"
}
if (c.toShort() != 3.toShort()) {
return "fail5"
}
val c2: Int = -5
if (c2.toShort() != (-5).toShort()) {
return "fail6"
}
if (c2.toFloat() != -5.toFloat()) {
return "fail7"
}
return "OK"
}
+20
View File
@@ -0,0 +1,20 @@
// EXPECTED_REACHABLE_NODES: 1284
// http://youtrack.jetbrains.com/issue/KT-5345
// KT-5345 (Javascript) Type mismatch on Int / Float division
// If any of Number operands is floating-point, the result should be float too.
package foo
fun box(): String {
assertEquals(0.5f, 1 / 2.0f, "Int / Float")
assertEquals(0.5, 1 / 2.0, "Int / Double")
assertEquals(0.5f, 1.toShort() / 2.0f, "Short / Float")
assertEquals(0.5, 1.toShort() / 2.0, "Short / Double")
assertEquals(0.5f, 1.toByte() / 2.0f, "Byte / Float")
assertEquals(0.5, 1.toByte() / 2.0, "Byte / Double")
return "OK"
}
@@ -0,0 +1,25 @@
// EXPECTED_REACHABLE_NODES: 1282
package foo
fun box(): String {
var b: Byte = 0x7F
b++
if (b.toInt() != -0x80) return "fail1a"
b--
if (b.toInt() != 0x7F) return "fail1b"
var s: Short = 0x7FFF
s++
if (s.toInt() != -0x8000) return "fail2a"
s--
if (s.toInt() != 0x7FFF) return "fail2b"
var i: Int = 0x7FFFFFFF
i++
if (i != -0x80000000) return "fail3a"
i--
if (i != 0x7FFFFFFF) return "fail3b"
return "OK"
}
+35
View File
@@ -0,0 +1,35 @@
// EXPECTED_REACHABLE_NODES: 1284
package foo
fun bigValue() = 0x7FFFFFFC
fun mediumValue() = 0x12345
fun four() = 4
fun box(): String {
var v = bigValue() + 1
if (v != 0x7FFFFFFD) return "fail1"
v = bigValue() + 8
if (v != -0x7FFFFFFC) return "fail2"
v = bigValue() + four() + 4
if (v != -0x7FFFFFFC) return "fail3"
v = (bigValue() + four() - 4) shr 1
if (v != 0x3FFFFFFE) return "fail3"
v = mediumValue() * 0x23456
if (v != -2112496338) return "fail5"
v = bigValue() * bigValue()
if (v != 16) return "fail6"
v = -minInt()
if (v != -2147483648) return "fail7"
return "OK"
}
fun minInt() = -2147483648
+20
View File
@@ -0,0 +1,20 @@
// EXPECTED_REACHABLE_NODES: 1281
package foo
fun test(a: Int, b: Int, expected: Int): Int {
val result = a / b
if (expected == result) return 100
return 25
}
fun box(): String {
var r = test(10, 3, 3)
if (r != 100) return "Fail1"
r = test(49, 6, 8)
if (r != 100) return "Fail 2"
if (2133 / 3 / 7 / (91 / 5) != 5) return "2133 / 3 / 7 / (91 / 5) != 5"
return "OK"
}
@@ -0,0 +1,57 @@
// EXPECTED_REACHABLE_NODES: 1230
package foo
fun fact(n: Int): Long = if (n == 1) 1L else n * fact(n - 1)
// TODO: Support loops
//fun fib(n: Int): Long {
// var a = 0L
// var b = 1L
// for (i in 2..n) {
// var tmp = a
// a = b
// b = b + tmp
// }
// return b
//}
fun box(): String {
assertEquals(30.0, 10L + 20.0)
assertEquals(30.0f, 10L + 20.0f)
assertEquals(30L, 10L + 20L)
assertEquals(30L, 10L + 20)
assertEquals(30L, 10L + 20.toShort())
assertEquals(30L, 10L + 20.toByte())
assertEquals(30.0, 20.0 + 10L)
assertEquals(30.0f, 20.0f + 10L)
assertEquals(20L, 10 + 10L)
assertEquals(20L, 10.toShort() + 10L)
assertEquals(20L, 10.toByte() + 10L)
assertEquals(20L, 30 - 10L)
assertEquals(100L, 10 * 10L)
assertEquals(100.0, 10.0 * 10L)
assertEquals(100L, 10L * 10)
assertEquals(100.0, 10L * 10.0)
assertEquals(100L, 1000L / 10)
assertEquals(100L, 1000 / 10L)
assertEquals(100.0, 1000L / 10.0)
assertEquals(100.0, 1000.0 / 10L)
assertEquals(2L, 100L % 7)
assertEquals(2L, 100 % 7L)
assertEquals(2432902008176640000L, fact(20))
// TODO: Support loops
// assertEquals(12586269025L, fib(50))
// assertEquals(7540113804746346429L, fib(92))
return "OK"
}
@@ -0,0 +1,24 @@
// EXPECTED_REACHABLE_NODES: 1228
package foo
fun box(): String {
assertEquals(65536L, 1L shl 16)
assertEquals(1L, 65536L shr 16)
assertEquals(-1L, -1L shr 48)
assertEquals(65535L, -1L ushr 48)
assertEquals(-1L, 0L.inv())
assertEquals(0b1000L, 0b1100L and 0b1010L)
assertEquals(0b1110L, 0b1100L or 0b1010L)
assertEquals(0b0110L, 0b1100L xor 0b1010L)
assertEquals(0xab88ac0021L, 0xabcdef0123L and 0xefaabcdef1L)
assertEquals(0xefefffdff3L, 0xabcdef0123L or 0xefaabcdef1L)
assertEquals(0x446753dfd2L, 0xabcdef0123L xor 0xefaabcdef1L)
assertEquals(-737894400292, 0xabcdef0123L.inv())
return "OK"
}
@@ -0,0 +1,41 @@
// EXPECTED_REACHABLE_NODES: 1226
package foo
fun box(): String {
assertEquals(true, 10.0 < 20L, "Double.compareTo(Long)")
assertEquals(true, 10.0 < 7540113804746346429L, "Double.compareTo(Long)")
assertEquals(true, 10.0f < 20L, "Float.compareTo(Long)")
assertEquals(true, 10.0f < 7540113804746346429L, "Float.compareTo(Long)")
assertEquals(true, 10L < 20L, "Long.compareTo(Long)")
assertEquals(true, 10 < 20L, "Int.compareTo(Long)")
assertEquals(true, 10 < 7540113804746346429L, "Int.compareTo(Long)")
assertEquals(true, 10.toShort() < 20L, "Short.compareTo(Long)")
assertEquals(true, 10.toShort() < 7540113804746346429L, "Short.compareTo(Long)")
assertEquals(true, 10.toByte() < 20L, "Byte.compareTo(Long)")
assertEquals(true, 10.toByte() < 7540113804746346429L, "Byte.compareTo(Long)")
assertEquals(true, 10L < 20.0, "Long.compareTo(Double)")
assertEquals(false, 7540113804746346429L < 20.0, "Long.compareTo(Double)")
assertEquals(true, 10L < 20.0f, "Long.compareTo(Float)")
assertEquals(true, 7540113804746346429L > 20.0f, "Long.compareTo(Float)")
assertEquals(false, 7540113804746346429L < 20.0f, "Long.compareTo(Float)")
assertEquals(true, 10L < 20, "Long.compareTo(Int)")
assertEquals(true, 7540113804746346429L > 20, "Long.compareTo(Int)")
assertEquals(false, 7540113804746346429L < 20, "Long.compareTo(Int)")
assertEquals(true, 10L < 20.toShort(), "Long.compareTo(Short)")
assertEquals(true, 7540113804746346429L > 20.toShort(), "Long.compareTo(Short)")
assertEquals(false, 7540113804746346429L < 20.toShort(), "Long.compareTo(Short)")
assertEquals(true, 10L < 20.toByte(), "Long.compareTo(Byte)")
assertEquals(true, 7540113804746346429L > 20.toByte(), "Long.compareTo(Byte)")
assertEquals(false, 7540113804746346429L < 20.toByte(), "Long.compareTo(Byte)")
return "OK"
}
@@ -0,0 +1,45 @@
// EXPECTED_REACHABLE_NODES: 1284
package foo
// WASM: TODO: Nullable types, Number, Any
fun box(): String {
assertEquals(true, 10L == 10L, "Long == Long")
assertEquals(true, 10L != 11L, "Long != Long")
// val x1: Long? = 10L
// val x2: Long? = 10L
// assertEquals(false, x1 == null, "Long? == null")
// assertEquals(false, null == x1, "null == Long?")
// assertEquals(true, x1 == 10L, "Long? == Long")
// assertEquals(true, 10L == x1, "Long == Long?")
// assertEquals(true, x1 == x2, "Long? == Long?")
// val x3: Long? = null
// val x4: Long? = null
// assertEquals(true, x3 == null, "Long?(null) == null")
// assertEquals(true, null == x3, "null == Long?(null)")
// assertEquals(false, x3 == 10L, "Long?(null) == Long")
// assertEquals(false, 10L == x3, "Long == Long?(null)")
// assertEquals(false, x3 == x1, "Long?(null) == Long?")
// assertEquals(true, x3 == x4, "Long?(null) == Long?(null)")
// val number1: Number = 10L
// val number2: Number = 10L
// assertEquals(true, number1 == number2, "Number == Number")
// assertEquals(true, number1 == 10L, "Number == Long")
// assertEquals(true, number1 != 11L, "Number != Long")
// assertEquals(true, 10L == number1, "Long == Number")
// assertEquals(true, 11L != number1, "Long != Number")
//
// val y1: Any = 10L
// var y2: Any = 10
// var y3: Any? = null
// assertEquals(true, y1 == 10L, "Any == Long")
// assertEquals(true, 10L == y1, "Long == Any 1")
// assertEquals(false, 10L == y2, "Long == Any 2")
// assertEquals(false, 10L == y3, "Long == Any?(null)")
// assertEquals(true, x3 == y3, "Long?(null) == Any?(null)")
return "OK"
}
@@ -0,0 +1,18 @@
// EXPECTED_REACHABLE_NODES: 1284
package foo
fun box(): String {
var l1: Long = 0x12344478935690
var l2: Long = 0x12344478935698
var diff: Long = l2 - l1
l1 += (diff / 2)
l2 -= (diff / 2)
assertEquals(l1, l2, "When L1 == L2")
assertEquals(l1.hashCode(), l2.hashCode(), "L1.hashCode() == L2.hashCode()")
// var l3: Any = l2
// assertEquals(l1.hashCode(), l3.hashCode(), "Any(Long).hashCode()")
return "OK"
}
@@ -0,0 +1,32 @@
// EXPECTED_REACHABLE_NODES: 1225
package foo
fun box(): String {
var x: Long = 2L
x++
assertEquals(3L, x)
++x
assertEquals(4L, x)
var y = x++
assertEquals(4L, y)
assertEquals(5L, x)
y = ++x
assertEquals(6L, y)
assertEquals(6L, x)
x--
assertEquals(5L, x)
--x
assertEquals(4L, x)
y = +x
assertEquals(4L, y)
y = -x
assertEquals(-4L, y)
return "OK"
}
@@ -0,0 +1,34 @@
// EXPECTED_REACHABLE_NODES: 1284
// IGNORE_BACKEND: JS
package foo
// TODO(WASM) Companions are not supported yet
fun box(): String {
val byteOne = 1.toByte()
val shortOne = 1.toShort()
var v: Int
v = maxInt() + byteOne
if (v != minInt()) return "fail1"
v = minInt() - byteOne
if (v != maxInt()) return "fail2"
v = maxInt() + shortOne
if (v != minInt()) return "fail3"
v = minInt() - shortOne
if (v != maxInt()) return "fail4"
v = maxInt() * 127 // Byte.MAX_VALUE
if (v != 2147483521) return "fail5"
v = maxInt() * 32767 // Short.MAX_VALUE
if (v != 2147450881) return "fail6"
return "OK"
}
fun minInt() = -2147483648 // Int.MIN_VALUE
fun maxInt() = 2147483647 // Int.MAX_VALUE
@@ -0,0 +1,127 @@
// EXPECTED_REACHABLE_NODES: 1289
package foo
// TODO: Wasm global initialization is not supported
//var global: String = ""
//
//fun id(s: String, value: Int): Int {
// global += s
// return value
//}
fun box(): String {
assertEquals(-1, 1.compareTo(2))
// assertEquals(-1, (1 as Comparable<Int>).compareTo(2))
assertEquals(-1, 1.compareTo(2L))
assertEquals(-1, 1.compareTo(2L))
assertEquals(-1, 1.compareTo(7540113804746346429L))
assertEquals(-1, 1.compareTo(2.toShort()))
assertEquals(-1, 1.compareTo(2.toByte()))
assertEquals(-1, 1.compareTo(2.0))
assertEquals(-1, 1.compareTo(2.0f))
assertEquals(1, 10.compareTo(2L))
assertEquals(1, 10.compareTo(2))
assertEquals(1, 10.compareTo(2.toShort()))
assertEquals(1, 10.compareTo(2.toByte()))
assertEquals(1, 10.compareTo(2.0))
assertEquals(1, 10.compareTo(2.0f))
assertEquals(0, 2.compareTo(2L))
assertEquals(0, 2.compareTo(2))
assertEquals(0, 2.compareTo(2.toShort()))
assertEquals(0, 2.compareTo(2.toByte()))
assertEquals(0, 2.compareTo(2.0))
assertEquals(0, 2.compareTo(2.0f))
assertEquals(-1, 1.toShort().compareTo(2L))
assertEquals(-1, 1.toShort().compareTo(7540113804746346429L))
assertEquals(-1, 1.toShort().compareTo(2))
assertEquals(-1, 1.toShort().compareTo(2.toShort()))
// assertEquals(-1, (1.toShort() as Comparable<Short>).compareTo(2.toShort()))
assertEquals(-1, 1.toShort().compareTo(2.toByte()))
assertEquals(-1, 1.toShort().compareTo(2.0))
assertEquals(-1, 1.toShort().compareTo(2.0f))
assertEquals(1, 10.toByte().compareTo(2L))
assertEquals(-1, 10.toByte().compareTo(7540113804746346429L))
assertEquals(1, 10.toByte().compareTo(2))
assertEquals(1, 10.toByte().compareTo(2.toShort()))
assertEquals(1, 10.toByte().compareTo(2.toByte()))
// assertEquals(1, (10.toByte() as Comparable<Byte>).compareTo(2.toByte()))
assertEquals(1, 10.toByte().compareTo(2.0))
assertEquals(1, 10.toByte().compareTo(2.0f))
assertEquals(0, 2.0.compareTo(2L))
assertEquals(-1, 2.0.compareTo(7540113804746346429L))
assertEquals(0, 2.0.compareTo(2))
assertEquals(0, 2.0.compareTo(2.toShort()))
assertEquals(0, 2.0.compareTo(2.toByte()))
assertEquals(0, 2.0.compareTo(2.0))
// assertEquals(0, (2.0 as Comparable<Double>).compareTo(2.0))
assertEquals(0, 2.0.compareTo(2.0f))
assertEquals(1, 3.0f.compareTo(2L))
assertEquals(-1, 3.0f.compareTo(7540113804746346429L))
assertEquals(1, 3.0f.compareTo(2))
assertEquals(1, 3.0f.compareTo(2.toShort()))
assertEquals(1, 3.0f.compareTo(2.toByte()))
assertEquals(1, 3.0f.compareTo(2.0))
assertEquals(1, 3.0f.compareTo(2.0f))
// assertEquals(1, (3.0f as Comparable<Float>).compareTo(2.0f))
assertEquals(1, 10L.compareTo(2L))
assertEquals(-1, 10L.compareTo(7540113804746346429L))
// assertEquals(1, (10L as Comparable<Long>).compareTo(2L))
assertEquals(1, 10L.compareTo(2))
assertEquals(1, 10L.compareTo(2.toShort()))
assertEquals(1, 10L.compareTo(2.toByte()))
assertEquals(1, 10L.compareTo(2.0))
assertEquals(1, 10L.compareTo(2.0f))
assertEquals(0, 'A'.compareTo('A'))
assertEquals(-1, 1L.compareTo(2L))
assertEquals(-1, 1L.compareTo(2))
assertEquals(-1, 1L.compareTo(2.toShort()))
assertEquals(-1, 1L.compareTo(2.toByte()))
assertEquals(-1, 1L.compareTo(2.0))
assertEquals(-1, 1L.compareTo(2.0f))
assertEquals(0, 7540113804746346429L.compareTo(7540113804746346429L))
assertEquals(1, 7540113804746346429L.compareTo(2L))
assertEquals(0, 2L.compareTo(2L))
assertEquals(0, 2L.compareTo(2))
assertEquals(0, 2L.compareTo(2.toShort()))
assertEquals(0, 2L.compareTo(2.toByte()))
assertEquals(0, 2L.compareTo(2.0))
assertEquals(0, 2L.compareTo(2.0f))
assertEquals(1, 10L.compareTo(2L))
assertEquals(1, 10L.compareTo(2))
assertEquals(1, 10L.compareTo(2.toShort()))
assertEquals(1, 10L.compareTo(2.toByte()))
assertEquals(1, 10L.compareTo(2.0))
assertEquals(1, 10L.compareTo(2.0f))
assertEquals(-1, 1L.compareTo(2L))
assertEquals(-1, 1L.compareTo(2))
assertEquals(-1, 1L.compareTo(2.toShort()))
assertEquals(-1, 1L.compareTo(2.toByte()))
assertEquals(-1, 1L.compareTo(2.0))
assertEquals(-1, 1L.compareTo(2.0f))
assertEquals(0, 2L.compareTo(2L))
assertEquals(0, 2L.compareTo(2))
assertEquals(0, 2L.compareTo(2.toShort()))
assertEquals(0, 2L.compareTo(2.toByte()))
assertEquals(0, 2L.compareTo(2.0))
assertEquals(0, 2L.compareTo(2.0f))
// assertEquals(1, id("A", 10).compareTo(id("B", 5)))
// assertEquals("AB", global)
return "OK"
}
@@ -0,0 +1,91 @@
// EXPECTED_REACHABLE_NODES: 1289
package foo
fun testIntegerConversions(c: Byte): Boolean {
if (c.toDouble() != 3.0) {
return false
}
if (c.toFloat() != 3.toFloat()) {
return false
}
if (c.toByte() != 3.toByte()) {
return false
}
if (c.toInt() != 3) {
return false
}
if (c.toShort() != 3.toShort()) {
return false
}
return true
}
fun testIntegerConversions(c: Short): Boolean {
if (c.toDouble() != 3.0) {
return false
}
if (c.toFloat() != 3.toFloat()) {
return false
}
if (c.toByte() != 3.toByte()) {
return false
}
if (c.toInt() != 3) {
return false
}
if (c.toShort() != 3.toShort()) {
return false
}
return true
}
fun testIntegerConversions(c: Int): Boolean {
if (c.toDouble() != 3.0) {
return false
}
if (c.toFloat() != 3.toFloat()) {
return false
}
if (c.toByte() != 3.toByte()) {
return false
}
if (c.toInt() != 3) {
return false
}
if (c.toShort() != 3.toShort()) {
return false
}
return true
}
fun testFloatingPointConversions(c: Float): Boolean {
// This is FALSE on JVM
// if (c.toDouble() != 3.6) {
// return false
// }
if (c.toFloat() != 3.6.toFloat()) {
return false
}
return true
}
fun testFloatingPointConversions(c: Double): Boolean {
if (c.toDouble() != 3.6) {
return false
}
if (c.toFloat() != 3.6.toFloat()) {
return false
}
return true
}
fun box(): String {
if (!testIntegerConversions(3)) return "fail: testIntegerConversions1"
if (!testFloatingPointConversions(3.6)) return "fail: testFloatingPointConversions1"
if (!testFloatingPointConversions(3.6.toFloat())) return "fail: testFloaintPointConversions2"
if (!testIntegerConversions(3.toByte())) return "fail: testIntegerConversions2"
if (!testIntegerConversions(3.toShort())) return "fail: testIntegerConversions3"
return "OK"
}
@@ -0,0 +1,55 @@
// !LANGUAGE: +ProperIeee754Comparisons
package foo
//fun testNullable(): String {
// val undefined: Double? = js("undefined")
// val doubleNull: Double? = null
//
// val plusZero: Double? = +0.0
// val minusZero: Double? = -0.0
//
// if ((+0.0).equals(minusZero)) return "Total order fail"
// if (plusZero != minusZero) return "IEEE 754 equals fail"
//
// if (plusZero == doubleNull) return "+0.0 != null fail"
// if (plusZero == undefined) return "+0.0 != undefined fail"
//
// if (undefined != doubleNull) return "undefined == null fail"
// if (undefined != undefined) return "undefined = undefined fail"
// if (doubleNull != doubleNull) return "doubleNull = doubleNull fail"
//
// // Double == Float
// val plusZeroAny: Any? = +0.0
// val minusZeroAny: Any? = -0.0f
//
// if (plusZeroAny is Double && minusZeroAny is Float) {
// if (plusZeroAny != minusZeroAny) return "IEEE 754 quals fail 2"
// }
//
// return "OK"
//}
fun box(): String {
val plusZero: Double = +0.0
val minusZero: Double = -0.0
if (plusZero.equals(minusZero)) return "Total order fail"
if (plusZero != minusZero) return "IEEE 754 equals fail"
val plusZeroFloat: Float = +0.0f
val minusZeroFloat: Float = -0.0f
if (plusZeroFloat.equals(minusZeroFloat)) return "Total order fail 2"
if (plusZeroFloat != minusZeroFloat) return "IEEE 754 equals fail 2"
// if ((plusZero as Any) == (minusZero as Any)) return "Total order fail 4"
// if ((plusZeroFloat as Any) == (minusZeroFloat as Any)) return "Total order fail 5"
// if (plusZero == (minusZero as Any)) return "Total order fail 6"
// val nullableRes = testNullable()
// if (nullableRes != "OK")
// return "Nullable" + nullableRes
return "OK"
}
@@ -0,0 +1,17 @@
// EXPECTED_REACHABLE_NODES: 1282
package foo
fun box(): String {
assertEquals(100.inc(), 101)
assertEquals(100.dec(), 99)
var x = 100
assertEquals(x.inc(), 101)
assertEquals(x, 100)
assertEquals(x.dec(), 99)
assertEquals(x, 100)
return "OK"
}
@@ -0,0 +1,7 @@
fun equals1(a: Double, b: Double) = a.equals(b)
fun box(): String {
if ((-0.0).equals(0.0)) return "fail 0"
return "OK"
}
@@ -0,0 +1,9 @@
public fun box() : String {
if ( 0 == 0 ) { // Does not crash if either this...
if ( 0 == 0 ) { // ...or this is changed to if ( true )
// Does not crash if the following is uncommented.
//println("foo")
}
}
return "OK"
}
@@ -0,0 +1,18 @@
fun box(): String {
if (1F != 1.toFloat()) return "fail 1"
if (1.0F != 1.0.toFloat()) return "fail 2"
if (1e1F != 1e1.toFloat()) return "fail 3"
if (1.0e1F != 1.0e1.toFloat()) return "fail 4"
if (1e-1F != 1e-1.toFloat()) return "fail 5"
if (1.0e-1F != 1.0e-1.toFloat()) return "fail 6"
if (1f != 1.toFloat()) return "fail 7"
if (1.0f != 1.0.toFloat()) return "fail 8"
if (1e1f != 1e1.toFloat()) return "fail 9"
if (1.0e1f != 1.0e1.toFloat()) return "fail 10"
if (1e-1f != 1e-1.toFloat()) return "fail 11"
if (1.0e-1f != 1.0e-1.toFloat()) return "fail 12"
return "OK"
}
@@ -0,0 +1,10 @@
fun box(): String {
if (1L != 1.toLong()) return "fail 1"
if (0x1L != 0x1.toLong()) return "fail 2"
if (0X1L != 0X1.toLong()) return "fail 3"
if (0b1L != 0b1.toLong()) return "fail 4"
if (0B1L != 0B1.toLong()) return "fail 5"
return "OK"
}
@@ -0,0 +1,19 @@
fun foo(b: Boolean): String {
return if (b) {
"OK"
} else if (false) {
"fail: reached unreachable code at line 5"
} else if (true) {
"fail: reached unexpected code at line 7"
} else if (true) {
"fail: reached unreachable code at line 9"
} else if (b) {
"fail: reached unreachable code at line 11"
} else {
"fail: reached unreachable code at line 13"
}
}
fun box(): String {
return foo(true)
}
@@ -0,0 +1,19 @@
fun foo(b: Boolean): String {
return if (b) {
"fail: reached unexpected code at line 3"
} else if (false) {
"fail: reached unreachable code at line 5"
} else if (true) {
"OK"
} else if (true) {
"fail: reached unreachable code at line 9"
} else if (b) {
"fail: reached unreachable code at line 11"
} else {
"fail: reached unreachable code at line 13"
}
}
fun box(): String {
return foo(false)
}
@@ -0,0 +1,5 @@
fun box(): String {
if (1 != 0) {
}
return "OK"
}
@@ -0,0 +1,6 @@
val Int.foo: String
get() = "OK"
fun box(): String {
return 1.foo
}
@@ -0,0 +1,7 @@
fun box(): String {
fun rmrf(i: Int) {
if (i > 0) rmrf(i - 1)
}
rmrf(5)
return "OK"
}
@@ -0,0 +1,8 @@
// !LANGUAGE: +ProperIeee754Comparisons +NewInference
fun box(): String {
if (-0.0 < 0.0) return "Fail 1"
if (-0.0 < 0) return "Fail 2"
return "OK"
}
@@ -0,0 +1,6 @@
fun foo(x: String): String {
fun bar(y: String) = x + y
return bar("K")
}
fun box() = foo("O")
@@ -0,0 +1,11 @@
fun foo(x: String): String {
fun bar(y: String): String {
fun qux(z: String): String =
x + y + z
return qux("")
}
return bar("K")
}
fun box(): String =
foo("O")
@@ -0,0 +1,6 @@
fun String.foo(): String {
fun bar(y: String) = this + y
return bar("K")
}
fun box() = "O".foo()
@@ -0,0 +1,11 @@
val Int.getter: Int
get() {
return this@getter
}
fun box(): String {
val i = 1
if (i.getter != 1) return "getter failed"
return "OK"
}
@@ -0,0 +1,7 @@
fun box(): String {
if (!(1 < 2)) {
return "fail"
}
return "OK"
}
@@ -0,0 +1,14 @@
@Target(AnnotationTarget.EXPRESSION)
@Retention(AnnotationRetention.SOURCE)
annotation class Annotation
fun box(): String {
var v = 0
@Annotation v += 1 + 2
if (v != 3) return "fail1"
@Annotation v = 4
if (v != 4) return "fail2"
return "OK"
}
@@ -0,0 +1,18 @@
infix fun Int.rem(other: Int) = 10
infix operator fun Int.minus(other: Int): Int = 20
fun box(): String {
val a = 5 rem 2
if (a != 10) return "fail 1"
val b = 5 minus 3
if (b != 20) return "fail 2"
val a1 = 5.rem(2)
if (a1 != 1) return "fail 3"
val b2 = 5.minus(3)
if (b2 != 2) return "fail 4"
return "OK"
}
@@ -0,0 +1,6 @@
fun box(): String {
if (1 != 0) {
1
}
return "OK"
}
@@ -0,0 +1,22 @@
fun byteArg(b: Byte) {}
fun charArg(c: Char) {}
fun shortArg(s: Short) {}
fun box(): String {
var b = 42.toByte()
b++
++b
byteArg(b)
var c = 'x'
c++
++c
charArg(c)
var s = 239.toShort()
s++
++s
shortArg(s)
return "OK"
}
@@ -0,0 +1,4 @@
fun box(): String {
!true
return "OK"
}
@@ -0,0 +1,7 @@
fun box(): String {
if (1 >= 1.9) return "Fail #1"
if (1.compareTo(1.1) >= 0) return "Fail #2"
if (1.9 <= 1) return "Fail #3"
if (1.1.compareTo(1) <= 0) return "Fail #4"
return "OK"
}
@@ -0,0 +1,15 @@
fun box(): String {
val i: Int = 10000
if (!(i === i)) return "Fail int ==="
if (i !== i) return "Fail int !=="
val j: Long = 123L
if (!(j === j)) return "Fail long ==="
if (j !== j) return "Fail long !=="
val d: Double = 3.14
if (!(d === d)) return "Fail double ==="
if (d !== d) return "Fail double !=="
return "OK"
}
@@ -0,0 +1,5 @@
fun box(): String {
if (3.compareTo(2) != 1) return "Fail #1"
if (5.toByte().compareTo(10.toLong()) >= 0) return "Fail #2"
return "OK"
}
@@ -0,0 +1,15 @@
package demo
fun box() : String {
var res : Boolean = true
res = (res and false)
res = (res or false)
res = (res xor false)
res = (true and false)
res = (true or false)
res = (true xor false)
res = (!true)
res = (true && false)
res = (true || false)
return "OK"
}
@@ -0,0 +1,9 @@
fun box() : String {
var a : Int = -1
if((+a) != -1) return "fail 1"
a = 1
if((+a) != 1) return "fail 2"
if((+-1) != -1) return "fail 3"
if((-+a) != -1) return "fail 4"
return "OK"
}
@@ -0,0 +1,10 @@
// MODULE: lib
// FILE: lib.kt
@PublishedApi
internal fun published() = "OK"
inline fun test() = published()
// MODULE: main(lib)
// FILE: main.kt
fun box() = test()
@@ -0,0 +1,17 @@
fun box(): String {
val a1: Byte = -1
val a2: Short = -1
val a3: Int = -1
val a4: Long = -1
val a5: Double = -1.0
val a6: Float = -1f
if (a1 != (-1).toByte()) return "fail 1"
if (a2 != (-1).toShort()) return "fail 2"
if (a3 != -1) return "fail 3"
if (a4 != -1L) return "fail 4"
if (a5 != -1.0) return "fail 5"
if (a6 != -1f) return "fail 6"
return "OK"
}
@@ -0,0 +1,8 @@
fun box(): String {
val x = 3
when (x) {
1 -> {}
2 -> {}
}
return "OK"
}
@@ -0,0 +1,4 @@
fun box(): String {
return "O" + "K"
}
-12
View File
@@ -1,12 +0,0 @@
/*
* Copyright 2010-2019 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 kotlin
import kotlin.annotation.AnnotationTarget.*
// Exclude declaration or file from lowerings and code generation
@Target(FILE, CLASS, FUNCTION, PROPERTY)
internal annotation class ExcludedFromCodegen
@@ -13,6 +13,9 @@
package kotlin
import kotlin.wasm.internal.WasmInstruction
import kotlin.wasm.internal.wasm_i32_compareTo
/**
* Represents a value which is either `true` or `false`. On the JVM, non-nullable values of this type are
* represented as values of the primitive type `boolean`.
@@ -21,26 +24,34 @@ public class Boolean private constructor() : Comparable<Boolean> {
/**
* Returns the inverse of this boolean.
*/
@WasmInstruction(WasmInstruction.I32_EQZ)
public operator fun not(): Boolean
/**
* Performs a logical `and` operation between this Boolean and the [other] one. Unlike the `&&` operator,
* this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
*/
@WasmInstruction(WasmInstruction.I32_AND)
public infix fun and(other: Boolean): Boolean
/**
* Performs a logical `or` operation between this Boolean and the [other] one. Unlike the `||` operator,
* this function does not perform short-circuit evaluation. Both `this` and [other] will always be evaluated.
*/
@WasmInstruction(WasmInstruction.I32_OR)
public infix fun or(other: Boolean): Boolean
/**
* Performs a logical `xor` operation between this Boolean and the [other] one.
*/
@WasmInstruction(WasmInstruction.I32_XOR)
public infix fun xor(other: Boolean): Boolean
public override fun compareTo(other: Boolean): Int
public override fun compareTo(other: Boolean): Int =
wasm_i32_compareTo(this.asInt(), other.asInt())
@WasmInstruction(WasmInstruction.NOP)
internal fun asInt(): Int
@SinceKotlin("1.3")
companion object {}
@@ -3,16 +3,15 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@file:Suppress(
"NON_ABSTRACT_FUNCTION_WITH_NO_BODY",
"MUST_BE_INITIALIZED_OR_BE_ABSTRACT",
"EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE",
"PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED",
"WRONG_MODIFIER_TARGET"
)
@file:Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE")
package kotlin
import kotlin.wasm.internal.ExcludedFromCodegen
import kotlin.wasm.internal.WasmInstruction
import kotlin.wasm.internal.implementedAsIntrinsic
import kotlin.wasm.internal.wasm_i32_compareTo
/**
* Represents a 16-bit Unicode character.
*
@@ -25,39 +24,56 @@ public class Char private constructor() : Comparable<Char> {
* Returns zero if this value is equal to the specified other value, a negative number if it's less than other,
* or a positive number if it's greater than other.
*/
public override fun compareTo(other: Char): Int
public override inline fun compareTo(other: Char): Int =
wasm_i32_compareTo(this.toInt(), other.toInt())
/** Adds the other Int value to this value resulting a Char. */
public operator fun plus(other: Int): Char
public inline operator fun plus(other: Int): Char =
(this.toInt() + other).toChar()
/** Subtracts the other Char value from this value resulting an Int. */
public operator fun minus(other: Char): Int
public inline operator fun minus(other: Char): Int =
(this.toInt() - other.toInt())
/** Subtracts the other Int value from this value resulting a Char. */
public operator fun minus(other: Int): Char
public inline operator fun minus(other: Int): Char =
(this.toInt() - other).toChar()
/** Increments this value. */
public operator fun inc(): Char
public inline operator fun inc(): Char =
(this.toInt() + 1).toChar()
/** Decrements this value. */
public operator fun dec(): Char
public inline operator fun dec(): Char =
(this.toInt() - 1).toChar()
// /** Creates a range from this value to the specified [other] value. */
// public operator fun rangeTo(other: Char): CharRange
/** Returns the value of this character as a `Byte`. */
public fun toByte(): Byte
public inline fun toByte(): Byte =
this.toInt().toByte()
/** Returns the value of this character as a `Char`. */
public fun toChar(): Char
public inline fun toChar(): Char =
this
/** Returns the value of this character as a `Short`. */
public fun toShort(): Short
public inline fun toShort(): Short =
this.toInt().toShort()
/** Returns the value of this character as a `Int`. */
public fun toInt(): Int
@WasmInstruction(WasmInstruction.NOP)
public fun toInt(): Int =
implementedAsIntrinsic
/** Returns the value of this character as a `Long`. */
public fun toLong(): Long
public inline fun toLong(): Long =
this.toInt().toLong()
/** Returns the value of this character as a `Float`. */
public fun toFloat(): Float
public inline fun toFloat(): Float =
this.toInt().toFloat()
/** Returns the value of this character as a `Double`. */
public fun toDouble(): Double
public inline fun toDouble(): Double =
this.toInt().toDouble()
@ExcludedFromCodegen
companion object {
/**
* The minimum value of a character code unit.
@@ -6,7 +6,7 @@
"NON_MEMBER_FUNCTION_NO_BODY",
"REIFIED_TYPE_PARAMETER_NO_INLINE"
)
@file:ExcludedFromCodegen
@file:kotlin.wasm.internal.ExcludedFromCodegen
package kotlin
File diff suppressed because it is too large Load Diff
@@ -13,19 +13,25 @@
package kotlin
import kotlin.wasm.internal.ExcludedFromCodegen
import kotlin.wasm.internal.WasmImport
/**
* The `String` class represents character strings. All string literals in Kotlin programs, such as `"abc"`, are
* implemented as instances of this class.
*/
public class String : Comparable<String>, CharSequence {
@ExcludedFromCodegen
companion object {}
/**
* Returns a string obtained by concatenating this string with the string representation of the given [other] object.
*/
@WasmImport("runtime", "String_plus")
public operator fun plus(other: Any?): String
public override val length: Int
@WasmImport("runtime", "String_getLength") get
/**
* Returns the character of this string at the specified [index].
@@ -33,9 +39,20 @@ public class String : Comparable<String>, CharSequence {
* If the [index] is out of bounds of this string, throws an [IndexOutOfBoundsException] except in Kotlin/JS
* where the behavior is unspecified.
*/
@WasmImport("runtime", "String_getChar")
public override fun get(index: Int): Char
@ExcludedFromCodegen
public override fun subSequence(startIndex: Int, endIndex: Int): CharSequence
@WasmImport("runtime", "String_compareTo")
public override fun compareTo(other: String): Int
}
@ExcludedFromCodegen
public override fun equals(other: Any?): Boolean
public override fun toString(): String = this
@ExcludedFromCodegen
public override fun hashCode(): Int
}
@@ -0,0 +1,397 @@
/*
* Copyright 2010-2019 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.
*/
@file:ExcludedFromCodegen
@file:Suppress("NON_ABSTRACT_FUNCTION_WITH_NO_BODY", "unused")
package kotlin.wasm.internal
@WasmInstruction(WasmInstruction.UNREACHABLE)
external fun wasm_unreachable(): Nothing
@WasmInstruction(WasmInstruction.I32_EQZ)
external fun wasm_i32_eqz(a: Int): Int
@WasmInstruction(WasmInstruction.I32_EQ)
external fun wasm_i32_eq(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_NE)
external fun wasm_i32_ne(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_LT_S)
external fun wasm_i32_lt_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_LT_U)
external fun wasm_i32_lt_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_GT_S)
external fun wasm_i32_gt_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_GT_U)
external fun wasm_i32_gt_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_LE_S)
external fun wasm_i32_le_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_LE_U)
external fun wasm_i32_le_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_GE_S)
external fun wasm_i32_ge_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_GE_U)
external fun wasm_i32_ge_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I64_EQZ)
external fun wasm_i64_eqz(a: Long): Int
@WasmInstruction(WasmInstruction.I64_EQ)
external fun wasm_i64_eq(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_NE)
external fun wasm_i64_ne(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_LT_S)
external fun wasm_i64_lt_s(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_LT_U)
external fun wasm_i64_lt_u(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_GT_S)
external fun wasm_i64_gt_s(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_GT_U)
external fun wasm_i64_gt_u(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_LE_S)
external fun wasm_i64_le_s(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_LE_U)
external fun wasm_i64_le_u(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_GE_S)
external fun wasm_i64_ge_s(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.I64_GE_U)
external fun wasm_i64_ge_u(a: Long, b: Long): Int
@WasmInstruction(WasmInstruction.F32_EQ)
external fun wasm_f32_eq(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F32_NE)
external fun wasm_f32_ne(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F32_LT)
external fun wasm_f32_lt(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F32_GT)
external fun wasm_f32_gt(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F32_LE)
external fun wasm_f32_le(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F32_GE)
external fun wasm_f32_ge(a: Float, b: Float): Int
@WasmInstruction(WasmInstruction.F64_EQ)
external fun wasm_f64_eq(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.F64_NE)
external fun wasm_f64_ne(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.F64_LT)
external fun wasm_f64_lt(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.F64_GT)
external fun wasm_f64_gt(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.F64_LE)
external fun wasm_f64_le(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.F64_GE)
external fun wasm_f64_ge(a: Double, b: Double): Int
@WasmInstruction(WasmInstruction.I32_CLZ)
external fun wasm_i32_clz(a: Int): Int
@WasmInstruction(WasmInstruction.I32_CTZ)
external fun wasm_i32_ctz(a: Int): Int
@WasmInstruction(WasmInstruction.I32_POPCNT)
external fun wasm_i32_popcnt(a: Int): Int
@WasmInstruction(WasmInstruction.I32_ADD)
external fun wasm_i32_add(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_SUB)
external fun wasm_i32_sub(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_MUL)
external fun wasm_i32_mul(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_DIV_S)
external fun wasm_i32_div_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_DIV_U)
external fun wasm_i32_div_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_REM_S)
external fun wasm_i32_rem_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_REM_U)
external fun wasm_i32_rem_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_AND)
external fun wasm_i32_and(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_OR)
external fun wasm_i32_or(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_XOR)
external fun wasm_i32_xor(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_SHL)
external fun wasm_i32_shl(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_SHR_S)
external fun wasm_i32_shr_s(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_SHR_U)
external fun wasm_i32_shr_u(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_ROTL)
external fun wasm_i32_rotl(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I32_ROTR)
external fun wasm_i32_rotr(a: Int, b: Int): Int
@WasmInstruction(WasmInstruction.I64_CLZ)
external fun wasm_i64_clz(a: Long): Long
@WasmInstruction(WasmInstruction.I64_CTZ)
external fun wasm_i64_ctz(a: Long): Long
@WasmInstruction(WasmInstruction.I64_POPCNT)
external fun wasm_i64_popcnt(a: Long): Long
@WasmInstruction(WasmInstruction.I64_ADD)
external fun wasm_i64_add(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_SUB)
external fun wasm_i64_sub(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_MUL)
external fun wasm_i64_mul(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_DIV_S)
external fun wasm_i64_div_s(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_DIV_U)
external fun wasm_i64_div_u(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_REM_S)
external fun wasm_i64_rem_s(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_REM_U)
external fun wasm_i64_rem_u(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_AND)
external fun wasm_i64_and(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_OR)
external fun wasm_i64_or(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_XOR)
external fun wasm_i64_xor(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_SHL)
external fun wasm_i64_shl(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_SHR_S)
external fun wasm_i64_shr_s(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_SHR_U)
external fun wasm_i64_shr_u(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_ROTL)
external fun wasm_i64_rotl(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.I64_ROTR)
external fun wasm_i64_rotr(a: Long, b: Long): Long
@WasmInstruction(WasmInstruction.F32_ABS)
external fun wasm_f32_abs(a: Float): Float
@WasmInstruction(WasmInstruction.F32_NEG)
external fun wasm_f32_neg(a: Float): Float
@WasmInstruction(WasmInstruction.F32_CEIL)
external fun wasm_f32_ceil(a: Float): Float
@WasmInstruction(WasmInstruction.F32_FLOOR)
external fun wasm_f32_floor(a: Float): Float
@WasmInstruction(WasmInstruction.F32_TRUNC)
external fun wasm_f32_trunc(a: Float): Float
@WasmInstruction(WasmInstruction.F32_NEAREST)
external fun wasm_f32_nearest(a: Float): Float
@WasmInstruction(WasmInstruction.F32_SQRT)
external fun wasm_f32_sqrt(a: Float): Float
@WasmInstruction(WasmInstruction.F32_ADD)
external fun wasm_f32_add(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_SUB)
external fun wasm_f32_sub(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_MUL)
external fun wasm_f32_mul(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_DIV)
external fun wasm_f32_div(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_FMIN)
external fun wasm_f32_fmin(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_FMAX)
external fun wasm_f32_fmax(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F32_COPYSIGN)
external fun wasm_f32_copysign(a: Float, b: Float): Float
@WasmInstruction(WasmInstruction.F64_ABS)
external fun wasm_f64_abs(a: Double): Double
@WasmInstruction(WasmInstruction.F64_NEG)
external fun wasm_f64_neg(a: Double): Double
@WasmInstruction(WasmInstruction.F64_CEIL)
external fun wasm_f64_ceil(a: Double): Double
@WasmInstruction(WasmInstruction.F64_FLOOR)
external fun wasm_f64_floor(a: Double): Double
@WasmInstruction(WasmInstruction.F64_TRUNC)
external fun wasm_f64_trunc(a: Double): Double
@WasmInstruction(WasmInstruction.F64_NEAREST)
external fun wasm_f64_nearest(a: Double): Double
@WasmInstruction(WasmInstruction.F64_SQRT)
external fun wasm_f64_sqrt(a: Double): Double
@WasmInstruction(WasmInstruction.F64_ADD)
external fun wasm_f64_add(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_SUB)
external fun wasm_f64_sub(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_MUL)
external fun wasm_f64_mul(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_DIV)
external fun wasm_f64_div(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_FMIN)
external fun wasm_f64_fmin(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_FMAX)
external fun wasm_f64_fmax(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.F64_COPYSIGN)
external fun wasm_f64_copysign(a: Double, b: Double): Double
@WasmInstruction(WasmInstruction.I32_WRAP_I64)
external fun wasm_i32_wrap_i64(a: Long): Int
@WasmInstruction(WasmInstruction.I32_TRUNC_F32_S)
external fun wasm_i32_trunc_f32_s(a: Float): Int
@WasmInstruction(WasmInstruction.I32_TRUNC_F32_U)
external fun wasm_i32_trunc_f32_u(a: Float): Int
@WasmInstruction(WasmInstruction.I32_TRUNC_F64_S)
external fun wasm_i32_trunc_f64_s(a: Double): Int
@WasmInstruction(WasmInstruction.I32_TRUNC_F64_U)
external fun wasm_i32_trunc_f64_u(a: Double): Int
@WasmInstruction(WasmInstruction.I64_EXTEND_I32_S)
external fun wasm_i64_extend_i32_s(a: Int): Long
@WasmInstruction(WasmInstruction.I64_EXTEND_I32_U)
external fun wasm_i64_extend_i32_u(a: Int): Long
@WasmInstruction(WasmInstruction.I64_TRUNC_F32_S)
external fun wasm_i64_trunc_f32_s(a: Float): Long
@WasmInstruction(WasmInstruction.I64_TRUNC_F32_U)
external fun wasm_i64_trunc_f32_u(a: Float): Long
@WasmInstruction(WasmInstruction.I64_TRUNC_F64_S)
external fun wasm_i64_trunc_f64_s(a: Double): Long
@WasmInstruction(WasmInstruction.I64_TRUNC_F64_U)
external fun wasm_i64_trunc_f64_u(a: Double): Long
@WasmInstruction(WasmInstruction.F32_CONVERT_I32_S)
external fun wasm_f32_convert_i32_s(a: Int): Float
@WasmInstruction(WasmInstruction.F32_CONVERT_I32_U)
external fun wasm_f32_convert_i32_u(a: Int): Float
@WasmInstruction(WasmInstruction.F32_CONVERT_I64_S)
external fun wasm_f32_convert_i64_s(a: Long): Float
@WasmInstruction(WasmInstruction.F32_CONVERT_I64_U)
external fun wasm_f32_convert_i64_u(a: Long): Float
@WasmInstruction(WasmInstruction.F32_DEMOTE_F64)
external fun wasm_f32_demote_f64(a: Double): Float
@WasmInstruction(WasmInstruction.F64_CONVERT_I32_S)
external fun wasm_f64_convert_i32_s(a: Int): Double
@WasmInstruction(WasmInstruction.F64_CONVERT_I32_U)
external fun wasm_f64_convert_i32_u(a: Int): Double
@WasmInstruction(WasmInstruction.F64_CONVERT_I64_S)
external fun wasm_f64_convert_i64_s(a: Long): Double
@WasmInstruction(WasmInstruction.F64_CONVERT_I64_U)
external fun wasm_f64_convert_i64_u(a: Long): Double
@WasmInstruction(WasmInstruction.F64_PROMOTE_F32)
external fun wasm_f64_promote_f32(a: Float): Double
@WasmInstruction(WasmInstruction.I32_REINTERPRET_F32)
external fun wasm_i32_reinterpret_f32(a: Float): Int
@WasmInstruction(WasmInstruction.I64_REINTERPRET_F64)
external fun wasm_i64_reinterpret_f64(a: Double): Long
@WasmInstruction(WasmInstruction.F32_REINTERPRET_I32)
external fun wasm_f32_reinterpret_i32(a: Int): Float
@WasmInstruction(WasmInstruction.F32_CONST_NAN)
external fun wasm_f32_const_nan(): Float
@WasmInstruction(WasmInstruction.F32_CONST_PLUS_INF)
external fun wasm_f32_const_plus_inf(): Float
@WasmInstruction(WasmInstruction.F32_CONST_MINUS_INF)
external fun wasm_f32_const_minus_inf(): Float
@WasmInstruction(WasmInstruction.F64_CONST_NAN)
external fun wasm_f64_const_nan(): Double
@WasmInstruction(WasmInstruction.F64_CONST_PLUS_INF)
external fun wasm_f64_const_plus_inf(): Float
@WasmInstruction(WasmInstruction.F64_CONST_MINUS_INF)
external fun wasm_f64_const_minus_inf(): Float
@@ -0,0 +1,20 @@
/*
* Copyright 2010-2019 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 kotlin.wasm.internal
// `compareTo(x, y)` implemented as `(x >= y) - (x <= y)`
fun wasm_i32_compareTo(x: Int, y: Int): Int =
wasm_i32_ge_s(x, y) - wasm_i32_le_s(x, y)
fun wasm_i64_compareTo(x: Long, y: Long): Int =
wasm_i64_ge_s(x, y) - wasm_i64_le_s(x, y)
fun wasm_f32_compareTo(x: Float, y: Float): Int =
wasm_f32_ge(x, y) - wasm_f32_le(x, y)
fun wasm_f64_compareTo(x: Double, y: Double): Int =
wasm_f64_ge(x, y) - wasm_f64_le(x, y)

Some files were not shown because too many files have changed in this diff Show More