Initial intrinsic implementation

This commit is contained in:
Michael Bogdanov
2016-09-19 11:28:33 +03:00
committed by Dmitry Petrov
parent 95c88e4445
commit 204a8c5c14
35 changed files with 1939 additions and 0 deletions
@@ -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) {
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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
}
}
}
@@ -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)
}
}
}*/
}
@@ -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()
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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<KtExpression>,
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", "<init>", "(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)
}
}
}
@@ -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)
}
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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<Type>,
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<Type>
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)
}
@@ -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)
}
}
}
@@ -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<Name> 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, "<init>", 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);
}
}
@@ -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<Key, IntrinsicMethod> 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);
}
}
@@ -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)
}
}
}
@@ -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<Type> = 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<Type>
get() = signature.valueParameters.map { it.asmType }
override val parameterTypes: Array<Type>
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<Type> = 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<Type>()) +
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)
}
}
}
@@ -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<CallableMemberDescriptor, IntrinsicMethod>()
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]
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
@@ -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)
}
}
}
@@ -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) {
}
}
}
}
@@ -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)
}
}
}
@@ -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)
}
}
}
@@ -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, "<init>", 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, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
// }
// }
// }
}
@@ -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)
}
}
@@ -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)
}
}
@@ -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)
}
}
}
@@ -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))
}
}
}
@@ -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) {
}
}
}