diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt new file mode 100644 index 00000000000..ef748e266bb --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayConstructor.kt @@ -0,0 +1,30 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +object ArrayConstructor : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt new file mode 100644 index 00000000000..64e93535d30 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayGet.kt @@ -0,0 +1,30 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ArrayGet : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val type = expressionType(expression, context) + return IrIntrinsicFunction.create(expression, signature, context) { + it.aload(type) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt new file mode 100644 index 00000000000..0185fcf5e5d --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayIterator.kt @@ -0,0 +1,39 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ArrayIterator : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val method = context.state.typeMapper.mapToCallableMethod(expression.descriptor as FunctionDescriptor, false) + return IrIntrinsicFunction.create(expression, signature, method.owner) { + val methodSignature = "(${method.owner.descriptor})${method.returnType.descriptor}" + val intrinsicOwner = + if (AsmUtil.isPrimitive(method.owner.elementType)) + "kotlin/jvm/internal/ArrayIteratorsKt" + else + "kotlin/jvm/internal/ArrayIteratorKt" + it.invokestatic(intrinsicOwner, "iterator", methodSignature, false) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt new file mode 100644 index 00000000000..93fd0ccc4d4 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArrayOf.kt @@ -0,0 +1,30 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ArrayOf : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + //do nothing all generated as vararg + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt new file mode 100644 index 00000000000..a477a58f610 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySet.kt @@ -0,0 +1,46 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ArraySet : IntrinsicMethod() { + + /*TODO return type, types*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val type = expressionType(expression.dispatchReceiver!!, context) + return IrIntrinsicFunction.create(expression, signature, context) { + it.astore(signature.valueParameters.last().asmType) + } + } + + /*override fun toCallable(method: CallableMethod): Callable { + val type = correctElementType(method.dispatchReceiverType) + return object : IntrinsicCallable( + Type.VOID_TYPE, + listOf(Type.INT_TYPE, type), + method.dispatchReceiverType, + method.extensionReceiverType + ) { + override fun invokeIntrinsic(v: InstructionAdapter) { + v.astore(type) + } + } + }*/ +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt new file mode 100644 index 00000000000..e6ecd556562 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ArraySize.kt @@ -0,0 +1,31 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ArraySize : IntrinsicMethod() { + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, context) { + it.arraylength() + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt new file mode 100644 index 00000000000..357468371ee --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/BinaryOp.kt @@ -0,0 +1,49 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Opcodes.* +import org.jetbrains.org.objectweb.asm.Type + +class BinaryOp(private val opcode: Int) : IntrinsicMethod() { + private fun shift(): Boolean = + opcode == ISHL || opcode == ISHR || opcode == IUSHR + + /*TODO new return type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val owner = context.state.typeMapper.mapOwner(expression.descriptor) + val returnType = signature.returnType + val intermediateResultType: Type = numberFunctionOperandType(returnType) + val argTypes = if (owner != Type.CHAR_TYPE) { + listOf(intermediateResultType, if (shift()) Type.INT_TYPE else intermediateResultType) + } + else { + listOf(Type.CHAR_TYPE, signature.valueParameters[0].asmType) + } + + return IrIntrinsicFunction.create(expression, signature, argTypes) { + it.visitInsn(returnType.getOpcode(opcode)) + StackValue.coerce(intermediateResultType, returnType, it) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt new file mode 100644 index 00000000000..24a954a28a5 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Clone.kt @@ -0,0 +1,42 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class Clone : IntrinsicMethod() { + + /*TODO return type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + val opcode = if (expression is IrCall && expression.superQualifier != null) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL + it.visitMethodInsn(opcode, "java/lang/Object", "clone", "()Ljava/lang/Object;", false) + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt new file mode 100644 index 00000000000..b495babf824 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/CompareTo.kt @@ -0,0 +1,48 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import java.lang.UnsupportedOperationException + +class CompareTo : IntrinsicMethod() { + private fun genInvoke(type: Type?, v: InstructionAdapter) { + when (type) { + Type.INT_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false) + Type.LONG_TYPE -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false) + Type.FLOAT_TYPE -> v.invokestatic("java/lang/Float", "compare", "(FF)I", false) + Type.DOUBLE_TYPE -> v.invokestatic("java/lang/Double", "compare", "(DD)I", false) + else -> throw UnsupportedOperationException() + } + } + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val parameterType = comparisonOperandType( + expressionType(expression.dispatchReceiver ?: expression.extensionReceiver!!, context), + signature.valueParameters.single().asmType + ) + return IrIntrinsicFunction.create(expression, signature, listOf(parameterType, parameterType)) { + genInvoke(parameterType, it) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt new file mode 100644 index 00000000000..b1506e0a257 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Concat.kt @@ -0,0 +1,102 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import com.intellij.psi.PsiElement +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.codegen.AsmUtil.genInvokeAppendMethod +import org.jetbrains.kotlin.codegen.AsmUtil.genStringBuilderConstructor +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.psi.KtCallableReferenceExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class Concat : IntrinsicMethod() { + fun generateImpl( + codegen: ExpressionCodegen, + v: InstructionAdapter, + returnType: Type, + element: PsiElement?, + arguments: List, + receiver: StackValue + ): Type { + if (element is KtBinaryExpression && element.operationReference.getReferencedNameElementType() == KtTokens.PLUS) { + // LHS + RHS + genStringBuilderConstructor(v) + codegen.invokeAppend(element.left) + codegen.invokeAppend(element.right) + } + else { + // LHS?.plus(RHS) + receiver.put(AsmTypes.OBJECT_TYPE, v) + genStringBuilderConstructor(v) + v.swap() + genInvokeAppendMethod(v, returnType) + codegen.invokeAppend(arguments.get(0)) + } + + v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false) + return JAVA_STRING_TYPE + } + + override fun toCallable(method: CallableMethod): Callable = + object : IntrinsicCallable(method) { + override fun invokeMethodWithArguments( + resolvedCall: ResolvedCall<*>, + receiver: StackValue, + codegen: ExpressionCodegen + ): StackValue { + if (resolvedCall.call.callElement.parent is KtCallableReferenceExpression) { + // NB we come here only in case of inlined callable reference to String::plus. + // This will map arguments properly, invoking callbacks defined in Callable. + return super.invokeMethodWithArguments(resolvedCall, receiver, codegen) + } + return StackValue.operation(returnType) { + val arguments = resolvedCall.call.valueArguments.map { it.getArgumentExpression()!! } + val actualType = generateImpl( + codegen, it, returnType, + resolvedCall.call.callElement, + arguments, + StackValue.receiver(resolvedCall, receiver, codegen, this) + ) + StackValue.coerce(actualType, returnType, it) + } + } + + override fun afterReceiverGeneration(v: InstructionAdapter) { + v.visitTypeInsn(Opcodes.NEW, "java/lang/StringBuilder") + v.dupX1() + v.swap() + v.invokespecial("java/lang/StringBuilder", "", "(Ljava/lang/String;)V", false) + } + + override fun invokeIntrinsic(v: InstructionAdapter) { + // String::plus has type String.(Any?) -> String, thus we have no argument type information + // in case of callable reference passed to a generic function, e.g.: + // charArrayOf('O', 'K').fold("", String::plus) + // TODO Make String::plus generic, and invoke proper StringBuilder#append. + AsmUtil.genInvokeAppendMethod(v, AsmTypes.OBJECT_TYPE) + v.invokevirtual("java/lang/StringBuilder", "toString", "()Ljava/lang/String;", false) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt new file mode 100644 index 00000000000..29cc7feec0d --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Equals.kt @@ -0,0 +1,59 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import com.intellij.psi.tree.IElementType +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.* +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin +import org.jetbrains.kotlin.ir.expressions.impl.IrBinaryPrimitiveImpl +import org.jetbrains.kotlin.lexer.KtTokens +import org.jetbrains.kotlin.psi2ir.generators.getInfixOperator +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class Equals(val operator: IElementType) : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val binary = expression as IrBinaryPrimitiveImpl + var leftType = context.state.typeMapper.mapType(binary.argument0.type) + var rightType = context.state.typeMapper.mapType(binary.argument1.type) + + if (isPrimitive(leftType) != isPrimitive(rightType)) { + leftType = boxType(leftType) + rightType = boxType(rightType) + } + + + return object: IrIntrinsicFunction(expression, signature, listOf(leftType, rightType)) { + override fun genInvokeInstruction(v: InstructionAdapter) { + val opToken = binary.origin + if (opToken === KtTokens.EQEQEQ || opToken === KtTokens.EXCLEQEQEQ) { + // TODO: always casting to the type of the left operand in case of primitives looks wrong + val operandType = if (isPrimitive(leftType)) leftType else OBJECT_TYPE + StackValue.cmp(operator, operandType, StackValue.onStack(leftType), StackValue.onStack(rightType)) + } + + genEqualsForExpressionsOnStack(operator, StackValue.onStack(leftType), StackValue.onStack(rightType)).put(Type.BOOLEAN_TYPE, v) + } + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt new file mode 100644 index 00000000000..ab28c7613cb --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/HashCode.kt @@ -0,0 +1,38 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class HashCode : IntrinsicMethod() { + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, AsmTypes.OBJECT_TYPE) { + it.visitMethodInsn(Opcodes.INVOKEVIRTUAL, "java/lang/Object", "hashCode", "()I", false) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt new file mode 100644 index 00000000000..8abfe9900ea --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Increment.kt @@ -0,0 +1,30 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.genIncrement +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class Increment(private val myDelta: Int) : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, context) { + genIncrement(signature.returnType, myDelta, it) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicCallable.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicCallable.kt new file mode 100644 index 00000000000..21e1b14ed8f --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicCallable.kt @@ -0,0 +1,112 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import java.lang.UnsupportedOperationException + +open class IntrinsicCallable( + override val returnType: Type, + override val valueParameterTypes: List, + override val dispatchReceiverType: Type?, + override val extensionReceiverType: Type?, + private val invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit = { throw UnsupportedOperationException() } +) : Callable { + + constructor( + callable: CallableMethod, + invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit = {} + ) : this( + callable.returnType, + callable.valueParameterTypes, + callable.dispatchReceiverType, + callable.extensionReceiverType, + invoke + ) + + override fun genInvokeInstruction(v: InstructionAdapter) { + invokeIntrinsic(v) + } + + open fun invokeIntrinsic(v: InstructionAdapter) { + invoke(v) + } + + override val parameterTypes: Array + get() = throw UnsupportedOperationException() + + override fun isStaticCall() = false + + override val generateCalleeType: Type? + get() = null + + override val owner: Type + get() = throw UnsupportedOperationException() + + fun calcReceiverType(): Type = + extensionReceiverType ?: dispatchReceiverType!! +} + +fun createBinaryIntrinsicCallable( + returnType: Type, + valueParameterType: Type, + thisType: Type? = null, + receiverType: Type? = null, + lambda: IntrinsicCallable.(v: InstructionAdapter) -> Unit +): IntrinsicCallable { + assert(AsmUtil.isPrimitive(returnType)) { "Return type of BinaryOp intrinsic should be of primitive type: $returnType" } + + return object : IntrinsicCallable(returnType, listOf(valueParameterType), thisType, receiverType) { + override fun invokeIntrinsic(v: InstructionAdapter) { + lambda(v) + } + } +} + +fun createUnaryIntrinsicCallable( + callable: CallableMethod, + newReturnType: Type? = null, + needPrimitiveCheck: Boolean = false, + newThisType: Type? = null, + invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit +): IntrinsicCallable { + val intrinsic = IntrinsicCallable( + newReturnType ?: callable.returnType, + callable.valueParameterTypes, + newThisType ?: callable.dispatchReceiverType, + callable.extensionReceiverType, + invoke + ) + assert(intrinsic.valueParameterTypes.isEmpty()) { "Unary operation should not have any parameters" } + if (needPrimitiveCheck) { + assert(AsmUtil.isPrimitive(intrinsic.returnType)) { + "Return type of UnaryPlus intrinsic should be of primitive type: ${intrinsic.returnType}" + } + } + return intrinsic +} + +fun createIntrinsicCallable( + callable: CallableMethod, + invoke: IntrinsicCallable.(v: InstructionAdapter) -> Unit +): IntrinsicCallable { + return IntrinsicCallable(callable, invoke) +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt new file mode 100644 index 00000000000..e8e9c20256c --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethod.kt @@ -0,0 +1,65 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type + +abstract class IntrinsicMethod { + + open fun toCallable( + expression: IrMemberAccessExpression, + signature: JvmMethodSignature, + context: JvmBackendContext + ): IrIntrinsicFunction { + TODO() + } + + + open fun toCallable( + fd: FunctionDescriptor, + isSuper: Boolean, + resolvedCall: ResolvedCall<*>, + codegen: ExpressionCodegen + ): Callable { + throw UnsupportedOperationException("Not implemented") + } + + open fun toCallable(method: CallableMethod): Callable { + throw UnsupportedOperationException("Not implemented") + } + + + companion object { + fun calcReceiverType(call: IrMemberAccessExpression, context: JvmBackendContext): Type { + return context.state.typeMapper.mapType(call.dispatchReceiver?.type ?: call.extensionReceiver!!.type) + } + + fun expressionType(expression: IrExpression, context: JvmBackendContext): Type { + return context.state.typeMapper.mapType(expression.type) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java new file mode 100644 index 00000000000..58441c62280 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicMethods.java @@ -0,0 +1,181 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics; + +import com.google.common.collect.ImmutableList; +import kotlin.text.StringsKt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.builtins.PrimitiveType; +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; +import org.jetbrains.kotlin.lexer.KtTokens; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.name.FqNameUnsafe; +import org.jetbrains.kotlin.name.Name; +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; +import org.jetbrains.kotlin.types.expressions.OperatorConventions; + +import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.*; +import static org.jetbrains.org.objectweb.asm.Opcodes.*; + +public class IntrinsicMethods { + public static final String INTRINSICS_CLASS_NAME = "kotlin/jvm/internal/Intrinsics"; + + private static final FqName KOTLIN_JVM = new FqName("kotlin.jvm"); + /* package */ static final FqNameUnsafe RECEIVER_PARAMETER_FQ_NAME = new FqNameUnsafe("T"); + + private static final IntrinsicMethod UNARY_MINUS = new UnaryMinus(); + private static final IntrinsicMethod UNARY_PLUS = new UnaryPlus(); + private static final IntrinsicMethod NUMBER_CAST = new NumberCast(); + private static final IntrinsicMethod INV = new Inv(); + private static final IntrinsicMethod RANGE_TO = new RangeTo(); + private static final IntrinsicMethod INC = new Increment(1); + private static final IntrinsicMethod DEC = new Increment(-1); + private static final IntrinsicMethod HASH_CODE = new HashCode(); + + private static final IntrinsicMethod ARRAY_SIZE = new ArraySize(); + private static final Equals EQUALS = new Equals(KtTokens.EQEQ); + private static final IteratorNext ITERATOR_NEXT = new IteratorNext(); + private static final ArraySet ARRAY_SET = new ArraySet(); + private static final ArrayGet ARRAY_GET = new ArrayGet(); + private static final StringPlus STRING_PLUS = new StringPlus(); + private static final ToString TO_STRING = new ToString(); + private static final Clone CLONE = new Clone(); + + private static final IntrinsicMethod ARRAY_ITERATOR = new ArrayIterator(); + private final IntrinsicsMap intrinsicsMap = new IntrinsicsMap(); + + public IntrinsicMethods() { + intrinsicsMap.registerIntrinsic(KOTLIN_JVM, RECEIVER_PARAMETER_FQ_NAME, "javaClass", -1, JavaClassProperty.INSTANCE); + intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.kClass, "java", -1, new KClassJavaProperty()); + intrinsicsMap.registerIntrinsic(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe(), null, "name", -1, new KCallableNameProperty()); + intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorEnter", 1, MonitorInstruction.MONITOR_ENTER); + intrinsicsMap.registerIntrinsic(new FqName("kotlin.jvm.internal.unsafe"), null, "monitorExit", 1, MonitorInstruction.MONITOR_EXIT); + intrinsicsMap.registerIntrinsic(KOTLIN_JVM, KotlinBuiltIns.FQ_NAMES.array, "isArrayOf", 0, new IsArrayOf()); + + intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOf", 1, new ArrayOf()); + + ImmutableList primitiveCastMethods = OperatorConventions.NUMBER_CONVERSIONS.asList(); + for (Name method : primitiveCastMethods) { + String methodName = method.asString(); + declareIntrinsicFunction(FQ_NAMES.number, methodName, 0, NUMBER_CAST); + for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) { + declareIntrinsicFunction(type.getTypeFqName(), methodName, 0, NUMBER_CAST); + } + } + + for (PrimitiveType type : PrimitiveType.NUMBER_TYPES) { + FqName typeFqName = type.getTypeFqName(); + declareIntrinsicFunction(typeFqName, "plus", 0, UNARY_PLUS); + declareIntrinsicFunction(typeFqName, "unaryPlus", 0, UNARY_PLUS); + declareIntrinsicFunction(typeFqName, "minus", 0, UNARY_MINUS); + declareIntrinsicFunction(typeFqName, "unaryMinus", 0, UNARY_MINUS); + declareIntrinsicFunction(typeFqName, "inv", 0, INV); + declareIntrinsicFunction(typeFqName, "rangeTo", 1, RANGE_TO); + declareIntrinsicFunction(typeFqName, "inc", 0, INC); + declareIntrinsicFunction(typeFqName, "dec", 0, DEC); + } + + for (PrimitiveType type : PrimitiveType.values()) { + FqName typeFqName = type.getTypeFqName(); + declareIntrinsicFunction(typeFqName, "equals", 1, EQUALS); + declareIntrinsicFunction(typeFqName, "hashCode", 0, HASH_CODE); + declareIntrinsicFunction(typeFqName, "toString", 0, TO_STRING); + + intrinsicsMap.registerIntrinsic( + BUILT_INS_PACKAGE_FQ_NAME, null, StringsKt.decapitalize(type.getArrayTypeName().asString()) + "Of", 1, new ArrayOf() + ); + } + + declareBinaryOp("plus", IADD); + declareBinaryOp("minus", ISUB); + declareBinaryOp("times", IMUL); + declareBinaryOp("div", IDIV); + declareBinaryOp("mod", IREM); + declareBinaryOp("shl", ISHL); + declareBinaryOp("shr", ISHR); + declareBinaryOp("ushr", IUSHR); + declareBinaryOp("and", IAND); + declareBinaryOp("or", IOR); + declareBinaryOp("xor", IXOR); + + declareIntrinsicFunction(FQ_NAMES._boolean, "not", 0, new Not()); + + declareIntrinsicFunction(FQ_NAMES.string, "plus", 1, new Concat()); + declareIntrinsicFunction(FQ_NAMES.string, "get", 1, new StringGetChar()); + + declareIntrinsicFunction(FQ_NAMES.cloneable, "clone", 0, CLONE); + + intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.any, "toString", 0, TO_STRING); + intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, KotlinBuiltIns.FQ_NAMES.string, "plus", 1, STRING_PLUS); + intrinsicsMap.registerIntrinsic(BUILT_INS_PACKAGE_FQ_NAME, null, "arrayOfNulls", 1, new NewArray()); + + for (PrimitiveType type : PrimitiveType.values()) { + declareIntrinsicFunction(type.getTypeFqName(), "compareTo", 1, new CompareTo()); + declareIntrinsicFunction(COLLECTIONS_PACKAGE_FQ_NAME.child(Name.identifier(type.getTypeName().asString() + "Iterator")), "next", 0, ITERATOR_NEXT); + } + + declareArrayMethods(); + } + + private void declareArrayMethods() { + for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { + declareArrayMethods(jvmPrimitiveType.getPrimitiveType().getArrayTypeFqName()); + } + declareArrayMethods(FQ_NAMES.array.toSafe()); + } + + private void declareArrayMethods(@NotNull FqName arrayTypeFqName) { + declareIntrinsicFunction(arrayTypeFqName, "size", -1, ARRAY_SIZE); + declareIntrinsicFunction(arrayTypeFqName, "set", 2, ARRAY_SET); + declareIntrinsicFunction(arrayTypeFqName, "get", 1, ARRAY_GET); + declareIntrinsicFunction(arrayTypeFqName, "clone", 0, CLONE); + declareIntrinsicFunction(arrayTypeFqName, "iterator", 0, ARRAY_ITERATOR); + declareIntrinsicFunction(arrayTypeFqName, "", 2, ArrayConstructor.INSTANCE); + } + + private void declareBinaryOp(@NotNull String methodName, int opcode) { + BinaryOp op = new BinaryOp(opcode); + for (PrimitiveType type : PrimitiveType.values()) { + declareIntrinsicFunction(type.getTypeFqName(), methodName, 1, op); + } + } + + private void declareIntrinsicFunction( + @NotNull FqName classFqName, + @NotNull String methodName, + int arity, + @NotNull IntrinsicMethod implementation + ) { + intrinsicsMap.registerIntrinsic(classFqName, null, methodName, arity, implementation); + } + + private void declareIntrinsicFunction( + @NotNull FqNameUnsafe classFqName, + @NotNull String methodName, + int arity, + @NotNull IntrinsicMethod implementation + ) { + intrinsicsMap.registerIntrinsic(classFqName.toSafe(), null, methodName, arity, implementation); + } + + @Nullable + public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) { + return intrinsicsMap.getIntrinsic(descriptor); + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java new file mode 100644 index 00000000000..a8982601c09 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IntrinsicsMap.java @@ -0,0 +1,118 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics; + +import com.google.common.collect.Maps; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.descriptors.*; +import org.jetbrains.kotlin.name.FqName; +import org.jetbrains.kotlin.name.FqNameUnsafe; +import org.jetbrains.kotlin.resolve.DescriptorUtils; + +import java.util.Map; + +class IntrinsicsMap { + private static final class Key { + private final FqNameUnsafe owner; + private final FqNameUnsafe receiverParameter; + private final String name; + private final int valueParameterCount; + + private Key(@NotNull FqNameUnsafe owner, @Nullable FqNameUnsafe receiverParameter, @NotNull String name, int valueParameterCount) { + this.owner = owner; + this.receiverParameter = receiverParameter; + this.name = name; + this.valueParameterCount = valueParameterCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Key key = (Key) o; + + if (valueParameterCount != key.valueParameterCount) return false; + if (!name.equals(key.name)) return false; + if (!owner.equals(key.owner)) return false; + if (receiverParameter == null ? key.receiverParameter != null : !receiverParameter.equals(key.receiverParameter)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = owner.hashCode(); + result = 31 * result + name.hashCode(); + result = 31 * result + valueParameterCount; + result = 31 * result + (receiverParameter != null ? receiverParameter.hashCode() : 0); + return result; + } + } + + private static int valueParameterCountForKey(@NotNull CallableMemberDescriptor member) { + if (member instanceof PropertyDescriptor) { + return -1; + } + else { + return member.getValueParameters().size(); + } + } + + private final Map intrinsicsMap = Maps.newHashMap(); + + + /** + * @param valueParameterCount -1 for property + */ + public void registerIntrinsic( + @NotNull FqName owner, + @Nullable FqNameUnsafe receiverParameter, + @NotNull String name, + int valueParameterCount, + @NotNull IntrinsicMethod impl + ) { + intrinsicsMap.put(new Key(owner.toUnsafe(), receiverParameter, name, valueParameterCount), impl); + } + + @Nullable + public IntrinsicMethod getIntrinsic(@NotNull CallableMemberDescriptor descriptor) { + Key key = new Key( + DescriptorUtils.getFqName(descriptor.getContainingDeclaration()), + getReceiverParameterFqName(descriptor), + descriptor.getName().asString(), + valueParameterCountForKey(descriptor) + ); + return intrinsicsMap.get(key); + } + + @Nullable + private static FqNameUnsafe getReceiverParameterFqName(@NotNull CallableMemberDescriptor descriptor) { + ReceiverParameterDescriptor receiverParameter = descriptor.getExtensionReceiverParameter(); + if (receiverParameter == null) return null; + + ClassifierDescriptor classifier = receiverParameter.getType().getConstructor().getDeclarationDescriptor(); + if (classifier == null) return null; + + if (classifier instanceof TypeParameterDescriptor) { + return IntrinsicMethods.RECEIVER_PARAMETER_FQ_NAME; + } + + return DescriptorUtils.getFqName(classifier); + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt new file mode 100644 index 00000000000..76b06d0dfd9 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Inv.kt @@ -0,0 +1,41 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type + +class Inv : IntrinsicMethod() { + /*TODO new this type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val returnType = signature.returnType + val type = numberFunctionOperandType(returnType) + return IrIntrinsicFunction.create(expression, signature) { + if (returnType == Type.LONG_TYPE) { + it.lconst(-1) + } + else { + it.iconst(-1) + } + it.xor(returnType) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicFunction.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicFunction.kt new file mode 100644 index 00000000000..eb31f766de8 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicFunction.kt @@ -0,0 +1,107 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.BlockInfo +import org.jetbrains.kotlin.backend.jvm.ExpressionCodegen +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + + +open class IrIntrinsicFunction( + val expression: IrMemberAccessExpression, + val signature: JvmMethodSignature, + val argsTypes: List = signature.valueParameters.map { it.asmType } +) : Callable { + override val owner: Type + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val dispatchReceiverType: Type? + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val extensionReceiverType: Type? + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val generateCalleeType: Type? + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val valueParameterTypes: List + get() = signature.valueParameters.map { it.asmType } + override val parameterTypes: Array + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + override val returnType: Type + get() = signature.returnType + + override fun isStaticCall(): Boolean { + return false + } + + override fun genInvokeInstruction(v: InstructionAdapter) { + TODO("not implemented for $this") + } + + open fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo):StackValue { + val args = mutableListOf(expression.dispatchReceiver, expression.extensionReceiver) + args.addAll(expression.descriptor.valueParameters.mapIndexed { + i, valueParameterDescriptor -> + expression.getValueArgument(i) + }) + args.filterNotNull().forEachIndexed { i, irExpression -> genArg(irExpression, codegen, i, data) } + genInvokeInstruction(v) + return StackValue.onStack(returnType) + } + + fun genArg(expression: IrExpression, codegen: ExpressionCodegen, index: Int, data: BlockInfo) { + codegen.gen(expression, argsTypes[index], data) + } + + companion object { + fun create(expression: IrMemberAccessExpression, + signature: JvmMethodSignature, + argsTypes: List = signature.valueParameters.map { it.asmType }, + invokeInstuction: (InstructionAdapter) -> Unit): IrIntrinsicFunction { + return object : IrIntrinsicFunction(expression, signature, argsTypes) { + override fun genInvokeInstruction(v: InstructionAdapter) { + invokeInstuction(v) + } + } + } + + fun create(expression: IrMemberAccessExpression, + signature: JvmMethodSignature, + context: JvmBackendContext, + invokeInstuction: (InstructionAdapter) -> Unit): IrIntrinsicFunction { + val args = (expression.dispatchReceiver?.let { listOf(context.state.typeMapper.mapType(it.type)) } ?: emptyList()) + + signature.valueParameters.map { it.asmType } + return object : IrIntrinsicFunction(expression, signature, args) { + override fun genInvokeInstruction(v: InstructionAdapter) { + invokeInstuction(v) + } + } + } + + fun create(expression: IrMemberAccessExpression, + signature: JvmMethodSignature, + type: Type, + invokeInstuction: (InstructionAdapter) -> Unit): IrIntrinsicFunction { + return create(expression, signature, listOf(type), invokeInstuction) + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt new file mode 100644 index 00000000000..e5a0094958a --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IrIntrinsicMethods.kt @@ -0,0 +1,42 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor +import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns +import org.jetbrains.kotlin.lexer.KtTokens + +class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) { + + private val intrinsics = IntrinsicMethods() + + private val irMapping = hashMapOf() + + init { + irMapping.put(irBuiltIns.eqeq, Equals(KtTokens.EQEQ)) + irMapping.put(irBuiltIns.eqeqeq, Equals(KtTokens.EQEQEQ)) + irMapping.put(irBuiltIns.booleanNot, Not()) + } + + fun getIntrinsic(descriptor: CallableMemberDescriptor): IntrinsicMethod? { + return intrinsics.getIntrinsic(descriptor) ?: + (if (descriptor is PropertyAccessorDescriptor) intrinsics.getIntrinsic(descriptor.correspondingProperty) else null) ?: + irMapping[descriptor] + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt new file mode 100644 index 00000000000..cfef5ef48fb --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IsArrayOf.kt @@ -0,0 +1,50 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.kotlin.types.Variance +import org.jetbrains.org.objectweb.asm.Type + +class IsArrayOf : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val typeMapper = context.state.typeMapper + + val descriptor = expression.descriptor + val builtIns = descriptor.module.builtIns + assert(descriptor.typeParameters.size == 1) { + "Expected only one type parameter for Any?.isArrayOf(), got: ${descriptor.typeParameters}" + } + /*TODO original?*/ + val elementType = expression.getTypeArgument(descriptor.original.typeParameters.first())!! + val arrayKtType = builtIns.getArrayType(Variance.INVARIANT, elementType) + val arrayType = typeMapper.mapType(arrayKtType) + + return IrIntrinsicFunction.create(expression, signature) { + it.instanceOf(arrayType) + } + } +} \ No newline at end of file diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt new file mode 100644 index 00000000000..d5b2a373ee8 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/IteratorNext.kt @@ -0,0 +1,64 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.builtins.KotlinBuiltIns.COLLECTIONS_PACKAGE_FQ_NAME +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.fileClasses.internalNameWithoutInnerClasses +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.resolve.jvm.AsmTypes +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.Method + +class IteratorNext : IntrinsicMethod() { + + /*TODO new return type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val type = AsmUtil.unboxType(signature.returnType) + val newMethod = with(signature.asmMethod) { + Method(name, type, argumentTypes) + } + + val newSignature = JvmMethodSignature(newMethod, signature.valueParameters) + return IrIntrinsicFunction.create(expression, newSignature, AsmTypes.OBJECT_TYPE) { + val primitiveClassName = getKotlinPrimitiveClassName(type) + it.invokevirtual( + getPrimitiveIteratorType(primitiveClassName).internalName, + "next${primitiveClassName.asString()}", + "()" + type.descriptor, + false + ) + } + } + + companion object { + // Type.CHAR_TYPE -> "Char" + private fun getKotlinPrimitiveClassName(type: Type): Name { + return JvmPrimitiveType.get(type.className).primitiveType.typeName + } + + // "Char" -> type for kotlin.collections.CharIterator + fun getPrimitiveIteratorType(primitiveClassName: Name): Type { + val iteratorName = Name.identifier(primitiveClassName.asString() + "Iterator") + return Type.getObjectType(COLLECTIONS_PACKAGE_FQ_NAME.child(iteratorName).internalNameWithoutInnerClasses) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt new file mode 100644 index 00000000000..3beff306d14 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/JavaClassProperty.kt @@ -0,0 +1,75 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.AsmUtil.boxType +import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +object JavaClassProperty : IntrinsicMethod() { + fun generate( + resolvedCall: ResolvedCall<*>?, + codegen: ExpressionCodegen, + returnType: Type, + receiver: StackValue + ): StackValue? = + StackValue.operation(returnType) { + val actualType = generateImpl(it, receiver) + StackValue.coerce(actualType, returnType, it) + } + + fun generateImpl(v: InstructionAdapter, receiver: StackValue): Type { + val type = receiver.type + if (isPrimitive(type)) { + if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) { + receiver.put(type, v) + AsmUtil.pop(v, type) + } + v.getstatic(boxType(type).internalName, "TYPE", "Ljava/lang/Class;") + } + else { + receiver.put(type, v) + v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + } + + return getType(Class::class.java) + } + + override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): Callable { + val classType = codegen.getState().typeMapper.mapType(resolvedCall.call.dispatchReceiver!!.type) + return object : IntrinsicCallable(getType(Class::class.java), listOf(), classType, null) { + override fun invokeIntrinsic(v: InstructionAdapter) { + if (isPrimitive(classType)) { + v.getstatic(boxType(classType).internalName, "TYPE", "Ljava/lang/Class;") + } + else { + v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false) + } + } + + override fun isStaticCall() = isPrimitive(classType) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt new file mode 100644 index 00000000000..900597f4ba3 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KCallableNameProperty.kt @@ -0,0 +1,51 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.psi.KtCallableReferenceExpression +import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE +import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.kotlin.types.expressions.DoubleColonLHS +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.Type.VOID_TYPE + +class KCallableNameProperty : IntrinsicMethod() { + fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? { + val expressionReceiver = resolvedCall!!.dispatchReceiver as? ExpressionReceiver ?: return null + val expression = expressionReceiver.expression as? KtCallableReferenceExpression ?: return null + + val receiverExpression = expression.receiverExpression + val lhs = receiverExpression?.let { codegen.bindingContext.get(DOUBLE_COLON_LHS, it) } + + val callableReference = expression.callableReference + val descriptor = callableReference.getResolvedCall(codegen.bindingContext)?.resultingDescriptor ?: return null + + return StackValue.operation(returnType) { iv -> + // Generate the left-hand side of a bound callable reference expression + if (lhs is DoubleColonLHS.Expression) { + codegen.gen(receiverExpression, VOID_TYPE) + } + iv.aconst(descriptor.name.asString()) + StackValue.coerce(JAVA_STRING_TYPE, returnType, iv) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt new file mode 100644 index 00000000000..4a3127a17ea --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/KClassJavaProperty.kt @@ -0,0 +1,36 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.ExpressionCodegen +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.psi.KtClassLiteralExpression +import org.jetbrains.kotlin.resolve.BindingContext.DOUBLE_COLON_LHS +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver +import org.jetbrains.org.objectweb.asm.Type + +class KClassJavaProperty : IntrinsicMethod() { + fun generate(resolvedCall: ResolvedCall<*>?, codegen: ExpressionCodegen, returnType: Type, receiver: StackValue): StackValue? { + val receiverValue = resolvedCall!!.extensionReceiver as? ExpressionReceiver ?: return null + val classLiteralExpression = receiverValue.expression as? KtClassLiteralExpression ?: return null + val receiverExpression = classLiteralExpression.receiverExpression ?: return null + val lhs = codegen.bindingContext.get(DOUBLE_COLON_LHS, receiverExpression) ?: return null + val value = codegen.generateClassLiteralReference(lhs, receiverExpression, /* wrapIntoKClass = */ false) + return StackValue.coercion(value, returnType) + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt new file mode 100644 index 00000000000..08c850eeae3 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/MonitorInstruction.kt @@ -0,0 +1,47 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Opcodes +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class MonitorInstruction private constructor(private val opcode: Int) : IntrinsicMethod() { + companion object { + @JvmField + val MONITOR_ENTER: MonitorInstruction = MonitorInstruction(Opcodes.MONITORENTER) + + @JvmField + val MONITOR_EXIT: MonitorInstruction = MonitorInstruction(Opcodes.MONITOREXIT) + } + + /*TODO void return type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, OBJECT_TYPE) { + it.visitInsn(opcode) + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt new file mode 100644 index 00000000000..7369859f55f --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NewArray.kt @@ -0,0 +1,41 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.BlockInfo +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter + +class NewArray : IntrinsicMethod() { + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val ktType = expression.type + return object : IrIntrinsicFunction(expression, signature) { + override fun invoke(v: InstructionAdapter, codegen: org.jetbrains.kotlin.backend.jvm.ExpressionCodegen, data: BlockInfo): StackValue { + super.invoke(v, codegen, data) + codegen.newArrayInstruction(ktType) + return StackValue.onStack(returnType) + } + + override fun genInvokeInstruction(v: InstructionAdapter) { + } + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt new file mode 100644 index 00000000000..f053124b384 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/Not.kt @@ -0,0 +1,53 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.* +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.psi.KtPrefixExpression +import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type + +class Not : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, context) { + StackValue.not(StackValue.onStack(Type.BOOLEAN_TYPE)).put(Type.BOOLEAN_TYPE, it) + } + } + + override fun toCallable(method: CallableMethod): Callable = + object : IntrinsicCallable(method) { + override fun invokeMethodWithArguments( + resolvedCall: ResolvedCall<*>, + receiver: StackValue, + codegen: ExpressionCodegen + ): StackValue { + val element = resolvedCall.call.callElement + val stackValue = + if (element is KtPrefixExpression) { + codegen.gen(element.baseExpression) + } + else { + StackValue.receiver(resolvedCall, receiver, codegen, this) + } + return StackValue.not(stackValue) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt new file mode 100644 index 00000000000..6298d892d08 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/NumberCast.kt @@ -0,0 +1,35 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class NumberCast : IntrinsicMethod() { + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature, context) { + StackValue.coerce(calcReceiverType(expression, context), signature.returnType, it) + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt new file mode 100644 index 00000000000..ad2f378dc5f --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/RangeTo.kt @@ -0,0 +1,89 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.BlockInfo +import org.jetbrains.kotlin.backend.jvm.ExpressionCodegen +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.StackValue +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature +import org.jetbrains.org.objectweb.asm.Type +import org.jetbrains.org.objectweb.asm.Type.* +import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter +import java.lang.IllegalStateException + +class RangeTo : IntrinsicMethod() { + private fun rangeTypeToPrimitiveType(rangeType: Type): Type { + val fqName = rangeType.internalName + val name = fqName.substringAfter("kotlin/ranges/").substringBefore("Range") + return when (name) { + "Double" -> DOUBLE_TYPE + "Float" -> FLOAT_TYPE + "Long" -> LONG_TYPE + "Int" -> INT_TYPE + "Short" -> SHORT_TYPE + "Char" -> CHAR_TYPE + "Byte" -> BYTE_TYPE + else -> throw IllegalStateException("RangeTo intrinsic can only work for primitive types: $fqName") + } + } + + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + val argType = rangeTypeToPrimitiveType(signature.returnType) + return object: IrIntrinsicFunction(expression, signature, listOf(argType) + signature.valueParameters.map { argType }) { + override fun genInvokeInstruction(v: InstructionAdapter) { + v.invokespecial(signature.returnType.internalName, "", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false) + } + + override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue { + v.anew(returnType) + v.dup() + return super.invoke(v, codegen, data) + } + } + } +// +// override fun toCallable(method: CallableMethod): Callable { +// val argType = rangeTypeToPrimitiveType(method.returnType) +// return object : IntrinsicCallable( +// method.returnType, +// method.valueParameterTypes.map { argType }, +// nullOr(method.dispatchReceiverType, argType), +// nullOr(method.extensionReceiverType, argType) +// ) { +// override fun afterReceiverGeneration(v: InstructionAdapter) { +// v.anew(returnType) +// when (argType.size) { +// 1 -> { +// v.dupX1() +// v.swap() +// } +// 2 -> { +// v.dup() +// v.dup2X2() +// v.pop2() +// } +// } +// } +// +// override fun invokeIntrinsic(v: InstructionAdapter) { +// v.invokespecial(returnType.internalName, "", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false) +// } +// } +// } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt new file mode 100644 index 00000000000..0c36f4d008c --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringGetChar.kt @@ -0,0 +1,27 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod + +class StringGetChar : IntrinsicMethod() { + override fun toCallable(method: CallableMethod): Callable = + createIntrinsicCallable(method) { + it.invokevirtual("java/lang/String", "charAt", "(I)C", false) + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringPlus.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringPlus.kt new file mode 100644 index 00000000000..9dd4ba25e7e --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/StringPlus.kt @@ -0,0 +1,28 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod + +class StringPlus : IntrinsicMethod() { + override fun toCallable(method: CallableMethod): Callable = + createIntrinsicCallable(method) { + it.invokestatic("kotlin/jvm/internal/Intrinsics", "stringPlus", + "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/String;", false) + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt new file mode 100644 index 00000000000..a150932fe10 --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/ToString.kt @@ -0,0 +1,40 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.Callable +import org.jetbrains.kotlin.codegen.CallableMethod +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class ToString : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + it.neg(AsmUtil.numberFunctionOperandType(signature.returnType)) + } + } + + override fun toCallable(method: CallableMethod): Callable { + val type = AsmUtil.stringValueOfType(method.dispatchReceiverType ?: method.extensionReceiverType) + return createUnaryIntrinsicCallable(method, newThisType = type) { + it.invokestatic("java/lang/String", "valueOf", "(${type.descriptor})Ljava/lang/String;", false) + } + } +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt new file mode 100644 index 00000000000..7df5279f5db --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryMinus.kt @@ -0,0 +1,33 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class UnaryMinus : IntrinsicMethod() { + /*TODO return type*/ + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + it.neg(numberFunctionOperandType(signature.returnType)) + } + } + +} diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt new file mode 100644 index 00000000000..5d01e9fc1be --- /dev/null +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/intrinsics/UnaryPlus.kt @@ -0,0 +1,30 @@ +/* + * 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 org.jetbrains.kotlin.backend.jvm.intrinsics + +import org.jetbrains.kotlin.backend.jvm.JvmBackendContext +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression +import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature + +class UnaryPlus : IntrinsicMethod() { + override fun toCallable(expression: IrMemberAccessExpression, signature: JvmMethodSignature, context: JvmBackendContext): IrIntrinsicFunction { + return IrIntrinsicFunction.create(expression, signature) { + + } + } +}