From bfd0f21e9d2137b40fc9229bed66642fd2c1d05d Mon Sep 17 00:00:00 2001 From: Svyatoslav Kuzmich Date: Mon, 27 Apr 2020 14:39:20 +0300 Subject: [PATCH] [Wasm] Major compiler and stdlib update --- build.gradle.kts | 1 + .../ir/FirBlackBoxCodegenTestGenerated.java | 5 + .../jetbrains/kotlin/backend/common/ir/Ir.kt | 3 + .../lower/InlineClassDeclarationLowering.kt | 12 +- .../org/jetbrains/kotlin/ir/backend/js/Dce.kt | 2 +- .../ir/backend/js/JsCommonBackendContext.kt | 25 + .../ir/backend/js/JsIrBackendContext.kt | 11 +- .../kotlin/ir/backend/js/JsLoweringPhases.kt | 9 +- .../backend/js/lower/AutoboxingTransformer.kt | 175 +- .../backend/js/lower/BridgesConstruction.kt | 63 +- .../ir/backend/js/lower/EnumClassLowering.kt | 74 +- .../js/lower/ExternalEnumUsagesLowering.kt | 60 + .../backend/js/lower/JsBridgesConstruction.kt | 16 + .../backend/js/lower/StaticMembersLowering.kt | 5 +- .../backend/js/lower/TypeOperatorLowering.kt | 5 +- .../ir/backend/js/lower/VarargLowering.kt | 3 +- .../coroutines/JsSuspendFunctionsLowering.kt | 8 + .../lower/coroutines/StateMachineBuilder.kt | 7 +- .../lower/coroutines/SuspendLoweringUtils.kt | 6 - .../irToJs/JsIntrinsicTransformers.kt | 6 +- .../kotlin/ir/backend/js/utils/IrTypeUtils.kt | 6 +- .../backend/js/utils/JsInlineClassesUtils.kt | 33 + .../kotlin/ir/backend/js/utils/NameTables.kt | 8 +- .../kotlin/ir/backend/js/utils/misc.kt | 12 +- compiler/ir/backend.wasm/build.gradle.kts | 1 + .../kotlin/backend/wasm/WasmBackendContext.kt | 62 +- .../kotlin/backend/wasm/WasmLoweringPhases.kt | 293 +- .../kotlin/backend/wasm/WasmSymbols.kt | 89 +- .../kotlin/backend/wasm/ast/WasmAstToWat.kt | 66 - .../backend/wasm/ast/WasmDeclarations.kt | 55 - .../backend/wasm/ast/WasmInstructions.kt | 65 - .../kotlin/backend/wasm/ast/WasmTypes.kt | 15 - .../backend/wasm/codegen/BaseTransformer.kt | 16 - .../wasm/codegen/DeclarationTransformer.kt | 123 - .../wasm/codegen/ExpressionTransformer.kt | 204 -- .../backend/wasm/codegen/ModuleTransformer.kt | 82 - .../kotlin/backend/wasm/codegen/NameTable.kt | 64 - .../wasm/codegen/StatementTransformer.kt | 35 - .../backend/wasm/codegen/TypeTransformer.kt | 27 - .../wasm/codegen/WasmCodegenContext.kt | 29 - .../jetbrains/kotlin/backend/wasm/compiler.kt | 29 +- .../backend/wasm/ir2wasm/BodyGenerator.kt | 492 ++++ .../kotlin/backend/wasm/ir2wasm/ClassInfo.kt | 113 + .../backend/wasm/ir2wasm/ConstantData.kt | 70 + .../wasm/ir2wasm/DeclarationGenerator.kt | 320 +++ .../kotlin/backend/wasm/ir2wasm/JsHelpers.kt | 21 + .../backend/wasm/ir2wasm/TypeTransformer.kt | 118 + .../wasm/ir2wasm/WasmBaseCodegenContext.kt | 45 + .../ir2wasm/WasmCompiledModuleFragment.kt | 207 ++ .../ir2wasm/WasmFunctionCodegenContext.kt | 28 + .../ir2wasm/WasmFunctionCodegenContextImpl.kt | 61 + .../wasm/ir2wasm/WasmModuleCodegenContext.kt | 34 + .../ir2wasm/WasmModuleCodegenContextImpl.kt | 169 ++ .../ir2wasm/WasmModuleFragmentGenerator.kt | 41 + .../wasm/lower/BlockDecomposerLowering.kt | 14 - .../backend/wasm/lower/BuiltInsLowering.kt | 121 +- ...eVirtualDispatchReceiverParametersTypes.kt | 91 + .../lower/ExcludeDeclarationsFromCodegen.kt | 103 +- .../wasm/lower/FieldInitializersLowering.kt | 53 + .../wasm/lower/GenericReturnTypeLowering.kt | 86 + .../SimpleStringConcatenationLowering.kt | 91 + .../VirtualDispatchReceiverExtraction.kt | 68 + .../wasm/lower/WasmBridgesConstruction.kt | 55 + .../lower/WasmCallableReferenceLowering.kt | 314 +++ .../wasm/lower/WasmNullCoercionLowering.kt | 34 + .../wasm/lower/WasmSharedVariablesManager.kt | 220 ++ .../wasm/lower/WasmThrowDebugLowering.kt | 37 + .../wasm/lower/WasmTypeOperatorLowering.kt | 287 ++ .../lower/WasmVarargExpressionLowering.kt | 100 + .../kotlin/backend/wasm/utils/Annotations.kt | 20 +- .../wasm/utils/WasmInlineClassesUtils.kt | 43 + .../org/jetbrains/kotlin/ir/util/IrUtils.kt | 11 +- .../functions/typeParameterAsUpperBound.kt | 9 + .../codegen/BlackBoxCodegenTestGenerated.java | 5 + .../LightAnalysisModeTestGenerated.java | 5 + .../ir/IrBlackBoxCodegenTestGenerated.java | 5 + js/js.tests/build.gradle.kts | 39 +- .../jetbrains/kotlin/js/test/BasicBoxTest.kt | 11 + .../kotlin/js/test/BasicWasmBoxTest.kt | 65 +- .../kotlin/js/test/engines/SpiderMonkey.kt | 2 +- .../IrJsCodegenBoxES6TestGenerated.java | 5 + .../IrJsCodegenBoxTestGenerated.java | 5 + .../semantics/JsCodegenBoxTestGenerated.java | 5 + libraries/stdlib/wasm/build.gradle.kts | 59 +- libraries/stdlib/wasm/builtins/README.md | 6 - .../wasm/builtins/{native => }/kotlin/Any.kt | 24 +- .../builtins/{native => }/kotlin/Array.kt | 37 +- .../stdlib/wasm/builtins/kotlin/Arrays.kt | 265 ++ .../builtins/{native => }/kotlin/Boolean.kt | 57 +- .../wasm/builtins/{native => }/kotlin/Char.kt | 44 +- libraries/stdlib/wasm/builtins/kotlin/Enum.kt | 20 + .../builtins/{native => }/kotlin/Library.kt | 38 +- .../builtins/{native => }/kotlin/Nothing.kt | 3 + .../{native => }/kotlin/Primitives.kt | 478 ++-- .../stdlib/wasm/builtins/kotlin/String.kt | 72 + .../wasm/builtins/native/kotlin/Annotation.kt | 13 - .../wasm/builtins/native/kotlin/Arrays.kt | 313 --- .../builtins/native/kotlin/CharSequence.kt | 46 - .../builtins/native/kotlin/Collections.kt | 438 --- .../wasm/builtins/native/kotlin/Comparable.kt | 29 - .../wasm/builtins/native/kotlin/Enum.kt | 58 - .../wasm/builtins/native/kotlin/Iterator.kt | 102 - .../wasm/builtins/native/kotlin/Number.kt | 58 - .../wasm/builtins/native/kotlin/String.kt | 58 - .../wasm/builtins/native/kotlin/Throwable.kt | 28 - .../wasm/builtins/src/kotlin/Annotations.kt | 152 -- .../wasm/builtins/src/kotlin/Function.kt | 24 - .../wasm/builtins/src/kotlin/Iterators.kt | 73 - .../stdlib/wasm/builtins/src/kotlin/Unit.kt | 24 - .../src/kotlin/annotation/Annotations.kt | 103 - .../kotlin/internal/InternalAnnotations.kt | 35 - .../src/kotlin/reflect/KAnnotatedElement.kt | 18 - .../builtins/src/kotlin/reflect/KCallable.kt | 85 - .../builtins/src/kotlin/reflect/KClass.kt | 144 - .../src/kotlin/reflect/KClassifier.kt | 26 - .../kotlin/reflect/KDeclarationContainer.kt | 28 - .../builtins/src/kotlin/reflect/KFunction.kt | 49 - .../builtins/src/kotlin/reflect/KParameter.kt | 80 - .../builtins/src/kotlin/reflect/KProperty.kt | 258 -- .../wasm/builtins/src/kotlin/reflect/KType.kt | 104 - .../src/kotlin/reflect/KTypeParameter.kt | 40 - .../builtins/src/kotlin/reflect/KVariance.kt | 45 - .../src/kotlin/reflect/KVisibility.kt | 50 - .../stdlib/wasm/internal/WasmInstructions.kt | 397 --- libraries/stdlib/wasm/internal/WasmMath.kt | 20 - .../internal/DefaultConstructorMarker.kt} | 10 +- .../kotlin/wasm/internal/Function0.kt | 341 +++ .../internal/kotlin/wasm/internal/JsArray.kt | 153 ++ .../internal/kotlin/wasm/internal/Runtime.kt | 50 + .../kotlin/wasm/internal/ThrowHelpers.kt | 27 + .../internal/kotlin/wasm/internal/TypeInfo.kt | 83 + .../kotlin/wasm/internal/WasmAnnotations.kt | 46 + .../kotlin/wasm/internal/WasmInstructions.kt | 22 + .../internal/kotlin/wasm/internal/WasmMath.kt | 18 + .../internal/kotlin/wasm/internal/WasmOp.kt | 514 ++++ libraries/stdlib/wasm/runtime/runtime.js | 55 + libraries/stdlib/wasm/runtime/runtime.kt | 10 - libraries/stdlib/wasm/runtime/testHelpers.kt | 59 - .../stdlib/wasm/runtime/wasmAnnotations.kt | 173 -- .../stdlib/wasm/src/generated/_ArraysWasm.kt | 2408 +++++++++++++++++ .../wasm/src/generated/_CollectionsWasm.kt | 30 + .../wasm/src/generated/_ComparisonsWasm.kt | 445 +++ .../stdlib/wasm/src/generated/_StringsWasm.kt | 23 + .../stdlib/wasm/src/generated/_UArraysWasm.kt | 127 + .../stdlib/wasm/src/kotlin/Exceptions.kt | 95 + libraries/stdlib/wasm/src/kotlin/Kotlin.kt | 107 + libraries/stdlib/wasm/src/kotlin/Math.kt | 990 +++++++ libraries/stdlib/wasm/src/kotlin/Sequences.kt | 12 + libraries/stdlib/wasm/src/kotlin/Text.kt | 402 +++ .../collections/AbstractMutableCollection.kt | 32 + .../kotlin/collections/AbstractMutableList.kt | 45 + .../kotlin/collections/AbstractMutableMap.kt | 42 + .../kotlin/collections/AbstractMutableSet.kt | 31 + .../wasm/src/kotlin/collections/ArrayList.kt | 45 + .../wasm/src/kotlin/collections/Arrays.kt | 105 + .../src/kotlin/collections/Collections.kt | 111 + .../wasm/src/kotlin/collections/HashMap.kt | 31 + .../wasm/src/kotlin/collections/HashSet.kt | 30 + .../src/kotlin/collections/LinkedHashMap.kt | 31 + .../src/kotlin/collections/LinkedHashSet.kt | 30 + .../wasm/src/kotlin/collections/Maps.kt | 20 + .../wasm/src/kotlin/coroutines/Coroutines.kt | 21 + .../kotlin/coroutines/CoroutinesIntrinsics.kt | 76 + .../cancellation/CancellationException.kt | 15 + libraries/stdlib/wasm/src/kotlin/io.kt | 31 + .../stdlib/wasm/src/kotlin/random/Random.kt | 9 + .../wasm/src/kotlin/reflect/KCallable.kt | 23 + .../stdlib/wasm/src/kotlin/reflect/KClass.kt | 35 + .../wasm/src/kotlin/reflect/KClasses.kt | 8 + .../wasm/src/kotlin/reflect/KFunction.kt | 11 + .../wasm/src/kotlin/reflect/KProperty.kt | 119 + .../stdlib/wasm/src/kotlin/reflect/KType.kt | 51 + .../stdlib/wasm/src/kotlin/text/Appendable.kt | 37 + .../kotlin/text/CharacterCodingException.kt | 13 + .../wasm/src/kotlin/text/StringBuilder.kt | 387 +++ .../wasm/src/kotlin/throwableExtensions.kt | 45 + .../stdlib/wasm/src/kotlin/time/Duration.kt | 9 + .../wasm/src/kotlin/time/DurationUnit.kt | 50 + .../wasm/src/kotlin/time/TimeSources.kt | 11 + .../stdlib/wasm/src/kotlin/util/Numbers.kt | 138 + .../wasm/stubs/experimentalPackageStub.kt | 8 + libraries/stdlib/wasm/stubs/testHelpers.kt | 22 + libraries/stdlib/wasm/stubs/testHelpers2.kt | 17 + .../src/generators/GenerateStandardLib.kt | 2 + .../kotlin-stdlib-gen/src/templates/Arrays.kt | 24 + .../src/templates/dsl/CommonTypes.kt | 6 +- .../src/templates/dsl/MemberBuilder.kt | 2 +- wasm/wasm.ir/build.gradle.kts | 2 +- .../jetbrains/kotlin/wasm/ir/Declarations.kt | 2 +- .../src/org/jetbrains/kotlin/wasm/ir/Types.kt | 3 +- .../kotlin/wasm/ir/WasmExpressionBuilder.kt | 8 +- .../kotlin/wasm/ir/WasmIrExpressionBuilder.kt | 2 +- .../{BinaryToAst.kt => WasmBinaryToIR.kt} | 4 +- .../{WasmAstToBinary.kt => WasmIrToBinary.kt} | 2 +- .../{WasmAstToWat.kt => WasmIrToText.kt} | 2 +- .../kotlin/wasm/ir/SpecTestRunner.kt | 27 +- 196 files changed, 12635 insertions(+), 4774 deletions(-) create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ExternalEnumUsagesLowering.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt create mode 100644 compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsInlineClassesUtils.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmAstToWat.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmDeclarations.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmInstructions.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmTypes.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/BaseTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/DeclarationTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ExpressionTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ModuleTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/NameTable.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/StatementTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/TypeTransformer.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/WasmCodegenContext.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/JsHelpers.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContextImpl.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt delete mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BlockDecomposerLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/EraseVirtualDispatchReceiverParametersTypes.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/FieldInitializersLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/SimpleStringConcatenationLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/VirtualDispatchReceiverExtraction.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmBridgesConstruction.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmCallableReferenceLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmThrowDebugLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt create mode 100644 compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/WasmInlineClassesUtils.kt create mode 100644 compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt delete mode 100644 libraries/stdlib/wasm/builtins/README.md rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Any.kt (81%) rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Array.kt (65%) create mode 100644 libraries/stdlib/wasm/builtins/kotlin/Arrays.kt rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Boolean.kt (51%) rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Char.kt (82%) create mode 100644 libraries/stdlib/wasm/builtins/kotlin/Enum.kt rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Library.kt (56%) rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Nothing.kt (92%) rename libraries/stdlib/wasm/builtins/{native => }/kotlin/Primitives.kt (86%) create mode 100644 libraries/stdlib/wasm/builtins/kotlin/String.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Annotation.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Arrays.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/CharSequence.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Collections.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Comparable.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Enum.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Iterator.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Number.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/String.kt delete mode 100644 libraries/stdlib/wasm/builtins/native/kotlin/Throwable.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/Annotations.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/Function.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/Iterators.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/Unit.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/annotation/Annotations.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/internal/InternalAnnotations.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KAnnotatedElement.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KCallable.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClass.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClassifier.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KDeclarationContainer.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KFunction.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KParameter.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KProperty.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KType.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KTypeParameter.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVariance.kt delete mode 100644 libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVisibility.kt delete mode 100644 libraries/stdlib/wasm/internal/WasmInstructions.kt delete mode 100644 libraries/stdlib/wasm/internal/WasmMath.kt rename libraries/stdlib/wasm/{runtime/stubsKotlinRanges.kt => internal/kotlin/wasm/internal/DefaultConstructorMarker.kt} (51%) create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/Function0.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/JsArray.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmAnnotations.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmMath.kt create mode 100644 libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmOp.kt delete mode 100644 libraries/stdlib/wasm/runtime/runtime.kt delete mode 100644 libraries/stdlib/wasm/runtime/testHelpers.kt delete mode 100644 libraries/stdlib/wasm/runtime/wasmAnnotations.kt create mode 100644 libraries/stdlib/wasm/src/generated/_ArraysWasm.kt create mode 100644 libraries/stdlib/wasm/src/generated/_CollectionsWasm.kt create mode 100644 libraries/stdlib/wasm/src/generated/_ComparisonsWasm.kt create mode 100644 libraries/stdlib/wasm/src/generated/_StringsWasm.kt create mode 100644 libraries/stdlib/wasm/src/generated/_UArraysWasm.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/Exceptions.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/Kotlin.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/Math.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/Sequences.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/Text.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableCollection.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableList.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableMap.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableSet.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/ArrayList.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/Arrays.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/Collections.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/HashMap.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/HashSet.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/LinkedHashMap.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/LinkedHashSet.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/collections/Maps.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/coroutines/Coroutines.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/coroutines/CoroutinesIntrinsics.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/coroutines/cancellation/CancellationException.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/io.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/random/Random.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KCallable.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KClasses.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KFunction.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KProperty.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/reflect/KType.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/text/Appendable.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/text/CharacterCodingException.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/text/StringBuilder.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/throwableExtensions.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/time/Duration.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/time/DurationUnit.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt create mode 100644 libraries/stdlib/wasm/src/kotlin/util/Numbers.kt create mode 100644 libraries/stdlib/wasm/stubs/experimentalPackageStub.kt create mode 100644 libraries/stdlib/wasm/stubs/testHelpers.kt create mode 100644 libraries/stdlib/wasm/stubs/testHelpers2.kt rename wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/{BinaryToAst.kt => WasmBinaryToIR.kt} (99%) rename wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/{WasmAstToBinary.kt => WasmIrToBinary.kt} (99%) rename wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/{WasmAstToWat.kt => WasmIrToText.kt} (99%) diff --git a/build.gradle.kts b/build.gradle.kts index f962b3ce496..6be3bbe8d88 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -29,6 +29,7 @@ buildscript { classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.20") classpath(kotlin("gradle-plugin", bootstrapKotlinVersion)) + classpath(kotlin("serialization", bootstrapKotlinVersion)) classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17") classpath("org.jfrog.buildinfo:build-info-extractor-gradle:4.17.2") } diff --git a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java index 8c37ec6734e..c5e0a449473 100644 --- a/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests/org/jetbrains/kotlin/codegen/ir/FirBlackBoxCodegenTestGenerated.java @@ -12415,6 +12415,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt index c83e1029eec..95889632606 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/ir/Ir.kt @@ -295,6 +295,9 @@ abstract class Symbols(val context: T, irBuiltIns: abstract val throwKotlinNothingValueException: IrSimpleFunctionSymbol + open val throwISE: IrSimpleFunctionSymbol + get() = error("throwISE is not implemented") + abstract val stringBuilder: IrClassSymbol abstract val defaultConstructorMarker: IrClassSymbol diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt index 9a2ad00cd32..e50f65d456c 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/InlineClassDeclarationLowering.kt @@ -271,9 +271,13 @@ class InlineClassLowering(val context: CommonBackendContext) { } } - private fun Name.toInlineClassImplementationName() = when { - isSpecial -> Name.special(asString() + INLINE_CLASS_IMPL_SUFFIX) - else -> Name.identifier(asString() + INLINE_CLASS_IMPL_SUFFIX) + private fun IrFunction.toInlineClassImplementationName(): Name { + val klass = this.parentAsClass!! + val newName = klass.name.asString() + "__" + name.asString() + INLINE_CLASS_IMPL_SUFFIX + return when { + name.isSpecial -> Name.special("<" + newName + ">") + else -> Name.identifier(newName) + } } private fun collectTypeParameters(declaration: IrTypeParametersContainer): List { @@ -292,7 +296,7 @@ class InlineClassLowering(val context: CommonBackendContext) { private fun createStaticBodilessMethod(function: IrFunction): IrSimpleFunction = context.irFactory.createStaticFunctionWithReceivers( function.parent, - function.name.toInlineClassImplementationName(), + function.toInlineClassImplementationName(), function, typeParametersFromContext = collectTypeParameters(function.parentAsClass) ) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt index 296c4c85a3c..7b4e4906b2d 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/Dce.kt @@ -284,7 +284,7 @@ fun usefulDeclarations(roots: Iterable, context: JsIrBackendConte when (expression.symbol) { context.intrinsics.jsBoxIntrinsic -> { - val inlineClass = expression.getTypeArgument(0)!!.getInlinedClass()!! + val inlineClass = context.inlineClassesUtils.getInlinedClass(expression.getTypeArgument(0)!!)!! val constructor = inlineClass.declarations.filterIsInstance().single { it.isPrimary } constructor.enqueue("intrinsic: jsBoxIntrinsic") } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsCommonBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsCommonBackendContext.kt index 22b3ca58aec..8ce110f8881 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsCommonBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsCommonBackendContext.kt @@ -6,10 +6,35 @@ package org.jetbrains.kotlin.ir.backend.js import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides +import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType interface JsCommonBackendContext : CommonBackendContext { override val mapping: JsMapping + val inlineClassesUtils: InlineClassesUtils + val es6mode: Boolean get() = false } + +interface InlineClassesUtils { + fun isTypeInlined(type: IrType): Boolean + + fun shouldValueParameterBeBoxed(parameter: IrValueParameter): Boolean { + val function = parameter.parent as? IrSimpleFunction ?: return false + val klass = function.parent as? IrClass ?: return false + if (!isClassInlineLike(klass)) return false + return parameter.isDispatchReceiver && function.isOverridableOrOverrides + } + + fun getInlinedClass(type: IrType): IrClass? + + fun isClassInlineLike(klass: IrClass): Boolean + + val boxIntrinsic: IrSimpleFunctionSymbol + val unboxIntrinsic: IrSimpleFunctionSymbol +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt index 1c42307b0ab..c91e5eaa544 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsIrBackendContext.kt @@ -16,9 +16,8 @@ import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport -import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames +import org.jetbrains.kotlin.ir.backend.js.utils.* import org.jetbrains.kotlin.ir.builders.declarations.addFunction -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl @@ -123,6 +122,9 @@ class JsIrBackendContext( get() = testContainerFuns override val mapping = JsMapping() + + override val inlineClassesUtils = JsInlineClassesUtils(this) + val innerClassesSupport = JsInnerClassesSupport(mapping, irFactory) companion object { @@ -196,6 +198,9 @@ class JsIrBackendContext( override val defaultConstructorMarker = symbolTable.referenceClass(context.getJsInternalClass("DefaultConstructorMarker")) + override val throwISE: IrSimpleFunctionSymbol = + symbolTable.referenceSimpleFunction(getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_ISE"))).single()) + override val stringBuilder get() = TODO("not implemented") override val copyRangeTo: Map @@ -226,7 +231,7 @@ class JsIrBackendContext( } override fun unfoldInlineClassType(irType: IrType): IrType? { - return irType.getInlinedClass()?.typeWith() + return inlineClassesUtils.getInlinedClass(irType)?.typeWith() } override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 3ea8f0c8a23..c76db464522 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -314,6 +314,12 @@ private val enumUsageLoweringPhase = makeBodyLoweringPhase( prerequisite = setOf(enumEntryCreateGetInstancesFunsLoweringPhase) ) +private val externalEnumUsageLoweringPhase = makeBodyLoweringPhase( + ::ExternalEnumUsagesLowering, + name = "ExternalEnumUsagesLowering", + description = "Replace external enum entry accesses with field accesses" +) + private val enumEntryRemovalLoweringPhase = makeDeclarationTransformerPhase( ::EnumClassRemoveEntriesLowering, name = "EnumEntryRemovalLowering", @@ -535,7 +541,7 @@ private val errorDeclarationLoweringPhase = makeDeclarationTransformerPhase( ) private val bridgesConstructionPhase = makeDeclarationTransformerPhase( - ::BridgesConstruction, + ::JsBridgesConstruction, name = "BridgesConstruction", description = "Generate bridges", prerequisite = setOf(suspendFunctionsLoweringPhase) @@ -712,6 +718,7 @@ val loweringList = listOf( enumEntryCreateGetInstancesFunsLoweringPhase, enumSyntheticFunsLoweringPhase, enumUsageLoweringPhase, + externalEnumUsageLoweringPhase, enumEntryRemovalLoweringPhase, suspendFunctionsLoweringPhase, propertyReferenceLoweringPhase, diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt index 8bd87b0347f..86914f662a9 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/AutoboxingTransformer.kt @@ -7,20 +7,26 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.backend.common.lower.AbstractValueUsageTransformer -import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass -import org.jetbrains.kotlin.ir.backend.js.utils.isInlined import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget -import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.util.isPrimitiveArray +import org.jetbrains.kotlin.ir.util.patchDeclarationParents +import org.jetbrains.kotlin.ir.util.render // Copied and adapted from Kotlin/Native -class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsageTransformer(context.irBuiltIns), BodyLoweringPass { +abstract class AbstractValueUsageLowering(val context: JsCommonBackendContext) : AbstractValueUsageTransformer(context.irBuiltIns), + BodyLoweringPass { + + val icUtils = context.inlineClassesUtils override fun lower(irBody: IrBody, container: IrDeclaration) { // TODO workaround for callable references @@ -35,36 +41,27 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag irBody.patchDeclarationParents(container as? IrDeclarationParent ?: container.parent) } - private tailrec fun IrExpression.isGetUnit(): Boolean = - when(this) { - is IrContainerExpression -> - when (val lastStmt = this.statements.lastOrNull()) { - is IrExpression -> lastStmt.isGetUnit() - else -> false - } - is IrGetObjectValue -> - this.symbol == irBuiltIns.unitClass - - else -> false - } + abstract fun IrExpression.useExpressionAsType(actualType: IrType, expectedType: IrType): IrExpression override fun IrExpression.useAs(type: IrType): IrExpression { - val actualType = when (this) { is IrConstructorCall -> symbol.owner.returnType is IrCall -> symbol.owner.realOverrideTarget.returnType is IrGetField -> this.symbol.owner.type is IrTypeOperatorCall -> { - assert(operator == IrTypeOperator.REINTERPRET_CAST) { "Only REINTERPRET_CAST expected at this point" } - this.typeOperand + if (operator == IrTypeOperator.REINTERPRET_CAST) { + this.typeOperand + } else { + this.type + } } is IrGetValue -> { val value = this.symbol.owner - if (value is IrValueParameter && value.isDispatchReceiver) { - irBuiltIns.anyNType + if (value is IrValueParameter && icUtils.shouldValueParameterBeBoxed(value)) { + irBuiltIns.anyType } else { this.type } @@ -73,12 +70,60 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag else -> this.type } + return useExpressionAsType(actualType, type) + } + + + private val IrFunctionAccessExpression.target: IrFunction + get() = when (this) { + is IrConstructorCall -> this.symbol.owner + is IrDelegatingConstructorCall -> this.symbol.owner + is IrCall -> this.callTarget + else -> TODO(this.render()) + } + + private val IrCall.callTarget: IrFunction + get() = symbol.owner.realOverrideTarget + + + override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression { + return if (expression.symbol.owner.dispatchReceiverParameter?.let { icUtils.shouldValueParameterBeBoxed(it) } == true) + this.useAs(irBuiltIns.anyType) + else + this.useAsArgument(expression.target.dispatchReceiverParameter!!) + } + + override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression { + return this.useAsArgument(expression.target.extensionReceiverParameter!!) + } + + override fun IrExpression.useAsValueArgument( + expression: IrFunctionAccessExpression, + parameter: IrValueParameter + ): IrExpression { + + return this.useAsArgument(expression.target.valueParameters[parameter.index]) + } + + + override fun IrExpression.useAsVarargElement(expression: IrVararg): IrExpression { + return this.useAs( + // Do not box primitive inline classes + if (icUtils.isTypeInlined(type) && !icUtils.isTypeInlined(expression.type) && !expression.type.isPrimitiveArray()) + irBuiltIns.anyNType + else + expression.varargElementType + ) + } +} + +class AutoboxingTransformer(context: JsCommonBackendContext) : AbstractValueUsageLowering(context) { + override fun IrExpression.useExpressionAsType(actualType: IrType, expectedType: IrType): IrExpression { // // TODO: Default parameters are passed as nulls and they need not to be unboxed. Fix this + if (actualType.makeNotNull().isNothing()) return this - val expectedType = type - if (actualType.isUnit() && !expectedType.isUnit()) { // Don't materialize Unit if value is known to be proper Unit on runtime if (!this.isGetUnit()) { @@ -87,8 +132,8 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag } } - val actualInlinedClass = actualType.getInlinedClass() - val expectedInlinedClass = expectedType.getInlinedClass() + val actualInlinedClass = icUtils.getInlinedClass(actualType) + val expectedInlinedClass = icUtils.getInlinedClass(expectedType) // Mimicking behaviour of current JS backend // TODO: Revisit @@ -99,8 +144,8 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag val function = when { actualInlinedClass == null && expectedInlinedClass == null -> return this - actualInlinedClass != null && expectedInlinedClass == null -> context.intrinsics.jsBoxIntrinsic - actualInlinedClass == null && expectedInlinedClass != null -> context.intrinsics.jsUnboxIntrinsic + actualInlinedClass != null && expectedInlinedClass == null -> icUtils.boxIntrinsic + actualInlinedClass == null && expectedInlinedClass != null -> icUtils.unboxIntrinsic else -> return this } @@ -115,14 +160,31 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag } } + private tailrec fun IrExpression.isGetUnit(): Boolean = + when (this) { + is IrContainerExpression -> + when (val lastStmt = this.statements.lastOrNull()) { + is IrExpression -> lastStmt.isGetUnit() + else -> false + } + + is IrGetObjectValue -> + this.symbol == irBuiltIns.unitClass + + else -> false + } + private fun buildSafeCall( arg: IrExpression, actualType: IrType, resultType: IrType, call: (IrExpression) -> IrExpression ): IrExpression { - if (!actualType.isNullable()) + // Safe call is only needed if we cast from Nullable type to Nullable type. + // Otherwise, null value cannot occur. + if (!actualType.isNullable() || !resultType.isNullable()) return call(arg) + return JsIrBuilder.run { // TODO: Set parent of local variables val tmp = buildVar(actualType, parent = null, initializer = arg) @@ -144,55 +206,4 @@ class AutoboxingTransformer(val context: JsIrBackendContext) : AbstractValueUsag ) } } - - private val IrFunctionAccessExpression.target: IrFunction - get() = when (this) { - is IrConstructorCall -> this.symbol.owner - is IrDelegatingConstructorCall -> this.symbol.owner - is IrCall -> this.callTarget - else -> TODO(this.render()) - } - - private val IrCall.callTarget: IrFunction - get() = symbol.owner.realOverrideTarget - - - override fun IrExpression.useAsDispatchReceiver(expression: IrFunctionAccessExpression): IrExpression { - return this.useAsArgument(expression.target.dispatchReceiverParameter!!) - } - - override fun IrExpression.useAsExtensionReceiver(expression: IrFunctionAccessExpression): IrExpression { - return this.useAsArgument(expression.target.extensionReceiverParameter!!) - } - - override fun IrExpression.useAsValueArgument( - expression: IrFunctionAccessExpression, - parameter: IrValueParameter - ): IrExpression { - - return this.useAsArgument(expression.target.valueParameters[parameter.index]) - } - - - override fun IrExpression.useAsVarargElement(expression: IrVararg): IrExpression { - return this.useAs( - // Do not box primitive inline classes - if (this.type.isInlined() && !expression.type.isInlined() && !expression.type.isPrimitiveArray()) - irBuiltIns.anyNType - else - expression.varargElementType - ) - } - - private val IrValueParameter.isDispatchReceiver: Boolean - get() { - val parent = this.parent - if (parent is IrClass) - return true - if (parent is IrFunction && parent.dispatchReceiverParameter == this) - return true - return false - } - -} - +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt index 67d066d6ab4..ac5637364e8 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt @@ -15,8 +15,8 @@ import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin -import org.jetbrains.kotlin.ir.backend.js.utils.functionSignature import org.jetbrains.kotlin.ir.backend.js.utils.getJsName +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* @@ -45,10 +45,15 @@ import org.jetbrains.kotlin.ir.util.* // } // @OptIn(ObsoleteDescriptorBasedAPI::class) -class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTransformer { +abstract class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTransformer { private val specialBridgeMethods = SpecialBridgeMethods(context) + abstract fun getFunctionSignature(function: IrSimpleFunction): Any + + // Should dispatch receiver type be casted inside a bridge. + open val shouldCastDispatchReceiver: Boolean = false + override fun transformFlat(declaration: IrDeclaration): List? { if (declaration !is IrSimpleFunction || declaration.isStaticMethodOfClass || declaration.parent !is IrClass) return null @@ -56,10 +61,6 @@ class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTran } private fun generateBridges(function: IrSimpleFunction): List? { - // equals(Any?), hashCode(), toString() never need bridges - if (function.isMethodOfAny()) - return null - val (specialOverride: IrSimpleFunction?, specialOverrideInfo) = specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null) @@ -83,6 +84,11 @@ class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTran continue } + // Don't build bridges for functions with the same signature. + // TODO: This should be caught earlier in bridgesToGenerate + if (FunctionAndSignature(to.function.realOverrideTarget) == FunctionAndSignature(from.function.realOverrideTarget)) + continue + if (from.function.correspondingPropertySymbol != null && from.function.isEffectivelyExternal()) { // TODO: Revisit bridges from external properties continue @@ -150,7 +156,13 @@ class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTran } val call = irCall(delegateTo.symbol) - call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!) + val dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!) + + call.dispatchReceiver = if (shouldCastDispatchReceiver) + irCastIfNeeded(dispatchReceiver, delegateTo.dispatchReceiverParameter!!.type) + else + dispatchReceiver + irFunction.extensionReceiverParameter?.let { call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type) } @@ -171,6 +183,25 @@ class BridgesConstruction(val context: JsCommonBackendContext) : DeclarationTran // TODO: get rid of Unit check private fun IrBlockBodyBuilder.irCastIfNeeded(argument: IrExpression, type: IrType): IrExpression = if (argument.type.classifierOrNull == type.classifierOrNull) argument else irAs(argument, type) + + // Wrapper around function that compares and hashCodes it based on signature + // Designed to be used as a Signature type parameter in backend.common.bridges + inner class FunctionAndSignature(val function: IrSimpleFunction) { + + // TODO: Use type-upper-bound-based signature instead of Strings + // Currently strings are used for compatibility with a hack-based name generator + + private val signature = getFunctionSignature(function) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is BridgesConstruction.FunctionAndSignature) return false + + return signature == other.signature + } + + override fun hashCode(): Int = signature.hashCode() + } } // Handle for common.bridges @@ -187,23 +218,5 @@ data class IrBasedFunctionHandle(val function: IrSimpleFunction) : FunctionHandl function.overriddenSymbols.map { IrBasedFunctionHandle(it.owner) } } -// Wrapper around function that compares and hashCodes it based on signature -// Designed to be used as a Signature type parameter in backend.common.bridges -class FunctionAndSignature(val function: IrSimpleFunction) { - - // TODO: Use type-upper-bound-based signature instead of Strings - // Currently strings are used for compatibility with a hack-based name generator - - private val signature = functionSignature(function) - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is FunctionAndSignature) return false - - return signature == other.signature - } - - override fun hashCode(): Int = signature.hashCode() -} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt index 174dc295a2c..444cd604f9f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/EnumClassLowering.kt @@ -17,18 +17,14 @@ import org.jetbrains.kotlin.backend.common.lower.parents import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext -import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.toJsArrayLiteral import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor import org.jetbrains.kotlin.ir.builders.declarations.buildField import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl -import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.makeNullable import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid @@ -36,7 +32,7 @@ import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid import org.jetbrains.kotlin.name.Name -class EnumUsageLowering(val context: JsIrBackendContext) : BodyLoweringPass { +class EnumUsageLowering(val context: JsCommonBackendContext) : BodyLoweringPass { private var IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun override fun lower(irBody: IrBody, container: IrDeclaration) { @@ -44,41 +40,13 @@ class EnumUsageLowering(val context: JsIrBackendContext) : BodyLoweringPass { override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { val enumEntry = expression.symbol.owner val klass = enumEntry.parent as IrClass - return if (klass.isExternal) lowerExternalEnumEntry(enumEntry, klass) else lowerEnumEntry(enumEntry) + if (klass.isExternal) return expression + return lowerEnumEntry(enumEntry, klass) } }) } - private fun lowerExternalEnumEntry(enumEntry: IrEnumEntry, klass: IrClass) = - context.mapping.enumEntryToInstanceField.getOrPut(enumEntry) { createFieldForEntry(enumEntry, klass) }.let { - JsIrBuilder.buildGetField(it.symbol, classAsReceiver(klass), null, klass.defaultType) - } - - private fun classAsReceiver(irClass: IrClass): IrExpression { - val intrinsic = context.intrinsics.jsClass - return JsIrBuilder.buildCall(intrinsic, context.irBuiltIns.anyType, listOf(irClass.defaultType)) - } - - private fun createFieldForEntry(entry: IrEnumEntry, irClass: IrClass): IrField = - context.irFactory.buildField { - startOffset = entry.startOffset - endOffset = entry.endOffset - origin = entry.origin - name = entry.name - type = irClass.defaultType - isFinal = false - isExternal = true - isStatic = true - }.also { - it.parent = irClass - - // TODO need a way to emerge local declarations from BodyLoweringPass - stageController.unrestrictDeclarationListsAccess { - irClass.declarations += it - } - } - - private fun lowerEnumEntry(enumEntry: IrEnumEntry) = + private fun lowerEnumEntry(enumEntry: IrEnumEntry, klass: IrClass) = enumEntry.getInstanceFun!!.run { JsIrBuilder.buildCall(symbol) } } @@ -313,7 +281,7 @@ class EnumClassConstructorBodyTransformer(val context: JsCommonBackendContext) : private val IrClass.goodEnum: Boolean get() = isEnumClass && !isExpect && !isEffectivelyExternal() -class EnumEntryInstancesLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class EnumEntryInstancesLowering(val context: JsCommonBackendContext) : DeclarationTransformer { private var IrEnumEntry.correspondingField by context.mapping.enumEntryToCorrespondingField @@ -346,7 +314,7 @@ class EnumEntryInstancesLowering(val context: JsIrBackendContext) : DeclarationT } } -class EnumEntryInstancesBodyLowering(val context: JsIrBackendContext) : BodyLoweringPass { +class EnumEntryInstancesBodyLowering(val context: JsCommonBackendContext) : BodyLoweringPass { private var IrEnumEntry.correspondingField by context.mapping.enumEntryToCorrespondingField @@ -370,7 +338,7 @@ class EnumEntryInstancesBodyLowering(val context: JsIrBackendContext) : BodyLowe } } -class EnumClassCreateInitializerLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class EnumClassCreateInitializerLowering(val context: JsCommonBackendContext) : DeclarationTransformer { private var IrEnumEntry.correspondingField by context.mapping.enumEntryToCorrespondingField private var IrClass.initEntryInstancesFun: IrSimpleFunction? by context.mapping.enumClassToInitEntryInstancesFun @@ -431,7 +399,7 @@ class EnumClassCreateInitializerLowering(val context: JsIrBackendContext) : Decl } } -class EnumEntryCreateGetInstancesFunsLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class EnumEntryCreateGetInstancesFunsLowering(val context: JsCommonBackendContext) : DeclarationTransformer { private var IrEnumEntry.correspondingField by context.mapping.enumEntryToCorrespondingField private var IrClass.initEntryInstancesFun: IrSimpleFunction? by context.mapping.enumClassToInitEntryInstancesFun @@ -477,7 +445,7 @@ class EnumEntryCreateGetInstancesFunsLowering(val context: JsIrBackendContext) : } } -class EnumSyntheticFunctionsLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class EnumSyntheticFunctionsLowering(val context: JsCommonBackendContext) : DeclarationTransformer { private var IrEnumEntry.getInstanceFun by context.mapping.enumEntryToGetInstanceFun @@ -500,7 +468,7 @@ class EnumSyntheticFunctionsLowering(val context: JsIrBackendContext) : Declarat return null } - private val throwISESymbol = context.throwISEsymbol + private val throwISESymbol = context.ir.symbols.throwISE private fun createEnumValueOfBody(valueOfFun: IrFunction, irClass: IrClass): IrBlockBody { val nameParameter = valueOfFun.valueParameters[0] @@ -521,26 +489,12 @@ class EnumSyntheticFunctionsLowering(val context: JsIrBackendContext) : Declarat } } - private fun List.toArrayLiteral(arrayType: IrType, elementType: IrType): IrExpression { - val irVararg = IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, arrayType, elementType, this) - - return IrCallImpl( - UNDEFINED_OFFSET, UNDEFINED_OFFSET, arrayType, - context.intrinsics.arrayLiteral, - typeArgumentsCount = 0, - valueArgumentsCount = 1 - ).apply { - putValueArgument(0, irVararg) - } - } - private fun createEnumValuesBody(valuesFun: IrFunction, irClass: IrClass): IrBlockBody { - val backendContext = context return context.createIrBuilder(valuesFun.symbol).run { irBlockBody { + val instances = irClass.enumEntries.map { irCall(it.getInstanceFun!!) } +irReturn( - irClass.enumEntries.map { irCall(it.getInstanceFun!!) } - .toJsArrayLiteral(backendContext, valuesFun.returnType, irClass.defaultType) + IrVarargImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, valuesFun.returnType, irClass.defaultType, instances) ) } } @@ -551,7 +505,7 @@ private val IrClass.enumEntries: List get() = declarations.filterIsInstance() // Should be applied recursively -class EnumClassRemoveEntriesLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class EnumClassRemoveEntriesLowering(val context: JsCommonBackendContext) : DeclarationTransformer { override fun transformFlat(declaration: IrDeclaration): List? { // Remove IrEnumEntry nodes from class declarations. Replace them with corresponding class declarations (if they have them). if (declaration is IrEnumEntry && !declaration.isExpect && !declaration.isEffectivelyExternal()) { @@ -560,4 +514,4 @@ class EnumClassRemoveEntriesLowering(val context: JsIrBackendContext) : Declarat return null } -} \ No newline at end of file +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ExternalEnumUsagesLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ExternalEnumUsagesLowering.kt new file mode 100644 index 00000000000..3c0cf4559c9 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/ExternalEnumUsagesLowering.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2018 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.ir.backend.js.lower + +import org.jetbrains.kotlin.backend.common.BodyLoweringPass +import org.jetbrains.kotlin.backend.common.getOrPut +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.builders.declarations.buildField +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrBody +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetEnumValue +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +class ExternalEnumUsagesLowering(val context: JsIrBackendContext) : BodyLoweringPass { + override fun lower(irBody: IrBody, container: IrDeclaration) { + irBody.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression { + val enumEntry = expression.symbol.owner + val klass = enumEntry.parent as IrClass + return if (klass.isExternal) lowerExternalEnumEntry(enumEntry, klass) else expression + } + }) + } + + private fun lowerExternalEnumEntry(enumEntry: IrEnumEntry, klass: IrClass) = + context.mapping.enumEntryToInstanceField.getOrPut(enumEntry) { createFieldForEntry(enumEntry, klass) }.let { + JsIrBuilder.buildGetField(it.symbol, classAsReceiver(klass), null, klass.defaultType) + } + + private fun classAsReceiver(irClass: IrClass): IrExpression { + val intrinsic = context.intrinsics.jsClass + return JsIrBuilder.buildCall(intrinsic, context.irBuiltIns.anyType, listOf(irClass.defaultType)) + } + + private fun createFieldForEntry(entry: IrEnumEntry, irClass: IrClass): IrField = + context.irFactory.buildField { + startOffset = entry.startOffset + endOffset = entry.endOffset + origin = entry.origin + name = entry.name + type = irClass.defaultType + isFinal = false + isExternal = true + isStatic = true + }.also { + it.parent = irClass + + // TODO need a way to emerge local declarations from BodyLoweringPass + stageController.unrestrictDeclarationListsAccess { + irClass.declarations += it + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.kt new file mode 100644 index 00000000000..1a59c7aeb7a --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsBridgesConstruction.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.ir.backend.js.lower + +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext +import org.jetbrains.kotlin.ir.backend.js.utils.Signature +import org.jetbrains.kotlin.ir.backend.js.utils.jsFunctionSignature +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction + +class JsBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction(context) { + override fun getFunctionSignature(function: IrSimpleFunction): Signature = + jsFunctionSignature(function) +} diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/StaticMembersLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/StaticMembersLowering.kt index 6941fa43863..6d2cb831373 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/StaticMembersLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/StaticMembersLowering.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.ir.backend.js.lower import org.jetbrains.kotlin.backend.common.DeclarationTransformer +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.export.isExported import org.jetbrains.kotlin.ir.declarations.* @@ -13,7 +14,7 @@ import org.jetbrains.kotlin.ir.util.file import org.jetbrains.kotlin.ir.util.isEffectivelyExternal // Move static member declarations from classes to top level -class StaticMembersLowering(val context: JsIrBackendContext) : DeclarationTransformer { +class StaticMembersLowering(val context: JsCommonBackendContext) : DeclarationTransformer { override fun transformFlat(declaration: IrDeclaration): List? { (declaration.parent as? IrClass)?.let { irClass -> val isStatic = when (declaration) { @@ -26,7 +27,7 @@ class StaticMembersLowering(val context: JsIrBackendContext) : DeclarationTransf if (isStatic) { // JsExport might be inherited from parent declaration which would be broken if we move it out of its parent. // Marking declaration as exported explicitly. - if (declaration.isExported(context)) { + if (context is JsIrBackendContext && declaration.isExported(context)) { context.additionalExportedDeclarations.add(declaration) } var extractedUnder = declaration diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt index 01e2a169d57..6d4a87f077f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/TypeOperatorLowering.kt @@ -10,7 +10,6 @@ import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.backend.js.utils.isPure import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration @@ -64,6 +63,8 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { private val litFalse: IrExpression get() = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false) private val litNull: IrExpression get() = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType) + private val icUtils = context.inlineClassesUtils + override fun lower(irBody: IrBody, container: IrDeclaration) { irBody.transformChildren(object : IrElementTransformer { override fun visitDeclaration(declaration: IrDeclarationBase, data: IrDeclarationParent) = @@ -102,7 +103,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : BodyLoweringPass { } private fun needBoxingOrUnboxing(fromType: IrType, toType: IrType): Boolean { - return ((fromType.getInlinedClass() != null) xor (toType.getInlinedClass() != null)) || (fromType.isUnit() && !toType.isUnit()) + return ((icUtils.getInlinedClass(fromType) != null) xor (icUtils.getInlinedClass(toType) != null)) || (fromType.isUnit() && !toType.isUnit()) } private fun IrTypeOperatorCall.wrapWithUnsafeCast(arg: IrExpression): IrExpression { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt index 860b9119126..f8018f17c9b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/VarargLowering.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.BodyLoweringPass import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl @@ -32,6 +31,8 @@ private class VarargTransformer( val context: JsIrBackendContext ) : IrElementTransformerVoid() { + fun IrType.getInlinedClass() = context.inlineClassesUtils.getInlinedClass(this) + @OptIn(ObsoleteDescriptorBasedAPI::class) private fun List.toArrayLiteral(type: IrType, varargElementType: IrType): IrExpression { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/JsSuspendFunctionsLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/JsSuspendFunctionsLowering.kt index d02a3bfe911..20b8c77661c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/JsSuspendFunctionsLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/JsSuspendFunctionsLowering.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrValueSymbol import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isUnit import org.jetbrains.kotlin.ir.util.explicitParameters import org.jetbrains.kotlin.ir.util.patchDeclarationParents import org.jetbrains.kotlin.ir.visitors.* @@ -225,6 +226,13 @@ class JsSuspendFunctionsLowering(ctx: JsIrBackendContext) : AbstractSuspendFunct return result } + private fun needUnboxingOrUnit(fromType: IrType, toType: IrType): Boolean { + val icUtils = context.inlineClassesUtils + + return (icUtils.getInlinedClass(fromType) == null && icUtils.getInlinedClass(toType) != null) || + (fromType.isUnit() && !toType.isUnit()) + } + override fun IrBuilderWithScope.generateDelegatedCall(expectedType: IrType, delegatingCall: IrExpression): IrExpression { val fromType = (delegatingCall as? IrCall)?.symbol?.owner?.returnType ?: delegatingCall.type if (!needUnboxingOrUnit(fromType, expectedType)) return delegatingCall diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt index 3016960ae2f..2f550983b31 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/StateMachineBuilder.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.ir.backend.js.lower.coroutines -import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.ir.isElseBranch import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.peek @@ -14,9 +13,9 @@ import org.jetbrains.kotlin.backend.common.push import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.utils.isPure -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* @@ -69,7 +68,7 @@ class DispatchPointTransformer(val action: (SuspendState) -> IrExpression) : IrE class StateMachineBuilder( private val suspendableNodes: MutableSet, - val context: CommonBackendContext, + val context: JsCommonBackendContext, val function: IrFunctionSymbol, private val rootLoop: IrLoop, private val exceptionSymbolGetter: IrSimpleFunction, @@ -279,7 +278,7 @@ class StateMachineBuilder( if (expression.isSuspend) { val result = lastExpression() val expectedType = expression.symbol.owner.returnType - val isInlineClassExpected = expectedType.getInlinedClass() != null + val isInlineClassExpected = context.inlineClassesUtils.getInlinedClass(expectedType) != null val continueState = SuspendState(unit) val unboxState = if (isInlineClassExpected) SuspendState(unit) else null diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt index 13706f08fd9..10b5c24d95c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/coroutines/SuspendLoweringUtils.kt @@ -9,7 +9,6 @@ import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl @@ -106,9 +105,4 @@ class LiveLocalsTransformer( JsIrBuilder.buildComposite(declaration.type) } } -} - -internal fun needUnboxingOrUnit(fromType: IrType, toType: IrType): Boolean { - return (fromType.getInlinedClass() == null && toType.getInlinedClass() != null) || - (fromType.isUnit() && !toType.isUnit()) } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index 6015dcf7814..004be491487 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -8,7 +8,6 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer -import org.jetbrains.kotlin.ir.backend.js.utils.getInlinedClass import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName @@ -27,6 +26,7 @@ typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpres class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { private val transformers: Map + val icUtils = backendContext.inlineClassesUtils init { val intrinsics = backendContext.intrinsics @@ -188,14 +188,14 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { add(intrinsics.jsBoxIntrinsic) { call, context -> val arg = translateCallArguments(call, context).single() - val inlineClass = call.getTypeArgument(0)!!.getInlinedClass()!! + val inlineClass = icUtils.getInlinedClass(call.getTypeArgument(0)!!)!! val constructor = inlineClass.declarations.filterIsInstance().single { it.isPrimary } JsNew(context.getNameForConstructor(constructor).makeRef(), listOf(arg)) } add(intrinsics.jsUnboxIntrinsic) { call, context -> val arg = translateCallArguments(call, context).single() - val inlineClass = call.getTypeArgument(1)!!.getInlinedClass()!! + val inlineClass = icUtils.getInlinedClass(call.getTypeArgument(1)!!)!! val field = getInlineClassBackingField(inlineClass) val fieldName = context.getNameForField(field) JsNameRef(fieldName, arg) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt index 506e799778c..04dab5665ce 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/IrTypeUtils.kt @@ -45,7 +45,7 @@ private fun IrClassifierSymbol.asString() = when (this) { /** * Returns inline class for given class or null of type is not inlined */ -fun IrType.getInlinedClass(): IrClass? { +fun IrType.getJsInlinedClass(): IrClass? { if (this is IrSimpleType) { val erased = erase(this) ?: return null if (erased.isInline) { @@ -58,7 +58,7 @@ fun IrType.getInlinedClass(): IrClass? { return null } - fieldInlinedClass = fieldType.getInlinedClass() ?: break + fieldInlinedClass = fieldType.getJsInlinedClass() ?: break } } @@ -68,8 +68,6 @@ fun IrType.getInlinedClass(): IrClass? { return null } -fun IrType.isInlined(): Boolean = this.getInlinedClass() != null - tailrec fun erase(type: IrType): IrClass? { val classifier = type.classifierOrFail diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsInlineClassesUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsInlineClassesUtils.kt new file mode 100644 index 00000000000..1fc4b7caa88 --- /dev/null +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsInlineClassesUtils.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.ir.backend.js.utils + +import org.jetbrains.kotlin.ir.backend.js.InlineClassesUtils +import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isMarkedNullable +import org.jetbrains.kotlin.ir.util.getInlineClassUnderlyingType + +class JsInlineClassesUtils(val context: JsIrBackendContext) : InlineClassesUtils { + override fun isTypeInlined(type: IrType): Boolean { + return getInlinedClass(type) != null + } + + override fun getInlinedClass(type: IrType): IrClass? = + type.getJsInlinedClass() + + override fun isClassInlineLike(klass: IrClass): Boolean = + klass.isInline + + override val boxIntrinsic: IrSimpleFunctionSymbol + get() = context.intrinsics.jsBoxIntrinsic + + override val unboxIntrinsic: IrSimpleFunctionSymbol + get() = context.intrinsics.jsUnboxIntrinsic +} \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt index c9b6a592329..74f4522f30a 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameTables.kt @@ -104,7 +104,7 @@ fun fieldSignature(field: IrField): Signature { return BackingFieldSignature(field) } -fun functionSignature(declaration: IrFunction): Signature { +fun jsFunctionSignature(declaration: IrFunction): Signature { require(!declaration.isStaticMethodOfClass) require(declaration.dispatchReceiverParameter != null) @@ -143,7 +143,7 @@ fun functionSignature(declaration: IrFunction): Signature { declaration.returnType.let { // Return type is only used in signature for inline class and Unit types because // they are binary incompatible with supertypes. - if (it.isInlined() || it.isUnit()) { + if (it.getJsInlinedClass() != null || it.isUnit()) { nameBuilder.append("_ret$${it.asString()}") } } @@ -286,7 +286,7 @@ class NameTables( } private fun generateNameForMemberFunction(declaration: IrSimpleFunction) { - when (val signature = functionSignature(declaration)) { + when (val signature = jsFunctionSignature(declaration)) { is StableNameSignature -> memberNames.declareStableName(signature, signature.name) is ParameterTypeBasedSignature -> memberNames.declareFreshName(signature, signature.suggestedName) } @@ -335,7 +335,7 @@ class NameTables( } fun getNameForMemberFunction(function: IrSimpleFunction): String { - val signature = functionSignature(function) + val signature = jsFunctionSignature(function) val name = memberNames.names[signature] ?: mappedNames[mapToKey(signature)] // TODO Add a compiler flag, which enables this behaviour diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt index f38e9748761..3b88272b7ba 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/misc.kt @@ -79,4 +79,14 @@ fun IrExpression?.isPure(anyVariable: Boolean, checkFields: Boolean = true): Boo } return false -} \ No newline at end of file +} + +val IrValueDeclaration.isDispatchReceiver: Boolean + get() { + val parent = this.parent + if (parent is IrClass) + return true + if (parent is IrFunction && parent.dispatchReceiverParameter == this) + return true + return false + } \ No newline at end of file diff --git a/compiler/ir/backend.wasm/build.gradle.kts b/compiler/ir/backend.wasm/build.gradle.kts index 64bed5c9355..745f12242a5 100644 --- a/compiler/ir/backend.wasm/build.gradle.kts +++ b/compiler/ir/backend.wasm/build.gradle.kts @@ -12,6 +12,7 @@ dependencies { compile(project(":compiler:ir.backend.common")) compile(project(":compiler:ir.serialization.common")) compile(project(":compiler:ir.serialization.js")) + compile(project(":compiler:ir.tree.persistent")) compile(project(":js:js.ast")) compile(project(":js:js.frontend")) compile(project(":compiler:backend.js")) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt index 6e6d12b703a..22cbe8649e7 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmBackendContext.kt @@ -7,24 +7,36 @@ package org.jetbrains.kotlin.backend.wasm import org.jetbrains.kotlin.backend.common.ir.Ir import org.jetbrains.kotlin.backend.common.ir.Symbols +import org.jetbrains.kotlin.backend.common.ir.addChild +import org.jetbrains.kotlin.backend.wasm.lower.WasmSharedVariablesManager +import org.jetbrains.kotlin.backend.wasm.utils.WasmInlineClassesUtils 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.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.SourceManager +import org.jetbrains.kotlin.ir.SourceRangeInfo +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext import org.jetbrains.kotlin.ir.backend.js.JsMapping import org.jetbrains.kotlin.ir.backend.js.JsSharedVariablesManager import org.jetbrains.kotlin.ir.backend.js.lower.JsInnerClassesSupport +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.buildFun import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.persistent.PersistentIrFactory +import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns -import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol import org.jetbrains.kotlin.ir.util.IdSignature import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name class WasmBackendContext( val module: ModuleDescriptor, @@ -43,10 +55,12 @@ class WasmBackendContext( override val irFactory: IrFactory = PersistentIrFactory // Place to store declarations excluded from code generation - val excludedDeclarations: IrPackageFragment by lazy { + private val excludedDeclarations = mutableMapOf() + + fun getExcludedPackageFragment(fqName: FqName): IrPackageFragment = excludedDeclarations.getOrPut(fqName) { IrExternalPackageFragmentImpl( DescriptorlessExternalPackageFragmentSymbol(), - FqName("kotlin") + fqName ) } @@ -54,14 +68,44 @@ class WasmBackendContext( val innerClassesSupport = JsInnerClassesSupport(mapping, irFactory) - val objectToGetInstanceFunction = mutableMapOf() override val internalPackageFqn = FqName("kotlin.wasm") - private val internalPackageFragment = IrExternalPackageFragmentImpl.createEmptyExternalPackageFragment( - builtIns.builtInsModule, FqName("kotlin.wasm.internal") - ) + private val internalPackageFragmentDescriptor = EmptyPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.wasm.internal")) + // TODO: Merge with JS IR Backend context lazy file + val internalPackageFragment by lazy { + IrFileImpl(object : SourceManager.FileEntry { + override val name = "" + override val maxOffset = UNDEFINED_OFFSET - override val sharedVariablesManager = JsSharedVariablesManager(TODO("...")) + override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int) = + SourceRangeInfo( + "", + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + UNDEFINED_OFFSET + ) + + override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET + override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET + }, internalPackageFragmentDescriptor).also { + irModuleFragment.files += it + } + } + + + val startFunction = irFactory.buildFun { + name = Name.identifier("startFunction") + returnType = irBuiltIns.unitType + }.apply { + body = irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) + internalPackageFragment.addChild(this) + } + + override val sharedVariablesManager = + WasmSharedVariablesManager(this, irBuiltIns, internalPackageFragment) val wasmSymbols: WasmSymbols = WasmSymbols(this@WasmBackendContext, symbolTable) override val ir = object : Ir(this, irModuleFragment) { @@ -69,6 +113,8 @@ class WasmBackendContext( override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true } + override val inlineClassesUtils = WasmInlineClassesUtils(wasmSymbols) + override fun log(message: () -> String) { /*TODO*/ if (inVerbosePhase) print(message()) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt index d661effa94a..78142b78ede 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmLoweringPhases.kt @@ -5,23 +5,16 @@ package org.jetbrains.kotlin.backend.wasm -import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass -import org.jetbrains.kotlin.backend.common.lower 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.common.runOnFilePostfix -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.backend.wasm.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineFunctionsWithReifiedTypeParametersLowering 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 makeWasmModulePhase( lowering: (WasmBackendContext) -> FileLoweringPass, name: String, @@ -60,6 +53,12 @@ private val expectDeclarationsRemovingPhase = makeWasmModulePhase( description = "Remove expect declaration from module fragment" ) +private val stringConstructorLowering = makeWasmModulePhase( + ::SimpleStringConcatenationLowering, + name = "StringConcatenation", + description = "String concatenation lowering" +) + private val lateinitNullableFieldsPhase = makeWasmModulePhase( ::NullableFieldsForLateinitCreationLowering, name = "LateinitNullableFields", @@ -86,12 +85,6 @@ private val provisionalFunctionExpressionPhase = makeWasmModulePhase( 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) @@ -112,7 +105,7 @@ private val removeInlineFunctionsWithReifiedTypeParametersLoweringPhase = makeWa private val tailrecLoweringPhase = makeWasmModulePhase( ::TailrecLowering, name = "TailrecLowering", - description = "Replace `tailrec` callsites with equivalent loop" + description = "Replace `tailrec` call sites with equivalent loop" ) private val enumClassConstructorLoweringPhase = makeWasmModulePhase( @@ -121,6 +114,62 @@ private val enumClassConstructorLoweringPhase = makeWasmModulePhase( description = "Transform Enum Class into regular Class" ) +private val enumClassConstructorBodyLoweringPhase = makeWasmModulePhase( + ::EnumClassConstructorBodyTransformer, + name = "EnumClassConstructorBodyLowering", + description = "Transform Enum Class into regular Class" +) + + +private val enumEntryInstancesLoweringPhase = makeWasmModulePhase( + ::EnumEntryInstancesLowering, + name = "EnumEntryInstancesLowering", + description = "Create instance variable for each enum entry initialized with `null`", + prerequisite = setOf(enumClassConstructorLoweringPhase) +) + +private val enumEntryInstancesBodyLoweringPhase = makeWasmModulePhase( + ::EnumEntryInstancesBodyLowering, + name = "EnumEntryInstancesBodyLowering", + description = "Insert enum entry field initialization into corresponding class constructors", + prerequisite = setOf(enumEntryInstancesLoweringPhase) +) + +private val enumClassCreateInitializerLoweringPhase = makeWasmModulePhase( + ::EnumClassCreateInitializerLowering, + name = "EnumClassCreateInitializerLowering", + description = "Create initializer for enum entries", + prerequisite = setOf(enumClassConstructorLoweringPhase) +) + +private val enumEntryCreateGetInstancesFunsLoweringPhase = makeWasmModulePhase( + ::EnumEntryCreateGetInstancesFunsLowering, + name = "EnumEntryCreateGetInstancesFunsLowering", + description = "Create enumEntry_getInstance functions", + prerequisite = setOf(enumClassConstructorLoweringPhase) +) + +private val enumSyntheticFunsLoweringPhase = makeWasmModulePhase( + ::EnumSyntheticFunctionsLowering, + name = "EnumSyntheticFunctionsLowering", + description = "Implement `valueOf` and `values`", + prerequisite = setOf(enumClassConstructorLoweringPhase) +) + +private val enumUsageLoweringPhase = makeWasmModulePhase( + ::EnumUsageLowering, + name = "EnumUsageLowering", + description = "Replace enum access with invocation of corresponding function", + prerequisite = setOf(enumEntryCreateGetInstancesFunsLoweringPhase) +) + +private val enumEntryRemovalLoweringPhase = makeWasmModulePhase( + ::EnumClassRemoveEntriesLowering, + name = "EnumEntryRemovalLowering", + description = "Replace enum entry with corresponding class", + prerequisite = setOf(enumUsageLoweringPhase) +) + private val sharedVariablesLoweringPhase = makeWasmModulePhase( ::SharedVariablesLowering, @@ -128,6 +177,12 @@ private val sharedVariablesLoweringPhase = makeWasmModulePhase( description = "Box captured mutable variables" ) +private val callableReferencePhase = makeWasmModulePhase( + ::WasmCallableReferenceLowering, + name = "WasmCallableReferenceLowering", + description = "Handle callable references" +) + private val localDelegatedPropertiesLoweringPhase = makeWasmModulePhase( { LocalDelegatedPropertiesLowering() }, name = "LocalDelegatedPropertiesLowering", @@ -183,7 +238,7 @@ private val defaultArgumentPatchOverridesPhase = makeWasmModulePhase( private val defaultParameterInjectorPhase = makeWasmModulePhase( { context -> DefaultParameterInjector(context, skipExternalMethods = true) }, name = "DefaultParameterInjector", - description = "Replace callsite with default parameters with corresponding stub function", + description = "Replace call site with default parameters with corresponding stub function", prerequisite = setOf(innerClassesLoweringPhase) ) @@ -193,18 +248,6 @@ private val defaultParameterCleanerPhase = makeWasmModulePhase( 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( { PropertiesLowering() }, name = "PropertiesLowering", @@ -254,7 +297,7 @@ private val returnableBlockLoweringPhase = makeWasmModulePhase( ) private val bridgesConstructionPhase = makeWasmModulePhase( - ::BridgesConstruction, + ::WasmBridgesConstruction, name = "BridgesConstruction", description = "Generate bridges" ) @@ -271,65 +314,57 @@ private val inlineClassUsageLoweringPhase = makeWasmModulePhase( description = "Handle inline class usages" ) -//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 autoboxingTransformerPhase = makeWasmModulePhase( + { context -> AutoboxingTransformer(context) }, + name = "AutoboxingTransformer", + description = "Insert box/unbox intrinsics" +) + +private val wasmNullSpecializationLowering = makeWasmModulePhase( + { context -> WasmNullCoercingLowering(context) }, + name = "WasmNullCoercingLowering", + description = "Specialize assigning Nothing? values to other types." +) + +private val staticMembersLoweringPhase = makeWasmModulePhase( + ::StaticMembersLowering, + name = "StaticMembersLowering", + description = "Move static member declarations to top-level" +) + +private val wasmVarargExpressionLoweringPhase = makeWasmModulePhase( + ::WasmVarargExpressionLowering, + name = "WasmVarargExpressionLowering", + description = "Lower varargs" +) + +private val wasmThrowDebugLoweringPhase = makeWasmModulePhase( + ::WasmThrowDebugLowering, + name = "WasmThrowDebugLowering", + description = "Instrument throws with debug print information" +) + +private val fieldInitializersLoweringPhase = makeWasmModulePhase( + ::FieldInitializersLowering, + name = "FieldInitializersLowering", + description = "Move field initializers to start function" +) + +private val builtInsLoweringPhase0 = makeWasmModulePhase( + ::BuiltInsLowering, + name = "BuiltInsLowering0", + description = "Lower IR builtins 0" ) -//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" + description = "Lower IR builtins" ) private val objectDeclarationLoweringPhase = makeWasmModulePhase( - ::ObjectUsageLowering, + ::ObjectDeclarationLowering, name = "ObjectDeclarationLowering", description = "Create lazy object instance generator functions" ) @@ -340,26 +375,52 @@ private val objectUsageLoweringPhase = makeWasmModulePhase( description = "Transform IrGetObjectValue into instance generator call" ) +private val typeOperatorLoweringPhase = makeWasmModulePhase( + ::WasmTypeOperatorLowering, + name = "TypeOperatorLowering", + description = "Lower IrTypeOperator with corresponding logic" +) + +private val genericReturnTypeLowering = makeWasmModulePhase( + ::GenericReturnTypeLowering, + name = "GenericReturnTypeLowering", + description = "Cast calls to functions with generic return types" +) + +private val eraseVirtualDispatchReceiverParametersTypes = makeWasmModulePhase( + ::EraseVirtualDispatchReceiverParametersTypes, + name = "EraseVirtualDispatchReceiverParametersTypes", + description = "Erase types of virtual dispatch receivers to Any" +) + +private val virtualDispatchReceiverExtractionPhase = makeWasmModulePhase( + ::VirtualDispatchReceiverExtraction, + name = "VirtualDispatchReceiverExtraction", + description = "Eliminate side-effects in dispatch receivers of virtual function calls" +) + val wasmPhases = NamedCompilerPhase( 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 + provisionalFunctionExpressionPhase then lateinitNullableFieldsPhase then lateinitDeclarationLoweringPhase then lateinitUsageLoweringPhase then tailrecLoweringPhase then enumClassConstructorLoweringPhase then + enumClassConstructorBodyLoweringPhase then sharedVariablesLoweringPhase then + callableReferencePhase then localDelegatedPropertiesLoweringPhase then localDeclarationsLoweringPhase then localClassExtractionPhase then @@ -373,68 +434,52 @@ val wasmPhases = NamedCompilerPhase( initializersCleanupLoweringPhase then // Common prefix ends - builtInsLoweringPhase then - -// TODO: Commonize enumEntryToGetInstanceFunction -// Commonize array literal creation -// Extract external enum lowering to JS part -// -// enumClassLoweringPhase then -// enumUsageLoweringPhase then - + enumEntryInstancesLoweringPhase then + enumEntryInstancesBodyLoweringPhase then + enumClassCreateInitializerLoweringPhase then + enumEntryCreateGetInstancesFunsLoweringPhase then + enumSyntheticFunsLoweringPhase then + enumUsageLoweringPhase then + enumEntryRemovalLoweringPhase then // TODO: Requires stdlib // suspendFunctionsLoweringPhase then + stringConstructorLowering then returnableBlockLoweringPhase then - -// TODO: Callable reference lowering is too JS specific. -// Should we reuse JVM or Native lowering? -// callableReferenceLoweringPhase then - defaultArgumentStubGeneratorPhase then defaultArgumentPatchOverridesPhase then defaultParameterInjectorPhase then defaultParameterCleanerPhase then - -// TODO: Investigate -// jsDefaultCallbackGeneratorPhase then - removeInlineFunctionsWithReifiedTypeParametersLoweringPhase then - -// TODO: Varargs are too platform-specific. Reimplement. -// varargLoweringPhase then - -// TODO: Investigate exception proposal +// TODO: // multipleCatchesLoweringPhase then - - bridgesConstructionPhase then - -// TODO: Reimplement -// typeOperatorLoweringPhase then - -// TODO: Reimplement -// secondaryConstructorLoweringPhase then -// secondaryFactoryInjectorLoweringPhase then - -// TODO: Reimplement // classReferenceLoweringPhase then + wasmVarargExpressionLoweringPhase then inlineClassDeclarationLoweringPhase then inlineClassUsageLoweringPhase then -// TODO: Commonize box/unbox intrinsics -// autoboxingTransformerPhase then - - blockDecomposerLoweringPhase then - -// TODO: Reimplement -// constLoweringPhase then - + eraseVirtualDispatchReceiverParametersTypes then + bridgesConstructionPhase then objectDeclarationLoweringPhase then - objectUsageLoweringPhase then -// staticMembersLoweringPhase then + fieldInitializersLoweringPhase then + genericReturnTypeLowering then + // Replace builtins before autoboxing + builtInsLoweringPhase0 then + + autoboxingTransformerPhase then + objectUsageLoweringPhase then + typeOperatorLoweringPhase then + + // Clean up built-ins after type operator lowering + builtInsLoweringPhase then + + virtualDispatchReceiverExtractionPhase then + wasmThrowDebugLoweringPhase then + staticMembersLoweringPhase then + wasmNullSpecializationLowering then validateIrAfterLowering ) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt index 898b676e80f..9c7d24dc128 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/WasmSymbols.kt @@ -7,10 +7,12 @@ 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.PackageViewDescriptor 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.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol @@ -18,24 +20,26 @@ import org.jetbrains.kotlin.ir.util.SymbolTable import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.scopes.MemberScope +import org.jetbrains.kotlin.util.OperatorNameConventions class WasmSymbols( context: WasmBackendContext, private val symbolTable: SymbolTable ) : Symbols(context, context.irBuiltIns, symbolTable) { - override val throwNullPointerException - get() = TODO() - override val throwNoWhenBranchMatchedException - get() = TODO() - override val throwTypeCastException - get() = TODO() - override val throwUninitializedPropertyAccessException - get() = TODO() + private val wasmInternalPackage: PackageViewDescriptor = + context.module.getPackage(FqName("kotlin.wasm.internal")) + + override val throwNullPointerException = getInternalFunction("THROW_NPE") + override val throwISE = getInternalFunction("THROW_ISE") + override val throwNoWhenBranchMatchedException = throwISE + override val throwTypeCastException = getInternalFunction("THROW_CCE") + override val throwUninitializedPropertyAccessException = + getInternalFunction("throwUninitializedPropertyAccessException") + override val defaultConstructorMarker = + getIrClass(FqName("kotlin.wasm.internal.DefaultConstructorMarker")) override val throwKotlinNothingValueException: IrSimpleFunctionSymbol get() = TODO() - override val defaultConstructorMarker - get() = TODO() override val stringBuilder get() = TODO() override val copyRangeTo: Map @@ -47,7 +51,7 @@ class WasmSymbols( override val getContinuation get() = TODO() override val coroutineContextGetter by lazy { - context.irFactory.addFunction(context.excludedDeclarations) { + context.irFactory.addFunction(context.getExcludedPackageFragment(FqName("kotlin.excluded"))) { name = Name.identifier("coroutineContextGetter\$Stub") }.symbol } @@ -62,7 +66,9 @@ class WasmSymbols( override val functionAdapter: IrClassSymbol get() = TODO() - private val wasmInternalPackage = context.module.getPackage(FqName("kotlin.wasm.internal")) + val wasmUnreachable = getInternalFunction("wasm_unreachable") + val wasmFloatNaN = getInternalFunction("wasm_float_nan") + val wasmDoubleNaN = getInternalFunction("wasm_double_nan") val equalityFunctions = mapOf( context.irBuiltIns.booleanType to getInternalFunction("wasm_i32_eq"), @@ -71,12 +77,16 @@ class WasmSymbols( 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.stringType to getInternalFunction("wasm_string_eq") + ) + + val floatEqualityFunctions = mapOf( context.irBuiltIns.floatType to getInternalFunction("wasm_f32_eq"), context.irBuiltIns.doubleType to getInternalFunction("wasm_f64_eq") ) - private fun wasmString(classfier: IrClassifierSymbol): String = with(context.irBuiltIns) { - when (classfier) { + private fun wasmPrimitiveTypeName(classifier: IrClassifierSymbol): String = with(context.irBuiltIns) { + when (classifier) { booleanClass, byteClass, shortClass, charClass, intClass -> "i32" floatClass -> "f32" doubleClass -> "f64" @@ -85,23 +95,66 @@ class WasmSymbols( } } - val irBuiltInsToWasmIntrinsics = context.irBuiltIns.run { - mapOf( + val comparisonBuiltInsToWasmIntrinsics = context.irBuiltIns.run { + listOf( lessFunByOperandType to "lt", lessOrEqualFunByOperandType to "le", greaterOrEqualFunByOperandType to "ge", greaterFunByOperandType to "gt" ).map { (typeToBuiltIn, wasmOp) -> typeToBuiltIn.map { (type, builtin) -> - val wasmType = wasmString(type) + val wasmType = wasmPrimitiveTypeName(type) val markSign = if (wasmType == "i32" || wasmType == "i64") "_s" else "" builtin to getInternalFunction("wasm_${wasmType}_$wasmOp$markSign") } }.flatten().toMap() } + val booleanAnd = getInternalFunction("wasm_i32_and") + val refEq = getInternalFunction("wasm_ref_eq") + val refIsNull = getInternalFunction("wasm_ref_is_null") + val intToLong = getInternalFunction("wasm_i64_extend_i32_s") + + val wasmRefCast = getInternalFunction("wasm_ref_cast") + + val boxIntrinsic: IrSimpleFunctionSymbol = getInternalFunction("boxIntrinsic") + val unboxIntrinsic: IrSimpleFunctionSymbol = getInternalFunction("unboxIntrinsic") + val stringGetLiteral = getInternalFunction("stringLiteral") + val wasmClassId = getInternalFunction("wasmClassId") + val wasmInterfaceId = getInternalFunction("wasmInterfaceId") + + val getVirtualMethodId = getInternalFunction("getVirtualMethodId") + val getInterfaceMethodId = getInternalFunction("getInterfaceMethodId") + + val isSubClass = getInternalFunction("isSubClass") + val isInterface = getInternalFunction("isInterface") + + val nullableEquals = getInternalFunction("nullableEquals") + val ensureNotNull = getInternalFunction("ensureNotNull") + val anyNtoString = getInternalFunction("anyNtoString") + + val nullableFloatIeee754Equals = getInternalFunction("nullableFloatIeee754Equals") + val nullableDoubleIeee754Equals = getInternalFunction("nullableDoubleIeee754Equals") + + val wasmThrow = getInternalFunction("wasmThrow") + + private val functionNInterfaces = (0..22).map { arity -> + getIrClass(FqName("kotlin.wasm.internal.Function$arity")) + } + + val functionNInvokeMethods by lazy { + functionNInterfaces.map { interfaceSymbol -> + interfaceSymbol.owner.declarations.filterIsInstance().single { method -> + method.name == OperatorNameConventions.INVOKE + }.symbol + } + } + + override fun functionN(n: Int): IrClassSymbol = + functionNInterfaces[n] + private fun findClass(memberScope: MemberScope, name: Name): ClassDescriptor = memberScope.getContributedClassifier(name, NoLookupLocation.FROM_BACKEND) as ClassDescriptor @@ -117,7 +170,7 @@ class WasmSymbols( internal fun getProperty(fqName: FqName): PropertyDescriptor = findProperty(context.module.getPackage(fqName.parent()).memberScope, fqName.shortName()).single() - internal fun getInternalFunction(name: String): IrSimpleFunctionSymbol { + private fun getInternalFunction(name: String): IrSimpleFunctionSymbol { val tmp = findFunctions(wasmInternalPackage.memberScope, Name.identifier(name)).single() return symbolTable.referenceSimpleFunction(tmp) } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmAstToWat.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmAstToWat.kt deleted file mode 100644 index 0b6ec521ad3..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmAstToWat.kt +++ /dev/null @@ -1,66 +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 org.jetbrains.kotlin.backend.wasm.ast - -import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly - -// 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".toLowerCaseAsciiOnly() -} - -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 + "\"" -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmDeclarations.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmDeclarations.kt deleted file mode 100644 index 8d0cc6ec4a6..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmDeclarations.kt +++ /dev/null @@ -1,55 +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 org.jetbrains.kotlin.backend.wasm.ast - -import org.jetbrains.kotlin.backend.wasm.utils.WasmImportPair - -class WasmModule( - val fields: List -) - -sealed class WasmModuleField - -class WasmModuleFieldList( - val fields: List -) : WasmModuleField() - -class WasmFunction( - val name: String, - val parameters: List, - val returnType: WasmValueType?, - val locals: List, - val instructions: List, - 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") - } -} diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmInstructions.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmInstructions.kt deleted file mode 100644 index 59c6f28c1e3..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmInstructions.kt +++ /dev/null @@ -1,65 +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 org.jetbrains.kotlin.backend.wasm.ast - - -sealed class WasmImmediate { - object None : WasmImmediate() - class DeclarationReference(val name: String) : WasmImmediate() - class LiteralValue(val value: T) : WasmImmediate() -} - -sealed class WasmInstruction( - val mnemonic: String, - val immediate: WasmImmediate = WasmImmediate.None, - val operands: List = emptyList() -) - -class WasmSimpleInstruction(mnemonic: String, operands: List) : - WasmInstruction(mnemonic, operands = operands) - -class WasmNop : WasmInstruction("nop") - -class WasmReturn(values: List) : - WasmInstruction("return", operands = values) - -class WasmDrop(instructions: List) : - WasmInstruction("drop", operands = instructions) - -class WasmCall(name: String, operands: List) : - 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("block", operands = instructions) - -sealed class WasmConst(value: KotlinType, type: WasmType) : - WasmInstruction(type.mnemonic + ".const", WasmImmediate.LiteralValue(value)) - -class WasmI32Const(value: Int) : WasmConst(value, WasmI32) -class WasmI64Const(value: Long) : WasmConst(value, WasmI64) -class WasmF32Const(value: Float) : WasmConst(value, WasmF32) -class WasmF64Const(value: Double) : WasmConst(value, WasmF64) diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmTypes.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmTypes.kt deleted file mode 100644 index a31df5ef6de..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ast/WasmTypes.kt +++ /dev/null @@ -1,15 +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 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") \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/BaseTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/BaseTransformer.kt deleted file mode 100644 index 8ea16a07b6d..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/BaseTransformer.kt +++ /dev/null @@ -1,16 +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 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 : IrElementVisitor { - override fun visitElement(element: IrElement, data: D): R { - TODO(element) - } -} diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/DeclarationTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/DeclarationTransformer.kt deleted file mode 100644 index d59251cf660..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/DeclarationTransformer.kt +++ /dev/null @@ -1,123 +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 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 { - 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() - - 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() - 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) - } - ) - } -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ExpressionTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ExpressionTransformer.kt deleted file mode 100644 index ec311c771b7..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ExpressionTransformer.kt +++ /dev/null @@ -1,204 +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 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.IrVariable -import org.jetbrains.kotlin.ir.expressions.* -import org.jetbrains.kotlin.ir.types.isUnit -import org.jetbrains.kotlin.ir.util.dump - -class ExpressionTransformer : BaseTransformer { - 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 visitConst(expression: IrConst, 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 visitSetValue(expression: IrSetValue, 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 - 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) - if (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) -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ModuleTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ModuleTransformer.kt deleted file mode 100644 index adb5dbf50c9..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/ModuleTransformer.kt +++ /dev/null @@ -1,82 +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 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.DescriptorVisibilities -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 { - return JsBlock( - jsAssignment( - JsNameRef("stringLiterals", "runtime"), - JsArrayLiteral(literals.map { JsStringLiteral(it) }) - ).makeStmt() - ).toString() - } - - private fun generateExports(module: IrModuleFragment, context: WasmCodegenContext): List { - val exports = mutableListOf() - 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 != DescriptorVisibilities.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 diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/NameTable.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/NameTable.kt deleted file mode 100644 index 8369181580d..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/NameTable.kt +++ /dev/null @@ -1,64 +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 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 wasmNameTable() = NameTable(sanitizer = ::sanitizeWatIdentifier) - -fun generateWatTopLevelNames(packages: List): Map { - val names = wasmNameTable() - - 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 "$.@_" - diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/StatementTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/StatementTransformer.kt deleted file mode 100644 index 13776fb2694..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/StatementTransformer.kt +++ /dev/null @@ -1,35 +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 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 { - 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 { - if (body is IrBlockBody) { - return body.statements.map { statementToWasmInstruction(it, context) } - } else TODO() -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/TypeTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/TypeTransformer.kt deleted file mode 100644 index 26e8959961a..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/TypeTransformer.kt +++ /dev/null @@ -1,27 +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 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()}") - } \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/WasmCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/WasmCodegenContext.kt deleted file mode 100644 index 21218fc17be..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/codegen/WasmCodegenContext.kt +++ /dev/null @@ -1,29 +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 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, - val backendContext: WasmBackendContext -) { - val imports = mutableListOf() - var localNames: Map = emptyMap() - val stringLiterals = mutableListOf() - - 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}") -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt index 968eb6635ef..0c9c937fe17 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/compiler.kt @@ -9,7 +9,9 @@ import com.intellij.openapi.project.Project import org.jetbrains.kotlin.analyzer.AbstractAnalyzerWithCompilerReport 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.backend.wasm.ir2wasm.WasmModuleFragmentGenerator +import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmCompiledModuleFragment +import org.jetbrains.kotlin.backend.wasm.ir2wasm.generateStringLiteralsSupport import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.languageVersionSettings import org.jetbrains.kotlin.ir.backend.js.MainModule @@ -22,8 +24,11 @@ import org.jetbrains.kotlin.library.KotlinLibrary import org.jetbrains.kotlin.library.resolver.KotlinLibraryResolveResult import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToBinary +import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToText +import java.io.ByteArrayOutputStream -data class WasmCompilerResult(val wat: String, val js: String) +class WasmCompilerResult(val wat: String, val js: String, val wasm: ByteArray) fun compileWasm( project: Project, @@ -60,9 +65,25 @@ fun compileWasm( val irProviders = generateTypicalIrProviderList(moduleDescriptor, irBuiltIns, symbolTable, deserializer) ExternalDependenciesGenerator(symbolTable, irProviders, configuration.languageVersionSettings).generateUnboundSymbolsAsDependencies() moduleFragment.patchDeclarationParents() - deserializer.postProcess() wasmPhases.invokeToplevel(phaseConfig, context, moduleFragment) - return IrModuleToWasm(context).generateModule(moduleFragment) + val compiledWasmModule = WasmCompiledModuleFragment() + val codeGenerator = WasmModuleFragmentGenerator(context, compiledWasmModule) + codeGenerator.generateModule(moduleFragment) + + val linkedModule = compiledWasmModule.linkWasmCompiledFragments() + val watGenerator = WasmIrToText() + watGenerator.appendWasmModule(linkedModule) + val wat = watGenerator.toString() + + val os = ByteArrayOutputStream() + WasmIrToBinary(os, linkedModule).appendWasmModule() + val byteArray = os.toByteArray() + + return WasmCompilerResult( + wat, + generateStringLiteralsSupport(compiledWasmModule.stringLiterals), + wasm = byteArray + ) } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt new file mode 100644 index 00000000000..2dae119441c --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/BodyGenerator.kt @@ -0,0 +1,492 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:OptIn(ExperimentalUnsignedTypes::class) + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.common.ir.isElseBranch +import org.jetbrains.kotlin.backend.common.ir.isOverridable +import org.jetbrains.kotlin.backend.common.ir.returnType +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.backend.wasm.WasmSymbols +import org.jetbrains.kotlin.backend.wasm.lower.wasmSignature +import org.jetbrains.kotlin.backend.wasm.utils.* +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.getInlineClassBackingField +import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.wasm.ir.* + +class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorVoid { + val body: WasmExpressionBuilder = context.bodyGen + + // Shortcuts + private val backendContext: WasmBackendContext = context.backendContext + private val wasmSymbols: WasmSymbols = backendContext.wasmSymbols + private val irBuiltIns: IrBuiltIns = backendContext.irBuiltIns + + override fun visitElement(element: IrElement) { + error("Unexpected element of type ${element::class}") + } + + override fun visitConst(expression: IrConst) { + when (val kind = expression.kind) { + is IrConstKind.Null -> generateDefaultInitializerForType(context.transformType(expression.type), body) + is IrConstKind.Boolean -> body.buildConstI32(if (kind.valueOf(expression)) 1 else 0) + is IrConstKind.Byte -> body.buildConstI32(kind.valueOf(expression).toInt()) + is IrConstKind.Short -> body.buildConstI32(kind.valueOf(expression).toInt()) + is IrConstKind.Int -> body.buildConstI32(kind.valueOf(expression)) + is IrConstKind.Long -> body.buildConstI64(kind.valueOf(expression)) + is IrConstKind.Char -> body.buildConstI32(kind.valueOf(expression).toInt()) + is IrConstKind.Float -> body.buildConstF32(kind.valueOf(expression)) + is IrConstKind.Double -> body.buildConstF64(kind.valueOf(expression)) + is IrConstKind.String -> { + body.buildConstI32Symbol(context.referenceStringLiteral(kind.valueOf(expression))) + body.buildCall(context.referenceFunction(wasmSymbols.stringGetLiteral)) + } + else -> error("Unknown constant kind") + } + } + + override fun visitGetField(expression: IrGetField) { + val field: IrField = expression.symbol.owner + val receiver: IrExpression? = expression.receiver + if (receiver != null) { + generateExpression(receiver) + if (backendContext.inlineClassesUtils.isClassInlineLike(field.parentAsClass)) { + // Unboxed inline class instance is already represented as backing field. + // Doing nothing. + } else { + generateInstanceFieldAccess(field) + } + } else { + body.buildGetGlobal(context.referenceGlobal(field.symbol)) + } + } + + private fun generateInstanceFieldAccess(field: IrField) { + body.buildStructGet( + context.referenceStructType(field.parentAsClass.symbol), + context.getStructFieldRef(field) + ) + } + + override fun visitSetField(expression: IrSetField) { + val field = expression.symbol.owner + val receiver = expression.receiver + + if (receiver != null) { + generateExpression(receiver) + generateExpression(expression.value) + body.buildStructSet( + struct = context.referenceStructType(field.parentAsClass.symbol), + fieldId = context.getStructFieldRef(field), + ) + } else { + generateExpression(expression.value) + body.buildSetGlobal(context.referenceGlobal(expression.symbol)) + } + } + + override fun visitGetValue(expression: IrGetValue) { + body.buildGetLocal(context.referenceLocal(expression.symbol)) + } + + override fun visitSetValue(expression: IrSetValue) { + generateExpression(expression.value) + body.buildSetLocal(context.referenceLocal(expression.symbol)) + } + + override fun visitCall(expression: IrCall) { + generateCall(expression) + } + + override fun visitConstructorCall(expression: IrConstructorCall) { + val klass: IrClass = expression.symbol.owner.parentAsClass + + if (backendContext.inlineClassesUtils.isClassInlineLike(klass)) { + // Unboxed instance is just a constructor argument. + generateExpression(expression.getValueArgument(0)!!) + return + } + + val wasmStruct: WasmSymbol = context.referenceStructType(klass.symbol) + val wasmClassId = context.referenceClassId(klass.symbol) + + val irFields: List = klass.allFields(backendContext.irBuiltIns) + + irFields.forEachIndexed { index, field -> + if (index == 0) + body.buildConstI32Symbol(wasmClassId) + else + generateDefaultInitializerForType(context.transformType(field.type), body) + } + + body.buildGetGlobal(context.referenceClassRTT(klass.symbol)) + body.buildStructNew(wasmStruct) + generateCall(expression) + } + + override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) { + val klass = context.irFunction.parentAsClass + + // Don't delegate constructors of Any to Any. + if (klass.defaultType.isAny()) { + return + } + + body.buildGetLocal(context.referenceLocal(0)) // this parameter + generateCall(expression) + } + + private fun generateCall(call: IrFunctionAccessExpression) { + // Box intrinsic has an additional klass ID argument. + // Processing it separately + if (call.symbol == wasmSymbols.boxIntrinsic) { + val toType = call.getTypeArgument(0)!! + val klass = toType.erasedUpperBound!! + val structTypeName = context.referenceStructType(klass.symbol) + val klassId = context.referenceClassId(klass.symbol) + + body.buildConstI32Symbol(klassId) + generateExpression(call.getValueArgument(0)!!) + body.buildGetGlobal(context.referenceClassRTT(klass.symbol)) + body.buildStructNew(structTypeName) + return + } + + call.dispatchReceiver?.let { generateExpression(it) } + call.extensionReceiver?.let { generateExpression(it) } + for (i in 0 until call.valueArgumentsCount) { + generateExpression(call.getValueArgument(i)!!) + } + + val function: IrFunction = call.symbol.owner.realOverrideTarget + + if (tryToGenerateIntrinsicCall(call, function)) { + return + } + + val isSuperCall = call is IrCall && call.superQualifierSymbol != null + if (function is IrSimpleFunction && function.isOverridable && !isSuperCall) { + // Generating index for indirect call + val klass = function.parentAsClass + if (!klass.isInterface) { + val classMetadata = context.getClassMetadata(klass.symbol) + val vfSlot = classMetadata.virtualMethods.map { it.function }.indexOf(function) + // Dispatch receiver should be simple and without side effects at this point + // TODO: Verify + generateExpression(call.dispatchReceiver!!) + body.buildConstI32(vfSlot) + body.buildCall(context.referenceFunction(wasmSymbols.getVirtualMethodId)) + } else { + val signatureId = context.referenceSignatureId(function.wasmSignature(backendContext.irBuiltIns)) + generateExpression(call.dispatchReceiver!!) + body.buildConstI32Symbol(signatureId) + body.buildCall(context.referenceFunction(wasmSymbols.getInterfaceMethodId)) + } + + body.buildCallIndirect( + symbol = context.referenceFunctionType(function.symbol) + ) + } else { + // Static function call + body.buildCall(context.referenceFunction(function.symbol)) + } + + // Return types of imported functions cannot have concrete struct/array references. + // Non-primitive return types are represented as eqref which need to be casted back to expected type on call site. + if (function.getWasmImportAnnotation() != null) { + val resT = context.transformResultType(function.returnType) + if (resT is WasmRefNullType) { + generateTypeRTT(function.returnType) + body.buildRefCast(fromType = WasmEqRef, toType = resT) + } + } + } + + private fun generateTypeRTT(type: IrType) { + val rtClass = type.erasedUpperBound?.symbol ?: context.backendContext.irBuiltIns.anyClass + body.buildGetGlobal(context.referenceClassRTT(rtClass)) + } + + // Return true if generated. + // Assumes call arguments are already on the stack + private fun tryToGenerateIntrinsicCall( + call: IrFunctionAccessExpression, + function: IrFunction + ): Boolean { + if (tryToGenerateWasmOpIntrinsicCall(function)) { + return true + } + + when (function.symbol) { + wasmSymbols.wasmClassId -> { + val klass = call.getTypeArgument(0)!!.getClass() + ?: error("No class given for wasmClassId intrinsic") + assert(!klass.isInterface) + body.buildConstI32Symbol(context.referenceClassId(klass.symbol)) + } + + wasmSymbols.wasmInterfaceId -> { + val irInterface = call.getTypeArgument(0)!!.getClass() + ?: error("No interface given for wasmInterfaceId intrinsic") + assert(irInterface.isInterface) + body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol)) + } + + wasmSymbols.wasmRefCast -> { + val fromType = call.getTypeArgument(0)!! + val toType = call.getTypeArgument(1)!! + generateTypeRTT(toType) + body.buildRefCast(context.transformType(fromType), context.transformType(toType)) + } + + wasmSymbols.wasmFloatNaN -> { + body.buildConstF32(Float.NaN) + } + wasmSymbols.wasmDoubleNaN -> { + body.buildConstF64(Double.NaN) + } + + wasmSymbols.unboxIntrinsic -> { + val fromType = call.getTypeArgument(0)!! + + if (fromType.isNothing()) { + body.buildUnreachable() + // TODO: Investigate why? + return true + } + + // Workaround test codegen/box/elvis/nullNullOk.kt + if (fromType.makeNotNull().isNothing()) { + body.buildUnreachable() + return true + } + + val toType = call.getTypeArgument(1)!! + val klass: IrClass = backendContext.inlineClassesUtils.getInlinedClass(toType)!! + val field = getInlineClassBackingField(klass) + + generateTypeRTT(toType) + body.buildRefCast(context.transformType(fromType), context.transformBoxedType(toType)) + generateInstanceFieldAccess(field) + } + else -> { + return false + } + } + return true + } + + override fun visitContainerExpression(expression: IrContainerExpression) { + val statements = expression.statements + if (statements.isEmpty()) return + + statements.dropLast(1).forEach { + statementToWasmInstruction(it) + } + + if (expression.type != irBuiltIns.unitType) { + generateExpression(statements.last() as IrExpression) + } else { + statementToWasmInstruction(statements.last()) + } + } + + override fun visitBreak(jump: IrBreak) { + body.buildBr(context.referenceLoopLevel(jump.loop, LoopLabelType.BREAK)) + } + + override fun visitContinue(jump: IrContinue) { + body.buildBr(context.referenceLoopLevel(jump.loop, LoopLabelType.CONTINUE)) + } + + override fun visitReturn(expression: IrReturn) { + generateExpression(expression.value) + + // FIXME: Hack for "returning" Unit from functions with generic return type. + // Common case -- lambdas returning unit. + if (expression.value.type == irBuiltIns.unitType && + expression.returnTargetSymbol.owner.returnType(backendContext) != irBuiltIns.unitType + ) { + val irReturnType = expression.returnTargetSymbol.owner.returnType(backendContext) + + if (irReturnType != irBuiltIns.unitType) { + generateDefaultInitializerForType(context.transformType(irReturnType), body) + } + } + + body.buildInstr(WasmOp.RETURN) + } + + override fun visitWhen(expression: IrWhen) { + if (expression.type == irBuiltIns.unitType) { + var ifCount = 0 + for (branch in expression.branches) { + if (!isElseBranch(branch)) { + generateExpression(branch.condition) + body.buildIf(label = null, resultType = null) + statementToWasmInstruction(branch.result) + body.buildElse() + ifCount++ + } else { + statementToWasmInstruction(branch.result) + break + } + } + + repeat(ifCount) { body.buildEnd() } + return + } + + val resultType = context.transformBlockResultType(expression.type) + var ifCount = 0 + for (branch in expression.branches) { + if (!isElseBranch(branch)) { + generateExpression(branch.condition) + body.buildIf(null, resultType) + generateExpression(branch.result) + if (expression.type == irBuiltIns.nothingType) { + body.buildUnreachable() + } + body.buildElse() + ifCount++ + } else { + generateExpression(branch.result) + if (expression.type == irBuiltIns.nothingType) { + body.buildUnreachable() + } + break + } + } + + repeat(ifCount) { body.buildEnd() } + } + + override fun visitDoWhileLoop(loop: IrDoWhileLoop) { + // (loop $LABEL + // (block $BREAK_LABEL + // (block $CONTINUE_LABEL ) + // (br_if $LABEL ))) + + val label = loop.label + + body.buildLoop(label) + val wasmLoop = body.numberOfNestedBlocks + + body.buildBlock("BREAK_$label") + val wasmBreakBlock = body.numberOfNestedBlocks + + body.buildBlock("CONTINUE_$label") + val wasmContinueBlock = body.numberOfNestedBlocks + + context.defineLoopLevel(loop, LoopLabelType.BREAK, wasmBreakBlock) + context.defineLoopLevel(loop, LoopLabelType.CONTINUE, wasmContinueBlock) + + loop.body?.let { statementToWasmInstruction(it) } + body.buildEnd() + generateExpression(loop.condition) + body.buildBrIf(wasmLoop) + body.buildEnd() + body.buildEnd() + } + + override fun visitWhileLoop(loop: IrWhileLoop) { + // (loop $CONTINUE_LABEL + // (block $BREAK_LABEL + // (br_if $BREAK_LABEL (i32.eqz )) + // + // (br $CONTINUE_LABEL))) + + val label = loop.label + + body.buildLoop(label) + val wasmLoop = body.numberOfNestedBlocks + + body.buildBlock("BREAK_$label") + val wasmBreakBlock = body.numberOfNestedBlocks + + context.defineLoopLevel(loop, LoopLabelType.BREAK, wasmBreakBlock) + context.defineLoopLevel(loop, LoopLabelType.CONTINUE, wasmLoop) + + generateExpression(loop.condition) + body.buildInstr(WasmOp.I32_EQZ) + body.buildBrIf(wasmBreakBlock) + loop.body?.let { + statementToWasmInstruction(it) + } + body.buildBr(wasmLoop) + body.buildEnd() + body.buildEnd() + } + + fun generateExpression(expression: IrExpression) { + expression.acceptVoid(this) + + if (expression.type == irBuiltIns.nothingType) { + body.buildUnreachable() + } + } + + fun statementToWasmInstruction(statement: IrStatement) { + if (statement is IrVariable) { + context.defineLocal(statement.symbol) + val init = statement.initializer ?: return + generateExpression(init) + val varName = context.referenceLocal(statement.symbol) + body.buildSetLocal(varName) + return + } + + generateExpression(statement as IrExpression) + + if (statement.type != irBuiltIns.unitType && statement.type != irBuiltIns.nothingType) { + body.buildInstr(WasmOp.DROP) + } + } + + // Return true if function is recognized as intrinsic. + fun tryToGenerateWasmOpIntrinsicCall(function: IrFunction): Boolean { + if (function.hasWasmReinterpretAnnotation()) { + return true + } + + val opString = function.getWasmOpAnnotation() + if (opString != null) { + val op = WasmOp.valueOf(opString) + var immediates = emptyArray() + when (op.immediates.size) { + 0 -> { + } + 1 -> { + when (val imm = op.immediates[0]) { + WasmImmediateKind.MEM_ARG -> + immediates = arrayOf(WasmImmediate.MemArg(0u, 0u)) + else -> + error("Immediate $imm is unsupported") + } + } + else -> + error("Op $opString is unsupported") + } + body.buildInstr(op, *immediates) + return true + } + + return false + } +} + diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt new file mode 100644 index 00000000000..32f55adec0d --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ClassInfo.kt @@ -0,0 +1,113 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides +import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature +import org.jetbrains.kotlin.backend.wasm.lower.wasmSignature +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.types.classifierOrFail +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.ir.util.isInterface + +class ClassMetadata( + val klass: IrClass, + val superClass: ClassMetadata?, + irBuiltIns: IrBuiltIns +) { + // List of all fields including fields of super classes + // In Wasm order + val fields: List = + superClass?.fields.orEmpty() + klass.declarations.filterIsInstance() + + // Implemented interfaces in no particular order + val interfaces: List = klass.allSuperInterfaces() + + // Virtual methods in Wasm order + // TODO: Collect interface methods separately + val virtualMethods: List = run { + val virtualFunctions = + klass.declarations + .filterVirtualFunctions() + .map { + VirtualMethodMetadata( + it, + it.wasmSignature(irBuiltIns) + ) + } + + val signatureToVirtualFunction = virtualFunctions.associateBy { it.signature } + + val superSignatures = superClass?.virtualMethodsSignatures.orEmpty() + + val newVirtualMethods = virtualFunctions.filter { it.signature !in superSignatures } + val superVirtualMethods = superClass?.virtualMethods.orEmpty().map { + signatureToVirtualFunction[it.signature] ?: it + } + val orderedVirtualFunctions = superVirtualMethods + newVirtualMethods + + orderedVirtualFunctions + } + + init { + val signatureToFunctions = mutableMapOf>() + for (vm in virtualMethods) { + signatureToFunctions.getOrPut(vm.signature) { mutableListOf() }.add(vm.function) + } + + for ((sig, functions) in signatureToFunctions) { + if (functions.size > 1) { + val funcList = functions.joinToString { " ---- ${it.fqNameWhenAvailable} \n" } + // TODO: Check in FE + error( + "Class ${klass.fqNameWhenAvailable} has ${functions.size} methods with the same signature $sig\n $funcList" + ) + } + } + } + + private val virtualMethodsSignatures: Set = + virtualMethods.map { it.signature }.toSet() +} + +class VirtualMethodMetadata( + val function: IrSimpleFunction, + val signature: WasmSignature +) + +fun IrClass.allSuperInterfaces(): List = + superTypes.map { + it.classifierOrFail.owner as IrClass + }.flatMap { + (if (it.isInterface) listOf(it) else emptyList()) + it.allSuperInterfaces() + } + +fun List.filterVirtualFunctions(): List = + asSequence() + .filterIsInstance() + .filter { it.dispatchReceiverParameter != null } + .map { it.realOverrideTarget } + .filter { it.isOverridableOrOverrides } + .distinct() + .toList() + +fun IrClass.getSuperClass(builtIns: IrBuiltIns): IrClass? = + when (this) { + builtIns.anyClass.owner -> null + else -> { + superTypes + .map { it.classifierOrFail.owner as IrClass } + .singleOrNull { !it.isInterface } ?: builtIns.anyClass.owner + } + } + +fun IrClass.allFields(builtIns: IrBuiltIns): List = + getSuperClass(builtIns)?.allFields(builtIns).orEmpty() + declarations.filterIsInstance() diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt new file mode 100644 index 00000000000..d427e77b11d --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/ConstantData.kt @@ -0,0 +1,70 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.wasm.ir.WasmSymbol + +// Representation of constant data in Wasm memory + +sealed class ConstantDataElement { + abstract val sizeInBytes: Int + abstract fun dump(indent: String = "", startAddress: Int = 0): String + abstract fun toBytes(): ByteArray +} + +private fun addressToString(address: Int): String = + address.toString().padEnd(6, ' ') + +class ConstantDataIntField(val name: String, val value: WasmSymbol) : ConstantDataElement() { + constructor(name: String, value: Int) : this(name, WasmSymbol(value)) + + override fun toBytes(): ByteArray = value.owner.toLittleEndianBytes() + + override fun dump(indent: String, startAddress: Int): String { + return "${addressToString(startAddress)}: $indent i32 : ${value.owner} ;; $name\n" + } + + override val sizeInBytes: Int = 4 +} + +class ConstantDataIntArray(val name: String, val value: List>) : ConstantDataElement() { + override fun toBytes(): ByteArray { + return value.fold(byteArrayOf()) { acc, el -> acc + el.owner.toLittleEndianBytes() } + } + + override fun dump(indent: String, startAddress: Int): String { + if (value.isEmpty()) return "" + return "${addressToString(startAddress)}: $indent i32[] : ${value.map { it.owner }.toIntArray().contentToString()} ;; $name\n" + } + + override val sizeInBytes: Int = value.size * 4 +} + +class ConstantDataStruct(val name: String, val elements: List) : ConstantDataElement() { + override fun toBytes(): ByteArray { + return elements.fold(byteArrayOf()) { acc, el -> acc + el.toBytes() } + } + + override fun dump(indent: String, startAddress: Int): String { + var res = "$indent;; $name\n" + var elemStartAddr = startAddress + + for (el in elements) { + res += el.dump("$indent ", elemStartAddr) + elemStartAddr += el.sizeInBytes + } + + return res + } + + override val sizeInBytes: Int = elements.map { it.sizeInBytes }.sum() +} + +fun Int.toLittleEndianBytes(): ByteArray { + return ByteArray(4) { + (this ushr (it * 8)).toByte() + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt new file mode 100644 index 00000000000..467e654be56 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/DeclarationGenerator.kt @@ -0,0 +1,320 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.backend.wasm.utils.* +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.expressions.IrBlockBody +import org.jetbrains.kotlin.ir.expressions.IrExpressionBody +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptVoid +import org.jetbrains.kotlin.wasm.ir.* + +class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVisitorVoid { + + // Shortcuts + private val backendContext: WasmBackendContext = context.backendContext + private val irBuiltIns: IrBuiltIns = backendContext.irBuiltIns + + override fun visitElement(element: IrElement) { + error("Unexpected element of type ${element::class}") + } + + override fun visitTypeAlias(declaration: IrTypeAlias) { + // Type aliases are not material + } + + override fun visitFunction(declaration: IrFunction) { + // Inline class constructors are currently empty + if (declaration is IrConstructor && backendContext.inlineClassesUtils.isClassInlineLike(declaration.parentAsClass)) + return + + val importedName = declaration.getWasmImportAnnotation() + + val isIntrinsic = declaration.hasWasmReinterpretAnnotation() || declaration.getWasmOpAnnotation() != null + if (isIntrinsic) { + return + } + + if (declaration.isFakeOverride) + return + + // Generate function type + val watName = declaration.fqNameWhenAvailable.toString() + val irParameters = declaration.getEffectiveValueParameters() + val wasmFunctionType = + WasmFunctionType( + name = watName, + parameterTypes = irParameters.map { + val t = context.transformValueParameterType(it) + if (importedName != null && t is WasmRefNullType) { + WasmEqRef + } else { + t + } + }, + resultTypes = listOfNotNull( + context.transformResultType(declaration.returnType).let { + if (importedName != null && it is WasmRefNullType) WasmEqRef else it + } + ) + ) + context.defineFunctionType(declaration.symbol, wasmFunctionType) + + if (declaration is IrSimpleFunction) { + if (declaration.modality == Modality.ABSTRACT) return + if (declaration.isOverridableOrOverrides) { + // Register function as virtual, meaning this function + // will be stored Wasm table and could be called indirectly. + context.registerVirtualFunction(declaration.symbol) + } + } + + assert(declaration == declaration.realOverrideTarget) { + "Sanity check that $declaration is a real function that can be used in calls" + } + + if (importedName != null) { + // Imported functions don't have bodies. Declaring the signature: + context.defineFunction( + declaration.symbol, + WasmFunction.Imported(watName, wasmFunctionType, importedName) + ) + // TODO: Support re-export of imported functions. + return + } + + val function = WasmFunction.Defined(watName, wasmFunctionType) + val functionCodegenContext = WasmFunctionCodegenContextImpl( + declaration, + function, + backendContext, + context + ) + + for (irParameter in irParameters) { + functionCodegenContext.defineLocal(irParameter.symbol) + } + + val exprGen = functionCodegenContext.bodyGen + val bodyBuilder = BodyGenerator(functionCodegenContext) + + when (val body = declaration.body) { + is IrBlockBody -> + for (statement in body.statements) { + bodyBuilder.statementToWasmInstruction(statement) + } + + is IrExpressionBody -> + bodyBuilder.generateExpression(body.expression) + + else -> error("Unexpected body $body") + } + + // Return implicit this from constructions to avoid extra tmp + // variables on constructor call sites. + // TODO: Redesign construction scheme. + if (declaration is IrConstructor) { + exprGen.buildGetLocal(/*implicit this*/ function.locals[0]) + exprGen.buildInstr(WasmOp.RETURN) + } + + // Add unreachable if function returns something but not as a last instruction. + if (wasmFunctionType.resultTypes.isNotEmpty() && declaration.body is IrBlockBody) { + // TODO: Add unreachable only if needed + exprGen.buildUnreachable() + } + + context.defineFunction(declaration.symbol, function) + + if (declaration == backendContext.startFunction) + context.setStartFunction(function) + + if (declaration.isExported(backendContext)) { + context.addExport( + WasmExport.Function( + field = function, + // TODO: Add ability to specify exported name. + name = declaration.name.identifier + ) + ) + } + } + + override fun visitClass(declaration: IrClass) { + if (declaration.isAnnotationClass) return + val symbol = declaration.symbol + + if (declaration.isInterface) { + context.registerInterface(symbol) + } else { + val nameStr = declaration.fqNameWhenAvailable.toString() + val structType = WasmStructDeclaration( + name = nameStr, + fields = declaration.allFields(irBuiltIns).map { + WasmStructFieldDeclaration( + name = it.name.toString(), + type = context.transformType(it.type), + isMutable = true + ) + } + ) + + context.defineStructType(symbol, structType) + + var depth = 2 + val metadata = context.getClassMetadata(symbol) + var subMetadata = metadata + while (true) { + subMetadata = subMetadata.superClass ?: break + depth++ + } + + val initBody = mutableListOf() + val wasmExpressionGenerator = WasmIrExpressionBuilder(initBody) + + val superClass = metadata.superClass + if (superClass != null) { + val superRTT = context.referenceClassRTT(superClass.klass.symbol) + wasmExpressionGenerator.buildGetGlobal(superRTT) + } else { + wasmExpressionGenerator.buildRttCanon(WasmRefType(WasmHeapType.Simple.Eq)) + } + + wasmExpressionGenerator.buildRttSub( + WasmRefType(WasmHeapType.Type(WasmSymbol(structType))) + ) + + val rtt = WasmGlobal( + name = "rtt_of_$nameStr", + isMutable = false, + type = WasmRtt(depth, WasmHeapType.Type(WasmSymbol(structType))), + init = initBody + ) + + context.defineRTT(symbol, rtt) + context.registerClass(symbol) + context.generateTypeInfo(symbol, binaryDataStruct(metadata)) + } + + for (member in declaration.declarations) { + member.acceptVoid(this) + } + } + + private fun binaryDataStruct(classMetadata: ClassMetadata): ConstantDataStruct { + val invalidIndex = -1 + val superClass = classMetadata.superClass?.klass + + val superClassSymbol: WasmSymbol = + superClass?.let { context.referenceClassId(it.symbol) } ?: WasmSymbol(invalidIndex) + + val superTypeField = + ConstantDataIntField("Super class", superClassSymbol) + + val interfacesArray = ConstantDataIntArray( + "data", + classMetadata.interfaces.map { context.referenceInterfaceId(it.symbol) } + ) + val interfacesArraySize = ConstantDataIntField( + "size", + interfacesArray.value.size + ) + + val implementedInterfacesArrayWithSize = ConstantDataStruct( + "Implemented interfaces array", + listOf(interfacesArraySize, interfacesArray) + ) + + val vtableSizeField = ConstantDataIntField( + "V-table length", + classMetadata.virtualMethods.size + ) + + val vtableArray = ConstantDataIntArray( + "V-table", + classMetadata.virtualMethods.map { + if (it.function.modality == Modality.ABSTRACT) { + WasmSymbol(invalidIndex) + } else { + context.referenceVirtualFunctionId(it.function.symbol) + } + } + ) + + val signaturesArray = ConstantDataIntArray( + "Signatures", + classMetadata.virtualMethods.map { + if (it.function.modality == Modality.ABSTRACT) { + WasmSymbol(invalidIndex) + } else { + context.referenceSignatureId(it.signature) + } + } + ) + + return ConstantDataStruct( + "Class TypeInfo: ${classMetadata.klass.fqNameWhenAvailable} ", + listOf( + superTypeField, + vtableSizeField, + vtableArray, + signaturesArray, + implementedInterfacesArrayWithSize, + ) + ) + } + + override fun visitField(declaration: IrField) { + // Member fields are generated as part of struct type + if (!declaration.isStatic) return + + val wasmType = context.transformType(declaration.type) + + val initBody = mutableListOf() + val wasmExpressionGenerator = WasmIrExpressionBuilder(initBody) + generateDefaultInitializerForType(wasmType, wasmExpressionGenerator) + + val global = WasmGlobal( + name = declaration.fqNameWhenAvailable.toString(), + type = wasmType, + isMutable = true, + // All globals are currently initialized in start function + init = initBody + ) + + context.defineGlobal(declaration.symbol, global) + } +} + + +fun generateDefaultInitializerForType(type: WasmType, g: WasmExpressionBuilder) = when (type) { + WasmI32 -> g.buildConstI32(0) + WasmI1 -> g.buildConstI32(0) + WasmI64 -> g.buildConstI64(0) + WasmF32 -> g.buildConstF32(0f) + WasmF64 -> g.buildConstF64(0.0) + is WasmRefNullType -> g.buildRefNull(type.heapType) + is WasmExternRef -> g.buildRefNull(WasmHeapType.Simple.Extern) + WasmUnreachableType -> error("Unreachable type can't be initialized") + else -> error("Unknown value type ${type.name}") +} + +fun IrFunction.getEffectiveValueParameters(): List { + val implicitThis = if (this is IrConstructor) parentAsClass.thisReceiver!! else null + return listOfNotNull(implicitThis, dispatchReceiverParameter, extensionReceiverParameter) + valueParameters +} + +fun IrFunction.isExported(context: WasmBackendContext): Boolean = + visibility == DescriptorVisibilities.PUBLIC && fqNameWhenAvailable in context.additionalExportedDeclarations \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/JsHelpers.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/JsHelpers.kt new file mode 100644 index 00000000000..ce94c92dbf6 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/JsHelpers.kt @@ -0,0 +1,21 @@ +/* + * 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.ir2wasm + +import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.jsAssignment +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 + +fun generateStringLiteralsSupport(literals: List): String { + return JsBlock( + jsAssignment( + JsNameRef("stringLiterals", "runtime"), + JsArrayLiteral(literals.map { JsStringLiteral(it) }) + ).makeStmt() + ).toString() +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt new file mode 100644 index 00000000000..584a710f37b --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/TypeTransformer.kt @@ -0,0 +1,118 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.backend.wasm.utils.hasWasmForeignAnnotation +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.types.classifierOrNull +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.util.getInlineClassUnderlyingType +import org.jetbrains.kotlin.ir.util.isInterface + +class WasmTypeTransformer( + val context: WasmBaseCodegenContext, + val builtIns: IrBuiltIns +) { + fun IrType.toWasmResultType(): WasmType? = + when (this) { + builtIns.unitType, + builtIns.nothingType -> + null + + else -> + toWasmValueType() + } + + fun IrType.toWasmBlockResultType(): WasmType? = + when (this) { + builtIns.unitType -> + null + + // TODO: Lower blocks with Nothing type? + builtIns.nothingType -> + WasmUnreachableType + + else -> + toWasmValueType() + } + + fun IrType.toStructType(): WasmType = + WasmRefNullType(WasmHeapType.Type(context.referenceStructType(erasedUpperBound?.symbol ?: builtIns.anyClass))) + + fun IrType.toBoxedInlineClassType(): WasmType = + toStructType() + + fun IrType.toWasmValueType(): WasmType = + when (this) { + builtIns.booleanType, + builtIns.byteType, + builtIns.shortType, + builtIns.intType, + builtIns.charType -> + WasmI32 + + builtIns.longType -> + WasmI64 + + builtIns.floatType -> + WasmF32 + + builtIns.doubleType -> + WasmF64 + + builtIns.stringType -> + WasmExternRef + + builtIns.nothingNType -> + WasmExternRef + + // Value will not be created. Just using a random Wasm type. + builtIns.nothingType -> + WasmExternRef + + else -> { + val klass = this.getClass() + val ic = context.backendContext.inlineClassesUtils.getInlinedClass(this) + + if (klass != null && klass.hasWasmForeignAnnotation()) { + WasmExternRef + } else if (ic != null) { + getInlineClassUnderlyingType(ic).toWasmValueType() + } else { + this.toStructType() + } + } + } +} + + +// Return null if upper bound is Any +val IrTypeParameter.erasedUpperBound: IrClass? + get() { + // Pick the (necessarily unique) non-interface upper bound if it exists + for (type in superTypes) { + return type.erasedUpperBound ?: continue + } + + return null + } + +val IrType.erasedUpperBound: IrClass? + get() = when (val classifier = classifierOrNull) { + is IrClassSymbol -> classifier.owner + is IrTypeParameterSymbol -> classifier.owner.erasedUpperBound + else -> throw IllegalStateException() + }.let { + if (it?.isInterface == true) null + else it + } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt new file mode 100644 index 00000000000..13ea4f95b2e --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmBaseCodegenContext.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType + +interface WasmBaseCodegenContext { + val backendContext: WasmBackendContext + + fun referenceFunction(irFunction: IrFunctionSymbol): WasmSymbol + fun referenceGlobal(irField: IrFieldSymbol): WasmSymbol + fun referenceStructType(irClass: IrClassSymbol): WasmSymbol + fun referenceFunctionType(irFunction: IrFunctionSymbol): WasmSymbol + + fun referenceClassId(irClass: IrClassSymbol): WasmSymbol + fun referenceInterfaceId(irInterface: IrClassSymbol): WasmSymbol + fun referenceVirtualFunctionId(irFunction: IrSimpleFunctionSymbol): WasmSymbol + fun referenceClassRTT(irClass: IrClassSymbol): WasmSymbol + + fun referenceSignatureId(signature: WasmSignature): WasmSymbol + + fun referenceStringLiteral(string: String): WasmSymbol + + fun transformType(irType: IrType): WasmType + fun transformBoxedType(irType: IrType): WasmType + fun transformValueParameterType(irValueParameter: IrValueParameter): WasmType + fun transformResultType(irType: IrType): WasmType? + fun transformBlockResultType(irType: IrType): WasmType? + + + fun getStructFieldRef(field: IrField): WasmSymbol + fun getClassMetadata(irClass: IrClassSymbol): ClassMetadata +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt new file mode 100644 index 00000000000..68192a71dd6 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmCompiledModuleFragment.kt @@ -0,0 +1,207 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrExternalPackageFragment +import org.jetbrains.kotlin.ir.symbols.* +import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.ir.util.getPackageFragment + +class WasmCompiledModuleFragment { + val functions = + ReferencableAndDefinable() + val globals = + ReferencableAndDefinable() + val functionTypes = + ReferencableAndDefinable() + val structTypes = + ReferencableAndDefinable() + val classIds = + ReferencableElements() + val interfaceId = + ReferencableElements() + val virtualFunctionId = + ReferencableElements() + val signatureId = + ReferencableElements() + val stringLiteralId = + ReferencableElements() + + val runtimeTypes = + ReferencableAndDefinable() + + val classes = mutableListOf() + val interfaces = mutableListOf() + val virtualFunctions = mutableListOf() + val signatures = LinkedHashSet() + val stringLiterals = mutableListOf() + + val typeInfo = + ReferencableAndDefinable() + val exports = mutableListOf>() + + // + var startFunction: WasmFunction? = null + + open class ReferencableElements { + val unbound = mutableMapOf>() + fun reference(ir: Ir): WasmSymbol { + val declaration = (ir as? IrSymbol)?.owner as? IrDeclarationWithName + if (declaration != null) { + val packageFragment = declaration.getPackageFragment() + ?: error("Referencing declaration without package fragment ${declaration.fqNameWhenAvailable}") + if (packageFragment is IrExternalPackageFragment) { + error("Referencing declaration without package fragment ${declaration.fqNameWhenAvailable}") + } + } + return unbound.getOrPut(ir) { WasmSymbol() } + } + } + + class ReferencableAndDefinable : ReferencableElements() { + fun define(ir: Ir, wasm: Wasm) { + if (ir in defined) + error("Trying to redefine element: IR: $ir Wasm: $wasm") + + elements += wasm + defined[ir] = wasm + wasmToIr[wasm] = ir + } + + val defined = LinkedHashMap() + val elements = mutableListOf() + + val wasmToIr = mutableMapOf() + } + + @OptIn(ExperimentalUnsignedTypes::class) + fun linkWasmCompiledFragments(): WasmModule { + bind(functions.unbound, functions.defined) + bind(globals.unbound, globals.defined) + bind(functionTypes.unbound, functionTypes.defined) + bind(structTypes.unbound, structTypes.defined) + bind(runtimeTypes.unbound, runtimeTypes.defined) + + val klassIds = mutableMapOf() + var classId = 0 + for (typeInfoElement in typeInfo.elements) { + val ir = typeInfo.wasmToIr.getValue(typeInfoElement) + klassIds[ir] = classId + classId += typeInfoElement.sizeInBytes + } + + bind(classIds.unbound, klassIds) + bindIndices(virtualFunctionId.unbound, virtualFunctions) + bindIndices(signatureId.unbound, signatures.toList()) + bindIndices(interfaceId.unbound, interfaces) + bindIndices(stringLiteralId.unbound, stringLiterals) + + val data = typeInfo.elements.map { + val ir = typeInfo.wasmToIr.getValue(it) + val id = klassIds.getValue(ir) + val offset = mutableListOf() + WasmIrExpressionBuilder(offset).buildConstI32(id) + WasmData(WasmDataMode.Active(0, offset), it.toBytes()) + } + + val logTypeInfo = false + if (logTypeInfo) { + println("Signatures: ") + for ((index, signature: WasmSignature) in signatures.withIndex()) { + println(" -- $index $signature") + } + + println("Interfaces: ") + for ((index, iface: IrClassSymbol) in interfaces.withIndex()) { + println(" -- $index ${iface.owner.fqNameWhenAvailable}") + } + + println("Virtual functions: ") + for ((index, vf: IrSimpleFunctionSymbol) in virtualFunctions.withIndex()) { + println(" -- $index ${vf.owner.fqNameWhenAvailable}") + } + + println( + ConstantDataStruct("typeInfo", typeInfo.elements).dump("", 0) + ) + } + + val table = WasmTable( + limits = WasmLimits(virtualFunctions.size.toUInt(), virtualFunctions.size.toUInt()), + elementType = WasmFuncRef, + ) + + val offsetExpr = mutableListOf() + WasmIrExpressionBuilder(offsetExpr).buildConstI32(0) + + val elements = WasmElement( + WasmFuncRef, + values = virtualFunctions.map { + WasmTable.Value.Function(functions.defined.getValue(it)) + }, + WasmElement.Mode.Active(table, offsetExpr) + ) + + val typeInfoSize = classId + val memorySizeInPages = (typeInfoSize / 65_536) + 1 + val memory = WasmMemory(WasmLimits(memorySizeInPages.toUInt(), memorySizeInPages.toUInt())) + + val importedFunctions = functions.elements.filterIsInstance() + + // Sorting by depth for a valid init order + val sortedRttGlobals = runtimeTypes.elements.sortedBy { (it.type as WasmRtt).depth } + + val module = WasmModule( + functionTypes = functionTypes.elements, + structs = structTypes.elements, + importsInOrder = importedFunctions, + importedFunctions = importedFunctions, + definedFunctions = functions.elements.filterIsInstance(), + tables = listOf(table), + memories = listOf(memory), + globals = globals.elements + sortedRttGlobals, + exports = exports, + startFunction = startFunction!!, + elements = listOf(elements), + data = data + ) + module.calculateIds() + return module + } +} + +fun > bind( + unbound: Map, + defined: Map +) { + unbound.forEach { (irSymbol, wasmSymbol) -> + if (irSymbol !in defined) + error("Can't link symbol ${irSymbolDebugDump(irSymbol)}") + wasmSymbol.bind(defined.getValue(irSymbol)) + } +} + +private fun irSymbolDebugDump(symbol: Any?): String = + when (symbol) { + is IrFunctionSymbol -> "function ${symbol.owner.fqNameWhenAvailable}" + is IrClassSymbol -> "class ${symbol.owner.fqNameWhenAvailable}" + else -> symbol.toString() + } + +fun bindIndices( + unbound: Map>, + ordered: List +) { + unbound.forEach { (irSymbol, wasmSymbol) -> + val index = ordered.indexOf(irSymbol) + if (index == -1) + error("Can't link symbol with indices ${irSymbolDebugDump(irSymbol)}") + wasmSymbol.bind(index) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt new file mode 100644 index 00000000000..86a4023f250 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContext.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.expressions.IrLoop +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.wasm.ir.WasmExpressionBuilder +import org.jetbrains.kotlin.wasm.ir.WasmInstr +import org.jetbrains.kotlin.wasm.ir.WasmLocal + +enum class LoopLabelType { BREAK, CONTINUE } + +interface WasmFunctionCodegenContext : WasmBaseCodegenContext { + val irFunction: IrFunction + + fun defineLocal(irValueDeclaration: IrValueSymbol) + fun referenceLocal(irValueDeclaration: IrValueSymbol): WasmLocal + fun referenceLocal(index: Int): WasmLocal + + fun defineLoopLevel(irLoop: IrLoop, labelType: LoopLabelType, level: Int) + fun referenceLoopLevel(irLoop: IrLoop, labelType: LoopLabelType): Int + + val bodyGen: WasmExpressionBuilder +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContextImpl.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContextImpl.kt new file mode 100644 index 00000000000..fad8a5ef160 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmFunctionCodegenContextImpl.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.expressions.IrLoop +import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol +import org.jetbrains.kotlin.ir.symbols.IrValueSymbol +import org.jetbrains.kotlin.wasm.ir.* + +class WasmFunctionCodegenContextImpl( + override val irFunction: IrFunction, + private val wasmFunction: WasmFunction.Defined, + override val backendContext: WasmBackendContext, + private val referencing: WasmBaseCodegenContext +) : WasmBaseCodegenContext by referencing, + WasmFunctionCodegenContext { + override val bodyGen: WasmExpressionBuilder = + WasmIrExpressionBuilder(wasmFunction.instructions) + + private val wasmLocals = LinkedHashMap() + private val loopLevels = LinkedHashMap, Int>() + + override fun defineLocal(irValueDeclaration: IrValueSymbol) { + assert(irValueDeclaration !in wasmLocals) { "Redefinition of local" } + + val owner = irValueDeclaration.owner + val wasmLocal = WasmLocal( + wasmFunction.locals.size, + owner.name.asString(), + if (owner is IrValueParameter) transformValueParameterType(owner) else transformType(owner.type), + isParameter = irValueDeclaration is IrValueParameterSymbol + ) + + wasmLocals[irValueDeclaration] = wasmLocal + wasmFunction.locals += wasmLocal + } + + override fun referenceLocal(irValueDeclaration: IrValueSymbol): WasmLocal { + return wasmLocals.getValue(irValueDeclaration) + } + + override fun referenceLocal(index: Int): WasmLocal { + return wasmFunction.locals[index] + } + + override fun defineLoopLevel(irLoop: IrLoop, labelType: LoopLabelType, level: Int) { + val loopKey = Pair(irLoop, labelType) + assert(loopKey !in loopLevels) { "Redefinition of loop" } + loopLevels[loopKey] = level + } + + override fun referenceLoopLevel(irLoop: IrLoop, labelType: LoopLabelType): Int { + return loopLevels.getValue(Pair(irLoop, labelType)) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt new file mode 100644 index 00000000000..df84575374b --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContext.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.backend.wasm.ir2wasm.ConstantDataElement +import org.jetbrains.kotlin.backend.wasm.ir2wasm.WasmBaseCodegenContext +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol + +/** + * Interface for generating WebAssembly module. + */ +interface WasmModuleCodegenContext : WasmBaseCodegenContext { + fun defineFunction(irFunction: IrFunctionSymbol, wasmFunction: WasmFunction) + fun defineGlobal(irField: IrFieldSymbol, wasmGlobal: WasmGlobal) + fun defineStructType(irClass: IrClassSymbol, wasmStruct: WasmStructDeclaration) + fun defineRTT(irClass: IrClassSymbol, wasmGlobal: WasmGlobal) + fun defineFunctionType(irFunction: IrFunctionSymbol, wasmFunctionType: WasmFunctionType) + + fun setStartFunction(wasmFunction: WasmFunction) + fun addExport(wasmExport: WasmExport<*>) + + fun registerVirtualFunction(irFunction: IrSimpleFunctionSymbol) + fun registerInterface(irInterface: IrClassSymbol) + fun registerClass(irClass: IrClassSymbol) + + fun generateTypeInfo(irClass: IrClassSymbol, typeInfo: ConstantDataElement) +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt new file mode 100644 index 00000000000..c642012504e --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleCodegenContextImpl.kt @@ -0,0 +1,169 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.wasm.ir.* +import org.jetbrains.kotlin.backend.wasm.lower.WasmSignature +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrValueParameter +import org.jetbrains.kotlin.ir.symbols.IrClassSymbol +import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol +import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.defaultType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.util.isFunction +import org.jetbrains.kotlin.ir.util.parentAsClass + + +class WasmModuleCodegenContextImpl( + override val backendContext: WasmBackendContext, + private val wasmFragment: WasmCompiledModuleFragment +) : WasmModuleCodegenContext { + private val typeTransformer = + WasmTypeTransformer(this, backendContext.irBuiltIns) + + override fun transformType(irType: IrType): WasmType { + return with(typeTransformer) { irType.toWasmValueType() } + } + + override fun transformBoxedType(irType: IrType): WasmType { + return with(typeTransformer) { irType.toBoxedInlineClassType() } + } + + override fun transformValueParameterType(irValueParameter: IrValueParameter): WasmType { + return with(typeTransformer) { + if (context.backendContext.inlineClassesUtils.shouldValueParameterBeBoxed(irValueParameter)) { + irValueParameter.type.toBoxedInlineClassType() + } else { + irValueParameter.type.toWasmValueType() + } + } + } + + override fun transformResultType(irType: IrType): WasmType? { + return with(typeTransformer) { irType.toWasmResultType() } + } + + override fun transformBlockResultType(irType: IrType): WasmType? { + return with(typeTransformer) { irType.toWasmBlockResultType() } + } + + override fun referenceStringLiteral(string: String): WasmSymbol { + wasmFragment.stringLiterals.add(string) + return wasmFragment.stringLiteralId.reference(string) + } + + override fun generateTypeInfo(irClass: IrClassSymbol, typeInfo: ConstantDataElement) { + wasmFragment.typeInfo.define(irClass, typeInfo) + } + + override fun setStartFunction(wasmFunction: WasmFunction) { + wasmFragment.startFunction = wasmFunction + } + + override fun addExport(wasmExport: WasmExport<*>) { + wasmFragment.exports += wasmExport + } + + override fun registerVirtualFunction(irFunction: IrSimpleFunctionSymbol) { + wasmFragment.virtualFunctions += irFunction + } + + override fun registerInterface(irInterface: IrClassSymbol) { + wasmFragment.interfaces += irInterface + } + + override fun registerClass(irClass: IrClassSymbol) { + wasmFragment.classes += irClass + } + + override fun defineFunction(irFunction: IrFunctionSymbol, wasmFunction: WasmFunction) { + wasmFragment.functions.define(irFunction, wasmFunction) + } + + override fun defineGlobal(irField: IrFieldSymbol, wasmGlobal: WasmGlobal) { + wasmFragment.globals.define(irField, wasmGlobal) + } + + override fun defineStructType(irClass: IrClassSymbol, wasmStruct: WasmStructDeclaration) { + wasmFragment.structTypes.define(irClass, wasmStruct) + } + + override fun defineRTT(irClass: IrClassSymbol, wasmGlobal: WasmGlobal) { + wasmFragment.runtimeTypes.define(irClass, wasmGlobal) + } + + override fun defineFunctionType(irFunction: IrFunctionSymbol, wasmFunctionType: WasmFunctionType) { + wasmFragment.functionTypes.define(irFunction, wasmFunctionType) + } + + private val classMetadataCache = mutableMapOf() + override fun getClassMetadata(irClass: IrClassSymbol): ClassMetadata = + classMetadataCache.getOrPut(irClass) { + val superClass = irClass.owner.getSuperClass(backendContext.irBuiltIns) + val superClassMetadata = superClass?.let { getClassMetadata(it.symbol) } + ClassMetadata( + irClass.owner, + superClassMetadata, + backendContext.irBuiltIns + ) + } + + override fun referenceFunction(irFunction: IrFunctionSymbol): WasmSymbol = + wasmFragment.functions.reference(irFunction) + + override fun referenceGlobal(irField: IrFieldSymbol): WasmSymbol = + wasmFragment.globals.reference(irField) + + override fun referenceStructType(irClass: IrClassSymbol): WasmSymbol { + val type = irClass.defaultType + require(!type.isNothing()) { + "Can't reference Nothing type" + } + return wasmFragment.structTypes.reference(irClass) + } + + override fun referenceClassRTT(irClass: IrClassSymbol): WasmSymbol = + wasmFragment.runtimeTypes.reference(irClass) + + override fun referenceFunctionType(irFunction: IrFunctionSymbol): WasmSymbol = + wasmFragment.functionTypes.reference(irFunction) + + override fun referenceClassId(irClass: IrClassSymbol): WasmSymbol = + wasmFragment.classIds.reference(irClass) + + override fun referenceInterfaceId(irInterface: IrClassSymbol): WasmSymbol { + // HACK to substitute kotlin.Function5 with kotlin.wasm.internal.Function5 + val defaultType = irInterface.defaultType + if (defaultType.isFunction()) { + val n = irInterface.owner.typeParameters.size - 1 + return wasmFragment.interfaceId.reference(backendContext.wasmSymbols.functionN(n)) + } + return wasmFragment.interfaceId.reference(irInterface) + } + + override fun referenceVirtualFunctionId(irFunction: IrSimpleFunctionSymbol): WasmSymbol { + if (irFunction.owner.modality == Modality.ABSTRACT) + error("Abstract functions are not stored in table") + return wasmFragment.virtualFunctionId.reference(irFunction) + } + + override fun referenceSignatureId(signature: WasmSignature): WasmSymbol { + wasmFragment.signatures.add(signature) + return wasmFragment.signatureId.reference(signature) + } + + override fun getStructFieldRef(field: IrField): WasmSymbol { + val klass = field.parentAsClass + val metadata = getClassMetadata(klass.symbol) + val fieldId = metadata.fields.indexOf(field) + return WasmSymbol(fieldId) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt new file mode 100644 index 00000000000..77a6c8a64c8 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/ir2wasm/WasmModuleFragmentGenerator.kt @@ -0,0 +1,41 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.ir2wasm + +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +import org.jetbrains.kotlin.ir.declarations.IrPackageFragment +import org.jetbrains.kotlin.ir.visitors.acceptVoid + +class WasmModuleFragmentGenerator( + backendContext: WasmBackendContext, + wasmModuleFragment: WasmCompiledModuleFragment +) { + private val declarationGenerator = + DeclarationGenerator( + WasmModuleCodegenContextImpl( + backendContext, + wasmModuleFragment + ) + ) + + fun generateModule(irModuleFragment: IrModuleFragment) { + for (irFile in irModuleFragment.files) { + generatePackageFragment(irFile) + } + } + + fun generatePackageFragment(irPackageFragment: IrPackageFragment) { + for (irDeclaration in irPackageFragment.declarations) { + generateDeclaration(irDeclaration) + } + } + + fun generateDeclaration(irDeclaration: IrDeclaration) { + irDeclaration.acceptVoid(declarationGenerator) + } +} diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BlockDecomposerLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BlockDecomposerLowering.kt deleted file mode 100644 index 33e411a2e42..00000000000 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BlockDecomposerLowering.kt +++ /dev/null @@ -1,14 +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 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() -} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt index b688091510e..3f5e9397025 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/BuiltInsLowering.kt @@ -6,40 +6,139 @@ package org.jetbrains.kotlin.backend.wasm.lower import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irComposite +import org.jetbrains.kotlin.ir.builders.irInt import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction 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.types.IrType +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.isNullable +import org.jetbrains.kotlin.ir.util.functions 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.util.isFunction +import org.jetbrains.kotlin.ir.util.isNullConst import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.util.OperatorNameConventions class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass { private val irBuiltins = context.irBuiltIns private val symbols = context.wasmSymbols - fun transformCall(call: IrCall): IrExpression { + private fun IrType.findEqualsMethod(): IrSimpleFunction { + val klass = getClass() ?: irBuiltins.anyClass.owner + return klass.functions.single { it.isEqualsInheritedFromAny() } + } + + fun transformCall( + call: IrCall, + builder: DeclarationIrBuilder + ): IrExpression { when (val symbol = call.symbol) { - irBuiltins.eqeqSymbol, irBuiltins.eqeqeqSymbol, in irBuiltins.ieee754equalsFunByOperandType.values -> { + irBuiltins.ieee754equalsFunByOperandType[irBuiltins.floatClass] -> { + if (call.getValueArgument(0)!!.type.isNullable() || call.getValueArgument(1)!!.type.isNullable()) { + return irCall(call, symbols.nullableFloatIeee754Equals) + } + return irCall(call, symbols.floatEqualityFunctions.getValue(irBuiltins.floatType)) + } + irBuiltins.ieee754equalsFunByOperandType[irBuiltins.doubleClass] -> { + if (call.getValueArgument(0)!!.type.isNullable() || call.getValueArgument(1)!!.type.isNullable()) { + return irCall(call, symbols.nullableDoubleIeee754Equals) + } + return irCall(call, symbols.floatEqualityFunctions.getValue(irBuiltins.doubleType)) + } + irBuiltins.eqeqSymbol -> { + val lhs = call.getValueArgument(0)!! + val rhs = call.getValueArgument(1)!! + val lhsType = lhs.type + val rhsType = rhs.type + if (lhsType == rhsType) { + val newSymbol = symbols.equalityFunctions[lhsType] + if (newSymbol != null) { + return irCall(call, newSymbol) + } + } + if (lhs.isNullConst()) { + return builder.irCall(symbols.refIsNull).apply { putValueArgument(0, rhs) } + } + if (rhs.isNullConst()) { + return builder.irCall(symbols.refIsNull).apply { putValueArgument(0, lhs) } + } + if (!lhsType.isNullable()) { + return irCall(call, lhsType.findEqualsMethod().symbol, argumentsAsReceivers = true) + } + return irCall(call, symbols.nullableEquals) + } + + irBuiltins.eqeqeqSymbol -> { val type = call.getValueArgument(0)!!.type - val newSymbol = symbols.equalityFunctions[type] - ?: error("Unsupported equality operator with type: ${type.render()}") + val newSymbol = symbols.equalityFunctions[type] ?: symbols.floatEqualityFunctions[type] ?: symbols.refEq return irCall(call, newSymbol) } - in symbols.irBuiltInsToWasmIntrinsics.keys -> { - val newSymbol = symbols.irBuiltInsToWasmIntrinsics[symbol]!! + + irBuiltins.checkNotNullSymbol -> { + return irCall(call, symbols.ensureNotNull).also { + it.putTypeArgument(0, call.type) + } + } + in symbols.comparisonBuiltInsToWasmIntrinsics.keys -> { + val newSymbol = symbols.comparisonBuiltInsToWasmIntrinsics[symbol]!! return irCall(call, newSymbol) } + + // TODO: Implement + irBuiltins.noWhenBranchMatchedExceptionSymbol -> + return builder.irCall(symbols.wasmUnreachable, irBuiltins.nothingType) + + // TODO: Implement + irBuiltins.illegalArgumentExceptionSymbol -> + return builder.irCall(symbols.wasmUnreachable, irBuiltins.nothingType) + + irBuiltins.dataClassArrayMemberHashCodeSymbol -> { + // TODO: Implement + return builder.irComposite { + +call.getValueArgument(0)!! + +irInt(7777) + } + } + irBuiltins.dataClassArrayMemberToStringSymbol -> { + // TODO: Implement + return builder.irCall(symbols.anyNtoString).apply { + putValueArgument(0, call.getValueArgument(0)) + } + } } + + val nativeInvokeArity = getKotlinFunctionInvokeArity(call) + if (nativeInvokeArity != null) { + return irCall(call, symbols.functionNInvokeMethods[nativeInvokeArity]) + } + return call } + private fun getKotlinFunctionInvokeArity(call: IrCall): Int? { + val simpleFunction = call.symbol.owner as? IrSimpleFunction ?: return null + val receiverType = simpleFunction.dispatchReceiverParameter?.type ?: return null + if (simpleFunction.isSuspend) return null + if (simpleFunction.name == OperatorNameConventions.INVOKE && receiverType.isFunction()) { + return simpleFunction.valueParameters.size + } + return null + } + override fun lower(irFile: IrFile) { - irFile.transformChildrenVoid(object : IrElementTransformerVoid() { + val builder = context.createIrBuilder(irFile.symbol) + irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { override fun visitCall(expression: IrCall): IrExpression { - val newExpression = transformCall(expression) + val newExpression = transformCall(expression, builder) newExpression.transformChildrenVoid(this) return newExpression } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/EraseVirtualDispatchReceiverParametersTypes.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/EraseVirtualDispatchReceiverParametersTypes.kt new file mode 100644 index 00000000000..cca0d770e93 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/EraseVirtualDispatchReceiverParametersTypes.kt @@ -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.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irImplicitCast +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.types.isAny +import org.jetbrains.kotlin.ir.util.isInterface +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * This lowering erases dispatch receiver types of virtual functions down to Any. + * + * WebAssembly function types are contravariant on their parameter types. + * But since child classes are not supertypes of parents, in order for virtual method + * reference to share the same v-table slot as parent's method, it's dispatch receiver type + * has to be erased at least down to type of the parent class. + * + * Current implementation is rather conservative: + * - Always erases parameter type down to Any + * - Inserts casts back to original type in every usage of dispatch receiver. + * + * Possible optimisations: + * - Instead of erasing type to Any, erase type down to least concrete supertype containing virtual method + * - Don't erase type at all if bridge will be needed anyway + * Cast receiver in bridge. This would keep precise type for direct calls + * - Cast `this` and assign it to local variable if dispatch receiver is used often + * - Don't cast if usages of `this` don't require precise type + * - Always use bridge + Wasm tail call + * + * Related issue: [https://github.com/WebAssembly/gc/issues/29] + */ +class EraseVirtualDispatchReceiverParametersTypes(val context: CommonBackendContext) : FileLoweringPass { + override fun lower(file: IrFile) { + file.acceptChildrenVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + lower(declaration) + super.visitFunction(declaration) + } + }) + } + + fun lower(irFunction: IrFunction) { + // Lower only functions that override other functions + if (irFunction !is IrSimpleFunction) return + if (!irFunction.isOverridableOrOverrides) return + + val oldReceiver = irFunction.dispatchReceiverParameter!! + val originalReceiverType = oldReceiver.type + + // Interfaces in Wasm are erased to Any, so they already have appropriate type + if (originalReceiverType.isInterface() || originalReceiverType.isAny()) return + + val builder = context.createIrBuilder(irFunction.symbol) + val newReceiver = oldReceiver.copyTo(irFunction, type = context.irBuiltIns.anyType) + irFunction.dispatchReceiverParameter = newReceiver + + // Cast receiver usages back to original type + irFunction.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitGetValue(expression: IrGetValue): IrExpression { + if (expression.symbol == oldReceiver.symbol) { + return with(builder) { + irImplicitCast(irGet(newReceiver), originalReceiverType) + } + } + return expression + } + }) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ExcludeDeclarationsFromCodegen.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ExcludeDeclarationsFromCodegen.kt index d61c2dc2ee3..5b3ebff6604 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ExcludeDeclarationsFromCodegen.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/ExcludeDeclarationsFromCodegen.kt @@ -8,102 +8,22 @@ 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() +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDeclarationWithName +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrModuleFragment +/** + * Move intrinsics marked with @ExcludedFromCodegen to special excluded files. + * All references to these declarations must be lowered or treated in a special way in a codegen. + */ fun excludeDeclarationsFromCodegen(context: WasmBackendContext, module: IrModuleFragment) { - fun isExcluded(declaration: IrDeclaration): Boolean { - if (declaration is IrDeclarationWithName && declaration.fqNameWhenAvailable in BODILESS_BUILTIN_CLASSES) - return true - + // Annotation can be applied to top-level declarations ... if (declaration.hasExcludedFromCodegenAnnotation()) return true + // ... or files as a whole val parentFile = declaration.parent as? IrFile if (parentFile?.hasExcludedFromCodegenAnnotation() == true) return true @@ -117,7 +37,8 @@ fun excludeDeclarationsFromCodegen(context: WasmBackendContext, module: IrModule val d = it.next() as? IrDeclarationWithName ?: continue if (isExcluded(d)) { it.remove() - context.excludedDeclarations.addChild(d) + // Move to "excluded" package fragment preserving fq-name + context.getExcludedPackageFragment(file.fqName).addChild(d) } } } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/FieldInitializersLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/FieldInitializersLowering.kt new file mode 100644 index 00000000000..0663c143d86 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/FieldInitializersLowering.kt @@ -0,0 +1,53 @@ +/* + * 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.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.builders.irSetField +import org.jetbrains.kotlin.ir.declarations.IrField +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrBlockBody +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid + +/** + * Move initialization of global fields to start function. + * + * WebAssembly allows only constant expressions to be used directly in + * field initializers. + * + * TODO: Don't move constant expression initializers + * TODO: Make field initialization lazy. Needs design. + */ +class FieldInitializersLowering(val context: WasmBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + val builder = context.createIrBuilder(context.startFunction.symbol) + val startFunctionBody = context.startFunction.body as IrBlockBody + + irFile.acceptChildrenVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitField(declaration: IrField) { + super.visitField(declaration) + if (!declaration.isStatic) return + val initValue: IrExpression = declaration.initializer?.expression ?: return + + startFunctionBody.statements.add( + builder.at(initValue).irSetField(null, declaration, initValue) + ) + // Replace initializer with default one + declaration.initializer = null + } + }) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt new file mode 100644 index 00000000000..c266c92ecd5 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/GenericReturnTypeLowering.kt @@ -0,0 +1,86 @@ +/* + * 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.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irComposite +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.builders.irImplicitCast +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.irCall +import org.jetbrains.kotlin.ir.util.isTypeParameter +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * This lowering adds implicit casts in places where erased generic function return type + * differs from expected type on the call site. + */ +class GenericReturnTypeLowering(val context: WasmBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(object : IrElementTransformerVoidWithContext() { + override fun visitCall(expression: IrCall): IrExpression = + transformGenericCall( + super.visitCall(expression) as IrCall, + currentScope!!.scope.scopeOwnerSymbol + ) + }) + } + + private fun IrType.eraseUpperBoundType(): IrType { + val type = erasedUpperBound?.defaultType ?: return context.irBuiltIns.anyNType + return if (this.isNullable()) + type.makeNullable() + else + type + } + + private fun transformGenericCall(call: IrCall, scopeOwnerSymbol: IrSymbol): IrExpression { + val function: IrSimpleFunction = + call.symbol.owner as? IrSimpleFunction ?: return call + + if (!function.realOverrideTarget.returnType.isTypeParameter()) + return call + + val erasedReturnType: IrType = + function.realOverrideTarget.returnType.eraseUpperBoundType() + + val callType = call.type + + if (erasedReturnType != call.type) { + if (callType.isNothing()) return call + if (erasedReturnType.isSubtypeOf(callType, context.irBuiltIns)) return call + + // Erase type parameter from call return type + val newCall = irCall( + call, + function.symbol, + newReturnType = erasedReturnType, + newSuperQualifierSymbol = call.superQualifierSymbol + ) + + context.createIrBuilder(scopeOwnerSymbol).apply { + if (call.type.isUnit()) { + return irComposite(call) { + +newCall + } + } + return irImplicitCast(newCall, call.type) + } + } + return call + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/SimpleStringConcatenationLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/SimpleStringConcatenationLowering.kt new file mode 100644 index 00000000000..3b32eaeef5c --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/SimpleStringConcatenationLowering.kt @@ -0,0 +1,91 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irString +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation +import org.jetbrains.kotlin.ir.types.getClass +import org.jetbrains.kotlin.ir.types.isNullable +import org.jetbrains.kotlin.ir.types.isString +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +/** + * Replace string concatenation with a chain of String.plus calls. + * TODO: Reuse common StringConcatenationLowering which uses string builder + */ +class SimpleStringConcatenationLowering(val context: WasmBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(StringConcatenationTransformer(this)) + } +} + +private class StringConcatenationTransformer(val lower: SimpleStringConcatenationLowering) : IrElementTransformerVoidWithContext() { + private val context = lower.context + private val irBuiltIns = context.irBuiltIns + private val stringPlus = irBuiltIns.stringClass.owner.declarations.filterIsInstance().find { + it.name == Name.identifier("plus") + }!! + + private val anyToString = irBuiltIns.anyClass.owner.declarations.filterIsInstance().find { + it.name == Name.identifier("toString") + }!! + + private val anyNToString = context.wasmSymbols.anyNtoString + + + override fun visitStringConcatenation(expression: IrStringConcatenation): IrExpression { + val transformed = super.visitStringConcatenation(expression) as IrStringConcatenation + val builder: DeclarationIrBuilder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).at(expression) + return transformed.arguments.fold( + builder.irString("") + ) { acc, el -> + builder.irCall(stringPlus).apply { + dispatchReceiver = acc + putValueArgument(0, expressionToString(el, builder)) + } + } + } + + private fun expressionToString(expression: IrExpression, builder: DeclarationIrBuilder): IrExpression { + if (expression.type.isString()) return expression + builder.at(expression) + val klass = expression.type.getClass() + + if (expression.type.isNullable()) { + return builder.irCall(anyNToString).apply { + putValueArgument(0, expression) + } + } + + val toStringMethod: IrSimpleFunction = if (klass != null) { + klass.declarations.filterIsInstance().find { it.isToStringInheritedFromAny() }!! + } else { + anyToString + } + + return builder.irCall(toStringMethod).apply { + dispatchReceiver = expression + } + } +} + +fun IrFunction.isToStringInheritedFromAny() = + name == Name.identifier("toString") && + dispatchReceiverParameter != null && + extensionReceiverParameter == null && + valueParameters.isEmpty() diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/VirtualDispatchReceiverExtraction.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/VirtualDispatchReceiverExtraction.kt new file mode 100644 index 00000000000..ae6fccaffdd --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/VirtualDispatchReceiverExtraction.kt @@ -0,0 +1,68 @@ +/* + * 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.CommonBackendContext +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.ir.isOverridable +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irBlock +import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget +import org.jetbrains.kotlin.ir.builders.createTmpVariable +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrGetValue +import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid +import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid +import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * During Wasm code generation, dispatch receiver can be used multiple times. + * Move it to temporary variable if it is complex or can have side effects. + */ +class VirtualDispatchReceiverExtraction(val context: CommonBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.acceptChildrenVoid(object : IrElementVisitorVoid { + override fun visitElement(element: IrElement) { + element.acceptChildrenVoid(this) + } + + override fun visitFunction(declaration: IrFunction) { + lower(declaration) + super.visitFunction(declaration) + } + }) + } + + fun lower(irFunction: IrFunction) { + irFunction.transformChildrenVoid(object : IrElementTransformerVoid() { + override fun visitCall(expression: IrCall): IrExpression { + expression.transformChildrenVoid(this) + val function = expression.symbol.owner.realOverrideTarget + val receiver = expression.dispatchReceiver + if (receiver == null || !function.isOverridable) + return expression + // TODO: Keep other simple receivers without side effects + // receiver.isPure(true) ? + if (receiver is IrGetValue) + return expression + return with(context.createIrBuilder(irFunction.symbol)) { + irBlock(expression) { + val tmp = createTmpVariable(receiver) + expression.dispatchReceiver = irGet(tmp) + +expression + } + } + } + }) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmBridgesConstruction.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmBridgesConstruction.kt new file mode 100644 index 00000000000..4866ee596d2 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmBridgesConstruction.kt @@ -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.lower + +import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext +import org.jetbrains.kotlin.ir.backend.js.lower.BridgesConstruction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNullable +import org.jetbrains.kotlin.ir.types.makeNullable +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.ir.util.render +import org.jetbrains.kotlin.name.Name + +class WasmBridgesConstruction(context: JsCommonBackendContext) : BridgesConstruction(context) { + override fun getFunctionSignature(function: IrSimpleFunction): WasmSignature = + function.wasmSignature(context.irBuiltIns) + + // Dispatch receiver type must be casted when types are different. + override val shouldCastDispatchReceiver: Boolean = true +} + +data class WasmSignature( + val name: Name, + val extensionReceiverType: IrType?, + val valueParametersType: List, + val returnType: IrType +) { + override fun toString(): String { + val er = extensionReceiverType?.let { "(er: ${it.render()}) " } ?: "" + val parameters = valueParametersType.joinToString(", ") { it.render() } + return "[$er$name($parameters) -> ${returnType.render()}]" + } +} + +fun IrSimpleFunction.wasmSignature(irBuiltIns: IrBuiltIns): WasmSignature = + WasmSignature( + name, + extensionReceiverParameter?.type?.eraseGenerics(irBuiltIns), + valueParameters.map { it.type.eraseGenerics(irBuiltIns) }, + returnType.eraseGenerics(irBuiltIns) + ) + +private fun IrType.eraseGenerics(irBuiltIns: IrBuiltIns): IrType { + val defaultType = this.erasedUpperBound?.defaultType ?: irBuiltIns.anyType + if (!this.isNullable()) return defaultType + return defaultType.makeNullable() +} + diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmCallableReferenceLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmCallableReferenceLowering.kt new file mode 100644 index 00000000000..71cd754ec96 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmCallableReferenceLowering.kt @@ -0,0 +1,314 @@ +/* + * 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.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.ir.copyTo +import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor +import org.jetbrains.kotlin.backend.common.ir.isSuspend +import org.jetbrains.kotlin.backend.common.ir.moveBodyTo +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.builders.declarations.addConstructor +import org.jetbrains.kotlin.ir.builders.declarations.addFunction +import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames + +/** + * TODO: Temporary lowering stub. Needs to be redone. + * This is a copy of JVM lowering, but parts that don't compile are commented out. + * Turns out this works decently as a stub in most tests. + */ + +val IrStatementOrigin?.isLambda: Boolean + get() = this == IrStatementOrigin.LAMBDA || this == IrStatementOrigin.ANONYMOUS_FUNCTION + +// Originally copied from K/Native +internal class WasmCallableReferenceLowering(private val context: WasmBackendContext) : FileLoweringPass, IrElementTransformerVoidWithContext() { + // This pass ignores suspend function references and function references used in inline arguments to inline functions. + private val ignoredFunctionReferences = mutableSetOf() + + private val IrFunctionReference.isIgnored: Boolean + get() = (!type.isFunctionOrKFunction() || ignoredFunctionReferences.contains(this)) && !isSuspendCallableReference() + + // TODO: Currently, origin of callable references is null. Do we need to create one? + private fun IrFunctionReference.isSuspendCallableReference(): Boolean = isSuspend && origin == null + + override fun lower(irFile: IrFile) { + // ignoredFunctionReferences.addAll(IrInlineReferenceLocator.scan(context, irFile)) + irFile.transformChildrenVoid(this) + } + + override fun visitBlock(expression: IrBlock): IrExpression { + if (!expression.origin.isLambda) + return super.visitBlock(expression) + + val reference = expression.statements.last() as IrFunctionReference + if (reference.isIgnored) + return super.visitBlock(expression) + + expression.statements.dropLast(1).forEach { it.transform(this, null) } + reference.transformChildrenVoid(this) + return FunctionReferenceBuilder(reference).build() + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transformChildrenVoid(this) + return if (expression.isIgnored) expression else FunctionReferenceBuilder(expression).build() + } + + // Handle SAM conversions which wrap a function reference: + // class sam$n(private val receiver: R) : Interface { override fun method(...) = receiver.target(...) } + // + // This avoids materializing an invokable KFunction representing, thus producing one less class. + // This is actually very common, as `Interface { something }` is a local function + a SAM-conversion + // of a reference to it into an implementation. + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + if (expression.operator == IrTypeOperator.SAM_CONVERSION) { + val invokable = expression.argument + val reference = if (invokable is IrFunctionReference) { + invokable + } else if (invokable is IrBlock && invokable.origin.isLambda && invokable.statements.last() is IrFunctionReference) { + invokable.statements.dropLast(1).forEach { it.transform(this, null) } + invokable.statements.last() as IrFunctionReference + } else { + return super.visitTypeOperator(expression) + } + reference.transformChildrenVoid() + return FunctionReferenceBuilder(reference, expression.typeOperand).build() + } + return super.visitTypeOperator(expression) + } + + private inner class FunctionReferenceBuilder(val irFunctionReference: IrFunctionReference, val samSuperType: IrType? = null) { + private val isLambda = irFunctionReference.origin.isLambda + + private val callee = irFunctionReference.symbol.owner + + // Only function references can bind a receiver and even then we can only bind either an extension or a dispatch receiver. + // However, when we bind a value of an inline class type as a receiver, the receiver will turn into an argument of + // the function in question. Yet we still need to record it as the "receiver" in CallableReference in order for reflection + // to work correctly. + private val boundReceiver: Pair? = irFunctionReference.getArgumentsWithIr().singleOrNull() + + // The type of the reference is KFunction + private val parameterTypes = (irFunctionReference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type } + private val argumentTypes = parameterTypes.dropLast(1) + + private val typeArgumentsMap = irFunctionReference.typeSubstitutionMap + + private val functionSuperClass = + samSuperType?.classOrNull + ?: if (irFunctionReference.isSuspend) + context.ir.symbols.suspendFunctionN(argumentTypes.size) + else + context.ir.symbols.functionN(argumentTypes.size) + + private val superMethod = + functionSuperClass.functions.single { it.owner.modality == Modality.ABSTRACT } + // TODO(WASM) + // private val superType = + // samSuperType ?: (if (isLambda) context.ir.symbols.lambdaClass else context.ir.symbols.functionReference).defaultType + + private val functionReferenceClass = context.irFactory.buildClass { + setSourceRange(irFunctionReference) + visibility = DescriptorVisibilities.LOCAL + // A callable reference results in a synthetic class, while a lambda is not synthetic. + // We don't produce GENERATED_SAM_IMPLEMENTATION, which is always synthetic. + // TODO(WASM) + // origin = if (isLambda) JvmLoweredDeclarationOrigin.LAMBDA_IMPL else JvmLoweredDeclarationOrigin.FUNCTION_REFERENCE_IMPL + name = SpecialNames.NO_NAME_PROVIDED + }.apply { + parent = currentDeclarationParent!! + // TODO(WASM) + // superTypes += superType + if (samSuperType == null) + superTypes += functionSuperClass.typeWith(parameterTypes) + // TODO(WASM) + // if (irFunctionReference.isSuspend) superTypes += context.ir.symbols.suspendFunctionInterface.defaultType + createImplicitParameterDeclarationWithWrappedDescriptor() + copyAttributes(irFunctionReference) + if (isLambda) { + this.metadata = irFunctionReference.symbol.owner.metadata + } + } + +// WASM(TODO) +// private val receiverFieldFromSuper = context.ir.symbols.functionReferenceReceiverField.owner +// +// val fakeOverrideReceiverField = functionReferenceClass.addField { +// name = receiverFieldFromSuper.name +// origin = IrDeclarationOrigin.FAKE_OVERRIDE +// type = receiverFieldFromSuper.type +// isFinal = receiverFieldFromSuper.isFinal +// isStatic = receiverFieldFromSuper.isStatic +// visibility = receiverFieldFromSuper.visibility +// } + + fun build(): IrExpression = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).run { + irBlock { + val constructor = createConstructor() + createInvokeMethod( + if (samSuperType != null && boundReceiver != null) { + irTemporary(boundReceiver.second) + } else null + ) + +// WASM(TODO) +// if (!isLambda && samSuperType == null) { +// createGetSignatureMethod(this@run.irSymbols.functionReferenceGetSignature.owner) +// createGetNameMethod(this@run.irSymbols.functionReferenceGetName.owner) +// createGetOwnerMethod(this@run.irSymbols.functionReferenceGetOwner.owner) +// } + + +functionReferenceClass + +irCall(constructor.symbol).apply { + if (valueArgumentsCount > 0) putValueArgument(0, boundReceiver!!.second) + } + } + } + + private fun createConstructor(): IrConstructor = + functionReferenceClass.addConstructor { + // origin = JvmLoweredDeclarationOrigin.GENERATED_MEMBER_IN_CALLABLE_REFERENCE + returnType = functionReferenceClass.defaultType + isPrimary = true + }.apply { + // Add receiver parameter for bound function references + if (samSuperType == null) { + boundReceiver?.first?.let { param -> + valueParameters += param.copyTo( + irFunction = this, + index = 0, + type = param.type.substitute(typeArgumentsMap) + ) + } + } + + // Super constructor: + // - For SAM references, the super class is Any + // - For function references with bound receivers, accepts arity and receiver + // - For lambdas and function references without bound receivers, accepts arity + +// WASM_TODO +// val constructor = if (samSuperType != null) { +// context.irBuiltIns.anyClass.owner.constructors.single() +// } else { +// superType.getClass()!!.constructors.single { +// it.valueParameters.size == if (boundReceiver != null) 2 else 1 +// } +// } + + val constructor = context.irBuiltIns.anyClass.owner.constructors.single() + + body = context.createIrBuilder(symbol).irBlockBody(startOffset, endOffset) { + +irDelegatingConstructorCall(constructor).apply { +// WASM_TODO +// if (samSuperType == null) { +// putValueArgument(0, irInt(argumentTypes.size + if (irFunctionReference.isSuspend) 1 else 0)) +// if (boundReceiver != null) +// putValueArgument(1, irGet(valueParameters.first())) +// } + } + +IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClass.symbol, context.irBuiltIns.unitType) + } + } + + private fun createInvokeMethod(receiverVar: IrValueDeclaration?): IrSimpleFunction = + functionReferenceClass.addFunction { + setSourceRange(if (isLambda) callee else irFunctionReference) + name = superMethod.owner.name + returnType = callee.returnType + isSuspend = callee.isSuspend + }.apply { + overriddenSymbols += superMethod + dispatchReceiverParameter = parentAsClass.thisReceiver!!.copyTo(this) + if (isLambda) createLambdaInvokeMethod() else createFunctionReferenceInvokeMethod(receiverVar) + } + + // Inline the body of an anonymous function into the generated lambda subclass. + private fun IrSimpleFunction.createLambdaInvokeMethod() { + annotations += callee.annotations + val valueParameterMap = callee.explicitParameters.withIndex().associate { (index, param) -> + param to param.copyTo(this, index = index) + } + valueParameters += valueParameterMap.values + body = callee.moveBodyTo(this, valueParameterMap) + } + + private fun IrSimpleFunction.createFunctionReferenceInvokeMethod(receiver: IrValueDeclaration?) { + for ((index, argumentType) in argumentTypes.withIndex()) { + addValueParameter { + name = Name.identifier("p$index") + type = argumentType + } + } + + body = context.createIrBuilder(symbol).run { + var unboundIndex = 0 + irExprBody(irCall(callee).apply { + for ((typeParameter, typeArgument) in typeArgumentsMap) { + putTypeArgument(typeParameter.owner.index, typeArgument) + } + + for (parameter in callee.explicitParameters) { + when { + boundReceiver?.first == parameter -> + // Bound receiver parameter. For function references, this is stored in a field of the superclass. + // For sam references, we just capture the value in a local variable and LocalDeclarationsLowering + // will put it into a field. +// if (samSuperType == null) +// irImplicitCast( +// irGetField(irGet(dispatchReceiverParameter!!), fakeOverrideReceiverField), +// boundReceiver.second.type +// ) +// else + irGet(receiver ?: error("Binding receivers is not supported yet")) + + // If a vararg parameter corresponds to exactly one KFunction argument, which is an array, that array + // is forwarded as is. + // + // fun f(x: (Int, Array) -> String) = x(0, arrayOf("OK", "FAIL")) + // fun h(i: Int, vararg xs: String) = xs[i] + // f(::h) + // + parameter.isVararg && unboundIndex < argumentTypes.size && parameter.type == valueParameters[unboundIndex].type -> + irGet(valueParameters[unboundIndex++]) + // In all other cases, excess arguments are packed into a new array. + // + // fun g(x: (Int, String, String) -> String) = x(0, "OK", "FAIL") + // f(::h) == g(::h) + // + parameter.isVararg && (unboundIndex < argumentTypes.size || !parameter.hasDefaultValue()) -> + TODO() + + unboundIndex >= argumentTypes.size -> + // Default value argument (this pass doesn't handle suspend functions, otherwise + // it could also be the continuation argument) + null + + else -> + irGet(valueParameters[unboundIndex++]) + }?.let { putArgument(callee, parameter, it) } + } + }) + } + } + } +} diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt new file mode 100644 index 00000000000..358f1d1091e --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmNullCoercionLowering.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.backend.js.lower.AbstractValueUsageLowering +import org.jetbrains.kotlin.ir.expressions.IrConstKind +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNothing +import org.jetbrains.kotlin.ir.types.isNullable +import org.jetbrains.kotlin.ir.types.makeNotNull + +/** + * Replace null constants of type Nothing? with null constants of a concrete class types. + * + * Wasm GC doesn't have a nullref type anymore. + */ +class WasmNullCoercingLowering(context: JsCommonBackendContext) : AbstractValueUsageLowering(context) { + override fun IrExpression.useExpressionAsType(actualType: IrType, expectedType: IrType): IrExpression = + if (actualType.makeNotNull().isNothing() && actualType.isNullable() && !expectedType.makeNotNull().isNothing()) + JsIrBuilder.buildComposite( + type, + listOf(this, IrConstImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, expectedType, IrConstKind.Null, null)) + ) + else + this +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt new file mode 100644 index 00000000000..ad7ec9ce650 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmSharedVariablesManager.kt @@ -0,0 +1,220 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.common.ir.SharedVariablesManager +import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.DescriptorVisibilities +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET +import org.jetbrains.kotlin.ir.backend.js.JsCommonBackendContext +import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin +import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder +import org.jetbrains.kotlin.ir.builders.declarations.buildClass +import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.* +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl +import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl +import org.jetbrains.kotlin.ir.util.defaultType +import org.jetbrains.kotlin.name.Name + +/** + * This is a copy of an old version of JS lowering, because JS did platform-specific optimization incompatible with Wasm. + * TODO: Revisit + */ +@OptIn(ObsoleteDescriptorBasedAPI::class) +class WasmSharedVariablesManager(val context: JsCommonBackendContext, val builtIns: IrBuiltIns, val implicitDeclarationsFile: IrPackageFragment) : SharedVariablesManager { + override fun declareSharedVariable(originalDeclaration: IrVariable): IrVariable { + val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull( + originalDeclaration.startOffset, + originalDeclaration.endOffset, + builtIns.nothingNType + ) + + val constructorSymbol = closureBoxConstructorDeclaration.symbol + + val irCall = + IrConstructorCallImpl.fromSymbolDescriptor(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol) + .apply { + putValueArgument(0, initializer) + } + + val descriptor = WrappedVariableDescriptor() + return IrVariableImpl( + originalDeclaration.startOffset, + originalDeclaration.endOffset, + originalDeclaration.origin, + IrVariableSymbolImpl(descriptor), + originalDeclaration.name, + irCall.type, + false, + false, + false + ).also { + descriptor.bind(it) + it.parent = originalDeclaration.parent + it.initializer = irCall + } + } + + override fun defineSharedValue(originalDeclaration: IrVariable, sharedVariableDeclaration: IrVariable) = sharedVariableDeclaration + + override fun getSharedValue(sharedVariableSymbol: IrVariableSymbol, originalGet: IrGetValue): IrExpression { + val getField = IrGetFieldImpl( + originalGet.startOffset, originalGet.endOffset, + closureBoxFieldDeclaration.symbol, + closureBoxFieldDeclaration.type, + IrGetValueImpl( + originalGet.startOffset, + originalGet.endOffset, + closureBoxType, + sharedVariableSymbol, + originalGet.origin + ), + originalGet.origin + ) + + return IrTypeOperatorCallImpl( + originalGet.startOffset, + originalGet.endOffset, + originalGet.type, + IrTypeOperator.IMPLICIT_CAST, + originalGet.type, + getField + ) + } + + override fun setSharedValue(sharedVariableSymbol: IrVariableSymbol, originalSet: IrSetValue): IrExpression = + IrSetFieldImpl( + originalSet.startOffset, + originalSet.endOffset, + closureBoxFieldDeclaration.symbol, + IrGetValueImpl( + originalSet.startOffset, + originalSet.endOffset, + closureBoxType, + sharedVariableSymbol, + originalSet.origin + ), + originalSet.value, + originalSet.type, + originalSet.origin + ) + + private val boxTypeName = "\$closureBox\$" + + private val closureBoxClassDeclaration by lazy { + createClosureBoxClassDeclaration() + } + + private val closureBoxConstructorDeclaration by lazy { + createClosureBoxConstructorDeclaration() + } + + private val closureBoxFieldDeclaration by lazy { + closureBoxPropertyDeclaration + } + + private val closureBoxPropertyDeclaration by lazy { + createClosureBoxPropertyDeclaration() + } + + private lateinit var closureBoxType: IrType + + private fun createClosureBoxClassDeclaration(): IrClass { + val declaration = context.irFactory.buildClass { + origin = JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION + name = Name.identifier(boxTypeName) + visibility = DescriptorVisibilities.PUBLIC + modality = Modality.FINAL + isCompanion = false + isInner = false + isData = false + isExternal = false + isInline = false + isExpect = false + isFun = false + } + + declaration.parent = implicitDeclarationsFile + // TODO: substitute + closureBoxType = IrSimpleTypeImpl(declaration.symbol, false, emptyList(), emptyList()) + declaration.thisReceiver = buildValueParameter(declaration) { + name = Name.identifier("_this_") + index = -1 + type = closureBoxType + } + implicitDeclarationsFile.declarations += declaration + + return declaration + } + + private fun createClosureBoxPropertyDeclaration(): IrField { + val descriptor = WrappedFieldDescriptor() + val symbol = IrFieldSymbolImpl(descriptor) + val fieldName = Name.identifier("v") + return context.irFactory.createField( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + InnerClassesSupport.FIELD_FOR_OUTER_THIS, + symbol, + fieldName, + builtIns.anyNType, + DescriptorVisibilities.PUBLIC, + isFinal = false, + isExternal = false, + isStatic = false, + ).also { + descriptor.bind(it) + it.parent = closureBoxClassDeclaration + closureBoxClassDeclaration.declarations += it + } + } + + private fun createClosureBoxConstructorDeclaration(): IrConstructor { + val descriptor = WrappedClassConstructorDescriptor() + val symbol = IrConstructorSymbolImpl(descriptor) + + val declaration = context.irFactory.createConstructor( + UNDEFINED_OFFSET, UNDEFINED_OFFSET, JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS_DECLARATION, symbol, + Name.special(""), DescriptorVisibilities.PUBLIC, closureBoxClassDeclaration.defaultType, + isInline = false, isExternal = false, isPrimary = true, isExpect = false + ) + + descriptor.bind(declaration) + declaration.parent = closureBoxClassDeclaration + + val parameterDeclaration = createClosureBoxConstructorParameterDeclaration(declaration) + + declaration.valueParameters += parameterDeclaration + + val receiver = JsIrBuilder.buildGetValue(closureBoxClassDeclaration.thisReceiver!!.symbol) + val value = JsIrBuilder.buildGetValue(parameterDeclaration.symbol) + + val setField = JsIrBuilder.buildSetField(closureBoxFieldDeclaration.symbol, receiver, value, builtIns.unitType) + + declaration.body = context.irFactory.createBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(setField)) + + closureBoxClassDeclaration.declarations += declaration + return declaration + } + + private fun createClosureBoxConstructorParameterDeclaration(irConstructor: IrConstructor): IrValueParameter { + return JsIrBuilder.buildValueParameter(irConstructor,"p", 0, closureBoxPropertyDeclaration.type) + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmThrowDebugLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmThrowDebugLowering.kt new file mode 100644 index 00000000000..45b21868330 --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmThrowDebugLowering.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrThrow +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + +/** + * Replace throw expressions with a runtime function call. + * TODO: Remove when full-blown exception handling is implemented + */ +internal class WasmThrowDebugLowering( + private val context: WasmBackendContext +) : FileLoweringPass, IrElementTransformerVoidWithContext() { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitThrow(expression: IrThrow): IrExpression { + expression.transformChildrenVoid(this) + val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol) + + return builder.irCall(context.wasmSymbols.wasmThrow).apply { + this.putValueArgument(0, expression.value) + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt new file mode 100644 index 00000000000..96b01eb139a --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmTypeOperatorLowering.kt @@ -0,0 +1,287 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder +import org.jetbrains.kotlin.backend.common.lower.at +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irNot +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.backend.wasm.ir2wasm.erasedUpperBound +import org.jetbrains.kotlin.ir.backend.js.utils.isPure +import org.jetbrains.kotlin.ir.builders.* +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrTypeParameter +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid + + +class WasmTypeOperatorLowering(val context: WasmBackendContext) : FileLoweringPass { + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(WasmBaseTypeOperatorTransformer(context)) + } +} + +class WasmBaseTypeOperatorTransformer(val context: WasmBackendContext) : IrElementTransformerVoidWithContext() { + private val symbols = context.wasmSymbols + private val builtIns = context.irBuiltIns + + private lateinit var builder: DeclarationIrBuilder + + override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression { + super.visitTypeOperator(expression) + builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol).at(expression) + + return when (expression.operator) { + IrTypeOperator.IMPLICIT_CAST -> lowerImplicitCast(expression) + IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> error("Dynamic casts are not supported in Wasm backend") + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> expression.argument + IrTypeOperator.IMPLICIT_INTEGER_COERCION -> lowerIntegerCoercion(expression) + IrTypeOperator.IMPLICIT_NOTNULL -> lowerImplicitCast(expression) + IrTypeOperator.INSTANCEOF -> lowerInstanceOf(expression, inverted = false) + IrTypeOperator.NOT_INSTANCEOF -> lowerInstanceOf(expression, inverted = true) + IrTypeOperator.CAST -> lowerCast(expression, isSafe = false) + IrTypeOperator.SAFE_CAST -> lowerCast(expression, isSafe = true) + IrTypeOperator.SAM_CONVERSION -> TODO("SAM conversion: ${expression.render()}") + IrTypeOperator.REINTERPRET_CAST -> expression + } + } + + private fun lowerInstanceOf( + expression: IrTypeOperatorCall, + inverted: Boolean + ): IrExpression { + return builder.irComposite(resultType = builtIns.booleanType) { + val argument = cacheValue(expression.argument) + val check = generateTypeCheck(argument, expression.typeOperand) + if (inverted) { + +builder.irNot(check) + } else { + +check + } + } + } + + private fun IrBlockBuilder.cacheValue(value: IrExpression): () -> IrExpressionWithCopy { + if (value.isPure(true) && value is IrExpressionWithCopy) { + return { value.deepCopyWithSymbols() } + } + val tmpVal = createTmpVariable(value) + return { builder.irGet(tmpVal) } + } + + private fun IrType.isInlined(): Boolean = + context.inlineClassesUtils.isTypeInlined(this) + + private val IrType.erasedType: IrType + get() = this.erasedUpperBound?.defaultType ?: builtIns.anyType + + private fun generateTypeCheck( + valueProvider: () -> IrExpressionWithCopy, + toType: IrType + ): IrExpression { + val toNotNullable = toType.makeNotNull() + val valueInstance: IrExpressionWithCopy = valueProvider() + val fromType = (valueInstance as IrExpression).type + + // Inlined values have no type information on runtime. + // But since they are final we can compute type checks on compile time. + if (fromType.isInlined()) { + val result = fromType.erasedType.isSubtypeOf(toType.erasedType, builtIns) + return builder.irBoolean(result) + } + + val instanceCheck = generateTypeCheckNonNull(valueInstance, toNotNullable) + val isFromNullable = valueInstance.type.isNullable() + val isToNullable = toType.isNullable() + + return when { + !isFromNullable -> instanceCheck + + else -> + builder.irIfThenElse( + type = builtIns.booleanType, + condition = builder.irEqualsNull(valueProvider() as IrExpression), + thenPart = builder.irBoolean(isToNullable), + elsePart = instanceCheck + ) + } + } + + private fun lowerIntegerCoercion(expression: IrTypeOperatorCall): IrExpression = + when (expression.typeOperand) { + builtIns.byteType, + builtIns.shortType -> + expression.argument + + builtIns.longType -> + builder.irCall(symbols.intToLong).apply { + putValueArgument(0, expression.argument) + } + + else -> error("Unreachable execution (coercion to non-Integer type") + } + + private fun generateTypeCheckNonNull(argument: IrExpressionWithCopy, toType: IrType): IrExpression { + assert(!toType.isMarkedNullable()) + return when { + toType.isNothing() -> builder.irComposite(resultType = builtIns.booleanType) { + +(argument as IrExpression) + +builder.irFalse() + } + toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType) + toType.isInterface() -> generateIsInterface(argument as IrExpression, toType) + else -> generateIsSubClass(argument as IrExpression, toType) + } + } + + private fun narrowType(fromType: IrType, toType: IrType, value: IrExpression): IrExpression { + if (fromType == toType) return value + + if (toType == builtIns.nothingNType) { + return builder.irComposite(resultType = builtIns.nothingNType) { + +value + +builder.irNull() + } + } + + // Handled by autoboxing transformer + if (toType.isInlined() && !fromType.isInlined()) { + return builder.irCall( + symbols.unboxIntrinsic, + toType, + typeArguments = listOf(fromType, toType) + ).also { + it.putValueArgument(0, value) + } + } + + if (!toType.isInlined() && fromType.isInlined()) { + return builder.irCall( + symbols.boxIntrinsic, + toType, + typeArguments = listOf(fromType, toType) + ).also { + it.putValueArgument(0, value) + } + } + + if (fromType.erasedType.isSubtypeOf(toType.erasedType, context.irBuiltIns)) { + return value + } + if (toType.isNothing()) { + return value + } + + + // Ref casts traps on null (https://github.com/WebAssembly/gc/issues/152) + // Handling null manually + if (toType.isNullable() && fromType.isNullable()) { + return builder.irComposite { + val value = cacheValue(value) + +builder.irIfNull( + type = toType, + subject = value() as IrExpression, + thenPart = builder.irNull(toType), + elsePart = builder.irCall(symbols.wasmRefCast, type = toType).apply { + putTypeArgument(0, fromType) + putTypeArgument(1, toType) + putValueArgument(0, value() as IrExpression) + } + ) + } + } + + return builder.irCall(symbols.wasmRefCast, type = toType).apply { + putTypeArgument(0, fromType) + putTypeArgument(1, toType) + putValueArgument(0, value) + } + } + + private fun lowerCast( + expression: IrTypeOperatorCall, + isSafe: Boolean + ): IrExpression { + val toType = expression.typeOperand + val fromType = expression.argument.type + + if (fromType.erasedType.isSubtypeOf(expression.type.erasedType, context.irBuiltIns)) { + return narrowType(fromType, expression.type, expression.argument) + } + + val failResult = if (isSafe) { + builder.irNull() + } else { + builder.irCall(context.ir.symbols.throwTypeCastException) + } + + return builder.irComposite(resultType = expression.type) { + val argument = cacheValue(expression.argument) + val narrowArg = narrowType(fromType, expression.type, argument() as IrExpression) + val check = generateTypeCheck(argument, toType) + if (check is IrConst<*>) { + val value = check.value as Boolean + if (value) { + +narrowArg + } else { + +failResult + } + } else { + +builder.irIfThenElse( + type = expression.type, + condition = check, + thenPart = narrowArg, + elsePart = failResult + ) + } + } + } + + private fun lowerImplicitCast(expression: IrTypeOperatorCall): IrExpression = + narrowType( + fromType = expression.argument.type, + toType = expression.typeOperand, + value = expression.argument + ) + + private fun generateTypeCheckWithTypeParameter(argument: IrExpressionWithCopy, toType: IrType): IrExpression { + val typeParameter = toType.classifierOrNull?.owner as? IrTypeParameter + ?: error("expected type parameter, but got $toType") + + return typeParameter.superTypes.fold(builder.irTrue() as IrExpression) { r, t -> + val check = generateTypeCheckNonNull(argument.copy() as IrExpressionWithCopy, t.makeNotNull()) + builder.irCall(symbols.booleanAnd).apply { + putValueArgument(0, r) + putValueArgument(1, check) + } + } + } + + private fun generateIsInterface(argument: IrExpression, toType: IrType): IrExpression { + val interfaceId = builder.irCall(symbols.wasmInterfaceId).apply { + putTypeArgument(0, toType) + } + return builder.irCall(symbols.isInterface).apply { + putValueArgument(0, argument) + putValueArgument(1, interfaceId) + } + } + + private fun generateIsSubClass(argument: IrExpression, toType: IrType): IrExpression { + val classId = builder.irCall(symbols.wasmClassId).apply { + putTypeArgument(0, toType) + } + return builder.irCall(symbols.isSubClass).apply { + putValueArgument(0, argument) + putValueArgument(1, classId) + } + } +} diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt new file mode 100644 index 00000000000..f454418a03e --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/lower/WasmVarargExpressionLowering.kt @@ -0,0 +1,100 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.lower + +import org.jetbrains.kotlin.backend.common.FileLoweringPass +import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext +import org.jetbrains.kotlin.backend.common.lower.createIrBuilder +import org.jetbrains.kotlin.backend.common.lower.irComposite +import org.jetbrains.kotlin.backend.wasm.WasmBackendContext +import org.jetbrains.kotlin.ir.builders.irCall +import org.jetbrains.kotlin.ir.builders.irGet +import org.jetbrains.kotlin.ir.builders.irInt +import org.jetbrains.kotlin.ir.builders.irTemporary +import org.jetbrains.kotlin.ir.declarations.IrFile +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.IrVararg +import org.jetbrains.kotlin.ir.expressions.IrVarargElement +import org.jetbrains.kotlin.ir.types.classOrNull +import org.jetbrains.kotlin.ir.util.primaryConstructor +import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid +import org.jetbrains.kotlin.name.Name + +internal class WasmVarargExpressionLowering( + private val context: WasmBackendContext +) : FileLoweringPass, IrElementTransformerVoidWithContext() { + val symbols = context.wasmSymbols + + override fun lower(irFile: IrFile) { + irFile.transformChildrenVoid(this) + } + + override fun visitVararg(expression: IrVararg): IrExpression { + val irVararg = super.visitVararg(expression) as IrVararg + val builder = context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol) + val arrayClass = irVararg.type.classOrNull!!.owner + val primaryConstructor = arrayClass.primaryConstructor!! + val setMethod = arrayClass.declarations.filterIsInstance().find { + it.name == Name.identifier("set") + }!! + return builder.irComposite(irVararg) { + val arrayTempVariable = irTemporary( + value = irCall(primaryConstructor).apply { + putValueArgument(0, irInt(irVararg.elements.size)) + if (primaryConstructor.typeParameters.isNotEmpty()) { + check(primaryConstructor.typeParameters.size == 1) + putTypeArgument(0, irVararg.varargElementType) + } + }, + nameHint = "array_tmp" + ) + for ((index: Int, element: IrVarargElement) in irVararg.elements.withIndex()) { + check(element is IrExpression) { + "TODO: Support $element as vararg elements" + } + + +irCall(setMethod).apply { + dispatchReceiver = irGet(arrayTempVariable) + putValueArgument(0, irInt(index)) + putValueArgument(1, element) + } + } + +irGet(arrayTempVariable) + } + } + + override fun visitFunctionAccess(expression: IrFunctionAccessExpression) = + transformFunctionAccessExpression(expression) + + private fun transformFunctionAccessExpression(expression: IrFunctionAccessExpression): IrExpression { + expression.transformChildrenVoid() + val builder by lazy { context.createIrBuilder(currentScope!!.scope.scopeOwnerSymbol) } + + // Replace empty vararg arguments with empty array construction + for (argumentIdx in 0 until expression.valueArgumentsCount) { + val argument = expression.getValueArgument(argumentIdx) + val parameter = expression.symbol.owner.valueParameters[argumentIdx] + val varargElementType = parameter.varargElementType + if (argument == null && varargElementType != null) { + val arrayClass = parameter.type.classOrNull!!.owner + val primaryConstructor = arrayClass.primaryConstructor!! + val emptyArrayCall = with(builder) { + irCall(primaryConstructor).apply { + putValueArgument(0, irInt(0)) + if (primaryConstructor.typeParameters.isNotEmpty()) { + check(primaryConstructor.typeParameters.size == 1) + putTypeArgument(0, parameter.varargElementType) + } + } + } + expression.putValueArgument(argumentIdx, emptyArrayCall) + } + } + return expression + } +} \ No newline at end of file diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/Annotations.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/Annotations.kt index e5765b0bf96..f61297926fe 100644 --- a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/Annotations.kt +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/Annotations.kt @@ -11,19 +11,27 @@ 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 +import org.jetbrains.kotlin.wasm.ir.WasmImportPair fun IrAnnotationContainer.hasExcludedFromCodegenAnnotation(): Boolean = hasAnnotation(FqName("kotlin.wasm.internal.ExcludedFromCodegen")) -fun IrAnnotationContainer.getWasmInstructionAnnotation(): String? = - getAnnotation(FqName("kotlin.wasm.internal.WasmInstruction"))?.getSingleConstStringArgument() +fun IrAnnotationContainer.getWasmOpAnnotation(): String? = + getAnnotation(FqName("kotlin.wasm.internal.WasmOp"))?.getSingleConstStringArgument() + +fun IrAnnotationContainer.hasWasmReinterpretAnnotation(): Boolean = + hasAnnotation(FqName("kotlin.wasm.internal.WasmReinterpret")) + +fun IrAnnotationContainer.hasWasmForeignAnnotation(): Boolean = + hasAnnotation(FqName("kotlin.wasm.internal.WasmForeign")) + +fun IrAnnotationContainer.hasWasmPrimitiveAnnotation(): Boolean = + hasAnnotation(FqName("kotlin.wasm.internal.WasmPrimitive")) -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).value, - (it.getValueArgument(1) as IrConst).value + (it.getValueArgument(0) as IrConst<*>).value as String, + (it.getValueArgument(1) as IrConst<*>).value as String ) } diff --git a/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/WasmInlineClassesUtils.kt b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/WasmInlineClassesUtils.kt new file mode 100644 index 00000000000..db1af80c55d --- /dev/null +++ b/compiler/ir/backend.wasm/src/org/jetbrains/kotlin/backend/wasm/utils/WasmInlineClassesUtils.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.backend.wasm.utils + +import org.jetbrains.kotlin.backend.wasm.WasmSymbols +import org.jetbrains.kotlin.ir.backend.js.InlineClassesUtils +import org.jetbrains.kotlin.ir.backend.js.utils.erase +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol +import org.jetbrains.kotlin.ir.types.IrSimpleType +import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.ir.types.isNullable + +class WasmInlineClassesUtils(private val wasmSymbols: WasmSymbols) : InlineClassesUtils { + override fun isTypeInlined(type: IrType): Boolean { + return getInlinedClass(type) != null + } + + override fun getInlinedClass(type: IrType): IrClass? { + if (type is IrSimpleType) { + // TODO: Make inlining less strict + if (type.isNullable()) return null + val erased = erase(type) ?: return null + if (isClassInlineLike(erased)) { + return erased + } + } + return null + } + + override fun isClassInlineLike(klass: IrClass): Boolean { + return klass.isInline || klass.hasWasmPrimitiveAnnotation() + } + + override val boxIntrinsic: IrSimpleFunctionSymbol + get() = wasmSymbols.boxIntrinsic + + override val unboxIntrinsic: IrSimpleFunctionSymbol + get() = wasmSymbols.unboxIntrinsic +} \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt index ec2195bda0d..f1435afa502 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/IrUtils.kt @@ -404,14 +404,16 @@ fun irCall( newFunction: IrSimpleFunction, receiversAsArguments: Boolean = false, argumentsAsReceivers: Boolean = false, - newSuperQualifierSymbol: IrClassSymbol? = null + newSuperQualifierSymbol: IrClassSymbol? = null, + newReturnType: IrType? = null ): IrCall = irCall( call, newFunction.symbol, receiversAsArguments, argumentsAsReceivers, - newSuperQualifierSymbol + newSuperQualifierSymbol, + newReturnType ) fun irCall( @@ -419,13 +421,14 @@ fun irCall( newSymbol: IrSimpleFunctionSymbol, receiversAsArguments: Boolean = false, argumentsAsReceivers: Boolean = false, - newSuperQualifierSymbol: IrClassSymbol? = null + newSuperQualifierSymbol: IrClassSymbol? = null, + newReturnType: IrType? = null ): IrCall = call.run { IrCallImpl( startOffset, endOffset, - type, + newReturnType ?: type, newSymbol, typeArgumentsCount, valueArgumentsCount = newSymbol.owner.valueParameters.size, diff --git a/compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt b/compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt new file mode 100644 index 00000000000..80624661016 --- /dev/null +++ b/compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt @@ -0,0 +1,9 @@ + +class C(val x: String) + +fun foo(x: T2): String = + x.x + +fun box(): String { + return foo(C("OK")) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 84247993e99..82a6380bfbe 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -13815,6 +13815,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index e75339efc73..d2dc5b2be07 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -13815,6 +13815,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 3eb4b7ad760..5acf07f1283 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -12415,6 +12415,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/js/js.tests/build.gradle.kts b/js/js.tests/build.gradle.kts index 1d819a6f959..a79d7594555 100644 --- a/js/js.tests/build.gradle.kts +++ b/js/js.tests/build.gradle.kts @@ -232,7 +232,7 @@ val currentOsType = run { OsType(osName, osArch) } -val jsShellDirectory = "https://archive.mozilla.org/pub/firefox/nightly/2019/08/2019-08-11-09-56-40-mozilla-central" +val jsShellDirectory = "https://archive.mozilla.org/pub/firefox/nightly/2020/06/2020-06-29-15-46-04-mozilla-central" val jsShellSuffix = when (currentOsType) { OsType(OsName.LINUX, OsArch.X86_32) -> "linux-i686" OsType(OsName.LINUX, OsArch.X86_64) -> "linux-x86_64" @@ -248,6 +248,7 @@ val downloadedTools = File(buildDir, "tools") val downloadJsShell by task { src(jsShellLocation) dest(File(downloadedTools, "jsshell-$jsShellSuffix.zip")) + overwrite(false) } val unzipJsShell by task { @@ -257,13 +258,45 @@ val unzipJsShell by task { into(unpackedDir) } +val v8osString = when (currentOsType) { + OsType(OsName.LINUX, OsArch.X86_32) -> "linux32" + OsType(OsName.LINUX, OsArch.X86_64) -> "linux64" + OsType(OsName.MAC, OsArch.X86_64) -> "mac64" + OsType(OsName.WINDOWS, OsArch.X86_32) -> "win32" + OsType(OsName.WINDOWS, OsArch.X86_64) -> "win64" + else -> error("unsupported os type $currentOsType") +} + +val v8edition = "rel" // rel or dbg +val v8version = "8.8.104" +val v8fileName = "v8-${v8osString}-${v8edition}-${v8version}" +val v8url = "https://storage.googleapis.com/chromium-v8/official/canary/$v8fileName.zip" + +val downloadV8 by task { + src(v8url) + dest(File(downloadedTools, "$v8fileName.zip")) + overwrite(false) +} + +val unzipV8 by task { + dependsOn(downloadV8) + from(zipTree(downloadV8.get().dest)) + val unpackedDir = File(downloadedTools, v8fileName) + into(unpackedDir) +} + projectTest("wasmTest", true) { dependsOn(unzipJsShell) + dependsOn(unzipV8) include("org/jetbrains/kotlin/js/test/wasm/semantics/*") val jsShellExecutablePath = File(unzipJsShell.get().destinationDir, "js").absolutePath - systemProperty("javascript.engine.path.SpiderMonkey", jsShellExecutablePath) + val v8ExecutablePath = File(unzipV8.get().destinationDir, "d8").absolutePath + println(v8ExecutablePath) - dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs") + systemProperty("javascript.engine.path.SpiderMonkey", jsShellExecutablePath) + systemProperty("javascript.engine.path.V8", v8ExecutablePath) + + dependsOn(":kotlin-stdlib-wasm:compileKotlinJs") systemProperty("kotlin.wasm.stdlib.path", "libraries/stdlib/wasm/build/classes/kotlin/js/main") setUpBoxTests() diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt index 2b9d852f8c0..96e3cf1ea64 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicBoxTest.kt @@ -956,3 +956,14 @@ abstract class BasicBoxTest( else ScriptEngineV8Lazy(KotlinTestUtils.tmpDirForReusableFolder("j2v8_library_path").path) } } + +fun KotlinTestWithEnvironment.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 +} + +fun KotlinTestWithEnvironment.createPsiFiles(fileNames: List): List = fileNames.map(this::createPsiFile) \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt index 5258988720c..8a9c4eed27b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/BasicWasmBoxTest.kt @@ -9,18 +9,20 @@ 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 junit.framework.TestCase 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.checkers.parseLanguageVersionSettings import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport 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.config.* 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.ExternalTool import org.jetbrains.kotlin.js.test.engines.SpiderMonkeyEngine import org.jetbrains.kotlin.library.resolver.impl.KotlinLibraryResolverResultImpl import org.jetbrains.kotlin.library.resolver.impl.KotlinResolvedLibraryImpl @@ -28,10 +30,11 @@ 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.InTextDirectivesUtils import org.jetbrains.kotlin.test.Directives import org.jetbrains.kotlin.test.KotlinTestUtils import org.jetbrains.kotlin.test.KotlinTestWithEnvironment -import org.jetbrains.kotlin.test.TestFiles +import org.jetbrains.kotlin.test.* import java.io.Closeable import java.io.File import java.lang.Boolean.getBoolean @@ -48,8 +51,13 @@ abstract class BasicWasmBoxTest( private val spiderMonkey by lazy { SpiderMonkeyEngine() } + fun doTestWithCoroutinesPackageReplacement(filePath: String, coroutinesPackage: String) { + TODO("TestWithCoroutinesPackageReplacement are not supported") + } + fun doTest(filePath: String) { val file = File(filePath) + val outputDir = getOutputDir(file) val fileContent = KotlinTestUtils.doLoadFile(file) @@ -58,21 +66,31 @@ abstract class BasicWasmBoxTest( val testPackage = testFactory.testPackage val outputFileBase = outputDir.absolutePath + "/" + getTestName(true) val outputWatFile = outputFileBase + ".wat" + val outputWasmFile = outputFileBase + ".wasm" val outputJsFile = outputFileBase + ".js" + val languageVersionSettings = inputFiles.mapNotNull { it.languageVersionSettings }.firstOrNull() + val kotlinFiles = inputFiles.filter { it.fileName.endsWith(".kt") } val psiFiles = createPsiFiles(kotlinFiles.map { File(it.fileName).canonicalPath }.sorted()) - val config = createConfig() + val config = createConfig(languageVersionSettings) translateFiles( + file, psiFiles.map(TranslationUnit::SourceFile), File(outputWatFile), + File(outputWasmFile), File(outputJsFile), config, testPackage, TEST_FUNCTION ) - spiderMonkey.runFile(outputJsFile) + ExternalTool(System.getProperty("javascript.engine.path.V8")) + .run( + "--experimental-wasm-typed-funcref", + "--experimental-wasm-gc", + outputJsFile + ) } } @@ -86,26 +104,32 @@ abstract class BasicWasmBoxTest( } private fun translateFiles( + testFile: File, units: List, outputWatFile: File, + outputWasmFile: File, outputJsFile: File, config: JsConfig, testPackage: String?, testFunction: String ) { val filesToCompile = units.map { (it as TranslationUnit.SourceFile).file } - val debugMode = getBoolean("kotlin.js.debugMode") + val debugMode =getBoolean("kotlin.js.debugMode") 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") + println("\n ------ KT file://${testFile.absolutePath}") + println("\n ------ WAT file://$outputWatFile") + println("\n ------ WASM file://$outputWasmFile") + println(" ------ JS file://$outputJsFile") PhaseConfig( wasmPhases, dumpToDirectory = dumpOutputDir.path, - toDumpStateAfter = allPhasesSet, - toValidateStateAfter = allPhasesSet, - dumpOnlyFqName = null + // toDumpStateAfter = allPhasesSet, + // toValidateStateAfter = allPhasesSet, + // dumpOnlyFqName = null ) } else { PhaseConfig(wasmPhases) @@ -124,12 +148,12 @@ abstract class BasicWasmBoxTest( ) outputWatFile.write(compilerResult.wat) + outputWasmFile.writeBytes(compilerResult.wasm) val runtime = File("libraries/stdlib/wasm/runtime/runtime.js").readText() val testRunner = """ - const wat = read(String.raw`${outputWatFile.absoluteFile}`); - const wasmBinary = wasmTextToBinary(wat); + const wasmBinary = read(String.raw`${outputWasmFile.absoluteFile}`, 'binary'); const wasmModule = new WebAssembly.Module(wasmBinary); const wasmInstance = new WebAssembly.Instance(wasmModule, { runtime }); @@ -141,20 +165,11 @@ abstract class BasicWasmBoxTest( 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): List = fileNames.map(this::createPsiFile) - - private fun createConfig(): JsConfig { + private fun createConfig(languageVersionSettings: LanguageVersionSettings?): JsConfig { val configuration = environment.configuration.copy() configuration.put(CommonConfigurationKeys.MODULE_NAME, TEST_MODULE) + configuration.languageVersionSettings = languageVersionSettings ?: LanguageVersionSettingsImpl(LanguageVersion.LATEST_STABLE, ApiVersion.LATEST_STABLE) return JsConfig(project, configuration, null, null) } @@ -169,11 +184,13 @@ abstract class BasicWasmBoxTest( } } + val languageVersionSettings = parseLanguageVersionSettings(directives) + val temporaryFile = File(tmpDir, "WASM_TEST/$fileName") KotlinTestUtils.mkdirs(temporaryFile.parentFile) temporaryFile.writeText(text, Charsets.UTF_8) - return TestFile(temporaryFile.absolutePath) + return TestFile(temporaryFile.absolutePath, languageVersionSettings) } var testPackage: String? = null @@ -184,7 +201,7 @@ abstract class BasicWasmBoxTest( } } - private class TestFile(val fileName: String) + private class TestFile(val fileName: String, val languageVersionSettings: LanguageVersionSettings?) override fun createEnvironment() = KotlinCoreEnvironment.createForTests(testRootDisposable, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES) diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt b/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt index 76fc2836e14..2a1db810565 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/engines/SpiderMonkey.kt @@ -39,6 +39,6 @@ class SpiderMonkeyEngine( private val jsShell = ExternalTool(jsShellPath) fun runFile(file: String) { - jsShell.run(file) + jsShell.run("--wasm-gc", file) } } \ No newline at end of file diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 9d938e7b4e8..f912b53c80b 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -10655,6 +10655,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 82c63d0a677..e17a9446dab 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -10655,6 +10655,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 4b2a245207b..50ca73ff7af 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -10655,6 +10655,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/functions/recursiveIncrementCall.kt"); } + @TestMetadata("typeParameterAsUpperBound.kt") + public void testTypeParameterAsUpperBound() throws Exception { + runTest("compiler/testData/codegen/box/functions/typeParameterAsUpperBound.kt"); + } + @TestMetadata("typeParametersInLocalFunction.kt") public void testTypeParametersInLocalFunction() throws Exception { runTest("compiler/testData/codegen/box/functions/typeParametersInLocalFunction.kt"); diff --git a/libraries/stdlib/wasm/build.gradle.kts b/libraries/stdlib/wasm/build.gradle.kts index 3c05bd98dc4..5de782a3139 100644 --- a/libraries/stdlib/wasm/build.gradle.kts +++ b/libraries/stdlib/wasm/build.gradle.kts @@ -1,19 +1,65 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinCompile -import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType.IR -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootExtension -import org.jetbrains.kotlin.gradle.targets.js.nodejs.NodeJsRootPlugin plugins { kotlin("multiplatform") } +val unimplementedNativeBuiltIns = + (file("$rootDir/core/builtins/native/kotlin/").list().toSortedSet() - file("$rootDir/libraries/stdlib/wasm/builtins/kotlin/").list()) + .map { "core/builtins/native/kotlin/$it" } + + + +val builtInsSources by task { + val sources = listOf( + "core/builtins/src/kotlin/" + ) + unimplementedNativeBuiltIns + + val excluded = listOf( + // JS-specific optimized version of emptyArray() already defined + "core/builtins/src/kotlin/ArrayIntrinsics.kt" + ) + + sources.forEach { path -> + from("$rootDir/$path") { + into(path.dropLastWhile { it != '/' }) + excluded.filter { it.startsWith(path) }.forEach { + exclude(it.substring(path.length)) + } + } + } + + into("$buildDir/builtInsSources") +} + +val commonMainSources by task { + val sources = listOf( + "libraries/stdlib/common/src/", + "libraries/stdlib/src/kotlin/", + "libraries/stdlib/unsigned/" + ) + + sources.forEach { path -> + from("$rootDir/$path") { + into(path.dropLastWhile { it != '/' }) + } + } + + into("$buildDir/commonMainSources") +} + kotlin { js(IR) { nodejs() } sourceSets { val jsMain by getting { - kotlin.srcDirs("builtins", "internal", "runtime") + kotlin.srcDirs("builtins", "internal", "runtime", "src", "stubs") + kotlin.srcDirs(files(builtInsSources.map { it.destinationDir })) + } + + val commonMain by getting { + kotlin.srcDirs(files(commonMainSources.map { it.destinationDir })) } } } @@ -28,10 +74,13 @@ tasks.withType>().configureEach { "-Xinline-classes", "-Xopt-in=kotlin.RequiresOptIn", "-Xopt-in=kotlin.ExperimentalUnsignedTypes", - "-Xopt-in=kotlin.ExperimentalStdlibApi" + "-Xopt-in=kotlin.ExperimentalStdlibApi", + "-Xexplicit-api=warning" ) } tasks.named("compileKotlinJs") { (this as KotlinCompile<*>).kotlinOptions.freeCompilerArgs += "-Xir-module-name=kotlin" + dependsOn(commonMainSources) + dependsOn(builtInsSources) } \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/README.md b/libraries/stdlib/wasm/builtins/README.md deleted file mode 100644 index 5fdf80ad83d..00000000000 --- a/libraries/stdlib/wasm/builtins/README.md +++ /dev/null @@ -1,6 +0,0 @@ -This directory is a modified copy of `core/builtins` adapted for current - needs of WASM backend. - -This is a temporary solution for a development convenience. Most of files -from `core/builtins` will be reused once compiler implementation and -stdlib become stable. \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Any.kt b/libraries/stdlib/wasm/builtins/kotlin/Any.kt similarity index 81% rename from libraries/stdlib/wasm/builtins/native/kotlin/Any.kt rename to libraries/stdlib/wasm/builtins/kotlin/Any.kt index 7e4e09f66bd..c95a877af4f 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Any.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Any.kt @@ -3,20 +3,19 @@ * 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" -) - package kotlin +import kotlin.wasm.internal.* + /** * The root of the Kotlin class hierarchy. Every Kotlin class has [Any] as a superclass. */ public open class Any { + // Pointer to runtime type info + // Initialized by a compiler + @Suppress("MUST_BE_INITIALIZED_OR_BE_ABSTRACT") + internal var typeInfo: Int + /** * Indicates whether some other object is "equal to" this one. Implementations must fulfil the following * requirements: @@ -29,7 +28,8 @@ public open class Any { * * Read more about [equality](https://kotlinlang.org/docs/reference/equality.html) in Kotlin. */ - public open operator fun equals(other: Any?): Boolean + public open operator fun equals(other: Any?): Boolean = + wasm_ref_eq(this, other) /** * Returns a hash code value for the object. The general contract of `hashCode` is: @@ -37,10 +37,12 @@ public open class Any { * * Whenever it is invoked on the same object more than once, the `hashCode` method must consistently return the same integer, provided no information used in `equals` comparisons on the object is modified. * * If two objects are equal according to the `equals()` method, then calling the `hashCode` method on each of the two objects must produce the same integer result. */ - public open fun hashCode(): Int + // TODO: Implement + public open fun hashCode(): Int = 100 /** * Returns a string representation of the object. */ - public open fun toString(): String + // TODO: Implement + public open fun toString(): String = "[Object object]" } diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Array.kt b/libraries/stdlib/wasm/builtins/kotlin/Array.kt similarity index 65% rename from libraries/stdlib/wasm/builtins/native/kotlin/Array.kt rename to libraries/stdlib/wasm/builtins/kotlin/Array.kt index 933f00c8f9e..cdc115b427f 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Array.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Array.kt @@ -3,16 +3,10 @@ * 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" -) - package kotlin +import kotlin.wasm.internal.* + /** * Represents an array (specifically, a Java array when targeting the JVM platform). * Array instances can be created using the [arrayOf], [arrayOfNulls] and [emptyArray] @@ -20,7 +14,9 @@ package kotlin * See [Kotlin language documentation](https://kotlinlang.org/docs/reference/basic-types.html#arrays) * for more information on arrays. */ -public class Array { +public class Array constructor(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + /** * Creates a new array with the specified [size], where each element is calculated by calling the specified * [init] function. @@ -28,7 +24,10 @@ public class Array { * The function [init] is called for each array element sequentially starting from the first one. * It should return the value for an array element given its index. */ - public inline constructor(size: Int, init: (Int) -> T) + @Suppress("TYPE_PARAMETER_AS_REIFIED") + public constructor(size: Int, init: (Int) -> T) : this(size) { + JsArray_fill_T(jsArray, size, init) + } /** * Returns the array element at the specified [index]. This method can be called using the @@ -40,7 +39,9 @@ public class Array { * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS * where the behavior is unspecified. */ - public operator fun get(index: Int): T + @Suppress("UNCHECKED_CAST") + public operator fun get(index: Int): T = + WasmExternRefToAny(JsArray_get_WasmExternRef(jsArray, index)) as T /** * Sets the array element at the specified [index] to the specified [value]. This method can @@ -52,15 +53,25 @@ public class Array { * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS * where the behavior is unspecified. */ - public operator fun set(index: Int, value: T): Unit + public operator fun set(index: Int, value: T) { + JsArray_set_WasmExternRef(jsArray, index, value.toWasmExternRef()) + } /** * Returns the number of elements in the array. */ public val size: Int + get() = JsArray_getSize(jsArray) /** * Creates an iterator for iterating over the elements of the array. */ - public operator fun iterator(): Iterator + public operator fun iterator(): Iterator = arrayIterator(this) } + +internal fun arrayIterator(array: Array) = object : Iterator { + var index = 0 + override fun hasNext() = index != array.size + override fun next() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + diff --git a/libraries/stdlib/wasm/builtins/kotlin/Arrays.kt b/libraries/stdlib/wasm/builtins/kotlin/Arrays.kt new file mode 100644 index 00000000000..3cc884ec1c9 --- /dev/null +++ b/libraries/stdlib/wasm/builtins/kotlin/Arrays.kt @@ -0,0 +1,265 @@ +/* + * 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.wasm.internal.* + +public class ByteArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Byte(jsArray, size) { 0 } + } + + public constructor(size: Int, init: (Int) -> Byte) : this(size) { + jsArray = JsArray_new(size) + JsArray_fill_Byte(jsArray, size, init) + } + + public operator fun get(index: Int): Byte = + JsArray_get_Byte(jsArray, index) + + public operator fun set(index: Int, value: Byte) { + JsArray_set_Byte(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): ByteIterator = byteArrayIterator(this) +} + +internal fun byteArrayIterator(array: ByteArray) = object : ByteIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextByte() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class CharArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Char(jsArray, size) { 0.toChar() } + } + + public constructor(size: Int, init: (Int) -> Char) : this(size) { + jsArray = JsArray_new(size) + JsArray_fill_Char(jsArray, size, init) + } + + public operator fun get(index: Int): Char = + JsArray_get_Char(jsArray, index) + + public operator fun set(index: Int, value: Char) { + JsArray_set_Char(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): CharIterator = charArrayIterator(this) +} + +internal fun charArrayIterator(array: CharArray) = object : CharIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextChar() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class ShortArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Short(jsArray, size) { 0 } + } + + public constructor(size: Int, init: (Int) -> Short) : this(size) { + JsArray_fill_Short(jsArray, size, init) + } + + public operator fun get(index: Int): Short = + JsArray_get_Short(jsArray, index) + + public operator fun set(index: Int, value: Short) { + JsArray_set_Short(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): ShortIterator = shortArrayIterator(this) +} + +internal fun shortArrayIterator(array: ShortArray) = object : ShortIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextShort() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class IntArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Int(jsArray, size) { 0 } + } + + public constructor(size: Int, init: (Int) -> Int) : this(size) { + JsArray_fill_Int(jsArray, size, init) + } + + public operator fun get(index: Int): Int = + JsArray_get_Int(jsArray, index) + + public operator fun set(index: Int, value: Int) { + JsArray_set_Int(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): IntIterator = intArrayIterator(this) +} + +internal fun intArrayIterator(array: IntArray) = object : IntIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextInt() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class LongArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Long(jsArray, size) { 0L } + } + + public constructor(size: Int, init: (Int) -> Long) : this(size) { + JsArray_fill_Long(jsArray, size, init) + } + + public operator fun get(index: Int): Long = + JsArray_get_Long(jsArray, index) + + public operator fun set(index: Int, value: Long) { + JsArray_set_Long(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): LongIterator = longArrayIterator(this) +} + +internal fun longArrayIterator(array: LongArray) = object : LongIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextLong() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class FloatArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Float(jsArray, size) { 0.0f } + } + + public constructor(size: Int, init: (Int) -> Float) : this(size) { + JsArray_fill_Float(jsArray, size, init) + } + + public operator fun get(index: Int): Float = + JsArray_get_Float(jsArray, index) + + public operator fun set(index: Int, value: Float) { + JsArray_set_Float(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): FloatIterator = floatArrayIterator(this) +} + +internal fun floatArrayIterator(array: FloatArray) = object : FloatIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextFloat() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class DoubleArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Double(jsArray, size) { 0.0 } + } + + public constructor(size: Int, init: (Int) -> Double) : this(size) { + JsArray_fill_Double(jsArray, size, init) + } + + public operator fun get(index: Int): Double = + JsArray_get_Double(jsArray, index) + + public operator fun set(index: Int, value: Double) { + JsArray_set_Double(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): DoubleIterator = doubleArrayIterator(this) +} + +internal fun doubleArrayIterator(array: DoubleArray) = object : DoubleIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextDouble() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} + + +public class BooleanArray(size: Int) { + private var jsArray: WasmExternRef = JsArray_new(size) + + init { + JsArray_fill_Boolean(jsArray, size) { false } + } + + public constructor(size: Int, init: (Int) -> Boolean) : this(size) { + JsArray_fill_Boolean(jsArray, size, init) + } + + public operator fun get(index: Int): Boolean = + JsArray_get_Boolean(jsArray, index) + + public operator fun set(index: Int, value: Boolean) { + JsArray_set_Boolean(jsArray, index, value) + } + + public val size: Int + get() = JsArray_getSize(jsArray) + + + public operator fun iterator(): BooleanIterator = booleanArrayIterator(this) +} + +internal fun booleanArrayIterator(array: BooleanArray) = object : BooleanIterator() { + var index = 0 + override fun hasNext() = index != array.size + override fun nextBoolean() = if (index != array.size) array[index++] else throw NoSuchElementException("$index") +} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Boolean.kt b/libraries/stdlib/wasm/builtins/kotlin/Boolean.kt similarity index 51% rename from libraries/stdlib/wasm/builtins/native/kotlin/Boolean.kt rename to libraries/stdlib/wasm/builtins/kotlin/Boolean.kt index adb106c4cc6..d40e68cf330 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Boolean.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Boolean.kt @@ -3,56 +3,67 @@ * 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" -) - package kotlin -import kotlin.wasm.internal.WasmInstruction -import kotlin.wasm.internal.wasm_i32_compareTo +import kotlin.wasm.internal.* /** * 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`. */ -public class Boolean private constructor() : Comparable { +@WasmPrimitive +public class Boolean private constructor(private val value: Boolean) : Comparable { /** * Returns the inverse of this boolean. */ - @WasmInstruction(WasmInstruction.I32_EQZ) - public operator fun not(): Boolean + @WasmOp(WasmOp.I32_EQZ) + public operator fun not(): Boolean = + implementedAsIntrinsic /** * 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 + @WasmOp(WasmOp.I32_AND) + public infix fun and(other: Boolean): Boolean = + implementedAsIntrinsic /** * 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 + @WasmOp(WasmOp.I32_OR) + public infix fun or(other: Boolean): Boolean = + implementedAsIntrinsic /** * Performs a logical `xor` operation between this Boolean and the [other] one. */ - @WasmInstruction(WasmInstruction.I32_XOR) - public infix fun xor(other: Boolean): Boolean + @WasmOp(WasmOp.I32_XOR) + public infix fun xor(other: Boolean): Boolean = + implementedAsIntrinsic public override fun compareTo(other: Boolean): Int = - wasm_i32_compareTo(this.asInt(), other.asInt()) + wasm_i32_compareTo(this.toInt(), other.toInt()) - @WasmInstruction(WasmInstruction.NOP) - internal fun asInt(): Int + override fun toString(): String = + if (this) "true" else "false" + + override fun hashCode(): Int = + toInt() + + override fun equals(other: Any?): Boolean { + return if (other !is Boolean) { + false + } else { + this === (other as Boolean) + } + } + + @WasmReinterpret + internal fun toInt(): Int = + implementedAsIntrinsic @SinceKotlin("1.3") - companion object {} + public companion object } diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Char.kt b/libraries/stdlib/wasm/builtins/kotlin/Char.kt similarity index 82% rename from libraries/stdlib/wasm/builtins/native/kotlin/Char.kt rename to libraries/stdlib/wasm/builtins/kotlin/Char.kt index 7f5dec7b135..49391beb5c9 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Char.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Char.kt @@ -3,30 +3,34 @@ * 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("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 +import kotlin.wasm.internal.* /** * Represents a 16-bit Unicode character. * * On the JVM, non-nullable values of this type are represented as values of the primitive type `char`. */ -public class Char private constructor() : Comparable { +@WasmPrimitive +@Suppress("NOTHING_TO_INLINE") +public class Char private constructor(public val value: Char) : Comparable { /** * Compares this value with the specified value for order. * * 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 inline fun compareTo(other: Char): Int = + public override fun compareTo(other: Char): Int = wasm_i32_compareTo(this.toInt(), other.toInt()) + public override fun equals(other: Any?): Boolean { + if (other is Char) + return this === (other as Char) + return false + } + /** Adds the other Int value to this value resulting a Char. */ public inline operator fun plus(other: Int): Char = (this.toInt() + other).toChar() @@ -47,34 +51,46 @@ public class Char private constructor() : Comparable { 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 + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Char): CharRange = + CharRange(this, other) /** Returns the value of this character as a `Byte`. */ public inline fun toByte(): Byte = this.toInt().toByte() + /** Returns the value of this character as a `Char`. */ public inline fun toChar(): Char = this + /** Returns the value of this character as a `Short`. */ public inline fun toShort(): Short = this.toInt().toShort() + /** Returns the value of this character as a `Int`. */ - @WasmInstruction(WasmInstruction.NOP) + @WasmReinterpret public fun toInt(): Int = implementedAsIntrinsic + /** Returns the value of this character as a `Long`. */ public inline fun toLong(): Long = this.toInt().toLong() + /** Returns the value of this character as a `Float`. */ public inline fun toFloat(): Float = this.toInt().toFloat() + /** Returns the value of this character as a `Double`. */ public inline fun toDouble(): Double = this.toInt().toDouble() - @ExcludedFromCodegen - companion object { + override fun toString(): String = + charToString(this) + + override fun hashCode(): Int = + this.toInt().hashCode() + + public companion object { /** * The minimum value of a character code unit. */ @@ -129,6 +145,8 @@ public class Char private constructor() : Comparable { @SinceKotlin("1.3") public const val SIZE_BITS: Int = 16 } - } +@WasmImport("runtime", "Char_toString") +private fun charToString(c: Char): String = implementedAsIntrinsic + diff --git a/libraries/stdlib/wasm/builtins/kotlin/Enum.kt b/libraries/stdlib/wasm/builtins/kotlin/Enum.kt new file mode 100644 index 00000000000..facf0e2758c --- /dev/null +++ b/libraries/stdlib/wasm/builtins/kotlin/Enum.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + +public abstract class Enum>( + public val name: String, + public val ordinal: Int +) : Comparable { + + override fun compareTo(other: E): Int = + ordinal.compareTo(other.ordinal) + + override fun toString(): String = + name + + public companion object +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Library.kt b/libraries/stdlib/wasm/builtins/kotlin/Library.kt similarity index 56% rename from libraries/stdlib/wasm/builtins/native/kotlin/Library.kt rename to libraries/stdlib/wasm/builtins/kotlin/Library.kt index 19dce79c26a..2fc76fcb4c7 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Library.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Library.kt @@ -2,86 +2,90 @@ * 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:Suppress( - "NON_MEMBER_FUNCTION_NO_BODY", - "REIFIED_TYPE_PARAMETER_NO_INLINE" -) -@file:kotlin.wasm.internal.ExcludedFromCodegen + +@file:Suppress("NOTHING_TO_INLINE") package kotlin import kotlin.internal.PureReifiable +public inline fun emptyArray(): Array = arrayOf() + /** * Returns a string representation of the object. Can be called with a null receiver, in which case * it returns the string "null". */ -public fun Any?.toString(): String +public fun Any?.toString(): String = this?.toString() ?: "null" /** * Concatenates this string with the string representation of the given [other] object. If either the receiver * or the [other] object are null, they are represented as the string "null". */ -public operator fun String?.plus(other: Any?): String +public operator fun String?.plus(other: Any?): String = (this ?: "null") + other.toString() /** * Returns an array of objects of the given type with the given [size], initialized with null values. */ -public fun arrayOfNulls(size: Int): Array +// TODO: Should T be reified? +@Suppress("REIFIED_TYPE_PARAMETER_NO_INLINE") +public fun <@PureReifiable reified T> arrayOfNulls(size: Int): Array = Array(size) { null } /** * Returns an array containing the specified elements. */ -public inline fun arrayOf(vararg elements: T): Array +@Suppress("UNCHECKED_CAST") +public inline fun arrayOf(vararg elements: T): Array = elements as Array /** * Returns an array containing the specified [Double] numbers. */ -public fun doubleArrayOf(vararg elements: Double): DoubleArray +public inline fun doubleArrayOf(vararg elements: Double): DoubleArray = elements /** * Returns an array containing the specified [Float] numbers. */ -public fun floatArrayOf(vararg elements: Float): FloatArray +public inline fun floatArrayOf(vararg elements: Float): FloatArray = elements /** * Returns an array containing the specified [Long] numbers. */ -public fun longArrayOf(vararg elements: Long): LongArray +public inline fun longArrayOf(vararg elements: Long): LongArray = elements /** * Returns an array containing the specified [Int] numbers. */ -public fun intArrayOf(vararg elements: Int): IntArray +public inline fun intArrayOf(vararg elements: Int): IntArray = elements /** * Returns an array containing the specified characters. */ -public fun charArrayOf(vararg elements: Char): CharArray +public inline fun charArrayOf(vararg elements: Char): CharArray = elements /** * Returns an array containing the specified [Short] numbers. */ -public fun shortArrayOf(vararg elements: Short): ShortArray +public inline fun shortArrayOf(vararg elements: Short): ShortArray = elements /** * Returns an array containing the specified [Byte] numbers. */ -public fun byteArrayOf(vararg elements: Byte): ByteArray +public inline fun byteArrayOf(vararg elements: Byte): ByteArray = elements /** * Returns an array containing the specified boolean values. */ -public fun booleanArrayOf(vararg elements: Boolean): BooleanArray +public inline fun booleanArrayOf(vararg elements: Boolean): BooleanArray = elements /** * Returns an array containing enum T entries. */ @SinceKotlin("1.1") +@Suppress("NON_MEMBER_FUNCTION_NO_BODY") public inline fun > enumValues(): Array /** * Returns an enum entry with specified name. */ @SinceKotlin("1.1") +@Suppress("NON_MEMBER_FUNCTION_NO_BODY") public inline fun > enumValueOf(name: String): T \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Nothing.kt b/libraries/stdlib/wasm/builtins/kotlin/Nothing.kt similarity index 92% rename from libraries/stdlib/wasm/builtins/native/kotlin/Nothing.kt rename to libraries/stdlib/wasm/builtins/kotlin/Nothing.kt index b2efbb75194..5fa13d4ff09 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Nothing.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Nothing.kt @@ -16,8 +16,11 @@ package kotlin +import kotlin.wasm.internal.ExcludedFromCodegen + /** * Nothing has no instances. You can use Nothing to represent "a value that never exists": for example, * if a function has the return type of Nothing, it means that it never returns (always throws an exception). */ +@ExcludedFromCodegen public class Nothing private constructor() diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Primitives.kt b/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt similarity index 86% rename from libraries/stdlib/wasm/builtins/native/kotlin/Primitives.kt rename to libraries/stdlib/wasm/builtins/kotlin/Primitives.kt index b645e6a3e90..bc585e0b1d6 100644 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Primitives.kt +++ b/libraries/stdlib/wasm/builtins/kotlin/Primitives.kt @@ -2,7 +2,11 @@ * 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:Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") +@file:Suppress( + "OVERRIDE_BY_INLINE", + "NOTHING_TO_INLINE", + "unused" +) package kotlin @@ -11,9 +15,9 @@ import kotlin.wasm.internal.* /** * Represents a 8-bit signed integer. */ -public class Byte private constructor() : Number(), Comparable { - @ExcludedFromCodegen - companion object { +@WasmPrimitive +public class Byte private constructor(public val value: Byte) : Number(), Comparable { + public companion object { /** * A constant holding the minimum value an instance of Byte can have. */ @@ -233,8 +237,7 @@ public class Byte private constructor() : Number(), Comparable { * The least significant 8 bits of the resulting `Char` code are the same as the bits of this `Byte` value, * whereas the most significant 8 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.NOP) - public override fun toChar(): Char = implementedAsIntrinsic + public override fun toChar(): Char = reinterpretAsInt().reinterpretAsChar() /** * Converts this [Byte] value to [Short]. @@ -244,8 +247,7 @@ public class Byte private constructor() : Number(), Comparable { * The least significant 8 bits of the resulting `Short` value are the same as the bits of this `Byte` value, * whereas the most significant 8 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.NOP) - public override fun toShort(): Short = implementedAsIntrinsic + public override fun toShort(): Short = reinterpretAsInt().reinterpretAsShort() /** * Converts this [Byte] value to [Int]. @@ -255,8 +257,7 @@ public class Byte private constructor() : Number(), Comparable { * The least significant 8 bits of the resulting `Int` value are the same as the bits of this `Byte` value, * whereas the most significant 24 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.NOP) - public override fun toInt(): Int = implementedAsIntrinsic + public override fun toInt(): Int = reinterpretAsInt() /** * Converts this [Byte] value to [Long]. @@ -266,62 +267,93 @@ public class Byte private constructor() : Number(), Comparable { * The least significant 8 bits of the resulting `Long` value are the same as the bits of this `Byte` value, * whereas the most significant 56 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.I64_EXTEND_I32_S) - public override fun toLong(): Long = implementedAsIntrinsic + public override fun toLong(): Long = wasm_i64_extend_i32_s(this.toInt()) /** * Converts this [Byte] value to [Float]. * * The resulting `Float` value represents the same numerical value as this `Byte`. */ - @WasmInstruction(WasmInstruction.F32_CONVERT_I32_S) - public override fun toFloat(): Float = implementedAsIntrinsic + public override fun toFloat(): Float = wasm_f32_convert_i32_s(this.toInt()) /** * Converts this [Byte] value to [Double]. * * The resulting `Double` value represents the same numerical value as this `Byte`. */ - @WasmInstruction(WasmInstruction.F64_CONVERT_I32_S) - public override fun toDouble(): Double = implementedAsIntrinsic + public override fun toDouble(): Double = wasm_f64_convert_i32_s(this.toInt()) -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Byte): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Short): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Int): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Long): LongRange { -// return LongRange(this.toLong(), other.toLong()) -// } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this.toInt(), other.toInt()) + } - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Byte && wasm_i32_eq(this.toInt(), other.toInt()).reinterpretAsBoolean() + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other.toLong()) + } + + /** Performs a bitwise AND operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_AND) + public infix fun and(other: Byte): Byte = + implementedAsIntrinsic + + /** Performs a bitwise OR operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_OR) + public infix fun or(other: Byte): Byte = + implementedAsIntrinsic + + /** Performs a bitwise XOR operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_XOR) + public infix fun xor(other: Byte): Byte = + implementedAsIntrinsic + + /** Inverts the bits in this value/ */ + @SinceKotlin("1.1") + public inline fun inv(): Byte = this.xor(-1) + + + public override fun equals(other: Any?): Boolean = + other is Byte && wasm_i32_eq(this.toInt(), other.toInt()) public inline fun equals(other: Byte): Boolean = - wasm_i32_eq(this.toInt(), other.toInt()).reinterpretAsBoolean() + wasm_i32_eq(this.toInt(), other.toInt()) - // TODO: Implement Byte.toString() - // public override fun toString(): String + public override fun toString(): String = + byteToStringImpl(this) public override inline fun hashCode(): Int = this.toInt() + + @WasmReinterpret + @PublishedApi + internal fun reinterpretAsInt(): Int = + implementedAsIntrinsic } +@WasmImport("runtime", "coerceToString") +private fun byteToStringImpl(byte: Byte): String = + implementedAsIntrinsic + /** * Represents a 16-bit signed integer. */ -public class Short private constructor() : Number(), Comparable { - @ExcludedFromCodegen - companion object { +@WasmPrimitive +public class Short private constructor(public val value: Short) : Number(), Comparable { + public companion object { /** * A constant holding the minimum value an instance of Short can have. */ @@ -529,22 +561,48 @@ public class Short private constructor() : Number(), Comparable { public inline operator fun unaryMinus(): Int = -this.toInt() -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Byte): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Short): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Int): IntRange { -// return IntRange(this.toInt(), other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Long): LongRange { -// return LongRange(this.toLong(), other.toLong()) -// } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this.toInt(), other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this.toInt(), other) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other) + } + + /** Performs a bitwise AND operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_AND) + public infix fun and(other: Short): Short = + implementedAsIntrinsic + + /** Performs a bitwise OR operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_OR) + public infix fun or(other: Short): Short = + implementedAsIntrinsic + + /** Performs a bitwise XOR operation between the two values. */ + @SinceKotlin("1.1") + @WasmOp(WasmOp.I32_XOR) + public infix fun xor(other: Short): Short = + implementedAsIntrinsic + + /** Inverts the bits in this value */ + @SinceKotlin("1.1") + public fun inv(): Short = + this.xor(-1) /** * Converts this [Short] value to [Byte]. @@ -563,9 +621,7 @@ public class Short private constructor() : Number(), Comparable { * The resulting `Char` code is equal to this value reinterpreted as an unsigned number, * i.e. it has the same binary representation as this `Short`. */ - @WasmInstruction(WasmInstruction.NOP) - public override fun toChar(): Char = - implementedAsIntrinsic + public override fun toChar(): Char = reinterpretAsInt().reinterpretAsChar() /** Returns this value. */ public override inline fun toShort(): Short = @@ -579,9 +635,7 @@ public class Short private constructor() : Number(), Comparable { * The least significant 16 bits of the resulting `Int` value are the same as the bits of this `Short` value, * whereas the most significant 16 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.NOP) - public override fun toInt(): Int = - implementedAsIntrinsic + public override fun toInt(): Int = reinterpretAsInt() /** * Converts this [Short] value to [Long]. @@ -591,49 +645,50 @@ public class Short private constructor() : Number(), Comparable { * The least significant 16 bits of the resulting `Long` value are the same as the bits of this `Short` value, * whereas the most significant 48 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.I64_EXTEND_I32_S) - public override fun toLong(): Long = - implementedAsIntrinsic + public override fun toLong(): Long = wasm_i64_extend_i32_s(this.toInt()) /** * Converts this [Short] value to [Float]. * * The resulting `Float` value represents the same numerical value as this `Short`. */ - @WasmInstruction(WasmInstruction.F32_CONVERT_I32_S) - public override fun toFloat(): Float = - implementedAsIntrinsic + public override fun toFloat(): Float = wasm_f32_convert_i32_s(this.toInt()) /** * Converts this [Short] value to [Double]. * * The resulting `Double` value represents the same numerical value as this `Short`. */ - @WasmInstruction(WasmInstruction.F64_CONVERT_I32_S) public override fun toDouble(): Double = - implementedAsIntrinsic + wasm_f64_convert_i32_s(this.toInt()) public inline fun equals(other: Short): Boolean = - wasm_i32_eq(this.toInt(), other.toInt()).reinterpretAsBoolean() + wasm_i32_eq(this.toInt(), other.toInt()) - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Short && wasm_i32_eq(this.toInt(), other.toInt()).reinterpretAsBoolean() + public override fun equals(other: Any?): Boolean = + other is Short && wasm_i32_eq(this.toInt(), other.toInt()) - // TODO: Implement Short.toString() - // public override fun toString(): String + public override fun toString(): String = shortToStringImpl(this) public override inline fun hashCode(): Int = this.toInt() + + @WasmReinterpret + @PublishedApi + internal fun reinterpretAsInt(): Int = + implementedAsIntrinsic } +@WasmImport("runtime", "coerceToString") +private fun shortToStringImpl(x: Short): String = implementedAsIntrinsic + /** * Represents a 32-bit signed integer. */ -public class Int private constructor() : Number(), Comparable { +@WasmPrimitive +public class Int private constructor(val value: Int) : Number(), Comparable { - @ExcludedFromCodegen - companion object { + public companion object { /** * A constant holding the minimum value an instance of Int can have. */ @@ -714,7 +769,7 @@ public class Int private constructor() : Number(), Comparable { this + other.toInt() /** Adds the other value to this value. */ - @WasmInstruction(WasmInstruction.I32_ADD) + @WasmOp(WasmOp.I32_ADD) public operator fun plus(other: Int): Int = implementedAsIntrinsic @@ -739,7 +794,7 @@ public class Int private constructor() : Number(), Comparable { this - other.toInt() /** Subtracts the other value from this value. */ - @WasmInstruction(WasmInstruction.I32_SUB) + @WasmOp(WasmOp.I32_SUB) public operator fun minus(other: Int): Int = implementedAsIntrinsic @@ -764,7 +819,7 @@ public class Int private constructor() : Number(), Comparable { this * other.toInt() /** Multiplies this value by the other value. */ - @WasmInstruction(WasmInstruction.I32_MUL) + @WasmOp(WasmOp.I32_MUL) public operator fun times(other: Int): Int = implementedAsIntrinsic @@ -789,7 +844,7 @@ public class Int private constructor() : Number(), Comparable { this / other.toInt() /** Divides this value by the other value. */ - @WasmInstruction(WasmInstruction.I32_DIV_S) + @WasmOp(WasmOp.I32_DIV_S) public operator fun div(other: Int): Int = implementedAsIntrinsic @@ -814,7 +869,7 @@ public class Int private constructor() : Number(), Comparable { this % other.toInt() /** Calculates the remainder of dividing this value by the other value. */ - @WasmInstruction(WasmInstruction.I32_REM_S) + @WasmOp(WasmOp.I32_REM_S) public operator fun rem(other: Int): Int = implementedAsIntrinsic @@ -835,7 +890,8 @@ public class Int private constructor() : Number(), Comparable { this + 1 /** Decrements this value. */ - public inline operator fun dec(): Int = + // TODO: Fix test compiler/testData/codegen/box/functions/invoke/invoke.kt with inline dec + public operator fun dec(): Int = this - 1 /** Returns this value. */ @@ -850,7 +906,7 @@ public class Int private constructor() : Number(), Comparable { * Note that only the five lowest-order bits of the [bitCount] are used as the shift distance. * The shift distance actually used is therefore always in the range `0..31`. */ - @WasmInstruction(WasmInstruction.I32_SHL) + @WasmOp(WasmOp.I32_SHL) public infix fun shl(bitCount: Int): Int = implementedAsIntrinsic @@ -860,7 +916,7 @@ public class Int private constructor() : Number(), Comparable { * Note that only the five lowest-order bits of the [bitCount] are used as the shift distance. * The shift distance actually used is therefore always in the range `0..31`. */ - @WasmInstruction(WasmInstruction.I32_SHR_S) + @WasmOp(WasmOp.I32_SHR_S) public infix fun shr(bitCount: Int): Int = implementedAsIntrinsic @@ -870,22 +926,22 @@ public class Int private constructor() : Number(), Comparable { * Note that only the five lowest-order bits of the [bitCount] are used as the shift distance. * The shift distance actually used is therefore always in the range `0..31`. */ - @WasmInstruction(WasmInstruction.I32_SHR_U) + @WasmOp(WasmOp.I32_SHR_U) public infix fun ushr(bitCount: Int): Int = implementedAsIntrinsic /** Performs a bitwise AND operation between the two values. */ - @WasmInstruction(WasmInstruction.I32_AND) + @WasmOp(WasmOp.I32_AND) public infix fun and(other: Int): Int = implementedAsIntrinsic /** Performs a bitwise OR operation between the two values. */ - @WasmInstruction(WasmInstruction.I32_OR) + @WasmOp(WasmOp.I32_OR) public infix fun or(other: Int): Int = implementedAsIntrinsic /** Performs a bitwise XOR operation between the two values. */ - @WasmInstruction(WasmInstruction.I32_XOR) + @WasmOp(WasmOp.I32_XOR) public infix fun xor(other: Int): Int = implementedAsIntrinsic @@ -893,22 +949,25 @@ public class Int private constructor() : Number(), Comparable { public inline fun inv(): Int = this.xor(-1) -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Byte): IntRange { -// return IntRange(this, other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Short): IntRange { -// return IntRange(this, other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Int): IntRange { -// return IntRange(this, other.toInt()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Long): LongRange { -// return LongRange(this.toLong(), other.toLong()) -// } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): IntRange { + return IntRange(this, other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): IntRange { + return IntRange(this, other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): IntRange { + return IntRange(this, other.toInt()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this.toLong(), other.toLong()) + } /** * Converts this [Int] value to [Byte]. @@ -955,9 +1014,8 @@ public class Int private constructor() : Number(), Comparable { * The least significant 32 bits of the resulting `Long` value are the same as the bits of this `Int` value, * whereas the most significant 32 bits are filled with the sign bit of this value. */ - @WasmInstruction(WasmInstruction.I64_EXTEND_I32_S) public override fun toLong(): Long = - implementedAsIntrinsic + wasm_i64_extend_i32_s(this) /** * Converts this [Int] value to [Float]. @@ -966,60 +1024,61 @@ public class Int private constructor() : Number(), Comparable { * In case when this `Int` value is exactly between two `Float`s, * the one with zero at least significant bit of mantissa is selected. */ - @WasmInstruction(WasmInstruction.F32_CONVERT_I32_S) public override fun toFloat(): Float = - implementedAsIntrinsic + wasm_f32_convert_i32_s(this) /** * Converts this [Int] value to [Double]. * * The resulting `Double` value represents the same numerical value as this `Int`. */ - @WasmInstruction(WasmInstruction.F64_CONVERT_I32_S) public override fun toDouble(): Double = - implementedAsIntrinsic + wasm_f64_convert_i32_s(this) public inline fun equals(other: Int): Boolean = - wasm_i32_eq(this, other).reinterpretAsBoolean() + wasm_i32_eq(this, other) - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Int && wasm_i32_eq(this, other).reinterpretAsBoolean() + public override fun equals(other: Any?): Boolean = + other is Int && wasm_i32_eq(this, other) - // TODO: Implement Int.toString() - // public override fun toString(): String + public override fun toString(): String = + intToStringImpl(this) public override inline fun hashCode(): Int = this - @WasmInstruction(WasmInstruction.NOP) + @WasmReinterpret @PublishedApi internal fun reinterpretAsBoolean(): Boolean = implementedAsIntrinsic @PublishedApi - @WasmInstruction(WasmInstruction.NOP) + @WasmReinterpret internal fun reinterpretAsByte(): Byte = implementedAsIntrinsic @PublishedApi - @WasmInstruction(WasmInstruction.NOP) + @WasmReinterpret internal fun reinterpretAsShort(): Short = implementedAsIntrinsic @PublishedApi - @WasmInstruction(WasmInstruction.NOP) + @WasmReinterpret internal fun reinterpretAsChar(): Char = implementedAsIntrinsic } +@WasmImport("runtime", "coerceToString") +private fun intToStringImpl(x: Int): String = + implementedAsIntrinsic + /** * Represents a 64-bit signed integer. */ -public class Long private constructor() : Number(), Comparable { +@WasmPrimitive +public class Long private constructor(val value: Long) : Number(), Comparable { - @ExcludedFromCodegen - companion object { + public companion object { /** * A constant holding the minimum value an instance of Long can have. */ @@ -1104,7 +1163,7 @@ public class Long private constructor() : Number(), Comparable { this + other.toLong() /** Adds the other value to this value. */ - @WasmInstruction(WasmInstruction.I64_ADD) + @WasmOp(WasmOp.I64_ADD) public operator fun plus(other: Long): Long = implementedAsIntrinsic @@ -1129,7 +1188,7 @@ public class Long private constructor() : Number(), Comparable { this - other.toLong() /** Subtracts the other value from this value. */ - @WasmInstruction(WasmInstruction.I64_SUB) + @WasmOp(WasmOp.I64_SUB) public operator fun minus(other: Long): Long = implementedAsIntrinsic @@ -1154,7 +1213,7 @@ public class Long private constructor() : Number(), Comparable { this * other.toLong() /** Multiplies this value by the other value. */ - @WasmInstruction(WasmInstruction.I64_MUL) + @WasmOp(WasmOp.I64_MUL) public operator fun times(other: Long): Long = implementedAsIntrinsic @@ -1179,7 +1238,7 @@ public class Long private constructor() : Number(), Comparable { this / other.toLong() /** Divides this value by the other value. */ - @WasmInstruction(WasmInstruction.I64_DIV_S) + @WasmOp(WasmOp.I64_DIV_S) public operator fun div(other: Long): Long = implementedAsIntrinsic @@ -1204,7 +1263,7 @@ public class Long private constructor() : Number(), Comparable { this % other.toLong() /** Calculates the remainder of dividing this value by the other value. */ - @WasmInstruction(WasmInstruction.I64_REM_S) + @WasmOp(WasmOp.I64_REM_S) public operator fun rem(other: Long): Long = implementedAsIntrinsic @@ -1231,22 +1290,25 @@ public class Long private constructor() : Number(), Comparable { /** Returns the negative of this value. */ public inline operator fun unaryMinus(): Long = 0L - this -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Byte): LongRange { -// return LongRange(this, other.toLong()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Short): LongRange { -// return LongRange(this, other.toLong()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Int): LongRange { -// return LongRange(this, other.toLong()) -// } -// /** Creates a range from this value to the specified [other] value. */ -// public operator fun rangeTo(other: Long): LongRange { -// return LongRange(this, other.toLong()) -// } + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Byte): LongRange { + return LongRange(this, other.toLong()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Short): LongRange { + return LongRange(this, other.toLong()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Int): LongRange { + return LongRange(this, other.toLong()) + } + + /** Creates a range from this value to the specified [other] value. */ + public operator fun rangeTo(other: Long): LongRange { + return LongRange(this, other.toLong()) + } /** * Shifts this value left by the [bitCount] number of bits. @@ -1276,17 +1338,17 @@ public class Long private constructor() : Number(), Comparable { wasm_i64_shr_u(this, bitCount.toLong()) /** Performs a bitwise AND operation between the two values. */ - @WasmInstruction(WasmInstruction.I64_AND) + @WasmOp(WasmOp.I64_AND) public infix fun and(other: Long): Long = implementedAsIntrinsic /** Performs a bitwise OR operation between the two values. */ - @WasmInstruction(WasmInstruction.I64_OR) + @WasmOp(WasmOp.I64_OR) public infix fun or(other: Long): Long = implementedAsIntrinsic /** Performs a bitwise XOR operation between the two values. */ - @WasmInstruction(WasmInstruction.I64_XOR) + @WasmOp(WasmOp.I64_XOR) public infix fun xor(other: Long): Long = implementedAsIntrinsic @@ -1335,9 +1397,8 @@ public class Long private constructor() : Number(), Comparable { * * The resulting `Int` value is represented by the least significant 32 bits of this `Long` value. */ - @WasmInstruction(WasmInstruction.I32_WRAP_I64) public override fun toInt(): Int = - implementedAsIntrinsic + wasm_i32_wrap_i64(this) /** Returns this value. */ public override inline fun toLong(): Long = @@ -1350,9 +1411,8 @@ public class Long private constructor() : Number(), Comparable { * In case when this `Long` value is exactly between two `Float`s, * the one with zero at least significant bit of mantissa is selected. */ - @WasmInstruction(WasmInstruction.F32_CONVERT_I64_S) public override fun toFloat(): Float = - implementedAsIntrinsic + wasm_f32_convert_i64_s(this) /** * Converts this [Long] value to [Double]. @@ -1361,19 +1421,18 @@ public class Long private constructor() : Number(), Comparable { * In case when this `Long` value is exactly between two `Double`s, * the one with zero at least significant bit of mantissa is selected. */ - @WasmInstruction(WasmInstruction.F64_CONVERT_I64_S) public override fun toDouble(): Double = - implementedAsIntrinsic + wasm_f64_convert_i64_s(this) public inline fun equals(other: Long): Boolean = - wasm_i64_eq(this, other).reinterpretAsBoolean() + wasm_i64_eq(this, other) - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Long && wasm_i64_eq(this, other).reinterpretAsBoolean() + public override fun equals(other: Any?): Boolean = + other is Long && wasm_i64_eq(this, other) - // TODO: Implement Long.toString() - // public override fun toString(): String + // TODO: Implement proper Long.toString + public override fun toString(): String = + toDouble().toString() public override fun hashCode(): Int = ((this ushr 32) xor this).toInt() @@ -1382,10 +1441,10 @@ public class Long private constructor() : Number(), Comparable { /** * Represents a single-precision 32-bit IEEE 754 floating point number. */ -public class Float private constructor() : Number(), Comparable { +@WasmPrimitive +public class Float private constructor(public val value: Float) : Number(), Comparable { - @ExcludedFromCodegen - companion object { + public companion object { /** * A constant holding the smallest *positive* nonzero value of Float. */ @@ -1411,7 +1470,9 @@ public class Float private constructor() : Number(), Comparable { /** * A constant holding the "not a number" value of Float. */ - public val NaN: Float = wasm_f32_const_nan() + public val NaN: Float + get() = + wasm_float_nan() } /** @@ -1483,7 +1544,7 @@ public class Float private constructor() : Number(), Comparable { this + other.toFloat() /** Adds the other value to this value. */ - @WasmInstruction(WasmInstruction.F32_ADD) + @WasmOp(WasmOp.F32_ADD) public operator fun plus(other: Float): Float = implementedAsIntrinsic @@ -1508,7 +1569,7 @@ public class Float private constructor() : Number(), Comparable { this - other.toFloat() /** Subtracts the other value from this value. */ - @WasmInstruction(WasmInstruction.F32_SUB) + @WasmOp(WasmOp.F32_SUB) public operator fun minus(other: Float): Float = implementedAsIntrinsic @@ -1533,7 +1594,7 @@ public class Float private constructor() : Number(), Comparable { this * other.toFloat() /** Multiplies this value by the other value. */ - @WasmInstruction(WasmInstruction.F32_MUL) + @WasmOp(WasmOp.F32_MUL) public operator fun times(other: Float): Float = implementedAsIntrinsic @@ -1558,7 +1619,7 @@ public class Float private constructor() : Number(), Comparable { this / other.toFloat() /** Divides this value by the other value. */ - @WasmInstruction(WasmInstruction.F32_DIV) + @WasmOp(WasmOp.F32_DIV) public operator fun div(other: Float): Float = implementedAsIntrinsic @@ -1602,7 +1663,7 @@ public class Float private constructor() : Number(), Comparable { public inline operator fun unaryPlus(): Float = this /** Returns the negative of this value. */ - @WasmInstruction(WasmInstruction.F32_NEG) + @WasmOp(WasmOp.F32_NEG) public operator fun unaryMinus(): Float = implementedAsIntrinsic @@ -1634,10 +1695,8 @@ public class Float private constructor() : Number(), Comparable { * Returns zero if this `Float` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`, * [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`. */ - // TODO: Implement Float.toInt() public override fun toInt(): Int { - wasm_unreachable() - return 0 + return wasm_i32_trunc_sat_f32_s(this) } /** @@ -1647,10 +1706,8 @@ public class Float private constructor() : Number(), Comparable { * Returns zero if this `Float` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`, * [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`. */ - // TODO: Implement Float.toLong() public override fun toLong(): Long { - wasm_unreachable() - return 0 + return wasm_i64_trunc_sat_f32_s(this) } /** Returns this value. */ @@ -1662,35 +1719,37 @@ public class Float private constructor() : Number(), Comparable { * * The resulting `Double` value represents the same numerical value as this `Float`. */ - @WasmInstruction(WasmInstruction.F64_PROMOTE_F32) public override fun toDouble(): Double = - implementedAsIntrinsic + wasm_f64_promote_f32(this) public inline fun equals(other: Float): Boolean = bits() == other.bits() - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Float && this.equals(other) + public override fun equals(other: Any?): Boolean = + other is Float && this.equals(other) - // TODO: Implement Float.toString() - // public override fun toString(): String + public override fun toString(): String = + floatToStringImpl(this) public override inline fun hashCode(): Int = bits() @PublishedApi - @WasmInstruction(WasmInstruction.I32_REINTERPRET_F32) + @WasmOp(WasmOp.I32_REINTERPRET_F32) internal fun bits(): Int = implementedAsIntrinsic } +@WasmImport("runtime", "coerceToString") +private fun floatToStringImpl(x: Float): String = + implementedAsIntrinsic + /** * Represents a double-precision 64-bit IEEE 754 floating point number. */ -public class Double private constructor() : Number(), Comparable { +@WasmPrimitive +public class Double private constructor(public val value: Double) : Number(), Comparable { - @ExcludedFromCodegen - companion object { + public companion object { /** * A constant holding the smallest *positive* nonzero value of Double. */ @@ -1716,7 +1775,10 @@ public class Double private constructor() : Number(), Comparable { /** * A constant holding the "not a number" value of Double. */ - public val NaN: Double = wasm_f64_const_nan() + public val NaN: Double + get() = + wasm_double_nan() + } /** @@ -1792,7 +1854,7 @@ public class Double private constructor() : Number(), Comparable { this + other.toDouble() /** Adds the other value to this value. */ - @WasmInstruction(WasmInstruction.F64_ADD) + @WasmOp(WasmOp.F64_ADD) public operator fun plus(other: Double): Double = implementedAsIntrinsic @@ -1817,7 +1879,7 @@ public class Double private constructor() : Number(), Comparable { this - other.toDouble() /** Subtracts the other value from this value. */ - @WasmInstruction(WasmInstruction.F64_SUB) + @WasmOp(WasmOp.F64_SUB) public operator fun minus(other: Double): Double = implementedAsIntrinsic @@ -1842,7 +1904,7 @@ public class Double private constructor() : Number(), Comparable { this * other.toDouble() /** Multiplies this value by the other value. */ - @WasmInstruction(WasmInstruction.F64_MUL) + @WasmOp(WasmOp.F64_MUL) public operator fun times(other: Double): Double = implementedAsIntrinsic @@ -1867,7 +1929,7 @@ public class Double private constructor() : Number(), Comparable { this / other.toDouble() /** Divides this value by the other value. */ - @WasmInstruction(WasmInstruction.F64_DIV) + @WasmOp(WasmOp.F64_DIV) public operator fun div(other: Double): Double = implementedAsIntrinsic @@ -1908,7 +1970,7 @@ public class Double private constructor() : Number(), Comparable { this /** Returns the negative of this value. */ - @WasmInstruction(WasmInstruction.F64_NEG) + @WasmOp(WasmOp.F64_NEG) public operator fun unaryMinus(): Double = implementedAsIntrinsic @@ -1940,10 +2002,8 @@ public class Double private constructor() : Number(), Comparable { * Returns zero if this `Double` value is `NaN`, [Int.MIN_VALUE] if it's less than `Int.MIN_VALUE`, * [Int.MAX_VALUE] if it's bigger than `Int.MAX_VALUE`. */ - // TODO: Implement Double.toInt() public override fun toInt(): Int { - wasm_unreachable() - return 0 + return wasm_i32_trunc_sat_f64_s(this) } /** @@ -1953,10 +2013,8 @@ public class Double private constructor() : Number(), Comparable { * Returns zero if this `Double` value is `NaN`, [Long.MIN_VALUE] if it's less than `Long.MIN_VALUE`, * [Long.MAX_VALUE] if it's bigger than `Long.MAX_VALUE`. */ - // TODO: Implement Double.toLong() public override fun toLong(): Long { - wasm_unreachable() - return 0 + return wasm_i64_trunc_sat_f64_s(this) } /** @@ -1966,9 +2024,8 @@ public class Double private constructor() : Number(), Comparable { * In case when this `Double` value is exactly between two `Float`s, * the one with zero at least significant bit of mantissa is selected. */ - @WasmInstruction(WasmInstruction.F32_DEMOTE_F64) public override fun toFloat(): Float = - implementedAsIntrinsic + wasm_f32_demote_f64(this) /** Returns this value. */ public override inline fun toDouble(): Double = @@ -1977,17 +2034,20 @@ public class Double private constructor() : Number(), Comparable { public inline fun equals(other: Double): Boolean = this.bits() == other.bits() - // TODO: Support Any? and type operators -// public override fun equals(other: Any?): Boolean = -// other is Double && this.bits() == other.bits() + public override fun equals(other: Any?): Boolean = + other is Double && this.bits() == other.bits() - // TODO: Implement Double.toString() - // public override fun toString(): String + public override fun toString(): String = + doubleToStringImpl(this) public override inline fun hashCode(): Int = bits().hashCode() @PublishedApi - @WasmInstruction(WasmInstruction.I64_REINTERPRET_F64) + @WasmOp(WasmOp.I64_REINTERPRET_F64) internal fun bits(): Long = implementedAsIntrinsic } + +@WasmImport("runtime", "coerceToString") +private fun doubleToStringImpl(x: Double): String = + implementedAsIntrinsic diff --git a/libraries/stdlib/wasm/builtins/kotlin/String.kt b/libraries/stdlib/wasm/builtins/kotlin/String.kt new file mode 100644 index 00000000000..1871d498ad3 --- /dev/null +++ b/libraries/stdlib/wasm/builtins/kotlin/String.kt @@ -0,0 +1,72 @@ +/* + * 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.wasm.internal.* + +/** + * The `String` class represents character strings. All string literals in Kotlin programs, such as `"abc"`, are + * implemented as instances of this class. + */ +@WasmPrimitive +public class String constructor(public val string: String) : Comparable, CharSequence { + public companion object; + + /** + * Returns a string obtained by concatenating this string with the string representation of the given [other] object. + */ + public operator fun plus(other: Any?): String = + stringPlusImpl(this, other.toString()) + + public override val length: Int + get() = stringLengthImpl(this) + + /** + * Returns the character of this string at the specified [index]. + * + * If the [index] is out of bounds of this string, throws an [IndexOutOfBoundsException] except in Kotlin/JS + * where the behavior is unspecified. + */ + public override fun get(index: Int): Char = + stringGetCharImpl(this, index) + + public override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = + stringSubSequenceImpl(this, startIndex, endIndex) + + public override fun compareTo(other: String): Int = + stringCompareToImpl(this, other) + + public override fun equals(other: Any?): Boolean { + if (other is String) + return this.compareTo(other) == 0 + return false + } + + public override fun toString(): String = this + + // TODO: Implement + public override fun hashCode(): Int = 10 +} + +@WasmImport("runtime", "String_plus") +private fun stringPlusImpl(it: String, other: String): String = + implementedAsIntrinsic + +@WasmImport("runtime", "String_getLength") +private fun stringLengthImpl(it: String): Int = + implementedAsIntrinsic + +@WasmImport("runtime", "String_getChar") +private fun stringGetCharImpl(it: String, index: Int): Char = + implementedAsIntrinsic + +@WasmImport("runtime", "String_compareTo") +private fun stringCompareToImpl(it: String, other: String): Int = + implementedAsIntrinsic + +@WasmImport("runtime", "String_subsequence") +private fun stringSubSequenceImpl(string: String, startIndex: Int, endIndex: Int): String = + implementedAsIntrinsic diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Annotation.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Annotation.kt deleted file mode 100644 index 8b640727b7e..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Annotation.kt +++ /dev/null @@ -1,13 +0,0 @@ -/* - * Copyright 2010-2018 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 - -/** - * Base interface implicitly implemented by all annotation interfaces. - * See [Kotlin language documentation](https://kotlinlang.org/docs/reference/annotations.html) for more information - * on annotations. - */ -public interface Annotation diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Arrays.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Arrays.kt deleted file mode 100644 index b8fd30c5892..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Arrays.kt +++ /dev/null @@ -1,313 +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. - */ - -// Auto-generated file. DO NOT EDIT! - -@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" -) - -package kotlin - -/** - * An array of bytes. When targeting the JVM, instances of this class are represented as `byte[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class ByteArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Byte) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Byte - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Byte): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): ByteIterator -} - -/** - * An array of chars. When targeting the JVM, instances of this class are represented as `char[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to null char (`\u0000'). - */ -public class CharArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Char) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Char - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Char): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): CharIterator -} - -/** - * An array of shorts. When targeting the JVM, instances of this class are represented as `short[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class ShortArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Short) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Short - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Short): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): ShortIterator -} - -/** - * An array of ints. When targeting the JVM, instances of this class are represented as `int[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class IntArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Int) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Int - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Int): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): IntIterator -} - -/** - * An array of longs. When targeting the JVM, instances of this class are represented as `long[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class LongArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Long) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Long - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Long): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): LongIterator -} - -/** - * An array of floats. When targeting the JVM, instances of this class are represented as `float[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class FloatArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Float) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Float - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Float): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): FloatIterator -} - -/** - * An array of doubles. When targeting the JVM, instances of this class are represented as `double[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to zero. - */ -public class DoubleArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Double) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Double - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Double): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): DoubleIterator -} - -/** - * An array of booleans. When targeting the JVM, instances of this class are represented as `boolean[]`. - * @constructor Creates a new array of the specified [size], with all elements initialized to `false`. - */ -public class BooleanArray(size: Int) { - /** - * Creates a new array of the specified [size], where each element is calculated by calling the specified - * [init] function. - * - * The function [init] is called for each array element sequentially starting from the first one. - * It should return the value for an array element given its index. - */ - public inline constructor(size: Int, init: (Int) -> Boolean) - - /** - * Returns the array element at the given [index]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun get(index: Int): Boolean - - /** - * Sets the element at the given [index] to the given [value]. This method can be called using the index operator. - * - * If the [index] is out of bounds of this array, throws an [IndexOutOfBoundsException] except in Kotlin/JS - * where the behavior is unspecified. - */ - public operator fun set(index: Int, value: Boolean): Unit - - /** Returns the number of elements in the array. */ - public val size: Int - - /** Creates an iterator over the elements of the array. */ - public operator fun iterator(): BooleanIterator -} - diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/CharSequence.kt b/libraries/stdlib/wasm/builtins/native/kotlin/CharSequence.kt deleted file mode 100644 index 335bc9bb63d..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/CharSequence.kt +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin - -/** - * Represents a readable sequence of [Char] values. - */ -public interface CharSequence { - /** - * Returns the length of this character sequence. - */ - public val length: Int - - /** - * Returns the character at the specified [index] in this character sequence. - * - * @throws [IndexOutOfBoundsException] if the [index] is out of bounds of this character sequence. - * - * Note that the [String] implementation of this interface in Kotlin/JS has unspecified behavior - * if the [index] is out of its bounds. - */ - public operator fun get(index: Int): Char - - /** - * Returns a new character sequence that is a subsequence of this character sequence, - * starting at the specified [startIndex] and ending right before the specified [endIndex]. - * - * @param startIndex the start index (inclusive). - * @param endIndex the end index (exclusive). - */ - public fun subSequence(startIndex: Int, endIndex: Int): CharSequence -} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Collections.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Collections.kt deleted file mode 100644 index caf6ab6212c..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Collections.kt +++ /dev/null @@ -1,438 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package kotlin.collections - -import kotlin.internal.PlatformDependent - -/** - * Classes that inherit from this interface can be represented as a sequence of elements that can - * be iterated over. - * @param T the type of element being iterated over. The iterator is covariant in its element type. - */ -public interface Iterable { - /** - * Returns an iterator over the elements of this object. - */ - public operator fun iterator(): Iterator -} - -/** - * Classes that inherit from this interface can be represented as a sequence of elements that can - * be iterated over and that supports removing elements during iteration. - * @param T the type of element being iterated over. The mutable iterator is invariant in its element type. - */ -public interface MutableIterable : Iterable { - /** - * Returns an iterator over the elements of this sequence that supports removing elements during iteration. - */ - override fun iterator(): MutableIterator -} - -/** - * A generic collection of elements. Methods in this interface support only read-only access to the collection; - * read/write access is supported through the [MutableCollection] interface. - * @param E the type of elements contained in the collection. The collection is covariant in its element type. - */ -public interface Collection : Iterable { - // Query Operations - /** - * Returns the size of the collection. - */ - public val size: Int - - /** - * Returns `true` if the collection is empty (contains no elements), `false` otherwise. - */ - public fun isEmpty(): Boolean - - /** - * Checks if the specified element is contained in this collection. - */ - public operator fun contains(element: @UnsafeVariance E): Boolean - - override fun iterator(): Iterator - - // Bulk Operations - /** - * Checks if all elements in the specified collection are contained in this collection. - */ - public fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean -} - -/** - * A generic collection of elements that supports adding and removing elements. - * - * @param E the type of elements contained in the collection. The mutable collection is invariant in its element type. - */ -public interface MutableCollection : Collection, MutableIterable { - // Query Operations - override fun iterator(): MutableIterator - - // Modification Operations - /** - * Adds the specified element to the collection. - * - * @return `true` if the element has been added, `false` if the collection does not support duplicates - * and the element is already contained in the collection. - */ - public fun add(element: E): Boolean - - /** - * Removes a single instance of the specified element from this - * collection, if it is present. - * - * @return `true` if the element has been successfully removed; `false` if it was not present in the collection. - */ - public fun remove(element: E): Boolean - - // Bulk Modification Operations - /** - * Adds all of the elements of the specified collection to this collection. - * - * @return `true` if any of the specified elements was added to the collection, `false` if the collection was not modified. - */ - public fun addAll(elements: Collection): Boolean - - /** - * Removes all of this collection's elements that are also contained in the specified collection. - * - * @return `true` if any of the specified elements was removed from the collection, `false` if the collection was not modified. - */ - public fun removeAll(elements: Collection): Boolean - - /** - * Retains only the elements in this collection that are contained in the specified collection. - * - * @return `true` if any element was removed from the collection, `false` if the collection was not modified. - */ - public fun retainAll(elements: Collection): Boolean - - /** - * Removes all elements from this collection. - */ - public fun clear(): Unit -} - -/** - * A generic ordered collection of elements. Methods in this interface support only read-only access to the list; - * read/write access is supported through the [MutableList] interface. - * @param E the type of elements contained in the list. The list is covariant in its element type. - */ -public interface List : Collection { - // Query Operations - - override val size: Int - override fun isEmpty(): Boolean - override fun contains(element: @UnsafeVariance E): Boolean - override fun iterator(): Iterator - - // Bulk Operations - override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean - - // Positional Access Operations - /** - * Returns the element at the specified index in the list. - */ - public operator fun get(index: Int): E - - // Search Operations - /** - * Returns the index of the first occurrence of the specified element in the list, or -1 if the specified - * element is not contained in the list. - */ - public fun indexOf(element: @UnsafeVariance E): Int - - /** - * Returns the index of the last occurrence of the specified element in the list, or -1 if the specified - * element is not contained in the list. - */ - public fun lastIndexOf(element: @UnsafeVariance E): Int - - // List Iterators - /** - * Returns a list iterator over the elements in this list (in proper sequence). - */ - public fun listIterator(): ListIterator - - /** - * Returns a list iterator over the elements in this list (in proper sequence), starting at the specified [index]. - */ - public fun listIterator(index: Int): ListIterator - - // View - /** - * Returns a view of the portion of this list between the specified [fromIndex] (inclusive) and [toIndex] (exclusive). - * The returned list is backed by this list, so non-structural changes in the returned list are reflected in this list, and vice-versa. - * - * Structural changes in the base list make the behavior of the view undefined. - */ - public fun subList(fromIndex: Int, toIndex: Int): List -} - -/** - * A generic ordered collection of elements that supports adding and removing elements. - * @param E the type of elements contained in the list. The mutable list is invariant in its element type. - */ -public interface MutableList : List, MutableCollection { - // Modification Operations - /** - * Adds the specified element to the end of this list. - * - * @return `true` because the list is always modified as the result of this operation. - */ - override fun add(element: E): Boolean - - override fun remove(element: E): Boolean - - // Bulk Modification Operations - /** - * Adds all of the elements of the specified collection to the end of this list. - * - * The elements are appended in the order they appear in the [elements] collection. - * - * @return `true` if the list was changed as the result of the operation. - */ - override fun addAll(elements: Collection): Boolean - - /** - * Inserts all of the elements of the specified collection [elements] into this list at the specified [index]. - * - * @return `true` if the list was changed as the result of the operation. - */ - public fun addAll(index: Int, elements: Collection): Boolean - - override fun removeAll(elements: Collection): Boolean - override fun retainAll(elements: Collection): Boolean - override fun clear(): Unit - - // Positional Access Operations - /** - * Replaces the element at the specified position in this list with the specified element. - * - * @return the element previously at the specified position. - */ - public operator fun set(index: Int, element: E): E - - /** - * Inserts an element into the list at the specified [index]. - */ - public fun add(index: Int, element: E): Unit - - /** - * Removes an element at the specified [index] from the list. - * - * @return the element that has been removed. - */ - public fun removeAt(index: Int): E - - // List Iterators - override fun listIterator(): MutableListIterator - - override fun listIterator(index: Int): MutableListIterator - - // View - override fun subList(fromIndex: Int, toIndex: Int): MutableList -} - -/** - * A generic unordered collection of elements that does not support duplicate elements. - * Methods in this interface support only read-only access to the set; - * read/write access is supported through the [MutableSet] interface. - * @param E the type of elements contained in the set. The set is covariant in its element type. - */ -public interface Set : Collection { - // Query Operations - - override val size: Int - override fun isEmpty(): Boolean - override fun contains(element: @UnsafeVariance E): Boolean - override fun iterator(): Iterator - - // Bulk Operations - override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean -} - -/** - * A generic unordered collection of elements that does not support duplicate elements, and supports - * adding and removing elements. - * @param E the type of elements contained in the set. The mutable set is invariant in its element type. - */ -public interface MutableSet : Set, MutableCollection { - // Query Operations - override fun iterator(): MutableIterator - - // Modification Operations - - /** - * Adds the specified element to the set. - * - * @return `true` if the element has been added, `false` if the element is already contained in the set. - */ - override fun add(element: E): Boolean - - override fun remove(element: E): Boolean - - // Bulk Modification Operations - - override fun addAll(elements: Collection): Boolean - override fun removeAll(elements: Collection): Boolean - override fun retainAll(elements: Collection): Boolean - override fun clear(): Unit -} - -/** - * A collection that holds pairs of objects (keys and values) and supports efficiently retrieving - * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. - * Methods in this interface support only read-only access to the map; read-write access is supported through - * the [MutableMap] interface. - * @param K the type of map keys. The map is invariant in its key type, as it - * can accept key as a parameter (of [containsKey] for example) and return it in [keys] set. - * @param V the type of map values. The map is covariant in its value type. - */ -public interface Map { - // Query Operations - /** - * Returns the number of key/value pairs in the map. - */ - public val size: Int - - /** - * Returns `true` if the map is empty (contains no elements), `false` otherwise. - */ - public fun isEmpty(): Boolean - - /** - * Returns `true` if the map contains the specified [key]. - */ - public fun containsKey(key: K): Boolean - - /** - * Returns `true` if the map maps one or more keys to the specified [value]. - */ - public fun containsValue(value: @UnsafeVariance V): Boolean - - /** - * Returns the value corresponding to the given [key], or `null` if such a key is not present in the map. - */ - public operator fun get(key: K): V? - - /** - * Returns the value corresponding to the given [key], or [defaultValue] if such a key is not present in the map. - * - * @since JDK 1.8 - */ - @SinceKotlin("1.1") - @PlatformDependent - public fun getOrDefault(key: K, defaultValue: @UnsafeVariance V): V { - // See default implementation in JDK sources - return null as V - } - - // Views - /** - * Returns a read-only [Set] of all keys in this map. - */ - public val keys: Set - - /** - * Returns a read-only [Collection] of all values in this map. Note that this collection may contain duplicate values. - */ - public val values: Collection - - /** - * Returns a read-only [Set] of all key/value pairs in this map. - */ - public val entries: Set> - - /** - * Represents a key/value pair held by a [Map]. - */ - public interface Entry { - /** - * Returns the key of this key/value pair. - */ - public val key: K - - /** - * Returns the value of this key/value pair. - */ - public val value: V - } -} - -/** - * A modifiable collection that holds pairs of objects (keys and values) and supports efficiently retrieving - * the value corresponding to each key. Map keys are unique; the map holds only one value for each key. - * @param K the type of map keys. The map is invariant in its key type. - * @param V the type of map values. The mutable map is invariant in its value type. - */ -public interface MutableMap : Map { - // Modification Operations - /** - * Associates the specified [value] with the specified [key] in the map. - * - * @return the previous value associated with the key, or `null` if the key was not present in the map. - */ - public fun put(key: K, value: V): V? - - /** - * Removes the specified key and its corresponding value from this map. - * - * @return the previous value associated with the key, or `null` if the key was not present in the map. - */ - public fun remove(key: K): V? - - /** - * Removes the entry for the specified key only if it is mapped to the specified value. - * - * @return true if entry was removed - */ - @SinceKotlin("1.1") - @PlatformDependent - public fun remove(key: K, value: V): Boolean { - // See default implementation in JDK sources - return true - } - - // Bulk Modification Operations - /** - * Updates this map with key/value pairs from the specified map [from]. - */ - public fun putAll(from: Map): Unit - - /** - * Removes all elements from this map. - */ - public fun clear(): Unit - - // Views - /** - * Returns a [MutableSet] of all keys in this map. - */ - override val keys: MutableSet - - /** - * Returns a [MutableCollection] of all values in this map. Note that this collection may contain duplicate values. - */ - override val values: MutableCollection - - /** - * Returns a [MutableSet] of all key/value pairs in this map. - */ - override val entries: MutableSet> - - /** - * Represents a key/value pair held by a [MutableMap]. - */ - public interface MutableEntry : Map.Entry { - /** - * Changes the value associated with the key of this entry. - * - * @return the previous value corresponding to the key. - */ - public fun setValue(newValue: V): V - } -} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Comparable.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Comparable.kt deleted file mode 100644 index bcc2bf337c9..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Comparable.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin - -/** - * Classes which inherit from this interface have a defined total ordering between their instances. - */ -public interface Comparable { - /** - * Compares this object with the specified object for order. Returns zero if this object is equal - * to the specified [other] object, a negative number if it's less than [other], or a positive number - * if it's greater than [other]. - */ - public operator fun compareTo(other: T): Int -} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Enum.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Enum.kt deleted file mode 100644 index 90a4931ea0a..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Enum.kt +++ /dev/null @@ -1,58 +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. - */ - -@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" -) - -package kotlin - -/** - * The common base class of all enum classes. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/enum-classes.html) for more - * information on enum classes. - */ -public abstract class Enum>(name: String, ordinal: Int): Comparable { - companion object {} - - /** - * Returns the name of this enum constant, exactly as declared in its enum declaration. - */ - public final val name: String - - /** - * Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant - * is assigned an ordinal of zero). - */ - public final val ordinal: Int - - public override final fun compareTo(other: E): Int - - /** - * Throws an exception since enum constants cannot be cloned. - * This method prevents enum classes from inheriting from `Cloneable`. - */ - protected final fun clone(): Any - - public override final fun equals(other: Any?): Boolean - public override final fun hashCode(): Int - public override fun toString(): String - - /** - * Returns an array containing the constants of this enum type, in the order they're declared. - * This method may be used to iterate over the constants. - * @values - */ - - /** - * Returns the enum constant of this type with the specified name. The string must match exactly an identifier used to declare an enum constant in this type. (Extraneous whitespace characters are not permitted.) - * @throws IllegalArgumentException if this enum type has no constant with the specified name - * @valueOf - */ -} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Iterator.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Iterator.kt deleted file mode 100644 index d854a6a66f9..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Iterator.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.collections - -/** - * An iterator over a collection or another entity that can be represented as a sequence of elements. - * Allows to sequentially access the elements. - */ -public interface Iterator { - /** - * Returns the next element in the iteration. - */ - public operator fun next(): T - - /** - * Returns `true` if the iteration has more elements. - */ - public operator fun hasNext(): Boolean -} - -/** - * An iterator over a mutable collection. Provides the ability to remove elements while iterating. - * @see MutableCollection.iterator - */ -public interface MutableIterator : Iterator { - /** - * Removes from the underlying collection the last element returned by this iterator. - */ - public fun remove(): Unit -} - -/** - * An iterator over a collection that supports indexed access. - * @see List.listIterator - */ -public interface ListIterator : Iterator { - // Query Operations - override fun next(): T - override fun hasNext(): Boolean - - /** - * Returns `true` if there are elements in the iteration before the current element. - */ - public fun hasPrevious(): Boolean - - /** - * Returns the previous element in the iteration and moves the cursor position backwards. - */ - public fun previous(): T - - /** - * Returns the index of the element that would be returned by a subsequent call to [next]. - */ - public fun nextIndex(): Int - - /** - * Returns the index of the element that would be returned by a subsequent call to [previous]. - */ - public fun previousIndex(): Int -} - -/** - * An iterator over a mutable collection that supports indexed access. Provides the ability - * to add, modify and remove elements while iterating. - */ -public interface MutableListIterator : ListIterator, MutableIterator { - // Query Operations - override fun next(): T - override fun hasNext(): Boolean - - // Modification Operations - override fun remove(): Unit - - /** - * Replaces the last element returned by [next] or [previous] with the specified element [element]. - */ - public fun set(element: T): Unit - - /** - * Adds the specified element [element] into the underlying collection immediately before the element that would be - * returned by [next], if any, and after the element that would be returned by [previous], if any. - * (If the collection contains no elements, the new element becomes the sole element in the collection.) - * The new element is inserted before the implicit cursor: a subsequent call to [next] would be unaffected, - * and a subsequent call to [previous] would return the new element. (This call increases by one the value \ - * that would be returned by a call to [nextIndex] or [previousIndex].) - */ - public fun add(element: T): Unit -} diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Number.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Number.kt deleted file mode 100644 index 49da583bf4b..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Number.kt +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin - -/** - * Superclass for all platform classes representing numeric values. - */ -public abstract class Number { - /** - * Returns the value of this number as a [Double], which may involve rounding. - */ - public abstract fun toDouble(): Double - - /** - * Returns the value of this number as a [Float], which may involve rounding. - */ - public abstract fun toFloat(): Float - - /** - * Returns the value of this number as a [Long], which may involve rounding or truncation. - */ - public abstract fun toLong(): Long - - /** - * Returns the value of this number as an [Int], which may involve rounding or truncation. - */ - public abstract fun toInt(): Int - - /** - * Returns the [Char] with the numeric value equal to this number, truncated to 16 bits if appropriate. - */ - public abstract fun toChar(): Char - - /** - * Returns the value of this number as a [Short], which may involve rounding or truncation. - */ - public abstract fun toShort(): Short - - /** - * Returns the value of this number as a [Byte], which may involve rounding or truncation. - */ - public abstract fun toByte(): Byte -} - diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/String.kt b/libraries/stdlib/wasm/builtins/native/kotlin/String.kt deleted file mode 100644 index 198d09abae4..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/String.kt +++ /dev/null @@ -1,58 +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. - */ - -@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" -) - -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, 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]. - * - * 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 -} \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/native/kotlin/Throwable.kt b/libraries/stdlib/wasm/builtins/native/kotlin/Throwable.kt deleted file mode 100644 index b6328940998..00000000000 --- a/libraries/stdlib/wasm/builtins/native/kotlin/Throwable.kt +++ /dev/null @@ -1,28 +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. - */ - -@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" -) - -package kotlin - -/** - * The base class for all errors and exceptions. Only instances of this class can be thrown or caught. - * - * @param message the detail message string. - * @param cause the cause of this throwable. - */ -public open class Throwable(open val message: String?, open val cause: Throwable?) { - constructor(message: String?) : this(message, null) - - constructor(cause: Throwable?) : this(cause?.toString(), cause) - - constructor() : this(null, null) -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/Annotations.kt b/libraries/stdlib/wasm/builtins/src/kotlin/Annotations.kt deleted file mode 100644 index 0af5712da18..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/Annotations.kt +++ /dev/null @@ -1,152 +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.AnnotationRetention.BINARY -import kotlin.annotation.AnnotationRetention.SOURCE -import kotlin.annotation.AnnotationTarget.* - -/** - * Marks the annotated declaration as deprecated. - * - * A deprecated API element is not recommended to use, typically because it's being phased out or a better alternative exists. - * - * To help removing deprecated API gradually, the property [level] could be used. - * Usually a gradual phase-out goes through the "warning", then "error", then "hidden" or "removed" stages: - * - First and by default, [DeprecationLevel.WARNING] is used to notify API consumers, but not to break their compilation or runtime usages. - * - Then, some time later the deprecation level is raised to [DeprecationLevel.ERROR], so that no new Kotlin code can be compiled - * using the deprecated API. - * - Finally, the API is either removed entirely, or hidden ([DeprecationLevel.HIDDEN]) from code, - * so its usages look like unresolved references, while the API remains in the compiled code - * preserving binary compatibility with previously compiled code. - * - * @property message The message explaining the deprecation and recommending an alternative API to use. - * @property replaceWith If present, specifies a code fragment which should be used as a replacement for - * the deprecated API usage. - * @property level Specifies how the deprecated element usages are reported in code. - * See the [DeprecationLevel] enum for the possible values. - */ -@Target(CLASS, FUNCTION, PROPERTY, ANNOTATION_CLASS, CONSTRUCTOR, PROPERTY_SETTER, PROPERTY_GETTER, TYPEALIAS) -@MustBeDocumented -public annotation class Deprecated( - val message: String, - val replaceWith: ReplaceWith = ReplaceWith(""), - val level: DeprecationLevel = DeprecationLevel.WARNING -) - -/** - * Specifies a code fragment that can be used to replace a deprecated function, property or class. Tools such - * as IDEs can automatically apply the replacements specified through this annotation. - * - * @property expression the replacement expression. The replacement expression is interpreted in the context - * of the symbol being used, and can reference members of enclosing classes etc. - * For function calls, the replacement expression may contain argument names of the deprecated function, - * which will be substituted with actual parameters used in the call being updated. The imports used in the file - * containing the deprecated function or property are NOT accessible; if the replacement expression refers - * on any of those imports, they need to be specified explicitly in the [imports] parameter. - * @property imports the qualified names that need to be imported in order for the references in the - * replacement expression to be resolved correctly. - */ -@Target() -@Retention(BINARY) -@MustBeDocumented -public annotation class ReplaceWith(val expression: String, vararg val imports: String) - -/** - * Possible levels of a deprecation. The level specifies how the deprecated element usages are reported in code. - * - * @see Deprecated - */ -public enum class DeprecationLevel { - /** Usage of the deprecated element will be reported as a warning. */ - WARNING, - /** Usage of the deprecated element will be reported as an error. */ - ERROR, - /** Deprecated element will not be accessible from code. */ - HIDDEN -} - -/** - * Signifies that the annotated functional type represents an extension function. - */ -@Target(TYPE) -@MustBeDocumented -public annotation class ExtensionFunctionType - -/** - * Annotates type arguments of functional type and holds corresponding parameter name specified by the user in type declaration (if any). - */ -@Target(TYPE) -@MustBeDocumented -@SinceKotlin("1.1") -public annotation class ParameterName(val name: String) - -/** - * Suppresses the given compilation warnings in the annotated element. - * @property names names of the compiler diagnostics to suppress. - */ -@Target(CLASS, ANNOTATION_CLASS, PROPERTY, FIELD, LOCAL_VARIABLE, VALUE_PARAMETER, - CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPE, EXPRESSION, FILE, TYPEALIAS) -@Retention(SOURCE) -public annotation class Suppress(vararg val names: String) - -/** - * Suppresses errors about variance conflict - */ -@Target(TYPE) -@Retention(SOURCE) -@MustBeDocumented -public annotation class UnsafeVariance - -/** - * Specifies the first version of Kotlin where a declaration has appeared. - * Using the declaration and specifying an older API version (via the `-api-version` command line option) will result in an error. - * - * @property version the version in the following formats: `.` or `..`, where major, minor and patch - * are non-negative integer numbers without leading zeros. - */ -@Target(CLASS, PROPERTY, FIELD, CONSTRUCTOR, FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER, TYPEALIAS) -@Retention(AnnotationRetention.BINARY) -@MustBeDocumented -public annotation class SinceKotlin(val version: String) - -/** - * When applied to annotation class X specifies that X defines a DSL language - * - * The general rule: - * - an implicit receiver may *belong to a DSL @X* if marked with a corresponding DSL marker annotation - * - two implicit receivers of the same DSL are not accessible in the same scope - * - the closest one wins - * - other available receivers are resolved as usual, but if the resulting resolved call binds to such a receiver, it's a compilation error - * - * Marking rules: an implicit receiver is considered marked with @Ann if - * - its type is marked, or - * - its type's classifier is marked - * - or any of its superclasses/superinterfaces - */ -@Target(ANNOTATION_CLASS) -@Retention(BINARY) -@MustBeDocumented -@SinceKotlin("1.1") -public annotation class DslMarker - - -/** - * When applied to a class or a member with internal visibility allows to use it from public inline functions and - * makes it effectively public. - * - * Public inline functions cannot use non-public API, since if they are inlined, those non-public API references - * would violate access restrictions at a call site (https://kotlinlang.org/docs/reference/inline-functions.html#public-inline-restrictions). - * - * To overcome this restriction an `internal` declaration can be annotated with the `@PublishedApi` annotation: - * - this allows to call that declaration from public inline functions; - * - the declaration becomes effectively public, and this should be considered with respect to binary compatibility maintaining. - */ -@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY) -@Retention(AnnotationRetention.BINARY) -@MustBeDocumented -@SinceKotlin("1.1") -public annotation class PublishedApi \ No newline at end of file diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/Function.kt b/libraries/stdlib/wasm/builtins/src/kotlin/Function.kt deleted file mode 100644 index 660d32a454d..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/Function.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin - -/** - * Represents a value of a functional type, such as a lambda, an anonymous function or a function reference. - * - * @param R return type of the function. - */ -public interface Function diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/Iterators.kt b/libraries/stdlib/wasm/builtins/src/kotlin/Iterators.kt deleted file mode 100644 index 1ee3ad3c928..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/Iterators.kt +++ /dev/null @@ -1,73 +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. - */ - -// Auto-generated file. DO NOT EDIT! - -package kotlin.collections - -/** An iterator over a sequence of values of type `Byte`. */ -public abstract class ByteIterator : Iterator { - override final fun next() = nextByte() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextByte(): Byte -} - -/** An iterator over a sequence of values of type `Char`. */ -public abstract class CharIterator : Iterator { - override final fun next() = nextChar() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextChar(): Char -} - -/** An iterator over a sequence of values of type `Short`. */ -public abstract class ShortIterator : Iterator { - override final fun next() = nextShort() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextShort(): Short -} - -/** An iterator over a sequence of values of type `Int`. */ -public abstract class IntIterator : Iterator { - override final fun next() = nextInt() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextInt(): Int -} - -/** An iterator over a sequence of values of type `Long`. */ -public abstract class LongIterator : Iterator { - override final fun next() = nextLong() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextLong(): Long -} - -/** An iterator over a sequence of values of type `Float`. */ -public abstract class FloatIterator : Iterator { - override final fun next() = nextFloat() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextFloat(): Float -} - -/** An iterator over a sequence of values of type `Double`. */ -public abstract class DoubleIterator : Iterator { - override final fun next() = nextDouble() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextDouble(): Double -} - -/** An iterator over a sequence of values of type `Boolean`. */ -public abstract class BooleanIterator : Iterator { - override final fun next() = nextBoolean() - - /** Returns the next value in the sequence without boxing. */ - public abstract fun nextBoolean(): Boolean -} - diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/Unit.kt b/libraries/stdlib/wasm/builtins/src/kotlin/Unit.kt deleted file mode 100644 index 4835929d904..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/Unit.kt +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin - -/** - * The type with only one value: the `Unit` object. This type corresponds to the `void` type in Java. - */ -public object Unit { - override fun toString() = "kotlin.Unit" -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/annotation/Annotations.kt b/libraries/stdlib/wasm/builtins/src/kotlin/annotation/Annotations.kt deleted file mode 100644 index 119dbfa55d6..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/annotation/Annotations.kt +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.annotation - -import kotlin.annotation.AnnotationTarget.* - -/** - * Contains the list of code elements which are the possible annotation targets - */ -public enum class AnnotationTarget { - /** Class, interface or object, annotation class is also included */ - CLASS, - /** Annotation class only */ - ANNOTATION_CLASS, - /** Generic type parameter (unsupported yet) */ - TYPE_PARAMETER, - /** Property */ - PROPERTY, - /** Field, including property's backing field */ - FIELD, - /** Local variable */ - LOCAL_VARIABLE, - /** Value parameter of a function or a constructor */ - VALUE_PARAMETER, - /** Constructor only (primary or secondary) */ - CONSTRUCTOR, - /** Function (constructors are not included) */ - FUNCTION, - /** Property getter only */ - PROPERTY_GETTER, - /** Property setter only */ - PROPERTY_SETTER, - /** Type usage */ - TYPE, - /** Any expression */ - EXPRESSION, - /** File */ - FILE, - /** Type alias */ - @SinceKotlin("1.1") - TYPEALIAS -} - -/** - * Contains the list of possible annotation's retentions. - * - * Determines how an annotation is stored in binary output. - */ -public enum class AnnotationRetention { - /** Annotation isn't stored in binary output */ - SOURCE, - /** Annotation is stored in binary output, but invisible for reflection */ - BINARY, - /** Annotation is stored in binary output and visible for reflection (default retention) */ - RUNTIME -} - -/** - * This meta-annotation indicates the kinds of code elements which are possible targets of an annotation. - * - * If the target meta-annotation is not present on an annotation declaration, the annotation is applicable to the following elements: - * [CLASS], [PROPERTY], [FIELD], [LOCAL_VARIABLE], [VALUE_PARAMETER], [CONSTRUCTOR], [FUNCTION], [PROPERTY_GETTER], [PROPERTY_SETTER]. - * - * @property allowedTargets list of allowed annotation targets - */ -@Target(AnnotationTarget.ANNOTATION_CLASS) -@MustBeDocumented -public annotation class Target(vararg val allowedTargets: AnnotationTarget) - -/** - * This meta-annotation determines whether an annotation is stored in binary output and visible for reflection. By default, both are true. - * - * @property value necessary annotation retention (RUNTIME, BINARY or SOURCE) - */ -@Target(AnnotationTarget.ANNOTATION_CLASS) -public annotation class Retention(val value: AnnotationRetention = AnnotationRetention.RUNTIME) - -/** - * This meta-annotation determines that an annotation is applicable twice or more on a single code element - */ -@Target(AnnotationTarget.ANNOTATION_CLASS) -public annotation class Repeatable - -/** - * This meta-annotation determines that an annotation is a part of public API and therefore should be included in the generated - * documentation for the element to which the annotation is applied. - */ -@Target(AnnotationTarget.ANNOTATION_CLASS) -public annotation class MustBeDocumented diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/internal/InternalAnnotations.kt b/libraries/stdlib/wasm/builtins/src/kotlin/internal/InternalAnnotations.kt deleted file mode 100644 index 09daa9dfda7..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/internal/InternalAnnotations.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.internal - -/** - * Specifies that the corresponding type parameter is not used for unsafe operations such as casts or 'is' checks - * That means it's completely safe to use generic types as argument for such parameter. - */ -@Target(AnnotationTarget.TYPE_PARAMETER) -@Retention(AnnotationRetention.BINARY) -internal annotation class PureReifiable - -/** - * Specifies that the corresponding built-in method exists depending on platform. - * Current implementation for JVM looks whether method with same JVM descriptor exists in the module JDK. - * For example MutableMap.remove(K, V) available only if corresponding - * method 'java/util/Map.remove(Ljava/lang/Object;Ljava/lang/Object;)Z' is defined in JDK (i.e. for major versions >= 8) - */ -@Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.BINARY) -internal annotation class PlatformDependent diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KAnnotatedElement.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KAnnotatedElement.kt deleted file mode 100644 index 4fa1a1e29eb..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KAnnotatedElement.kt +++ /dev/null @@ -1,18 +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.reflect - -/** - * Represents an annotated element and allows to obtain its annotations. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/annotations.html) - * for more information. - */ -public interface KAnnotatedElement { - /** - * Annotations which are present on this element. - */ - public val annotations: List -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KCallable.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KCallable.kt deleted file mode 100644 index a95dbf4fed1..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KCallable.kt +++ /dev/null @@ -1,85 +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.reflect - -/** - * Represents a callable entity, such as a function or a property. - * - * @param R return type of the callable. - */ -public interface KCallable : KAnnotatedElement { - /** - * The name of this callable as it was declared in the source code. - * If the callable has no name, a special invented name is created. - * Nameless callables include: - * - constructors have the name "", - * - property accessors: the getter for a property named "foo" will have the name "", - * the setter, similarly, will have the name "". - */ - public val name: String - - /** - * Parameters required to make a call to this callable. - * If this callable requires a `this` instance or an extension receiver parameter, - * they come first in the list in that order. - */ - public val parameters: List - - /** - * The type of values returned by this callable. - */ - public val returnType: KType - - /** - * The list of type parameters of this callable. - */ - @SinceKotlin("1.1") - public val typeParameters: List - - /** - * Calls this callable with the specified list of arguments and returns the result. - * Throws an exception if the number of specified arguments is not equal to the size of [parameters], - * or if their types do not match the types of the parameters. - */ - public fun call(vararg args: Any?): R - - /** - * Calls this callable with the specified mapping of parameters to arguments and returns the result. - * If a parameter is not found in the mapping and is not optional (as per [KParameter.isOptional]), - * or its type does not match the type of the provided value, an exception is thrown. - */ - public fun callBy(args: Map): R - - /** - * Visibility of this callable, or `null` if its visibility cannot be represented in Kotlin. - */ - @SinceKotlin("1.1") - public val visibility: KVisibility? - - /** - * `true` if this callable is `final`. - */ - @SinceKotlin("1.1") - public val isFinal: Boolean - - /** - * `true` if this callable is `open`. - */ - @SinceKotlin("1.1") - public val isOpen: Boolean - - /** - * `true` if this callable is `abstract`. - */ - @SinceKotlin("1.1") - public val isAbstract: Boolean - - /** - * `true` if this is a suspending function. - */ - @SinceKotlin("1.3") - public val isSuspend: Boolean -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClass.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClass.kt deleted file mode 100644 index 29f99188475..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClass.kt +++ /dev/null @@ -1,144 +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.reflect - -/** - * Represents a class and provides introspection capabilities. - * Instances of this class are obtainable by the `::class` syntax. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html#class-references) - * for more information. - * - * @param T the type of the class. - */ -public interface KClass : KDeclarationContainer, KAnnotatedElement, KClassifier { - /** - * The simple name of the class as it was declared in the source code, - * or `null` if the class has no name (if, for example, it is an anonymous object literal). - */ - public val simpleName: String? - - /** - * The fully qualified dot-separated name of the class, - * or `null` if the class is local or it is an anonymous object literal. - */ - public val qualifiedName: String? - - /** - * All functions and properties accessible in this class, including those declared in this class - * and all of its superclasses. Does not include constructors. - */ - override val members: Collection> - - /** - * All constructors declared in this class. - */ - public val constructors: Collection> - - /** - * All classes declared inside this class. This includes both inner and static nested classes. - */ - public val nestedClasses: Collection> - - /** - * The instance of the object declaration, or `null` if this class is not an object declaration. - */ - public val objectInstance: T? - - /** - * Returns `true` if [value] is an instance of this class on a given platform. - */ - @SinceKotlin("1.1") - public fun isInstance(value: Any?): Boolean - - /** - * The list of type parameters of this class. This list does *not* include type parameters of outer classes. - */ - @SinceKotlin("1.1") - public val typeParameters: List - - /** - * The list of immediate supertypes of this class, in the order they are listed in the source code. - */ - @SinceKotlin("1.1") - public val supertypes: List - - /** - * The list of the immediate subclasses if this class is a sealed class, or an empty list otherwise. - */ - @SinceKotlin("1.3") - public val sealedSubclasses: List> - - /** - * Visibility of this class, or `null` if its visibility cannot be represented in Kotlin. - */ - @SinceKotlin("1.1") - public val visibility: KVisibility? - - /** - * `true` if this class is `final`. - */ - @SinceKotlin("1.1") - public val isFinal: Boolean - - /** - * `true` if this class is `open`. - */ - @SinceKotlin("1.1") - public val isOpen: Boolean - - /** - * `true` if this class is `abstract`. - */ - @SinceKotlin("1.1") - public val isAbstract: Boolean - - /** - * `true` if this class is `sealed`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/sealed-classes.html) - * for more information. - */ - @SinceKotlin("1.1") - public val isSealed: Boolean - - /** - * `true` if this class is a data class. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/data-classes.html) - * for more information. - */ - @SinceKotlin("1.1") - public val isData: Boolean - - /** - * `true` if this class is an inner class. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/nested-classes.html#inner-classes) - * for more information. - */ - @SinceKotlin("1.1") - public val isInner: Boolean - - /** - * `true` if this class is a companion object. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/object-declarations.html#companion-objects) - * for more information. - */ - @SinceKotlin("1.1") - public val isCompanion: Boolean - - /** - * Returns `true` if this [KClass] instance represents the same Kotlin class as the class represented by [other]. - * On JVM this means that all of the following conditions are satisfied: - * - * 1. [other] has the same (fully qualified) Kotlin class name as this instance. - * 2. [other]'s backing [Class] object is loaded with the same class loader as the [Class] object of this instance. - * 3. If the classes represent [Array], then [Class] objects of their element types are equal. - * - * For example, on JVM, [KClass] instances for a primitive type (`int`) and the corresponding wrapper type (`java.lang.Integer`) - * are considered equal, because they have the same fully qualified name "kotlin.Int". - */ - override fun equals(other: Any?): Boolean - - override fun hashCode(): Int -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClassifier.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClassifier.kt deleted file mode 100644 index 3c804e9cfa6..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KClassifier.kt +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.reflect - -/** - * A classifier is either a class or a type parameter. - * - * @see [KClass] - * @see [KTypeParameter] - */ -@SinceKotlin("1.1") -public interface KClassifier diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KDeclarationContainer.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KDeclarationContainer.kt deleted file mode 100644 index 447cfb33d49..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KDeclarationContainer.kt +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.reflect - -/** - * Represents an entity which may contain declarations of any other entities, - * such as a class or a package. - */ -public interface KDeclarationContainer { - /** - * All functions and properties accessible in this container. - */ - public val members: Collection> -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KFunction.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KFunction.kt deleted file mode 100644 index 72b975b9313..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KFunction.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2010-2018 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.reflect - -/** - * Represents a function with introspection capabilities. - */ -public interface KFunction : KCallable, Function { - /** - * `true` if this function is `inline`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html) - * for more information. - */ - @SinceKotlin("1.1") - public val isInline: Boolean - - /** - * `true` if this function is `external`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/java-interop.html#using-jni-with-kotlin) - * for more information. - */ - @SinceKotlin("1.1") - public val isExternal: Boolean - - /** - * `true` if this function is `operator`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/operator-overloading.html) - * for more information. - */ - @SinceKotlin("1.1") - public val isOperator: Boolean - - /** - * `true` if this function is `infix`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#infix-notation) - * for more information. - */ - @SinceKotlin("1.1") - public val isInfix: Boolean - - /** - * `true` if this is a suspending function. - */ - @SinceKotlin("1.1") - public override val isSuspend: Boolean -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KParameter.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KParameter.kt deleted file mode 100644 index 2267986d45f..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KParameter.kt +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.reflect - -/** - * Represents a parameter passed to a function or a property getter/setter, - * including `this` and extension receiver parameters. - */ -public interface KParameter : KAnnotatedElement { - /** - * 0-based index of this parameter in the parameter list of its containing callable. - */ - public val index: Int - - /** - * Name of this parameter as it was declared in the source code, - * or `null` if the parameter has no name or its name is not available at runtime. - * Examples of nameless parameters include `this` instance for member functions, - * extension receiver for extension functions or properties, parameters of Java methods - * compiled without the debug information, and others. - */ - public val name: String? - - /** - * Type of this parameter. For a `vararg` parameter, this is the type of the corresponding array, - * not the individual element. - */ - public val type: KType - - /** - * Kind of this parameter. - */ - public val kind: Kind - - /** - * Kind represents a particular position of the parameter declaration in the source code, - * such as an instance, an extension receiver parameter or a value parameter. - */ - public enum class Kind { - /** Instance required to make a call to the member, or an outer class instance for an inner class constructor. */ - INSTANCE, - - /** Extension receiver of an extension function or property. */ - EXTENSION_RECEIVER, - - /** Ordinary named value parameter. */ - VALUE, - } - - /** - * `true` if this parameter is optional and can be omitted when making a call via [KCallable.callBy], or `false` otherwise. - * - * A parameter is optional in any of the two cases: - * 1. The default value is provided at the declaration of this parameter. - * 2. The parameter is declared in a member function and one of the corresponding parameters in the super functions is optional. - */ - public val isOptional: Boolean - - /** - * `true` if this parameter is `vararg`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs) - * for more information. - */ - @SinceKotlin("1.1") - public val isVararg: Boolean -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KProperty.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KProperty.kt deleted file mode 100644 index 70704209c81..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KProperty.kt +++ /dev/null @@ -1,258 +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. - */ - -@file:Suppress("IMPLEMENTING_FUNCTION_INTERFACE") -package kotlin.reflect - -/** - * Represents a property, such as a named `val` or `var` declaration. - * Instances of this class are obtainable by the `::` operator. - * - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html) - * for more information. - * - * @param R the type of the property. - */ -public interface KProperty : KCallable { - /** - * `true` if this property is `lateinit`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#late-initialized-properties) - * for more information. - */ - @SinceKotlin("1.1") - public val isLateinit: Boolean - - /** - * `true` if this property is `const`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#compile-time-constants) - * for more information. - */ - @SinceKotlin("1.1") - public val isConst: Boolean - - /** The getter of this property, used to obtain the value of the property. */ - public val getter: Getter - - /** - * Represents a property accessor, which is a `get` or `set` method declared alongside the property. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/properties.html#getters-and-setters) - * for more information. - * - * @param R the type of the property, which it is an accessor of. - */ - public interface Accessor { - /** The property which this accessor is originated from. */ - public val property: KProperty - } - - /** - * Getter of the property is a `get` method declared alongside the property. - */ - public interface Getter : Accessor, KFunction -} - -/** - * Represents a property declared as a `var`. - */ -public interface KMutableProperty : KProperty { - /** The setter of this mutable property, used to change the value of the property. */ - public val setter: Setter - - /** - * Setter of the property is a `set` method declared alongside the property. - */ - public interface Setter : KProperty.Accessor, KFunction -} - - -/** - * Represents a property without any kind of receiver. - * Such property is either originally declared in a receiverless context such as a package, - * or has the receiver bound to it. - */ -public interface KProperty0 : KProperty, () -> R { - /** - * Returns the current value of the property. - */ - public fun get(): R - - /** - * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) - * for more information. - */ - @SinceKotlin("1.1") - public fun getDelegate(): Any? - - override val getter: Getter - - /** - * Getter of the property is a `get` method declared alongside the property. - * - * Can be used as a function that takes 0 arguments and returns the value of the property type [R]. - */ - public interface Getter : KProperty.Getter, () -> R -} - -/** - * Represents a `var`-property without any kind of receiver. - */ -public interface KMutableProperty0 : KProperty0, KMutableProperty { - /** - * Modifies the value of the property. - * - * @param value the new value to be assigned to this property. - */ - public fun set(value: R) - - override val setter: Setter - - /** - * Setter of the property is a `set` method declared alongside the property. - * - * Can be used as a function that takes new property value as an argument and returns [Unit]. - */ - public interface Setter : KMutableProperty.Setter, (R) -> Unit -} - - -/** - * Represents a property, operations on which take one receiver as a parameter. - * - * @param T the type of the receiver which should be used to obtain the value of the property. - * @param R the type of the property. - */ -public interface KProperty1 : KProperty, (T) -> R { - /** - * Returns the current value of the property. - * - * @param receiver the receiver which is used to obtain the value of the property. - * For example, it should be a class instance if this is a member property of that class, - * or an extension receiver if this is a top level extension property. - */ - public fun get(receiver: T): R - - /** - * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) - * for more information. - * - * Note that for a top level **extension** property, the delegate is the same for all extension receivers, - * so the [receiver] instance passed in is not going to make any difference, it must only be a value of [T]. - * - * @param receiver the receiver which is used to obtain the value of the property delegate. - * For example, it should be a class instance if this is a member property of that class, - * or an extension receiver if this is a top level extension property. - * - * @see [kotlin.reflect.full.getExtensionDelegate] // [KProperty1.getExtensionDelegate] - */ - @SinceKotlin("1.1") - public fun getDelegate(receiver: T): Any? - - override val getter: Getter - - /** - * Getter of the property is a `get` method declared alongside the property. - * - * Can be used as a function that takes an argument of type [T] (the receiver) and returns the value of the property type [R]. - */ - public interface Getter : KProperty.Getter, (T) -> R -} - -/** - * Represents a `var`-property, operations on which take one receiver as a parameter. - */ -public interface KMutableProperty1 : KProperty1, KMutableProperty { - /** - * Modifies the value of the property. - * - * @param receiver the receiver which is used to modify the value of the property. - * For example, it should be a class instance if this is a member property of that class, - * or an extension receiver if this is a top level extension property. - * @param value the new value to be assigned to this property. - */ - public fun set(receiver: T, value: R) - - override val setter: Setter - - /** - * Setter of the property is a `set` method declared alongside the property. - * - * Can be used as a function that takes the receiver and the new property value as arguments and returns [Unit]. - */ - public interface Setter : KMutableProperty.Setter, (T, R) -> Unit -} - - -/** - * Represents a property, operations on which take two receivers as parameters, - * such as an extension property declared in a class. - * - * @param D the type of the first receiver. In case of the extension property in a class this is - * the type of the declaring class of the property, or any subclass of that class. - * @param E the type of the second receiver. In case of the extension property in a class this is - * the type of the extension receiver. - * @param R the type of the property. - */ -public interface KProperty2 : KProperty, (D, E) -> R { - /** - * Returns the current value of the property. In case of the extension property in a class, - * the instance of the class should be passed first and the instance of the extension receiver second. - * - * @param receiver1 the instance of the first receiver. - * @param receiver2 the instance of the second receiver. - */ - public fun get(receiver1: D, receiver2: E): R - - /** - * Returns the value of the delegate if this is a delegated property, or `null` if this property is not delegated. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/delegated-properties.html) - * for more information. - * - * In case of the extension property in a class, the instance of the class should be passed first - * and the instance of the extension receiver second. - * - * @param receiver1 the instance of the first receiver. - * @param receiver2 the instance of the second receiver. - * - * @see [kotlin.reflect.full.getExtensionDelegate] // [KProperty2.getExtensionDelegate] - */ - @SinceKotlin("1.1") - public fun getDelegate(receiver1: D, receiver2: E): Any? - - override val getter: Getter - - /** - * Getter of the property is a `get` method declared alongside the property. - * - * Can be used as a function that takes an argument of type [D] (the first receiver), an argument of type [E] (the second receiver) - * and returns the value of the property type [R]. - */ - public interface Getter : KProperty.Getter, (D, E) -> R -} - -/** - * Represents a `var`-property, operations on which take two receivers as parameters. - */ -public interface KMutableProperty2 : KProperty2, KMutableProperty { - /** - * Modifies the value of the property. - * - * @param receiver1 the instance of the first receiver. - * @param receiver2 the instance of the second receiver. - * @param value the new value to be assigned to this property. - */ - public fun set(receiver1: D, receiver2: E, value: R) - - override val setter: Setter - - /** - * Setter of the property is a `set` method declared alongside the property. - * - * Can be used as a function that takes an argument of type [D] (the first receiver), an argument of type [E] (the second receiver), - * and the new property value and returns [Unit]. - */ - public interface Setter : KMutableProperty.Setter, (D, E, R) -> Unit -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KType.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KType.kt deleted file mode 100644 index dc3263244f3..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KType.kt +++ /dev/null @@ -1,104 +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.reflect - -/** - * Represents a type. Type is usually either a class with optional type arguments, - * or a type parameter of some declaration, plus nullability. - */ -public interface KType : KAnnotatedElement { - /** - * The declaration of the classifier used in this type. - * For example, in the type `List` the classifier would be the [KClass] instance for [List]. - * - * Returns `null` if this type is not denotable in Kotlin, for example if it is an intersection type. - */ - @SinceKotlin("1.1") - public val classifier: KClassifier? - - /** - * Type arguments passed for the parameters of the classifier in this type. - * For example, in the type `Array` the only type argument is `out Number`. - * - * In case this type is based on an inner class, the returned list contains the type arguments provided for the innermost class first, - * then its outer class, and so on. - * For example, in the type `Outer.Inner` the returned list is `[C, D, A, B]`. - */ - @SinceKotlin("1.1") - public val arguments: List - - /** - * `true` if this type was marked nullable in the source code. - * - * For Kotlin types, it means that `null` value is allowed to be represented by this type. - * In practice it means that the type was declared with a question mark at the end. - * For non-Kotlin types, it means the type or the symbol which was declared with this type - * is annotated with a runtime-retained nullability annotation such as [javax.annotation.Nullable]. - * - * Note that even if [isMarkedNullable] is false, values of the type can still be `null`. - * This may happen if it is a type of the type parameter with a nullable upper bound: - * - * ``` - * fun foo(t: T) { - * // isMarkedNullable == false for t's type, but t can be null here when T = "Any?" - * } - * ``` - */ - public val isMarkedNullable: Boolean -} - -/** - * Represents a type projection. Type projection is usually the argument to another type in a type usage. - * For example, in the type `Array`, `out Number` is the covariant projection of the type represented by the class `Number`. - * - * Type projection is either the star projection, or an entity consisting of a specific type plus optional variance. - * - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#type-projections) - * for more information. - */ -@SinceKotlin("1.1") -public data class KTypeProjection constructor( - /** - * The use-site variance specified in the projection, or `null` if this is a star projection. - */ - public val variance: KVariance?, - /** - * The type specified in the projection, or `null` if this is a star projection. - */ - public val type: KType? -) { - public companion object { - /** - * Star projection, denoted by the `*` character. - * For example, in the type `KClass<*>`, `*` is the star projection. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#star-projections) - * for more information. - */ - public val STAR: KTypeProjection = KTypeProjection(null, null) - - /** - * Creates an invariant projection of a given type. Invariant projection is just the type itself, - * without any use-site variance modifiers applied to it. - * For example, in the type `Set`, `String` is an invariant projection of the type represented by the class `String`. - */ - public fun invariant(type: KType): KTypeProjection = - KTypeProjection(KVariance.INVARIANT, type) - - /** - * Creates a contravariant projection of a given type, denoted by the `in` modifier applied to a type. - * For example, in the type `MutableList`, `in Number` is a contravariant projection of the type of class `Number`. - */ - public fun contravariant(type: KType): KTypeProjection = - KTypeProjection(KVariance.IN, type) - - /** - * Creates a covariant projection of a given type, denoted by the `out` modifier applied to a type. - * For example, in the type `Array`, `out Number` is a covariant projection of the type of class `Number`. - */ - public fun covariant(type: KType): KTypeProjection = - KTypeProjection(KVariance.OUT, type) - } -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KTypeParameter.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KTypeParameter.kt deleted file mode 100644 index 5351ffc7100..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KTypeParameter.kt +++ /dev/null @@ -1,40 +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.reflect - -/** - * Represents a declaration of a type parameter of a class or a callable. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#generics) - * for more information. - */ -@SinceKotlin("1.1") -public interface KTypeParameter : KClassifier { - /** - * The name of this type parameter as it was declared in the source code. - */ - public val name: String - - /** - * Upper bounds, or generic constraints imposed on this type parameter. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#upper-bounds) - * for more information. - */ - public val upperBounds: List - - /** - * Declaration-site variance of this type parameter. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#declaration-site-variance) - * for more information. - */ - public val variance: KVariance - - /** - * `true` if this type parameter is `reified`. - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/inline-functions.html#reified-type-parameters) - * for more information. - */ - public val isReified: Boolean -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVariance.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVariance.kt deleted file mode 100644 index 9a237cbbb9b..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVariance.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.reflect - -/** - * Represents variance applied to a type parameter on the declaration site (*declaration-site variance*), - * or to a type in a projection (*use-site variance*). - * - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/generics.html#variance) - * for more information. - * - * @see [KTypeParameter.variance] - * @see [KTypeProjection] - */ -@SinceKotlin("1.1") -enum class KVariance { - /** - * The affected type parameter or type is *invariant*, which means it has no variance applied to it. - */ - INVARIANT, - - /** - * The affected type parameter or type is *contravariant*. Denoted by the `in` modifier in the source code. - */ - IN, - - /** - * The affected type parameter or type is *covariant*. Denoted by the `out` modifier in the source code. - */ - OUT, -} diff --git a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVisibility.kt b/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVisibility.kt deleted file mode 100644 index 6ddd7e1769b..00000000000 --- a/libraries/stdlib/wasm/builtins/src/kotlin/reflect/KVisibility.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.reflect - -/** - * Visibility is an aspect of a Kotlin declaration regulating where that declaration is accessible in the source code. - * Visibility can be changed with one of the following modifiers: `public`, `protected`, `internal`, `private`. - * - * Note that some Java visibilities such as package-private and protected (which also gives access to items from the same package) - * cannot be represented in Kotlin, so there's no [KVisibility] value corresponding to them. - * - * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/visibility-modifiers.html) - * for more information. - */ -@SinceKotlin("1.1") -enum class KVisibility { - /** - * Visibility of declarations marked with the `public` modifier, or with no modifier at all. - */ - PUBLIC, - - /** - * Visibility of declarations marked with the `protected` modifier. - */ - PROTECTED, - - /** - * Visibility of declarations marked with the `internal` modifier. - */ - INTERNAL, - - /** - * Visibility of declarations marked with the `private` modifier. - */ - PRIVATE, -} diff --git a/libraries/stdlib/wasm/internal/WasmInstructions.kt b/libraries/stdlib/wasm/internal/WasmInstructions.kt deleted file mode 100644 index a4369aed7ea..00000000000 --- a/libraries/stdlib/wasm/internal/WasmInstructions.kt +++ /dev/null @@ -1,397 +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. - */ - -@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 - diff --git a/libraries/stdlib/wasm/internal/WasmMath.kt b/libraries/stdlib/wasm/internal/WasmMath.kt deleted file mode 100644 index bfe5e1681e4..00000000000 --- a/libraries/stdlib/wasm/internal/WasmMath.kt +++ /dev/null @@ -1,20 +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.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) \ No newline at end of file diff --git a/libraries/stdlib/wasm/runtime/stubsKotlinRanges.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/DefaultConstructorMarker.kt similarity index 51% rename from libraries/stdlib/wasm/runtime/stubsKotlinRanges.kt rename to libraries/stdlib/wasm/internal/kotlin/wasm/internal/DefaultConstructorMarker.kt index e952b6893eb..cc6a5de4771 100644 --- a/libraries/stdlib/wasm/runtime/stubsKotlinRanges.kt +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/DefaultConstructorMarker.kt @@ -3,12 +3,6 @@ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. */ -@file:kotlin.wasm.internal.ExcludedFromCodegen +package kotlin.wasm.internal -package kotlin.ranges - -// Stubs for unimplemented classes used by CommonBackendContext - -class CharProgression -class IntProgression -class LongProgression \ No newline at end of file +internal object DefaultConstructorMarker \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Function0.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Function0.kt new file mode 100644 index 00000000000..e542e4ee725 --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Function0.kt @@ -0,0 +1,341 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("unused") + +package kotlin.wasm.internal + +/** A function that takes 0 arguments. */ +public interface Function0 : Function { + /** Invokes the function. */ + public operator fun invoke(): R +} + +/** A function that takes 1 argument. */ +public interface Function1 : Function { + /** Invokes the function with the specified argument. */ + public operator fun invoke(p1: P1): R +} + +/** A function that takes 2 arguments. */ +public interface Function2 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2): R +} + +/** A function that takes 3 arguments. */ +public interface Function3 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3): R +} + +/** A function that takes 4 arguments. */ +public interface Function4 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4): R +} + +/** A function that takes 5 arguments. */ +public interface Function5 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R +} + +/** A function that takes 6 arguments. */ +public interface Function6 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R +} + +/** A function that takes 7 arguments. */ +public interface Function7 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R +} + +/** A function that takes 8 arguments. */ +public interface Function8 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R +} + +/** A function that takes 9 arguments. */ +public interface Function9 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R +} + +/** A function that takes 10 arguments. */ +public interface Function10 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10): R +} + +/** A function that takes 11 arguments. */ +public interface Function11 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11): R +} + +/** A function that takes 12 arguments. */ +public interface Function12 : Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12): R +} + +/** A function that takes 13 arguments. */ +public interface Function13 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13 + ): R +} + +/** A function that takes 14 arguments. */ +public interface Function14 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14 + ): R +} + +/** A function that takes 15 arguments. */ +public interface Function15 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15 + ): R +} + +/** A function that takes 16 arguments. */ +public interface Function16 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16 + ): R +} + +/** A function that takes 17 arguments. */ +public interface Function17 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17 + ): R +} + +/** A function that takes 18 arguments. */ +public interface Function18 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17, + p18: P18 + ): R +} + +/** A function that takes 19 arguments. */ +public interface Function19 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17, + p18: P18, + p19: P19 + ): R +} + +/** A function that takes 20 arguments. */ +public interface Function20 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17, + p18: P18, + p19: P19, + p20: P20 + ): R +} + +/** A function that takes 21 arguments. */ +public interface Function21 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17, + p18: P18, + p19: P19, + p20: P20, + p21: P21 + ): R +} + +/** A function that takes 22 arguments. */ +public interface Function22 : + Function { + /** Invokes the function with the specified arguments. */ + public operator fun invoke( + p1: P1, + p2: P2, + p3: P3, + p4: P4, + p5: P5, + p6: P6, + p7: P7, + p8: P8, + p9: P9, + p10: P10, + p11: P11, + p12: P12, + p13: P13, + p14: P14, + p15: P15, + p16: P16, + p17: P17, + p18: P18, + p19: P19, + p20: P20, + p21: P21, + p22: P22 + ): R +} diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/JsArray.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/JsArray.kt new file mode 100644 index 00000000000..58e6f2f004b --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/JsArray.kt @@ -0,0 +1,153 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + + +package kotlin.wasm.internal + +@ExcludedFromCodegen +@WasmForeign +internal class WasmExternRef + +@WasmImport("runtime", "JsArray_new") +internal fun JsArray_new(size: Int): WasmExternRef = + implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Byte(array: WasmExternRef, index: Int): Byte = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Byte(array: WasmExternRef, index: Int, value: Byte): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Char(array: WasmExternRef, index: Int): Char = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Char(array: WasmExternRef, index: Int, value: Char): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Short(array: WasmExternRef, index: Int): Short = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Short(array: WasmExternRef, index: Int, value: Short): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Int(array: WasmExternRef, index: Int): Int = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Int(array: WasmExternRef, index: Int, value: Int): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Long(array: WasmExternRef, index: Int): Long = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Long(array: WasmExternRef, index: Int, value: Long): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Float(array: WasmExternRef, index: Int): Float = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Float(array: WasmExternRef, index: Int, value: Float): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Double(array: WasmExternRef, index: Int): Double = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Double(array: WasmExternRef, index: Int, value: Double): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_Boolean(array: WasmExternRef, index: Int): Boolean = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_Boolean(array: WasmExternRef, index: Int, value: Boolean): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_get") +internal fun JsArray_get_WasmExternRef(array: WasmExternRef, index: Int): WasmExternRef = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_set") +internal fun JsArray_set_WasmExternRef(array: WasmExternRef, index: Int, value: WasmExternRef): Unit = implementedAsIntrinsic + +@WasmImport("runtime", "JsArray_getSize") +internal fun JsArray_getSize(array: WasmExternRef): Int = + implementedAsIntrinsic + +@WasmImport("runtime", "identity") +internal fun Any?.toWasmExternRef(): WasmExternRef = + implementedAsIntrinsic + +@WasmImport("runtime", "identity") +internal fun WasmExternRefToAny(ref: WasmExternRef): Any? = + implementedAsIntrinsic + +internal inline fun JsArray_fill_Byte(array: WasmExternRef, size: Int, init: (Int) -> Byte) { + var i = 0 + while (i < size) { + JsArray_set_Byte(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Char(array: WasmExternRef, size: Int, init: (Int) -> Char) { + var i = 0 + while (i < size) { + JsArray_set_Char(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Short(array: WasmExternRef, size: Int, init: (Int) -> Short) { + var i = 0 + while (i < size) { + JsArray_set_Short(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Int(array: WasmExternRef, size: Int, init: (Int) -> Int) { + var i = 0 + while (i < size) { + JsArray_set_Int(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Long(array: WasmExternRef, size: Int, init: (Int) -> Long) { + var i = 0 + while (i < size) { + JsArray_set_Long(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Float(array: WasmExternRef, size: Int, init: (Int) -> Float) { + var i = 0 + while (i < size) { + JsArray_set_Float(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Double(array: WasmExternRef, size: Int, init: (Int) -> Double) { + var i = 0 + while (i < size) { + JsArray_set_Double(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_Boolean(array: WasmExternRef, size: Int, init: (Int) -> Boolean) { + var i = 0 + while (i < size) { + JsArray_set_Boolean(array, i, init(i)) + i++ + } +} + +internal inline fun JsArray_fill_T(array: WasmExternRef, size: Int, init: (Int) -> T) { + var i = 0 + while (i < size) { + JsArray_set_WasmExternRef(array, i, init(i).toWasmExternRef()) + i++ + } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt new file mode 100644 index 00000000000..9046afa96f7 --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/Runtime.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.wasm.internal + +@WasmImport("runtime", "String_getLiteral") +internal fun stringLiteral(index: Int): String = + implementedAsIntrinsic + +@WasmReinterpret +internal fun unsafeNotNull(x: Any?): Any = + implementedAsIntrinsic + +internal fun nullableEquals(lhs: Any?, rhs: Any?): Boolean { + if (wasm_ref_is_null(lhs)) + return wasm_ref_is_null(rhs) + return unsafeNotNull(lhs).equals(rhs) +} + +internal fun anyNtoString(x: Any?): String = x.toString() + +internal fun nullableFloatIeee754Equals(lhs: Float?, rhs: Float?): Boolean { + if (lhs == null) return rhs == null + if (rhs == null) return false + return wasm_f32_eq(lhs, rhs) +} + +internal fun nullableDoubleIeee754Equals(lhs: Double?, rhs: Double?): Boolean { + if (lhs == null) return rhs == null + if (rhs == null) return false + return wasm_f64_eq(lhs, rhs) +} + + +internal fun ensureNotNull(v: T?): T = if (v == null) THROW_NPE() else v + +@ExcludedFromCodegen +internal fun boxIntrinsic(x: T): R = + implementedAsIntrinsic + +@ExcludedFromCodegen +internal fun unboxIntrinsic(x: T): R = + implementedAsIntrinsic + +internal fun wasmThrow(e: Throwable): Nothing { + println("Kotlin/Wasm exception wasm thrown: ${e.message}") + wasm_unreachable() +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt new file mode 100644 index 00000000000..afc6ae3d74c --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/ThrowHelpers.kt @@ -0,0 +1,27 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.wasm.internal + +internal fun THROW_CCE(): Nothing { + throw ClassCastException() +} + +internal fun THROW_NPE(): Nothing { + throw NullPointerException() +} + +internal fun THROW_ISE(): Nothing { + throw IllegalStateException() +} + +internal fun THROW_IAE(): Nothing { + throw IllegalArgumentException() +} + +@PublishedApi +internal fun throwUninitializedPropertyAccessException(name: String): Nothing { + throw UninitializedPropertyAccessException("lateinit property $name has not been initialized") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt new file mode 100644 index 00000000000..86f80ef7607 --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/TypeInfo.kt @@ -0,0 +1,83 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("unused") // Used by compiler + +package kotlin.wasm.internal + +internal const val TYPE_INFO_ELEMENT_SIZE = 4 + +internal const val TYPE_INFO_VTABLE_OFFSET = 2 * TYPE_INFO_ELEMENT_SIZE +internal const val TYPE_INFO_VTABLE_LENGTH_OFFSET = TYPE_INFO_ELEMENT_SIZE +internal const val SUPER_CLASS_ID_OFFSET = 0 + +internal fun getVtablePtr(obj: Any): Int = + obj.typeInfo + TYPE_INFO_VTABLE_OFFSET + +internal fun getVtableLength(obj: Any): Int = + wasm_i32_load(obj.typeInfo + TYPE_INFO_VTABLE_LENGTH_OFFSET) + +internal fun getInterfaceListLength(obj: Any): Int = + wasm_i32_load(obj.typeInfo + TYPE_INFO_VTABLE_LENGTH_OFFSET) + +internal fun getSuperClassId(obj: Any): Int = + wasm_i32_load(obj.typeInfo + SUPER_CLASS_ID_OFFSET) + +internal fun getVirtualMethodId(obj: Any, virtualFunctionSlot: Int): Int { + val vtablePtr = getVtablePtr(obj) + val methodIdPtr = vtablePtr + virtualFunctionSlot * TYPE_INFO_ELEMENT_SIZE + return wasm_i32_load(methodIdPtr) +} + +internal fun getInterfaceMethodId(obj: Any, methodSignatureId: Int): Int { + val vtableLength = getVtableLength(obj) + val vtableSignatures = getVtablePtr(obj) + vtableLength * TYPE_INFO_ELEMENT_SIZE + var virtualFunctionSlot = 0 + while (virtualFunctionSlot < vtableLength) { + if (wasm_i32_load(vtableSignatures + virtualFunctionSlot * TYPE_INFO_ELEMENT_SIZE) == methodSignatureId) { + return getVirtualMethodId(obj, virtualFunctionSlot) + } + virtualFunctionSlot++ + } + wasm_unreachable() +} + + +internal fun isSubClassOfImpl(currentClassId: Int, otherClassId: Int): Boolean { + if (currentClassId == otherClassId) return true + val anyClassId = wasmClassId() + if (currentClassId == anyClassId && otherClassId != anyClassId) return false + return isSubClassOfImpl(wasm_i32_load(currentClassId + SUPER_CLASS_ID_OFFSET), otherClassId) +} + +internal fun isSubClass(obj: Any, classId: Int): Boolean { + return isSubClassOfImpl(obj.typeInfo, classId) +} + +internal fun isInterface(obj: Any, interfaceId: Int): Boolean { + val vtableLength = getVtableLength(obj) + val interfaceListSizePtr = getVtablePtr(obj) + 2 * vtableLength * TYPE_INFO_ELEMENT_SIZE + val interfaceListPtr = interfaceListSizePtr + TYPE_INFO_ELEMENT_SIZE + val interfaceListSize = wasm_i32_load(interfaceListSizePtr) + + var interfaceSlot = 0 + while (interfaceSlot < interfaceListSize) { + val supportedInterface = wasm_i32_load(interfaceListPtr + interfaceSlot * TYPE_INFO_ELEMENT_SIZE) + if (supportedInterface == interfaceId) { + return true + } + interfaceSlot++ + } + + return false +} + +@ExcludedFromCodegen +internal fun wasmClassId(): Int = + implementedAsIntrinsic + +@ExcludedFromCodegen +internal fun wasmInterfaceId(): Int = + implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmAnnotations.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmAnnotations.kt new file mode 100644 index 00000000000..24f44c8057e --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmAnnotations.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.wasm.internal + +import kotlin.annotation.AnnotationTarget.* + +// Exclude declaration or file from lowering and code generation +@Target(FILE, CLASS, FUNCTION, CONSTRUCTOR, PROPERTY) +@Retention(AnnotationRetention.BINARY) +internal annotation class ExcludedFromCodegen + +@Target(FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER) +@Retention(AnnotationRetention.BINARY) +internal annotation class WasmImport(val module: String, val name: String) + +@Target(CLASS) +@Retention(AnnotationRetention.BINARY) +internal annotation class WasmForeign + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class WasmReinterpret + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +internal annotation class WasmPrimitive + +/** + * Replace calls to this functions with specified Wasm instruction. + * + * Operands are passed in the following order: + * 1. Dispatch receiver (if present) + * 2. Extension receiver (if present) + * 3. Value arguments + * + * @mnemonic parameter is an instruction WAT name: "i32.add", "f64.trunc", etc. + * + * Immediate arguments (label, index, offest, align, etc.) are not supported yet. + */ + +@ExcludedFromCodegen +internal val implementedAsIntrinsic: Nothing + get() = null!! \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt new file mode 100644 index 00000000000..ff5569aa198 --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmInstructions.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:ExcludedFromCodegen +@file:Suppress("unused") + +package kotlin.wasm.internal + +@WasmOp(WasmOp.UNREACHABLE) +internal fun wasm_unreachable(): Nothing = + implementedAsIntrinsic + +internal fun wasm_float_nan(): Float = + implementedAsIntrinsic + +internal fun wasm_double_nan(): Double = + implementedAsIntrinsic + +internal fun wasm_ref_cast(a: From): To = + implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmMath.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmMath.kt new file mode 100644 index 00000000000..2a1c273fd23 --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmMath.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package 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).toInt() - wasm_i32_le_s(x, y).toInt() + +fun wasm_i64_compareTo(x: Long, y: Long): Int = + wasm_i64_ge_s(x, y).toInt() - wasm_i64_le_s(x, y).toInt() + +@WasmImport("runtime", "String_equals") +fun wasm_string_eq(x: String, y: String): Boolean = + implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmOp.kt b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmOp.kt new file mode 100644 index 00000000000..b69794a9f4f --- /dev/null +++ b/libraries/stdlib/wasm/internal/kotlin/wasm/internal/WasmOp.kt @@ -0,0 +1,514 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:ExcludedFromCodegen +@file:Suppress( + "INLINE_CLASS_IN_EXTERNAL_DECLARATION", + "NON_ABSTRACT_FUNCTION_WITH_NO_BODY", + "unused" +) + +package kotlin.wasm.internal + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +internal annotation class WasmOp(val name: String) { + companion object { + const val I32_EQZ = "I32_EQZ" + const val I64_EQZ = "I64_EQZ" + const val I32_CLZ = "I32_CLZ" + const val I32_CTZ = "I32_CTZ" + const val I32_POPCNT = "I32_POPCNT" + const val I64_CLZ = "I64_CLZ" + const val I64_CTZ = "I64_CTZ" + const val I64_POPCNT = "I64_POPCNT" + const val F32_ABS = "F32_ABS" + const val F32_NEG = "F32_NEG" + const val F32_CEIL = "F32_CEIL" + const val F32_FLOOR = "F32_FLOOR" + const val F32_TRUNC = "F32_TRUNC" + const val F32_NEAREST = "F32_NEAREST" + const val F32_SQRT = "F32_SQRT" + const val F64_ABS = "F64_ABS" + const val F64_NEG = "F64_NEG" + const val F64_CEIL = "F64_CEIL" + const val F64_FLOOR = "F64_FLOOR" + const val F64_TRUNC = "F64_TRUNC" + const val F64_NEAREST = "F64_NEAREST" + const val F64_SQRT = "F64_SQRT" + const val I32_WRAP_I64 = "I32_WRAP_I64" + const val I32_TRUNC_F32_S = "I32_TRUNC_F32_S" + const val I32_TRUNC_F32_U = "I32_TRUNC_F32_U" + const val I32_TRUNC_F64_S = "I32_TRUNC_F64_S" + const val I32_TRUNC_F64_U = "I32_TRUNC_F64_U" + const val I64_EXTEND_I32_S = "I64_EXTEND_I32_S" + const val I64_EXTEND_I32_U = "I64_EXTEND_I32_U" + const val I64_TRUNC_F32_S = "I64_TRUNC_F32_S" + const val I64_TRUNC_F32_U = "I64_TRUNC_F32_U" + const val I64_TRUNC_F64_S = "I64_TRUNC_F64_S" + const val I64_TRUNC_F64_U = "I64_TRUNC_F64_U" + const val F32_CONVERT_I32_S = "F32_CONVERT_I32_S" + const val F32_CONVERT_I32_U = "F32_CONVERT_I32_U" + const val F32_CONVERT_I64_S = "F32_CONVERT_I64_S" + const val F32_CONVERT_I64_U = "F32_CONVERT_I64_U" + const val F32_DEMOTE_F64 = "F32_DEMOTE_F64" + const val F64_CONVERT_I32_S = "F64_CONVERT_I32_S" + const val F64_CONVERT_I32_U = "F64_CONVERT_I32_U" + const val F64_CONVERT_I64_S = "F64_CONVERT_I64_S" + const val F64_CONVERT_I64_U = "F64_CONVERT_I64_U" + const val F64_PROMOTE_F32 = "F64_PROMOTE_F32" + const val I32_REINTERPRET_F32 = "I32_REINTERPRET_F32" + const val I64_REINTERPRET_F64 = "I64_REINTERPRET_F64" + const val F32_REINTERPRET_I32 = "F32_REINTERPRET_I32" + const val F64_REINTERPRET_I64 = "F64_REINTERPRET_I64" + const val I32_EXTEND8_S = "I32_EXTEND8_S" + const val I32_EXTEND16_S = "I32_EXTEND16_S" + const val I64_EXTEND8_S = "I64_EXTEND8_S" + const val I64_EXTEND16_S = "I64_EXTEND16_S" + const val I64_EXTEND32_S = "I64_EXTEND32_S" + const val I32_TRUNC_SAT_F32_S = "I32_TRUNC_SAT_F32_S" + const val I32_TRUNC_SAT_F32_U = "I32_TRUNC_SAT_F32_U" + const val I32_TRUNC_SAT_F64_S = "I32_TRUNC_SAT_F64_S" + const val I32_TRUNC_SAT_F64_U = "I32_TRUNC_SAT_F64_U" + const val I64_TRUNC_SAT_F32_S = "I64_TRUNC_SAT_F32_S" + const val I64_TRUNC_SAT_F32_U = "I64_TRUNC_SAT_F32_U" + const val I64_TRUNC_SAT_F64_S = "I64_TRUNC_SAT_F64_S" + const val I64_TRUNC_SAT_F64_U = "I64_TRUNC_SAT_F64_U" + const val I32_EQ = "I32_EQ" + const val I32_NE = "I32_NE" + const val I32_LT_S = "I32_LT_S" + const val I32_LT_U = "I32_LT_U" + const val I32_GT_S = "I32_GT_S" + const val I32_GT_U = "I32_GT_U" + const val I32_LE_S = "I32_LE_S" + const val I32_LE_U = "I32_LE_U" + const val I32_GE_S = "I32_GE_S" + const val I32_GE_U = "I32_GE_U" + const val I64_EQ = "I64_EQ" + const val I64_NE = "I64_NE" + const val I64_LT_S = "I64_LT_S" + const val I64_LT_U = "I64_LT_U" + const val I64_GT_S = "I64_GT_S" + const val I64_GT_U = "I64_GT_U" + const val I64_LE_S = "I64_LE_S" + const val I64_LE_U = "I64_LE_U" + const val I64_GE_S = "I64_GE_S" + const val I64_GE_U = "I64_GE_U" + const val F32_EQ = "F32_EQ" + const val F32_NE = "F32_NE" + const val F32_LT = "F32_LT" + const val F32_GT = "F32_GT" + const val F32_LE = "F32_LE" + const val F32_GE = "F32_GE" + const val F64_EQ = "F64_EQ" + const val F64_NE = "F64_NE" + const val F64_LT = "F64_LT" + const val F64_GT = "F64_GT" + const val F64_LE = "F64_LE" + const val F64_GE = "F64_GE" + const val I32_ADD = "I32_ADD" + const val I32_SUB = "I32_SUB" + const val I32_MUL = "I32_MUL" + const val I32_DIV_S = "I32_DIV_S" + const val I32_DIV_U = "I32_DIV_U" + const val I32_REM_S = "I32_REM_S" + const val I32_REM_U = "I32_REM_U" + const val I32_AND = "I32_AND" + const val I32_OR = "I32_OR" + const val I32_XOR = "I32_XOR" + const val I32_SHL = "I32_SHL" + const val I32_SHR_S = "I32_SHR_S" + const val I32_SHR_U = "I32_SHR_U" + const val I32_ROTL = "I32_ROTL" + const val I32_ROTR = "I32_ROTR" + const val I64_ADD = "I64_ADD" + const val I64_SUB = "I64_SUB" + const val I64_MUL = "I64_MUL" + const val I64_DIV_S = "I64_DIV_S" + const val I64_DIV_U = "I64_DIV_U" + const val I64_REM_S = "I64_REM_S" + const val I64_REM_U = "I64_REM_U" + const val I64_AND = "I64_AND" + const val I64_OR = "I64_OR" + const val I64_XOR = "I64_XOR" + const val I64_SHL = "I64_SHL" + const val I64_SHR_S = "I64_SHR_S" + const val I64_SHR_U = "I64_SHR_U" + const val I64_ROTL = "I64_ROTL" + const val I64_ROTR = "I64_ROTR" + const val F32_ADD = "F32_ADD" + const val F32_SUB = "F32_SUB" + const val F32_MUL = "F32_MUL" + const val F32_DIV = "F32_DIV" + const val F32_MIN = "F32_MIN" + const val F32_MAX = "F32_MAX" + const val F32_COPYSIGN = "F32_COPYSIGN" + const val F64_ADD = "F64_ADD" + const val F64_SUB = "F64_SUB" + const val F64_MUL = "F64_MUL" + const val F64_DIV = "F64_DIV" + const val F64_MIN = "F64_MIN" + const val F64_MAX = "F64_MAX" + const val F64_COPYSIGN = "F64_COPYSIGN" + const val I32_CONST = "I32_CONST" + const val I64_CONST = "I64_CONST" + const val F32_CONST = "F32_CONST" + const val F64_CONST = "F64_CONST" + const val I32_LOAD = "I32_LOAD" + const val I64_LOAD = "I64_LOAD" + const val F32_LOAD = "F32_LOAD" + const val F64_LOAD = "F64_LOAD" + const val I32_LOAD8_S = "I32_LOAD8_S" + const val I32_LOAD8_U = "I32_LOAD8_U" + const val I32_LOAD16_S = "I32_LOAD16_S" + const val I32_LOAD16_U = "I32_LOAD16_U" + const val I64_LOAD8_S = "I64_LOAD8_S" + const val I64_LOAD8_U = "I64_LOAD8_U" + const val I64_LOAD16_S = "I64_LOAD16_S" + const val I64_LOAD16_U = "I64_LOAD16_U" + const val I64_LOAD32_S = "I64_LOAD32_S" + const val I64_LOAD32_U = "I64_LOAD32_U" + const val I32_STORE = "I32_STORE" + const val I64_STORE = "I64_STORE" + const val F32_STORE = "F32_STORE" + const val F64_STORE = "F64_STORE" + const val I32_STORE8 = "I32_STORE8" + const val I32_STORE16 = "I32_STORE16" + const val I64_STORE8 = "I64_STORE8" + const val I64_STORE16 = "I64_STORE16" + const val I64_STORE32 = "I64_STORE32" + const val MEMORY_SIZE = "MEMORY_SIZE" + const val MEMORY_GROW = "MEMORY_GROW" + const val MEMORY_INIT = "MEMORY_INIT" + const val DATA_DROP = "DATA_DROP" + const val MEMORY_COPY = "MEMORY_COPY" + const val MEMORY_FILL = "MEMORY_FILL" + const val TABLE_GET = "TABLE_GET" + const val TABLE_SET = "TABLE_SET" + const val TABLE_GROW = "TABLE_GROW" + const val TABLE_SIZE = "TABLE_SIZE" + const val TABLE_FILL = "TABLE_FILL" + const val TABLE_INIT = "TABLE_INIT" + const val ELEM_DROP = "ELEM_DROP" + const val TABLE_COPY = "TABLE_COPY" + const val UNREACHABLE = "UNREACHABLE" + const val NOP = "NOP" + const val BLOCK = "BLOCK" + const val LOOP = "LOOP" + const val IF = "IF" + const val ELSE = "ELSE" + const val END = "END" + const val BR = "BR" + const val BR_IF = "BR_IF" + const val BR_TABLE = "BR_TABLE" + const val RETURN = "RETURN" + const val CALL = "CALL" + const val CALL_INDIRECT = "CALL_INDIRECT" + const val DROP = "DROP" + const val SELECT = "SELECT" + const val SELECT_TYPED = "SELECT_TYPED" + const val LOCAL_GET = "LOCAL_GET" + const val LOCAL_SET = "LOCAL_SET" + const val LOCAL_TEE = "LOCAL_TEE" + const val GLOBAL_GET = "GLOBAL_GET" + const val GLOBAL_SET = "GLOBAL_SET" + const val REF_NULL = "REF_NULL" + const val REF_IS_NULL = "REF_IS_NULL" + const val REF_EQ = "REF_EQ" + const val REF_FUNC = "REF_FUNC" + const val STRUCT_NEW_WITH_RTT = "STRUCT_NEW_WITH_RTT" + const val STRUCT_GET = "STRUCT_GET" + const val STRUCT_SET = "STRUCT_SET" + const val REF_CAST = "REF_CAST" + const val RTT_CANON = "RTT_CANON" + const val RTT_SUB = "RTT_SUB" + } +} + +@WasmOp(WasmOp.I32_EQ) +public external fun wasm_i32_eq(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_NE) +public external fun wasm_i32_ne(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_LT_S) +public external fun wasm_i32_lt_s(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_LT_U) +public external fun wasm_i32_lt_u(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_GT_S) +public external fun wasm_i32_gt_s(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_GT_U) +public external fun wasm_i32_gt_u(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_LE_S) +public external fun wasm_i32_le_s(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_LE_U) +public external fun wasm_i32_le_u(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_GE_S) +public external fun wasm_i32_ge_s(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I32_GE_U) +public external fun wasm_i32_ge_u(a: Int, b: Int): Boolean + +@WasmOp(WasmOp.I64_EQ) +public external fun wasm_i64_eq(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_NE) +public external fun wasm_i64_ne(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_LT_S) +public external fun wasm_i64_lt_s(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_LT_U) +public external fun wasm_i64_lt_u(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_GT_S) +public external fun wasm_i64_gt_s(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_GT_U) +public external fun wasm_i64_gt_u(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_LE_S) +public external fun wasm_i64_le_s(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_LE_U) +public external fun wasm_i64_le_u(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_GE_S) +public external fun wasm_i64_ge_s(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.I64_GE_U) +public external fun wasm_i64_ge_u(a: Long, b: Long): Boolean + +@WasmOp(WasmOp.F32_EQ) +public external fun wasm_f32_eq(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F32_NE) +public external fun wasm_f32_ne(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F32_LT) +public external fun wasm_f32_lt(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F32_GT) +public external fun wasm_f32_gt(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F32_LE) +public external fun wasm_f32_le(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F32_GE) +public external fun wasm_f32_ge(a: Float, b: Float): Boolean + +@WasmOp(WasmOp.F64_EQ) +public external fun wasm_f64_eq(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.F64_NE) +public external fun wasm_f64_ne(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.F64_LT) +public external fun wasm_f64_lt(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.F64_GT) +public external fun wasm_f64_gt(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.F64_LE) +public external fun wasm_f64_le(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.F64_GE) +public external fun wasm_f64_ge(a: Double, b: Double): Boolean + +@WasmOp(WasmOp.I32_ADD) +public external fun wasm_i32_add(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_SUB) +public external fun wasm_i32_sub(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_MUL) +public external fun wasm_i32_mul(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_DIV_S) +public external fun wasm_i32_div_s(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_DIV_U) +public external fun wasm_i32_div_u(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_REM_S) +public external fun wasm_i32_rem_s(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_REM_U) +public external fun wasm_i32_rem_u(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_AND) +public external fun wasm_i32_and(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_OR) +public external fun wasm_i32_or(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_XOR) +public external fun wasm_i32_xor(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_SHL) +public external fun wasm_i32_shl(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_SHR_S) +public external fun wasm_i32_shr_s(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_SHR_U) +public external fun wasm_i32_shr_u(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_ROTL) +public external fun wasm_i32_rotl(a: Int, b: Int): Int + +@WasmOp(WasmOp.I32_ROTR) +public external fun wasm_i32_rotr(a: Int, b: Int): Int + +@WasmOp(WasmOp.I64_ADD) +public external fun wasm_i64_add(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_SUB) +public external fun wasm_i64_sub(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_MUL) +public external fun wasm_i64_mul(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_DIV_S) +public external fun wasm_i64_div_s(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_DIV_U) +public external fun wasm_i64_div_u(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_REM_S) +public external fun wasm_i64_rem_s(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_REM_U) +public external fun wasm_i64_rem_u(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_AND) +public external fun wasm_i64_and(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_OR) +public external fun wasm_i64_or(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_XOR) +public external fun wasm_i64_xor(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_SHL) +public external fun wasm_i64_shl(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_SHR_S) +public external fun wasm_i64_shr_s(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_SHR_U) +public external fun wasm_i64_shr_u(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_ROTL) +public external fun wasm_i64_rotl(a: Long, b: Long): Long + +@WasmOp(WasmOp.I64_ROTR) +public external fun wasm_i64_rotr(a: Long, b: Long): Long + +@WasmOp(WasmOp.F32_ADD) +public external fun wasm_f32_add(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_SUB) +public external fun wasm_f32_sub(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_MUL) +public external fun wasm_f32_mul(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_DIV) +public external fun wasm_f32_div(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_MIN) +public external fun wasm_f32_min(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_MAX) +public external fun wasm_f32_max(a: Float, b: Float): Float + +@WasmOp(WasmOp.F32_COPYSIGN) +public external fun wasm_f32_copysign(a: Float, b: Float): Float + +@WasmOp(WasmOp.F64_ADD) +public external fun wasm_f64_add(a: Double, b: Double): Double + +@WasmOp(WasmOp.F64_SUB) +public external fun wasm_f64_sub(a: Double, b: Double): Double + +@WasmOp(WasmOp.F64_MUL) +public external fun wasm_f64_mul(a: Double, b: Double): Double + +@WasmOp(WasmOp.F64_DIV) +public external fun wasm_f64_div(a: Double, b: Double): Double + +@WasmOp(WasmOp.F64_MIN) +public external fun wasm_f64_min(a: Double, b: Double): Double + +@WasmOp(WasmOp.F64_MAX) +public external fun wasm_f64_max(a: Double, b: Double): Double + + +@WasmOp(WasmOp.REF_IS_NULL) +public external fun wasm_ref_is_null(a: Any?): Boolean + +@WasmOp(WasmOp.REF_EQ) +public external fun wasm_ref_eq(a: Any?, b: Any?): Boolean + + +// --- + +@WasmOp(WasmOp.F32_NEAREST) +public external fun wasm_f32_nearest(a: Float): Float + +@WasmOp(WasmOp.F64_NEAREST) +public external fun wasm_f64_nearest(a: Double): Double + +@WasmOp(WasmOp.I32_WRAP_I64) +public external fun wasm_i32_wrap_i64(a: Long): Int + +@WasmOp(WasmOp.I64_EXTEND_I32_S) +public external fun wasm_i64_extend_i32_s(a: Int): Long + +@WasmOp(WasmOp.F32_CONVERT_I32_S) +public external fun wasm_f32_convert_i32_s(a: Int): Float + +@WasmOp(WasmOp.F32_CONVERT_I64_S) +public external fun wasm_f32_convert_i64_s(a: Long): Float + +@WasmOp(WasmOp.F32_DEMOTE_F64) +public external fun wasm_f32_demote_f64(a: Double): Float + +@WasmOp(WasmOp.F64_CONVERT_I32_S) +public external fun wasm_f64_convert_i32_s(a: Int): Double + +@WasmOp(WasmOp.F64_CONVERT_I64_S) +public external fun wasm_f64_convert_i64_s(a: Long): Double + +@WasmOp(WasmOp.F64_PROMOTE_F32) +public external fun wasm_f64_promote_f32(a: Float): Double + +@WasmOp(WasmOp.I32_REINTERPRET_F32) +public external fun wasm_i32_reinterpret_f32(a: Float): Int + +@WasmOp(WasmOp.F32_REINTERPRET_I32) +public external fun wasm_f32_reinterpret_i32(a: Int): Float + +@WasmOp(WasmOp.I32_TRUNC_SAT_F32_S) +public external fun wasm_i32_trunc_sat_f32_s(a: Float): Int + +@WasmOp(WasmOp.I32_TRUNC_SAT_F64_S) +public external fun wasm_i32_trunc_sat_f64_s(a: Double): Int + +@WasmOp(WasmOp.I64_TRUNC_SAT_F32_S) +public external fun wasm_i64_trunc_sat_f32_s(a: Float): Long + +@WasmOp(WasmOp.I64_TRUNC_SAT_F64_S) +public external fun wasm_i64_trunc_sat_f64_s(a: Double): Long + +@WasmOp(WasmOp.I32_LOAD) +public external fun wasm_i32_load(x: Int): Int \ No newline at end of file diff --git a/libraries/stdlib/wasm/runtime/runtime.js b/libraries/stdlib/wasm/runtime/runtime.js index 453739330c5..85e0786bb3a 100644 --- a/libraries/stdlib/wasm/runtime/runtime.js +++ b/libraries/stdlib/wasm/runtime/runtime.js @@ -39,7 +39,62 @@ const runtime = { return 0; }, + /** + * @return {boolean} + */ + String_equals(str, other) { + // if (typeof str != "string") throw `Illegal argument str: ${str}`; + return str === other; + }, + + /** + * @return {string} + */ + String_subsequence(str, startIndex, endIndex) { + return str.substring(startIndex, endIndex); + }, + String_getLiteral(index) { return runtime.stringLiterals[index]; + }, + + coerceToString(value) { + return String(value); + }, + + /** + * @return {string} + */ + Char_toString(char) { + return String.fromCharCode(char) + }, + + JsArray_new(size) { + if (typeof size != "number") throw `Illegal argument size: ${size}`; + return new Array(size); + }, + + JsArray_get(array, index) { + if (typeof index != "number") throw `Illegal argument index: ${index}`; + if (array.length <= index) throw `Index out of bounds: index=${index} length=${array.length}`; + return array[index]; + }, + + JsArray_set(array, index, value) { + if (typeof index != "number") throw `Illegal argument index: ${index}`; + if (array.length <= index) throw `Index out of bounds: index=${index} length=${array.length}`; + array[index] = value; + }, + + JsArray_getSize(array) { + return array.length; + }, + + identity(x) { + return x; + }, + + println(value) { + console.log(">>> " + value) } }; \ No newline at end of file diff --git a/libraries/stdlib/wasm/runtime/runtime.kt b/libraries/stdlib/wasm/runtime/runtime.kt deleted file mode 100644 index a77b3ef53d2..00000000000 --- a/libraries/stdlib/wasm/runtime/runtime.kt +++ /dev/null @@ -1,10 +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.wasm.internal - -@WasmImport("runtime", "String_getLiteral") -public fun stringLiteral(index: Int): String = - implementedAsIntrinsic \ No newline at end of file diff --git a/libraries/stdlib/wasm/runtime/testHelpers.kt b/libraries/stdlib/wasm/runtime/testHelpers.kt deleted file mode 100644 index fa2d30a86d8..00000000000 --- a/libraries/stdlib/wasm/runtime/testHelpers.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package kotlin - -import kotlin.wasm.internal.wasm_unreachable - -fun assertEquals(x: Boolean, y: Boolean) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Byte, y: Byte) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Short, y: Short) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Char, y: Char) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Int, y: Int) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Long, y: Long) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Float, y: Float) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Double, y: Double) { - if (x != y) wasm_unreachable() -} - - -fun assertEquals(x: Boolean, y: Boolean, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Byte, y: Byte, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Short, y: Short, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Char, y: Char, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Int, y: Int, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Long, y: Long, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Float, y: Float, s: String) { - if (x != y) wasm_unreachable() -} -fun assertEquals(x: Double, y: Double, s: String) { - if (x != y) wasm_unreachable() -} \ No newline at end of file diff --git a/libraries/stdlib/wasm/runtime/wasmAnnotations.kt b/libraries/stdlib/wasm/runtime/wasmAnnotations.kt deleted file mode 100644 index 6ec72a60151..00000000000 --- a/libraries/stdlib/wasm/runtime/wasmAnnotations.kt +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. - * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. - */ - -package kotlin.wasm.internal - -import kotlin.annotation.AnnotationTarget.* - -// Exclude declaration or file from lowerings and code generation -@Target(FILE, CLASS, FUNCTION, PROPERTY) -@Retention(AnnotationRetention.BINARY) -internal annotation class ExcludedFromCodegen - -@ExcludedFromCodegen -@Target(FUNCTION, PROPERTY_GETTER, PROPERTY_SETTER) -@Retention(AnnotationRetention.BINARY) -internal annotation class WasmImport(val module: String, val name: String) - -/** - * Replace calls to this functions with specified Wasm instruction. - * - * Operands are passed in the following order: - * 1. Dispatch receiver (if present) - * 2. Extension receiver (if present) - * 3. Value arguments - * - * @mnemonic parameter is an instruction WAT name: "i32.add", "f64.trunc", etc. - * - * Immediate arguments (label, index, offest, align, etc.) are not supported yet. - */ -@Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.BINARY) -@ExcludedFromCodegen -internal annotation class WasmInstruction(val mnemonic: String) { - companion object { - const val NOP = "nop" - const val UNREACHABLE = "unreachable" - const val I32_EQZ = "i32.eqz" - const val I32_EQ = "i32.eq" - const val I32_NE = "i32.ne" - const val I32_LT_S = "i32.lt_s" - const val I32_LT_U = "i32.lt_u" - const val I32_GT_S = "i32.gt_s" - const val I32_GT_U = "i32.gt_u" - const val I32_LE_S = "i32.le_s" - const val I32_LE_U = "i32.le_u" - const val I32_GE_S = "i32.ge_s" - const val I32_GE_U = "i32.ge_u" - const val I64_EQZ = "i64.eqz" - const val I64_EQ = "i64.eq" - const val I64_NE = "i64.ne" - const val I64_LT_S = "i64.lt_s" - const val I64_LT_U = "i64.lt_u" - const val I64_GT_S = "i64.gt_s" - const val I64_GT_U = "i64.gt_u" - const val I64_LE_S = "i64.le_s" - const val I64_LE_U = "i64.le_u" - const val I64_GE_S = "i64.ge_s" - const val I64_GE_U = "i64.ge_u" - const val F32_EQ = "f32.eq" - const val F32_NE = "f32.ne" - const val F32_LT = "f32.lt" - const val F32_GT = "f32.gt" - const val F32_LE = "f32.le" - const val F32_GE = "f32.ge" - const val F64_EQ = "f64.eq" - const val F64_NE = "f64.ne" - const val F64_LT = "f64.lt" - const val F64_GT = "f64.gt" - const val F64_LE = "f64.le" - const val F64_GE = "f64.ge" - const val I32_CLZ = "i32.clz" - const val I32_CTZ = "i32.ctz" - const val I32_POPCNT = "i32.popcnt" - const val I32_ADD = "i32.add" - const val I32_SUB = "i32.sub" - const val I32_MUL = "i32.mul" - const val I32_DIV_S = "i32.div_s" - const val I32_DIV_U = "i32.div_u" - const val I32_REM_S = "i32.rem_s" - const val I32_REM_U = "i32.rem_u" - const val I32_AND = "i32.and" - const val I32_OR = "i32.or" - const val I32_XOR = "i32.xor" - const val I32_SHL = "i32.shl" - const val I32_SHR_S = "i32.shr_s" - const val I32_SHR_U = "i32.shr_u" - const val I32_ROTL = "i32.rotl" - const val I32_ROTR = "i32.rotr" - const val I64_CLZ = "i64.clz" - const val I64_CTZ = "i64.ctz" - const val I64_POPCNT = "i64.popcnt" - const val I64_ADD = "i64.add" - const val I64_SUB = "i64.sub" - const val I64_MUL = "i64.mul" - const val I64_DIV_S = "i64.div_s" - const val I64_DIV_U = "i64.div_u" - const val I64_REM_S = "i64.rem_s" - const val I64_REM_U = "i64.rem_u" - const val I64_AND = "i64.and" - const val I64_OR = "i64.or" - const val I64_XOR = "i64.xor" - const val I64_SHL = "i64.shl" - const val I64_SHR_S = "i64.shr_s" - const val I64_SHR_U = "i64.shr_u" - const val I64_ROTL = "i64.rotl" - const val I64_ROTR = "i64.rotr" - const val F32_ABS = "f32.abs" - const val F32_NEG = "f32.neg" - const val F32_CEIL = "f32.ceil" - const val F32_FLOOR = "f32.floor" - const val F32_TRUNC = "f32.trunc" - const val F32_NEAREST = "f32.nearest" - const val F32_SQRT = "f32.sqrt" - const val F32_ADD = "f32.add" - const val F32_SUB = "f32.sub" - const val F32_MUL = "f32.mul" - const val F32_DIV = "f32.div" - const val F32_FMIN = "f32.fmin" - const val F32_FMAX = "f32.fmax" - const val F32_COPYSIGN = "f32.copysign" - const val F64_ABS = "f64.abs" - const val F64_NEG = "f64.neg" - const val F64_CEIL = "f64.ceil" - const val F64_FLOOR = "f64.floor" - const val F64_TRUNC = "f64.trunc" - const val F64_NEAREST = "f64.nearest" - const val F64_SQRT = "f64.sqrt" - const val F64_ADD = "f64.add" - const val F64_SUB = "f64.sub" - const val F64_MUL = "f64.mul" - const val F64_DIV = "f64.div" - const val F64_FMIN = "f64.fmin" - const val F64_FMAX = "f64.fmax" - const val F64_COPYSIGN = "f64.copysign" - const val I32_WRAP_I64 = "i32.wrap/i64" - const val I32_TRUNC_F32_S = "i32.trunc_s/f32" - const val I32_TRUNC_F32_U = "i32.trunc_u/f32" - const val I32_TRUNC_F64_S = "i32.trunc_s/f64" - const val I32_TRUNC_F64_U = "i32.trunc_u/f64" - const val I64_EXTEND_I32_S = "i64.extend_s/i32" - const val I64_EXTEND_I32_U = "i64.extend_u/i32" - const val I64_TRUNC_F32_S = "i64.trunc_s/f32" - const val I64_TRUNC_F32_U = "i64.trunc_u/f32" - const val I64_TRUNC_F64_S = "i64.trunc_s/f64" - const val I64_TRUNC_F64_U = "i64.trunc_u/f64" - const val F32_CONVERT_I32_S = "f32.convert_s/i32" - const val F32_CONVERT_I32_U = "f32.convert_u/i32" - const val F32_CONVERT_I64_S = "f32.convert_s/i64" - const val F32_CONVERT_I64_U = "f32.convert_u/i64" - const val F64_CONVERT_I32_S = "f64.convert_s/i32" - const val F64_CONVERT_I32_U = "f64.convert_u/i32" - const val F64_CONVERT_I64_S = "f64.convert_s/i64" - const val F64_CONVERT_I64_U = "f64.convert_u/i64" - const val F32_DEMOTE_F64 = "f32.demote/f64" - const val F64_PROMOTE_F32 = "f64.promote/f32" - const val I32_REINTERPRET_F32 = "i32.reinterpret/f32" - const val I64_REINTERPRET_F64 = "i64.reinterpret/f64" - const val F32_REINTERPRET_I32 = "f32.reinterpret/i32" - - const val F32_CONST_NAN = "f32.const nan" - const val F64_CONST_NAN = "f64.const nan" - const val F32_CONST_PLUS_INF = "f32.const +inf" - const val F32_CONST_MINUS_INF = "f32.const -inf" - const val F64_CONST_PLUS_INF = "f64.const +inf" - const val F64_CONST_MINUS_INF = "f64.const -inf" - } -} - -@ExcludedFromCodegen -internal val implementedAsIntrinsic: Nothing - get() = null!! \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/generated/_ArraysWasm.kt b/libraries/stdlib/wasm/src/generated/_ArraysWasm.kt new file mode 100644 index 00000000000..df7fd477c9a --- /dev/null +++ b/libraries/stdlib/wasm/src/generated/_ArraysWasm.kt @@ -0,0 +1,2408 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.elementAt(index: Int): T { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun ByteArray.elementAt(index: Int): Byte { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun ShortArray.elementAt(index: Int): Short { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun IntArray.elementAt(index: Int): Int { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun LongArray.elementAt(index: Int): Long { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun FloatArray.elementAt(index: Int): Float { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun DoubleArray.elementAt(index: Int): Double { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun BooleanArray.elementAt(index: Int): Boolean { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun CharArray.elementAt(index: Int): Char { + return get(index) +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun Array.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: T): Boolean = this@asList.contains(element) + override fun get(index: Int): T = this@asList[index] + override fun indexOf(element: T): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: T): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun ByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Byte): Boolean = this@asList.contains(element) + override fun get(index: Int): Byte = this@asList[index] + override fun indexOf(element: Byte): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Byte): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun ShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Short): Boolean = this@asList.contains(element) + override fun get(index: Int): Short = this@asList[index] + override fun indexOf(element: Short): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Short): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun IntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Int): Boolean = this@asList.contains(element) + override fun get(index: Int): Int = this@asList[index] + override fun indexOf(element: Int): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Int): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun LongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Long): Boolean = this@asList.contains(element) + override fun get(index: Int): Long = this@asList[index] + override fun indexOf(element: Long): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Long): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun FloatArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Float): Boolean = this@asList.any { it.toBits() == element.toBits() } + override fun get(index: Int): Float = this@asList[index] + override fun indexOf(element: Float): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Float): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun DoubleArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Double): Boolean = this@asList.any { it.toBits() == element.toBits() } + override fun get(index: Int): Double = this@asList[index] + override fun indexOf(element: Double): Int = this@asList.indexOfFirst { it.toBits() == element.toBits() } + override fun lastIndexOf(element: Double): Int = this@asList.indexOfLast { it.toBits() == element.toBits() } + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun BooleanArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Boolean): Boolean = this@asList.contains(element) + override fun get(index: Int): Boolean = this@asList[index] + override fun indexOf(element: Boolean): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Boolean): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +public actual fun CharArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: Char): Boolean = this@asList.contains(element) + override fun get(index: Int): Char = this@asList[index] + override fun indexOf(element: Char): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: Char): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual infix fun Array.contentDeepEquals(other: Array): Boolean { + return this.contentDeepEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *deeply* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The specified arrays are also considered deeply equal if both are `null`. + * + * If two corresponding elements are nested arrays, they are also compared deeply. + * If any of arrays contains itself on any nesting level the behavior is undefined. + * + * The elements of other types are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentDeepEquals(other: Array?): Boolean { + return contentDeepEqualsImpl(other) +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual fun Array.contentDeepHashCode(): Int { + return this.contentDeepHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepHashCode(): Int { + return contentDeepHashCodeImpl() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.1") +@kotlin.internal.LowPriorityInOverloadResolution +public actual fun Array.contentDeepToString(): String { + return this.contentDeepToString() +} + +/** + * Returns a string representation of the contents of this array as if it is a [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level that reference + * is rendered as `"[...]"` to prevent recursion. + * + * @sample samples.collections.Arrays.ContentOperations.contentDeepToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentDeepToString(): String { + return contentDeepToStringImpl() +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun Array.contentEquals(other: Array): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun ByteArray.contentEquals(other: ByteArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun ShortArray.contentEquals(other: ShortArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun IntArray.contentEquals(other: IntArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun LongArray.contentEquals(other: LongArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun FloatArray.contentEquals(other: FloatArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun DoubleArray.contentEquals(other: DoubleArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun BooleanArray.contentEquals(other: BooleanArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual infix fun CharArray.contentEquals(other: CharArray): Boolean { + return this.contentEquals(other) +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun Array?.contentEquals(other: Array?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ByteArray?.contentEquals(other: ByteArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun ShortArray?.contentEquals(other: ShortArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun IntArray?.contentEquals(other: IntArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun LongArray?.contentEquals(other: LongArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun FloatArray?.contentEquals(other: FloatArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (!this[i].equals(other[i])) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun DoubleArray?.contentEquals(other: DoubleArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (!this[i].equals(other[i])) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun BooleanArray?.contentEquals(other: BooleanArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns `true` if the two specified arrays are *structurally* equal to one another, + * i.e. contain the same number of the same elements in the same order. + * + * The elements are compared for equality with the [equals][Any.equals] function. + * For floating point numbers it means that `NaN` is equal to itself and `-0.0` is not equal to `0.0`. + */ +@SinceKotlin("1.4") +public actual infix fun CharArray?.contentEquals(other: CharArray?): Boolean { + if (this === other) return true + if (this === null || other === null) return false + if (size != other.size) return false + for (i in indices) { + if (this[i] != other[i]) return false + } + return true +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun Array.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ByteArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ShortArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun IntArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun LongArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun FloatArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun DoubleArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun BooleanArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun CharArray.contentHashCode(): Int { + return this.contentHashCode() +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun Array?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentHashCode(): Int { + if (this === null) return 0 + var result = 1 + for (element in this) + result = 31 * result + element.hashCode() + return result +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun Array.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ByteArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun ShortArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun IntArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun LongArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun FloatArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun DoubleArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun BooleanArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@Deprecated("Use Kotlin compiler 1.4 to avoid deprecation warning.") +@SinceKotlin("1.1") +@DeprecatedSinceKotlin(hiddenSince = "1.4") +public actual fun CharArray.contentToString(): String { + return this.contentToString() +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun Array?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ByteArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun ShortArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun IntArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun LongArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun FloatArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun DoubleArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun BooleanArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Returns a string representation of the contents of the specified array as if it is [List]. + * + * @sample samples.collections.Arrays.ContentOperations.contentToString + */ +@SinceKotlin("1.4") +public actual fun CharArray?.contentToString(): String { + return this?.joinToString(", ", "[", "]") ?: "null" +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.copyInto(destination: Array, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): Array { + TODO("Wasm stdlib: copyInto(destination: Array, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.copyInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): ByteArray { + TODO("Wasm stdlib: copyInto(destination: ByteArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.copyInto(destination: ShortArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): ShortArray { + TODO("Wasm stdlib: copyInto(destination: ShortArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.copyInto(destination: IntArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): IntArray { + TODO("Wasm stdlib: copyInto(destination: IntArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.copyInto(destination: LongArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): LongArray { + TODO("Wasm stdlib: copyInto(destination: LongArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.copyInto(destination: FloatArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): FloatArray { + TODO("Wasm stdlib: copyInto(destination: FloatArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.copyInto(destination: DoubleArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): DoubleArray { + TODO("Wasm stdlib: copyInto(destination: DoubleArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun BooleanArray.copyInto(destination: BooleanArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): BooleanArray { + TODO("Wasm stdlib: copyInto(destination: BooleanArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Copies this array or its subrange into the [destination] array and returns that array. + * + * It's allowed to pass the same array in the [destination] and even specify the subrange so that it overlaps with the destination range. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the [destination] array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the subrange to copy, 0 by default. + * @param endIndex the end (exclusive) of the subrange to copy, size of this array by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + * + * @return the [destination] array. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.copyInto(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size): CharArray { + TODO("Wasm stdlib: copyInto(destination: CharArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size)") +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun Array.copyOf(): Array { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun ByteArray.copyOf(): ByteArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun ShortArray.copyOf(): ShortArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun IntArray.copyOf(): IntArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun LongArray.copyOf(): LongArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun FloatArray.copyOf(): FloatArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun DoubleArray.copyOf(): DoubleArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun BooleanArray.copyOf(): BooleanArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array. + * + * @sample samples.collections.Arrays.CopyOfOperations.copyOf + */ +public actual fun CharArray.copyOf(): CharArray { + return this.copyOfUninitializedElements(size) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun ByteArray.copyOf(newSize: Int): ByteArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun ShortArray.copyOf(newSize: Int): ShortArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun IntArray.copyOf(newSize: Int): IntArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun LongArray.copyOf(newSize: Int): LongArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun FloatArray.copyOf(newSize: Int): FloatArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with zero values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with zero values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun DoubleArray.copyOf(newSize: Int): DoubleArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with `false` values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with `false` values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun BooleanArray.copyOf(newSize: Int): BooleanArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with null char (`\u0000`) values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with null char (`\u0000`) values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizedPrimitiveCopyOf + */ +public actual fun CharArray.copyOf(newSize: Int): CharArray { + return this.copyOfUninitializedElements(newSize) +} + +/** + * Returns new array which is a copy of the original array, resized to the given [newSize]. + * The copy is either truncated or padded at the end with `null` values if necessary. + * + * - If [newSize] is less than the size of the original array, the copy array is truncated to the [newSize]. + * - If [newSize] is greater than the size of the original array, the extra elements in the copy array are filled with `null` values. + * + * @sample samples.collections.Arrays.CopyOfOperations.resizingCopyOf + */ +public actual fun Array.copyOf(newSize: Int): Array { + TODO("Wasm stdlib: copyOf(newSize: Int)") +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun Array.copyOfRange(fromIndex: Int, toIndex: Int): Array { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun ByteArray.copyOfRange(fromIndex: Int, toIndex: Int): ByteArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun ShortArray.copyOfRange(fromIndex: Int, toIndex: Int): ShortArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun IntArray.copyOfRange(fromIndex: Int, toIndex: Int): IntArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun LongArray.copyOfRange(fromIndex: Int, toIndex: Int): LongArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun FloatArray.copyOfRange(fromIndex: Int, toIndex: Int): FloatArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun DoubleArray.copyOfRange(fromIndex: Int, toIndex: Int): DoubleArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun BooleanArray.copyOfRange(fromIndex: Int, toIndex: Int): BooleanArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns a new array which is a copy of the specified range of the original array. + * + * @param fromIndex the start of the range (inclusive) to copy. + * @param toIndex the end of the range (exclusive) to copy. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +public actual fun CharArray.copyOfRange(fromIndex: Int, toIndex: Int): CharArray { + checkCopyOfRangeArguments(fromIndex, toIndex, size) + return copyOfUninitializedElements(fromIndex, toIndex) +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): Array { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ByteArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): ByteArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ShortArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): ShortArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun IntArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): IntArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun LongArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): LongArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun FloatArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): FloatArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun DoubleArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): DoubleArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun BooleanArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): BooleanArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array's range between [fromIndex] (inclusive) + * and [toIndex] (exclusive) with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun CharArray.copyOfUninitializedElements(fromIndex: Int, toIndex: Int): CharArray { + TODO("Wasm stdlib: copyOfUninitializedElements(fromIndex: Int, toIndex: Int)") +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun Array.copyOfUninitializedElements(newSize: Int): Array { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ByteArray.copyOfUninitializedElements(newSize: Int): ByteArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun ShortArray.copyOfUninitializedElements(newSize: Int): ShortArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun IntArray.copyOfUninitializedElements(newSize: Int): IntArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun LongArray.copyOfUninitializedElements(newSize: Int): LongArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun FloatArray.copyOfUninitializedElements(newSize: Int): FloatArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun DoubleArray.copyOfUninitializedElements(newSize: Int): DoubleArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun BooleanArray.copyOfUninitializedElements(newSize: Int): BooleanArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Returns new array which is a copy of the original array with new elements filled with **lateinit** _uninitialized_ values. + * Attempts to read _uninitialized_ values from this array work in implementation-dependent manner, + * either throwing exception or returning some kind of implementation-specific default value. + */ +internal fun CharArray.copyOfUninitializedElements(newSize: Int): CharArray { + return copyOfUninitializedElements(0, newSize) +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.fill(element: T, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: T, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Byte, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.fill(element: Short, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Short, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.fill(element: Int, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Int, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.fill(element: Long, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Long, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.fill(element: Float, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Float, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.fill(element: Double, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Double, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun BooleanArray.fill(element: Boolean, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Boolean, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Fills this array or its subrange with the specified [element] value. + * + * @param fromIndex the start of the range (inclusive) to fill, 0 by default. + * @param toIndex the end of the range (exclusive) to fill, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@SinceKotlin("1.3") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.fill(element: Char, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: fill(element: Char, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun Array.plus(element: T): Array { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ByteArray.plus(element: Byte): ByteArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun ShortArray.plus(element: Short): ShortArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun IntArray.plus(element: Int): IntArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun LongArray.plus(element: Long): LongArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun FloatArray.plus(element: Float): FloatArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun DoubleArray.plus(element: Double): DoubleArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun BooleanArray.plus(element: Boolean): BooleanArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +public actual operator fun CharArray.plus(element: Char): CharArray { + val index = size + val result = copyOfUninitializedElements(index + 1) + result[index] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun Array.plus(elements: Collection): Array { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ByteArray.plus(elements: Collection): ByteArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun ShortArray.plus(elements: Collection): ShortArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun IntArray.plus(elements: Collection): IntArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun LongArray.plus(elements: Collection): LongArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun FloatArray.plus(elements: Collection): FloatArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun DoubleArray.plus(elements: Collection): DoubleArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun BooleanArray.plus(elements: Collection): BooleanArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] collection. + */ +public actual operator fun CharArray.plus(elements: Collection): CharArray { + var index = size + val result = copyOfUninitializedElements(index + elements.size) + for (element in elements) result[index++] = element + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun Array.plus(elements: Array): Array { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ByteArray.plus(elements: ByteArray): ByteArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun ShortArray.plus(elements: ShortArray): ShortArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun IntArray.plus(elements: IntArray): IntArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun LongArray.plus(elements: LongArray): LongArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun FloatArray.plus(elements: FloatArray): FloatArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun DoubleArray.plus(elements: DoubleArray): DoubleArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun BooleanArray.plus(elements: BooleanArray): BooleanArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then all elements of the given [elements] array. + */ +public actual operator fun CharArray.plus(elements: CharArray): CharArray { + val thisSize = size + val arraySize = elements.size + val result = copyOfUninitializedElements(thisSize + arraySize) + elements.copyInto(result, thisSize) + return result +} + +/** + * Returns an array containing all elements of the original array and then the given [element]. + */ +@kotlin.internal.InlineOnly +public actual inline fun Array.plusElement(element: T): Array { + return plus(element) +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun IntArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun LongArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun ByteArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun ShortArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun DoubleArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun FloatArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place. + * + * @sample samples.collections.Arrays.Sorting.sortArray + */ +public actual fun CharArray.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts the array in-place according to the natural order of its elements. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @sample samples.collections.Arrays.Sorting.sortArrayOfComparable + */ +public actual fun > Array.sort(): Unit { + TODO("Wasm stdlib: sort()") +} + +/** + * Sorts a range in the array in-place. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArrayOfComparable + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun > Array.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ByteArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun ShortArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun IntArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun LongArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun FloatArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun DoubleArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts a range in the array in-place. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + * + * @sample samples.collections.Arrays.Sorting.sortRangeOfArray + */ +@SinceKotlin("1.4") +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun CharArray.sort(fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sort(fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Sorts the array in-place according to the order specified by the given [comparator]. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + */ +public actual fun Array.sortWith(comparator: Comparator): Unit { + TODO("Wasm stdlib: sortWith(comparator: Comparator)") +} + +/** + * Sorts a range in the array in-place with the given [comparator]. + * + * The sort is _stable_. It means that equal elements preserve their order relative to each other after sorting. + * + * @param fromIndex the start of the range (inclusive) to sort, 0 by default. + * @param toIndex the end of the range (exclusive) to sort, size of this array by default. + * + * @throws IndexOutOfBoundsException if [fromIndex] is less than zero or [toIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [fromIndex] is greater than [toIndex]. + */ +@Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") +public actual fun Array.sortWith(comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size): Unit { + TODO("Wasm stdlib: sortWith(comparator: Comparator, fromIndex: Int = 0, toIndex: Int = size)") +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ByteArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun ShortArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun IntArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun LongArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun FloatArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun DoubleArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun BooleanArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + +/** + * Returns a *typed* object array containing all of the elements of this primitive array. + */ +public actual fun CharArray.toTypedArray(): Array { + return Array(size) { index -> this[index] } +} + diff --git a/libraries/stdlib/wasm/src/generated/_CollectionsWasm.kt b/libraries/stdlib/wasm/src/generated/_CollectionsWasm.kt new file mode 100644 index 00000000000..776281e0520 --- /dev/null +++ b/libraries/stdlib/wasm/src/generated/_CollectionsWasm.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Reverses elements in the list in-place. + */ +public actual fun MutableList.reverse(): Unit { + val midPoint = (size / 2) - 1 + if (midPoint < 0) return + var reverseIndex = lastIndex + for (index in 0..midPoint) { + val tmp = this[index] + this[index] = this[reverseIndex] + this[reverseIndex] = tmp + reverseIndex-- + } +} + diff --git a/libraries/stdlib/wasm/src/generated/_ComparisonsWasm.kt b/libraries/stdlib/wasm/src/generated/_ComparisonsWasm.kt new file mode 100644 index 00000000000..d19edc4f00b --- /dev/null +++ b/libraries/stdlib/wasm/src/generated/_ComparisonsWasm.kt @@ -0,0 +1,445 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.comparisons + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + + +/** + * Returns the greater of two values. + * + * If values are equal, returns the first one. + */ +@SinceKotlin("1.1") +public actual fun > maxOf(a: T, b: T): T { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Byte, b: Byte): Byte { + return maxOf(a.toInt(), b.toInt()).toByte() +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Short, b: Short): Short { + return maxOf(a.toInt(), b.toInt()).toShort() +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Int, b: Int): Int { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Long, b: Long): Long { + return if (a >= b) a else b +} + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Float, b: Float): Float { + return if (a.compareTo(b) >= 0) a else b +} + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Double, b: Double): Double { + return if (a.compareTo(b) >= 0) a else b +} + +/** + * Returns the greater of three values. + * + * If there are multiple equal maximal values, returns the first of them. + */ +@SinceKotlin("1.1") +public actual fun > maxOf(a: T, b: T, c: T): T { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Byte, b: Byte, c: Byte): Byte { + return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toByte() +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Short, b: Short, c: Short): Short { + return maxOf(a.toInt(), maxOf(b.toInt(), c.toInt())).toShort() +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Int, b: Int, c: Int): Int { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Long, b: Long, c: Long): Long { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Float, b: Float, c: Float): Float { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun maxOf(a: Double, b: Double, c: Double): Double { + return maxOf(a, maxOf(b, c)) +} + +/** + * Returns the greater of the given values. + * + * If there are multiple equal maximal values, returns the first of them. + */ +@SinceKotlin("1.4") +public actual fun > maxOf(a: T, vararg other: T): T { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Byte, vararg other: Byte): Byte { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Short, vararg other: Short): Short { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Int, vararg other: Int): Int { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Long, vararg other: Long): Long { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Float, vararg other: Float): Float { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the greater of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun maxOf(a: Double, vararg other: Double): Double { + var max = a + for (e in other) max = maxOf(max, e) + return max +} + +/** + * Returns the smaller of two values. + * + * If values are equal, returns the first one. + */ +@SinceKotlin("1.1") +public actual fun > minOf(a: T, b: T): T { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Byte, b: Byte): Byte { + return minOf(a.toInt(), b.toInt()).toByte() +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Short, b: Short): Short { + return minOf(a.toInt(), b.toInt()).toShort() +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Int, b: Int): Int { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Long, b: Long): Long { + return if (a <= b) a else b +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Float, b: Float): Float { + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> if (a.compareTo(b) <= 0) a else b + } +} + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Double, b: Double): Double { + return when { + a.isNaN() -> a + b.isNaN() -> b + else -> if (a.compareTo(b) <= 0) a else b + } +} + +/** + * Returns the smaller of three values. + * + * If there are multiple equal minimal values, returns the first of them. + */ +@SinceKotlin("1.1") +public actual fun > minOf(a: T, b: T, c: T): T { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Byte, b: Byte, c: Byte): Byte { + return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toByte() +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Short, b: Short, c: Short): Short { + return minOf(a.toInt(), minOf(b.toInt(), c.toInt())).toShort() +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Int, b: Int, c: Int): Int { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Long, b: Long, c: Long): Long { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Float, b: Float, c: Float): Float { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of three values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public actual inline fun minOf(a: Double, b: Double, c: Double): Double { + return minOf(a, minOf(b, c)) +} + +/** + * Returns the smaller of the given values. + * + * If there are multiple equal minimal values, returns the first of them. + */ +@SinceKotlin("1.4") +public actual fun > minOf(a: T, vararg other: T): T { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Byte, vararg other: Byte): Byte { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Short, vararg other: Short): Short { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Int, vararg other: Int): Int { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Long, vararg other: Long): Long { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Float, vararg other: Float): Float { + var min = a + for (e in other) min = minOf(min, e) + return min +} + +/** + * Returns the smaller of the given values. + * + * If any value is `NaN`, returns `NaN`. + */ +@SinceKotlin("1.4") +public actual fun minOf(a: Double, vararg other: Double): Double { + var min = a + for (e in other) min = minOf(min, e) + return min +} + diff --git a/libraries/stdlib/wasm/src/generated/_StringsWasm.kt b/libraries/stdlib/wasm/src/generated/_StringsWasm.kt new file mode 100644 index 00000000000..9ed5b20ff09 --- /dev/null +++ b/libraries/stdlib/wasm/src/generated/_StringsWasm.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + + +/** + * Returns a character at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this char sequence. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@kotlin.internal.InlineOnly +public actual inline fun CharSequence.elementAt(index: Int): Char { + return get(index) +} + diff --git a/libraries/stdlib/wasm/src/generated/_UArraysWasm.kt b/libraries/stdlib/wasm/src/generated/_UArraysWasm.kt new file mode 100644 index 00000000000..a42075114c8 --- /dev/null +++ b/libraries/stdlib/wasm/src/generated/_UArraysWasm.kt @@ -0,0 +1,127 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +// +// NOTE: THIS FILE IS AUTO-GENERATED by the GenerateStandardLib.kt +// See: https://github.com/JetBrains/kotlin/tree/master/libraries/stdlib +// + +import kotlin.ranges.contains +import kotlin.ranges.reversed + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UIntArray.elementAt(index: Int): UInt { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun ULongArray.elementAt(index: Int): ULong { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UByteArray.elementAt(index: Int): UByte { + return get(index) +} + +/** + * Returns an element at the given [index] or throws an [IndexOutOfBoundsException] if the [index] is out of bounds of this array. + * + * @sample samples.collections.Collections.Elements.elementAt + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +@kotlin.internal.InlineOnly +public actual inline fun UShortArray.elementAt(index: Int): UShort { + return get(index) +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UIntArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UInt): Boolean = this@asList.contains(element) + override fun get(index: Int): UInt = this@asList[index] + override fun indexOf(element: UInt): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UInt): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun ULongArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: ULong): Boolean = this@asList.contains(element) + override fun get(index: Int): ULong = this@asList[index] + override fun indexOf(element: ULong): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: ULong): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UByteArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UByte): Boolean = this@asList.contains(element) + override fun get(index: Int): UByte = this@asList[index] + override fun indexOf(element: UByte): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UByte): Int = this@asList.lastIndexOf(element) + } +} + +/** + * Returns a [List] that wraps the original array. + */ +@SinceKotlin("1.3") +@ExperimentalUnsignedTypes +public actual fun UShortArray.asList(): List { + return object : AbstractList(), RandomAccess { + override val size: Int get() = this@asList.size + override fun isEmpty(): Boolean = this@asList.isEmpty() + override fun contains(element: UShort): Boolean = this@asList.contains(element) + override fun get(index: Int): UShort = this@asList[index] + override fun indexOf(element: UShort): Int = this@asList.indexOf(element) + override fun lastIndexOf(element: UShort): Int = this@asList.lastIndexOf(element) + } +} + diff --git a/libraries/stdlib/wasm/src/kotlin/Exceptions.kt b/libraries/stdlib/wasm/src/kotlin/Exceptions.kt new file mode 100644 index 00000000000..82e33cbb565 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Exceptions.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + + +public actual open class Exception actual constructor(message: String?, cause: Throwable?) : Throwable(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class Error actual constructor(message: String?, cause: Throwable?) : Throwable(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class RuntimeException actual constructor(message: String?, cause: Throwable?) : Exception(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class IllegalArgumentException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class IllegalStateException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class IndexOutOfBoundsException actual constructor(message: String?) : RuntimeException(message) { + actual constructor() : this(null) +} + +public actual open class ConcurrentModificationException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class UnsupportedOperationException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + + +public actual open class NumberFormatException actual constructor(message: String?) : IllegalArgumentException(message) { + actual constructor() : this(null) +} + + +public actual open class NullPointerException actual constructor(message: String?) : RuntimeException(message) { + actual constructor() : this(null) +} + +public actual open class ClassCastException actual constructor(message: String?) : RuntimeException(message) { + actual constructor() : this(null) +} + +public actual open class AssertionError private constructor(message: String?, cause: Throwable?) : Error(message, cause) { + actual constructor() : this(null) + constructor(message: String?) : this(message, null) + actual constructor(message: Any?) : this(message.toString(), message as? Throwable) +} + +public actual open class NoSuchElementException actual constructor(message: String?) : RuntimeException(message) { + actual constructor() : this(null) +} + +@SinceKotlin("1.3") +public actual open class ArithmeticException actual constructor(message: String?) : RuntimeException(message) { + actual constructor() : this(null) +} + +public actual open class NoWhenBranchMatchedException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + +public actual open class UninitializedPropertyAccessException actual constructor(message: String?, cause: Throwable?) : RuntimeException(message, cause) { + actual constructor() : this(null, null) + actual constructor(message: String?) : this(message, null) + actual constructor(cause: Throwable?) : this(null, cause) +} + diff --git a/libraries/stdlib/wasm/src/kotlin/Kotlin.kt b/libraries/stdlib/wasm/src/kotlin/Kotlin.kt new file mode 100644 index 00000000000..d45631a5835 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Kotlin.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + +import kotlin.annotation.AnnotationTarget.FIELD +import kotlin.annotation.AnnotationTarget.PROPERTY + + +/** + * Provides a comparison function for imposing a total ordering between instances of the type [T]. + */ +public actual fun interface Comparator { + /** + * Compares its two arguments for order. Returns zero if the arguments are equal, + * a negative number if the first argument is less than the second, or a positive number + * if the first argument is greater than the second. + */ + public actual fun compare(a: T, b: T): Int +} + +// From kotlin.kt + + + +// From numbers.kt + +actual fun Double.isNaN(): Boolean = TODO("Wasm stdlib: Kotlin") +actual fun Float.isNaN(): Boolean = TODO("Wasm stdlib: Kotlin") +actual fun Double.isInfinite(): Boolean = TODO("Wasm stdlib: Kotlin") +actual fun Float.isInfinite(): Boolean = TODO("Wasm stdlib: Kotlin") +actual fun Double.isFinite(): Boolean = TODO("Wasm stdlib: Kotlin") +actual fun Float.isFinite(): Boolean = TODO("Wasm stdlib: Kotlin") + +/** + * Returns a bit representation of the specified floating-point value as [Long] + * according to the IEEE 754 floating-point "double format" bit layout. + */ +@SinceKotlin("1.2") +public actual fun Double.toBits(): Long = TODO("Wasm stdlib: Kotlin") + +/** + * Returns a bit representation of the specified floating-point value as [Long] + * according to the IEEE 754 floating-point "double format" bit layout, + * preserving `NaN` values exact layout. + */ +@SinceKotlin("1.2") +public actual fun Double.toRawBits(): Long = TODO("Wasm stdlib: Kotlin") + +/** + * Returns the [Double] value corresponding to a given bit representation. + */ +@SinceKotlin("1.2") +public actual fun Double.Companion.fromBits(bits: Long): Double = TODO("Wasm stdlib: Kotlin") + +/** + * Returns a bit representation of the specified floating-point value as [Int] + * according to the IEEE 754 floating-point "single format" bit layout. + */ +@SinceKotlin("1.2") +public actual fun Float.toBits(): Int = TODO("Wasm stdlib: Kotlin") + +/** + * Returns a bit representation of the specified floating-point value as [Int] + * according to the IEEE 754 floating-point "single format" bit layout, + * preserving `NaN` values exact layout. + */ +@SinceKotlin("1.2") +public actual fun Float.toRawBits(): Int = TODO("Wasm stdlib: Kotlin") + +/** + * Returns the [Float] value corresponding to a given bit representation. + */ +@SinceKotlin("1.2") +public actual fun Float.Companion.fromBits(bits: Int): Float = TODO("Wasm stdlib: Kotlin") + + +// From concurrent.kt + +// TODO: promote to error? Otherwise it gets to JVM part +//@Deprecated("Use Volatile annotation from kotlin.jvm package", ReplaceWith("kotlin.jvm.Volatile"), level = DeprecationLevel.WARNING) +//public typealias Volatile = kotlin.jvm.Volatile + +@Deprecated("Synchronization on any object is not supported on every platform and will be removed from the common standard library soon.") +public actual inline fun synchronized(lock: Any, block: () -> R): R = TODO("Wasm stdlib: Kotlin") + + + + +// from lazy.kt + +public actual fun lazy(initializer: () -> T): Lazy = TODO("Wasm stdlib: Kotlin") + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]. + * + * The [mode] parameter is ignored. */ +public actual fun lazy(mode: LazyThreadSafetyMode, initializer: () -> T): Lazy = TODO("Wasm stdlib: Kotlin") + +/** + * Creates a new instance of the [Lazy] that uses the specified initialization function [initializer]. + * + * The [lock] parameter is ignored. + */ +public actual fun lazy(lock: Any?, initializer: () -> T): Lazy = TODO("Wasm stdlib: Kotlin") diff --git a/libraries/stdlib/wasm/src/kotlin/Math.kt b/libraries/stdlib/wasm/src/kotlin/Math.kt new file mode 100644 index 00000000000..61843481e38 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Math.kt @@ -0,0 +1,990 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.math + + +// region ================ Double Math ======================================== + +/** Computes the sine of the angle [x] given in radians. + * + * Special cases: + * - `sin(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sin(x: Double): Double = TODO("Wasm stdlib: Math") + +/** Computes the cosine of the angle [x] given in radians. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun cos(x: Double): Double = TODO("Wasm stdlib: Math") + +/** Computes the tangent of the angle [x] given in radians. + * + * Special cases: + * - `tan(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun tan(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the arc sine of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `asin(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +public actual fun asin(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the arc cosine of the value [x]; + * the returned value is an angle in the range from `0.0` to `PI` radians. + * + * Special cases: + * - `acos(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +public actual fun acos(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the arc tangent of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `atan(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun atan(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond + * to the rectangular coordinates `(x, y)` by computing the arc tangent of the value [y] / [x]; + * the returned value is an angle in the range from `-PI` to `PI` radians. + * + * Special cases: + * - `atan2(0.0, 0.0)` is `0.0` + * - `atan2(0.0, x)` is `0.0` for `x > 0` and `PI` for `x < 0` + * - `atan2(-0.0, x)` is `-0.0` for 'x > 0` and `-PI` for `x < 0` + * - `atan2(y, +Inf)` is `0.0` for `0 < y < +Inf` and `-0.0` for '-Inf < y < 0` + * - `atan2(y, -Inf)` is `PI` for `0 < y < +Inf` and `-PI` for `-Inf < y < 0` + * - `atan2(y, 0.0)` is `PI/2` for `y > 0` and `-PI/2` for `y < 0` + * - `atan2(+Inf, x)` is `PI/2` for finite `x`y + * - `atan2(-Inf, x)` is `-PI/2` for finite `x` + * - `atan2(NaN, x)` and `atan2(y, NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun atan2(y: Double, x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic sine of the value [x]. + * + * Special cases: + * - `sinh(NaN)` is `NaN` + * - `sinh(+Inf)` is `+Inf` + * - `sinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun sinh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic cosine of the value [x]. + * + * Special cases: + * - `cosh(NaN)` is `NaN` + * - `cosh(+Inf|-Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +public actual fun cosh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic tangent of the value [x]. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(+Inf)` is `1.0` + * - `tanh(-Inf)` is `-1.0` + */ +@SinceKotlin("1.2") +public actual fun tanh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic sine of the value [x]. + * + * The returned value is `y` such that `sinh(y) == x`. + * + * Special cases: + * - `asinh(NaN)` is `NaN` + * - `asinh(+Inf)` is `+Inf` + * - `asinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun asinh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic cosine of the value [x]. + * + * The returned value is positive `y` such that `cosh(y) == x`. + * + * Special cases: + * - `acosh(NaN)` is `NaN` + * - `acosh(x)` is `NaN` when `x < 1` + * - `acosh(+Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +public actual fun acosh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic tangent of the value [x]. + * + * The returned value is `y` such that `tanh(y) == x`. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(x)` is `NaN` when `x > 1` or `x < -1` + * - `tanh(1.0)` is `+Inf` + * - `tanh(-1.0)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun atanh(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. + * + * Special cases: + * - returns `+Inf` if any of arguments is infinite + * - returns `NaN` if any of arguments is `NaN` and the other is not infinite + */ +@SinceKotlin("1.2") +public actual fun hypot(x: Double, y: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the positive square root of the value [x]. + * + * Special cases: + * - `sqrt(x)` is `NaN` when `x < 0` or `x` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sqrt(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes Euler's number `e` raised to the power of the value [x]. + * + * Special cases: + * - `exp(NaN)` is `NaN` + * - `exp(+Inf)` is `+Inf` + * - `exp(-Inf)` is `0.0` + */ +@SinceKotlin("1.2") +public actual fun exp(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes `exp(x) - 1`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `expm1(NaN)` is `NaN` + * - `expm1(+Inf)` is `+Inf` + * - `expm1(-Inf)` is `-1.0` + * + * @see [exp] function. + */ +@SinceKotlin("1.2") +public actual fun expm1(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the logarithm of the value [x] to the given [base]. + * + * Special cases: + * - `log(x, b)` is `NaN` if either `x` or `b` are `NaN` + * - `log(x, b)` is `NaN` when `x < 0` or `b <= 0` or `b == 1.0` + * - `log(+Inf, +Inf)` is `NaN` + * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` + * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` + * + * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + */ +@SinceKotlin("1.2") +public actual fun log(x: Double, base: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the natural logarithm (base `E`) of the value [x]. + * + * Special cases: + * - `ln(NaN)` is `NaN` + * - `ln(x)` is `NaN` when `x < 0.0` + * - `ln(+Inf)` is `+Inf` + * - `ln(0.0)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun ln(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the common logarithm (base 10) of the value [x]. + * + * @see [ln] function for special cases. + */ +@SinceKotlin("1.2") +public actual fun log10(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes the binary logarithm (base 2) of the value [x]. + * + * @see [ln] function for special cases. + */ +@SinceKotlin("1.2") +public actual fun log2(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Computes `ln(x + 1)`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `ln1p(NaN)` is `NaN` + * - `ln1p(x)` is `NaN` where `x < -1.0` + * - `ln1p(-1.0)` is `-Inf` + * - `ln1p(+Inf)` is `+Inf` + * + * @see [ln] function + * @see [expm1] function + */ +@SinceKotlin("1.2") +public actual fun ln1p(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards positive infinity. + + * @return the smallest double value that is greater than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `ceil(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun ceil(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards negative infinity. + + * @return the largest double value that is smaller than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `floor(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun floor(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards zero. + * + * @return the value [x] having its fractional part truncated. + * + * Special cases: + * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun truncate(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] towards the closest integer with ties rounded towards even integer. + * + * Special cases: + * - `round(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun round(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the absolute value of the given value [x]. + * + * Special cases: + * - `abs(NaN)` is `NaN` + * + * @see absoluteValue extension property for [Double] + */ +@SinceKotlin("1.2") +public actual fun abs(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of the given value [x]: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `sign(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sign(x: Double): Double = TODO("Wasm stdlib: Math") + + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun min(a: Double, b: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun max(a: Double, b: Double): Double = TODO("Wasm stdlib: Math") + +// extensions + +/** + * Raises this value to the power [x]. + * + * Special cases: + * - `b.pow(0.0)` is `1.0` + * - `b.pow(1.0) == b` + * - `b.pow(NaN)` is `NaN` + * - `NaN.pow(x)` is `NaN` for `x != 0.0` + * - `b.pow(Inf)` is `NaN` for `abs(b) == 1.0` + * - `b.pow(x)` is `NaN` for `b < 0` and `x` is finite and not an integer + */ +@SinceKotlin("1.2") +public actual fun Double.pow(x: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Raises this value to the integer power [n]. + * + * See the other overload of [pow] for details. + */ +@SinceKotlin("1.2") +public actual fun Double.pow(n: Int): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `NaN.absoluteValue` is `NaN` + * + * @see abs function + */ +@SinceKotlin("1.2") +public actual val Double.absoluteValue: Double get() = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of this value: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `NaN.sign` is `NaN` + */ +@SinceKotlin("1.2") +public actual val Double.sign: Double get() = TODO("Wasm stdlib: Math") + +/** + * Returns this value with the sign bit same as of the [sign] value. + * + * If [sign] is `NaN` the sign of the result is undefined. + */ +@SinceKotlin("1.2") +public actual fun Double.withSign(sign: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Returns this value with the sign bit same as of the [sign] value. + */ +@SinceKotlin("1.2") +public actual fun Double.withSign(sign: Int): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the ulp (unit in the last place) of this value. + * + * An ulp is a positive distance between this value and the next nearest [Double] value larger in magnitude. + * + * Special Cases: + * - `NaN.ulp` is `NaN` + * - `x.ulp` is `+Inf` when `x` is `+Inf` or `-Inf` + * - `0.0.ulp` is `Double.MIN_VALUE` + */ +@SinceKotlin("1.2") +public actual val Double.ulp: Double get() = TODO("Wasm stdlib: Math") + +/** + * Returns the [Double] value nearest to this value in direction of positive infinity. + */ +@SinceKotlin("1.2") +public actual fun Double.nextUp(): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the [Double] value nearest to this value in direction of negative infinity. + */ +@SinceKotlin("1.2") +public actual fun Double.nextDown(): Double = TODO("Wasm stdlib: Math") + +/** + * Returns the [Double] value nearest to this value in direction from this value towards the value [to]. + * + * Special cases: + * - `x.nextTowards(y)` is `NaN` if either `x` or `y` are `NaN` + * - `x.nextTowards(x) == x` + * + */ +@SinceKotlin("1.2") +public actual fun Double.nextTowards(to: Double): Double = TODO("Wasm stdlib: Math") + +/** + * Rounds this [Double] value to the nearest integer and converts the result to [Int]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToInt() == Int.MAX_VALUE` when `x > Int.MAX_VALUE` + * - `x.roundToInt() == Int.MIN_VALUE` when `x < Int.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Double.roundToInt(): Int = TODO("Wasm stdlib: Math") + +/** + * Rounds this [Double] value to the nearest integer and converts the result to [Long]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToLong() == Long.MAX_VALUE` when `x > Long.MAX_VALUE` + * - `x.roundToLong() == Long.MIN_VALUE` when `x < Long.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Double.roundToLong(): Long = TODO("Wasm stdlib: Math") + +// endregion + + + +// region ================ Float Math ======================================== + +/** Computes the sine of the angle [x] given in radians. + * + * Special cases: + * - `sin(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sin(x: Float): Float = TODO("Wasm stdlib: Math") + +/** Computes the cosine of the angle [x] given in radians. + * + * Special cases: + * - `cos(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun cos(x: Float): Float = TODO("Wasm stdlib: Math") + +/** Computes the tangent of the angle [x] given in radians. + * + * Special cases: + * - `tan(NaN|+Inf|-Inf)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun tan(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the arc sine of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `asin(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +public actual fun asin(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the arc cosine of the value [x]; + * the returned value is an angle in the range from `0.0` to `PI` radians. + * + * Special cases: + * - `acos(x)` is `NaN`, when `abs(x) > 1` or x is `NaN` + */ +@SinceKotlin("1.2") +public actual fun acos(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the arc tangent of the value [x]; + * the returned value is an angle in the range from `-PI/2` to `PI/2` radians. + * + * Special cases: + * - `atan(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun atan(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Returns the angle `theta` of the polar coordinates `(r, theta)` that correspond + * to the rectangular coordinates `(x, y)` by computing the arc tangent of the value [y] / [x]; + * the returned value is an angle in the range from `-PI` to `PI` radians. + * + * Special cases: + * - `atan2(0.0, 0.0)` is `0.0` + * - `atan2(0.0, x)` is `0.0` for `x > 0` and `PI` for `x < 0` + * - `atan2(-0.0, x)` is `-0.0` for 'x > 0` and `-PI` for `x < 0` + * - `atan2(y, +Inf)` is `0.0` for `0 < y < +Inf` and `-0.0` for '-Inf < y < 0` + * - `atan2(y, -Inf)` is `PI` for `0 < y < +Inf` and `-PI` for `-Inf < y < 0` + * - `atan2(y, 0.0)` is `PI/2` for `y > 0` and `-PI/2` for `y < 0` + * - `atan2(+Inf, x)` is `PI/2` for finite `x`y + * - `atan2(-Inf, x)` is `-PI/2` for finite `x` + * - `atan2(NaN, x)` and `atan2(y, NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun atan2(y: Float, x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic sine of the value [x]. + * + * Special cases: + * - `sinh(NaN)` is `NaN` + * - `sinh(+Inf)` is `+Inf` + * - `sinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun sinh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic cosine of the value [x]. + * + * Special cases: + * - `cosh(NaN)` is `NaN` + * - `cosh(+Inf|-Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +public actual fun cosh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the hyperbolic tangent of the value [x]. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(+Inf)` is `1.0` + * - `tanh(-Inf)` is `-1.0` + */ +@SinceKotlin("1.2") +public actual fun tanh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic sine of the value [x]. + * + * The returned value is `y` such that `sinh(y) == x`. + * + * Special cases: + * - `asinh(NaN)` is `NaN` + * - `asinh(+Inf)` is `+Inf` + * - `asinh(-Inf)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun asinh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic cosine of the value [x]. + * + * The returned value is positive `y` such that `cosh(y) == x`. + * + * Special cases: + * - `acosh(NaN)` is `NaN` + * - `acosh(x)` is `NaN` when `x < 1` + * - `acosh(+Inf)` is `+Inf` + */ +@SinceKotlin("1.2") +public actual fun acosh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the inverse hyperbolic tangent of the value [x]. + * + * The returned value is `y` such that `tanh(y) == x`. + * + * Special cases: + * - `tanh(NaN)` is `NaN` + * - `tanh(x)` is `NaN` when `x > 1` or `x < -1` + * - `tanh(1.0)` is `+Inf` + * - `tanh(-1.0)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun atanh(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes `sqrt(x^2 + y^2)` without intermediate overflow or underflow. + * + * Special cases: + * - returns `+Inf` if any of arguments is infinite + * - returns `NaN` if any of arguments is `NaN` and the other is not infinite + */ +@SinceKotlin("1.2") +public actual fun hypot(x: Float, y: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the positive square root of the value [x]. + * + * Special cases: + * - `sqrt(x)` is `NaN` when `x < 0` or `x` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sqrt(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes Euler's number `e` raised to the power of the value [x]. + * + * Special cases: + * - `exp(NaN)` is `NaN` + * - `exp(+Inf)` is `+Inf` + * - `exp(-Inf)` is `0.0` + */ +@SinceKotlin("1.2") +public actual fun exp(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes `exp(x) - 1`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `expm1(NaN)` is `NaN` + * - `expm1(+Inf)` is `+Inf` + * - `expm1(-Inf)` is `-1.0` + * + * @see [exp] function. + */ +@SinceKotlin("1.2") +public actual fun expm1(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the logarithm of the value [x] to the given [base]. + * + * Special cases: + * - `log(x, b)` is `NaN` if either `x` or `b` are `NaN` + * - `log(x, b)` is `NaN` when `x < 0` or `b <= 0` or `b == 1.0` + * - `log(+Inf, +Inf)` is `NaN` + * - `log(+Inf, b)` is `+Inf` for `b > 1` and `-Inf` for `b < 1` + * - `log(0.0, b)` is `-Inf` for `b > 1` and `+Inf` for `b > 1` + * + * See also logarithm functions for common fixed bases: [ln], [log10] and [log2]. + */ +@SinceKotlin("1.2") +public actual fun log(x: Float, base: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the natural logarithm (base `E`) of the value [x]. + * + * Special cases: + * - `ln(NaN)` is `NaN` + * - `ln(x)` is `NaN` when `x < 0.0` + * - `ln(+Inf)` is `+Inf` + * - `ln(0.0)` is `-Inf` + */ +@SinceKotlin("1.2") +public actual fun ln(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the common logarithm (base 10) of the value [x]. + * + * @see [ln] function for special cases. + */ +@SinceKotlin("1.2") +public actual fun log10(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes the binary logarithm (base 2) of the value [x]. + * + * @see [ln] function for special cases. + */ +@SinceKotlin("1.2") +public actual fun log2(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Computes `ln(a + 1)`. + * + * This function can be implemented to produce more precise result for [x] near zero. + * + * Special cases: + * - `ln1p(NaN)` is `NaN` + * - `ln1p(x)` is `NaN` where `x < -1.0` + * - `ln1p(-1.0)` is `-Inf` + * - `ln1p(+Inf)` is `+Inf` + * + * @see [ln] function + * @see [expm1] function + */ +@SinceKotlin("1.2") +public actual fun ln1p(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards positive infinity. + + * @return the smallest Float value that is greater than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `ceil(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun ceil(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards negative infinity. + + * @return the largest Float value that is smaller than or equal to the given value [x] and is a mathematical integer. + * + * Special cases: + * - `floor(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun floor(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] to an integer towards zero. + * + * @return the value [x] having its fractional part truncated. + * + * Special cases: + * - `truncate(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun truncate(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Rounds the given value [x] towards the closest integer with ties rounded towards even integer. + * + * Special cases: + * - `round(x)` is `x` where `x` is `NaN` or `+Inf` or `-Inf` or already a mathematical integer. + */ +@SinceKotlin("1.2") +public actual fun round(x: Float): Float = TODO("Wasm stdlib: Math") + + +/** + * Returns the absolute value of the given value [x]. + * + * Special cases: + * - `abs(NaN)` is `NaN` + * + * @see absoluteValue extension property for [Float] + */ +@SinceKotlin("1.2") +public actual fun abs(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of the given value [x]: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `sign(NaN)` is `NaN` + */ +@SinceKotlin("1.2") +public actual fun sign(x: Float): Float = TODO("Wasm stdlib: Math") + + + +/** + * Returns the smaller of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun min(a: Float, b: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Returns the greater of two values. + * + * If either value is `NaN`, then the result is `NaN`. + */ +@SinceKotlin("1.2") +public actual fun max(a: Float, b: Float): Float = TODO("Wasm stdlib: Math") + +// extensions + + +/** + * Raises this value to the power [x]. + * + * Special cases: + * - `b.pow(0.0)` is `1.0` + * - `b.pow(1.0) == b` + * - `b.pow(NaN)` is `NaN` + * - `NaN.pow(x)` is `NaN` for `x != 0.0` + * - `b.pow(Inf)` is `NaN` for `abs(b) == 1.0` + * - `b.pow(x)` is `NaN` for `b < 0` and `x` is finite and not an integer + */ +@SinceKotlin("1.2") +public actual fun Float.pow(x: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Raises this value to the integer power [n]. + * + * See the other overload of [pow] for details. + */ +@SinceKotlin("1.2") +public actual fun Float.pow(n: Int): Float = TODO("Wasm stdlib: Math") + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `NaN.absoluteValue` is `NaN` + * + * @see abs function + */ +@SinceKotlin("1.2") +public actual val Float.absoluteValue: Float get() = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of this value: + * - `-1.0` if the value is negative, + * - zero if the value is zero, + * - `1.0` if the value is positive + * + * Special case: + * - `NaN.sign` is `NaN` + */ +@SinceKotlin("1.2") +public actual val Float.sign: Float get() = TODO("Wasm stdlib: Math") + +/** + * Returns this value with the sign bit same as of the [sign] value. + * + * If [sign] is `NaN` the sign of the result is undefined. + */ +@SinceKotlin("1.2") +public actual fun Float.withSign(sign: Float): Float = TODO("Wasm stdlib: Math") + +/** + * Returns this value with the sign bit same as of the [sign] value. + */ +@SinceKotlin("1.2") +public actual fun Float.withSign(sign: Int): Float = TODO("Wasm stdlib: Math") + + +/** + * Rounds this [Float] value to the nearest integer and converts the result to [Int]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToInt() == Int.MAX_VALUE` when `x > Int.MAX_VALUE` + * - `x.roundToInt() == Int.MIN_VALUE` when `x < Int.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Float.roundToInt(): Int = TODO("Wasm stdlib: Math") + +/** + * Rounds this [Float] value to the nearest integer and converts the result to [Long]. + * Ties are rounded towards positive infinity. + * + * Special cases: + * - `x.roundToLong() == Long.MAX_VALUE` when `x > Long.MAX_VALUE` + * - `x.roundToLong() == Long.MIN_VALUE` when `x < Long.MIN_VALUE` + * + * @throws IllegalArgumentException when this value is `NaN` + */ +@SinceKotlin("1.2") +public actual fun Float.roundToLong(): Long = TODO("Wasm stdlib: Math") + + +// endregion + +// region ================ Integer Math ======================================== + + +/** + * Returns the absolute value of the given value [n]. + * + * Special cases: + * - `abs(Int.MIN_VALUE)` is `Int.MIN_VALUE` due to an overflow + * + * @see absoluteValue extension property for [Int] + */ +@SinceKotlin("1.2") +public actual fun abs(n: Int): Int = TODO("Wasm stdlib: Math") + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.2") +public actual fun min(a: Int, b: Int): Int = TODO("Wasm stdlib: Math") + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.2") +public actual fun max(a: Int, b: Int): Int = TODO("Wasm stdlib: Math") + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `Int.MIN_VALUE.absoluteValue` is `Int.MIN_VALUE` due to an overflow + * + * @see abs function + */ +@SinceKotlin("1.2") +public actual val Int.absoluteValue: Int get() = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of this value: + * - `-1` if the value is negative, + * - `0` if the value is zero, + * - `1` if the value is positive + */ +@SinceKotlin("1.2") +public actual val Int.sign: Int get() = TODO("Wasm stdlib: Math") + + + +/** + * Returns the absolute value of the given value [n]. + * + * Special cases: + * - `abs(Long.MIN_VALUE)` is `Long.MIN_VALUE` due to an overflow + * + * @see absoluteValue extension property for [Long] + */ +@SinceKotlin("1.2") +public actual fun abs(n: Long): Long = TODO("Wasm stdlib: Math") + +/** + * Returns the smaller of two values. + */ +@SinceKotlin("1.2") +public actual fun min(a: Long, b: Long): Long = TODO("Wasm stdlib: Math") + +/** + * Returns the greater of two values. + */ +@SinceKotlin("1.2") +public actual fun max(a: Long, b: Long): Long = TODO("Wasm stdlib: Math") + +/** + * Returns the absolute value of this value. + * + * Special cases: + * - `Long.MIN_VALUE.absoluteValue` is `Long.MIN_VALUE` due to an overflow + * + * @see abs function + */ +@SinceKotlin("1.2") +public actual val Long.absoluteValue: Long get() = TODO("Wasm stdlib: Math") + +/** + * Returns the sign of this value: + * - `-1` if the value is negative, + * - `0` if the value is zero, + * - `1` if the value is positive + */ +@SinceKotlin("1.2") +public actual val Long.sign: Int get() = TODO("Wasm stdlib: Math") + + +// endregion diff --git a/libraries/stdlib/wasm/src/kotlin/Sequences.kt b/libraries/stdlib/wasm/src/kotlin/Sequences.kt new file mode 100644 index 00000000000..01e51c5d714 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Sequences.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.sequences + +internal actual class ConstrainedOnceSequence : Sequence { + actual constructor(sequence: Sequence) { TODO("Wasm stdlib: ConstrainedOnceSequence") } + + actual override fun iterator(): Iterator = TODO("Wasm stdlib: ConstrainedOnceSequence") +} diff --git a/libraries/stdlib/wasm/src/kotlin/Text.kt b/libraries/stdlib/wasm/src/kotlin/Text.kt new file mode 100644 index 00000000000..9e2efe0528e --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/Text.kt @@ -0,0 +1,402 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +actual class Regex { + actual constructor(pattern: String) { TODO("Wasm stdlib: Text") } + actual constructor(pattern: String, option: RegexOption) { TODO("Wasm stdlib: Text") } + actual constructor(pattern: String, options: Set) { TODO("Wasm stdlib: Text") } + + actual val pattern: String = TODO("Wasm stdlib: Text") + actual val options: Set = TODO("Wasm stdlib: Text") + + actual fun matchEntire(input: CharSequence): MatchResult? = TODO("Wasm stdlib: Text") + actual infix fun matches(input: CharSequence): Boolean = TODO("Wasm stdlib: Text") + actual fun containsMatchIn(input: CharSequence): Boolean = TODO("Wasm stdlib: Text") + actual fun replace(input: CharSequence, replacement: String): String = TODO("Wasm stdlib: Text") + actual fun replace(input: CharSequence, transform: (MatchResult) -> CharSequence): String = TODO("Wasm stdlib: Text") + actual fun replaceFirst(input: CharSequence, replacement: String): String = TODO("Wasm stdlib: Text") + + /** + * Returns the first match of a regular expression in the [input], beginning at the specified [startIndex]. + * + * @param startIndex An index to start search with, by default 0. Must be not less than zero and not greater than `input.length()` + * @return An instance of [MatchResult] if match was found or `null` otherwise. + * @sample samples.text.Regexps.find + */ + actual fun find(input: CharSequence, startIndex: Int): MatchResult? = TODO("Wasm stdlib: Text") + + /** + * Returns a sequence of all occurrences of a regular expression within the [input] string, beginning at the specified [startIndex]. + * + * @sample samples.text.Regexps.findAll + */ + actual fun findAll(input: CharSequence, startIndex: Int): Sequence = TODO("Wasm stdlib: Text") + + /** + * Splits the [input] CharSequence around matches of this regular expression. + * + * @param limit Non-negative value specifying the maximum number of substrings the string can be split to. + * Zero by default means no limit is set. + */ + actual fun split(input: CharSequence, limit: Int): List = TODO("Wasm stdlib: Text") + + actual companion object { + actual fun fromLiteral(literal: String): Regex = TODO("Wasm stdlib: Text") + actual fun escape(literal: String): String = TODO("Wasm stdlib: Text") + actual fun escapeReplacement(literal: String): String = TODO("Wasm stdlib: Text") + } +} + +actual class MatchGroup { + actual val value: String = TODO("Wasm stdlib: Text") +} + +actual enum class RegexOption { + IGNORE_CASE, + MULTILINE +} + + +// From char.kt + +actual fun Char.isWhitespace(): Boolean = TODO("Wasm stdlib: Text") +actual fun Char.toLowerCase(): Char = TODO("Wasm stdlib: Text") +actual fun Char.toUpperCase(): Char = TODO("Wasm stdlib: Text") +actual fun Char.isHighSurrogate(): Boolean = TODO("Wasm stdlib: Text") +actual fun Char.isLowSurrogate(): Boolean = TODO("Wasm stdlib: Text") + +// From string.kt + + +/** + * Converts the characters in the specified array to a string. + */ +@SinceKotlin("1.2") +public actual fun String(chars: CharArray): String = TODO("Wasm stdlib: Text") + +/** + * Converts the characters from a portion of the specified array to a string. + * + * @throws IndexOutOfBoundsException if either [offset] or [length] are less than zero + * or `offset + length` is out of [chars] array bounds. + */ +@SinceKotlin("1.2") +public actual fun String(chars: CharArray, offset: Int, length: Int): String = TODO("Wasm stdlib: Text") + +/** + * Concatenates characters in this [CharArray] into a String. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun CharArray.concatToString(): String = TODO("Wasm stdlib: Text") + +/** + * Concatenates characters in this [CharArray] or its subrange into a String. + * + * @param startIndex the beginning (inclusive) of the subrange of characters, 0 by default. + * @param endIndex the end (exclusive) of the subrange of characters, size of this array by default. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun CharArray.concatToString(startIndex: Int, endIndex: Int): String = TODO("Wasm stdlib: Text") + +/** + * Returns a [CharArray] containing characters of this string. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun String.toCharArray(): CharArray = TODO("Wasm stdlib: Text") + +/** + * Returns a [CharArray] containing characters of this string or its substring. + * + * @param startIndex the beginning (inclusive) of the substring, 0 by default. + * @param endIndex the end (exclusive) of the substring, length of this string by default. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun String.toCharArray(startIndex: Int, endIndex: Int): CharArray = TODO("Wasm stdlib: Text") + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array. + * + * Malformed byte sequences are replaced by the replacement char `\uFFFD`. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun ByteArray.decodeToString(): String = TODO("Wasm stdlib: Text") + +/** + * Decodes a string from the bytes in UTF-8 encoding in this array or its subrange. + * + * @param startIndex the beginning (inclusive) of the subrange to decode, 0 by default. + * @param endIndex the end (exclusive) of the subrange to decode, size of this array by default. + * @param throwOnInvalidSequence specifies whether to throw an exception on malformed byte sequence or replace it by the replacement char `\uFFFD`. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the size of this array. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + * @throws CharacterCodingException if the byte array contains malformed UTF-8 byte sequence and [throwOnInvalidSequence] is true. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun ByteArray.decodeToString( + startIndex: Int, + endIndex: Int, + throwOnInvalidSequence: Boolean +): String = TODO("Wasm stdlib: Text") + +/** + * Encodes this string to an array of bytes in UTF-8 encoding. + * + * Any malformed char sequence is replaced by the replacement byte sequence. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun String.encodeToByteArray(): ByteArray = TODO("Wasm stdlib: Text") + +/** + * Encodes this string or its substring to an array of bytes in UTF-8 encoding. + * + * @param startIndex the beginning (inclusive) of the substring to encode, 0 by default. + * @param endIndex the end (exclusive) of the substring to encode, length of this string by default. + * @param throwOnInvalidSequence specifies whether to throw an exception on malformed char sequence or replace. + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or [endIndex] is greater than the length of this string. + * @throws IllegalArgumentException if [startIndex] is greater than [endIndex]. + * @throws CharacterCodingException if this string contains malformed char sequence and [throwOnInvalidSequence] is true. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun String.encodeToByteArray( + startIndex: Int, + endIndex: Int, + throwOnInvalidSequence: Boolean +): ByteArray = TODO("Wasm stdlib: Text") + + +internal actual fun String.nativeIndexOf(str: String, fromIndex: Int): Int = TODO("Wasm stdlib: Text") +internal actual fun String.nativeLastIndexOf(str: String, fromIndex: Int): Int = TODO("Wasm stdlib: Text") + + +public actual fun String.substring(startIndex: Int): String = TODO("Wasm stdlib: Text") +public actual fun String.substring(startIndex: Int, endIndex: Int): String = TODO("Wasm stdlib: Text") + +/** + * Returns a copy of this string converted to upper case using the rules of the default locale. + * + * @sample samples.text.Strings.toUpperCase + */ +public actual fun String.toUpperCase(): String = TODO("Wasm stdlib: Text") + +/** + * Returns a copy of this string converted to lower case using the rules of the default locale. + * + * @sample samples.text.Strings.toLowerCase + */ +public actual fun String.toLowerCase(): String = TODO("Wasm stdlib: Text") +public actual fun String.capitalize(): String = TODO("Wasm stdlib: Text") +public actual fun String.decapitalize(): String = TODO("Wasm stdlib: Text") +public actual fun CharSequence.repeat(n: Int): String = TODO("Wasm stdlib: Text") + + +/** + * Returns a new string with all occurrences of [oldChar] replaced with [newChar]. + */ +actual fun String.replace(oldChar: Char, newChar: Char, ignoreCase: Boolean): String = TODO("Wasm stdlib: Text") + +/** + * Returns a new string obtained by replacing all occurrences of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +actual fun String.replace(oldValue: String, newValue: String, ignoreCase: Boolean): String = TODO("Wasm stdlib: Text") + +/** + * Returns a new string with the first occurrence of [oldChar] replaced with [newChar]. + */ +actual fun String.replaceFirst(oldChar: Char, newChar: Char, ignoreCase: Boolean): String = TODO("Wasm stdlib: Text") + +/** + * Returns a new string obtained by replacing the first occurrence of the [oldValue] substring in this string + * with the specified [newValue] string. + */ +actual fun String.replaceFirst(oldValue: String, newValue: String, ignoreCase: Boolean): String = TODO("Wasm stdlib: Text") + +/** + * Returns `true` if this string is equal to [other], optionally ignoring character case. + * + * @param ignoreCase `true` to ignore character case when comparing strings. By default `false`. + */ +actual fun String?.equals(other: String?, ignoreCase: Boolean): Boolean = TODO("Wasm stdlib: Text") + +/** + * Compares two strings lexicographically, optionally ignoring case differences. + */ +@SinceKotlin("1.2") +actual fun String.compareTo(other: String, ignoreCase: Boolean): Int = TODO("Wasm stdlib: Text") + + +public actual fun String.startsWith(prefix: String, ignoreCase: Boolean): Boolean = TODO("Wasm stdlib: Text") +public actual fun String.startsWith(prefix: String, startIndex: Int, ignoreCase: Boolean): Boolean = TODO("Wasm stdlib: Text") +public actual fun String.endsWith(suffix: String, ignoreCase: Boolean): Boolean = TODO("Wasm stdlib: Text") + +// From stringsCode.kt + +internal actual fun String.nativeIndexOf(ch: Char, fromIndex: Int): Int = TODO("Wasm stdlib: Text") +internal actual fun String.nativeLastIndexOf(ch: Char, fromIndex: Int): Int = TODO("Wasm stdlib: Text") + +actual fun CharSequence.isBlank(): Boolean = TODO("Wasm stdlib: Text") +/** + * Returns `true` if the specified range in this char sequence is equal to the specified range in another char sequence. + * @param thisOffset the start offset in this char sequence of the substring to compare. + * @param other the string against a substring of which the comparison is performed. + * @param otherOffset the start offset in the other char sequence of the substring to compare. + * @param length the length of the substring to compare. + */ +actual fun CharSequence.regionMatches( + thisOffset: Int, + other: CharSequence, + otherOffset: Int, + length: Int, + ignoreCase: Boolean +): Boolean = TODO("Wasm stdlib: Text") + + +/** + * A Comparator that orders strings ignoring character case. + * + * Note that this Comparator does not take locale into account, + * and will result in an unsatisfactory ordering for certain locales. + */ +@SinceKotlin("1.2") +public actual val String.Companion.CASE_INSENSITIVE_ORDER: Comparator get() = TODO("Wasm stdlib: Text") + +actual fun String.toBoolean(): Boolean = TODO("Wasm stdlib: Text") + +/** + * Returns `true` if the contents of this string is equal to the word "true", ignoring case, and `false` otherwise. + */ +actual fun String?.toBoolean(): Boolean = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a signed [Byte] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toByte(): Byte = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a signed [Byte] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +actual fun String.toByte(radix: Int): Byte = TODO("Wasm stdlib: Text") + + +/** + * Parses the string as a [Short] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toShort(): Short = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Short] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +actual fun String.toShort(radix: Int): Short = TODO("Wasm stdlib: Text") + +/** + * Parses the string as an [Int] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toInt(): Int = TODO("Wasm stdlib: Text") + +/** + * Parses the string as an [Int] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +actual fun String.toInt(radix: Int): Int = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Long] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toLong(): Long = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Long] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + * @throws IllegalArgumentException when [radix] is not a valid radix for string to number conversion. + */ +actual fun String.toLong(radix: Int): Long = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Double] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toDouble(): Double = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Float] number and returns the result. + * @throws NumberFormatException if the string is not a valid representation of a number. + */ +actual fun String.toFloat(): Float = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Double] number and returns the result + * or `null` if the string is not a valid representation of a number. + */ +actual fun String.toDoubleOrNull(): Double? = TODO("Wasm stdlib: Text") + +/** + * Parses the string as a [Float] number and returns the result + * or `null` if the string is not a valid representation of a number. + */ +actual fun String.toFloatOrNull(): Float? = TODO("Wasm stdlib: Text") + +/** + * Returns a string representation of this [Byte] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.2") +actual fun Byte.toString(radix: Int): String = TODO("Wasm stdlib: Text") + +/** + * Returns a string representation of this [Short] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.2") +actual fun Short.toString(radix: Int): String = TODO("Wasm stdlib: Text") + +/** + * Returns a string representation of this [Int] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.2") +actual fun Int.toString(radix: Int): String = TODO("Wasm stdlib: Text") + +/** + * Returns a string representation of this [Long] value in the specified [radix]. + * + * @throws IllegalArgumentException when [radix] is not a valid radix for number to string conversion. + */ +@SinceKotlin("1.2") +actual fun Long.toString(radix: Int): String = TODO("Wasm stdlib: Text") + +@PublishedApi +internal actual fun checkRadix(radix: Int): Int = TODO("Wasm stdlib: Text") + +internal actual fun digitOf(char: Char, radix: Int): Int = TODO("Wasm stdlib: Text") diff --git a/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableCollection.kt b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableCollection.kt new file mode 100644 index 00000000000..4114e8b5193 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableCollection.kt @@ -0,0 +1,32 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableCollection] interface. + * + * @param E the type of elements contained in the collection. The collection is invariant on its element type. + */ +@SinceKotlin("1.3") +public actual abstract class AbstractMutableCollection : MutableCollection { + actual protected constructor() + + actual abstract override val size: Int + actual abstract override fun iterator(): MutableIterator + actual abstract override fun add(element: E): Boolean + + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + + + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableCollection") + actual override fun clear(): Unit = TODO("Wasm stdlib: AbstractMutableCollection") +} + diff --git a/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableList.kt b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableList.kt new file mode 100644 index 00000000000..f2ba41d66c5 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableList.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableList] interface. + * + * @param E the type of elements contained in the list. The list is invariant on its element type. + */ +public actual abstract class AbstractMutableList : MutableList { + actual protected constructor() + + // From List + + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun indexOf(element: @UnsafeVariance E): Int = TODO("Wasm stdlib: AbstractMutableList") + actual override fun lastIndexOf(element: @UnsafeVariance E): Int = TODO("Wasm stdlib: AbstractMutableList") + + // From MutableCollection + + actual override fun iterator(): MutableIterator = TODO("Wasm stdlib: AbstractMutableList") + + // From MutableList + + /** + * Adds the specified element to the end of this list. + * + * @return `true` because the list is always modified as the result of this operation. + */ + actual override fun add(element: E): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun addAll(index: Int, elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableList") + actual override fun clear() { TODO("Wasm stdlib: AbstractMutableList") } + actual override fun listIterator(): MutableListIterator = TODO("Wasm stdlib: AbstractMutableList") + actual override fun listIterator(index: Int): MutableListIterator = TODO("Wasm stdlib: AbstractMutableList") + actual override fun subList(fromIndex: Int, toIndex: Int): MutableList = TODO("Wasm stdlib: AbstractMutableList") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableMap.kt b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableMap.kt new file mode 100644 index 00000000000..31fb824b2a8 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableMap.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableMap] interface. + * + * The implementor is required to implement [entries] property, which should return mutable set of map entries, and [put] function. + * + * @param K the type of map keys. The map is invariant on its key type. + * @param V the type of map values. The map is invariant on its value type. + */ +@SinceKotlin("1.3") +public actual abstract class AbstractMutableMap : MutableMap { + actual protected constructor() + + /** + * Associates the specified [value] with the specified [key] in the map. + * + * This method is redeclared as abstract, because it's not implemented in the base class, + * so it must be always overridden in the concrete mutable collection implementation. + * + * @return the previous value associated with the key, or `null` if the key was not present in the map. + */ + abstract actual override fun put(key: K, value: V): V? + + abstract actual override val entries: MutableSet> + + actual override val keys: MutableSet = TODO("Wasm stdlib: AbstractMutableMap") + actual override val size: Int = TODO("Wasm stdlib: AbstractMutableMap") + actual override val values: MutableCollection = TODO("Wasm stdlib: AbstractMutableMap") + actual override fun clear() { TODO("Wasm stdlib: AbstractMutableMap") } + actual override fun containsKey(key: K): Boolean = TODO("Wasm stdlib: AbstractMutableMap") + actual override fun containsValue(value: V): Boolean = TODO("Wasm stdlib: AbstractMutableMap") + actual override fun get(key: K): V? = TODO("Wasm stdlib: AbstractMutableMap") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: AbstractMutableMap") + actual override fun putAll(from: Map) { TODO("Wasm stdlib: AbstractMutableMap") } + actual override fun remove(key: K): V? = TODO("Wasm stdlib: AbstractMutableMap") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableSet.kt b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableSet.kt new file mode 100644 index 00000000000..1db74638914 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/AbstractMutableSet.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +/** + * Provides a skeletal implementation of the [MutableSet] interface. + * + * @param E the type of elements contained in the set. The set is invariant on its element type. + */ +@SinceKotlin("1.3") +public actual abstract class AbstractMutableSet : MutableSet { + actual protected constructor() + + actual abstract override val size: Int + actual abstract override fun iterator(): MutableIterator + actual abstract override fun add(element: E): Boolean + + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + + + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: AbstractMutableSet") + actual override fun clear() { TODO("Wasm stdlib: AbstractMutableSet") } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/ArrayList.kt b/libraries/stdlib/wasm/src/kotlin/collections/ArrayList.kt new file mode 100644 index 00000000000..df2a7816202 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/ArrayList.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual open class ArrayList : MutableList, RandomAccess { + actual constructor() { TODO("Wasm stdlib: ArrayList") } + actual constructor(initialCapacity: Int) { TODO("Wasm stdlib: ArrayList") } + actual constructor(elements: Collection) { TODO("Wasm stdlib: ArrayList") } + + actual fun trimToSize() { TODO("Wasm stdlib: ArrayList") } + actual fun ensureCapacity(minCapacity: Int) { TODO("Wasm stdlib: ArrayList") } + + // From List + + actual override val size: Int = TODO("Wasm stdlib: ArrayList") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: ArrayList") + actual override operator fun get(index: Int): E = TODO("Wasm stdlib: ArrayList") + actual override fun indexOf(element: @UnsafeVariance E): Int = TODO("Wasm stdlib: ArrayList") + actual override fun lastIndexOf(element: @UnsafeVariance E): Int = TODO("Wasm stdlib: ArrayList") + + // From MutableCollection + + actual override fun iterator(): MutableIterator = TODO("Wasm stdlib: ArrayList") + + // From MutableList + + actual override fun add(element: E): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun addAll(index: Int, elements: Collection): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: ArrayList") + actual override fun clear() { TODO("Wasm stdlib: ArrayList") } + actual override operator fun set(index: Int, element: E): E = TODO("Wasm stdlib: ArrayList") + actual override fun add(index: Int, element: E) { TODO("Wasm stdlib: ArrayList") } + actual override fun removeAt(index: Int): E = TODO("Wasm stdlib: ArrayList") + actual override fun listIterator(): MutableListIterator = TODO("Wasm stdlib: ArrayList") + actual override fun listIterator(index: Int): MutableListIterator = TODO("Wasm stdlib: ArrayList") + actual override fun subList(fromIndex: Int, toIndex: Int): MutableList = TODO("Wasm stdlib: ArrayList") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/Arrays.kt b/libraries/stdlib/wasm/src/kotlin/collections/Arrays.kt new file mode 100644 index 00000000000..f9c4e90b0e6 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/Arrays.kt @@ -0,0 +1,105 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +import kotlin.internal.PureReifiable + +// Array Utils copied from K/N + +internal fun checkCopyOfRangeArguments(fromIndex: Int, toIndex: Int, size: Int) { + if (toIndex > size) + throw IndexOutOfBoundsException("toIndex ($toIndex) is greater than size ($size).") + if (fromIndex > toIndex) + throw IllegalArgumentException("fromIndex ($fromIndex) is greater than toIndex ($toIndex).") +} + + +// TODO: internal +/** + * Returns a string representation of the contents of the subarray of the specified array as if it is [List]. + */ +@SinceKotlin("1.1") +@kotlin.internal.InlineOnly +public inline fun Array.subarrayContentToString(offset: Int, length: Int): String { + val sb = StringBuilder(2 + length * 3) + sb.append("[") + var i = 0 + while (i < length) { + if (i > 0) sb.append(", ") + sb.append(this[offset + i]) + i++ + } + sb.append("]") + return sb.toString() +} + + +/** + * Returns a hash code based on the contents of this array as if it is [List]. + * Nested arrays are treated as lists too. + * + * If any of arrays contains itself on any nesting level the behavior is undefined. + */ +@SinceKotlin("1.1") +@UseExperimental(ExperimentalUnsignedTypes::class) +internal fun Array?.contentDeepHashCodeImpl(): Int { + if (this == null) return 0 + var result = 1 + for (element in this) { + val elementHash = when (element) { + null -> 0 + + is Array<*> -> element.contentDeepHashCode() + + is ByteArray -> element.contentHashCode() + is ShortArray -> element.contentHashCode() + is IntArray -> element.contentHashCode() + is LongArray -> element.contentHashCode() + is FloatArray -> element.contentHashCode() + is DoubleArray -> element.contentHashCode() + is CharArray -> element.contentHashCode() + is BooleanArray -> element.contentHashCode() + + is UByteArray -> element.contentHashCode() + is UShortArray -> element.contentHashCode() + is UIntArray -> element.contentHashCode() + is ULongArray -> element.contentHashCode() + + else -> element.hashCode() + } + + result = 31 * result + elementHash + } + return result +} + +@Suppress("UNCHECKED_CAST") +internal actual fun arrayOfNulls(reference: Array, size: Int): Array = arrayOfNulls(size) as Array + +internal actual fun copyToArrayImpl(collection: Collection<*>): Array { + val array = Array(collection.size) + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) + array[index++] = iterator.next() + return array +} + +@Suppress("UNCHECKED_CAST") +internal actual fun copyToArrayImpl(collection: Collection<*>, array: Array): Array { + if (array.size < collection.size) + return copyToArrayImpl(collection) as Array + + val iterator = collection.iterator() + var index = 0 + while (iterator.hasNext()) { + array[index++] = iterator.next() as T + } + if (index < array.size) { + return array.copyOf(index) as Array + } + return array +} diff --git a/libraries/stdlib/wasm/src/kotlin/collections/Collections.kt b/libraries/stdlib/wasm/src/kotlin/collections/Collections.kt new file mode 100644 index 00000000000..87abd933c9f --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/Collections.kt @@ -0,0 +1,111 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual interface RandomAccess + +/** Returns the array if it's not `null`, or an empty array otherwise. */ +actual inline fun Array?.orEmpty(): Array = this ?: emptyArray() + + +public actual inline fun Collection.toTypedArray(): Array { + val result = arrayOfNulls(size) + var index = 0 + for (element in this) result[index++] = element + @Suppress("UNCHECKED_CAST") + return result as Array +} + +@SinceKotlin("1.2") +actual fun MutableList.fill(value: T): Unit = TODO("Wasm stdlib: Collections") + +@SinceKotlin("1.2") +actual fun MutableList.shuffle(): Unit = TODO("Wasm stdlib: Collections") + +@SinceKotlin("1.2") +actual fun Iterable.shuffled(): List = TODO("Wasm stdlib: Collections") + +actual fun > MutableList.sort(): Unit = TODO("Wasm stdlib: Collections") +actual fun MutableList.sortWith(comparator: Comparator): Unit = TODO("Wasm stdlib: Collections") + + +// from Grouping.kt +public actual fun Grouping.eachCount(): Map = TODO("Wasm stdlib: Collections") +// public actual inline fun Grouping.eachSumOf(valueSelector: (T) -> Int): Map + +internal actual fun Map.toSingletonMapOrSelf(): Map = TODO("Wasm stdlib: Collections") +internal actual fun Map.toSingletonMap(): Map = TODO("Wasm stdlib: Collections") +internal actual fun Array.copyToArrayOfAny(isVarargs: Boolean): Array = TODO("Wasm stdlib: Collections") + +@PublishedApi +@SinceKotlin("1.3") +internal actual fun checkIndexOverflow(index: Int): Int = TODO("Wasm stdlib: Collections") + +@PublishedApi +@SinceKotlin("1.3") +internal actual fun checkCountOverflow(count: Int): Int = TODO("Wasm stdlib: Collections") + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(builderAction: MutableList.() -> Unit): List { + return TODO("Wasm stdlib: Collections") +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildListInternal(capacity: Int, builderAction: MutableList.() -> Unit): List { + checkBuilderCapacity(capacity) + return TODO("Wasm stdlib: Collections") +} + + +/** + * Returns an immutable set containing only the specified object [element]. + */ +public fun setOf(element: T): Set = hashSetOf(element) + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(builderAction: MutableSet.() -> Unit): Set { + return TODO("Wasm stdlib: Collections") +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildSetInternal(capacity: Int, builderAction: MutableSet.() -> Unit): Set { + return TODO("Wasm stdlib: Collections") +} + + +/** + * Returns an immutable map, mapping only the specified key to the + * specified value. + */ +public fun mapOf(pair: Pair): Map = hashMapOf(pair) + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(builderAction: MutableMap.() -> Unit): Map { + return TODO("Wasm stdlib: Collections") +} + +@PublishedApi +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@kotlin.internal.InlineOnly +internal actual inline fun buildMapInternal(capacity: Int, builderAction: MutableMap.() -> Unit): Map { + return TODO("Wasm stdlib: Collections") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/HashMap.kt b/libraries/stdlib/wasm/src/kotlin/collections/HashMap.kt new file mode 100644 index 00000000000..10add08b1fe --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/HashMap.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual open class HashMap : MutableMap { + actual constructor() { TODO("Wasm stdlib: HashMap") } + actual constructor(initialCapacity: Int) { TODO("Wasm stdlib: HashMap") } + actual constructor(initialCapacity: Int, loadFactor: Float) { TODO("Wasm stdlib: HashMap") } + actual constructor(original: Map) { TODO("Wasm stdlib: HashMap") } + + // From Map + + actual override val size: Int = TODO("Wasm stdlib: HashMap") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: HashMap") + actual override fun containsKey(key: K): Boolean = TODO("Wasm stdlib: HashMap") + actual override fun containsValue(value: @UnsafeVariance V): Boolean = TODO("Wasm stdlib: HashMap") + actual override operator fun get(key: K): V? = TODO("Wasm stdlib: HashMap") + + // From MutableMap + + actual override fun put(key: K, value: V): V? = TODO("Wasm stdlib: HashMap") + actual override fun remove(key: K): V? = TODO("Wasm stdlib: HashMap") + actual override fun putAll(from: Map) { TODO("Wasm stdlib: HashMap") } + actual override fun clear() { TODO("Wasm stdlib: HashMap") } + actual override val keys: MutableSet = TODO("Wasm stdlib: HashMap") + actual override val values: MutableCollection = TODO("Wasm stdlib: HashMap") + actual override val entries: MutableSet> = TODO("Wasm stdlib: HashMap") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/HashSet.kt b/libraries/stdlib/wasm/src/kotlin/collections/HashSet.kt new file mode 100644 index 00000000000..9c8863b5fcb --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/HashSet.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual open class HashSet : MutableSet { + actual constructor() { TODO("Wasm stdlib: HashSet") } + actual constructor(initialCapacity: Int) { TODO("Wasm stdlib: HashSet") } + actual constructor(initialCapacity: Int, loadFactor: Float) { TODO("Wasm stdlib: HashSet") } + actual constructor(elements: Collection) { TODO("Wasm stdlib: HashSet") } + + // From Set + + actual override val size: Int = TODO("Wasm stdlib: HashSet") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: HashSet") + + // From MutableSet + + actual override fun iterator(): MutableIterator = TODO("Wasm stdlib: HashSet") + actual override fun add(element: E): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: HashSet") + actual override fun clear() { TODO("Wasm stdlib: HashSet") } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashMap.kt b/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashMap.kt new file mode 100644 index 00000000000..a7be8b0918b --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashMap.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual open class LinkedHashMap : MutableMap { + actual constructor() { TODO("Wasm stdlib: LinkedHashMap") } + actual constructor(initialCapacity: Int) { TODO("Wasm stdlib: LinkedHashMap") } + actual constructor(initialCapacity: Int, loadFactor: Float) { TODO("Wasm stdlib: LinkedHashMap") } + actual constructor(original: Map) { TODO("Wasm stdlib: LinkedHashMap") } + + // From Map + + actual override val size: Int = TODO("Wasm stdlib: LinkedHashMap") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: LinkedHashMap") + actual override fun containsKey(key: K): Boolean = TODO("Wasm stdlib: LinkedHashMap") + actual override fun containsValue(value: V): Boolean = TODO("Wasm stdlib: LinkedHashMap") + actual override fun get(key: K): V? = TODO("Wasm stdlib: LinkedHashMap") + + // From MutableMap + + actual override fun put(key: K, value: V): V? = TODO("Wasm stdlib: LinkedHashMap") + actual override fun remove(key: K): V? = TODO("Wasm stdlib: LinkedHashMap") + actual override fun putAll(from: Map) { TODO("Wasm stdlib: LinkedHashMap") } + actual override fun clear() { TODO("Wasm stdlib: LinkedHashMap") } + actual override val keys: MutableSet = TODO("Wasm stdlib: LinkedHashMap") + actual override val values: MutableCollection = TODO("Wasm stdlib: LinkedHashMap") + actual override val entries: MutableSet> = TODO("Wasm stdlib: LinkedHashMap") +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashSet.kt b/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashSet.kt new file mode 100644 index 00000000000..6a9dda88390 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/LinkedHashSet.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +actual open class LinkedHashSet : MutableSet { + actual constructor() { TODO("Wasm stdlib: LinkedHashSet") } + actual constructor(initialCapacity: Int) { TODO("Wasm stdlib: LinkedHashSet") } + actual constructor(initialCapacity: Int, loadFactor: Float) { TODO("Wasm stdlib: LinkedHashSet") } + actual constructor(elements: Collection) { TODO("Wasm stdlib: LinkedHashSet") } + + // From Set + + actual override val size: Int = TODO("Wasm stdlib: LinkedHashSet") + actual override fun isEmpty(): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun contains(element: @UnsafeVariance E): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun containsAll(elements: Collection<@UnsafeVariance E>): Boolean = TODO("Wasm stdlib: LinkedHashSet") + + // From MutableSet + + actual override fun iterator(): MutableIterator = TODO("Wasm stdlib: LinkedHashSet") + actual override fun add(element: E): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun remove(element: E): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun addAll(elements: Collection): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun removeAll(elements: Collection): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun retainAll(elements: Collection): Boolean = TODO("Wasm stdlib: LinkedHashSet") + actual override fun clear() { TODO("Wasm stdlib: LinkedHashSet") } +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/collections/Maps.kt b/libraries/stdlib/wasm/src/kotlin/collections/Maps.kt new file mode 100644 index 00000000000..42038dd6088 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/collections/Maps.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.collections + +/** + * Calculate the initial capacity of a map. + */ +@PublishedApi +internal actual fun mapCapacity(expectedSize: Int): Int = TODO("Wasm stdlib: Maps") + +/** + * Checks a collection builder function capacity argument. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +@PublishedApi +internal fun checkBuilderCapacity(capacity: Int) { TODO("Wasm stdlib: Maps") } \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/coroutines/Coroutines.kt b/libraries/stdlib/wasm/src/kotlin/coroutines/Coroutines.kt new file mode 100644 index 00000000000..0961934ca18 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/coroutines/Coroutines.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.coroutines + +@PublishedApi +@SinceKotlin("1.3") +internal actual class SafeContinuation : Continuation { + actual internal constructor(delegate: Continuation, initialResult: Any?) { TODO("Wasm stdlib: Coroutines") } + + @PublishedApi + actual internal constructor(delegate: Continuation) { TODO("Wasm stdlib: Coroutines") } + + @PublishedApi + actual internal fun getOrThrow(): Any? = TODO("Wasm stdlib: Coroutines") + + actual override val context: CoroutineContext = TODO("Wasm stdlib: Coroutines") + actual override fun resumeWith(result: Result): Unit { TODO("Wasm stdlib: Coroutines") } +} diff --git a/libraries/stdlib/wasm/src/kotlin/coroutines/CoroutinesIntrinsics.kt b/libraries/stdlib/wasm/src/kotlin/coroutines/CoroutinesIntrinsics.kt new file mode 100644 index 00000000000..d8959b4a719 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/coroutines/CoroutinesIntrinsics.kt @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.coroutines.intrinsics + +import kotlin.coroutines.Continuation +import kotlin.coroutines.ContinuationInterceptor +import kotlin.coroutines.CoroutineContext +import kotlin.internal.InlineOnly + +/** + * Starts an unintercepted coroutine without a receiver and with result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the latter case, the [completion] continuation is invoked when the coroutine completes with a result or an exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is the invoker's responsibility to ensure that a proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of the suspended + * coroutine using a reference to the suspending function. + */ +@SinceKotlin("1.3") +public actual inline fun (suspend () -> T).startCoroutineUninterceptedOrReturn( + completion: Continuation +): Any? = TODO("Wasm stdlib: Coroutines intrinsics") + +/** + * Starts an unintercepted coroutine with receiver type [R] and result type [T] and executes it until its first suspension. + * Returns the result of the coroutine or throws its exception if it does not suspend or [COROUTINE_SUSPENDED] if it suspends. + * In the latter case, the [completion] continuation is invoked when the coroutine completes with a result or an exception. + * + * The coroutine is started directly in the invoker's thread without going through the [ContinuationInterceptor] that might + * be present in the completion's [CoroutineContext]. It is the invoker's responsibility to ensure that a proper invocation + * context is established. + * + * This function is designed to be used from inside of [suspendCoroutineUninterceptedOrReturn] to resume the execution of the suspended + * coroutine using a reference to the suspending function. + */ +@SinceKotlin("1.3") +public actual inline fun (suspend R.() -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + completion: Continuation +): Any? = TODO("Wasm stdlib: Coroutines intrinsics") + +@InlineOnly +internal actual inline fun (suspend R.(P) -> T).startCoroutineUninterceptedOrReturn( + receiver: R, + param: P, + completion: Continuation +): Any? = TODO("Wasm stdlib: Coroutines intrinsics") + +@SinceKotlin("1.3") +public actual fun (suspend () -> T).createCoroutineUnintercepted( + completion: Continuation +): Continuation = TODO("Wasm stdlib: Coroutines intrinsics") + +@SinceKotlin("1.3") +public actual fun (suspend R.() -> T).createCoroutineUnintercepted( + receiver: R, + completion: Continuation +): Continuation = TODO("Wasm stdlib: Coroutines intrinsics") + +/** + * Intercepts this continuation with [ContinuationInterceptor]. + * + * This function shall be used on the immediate result of [createCoroutineUnintercepted] or [suspendCoroutineUninterceptedOrReturn], + * in which case it checks for [ContinuationInterceptor] in the continuation's [context][Continuation.context], + * invokes [ContinuationInterceptor.interceptContinuation], caches and returns the result. + * + * If this function is invoked on other [Continuation] instances it returns `this` continuation unchanged. + */ +@SinceKotlin("1.3") +public actual fun Continuation.intercepted(): Continuation = TODO("Wasm stdlib: Coroutines intrinsics") diff --git a/libraries/stdlib/wasm/src/kotlin/coroutines/cancellation/CancellationException.kt b/libraries/stdlib/wasm/src/kotlin/coroutines/cancellation/CancellationException.kt new file mode 100644 index 00000000000..0438d8b0b19 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/coroutines/cancellation/CancellationException.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.coroutines.cancellation + +@ExperimentalStdlibApi +@SinceKotlin("1.4") +public actual open class CancellationException : IllegalStateException { + actual constructor() : super() + actual constructor(message: String?) : super(message) + constructor(message: String?, cause: Throwable?) : super(message, cause) + constructor(cause: Throwable?) : super(cause) +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/io.kt b/libraries/stdlib/wasm/src/kotlin/io.kt new file mode 100644 index 00000000000..0d27e864646 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/io.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.io + +import kotlin.wasm.internal.* + +/** Prints the line separator to the standard output stream. */ +public actual fun println() { + println("") +} + +/** Prints the given [message] and the line separator to the standard output stream. */ +public actual fun println(message: Any?) { + printlnImpl(message.toString()) +} + +/** Prints the given [message] to the standard output stream. */ +public actual fun print(message: Any?) { + // TODO: Support print without newline + println(message) +} + + +internal actual interface Serializable + +@WasmImport("runtime", "println") +private fun printlnImpl(message: String): Unit = + implementedAsIntrinsic diff --git a/libraries/stdlib/wasm/src/kotlin/random/Random.kt b/libraries/stdlib/wasm/src/kotlin/random/Random.kt new file mode 100644 index 00000000000..4270affaaec --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/random/Random.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.random + +internal actual fun defaultPlatformRandom(): Random = TODO("Wasm stdlib: Random") +internal actual fun doubleFromParts(hi26: Int, low27: Int): Double = TODO("Wasm stdlib: Random") diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KCallable.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KCallable.kt new file mode 100644 index 00000000000..15a8c0ec4f2 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KCallable.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +/** + * Represents a callable entity, such as a function or a property. + * + * @param R return type of the callable. + */ +public actual interface KCallable { + /** + * The name of this callable as it was declared in the source code. + * If the callable has no name, a special invented name is created. + * Nameless callables include: + * - constructors have the name "", + * - property accessors: the getter for a property named "foo" will have the name "", + * the setter, similarly, will have the name "". + */ + actual public val name: String +} diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt new file mode 100644 index 00000000000..2251a80db6f --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClass.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +/** + * Represents a class and provides introspection capabilities. + * Instances of this class are obtainable by the `::class` syntax. + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html#class-references) + * for more information. + * + * @param T the type of the class. + */ +public actual interface KClass : KClassifier { + /** + * The simple name of the class as it was declared in the source code, + * or `null` if the class has no name (if, for example, it is a class of an anonymous object). + */ + public actual val simpleName: String? + + /** + * The fully qualified dot-separated name of the class, + * or `null` if the class is local or a class of an anonymous object. + */ + public actual val qualifiedName: String? + + /** + * Returns `true` if [value] is an instance of this class on a given platform. + */ + @SinceKotlin("1.1") + public actual fun isInstance(value: Any?): Boolean + +} \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KClasses.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KClasses.kt new file mode 100644 index 00000000000..fa239b1368d --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KClasses.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +internal actual val KClass<*>.qualifiedOrSimpleName: String? get() = TODO("Wasm stdlib: KClass<*>.qualifiedOrSimpleName") diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KFunction.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KFunction.kt new file mode 100644 index 00000000000..9810f3d5653 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KFunction.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +/** + * Represents a function with introspection capabilities. + */ +public actual interface KFunction : KCallable, Function \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KProperty.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KProperty.kt new file mode 100644 index 00000000000..0e80aa9178a --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KProperty.kt @@ -0,0 +1,119 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:Suppress("IMPLEMENTING_FUNCTION_INTERFACE") +package kotlin.reflect + +/** + * Represents a property, such as a named `val` or `var` declaration. + * Instances of this class are obtainable by the `::` operator. + * + * See the [Kotlin language documentation](https://kotlinlang.org/docs/reference/reflection.html) + * for more information. + * + * @param R the type of the property. + */ +public actual interface KProperty : KCallable { +} + +/** + * Represents a property declared as a `var`. + */ +public actual interface KMutableProperty : KProperty { +} + + +/** + * Represents a property without any kind of receiver. + * Such property is either originally declared in a receiverless context such as a package, + * or has the receiver bound to it. + */ +public actual interface KProperty0 : KProperty, () -> R { + /** + * Returns the current value of the property. + */ + public actual fun get(): R +} + +/** + * Represents a `var`-property without any kind of receiver. + */ +public actual interface KMutableProperty0 : KProperty0, KMutableProperty { + /** + * Modifies the value of the property. + * + * @param value the new value to be assigned to this property. + */ + public actual fun set(value: R) +} + + +/** + * Represents a property, operations on which take one receiver as a parameter. + * + * @param T the type of the receiver which should be used to obtain the value of the property. + * @param R the type of the property. + */ +public actual interface KProperty1 : KProperty, (T) -> R { + /** + * Returns the current value of the property. + * + * @param receiver the receiver which is used to obtain the value of the property. + * For example, it should be a class instance if this is a member property of that class, + * or an extension receiver if this is a top level extension property. + */ + public actual fun get(receiver: T): R +} + +/** + * Represents a `var`-property, operations on which take one receiver as a parameter. + */ +public actual interface KMutableProperty1 : KProperty1, KMutableProperty { + /** + * Modifies the value of the property. + * + * @param receiver the receiver which is used to modify the value of the property. + * For example, it should be a class instance if this is a member property of that class, + * or an extension receiver if this is a top level extension property. + * @param value the new value to be assigned to this property. + */ + public actual fun set(receiver: T, value: R) +} + + +/** + * Represents a property, operations on which take two receivers as parameters, + * such as an extension property declared in a class. + * + * @param D the type of the first receiver. In case of the extension property in a class this is + * the type of the declaring class of the property, or any subclass of that class. + * @param E the type of the second receiver. In case of the extension property in a class this is + * the type of the extension receiver. + * @param R the type of the property. + */ +public actual interface KProperty2 : KProperty, (D, E) -> R { + /** + * Returns the current value of the property. In case of the extension property in a class, + * the instance of the class should be passed first and the instance of the extension receiver second. + * + * @param receiver1 the instance of the first receiver. + * @param receiver2 the instance of the second receiver. + */ + public actual fun get(receiver1: D, receiver2: E): R +} + +/** + * Represents a `var`-property, operations on which take two receivers as parameters. + */ +public actual interface KMutableProperty2 : KProperty2, KMutableProperty { + /** + * Modifies the value of the property. + * + * @param receiver1 the instance of the first receiver. + * @param receiver2 the instance of the second receiver. + * @param value the new value to be assigned to this property. + */ + public actual fun set(receiver1: D, receiver2: E, value: R) +} diff --git a/libraries/stdlib/wasm/src/kotlin/reflect/KType.kt b/libraries/stdlib/wasm/src/kotlin/reflect/KType.kt new file mode 100644 index 00000000000..b3a1926acc9 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/reflect/KType.kt @@ -0,0 +1,51 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.reflect + +/** + * Represents a type. Type is usually either a class with optional type arguments, + * or a type parameter of some declaration, plus nullability. + */ +public actual interface KType { + /** + * The declaration of the classifier used in this type. + * For example, in the type `List` the classifier would be the [KClass] instance for [List]. + * + * Returns `null` if this type is not denotable in Kotlin, for example if it is an intersection type. + */ + @SinceKotlin("1.1") + public actual val classifier: KClassifier? + + /** + * Type arguments passed for the parameters of the classifier in this type. + * For example, in the type `Array` the only type argument is `out Number`. + * + * In case this type is based on an inner class, the returned list contains the type arguments provided for the innermost class first, + * then its outer class, and so on. + * For example, in the type `Outer.Inner` the returned list is `[C, D, A, B]`. + */ + @SinceKotlin("1.1") + public actual val arguments: List + + /** + * `true` if this type was marked nullable in the source code. + * + * For Kotlin types, it means that `null` value is allowed to be represented by this type. + * In practice it means that the type was declared with a question mark at the end. + * For non-Kotlin types, it means the type or the symbol which was declared with this type + * is annotated with a runtime-retained nullability annotation such as [javax.annotation.Nullable]. + * + * Note that even if [isMarkedNullable] is false, values of the type can still be `null`. + * This may happen if it is a type of the type parameter with a nullable upper bound: + * + * ``` + * fun foo(t: T) { + * // isMarkedNullable == false for t's type, but t can be null here when T = "Any?" + * } + * ``` + */ + public actual val isMarkedNullable: Boolean +} diff --git a/libraries/stdlib/wasm/src/kotlin/text/Appendable.kt b/libraries/stdlib/wasm/src/kotlin/text/Appendable.kt new file mode 100644 index 00000000000..3e251ef6edc --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/text/Appendable.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +/** + * An object to which char sequences and values can be appended. + */ +actual interface Appendable { + /** + * Appends the specified character [value] to this Appendable and returns this instance. + * + * @param value the character to append. + */ + actual fun append(value: Char): Appendable + + /** + * Appends the specified character sequence [value] to this Appendable and returns this instance. + * + * @param value the character sequence to append. If [value] is `null`, then the four characters `"null"` are appended to this Appendable. + */ + actual fun append(value: CharSequence?): Appendable + + /** + * Appends a subsequence of the specified character sequence [value] to this Appendable and returns this instance. + * + * @param value the character sequence from which a subsequence is appended. If [value] is `null`, + * then characters are appended as if [value] contained the four characters `"null"`. + * @param startIndex the beginning (inclusive) of the subsequence to append. + * @param endIndex the end (exclusive) of the subsequence to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + */ + actual fun append(value: CharSequence?, startIndex: Int, endIndex: Int): Appendable +} diff --git a/libraries/stdlib/wasm/src/kotlin/text/CharacterCodingException.kt b/libraries/stdlib/wasm/src/kotlin/text/CharacterCodingException.kt new file mode 100644 index 00000000000..9e3a8aae00c --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/text/CharacterCodingException.kt @@ -0,0 +1,13 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +/** + * The exception thrown when a character encoding or decoding error occurs. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual open class CharacterCodingException actual constructor() : Exception() \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/text/StringBuilder.kt b/libraries/stdlib/wasm/src/kotlin/text/StringBuilder.kt new file mode 100644 index 00000000000..4b7037f5605 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/text/StringBuilder.kt @@ -0,0 +1,387 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.text + +/** + * A mutable sequence of characters. + * + * String builder can be used to efficiently perform multiple string manipulation operations. + */ +actual class StringBuilder : Appendable, CharSequence { + /** Constructs an empty string builder. */ + actual constructor() { TODO("Wasm stdlib: StringBuilder") } + + /** Constructs an empty string builder with the specified initial [capacity]. */ + actual constructor(capacity: Int) { TODO("Wasm stdlib: StringBuilder") } + + /** Constructs a string builder that contains the same characters as the specified [content] char sequence. */ + actual constructor(content: CharSequence) { TODO("Wasm stdlib: StringBuilder") } + + /** Constructs a string builder that contains the same characters as the specified [content] string. */ + @SinceKotlin("1.3") +// @ExperimentalStdlibApi + actual constructor(content: String) { TODO("Wasm stdlib: StringBuilder") } + + actual override val length: Int = TODO("Wasm stdlib: StringBuilder") + + actual override operator fun get(index: Int): Char = TODO("Wasm stdlib: StringBuilder") + + actual override fun subSequence(startIndex: Int, endIndex: Int): CharSequence = TODO("Wasm stdlib: StringBuilder") + + actual override fun append(value: Char): StringBuilder = TODO("Wasm stdlib: StringBuilder") + actual override fun append(value: CharSequence?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + actual override fun append(value: CharSequence?, startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Reverses the contents of this string builder and returns this instance. + * + * Surrogate pairs included in this string builder are treated as single characters. + * Therefore, the order of the high-low surrogates is never reversed. + * + * Note that the reverse operation may produce new surrogate pairs that were unpaired low-surrogates and high-surrogates before the operation. + * For example, reversing `"\uDC00\uD800"` produces `"\uD800\uDC00"` which is a valid surrogate pair. + */ + actual fun reverse(): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Appends the string representation of the specified object [value] to this string builder and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was appended to this string builder. + */ + actual fun append(value: Any?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Appends the string representation of the specified boolean [value] to this string builder and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was appended to this string builder. + */ + @SinceKotlin("1.3") +// @ExperimentalStdlibApi + actual fun append(value: Boolean): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Appends characters in the specified character array [value] to this string builder and returns this instance. + * + * Characters are appended in order, starting at the index 0. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun append(value: CharArray): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Appends the specified string [value] to this string builder and returns this instance. + */ + @SinceKotlin("1.3") +// @ExperimentalStdlibApi + actual fun append(value: String?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Returns the current capacity of this string builder. + * + * The capacity is the maximum length this string builder can have before an allocation occurs. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun capacity(): Int = TODO("Wasm stdlib: StringBuilder") + + /** + * Ensures that the capacity of this string builder is at least equal to the specified [minimumCapacity]. + * + * If the current capacity is less than the [minimumCapacity], a new backing storage is allocated with greater capacity. + * Otherwise, this method takes no action and simply returns. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun ensureCapacity(minimumCapacity: Int) { TODO("Wasm stdlib: StringBuilder") } + + /** + * Returns the index within this string builder of the first occurrence of the specified [string]. + * + * Returns `-1` if the specified [string] does not occur in this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun indexOf(string: String): Int = TODO("Wasm stdlib: StringBuilder") + + /** + * Returns the index within this string builder of the first occurrence of the specified [string], + * starting at the specified [startIndex]. + * + * Returns `-1` if the specified [string] does not occur in this string builder starting at the specified [startIndex]. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun indexOf(string: String, startIndex: Int): Int = TODO("Wasm stdlib: StringBuilder") + + /** + * Returns the index within this string builder of the last occurrence of the specified [string]. + * The last occurrence of empty string `""` is considered to be at the index equal to `this.length`. + * + * Returns `-1` if the specified [string] does not occur in this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun lastIndexOf(string: String): Int = TODO("Wasm stdlib: StringBuilder") + + /** + * Returns the index within this string builder of the last occurrence of the specified [string], + * starting from the specified [startIndex] toward the beginning. + * + * Returns `-1` if the specified [string] does not occur in this string builder starting at the specified [startIndex]. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun lastIndexOf(string: String, startIndex: Int): Int = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts the string representation of the specified boolean [value] into this string builder at the specified [index] and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was inserted into this string builder at the specified [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: Boolean): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts the specified character [value] into this string builder at the specified [index] and returns this instance. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: Char): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts characters in the specified character array [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in same order as in the [value] character array, starting at [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: CharArray): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts characters in the specified character sequence [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [value] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the character sequence from which characters are inserted. If [value] is `null`, then the four characters `"null"` are inserted. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: CharSequence?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts the string representation of the specified object [value] into this string builder at the specified [index] and returns this instance. + * + * The overall effect is exactly as if the [value] were converted to a string by the `value.toString()` method, + * and then that string was inserted into this string builder at the specified [index]. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: Any?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Inserts the string [value] into this string builder at the specified [index] and returns this instance. + * + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun insert(index: Int, value: String?): StringBuilder = TODO("Wasm stdlib: StringBuilder") + + /** + * Sets the length of this string builder to the specified [newLength]. + * + * If the [newLength] is less than the current length, it is changed to the specified [newLength]. + * Otherwise, null characters '\u0000' are appended to this string builder until its length is less than the [newLength]. + * + * Note that in Kotlin/JS [set] operator function has non-constant execution time complexity. + * Therefore, increasing length of this string builder and then updating each character by index may slow down your program. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] if [newLength] is less than zero. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun setLength(newLength: Int) { TODO("Wasm stdlib: StringBuilder") } + + /** + * Returns a new [String] that contains characters in this string builder at [startIndex] (inclusive) and up to the [length] (exclusive). + * + * @throws IndexOutOfBoundsException if [startIndex] is less than zero or greater than the length of this string builder. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun substring(startIndex: Int): String = TODO("Wasm stdlib: StringBuilder") + + /** + * Returns a new [String] that contains characters in this string builder at [startIndex] (inclusive) and up to the [endIndex] (exclusive). + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun substring(startIndex: Int, endIndex: Int): String = TODO("Wasm stdlib: StringBuilder") + + /** + * Attempts to reduce storage used for this string builder. + * + * If the backing storage of this string builder is larger than necessary to hold its current contents, + * then it may be resized to become more space efficient. + * Calling this method may, but is not required to, affect the value of the [capacity] property. + */ + @SinceKotlin("1.3") + @ExperimentalStdlibApi + actual fun trimToSize() { TODO("Wasm stdlib: StringBuilder") } +} + + +/** + * Clears the content of this string builder making it empty and returns this instance. + * + * @sample samples.text.Strings.clearStringBuilder + */ +@SinceKotlin("1.3") +public actual fun StringBuilder.clear(): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Sets the character at the specified [index] to the specified [value]. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual operator fun StringBuilder.set(index: Int, value: Char) { TODO("Wasm stdlib: StringBuilder") } + +/** + * Replaces characters in the specified range of this string builder with characters in the specified string [value] and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to replace. + * @param endIndex the end (exclusive) of the range to replace. + * @param value the string to replace with. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] if [startIndex] is less than zero, greater than the length of this string builder, or `startIndex > endIndex`. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.setRange(startIndex: Int, endIndex: Int, value: String): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Removes the character at the specified [index] from this string builder and returns this instance. + * + * If the `Char` at the specified [index] is part of a supplementary code point, this method does not remove the entire supplementary character. + * + * @param index the index of `Char` to remove. + * + * @throws IndexOutOfBoundsException if [index] is out of bounds of this string builder. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.deleteAt(index: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Removes characters in the specified range from this string builder and returns this instance. + * + * @param startIndex the beginning (inclusive) of the range to remove. + * @param endIndex the end (exclusive) of the range to remove. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.deleteRange(startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Copies characters from this string builder into the [destination] character array. + * + * @param destination the array to copy to. + * @param destinationOffset the position in the array to copy to, 0 by default. + * @param startIndex the beginning (inclusive) of the range to copy, 0 by default. + * @param endIndex the end (exclusive) of the range to copy, length of this string builder by default. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of this string builder indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException when the subrange doesn't fit into the [destination] array starting at the specified [destinationOffset], + * or when that index is out of the [destination] array indices range. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.toCharArray(destination: CharArray, destinationOffset: Int, startIndex: Int, endIndex: Int) { TODO("Wasm stdlib: StringBuilder") } + +/** + * Appends characters in a subarray of the specified character array [value] to this string builder and returns this instance. + * + * Characters are appended in order, starting at specified [startIndex]. + * + * @param value the array from which characters are appended. + * @param startIndex the beginning (inclusive) of the subarray to append. + * @param endIndex the end (exclusive) of the subarray to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.appendRange(value: CharArray, startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Appends a subsequence of the specified character sequence [value] to this string builder and returns this instance. + * + * @param value the character sequence from which a subsequence is appended. If [value] is `null`, + * then characters are appended as if [value] contained the four characters `"null"`. + * @param startIndex the beginning (inclusive) of the subsequence to append. + * @param endIndex the end (exclusive) of the subsequence to append. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.appendRange(value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Inserts characters in a subarray of the specified character array [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in same order as in the [value] array, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the array from which characters are inserted. + * @param startIndex the beginning (inclusive) of the subarray to insert. + * @param endIndex the end (exclusive) of the subarray to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] array indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.insertRange(index: Int, value: CharArray, startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") + +/** + * Inserts characters in a subsequence of the specified character sequence [value] into this string builder at the specified [index] and returns this instance. + * + * The inserted characters go in the same order as in the [value] character sequence, starting at [index]. + * + * @param index the position in this string builder to insert at. + * @param value the character sequence from which a subsequence is inserted. If [value] is `null`, + * then characters will be inserted as if [value] contained the four characters `"null"`. + * @param startIndex the beginning (inclusive) of the subsequence to insert. + * @param endIndex the end (exclusive) of the subsequence to insert. + * + * @throws IndexOutOfBoundsException or [IllegalArgumentException] when [startIndex] or [endIndex] is out of range of the [value] character sequence indices or when `startIndex > endIndex`. + * @throws IndexOutOfBoundsException if [index] is less than zero or greater than the length of this string builder. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun StringBuilder.insertRange(index: Int, value: CharSequence, startIndex: Int, endIndex: Int): StringBuilder = TODO("Wasm stdlib: StringBuilder") \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/throwableExtensions.kt b/libraries/stdlib/wasm/src/kotlin/throwableExtensions.kt new file mode 100644 index 00000000000..fc2ef231f66 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/throwableExtensions.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + +/** + * Returns the detailed description of this throwable with its stack trace. + * + * The detailed description includes: + * - the short description (see [Throwable.toString]) of this throwable; + * - the complete stack trace; + * - detailed descriptions of the exceptions that were [suppressed][suppressedExceptions] in order to deliver this exception; + * - the detailed description of each throwable in the [Throwable.cause] chain. + */ +@SinceKotlin("1.4") +public actual fun Throwable.stackTraceToString(): String = + TODO("Implement stackTraceToString") + +/** + * Prints the [detailed description][Throwable.stackTraceToString] of this throwable to console error output. + */ +@SinceKotlin("1.4") +public actual fun Throwable.printStackTrace() { + TODO("Implement printStackTrace") +} + +/** + * Adds the specified exception to the list of exceptions that were + * suppressed in order to deliver this exception. + */ +@SinceKotlin("1.4") +public actual fun Throwable.addSuppressed(exception: Throwable) { + TODO("Implement Throwable.addSuppressed") +} + +/** + * Returns a list of all exceptions that were suppressed in order to deliver this exception. + */ +@SinceKotlin("1.4") +public actual val Throwable.suppressedExceptions: List + get() { + TODO("Implement Throwable.suppressedExceptions") + } \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/time/Duration.kt b/libraries/stdlib/wasm/src/kotlin/time/Duration.kt new file mode 100644 index 00000000000..f36abccdbca --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/time/Duration.kt @@ -0,0 +1,9 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +package kotlin.time + +internal actual fun formatToExactDecimals(value: Double, decimals: Int): String = TODO("Wasm stdlib: Duration") +internal actual fun formatUpToDecimals(value: Double, decimals: Int): String = TODO("Wasm stdlib: Duration") +internal actual fun formatScientific(value: Double): String = TODO("Wasm stdlib: Duration") \ No newline at end of file diff --git a/libraries/stdlib/wasm/src/kotlin/time/DurationUnit.kt b/libraries/stdlib/wasm/src/kotlin/time/DurationUnit.kt new file mode 100644 index 00000000000..515e8385967 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/time/DurationUnit.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.time + + +/** + * The list of possible time measurement units, in which a duration can be expressed. + * + * The smallest time unit is [NANOSECONDS] and the largest is [DAYS], which corresponds to exactly 24 [HOURS]. + */ +@SinceKotlin("1.3") +@ExperimentalTime +public actual enum class DurationUnit { + /** + * Time unit representing one nanosecond, which is 1/1000 of a microsecond. + */ + NANOSECONDS, + /** + * Time unit representing one microsecond, which is 1/1000 of a millisecond. + */ + MICROSECONDS, + /** + * Time unit representing one millisecond, which is 1/1000 of a second. + */ + MILLISECONDS, + /** + * Time unit representing one second. + */ + SECONDS, + /** + * Time unit representing one minute. + */ + MINUTES, + /** + * Time unit representing one hour. + */ + HOURS, + /** + * Time unit representing one day, which is always equal to 24 hours. + */ + DAYS; +} + +/** Converts the given time duration [value] expressed in the specified [sourceUnit] into the specified [targetUnit]. */ +@SinceKotlin("1.3") +@ExperimentalTime +internal actual fun convertDurationUnit(value: Double, sourceUnit: DurationUnit, targetUnit: DurationUnit): Double = TODO("Wasm stdlib: convertDurationUnit") diff --git a/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt b/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt new file mode 100644 index 00000000000..2438fe3cebd --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/time/TimeSources.kt @@ -0,0 +1,11 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ +package kotlin.time + +@SinceKotlin("1.3") +@ExperimentalTime +internal actual object MonotonicTimeSource : TimeSource { + override fun markNow(): TimeMark = TODO("Wasm stdlib: MonotonicTimeSource::markNow") +} diff --git a/libraries/stdlib/wasm/src/kotlin/util/Numbers.kt b/libraries/stdlib/wasm/src/kotlin/util/Numbers.kt new file mode 100644 index 00000000000..e84353a1fa4 --- /dev/null +++ b/libraries/stdlib/wasm/src/kotlin/util/Numbers.kt @@ -0,0 +1,138 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + +/** + * Counts the number of set bits in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countOneBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countLeadingZeroBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Int] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.countTrailingZeroBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.takeHighestOneBit(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Int] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.takeLowestOneBit(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Rotates the binary representation of this [Int] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateLeft(bitCount: Int): Int = TODO("Wasm stdlib: Numbers") + + +/** + * Rotates the binary representation of this [Int] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Int.SIZE_BITS] (32) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 32)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Int.rotateRight(bitCount: Int): Int = TODO("Wasm stdlib: Numbers") + + +/** + * Counts the number of set bits in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countOneBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Counts the number of consecutive most significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countLeadingZeroBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Counts the number of consecutive least significant bits that are zero in the binary representation of this [Long] number. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.countTrailingZeroBits(): Int = TODO("Wasm stdlib: Numbers") + +/** + * Returns a number having a single bit set in the position of the most significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.takeHighestOneBit(): Long = TODO("Wasm stdlib: Numbers") + +/** + * Returns a number having a single bit set in the position of the least significant set bit of this [Long] number, + * or zero, if this number is zero. + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.takeLowestOneBit(): Long = TODO("Wasm stdlib: Numbers") + +/** + * Rotates the binary representation of this [Long] number left by the specified [bitCount] number of bits. + * The most significant bits pushed out from the left side reenter the number as the least significant bits on the right side. + * + * Rotating the number left by a negative bit count is the same as rotating it right by the negated bit count: + * `number.rotateLeft(-n) == number.rotateRight(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateLeft(n) == number.rotateLeft(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.rotateLeft(bitCount: Int): Long = TODO("Wasm stdlib: Numbers") + +/** + * Rotates the binary representation of this [Long] number right by the specified [bitCount] number of bits. + * The least significant bits pushed out from the right side reenter the number as the most significant bits on the left side. + * + * Rotating the number right by a negative bit count is the same as rotating it left by the negated bit count: + * `number.rotateRight(-n) == number.rotateLeft(n)` + * + * Rotating by a multiple of [Long.SIZE_BITS] (64) returns the same number, or more generally + * `number.rotateRight(n) == number.rotateRight(n % 64)` + */ +@SinceKotlin("1.3") +@ExperimentalStdlibApi +public actual fun Long.rotateRight(bitCount: Int): Long = TODO("Wasm stdlib: Numbers") diff --git a/libraries/stdlib/wasm/stubs/experimentalPackageStub.kt b/libraries/stdlib/wasm/stubs/experimentalPackageStub.kt new file mode 100644 index 00000000000..9d00c812f07 --- /dev/null +++ b/libraries/stdlib/wasm/stubs/experimentalPackageStub.kt @@ -0,0 +1,8 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.experimental + +// In some tests `import kotlin.experimental*` is used without actually importing anything \ No newline at end of file diff --git a/libraries/stdlib/wasm/stubs/testHelpers.kt b/libraries/stdlib/wasm/stubs/testHelpers.kt new file mode 100644 index 00000000000..4b51e714be5 --- /dev/null +++ b/libraries/stdlib/wasm/stubs/testHelpers.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin.test + +import kotlin.internal.OnlyInputTypes + +public fun assert(x: Boolean) { + if (!x) throw AssertionError("Assertion failed") +} + +/** Asserts that the [expected] value is equal to the [actual] value, with an optional [message]. */ +public fun <@OnlyInputTypes T> assertEquals(expected: T, actual: T, message: String? = null) { + if (expected != actual) throw AssertionError("assertEquals failed: expected:$expected, actual:$actual, message=$message") +} + +/** Asserts that the [actual] value is not equal to the illegal value, with an optional [message]. */ +public fun <@OnlyInputTypes T> assertNotEquals(illegal: T, actual: T, message: String? = null) { + if (illegal == actual) throw AssertionError("assertNotEquals failed: illegal:$illegal, actual:$actual, message=$message") +} diff --git a/libraries/stdlib/wasm/stubs/testHelpers2.kt b/libraries/stdlib/wasm/stubs/testHelpers2.kt new file mode 100644 index 00000000000..bae3a0dbeb9 --- /dev/null +++ b/libraries/stdlib/wasm/stubs/testHelpers2.kt @@ -0,0 +1,17 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package kotlin + +import kotlin.internal.OnlyInputTypes + +public fun assert(x: Boolean) { + if (!x) throw AssertionError("Assertion failed") +} + +/** Asserts that the [expected] value is equal to the [actual] value, with an optional [message]. */ +public fun <@OnlyInputTypes T> assertEquals(expected: T, actual: T, message: String? = null) { + if (expected != actual) throw AssertionError("assertEquals failed: expected:$expected, actual:$actual, message=$message") +} \ No newline at end of file diff --git a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt index e1d638f1a04..c1a7fbb243e 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/generators/GenerateStandardLib.kt @@ -46,6 +46,7 @@ fun main(args: Array) { targetBaseDirs[KotlinTarget.JVM] = baseDir.resolveExistingDir("libraries/stdlib/jvm/src/generated") targetBaseDirs[KotlinTarget.JS] = baseDir.resolveExistingDir("libraries/stdlib/js/src/generated") targetBaseDirs[KotlinTarget.JS_IR] = baseDir.resolveExistingDir("libraries/stdlib/js-ir/src/generated") + targetBaseDirs[KotlinTarget.WASM] = baseDir.resolveExistingDir("libraries/stdlib/wasm/src/generated") } 2 -> { val (targetName, targetDir) = args @@ -65,6 +66,7 @@ fun main(args: Array) { val targetDir = targetBaseDirs[target] ?: error("Target $target directory is not configured") val platformSuffix = when (val platform = target.platform) { Platform.Common -> "" + Platform.Native -> if (target.backend == Backend.Wasm) "Wasm" else "Native" else -> platform.name.toLowerCase().capitalize() } targetDir.resolve("_${source.name.capitalize()}$platformSuffix.kt") diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt index c7899caff50..196ffc4f090 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/Arrays.kt @@ -919,6 +919,9 @@ object ArrayOps : TemplateGroupBase() { """ } } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } } } @@ -1046,6 +1049,9 @@ object ArrayOps : TemplateGroupBase() { return result """ } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } val f_copyOf = fn("copyOf()") { @@ -1154,6 +1160,9 @@ object ArrayOps : TemplateGroupBase() { } on(Platform.Native) { body { "return this.copyOfNulls(newSize)" } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } } specialFor(ArraysOfPrimitives, InvariantArraysOfObjects) { @@ -1233,6 +1242,9 @@ object ArrayOps : TemplateGroupBase() { } on(Platform.Native) { body { """if (size > 1) sortArray(this, 0, size)""" } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } } } @@ -1255,6 +1267,9 @@ object ArrayOps : TemplateGroupBase() { } on(Platform.Native) { body { """if (size > 1) sortArrayWith(this, 0, size, comparator)""" } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } } @@ -1363,6 +1378,9 @@ object ArrayOps : TemplateGroupBase() { sortArray(this, fromIndex, toIndex) """ } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } on(Platform.JS) { since("1.4") @@ -1419,6 +1437,9 @@ object ArrayOps : TemplateGroupBase() { sortArrayWith(this, fromIndex, toIndex, comparator) """ } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } on(Platform.JS) { since("1.4") @@ -1624,6 +1645,9 @@ object ArrayOps : TemplateGroupBase() { body { "arrayFill(this, fromIndex, toIndex, element)" } + on(Backend.Wasm) { + body { """TODO("Wasm stdlib: $signature")""" } + } } on(Platform.Common) { since("1.3") diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt index a29e2b82b70..e0ef31999c3 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/CommonTypes.kt @@ -106,13 +106,14 @@ enum class Platform { Common, JVM, JS, - Native + Native, } enum class Backend { Any, Legacy, - IR + IR, + Wasm, } enum class KotlinTarget(val platform: Platform, val backend: Backend) { @@ -120,6 +121,7 @@ enum class KotlinTarget(val platform: Platform, val backend: Backend) { JVM(Platform.JVM, Backend.Any), JS(Platform.JS, Backend.Legacy), JS_IR(Platform.JS, Backend.IR), + WASM(Platform.Native, Backend.Wasm), Native(Platform.Native, Backend.IR); val fullName get() = "Kotlin/$name" diff --git a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt index 9a3acc6e0fa..fe73be79907 100644 --- a/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt +++ b/libraries/tools/kotlin-stdlib-gen/src/templates/dsl/MemberBuilder.kt @@ -159,7 +159,7 @@ class MemberBuilder( } fun on(backend: Backend, action: () -> Unit) { - require(target.platform == Platform.JS) + require(target.platform == Platform.JS || target.platform == Platform.Native) if (target.backend == backend) action() } diff --git a/wasm/wasm.ir/build.gradle.kts b/wasm/wasm.ir/build.gradle.kts index 0161aeb5dbc..8acead9d371 100644 --- a/wasm/wasm.ir/build.gradle.kts +++ b/wasm/wasm.ir/build.gradle.kts @@ -1,7 +1,7 @@ plugins { kotlin("jvm") id("jps-compatible") - kotlin("plugin.serialization") version "1.4.10" + kotlin("plugin.serialization") } dependencies { diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt index 3010da3cef3..cbc7e971293 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Declarations.kt @@ -53,7 +53,7 @@ sealed class WasmFunction( } class WasmMemory( - val limits: WasmLimits = WasmLimits(1u, null), + val limits: WasmLimits, val importPair: WasmImportPair? = null, ) : WasmNamedModuleField() diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt index 77f3637d5ba..4ba81b2ed90 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/Types.kt @@ -12,6 +12,7 @@ sealed class WasmType( override fun toString(): String = name } +// TODO: Remove this type. object WasmUnreachableType : WasmType("unreachable", -0x40) object WasmI32 : WasmType("i32", -0x1) object WasmI1 : WasmType("i32", -0x1) @@ -26,7 +27,7 @@ object WasmExternRef : WasmType("externref", -0x11) object WasmAnyRef : WasmType("anyref", -0x12) object WasmEqRef : WasmType("eqref", -0x13) -class WasmRefNullType(val heapType: WasmHeapType) : WasmType("optref", -0x14) +class WasmRefNullType(val heapType: WasmHeapType) : WasmType("ref null", -0x14) class WasmRefType(val heapType: WasmHeapType) : WasmType("ref", -0x15) @Suppress("unused") diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt index 0db3c67eb6a..614569d9a68 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmExpressionBuilder.kt @@ -5,9 +5,9 @@ package org.jetbrains.kotlin.wasm.ir -interface WasmExpressionBuilder { - fun buildInstr(op: WasmOp, vararg immediates: WasmImmediate) - var numberOfNestedBlocks: Int +abstract class WasmExpressionBuilder { + abstract fun buildInstr(op: WasmOp, vararg immediates: WasmImmediate) + abstract var numberOfNestedBlocks: Int fun buildConstI32(value: Int) { buildInstr(WasmOp.I32_CONST, WasmImmediate.ConstI32(value)) @@ -118,7 +118,7 @@ interface WasmExpressionBuilder { } - fun buildStructNarrow(fromType: WasmType, toType: WasmType) { + fun buildRefCast(fromType: WasmType, toType: WasmType) { buildInstr( WasmOp.REF_CAST, WasmImmediate.HeapType(fromType.getHeapType()), diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmIrExpressionBuilder.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmIrExpressionBuilder.kt index 122af82aaff..ff782b18a8a 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmIrExpressionBuilder.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/WasmIrExpressionBuilder.kt @@ -7,7 +7,7 @@ package org.jetbrains.kotlin.wasm.ir class WasmIrExpressionBuilder( val expression: MutableList -) : WasmExpressionBuilder { +) : WasmExpressionBuilder() { override fun buildInstr(op: WasmOp, vararg immediates: WasmImmediate) { expression.add(WasmInstr(op, immediates.toList())) diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/BinaryToAst.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt similarity index 99% rename from wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/BinaryToAst.kt rename to wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt index 23208979c6b..a9c38336fc4 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/BinaryToAst.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmBinaryToIR.kt @@ -328,7 +328,9 @@ class WasmBinaryToIR(val b: MyByteReader) { elements = elements, data = data, dataCount = dataCount - ) + ).also { + it.calculateIds() + } } private fun readLimits(): WasmLimits { diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToBinary.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt similarity index 99% rename from wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToBinary.kt rename to wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt index d41142a68b4..de4a563c981 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToBinary.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToBinary.kt @@ -11,7 +11,7 @@ import org.jetbrains.kotlin.wasm.ir.* import java.io.ByteArrayOutputStream import java.io.OutputStream -class WasmBinaryBuilder(outputStream: OutputStream, val module: WasmModule) { +class WasmIrToBinary(outputStream: OutputStream, val module: WasmModule) { var b: ByteWriter = ByteWriter.OutputStream(outputStream) fun appendWasmModule() { diff --git a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToWat.kt b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt similarity index 99% rename from wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToWat.kt rename to wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt index 6b501da6fef..f2b4b5ecc3d 100644 --- a/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmAstToWat.kt +++ b/wasm/wasm.ir/src/org/jetbrains/kotlin/wasm/ir/convertors/WasmIrToText.kt @@ -45,7 +45,7 @@ open class SExpressionBuilder { } -class WatBuilder : SExpressionBuilder() { +class WasmIrToText : SExpressionBuilder() { fun appendOffset(value: UInt) { if (value != 0u) appendElement("offset=$value") diff --git a/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt b/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt index e062e83ccc4..875c4849012 100644 --- a/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt +++ b/wasm/wasm.ir/test/org/jetbrains/kotlin/wasm/ir/SpecTestRunner.kt @@ -11,9 +11,9 @@ import kotlinx.serialization.json.Json import org.jetbrains.kotlin.test.KotlinTestUtils.assertEqualsToFile import org.jetbrains.kotlin.utils.fileUtils.withReplacedExtensionOrNull import org.jetbrains.kotlin.wasm.ir.convertors.MyByteReader -import org.jetbrains.kotlin.wasm.ir.convertors.WasmBinaryBuilder +import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToBinary import org.jetbrains.kotlin.wasm.ir.convertors.WasmBinaryToIR -import org.jetbrains.kotlin.wasm.ir.convertors.WatBuilder +import org.jetbrains.kotlin.wasm.ir.convertors.WasmIrToText import java.io.ByteArrayOutputStream import java.io.File @@ -135,24 +135,6 @@ private fun runSpecTest(specTest: SpecTest, testDir: File, wastFile: File, wabtO val wasmFile = File(testDir, command.filename) testWasmFile(wasmFile, testDir.name) } - is SpecTest.Command.Register -> { - } - is SpecTest.Command.AssertReturn -> { - } - is SpecTest.Command.AssertTrap -> { - } - is SpecTest.Command.AssertExhaustion -> { - } - is SpecTest.Command.AssertMalformed -> { - } - is SpecTest.Command.AssertInvalid -> { - } - is SpecTest.Command.AssertUnlinkable -> { - } - is SpecTest.Command.AssertUninstantiable -> { - } - is SpecTest.Command.ActionCommand -> { - } } } } @@ -221,7 +203,6 @@ fun testWasmFile(wasmFile: File, dirName: String) { println("Testing wasm file : ${wasmFile.absolutePath} ... ") val module = fileToWasmModule(wasmFile) - module.calculateIds() val kotlinTextFormat = module.toTextFormat() val kotlinBinaryFormat = module.toBinaryFormat() @@ -248,12 +229,12 @@ fun testWasmFile(wasmFile: File, dirName: String) { fun WasmModule.toBinaryFormat(): ByteArray { val os = ByteArrayOutputStream() - WasmBinaryBuilder(os, this).appendWasmModule() + WasmIrToBinary(os, this).appendWasmModule() return os.toByteArray() } fun WasmModule.toTextFormat(): String { - val builder = WatBuilder() + val builder = WasmIrToText() builder.appendWasmModule(this) return builder.toString() }