Intrinsic conversion

This commit is contained in:
Michael Bogdanov
2015-04-04 10:41:24 +03:00
parent a5612ec4c0
commit b99ff5c7ae
17 changed files with 613 additions and 528 deletions
@@ -14,66 +14,106 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.builtins.PrimitiveType; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor; import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetCallExpression; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.psi.JetSimpleNameExpression; import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.Iterator; import org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME; public class ArrayIterator : IntrinsicMethod() {
import static org.jetbrains.kotlin.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType; receiver.put(receiver.type, v)
val call = element as JetCallExpression
public class ArrayIterator extends IntrinsicMethod { val funDescriptor = codegen.getBindingContext().get(BindingContext.REFERENCE_TARGET, call.getCalleeExpression() as JetSimpleNameExpression) as FunctionDescriptor
@NotNull val containingDeclaration = funDescriptor.getContainingDeclaration().getOriginal() as ClassDescriptor
@Override if (containingDeclaration == KotlinBuiltIns.getInstance().getArray()) {
public Type generateImpl( v.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", "([Ljava/lang/Object;)Ljava/util/Iterator;", false)
@NotNull ExpressionCodegen codegen, return getType(javaClass<Iterator<Any>>())
@NotNull InstructionAdapter v,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
receiver.put(receiver.type, v);
JetCallExpression call = (JetCallExpression) element;
FunctionDescriptor funDescriptor = (FunctionDescriptor) codegen.getBindingContext()
.get(BindingContext.REFERENCE_TARGET, (JetSimpleNameExpression) call.getCalleeExpression());
assert funDescriptor != null;
ClassDescriptor containingDeclaration = (ClassDescriptor) funDescriptor.getContainingDeclaration().getOriginal();
if (containingDeclaration.equals(KotlinBuiltIns.getInstance().getArray())) {
v.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", "([Ljava/lang/Object;)Ljava/util/Iterator;", false);
return getType(Iterator.class);
} }
for (JvmPrimitiveType jvmPrimitiveType : JvmPrimitiveType.values()) { for (jvmPrimitiveType in JvmPrimitiveType.values()) {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); val primitiveType = jvmPrimitiveType.getPrimitiveType()
ClassDescriptor arrayClass = KotlinBuiltIns.getInstance().getPrimitiveArrayClassDescriptor(primitiveType); val arrayClass = KotlinBuiltIns.getInstance().getPrimitiveArrayClassDescriptor(primitiveType)
if (containingDeclaration.equals(arrayClass)) { if (containingDeclaration == arrayClass) {
FqName fqName = new FqName(BUILT_INS_PACKAGE_FQ_NAME + "." + primitiveType.getTypeName() + "Iterator"); val fqName = FqName(BUILT_INS_PACKAGE_FQ_NAME.toString() + "." + primitiveType.getTypeName() + "Iterator")
String iteratorDesc = asmDescByFqNameWithoutInnerClasses(fqName); val iteratorDesc = asmDescByFqNameWithoutInnerClasses(fqName)
String methodSignature = "([" + jvmPrimitiveType.getDesc() + ")" + iteratorDesc; val methodSignature = "([" + jvmPrimitiveType.getDesc() + ")" + iteratorDesc
v.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", methodSignature, false); v.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", methodSignature, false)
return Type.getType(iteratorDesc); return Type.getType(iteratorDesc)
} }
} }
throw new UnsupportedOperationException(containingDeclaration.toString()); throw UnsupportedOperationException(containingDeclaration.toString())
}
override fun supportCallable(): Boolean {
return true
}
//TODO refactor
override fun toCallable(state: GenerationState, fd: FunctionDescriptor, context: CodegenContext<*>, isSuper: Boolean): ExtendedCallable {
val callableMethod = state.getTypeMapper().mapToCallableMethod(fd, false, context)
val containingDeclaration = fd.getContainingDeclaration().getOriginal() as ClassDescriptor
var type: Type? = null;
if (containingDeclaration == KotlinBuiltIns.getInstance().getArray()) {
type = getType(javaClass<Iterator<Any>>())
} else {
for (jvmPrimitiveType in JvmPrimitiveType.values()) {
val primitiveType = jvmPrimitiveType.getPrimitiveType()
val arrayClass = KotlinBuiltIns.getInstance().getPrimitiveArrayClassDescriptor(primitiveType)
if (containingDeclaration == arrayClass) {
val fqName = FqName(BUILT_INS_PACKAGE_FQ_NAME.toString() + "." + primitiveType.getTypeName() + "Iterator")
val iteratorDesc = asmDescByFqNameWithoutInnerClasses(fqName)
type = Type.getType(iteratorDesc)
break
}
}
}
if (type == null) {
throw UnsupportedOperationException(containingDeclaration.toString())
}
return UnaryIntrinsic(callableMethod, type) {
val containingDeclaration = fd.getContainingDeclaration().getOriginal() as ClassDescriptor
if (containingDeclaration == KotlinBuiltIns.getInstance().getArray()) {
it.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", "([Ljava/lang/Object;)Ljava/util/Iterator;", false)
} else {
for (jvmPrimitiveType in JvmPrimitiveType.values()) {
val primitiveType = jvmPrimitiveType.getPrimitiveType()
val arrayClass = KotlinBuiltIns.getInstance().getPrimitiveArrayClassDescriptor(primitiveType)
if (containingDeclaration == arrayClass) {
val fqName = FqName(BUILT_INS_PACKAGE_FQ_NAME.toString() + "." + primitiveType.getTypeName() + "Iterator")
val iteratorDesc = asmDescByFqNameWithoutInnerClasses(fqName)
val methodSignature = "([" + jvmPrimitiveType.getDesc() + ")" + iteratorDesc
it.invokestatic("kotlin/jvm/internal/InternalPackage", "iterator", methodSignature, false)
break;
}
}
}
}
} }
} }
@@ -14,38 +14,42 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.correctElementType
import static org.jetbrains.kotlin.codegen.AsmUtil.correctElementType; public class ArraySet : IntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
receiver.put(receiver.type, v)
val type = correctElementType(receiver.type)
public class ArraySet extends IntrinsicMethod { codegen.gen(arguments.get(0), Type.INT_TYPE)
@NotNull codegen.gen(arguments.get(1), type)
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
receiver.put(receiver.type, v);
Type type = correctElementType(receiver.type);
codegen.gen(arguments.get(0), Type.INT_TYPE); v.astore(type)
codegen.gen(arguments.get(1), type); return Type.VOID_TYPE
}
v.astore(type); override fun supportCallable(): Boolean {
return Type.VOID_TYPE; return true
}
override fun toCallable(method: CallableMethod): ExtendedCallable {
val type = correctElementType(method.getThisType())
return object: IntrinsicCallable(Type.VOID_TYPE, listOf(Type.INT_TYPE, type), method.getThisType(), method.getReceiverClass()) {
override fun invokeIntrinsic(v: InstructionAdapter) {
v.astore(type)
}
}
} }
} }
@@ -14,52 +14,52 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.JetElement; import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetSuperExpression; import org.jetbrains.kotlin.psi.JetSuperExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue; import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import org.jetbrains.org.objectweb.asm.Opcodes
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert; public class Clone : IntrinsicMethod() {
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
val resolvedCall = (element as JetElement).getResolvedCallWithAssert(codegen.getBindingContext())
public class Clone extends IntrinsicMethod { StackValue.receiver(resolvedCall, receiver, codegen, null).put(OBJECT_TYPE, v)
@NotNull
@Override
protected Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert(((JetElement) element), codegen.getBindingContext());
StackValue.receiver(resolvedCall, receiver, codegen, null).put(OBJECT_TYPE, v);
if (isSuperCall(resolvedCall)) { if (isSuperCall(resolvedCall)) {
v.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false); v.invokespecial("java/lang/Object", "clone", "()Ljava/lang/Object;", false)
} }
else { else {
v.invokevirtual("java/lang/Object", "clone", "()Ljava/lang/Object;", false); v.invokevirtual("java/lang/Object", "clone", "()Ljava/lang/Object;", false)
} }
return OBJECT_TYPE; return OBJECT_TYPE
} }
private static boolean isSuperCall(@NotNull ResolvedCall<?> resolvedCall) { private fun isSuperCall(resolvedCall: ResolvedCall<*>): Boolean {
ReceiverValue dispatchReceiver = resolvedCall.getDispatchReceiver(); val dispatchReceiver = resolvedCall.getDispatchReceiver()
return dispatchReceiver instanceof ExpressionReceiver && return dispatchReceiver is ExpressionReceiver && (dispatchReceiver as ExpressionReceiver).getExpression() is JetSuperExpression
((ExpressionReceiver) dispatchReceiver).getExpression() instanceof JetSuperExpression; }
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(method: CallableMethod, isSuperCall: Boolean): ExtendedCallable {
return UnaryIntrinsic(method, OBJECT_TYPE) {
val opcodes: Int = if (isSuperCall) Opcodes.INVOKESPECIAL else Opcodes.INVOKEVIRTUAL
it.visitMethodInsn(opcodes, "java/lang/Object", "clone", "()Ljava/lang/Object;", false)
}
} }
} }
@@ -14,64 +14,70 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExtendedCallable
import static org.jetbrains.kotlin.codegen.AsmUtil.comparisonOperandType; public class CompareTo : IntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
public class CompareTo extends IntrinsicMethod { var receiver = receiver
@NotNull val argument: JetExpression
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
JetExpression argument;
if (arguments.size() == 1) { if (arguments.size() == 1) {
argument = arguments.get(0); argument = arguments.get(0)
} }
else if (arguments.size() == 2) { else if (arguments.size() == 2) {
receiver = codegen.gen(arguments.get(0)); receiver = codegen.gen(arguments.get(0))
argument = arguments.get(1); argument = arguments.get(1)
} }
else { else {
throw new IllegalStateException("Invalid arguments to compareTo: " + arguments); throw IllegalStateException("Invalid arguments to compareTo: " + arguments)
} }
Type type = comparisonOperandType(receiver.type, codegen.expressionType(argument)); val type = comparisonOperandType(receiver.type, codegen.expressionType(argument))
receiver.put(type, v); receiver.put(type, v)
codegen.gen(argument, type); codegen.gen(argument, type)
genInvoke(type, v)
return Type.INT_TYPE
}
private fun genInvoke(type: Type?, v: InstructionAdapter) {
if (type == Type.INT_TYPE) { if (type == Type.INT_TYPE) {
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false); v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(II)I", false)
} }
else if (type == Type.LONG_TYPE) { else if (type == Type.LONG_TYPE) {
v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false); v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "compare", "(JJ)I", false)
} }
else if (type == Type.FLOAT_TYPE) { else if (type == Type.FLOAT_TYPE) {
v.invokestatic("java/lang/Float", "compare", "(FF)I", false); v.invokestatic("java/lang/Float", "compare", "(FF)I", false)
} }
else if (type == Type.DOUBLE_TYPE) { else if (type == Type.DOUBLE_TYPE) {
v.invokestatic("java/lang/Double", "compare", "(DD)I", false); v.invokestatic("java/lang/Double", "compare", "(DD)I", false)
} }
else { else {
throw new UnsupportedOperationException(); throw UnsupportedOperationException()
} }
}
return Type.INT_TYPE; //TODO seems we need to different CompareTo
override fun supportCallable(): Boolean {
return false
}
override fun toCallable(method: CallableMethod): ExtendedCallable {
val argumentType = comparisonOperandType(method.getThisType() ?: method.getReceiverClass(), method.getArgumentTypes().first())
return IntrinsicCallable.binaryIntrinsic(method.getReturnType(), argumentType, argumentType, null) {
genInvoke(argumentType, it)
}
} }
} }
@@ -49,7 +49,7 @@ public class Concat extends IntrinsicMethod {
codegen.invokeAppend(arguments.get(1)); codegen.invokeAppend(arguments.get(1));
} }
else { else {
// LHS.plus(RHS) // LHS?.plus(RHS)
receiver.put(AsmTypes.OBJECT_TYPE, v); receiver.put(AsmTypes.OBJECT_TYPE, v);
genStringBuilderConstructor(v); genStringBuilderConstructor(v);
v.swap(); v.swap();
@@ -14,44 +14,52 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.types.JetType; import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType; public class CopyToArray : IntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
receiver.put(receiver.type, v)
v.dup()
v.invokeinterface("java/util/Collection", "size", "()I")
public class CopyToArray extends IntrinsicMethod { assert(element is JetExpression)
@NotNull val arrayType = codegen.expressionJetType(element as JetExpression)
@Override assert(arrayType != null)
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
receiver.put(receiver.type, v);
v.dup();
v.invokeinterface("java/util/Collection", "size", "()I");
assert element instanceof JetExpression; codegen.newArrayInstruction(arrayType)
JetType arrayType = codegen.expressionJetType((JetExpression) element); v.invokeinterface("java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;")
assert arrayType != null;
codegen.newArrayInstruction(arrayType); return getType(javaClass<Array<Any>>())
v.invokeinterface("java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;"); }
return getType(Object[].class); override fun supportCallable(): Boolean {
return true
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable {
return object : IntrinsicCallable(getType(javaClass<Array<Any>>()), listOf(), null, Type.getType(javaClass<Collection<*>>())) {
override fun invokeIntrinsic(v: InstructionAdapter) {
v.dup()
v.invokeinterface("java/util/Collection", "size", "()I")
codegen.newArrayInstruction(resolvedCall.getResultingDescriptor().getReturnType()!!)
v.invokeinterface("java/util/Collection", "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;")
}
}
} }
} }
@@ -14,44 +14,45 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.*
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.psi.JetBinaryExpression
import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetBinaryExpression; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetCallExpression; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.psi.JetExpression;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.List; import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; public class IdentityEquals : LazyIntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): StackValue {
public class IdentityEquals extends LazyIntrinsicMethod { val left: StackValue
@NotNull val right: StackValue
@Override if (element is JetCallExpression) {
public StackValue generateImpl( left = receiver
@NotNull ExpressionCodegen codegen, right = codegen.gen(arguments.get(0))
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
StackValue left;
StackValue right;
if (element instanceof JetCallExpression) {
left = receiver;
right = codegen.gen(arguments.get(0));
} }
else { else {
assert element instanceof JetBinaryExpression; assert(element is JetBinaryExpression)
JetBinaryExpression e = (JetBinaryExpression) element; val e = element as JetBinaryExpression
left = codegen.gen(e.getLeft()); left = codegen.gen(e.getLeft())
right = codegen.gen(e.getRight()); right = codegen.gen(e.getRight())
} }
return StackValue.cmp(JetTokens.EQEQEQ, OBJECT_TYPE, left, right); return StackValue.cmp(JetTokens.EQEQEQ, OBJECT_TYPE, left, right)
} }
override fun supportCallable(): Boolean {
return false
}
override fun toCallable(method: CallableMethod): ExtendedCallable {
return IntrinsicCallable.binaryIntrinsic(method.getReturnType(), OBJECT_TYPE, nullOrObject(method.getThisType()), nullOrObject(method.getReceiverClass())) {
v -> v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "areEqual", "(Ljava/lang/Object;Ljava/lang/Object;)Z", false)
AsmUtil.genAreEqualCall(v)
}
}
} }
@@ -14,42 +14,49 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; public class Inv : IntrinsicMethod() {
import static org.jetbrains.kotlin.codegen.AsmUtil.numberFunctionOperandType; override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
assert(isPrimitive(returnType)) { "Return type of Inv intrinsic should be of primitive type : " + returnType }
public class Inv extends IntrinsicMethod { receiver.put(numberFunctionOperandType(returnType), v)
@NotNull
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
assert isPrimitive(returnType) : "Return type of Inv intrinsic should be of primitive type : " + returnType;
receiver.put(numberFunctionOperandType(returnType), v);
if (returnType == Type.LONG_TYPE) { if (returnType == Type.LONG_TYPE) {
v.lconst(-1L); v.lconst(-1)
} }
else { else {
v.iconst(-1); v.iconst(-1)
}
v.xor(returnType)
return returnType
}
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(method: CallableMethod): ExtendedCallable {
val type = numberFunctionOperandType(method.getReturnType())
return UnaryIntrinsic(method, method.getReturnType(), newThisType = type) {
if (getReturnType() == Type.LONG_TYPE) {
it.lconst(-1)
}
else {
it.iconst(-1)
}
it.xor(getReturnType())
} }
v.xor(returnType);
return returnType;
} }
} }
@@ -14,62 +14,76 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME
import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.BUILT_INS_PACKAGE_FQ_NAME; public class IteratorNext : IntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
val name = getIteratorName(returnType)
receiver.put(AsmTypes.OBJECT_TYPE, v)
v.invokevirtual(BUILT_INS_PACKAGE_FQ_NAME.toString() + "/" + name + "Iterator", "next" + name, "()" + returnType.getDescriptor(), false)
return returnType
}
public class IteratorNext extends IntrinsicMethod { protected fun getIteratorName(returnType: Type): String {
@NotNull val name: String
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
String name;
if (returnType == Type.CHAR_TYPE) { if (returnType == Type.CHAR_TYPE) {
name = "Char"; name = "Char"
} }
else if (returnType == Type.BOOLEAN_TYPE) { else if (returnType == Type.BOOLEAN_TYPE) {
name = "Boolean"; name = "Boolean"
} }
else if (returnType == Type.BYTE_TYPE) { else if (returnType == Type.BYTE_TYPE) {
name = "Byte"; name = "Byte"
} }
else if (returnType == Type.SHORT_TYPE) { else if (returnType == Type.SHORT_TYPE) {
name = "Short"; name = "Short"
} }
else if (returnType == Type.INT_TYPE) { else if (returnType == Type.INT_TYPE) {
name = "Int"; name = "Int"
} }
else if (returnType == Type.LONG_TYPE) { else if (returnType == Type.LONG_TYPE) {
name = "Long"; name = "Long"
} }
else if (returnType == Type.FLOAT_TYPE) { else if (returnType == Type.FLOAT_TYPE) {
name = "Float"; name = "Float"
} }
else if (returnType == Type.DOUBLE_TYPE) { else if (returnType == Type.DOUBLE_TYPE) {
name = "Double"; name = "Double"
} }
else { else {
throw new UnsupportedOperationException(); throw UnsupportedOperationException("Can't get correct name for iterator from type: " + returnType)
}
return name
}
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(state: GenerationState, fd: FunctionDescriptor, context: CodegenContext<*>, isSuper: Boolean): ExtendedCallable {
val type = state.getTypeMapper().mapReturnType(fd)
return object: IntrinsicCallable(type, listOf(), AsmTypes.OBJECT_TYPE, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
val returnType = getReturnType()
val name = getIteratorName(returnType)
v.invokevirtual(BUILT_INS_PACKAGE_FQ_NAME.toString() + "/" + name + "Iterator", "next" + name, "()" + returnType.getDescriptor(), false)
}
} }
receiver.put(AsmTypes.OBJECT_TYPE, v);
v.invokevirtual(BUILT_INS_PACKAGE_FQ_NAME + "/" + name + "Iterator", "next" + name, "()" + returnType.getDescriptor(), false);
return returnType;
} }
} }
@@ -14,42 +14,41 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor; import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.JetElement; import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.resolve.calls.model.VarargValueArgument
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import java.util.Map;
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert; public class JavaClassArray : IntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
assert(element != null, "Element should not be null")
val resolvedCall = (element as JetElement).getResolvedCallWithAssert(codegen.getBindingContext())
val argument = resolvedCall.getValueArguments().entrySet().iterator().next()
codegen.genVarargs(argument.getValue() as VarargValueArgument, argument.getKey().getType())
return returnType
}
public class JavaClassArray extends IntrinsicMethod { override fun supportCallable(): Boolean {
@NotNull return true
@Override }
public Type generateImpl(
@NotNull ExpressionCodegen codegen, override fun toCallable(method: CallableMethod): ExtendedCallable {
@NotNull InstructionAdapter v, return MappedCallable(method) {
@NotNull Type returnType, //do nothing all generated as vararg
@Nullable PsiElement element, }
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
assert element != null : "Element should not be null";
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert((JetElement) element, codegen.getBindingContext());
Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> argument = resolvedCall.getValueArguments().entrySet().iterator().next();
codegen.genVarargs((VarargValueArgument) argument.getValue(), argument.getKey().getType());
return returnType;
} }
} }
@@ -14,49 +14,52 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.psi.JetElement; import org.jetbrains.kotlin.resolve.calls.callUtil.*
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage; import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.types.JetType; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.putJavaLangClassInstance
import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
import static org.jetbrains.kotlin.codegen.AsmUtil.putJavaLangClassInstance; public class JavaClassFunction : IntrinsicMethod() {
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType; override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, expectedType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
val resolvedCall = (element as JetElement).getResolvedCallWithAssert(codegen.getBindingContext())
val returnType = resolvedCall.getResultingDescriptor().getReturnType()
assert(returnType != null)
public class JavaClassFunction extends IntrinsicMethod { val type = returnType!!.getArguments().get(0).getType()
@NotNull
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type expectedType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCallWithAssert(
(JetElement) element, codegen.getBindingContext());
JetType returnType = resolvedCall.getResultingDescriptor().getReturnType();
assert returnType != null;
JetType type = returnType.getArguments().get(0).getType(); codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME)
codegen.putReifierMarkerIfTypeIsReifiedParameter(type, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME); putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(type))
putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(type)); return getType(javaClass<Class<Any>>())
}
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable {
val javaClass = resolvedCall.getResultingDescriptor().getReturnType()!!.getArguments().get(0).getType()
return object: IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), null, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
codegen.putReifierMarkerIfTypeIsReifiedParameter(javaClass, ReifiedTypeInliner.JAVA_CLASS_MARKER_METHOD_NAME)
putJavaLangClassInstance(v, codegen.getState().getTypeMapper().mapType(javaClass))
}
}
return getType(Class.class);
} }
} }
@@ -14,48 +14,60 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.AsmUtil
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.AsmUtil; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import org.jetbrains.org.objectweb.asm.Type;
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.boxType
import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType
import static org.jetbrains.kotlin.codegen.AsmUtil.boxType; public class JavaClassProperty : IntrinsicMethod() {
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.getType; val type = receiver.type
public class JavaClassProperty extends IntrinsicMethod {
@NotNull
@Override
public Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
Type type = receiver.type;
if (isPrimitive(type)) { if (isPrimitive(type)) {
if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) { if (!StackValue.couldSkipReceiverOnStaticCall(receiver)) {
receiver.put(type, v); receiver.put(type, v)
AsmUtil.pop(v, type); AsmUtil.pop(v, type)
} }
v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;"); v.getstatic(boxType(type).getInternalName(), "TYPE", "Ljava/lang/Class;")
} }
else { else {
receiver.put(type, v); receiver.put(type, v)
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false); v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
} }
return getType(Class.class); return getType(javaClass<Class<Any>>())
}
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable {
val classType = codegen.getState().getTypeMapper().mapType(resolvedCall.getCall().getDispatchReceiver().getType())
return object : IntrinsicCallable(getType(javaClass<Class<Any>>()), listOf(), classType, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
if (isPrimitive(classType)) {
v.getstatic(boxType(classType).getInternalName(), "TYPE", "Ljava/lang/Class;")
}
else {
v.invokevirtual("java/lang/Object", "getClass", "()Ljava/lang/Class;", false)
}
}
override fun isStaticCall(): Boolean {
return isPrimitive(classType)
}
}
} }
} }
@@ -14,66 +14,62 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.context.CodegenContext
import org.jetbrains.kotlin.psi.JetElement; import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.psi.ValueArgument; import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.psi.ValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument; import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.org.objectweb.asm.Opcodes; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter; import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
import static org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilPackage.getResolvedCallWithAssert; public class MonitorInstruction private(private val opcode: Int) : IntrinsicMethod() {
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE; companion object {
public val MONITOR_ENTER: MonitorInstruction = MonitorInstruction(Opcodes.MONITORENTER)
public class MonitorInstruction extends IntrinsicMethod { public val MONITOR_EXIT: MonitorInstruction = MonitorInstruction(Opcodes.MONITOREXIT)
public static final MonitorInstruction MONITOR_ENTER = new MonitorInstruction(Opcodes.MONITORENTER);
public static final MonitorInstruction MONITOR_EXIT = new MonitorInstruction(Opcodes.MONITOREXIT);
private final int opcode;
private MonitorInstruction(int opcode) {
this.opcode = opcode;
} }
@NotNull override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
@Override assert(element != null, "Element should not be null")
protected Type generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull InstructionAdapter v,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
assert element != null : "Element should not be null";
ResolvedCall<?> resolvedCall = getResolvedCallWithAssert((JetElement) element, codegen.getBindingContext()); val resolvedCall = (element as JetElement).getResolvedCallWithAssert(codegen.getBindingContext())
List<ResolvedValueArgument> resolvedArguments = resolvedCall.getValueArgumentsByIndex(); val resolvedArguments = resolvedCall.getValueArgumentsByIndex()
assert resolvedArguments != null && resolvedArguments.size() == 1 : assert(resolvedArguments != null && resolvedArguments.size() == 1) { "Monitor instruction (" + opcode + ") should have exactly 1 argument: " + resolvedArguments }
"Monitor instruction (" + opcode + ") should have exactly 1 argument: " + resolvedArguments;
ResolvedValueArgument argument = resolvedArguments.get(0); val argument = resolvedArguments!!.get(0)
assert argument instanceof ExpressionValueArgument : assert(argument is ExpressionValueArgument) { "Monitor instruction (" + opcode + ") should have expression value argument: " + argument }
"Monitor instruction (" + opcode + ") should have expression value argument: " + argument;
ValueArgument valueArgument = ((ExpressionValueArgument) argument).getValueArgument(); val valueArgument = (argument as ExpressionValueArgument).getValueArgument()
assert valueArgument != null : "Unresolved value argument: " + argument; assert(valueArgument != null) { "Unresolved value argument: " + argument }
codegen.gen(valueArgument.getArgumentExpression(), OBJECT_TYPE); codegen.gen(valueArgument!!.getArgumentExpression(), OBJECT_TYPE)
v.visitInsn(opcode); v.visitInsn(opcode)
return Type.VOID_TYPE; return Type.VOID_TYPE
}
override fun supportCallable(): Boolean {
return true
}
override fun toCallable(state: GenerationState, fd: FunctionDescriptor, context: CodegenContext<*>, isSuper: Boolean, resolvedCall: ResolvedCall<*>): ExtendedCallable {
return object : IntrinsicCallable(Type.VOID_TYPE, listOf(OBJECT_TYPE), null, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
v.visitInsn(opcode)
}
}
} }
} }
@@ -14,28 +14,34 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.psi.JetCallExpression; import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.List; public class NewArray : LazyIntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): StackValue {
public class NewArray extends LazyIntrinsicMethod { return codegen.generateNewArray(element as JetCallExpression)
@NotNull
@Override
public StackValue generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
return codegen.generateNewArray((JetCallExpression) element);
} }
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable {
val jetType = resolvedCall.getResultingDescriptor().getReturnType()!!
val type = codegen.getState().getTypeMapper().mapType(jetType)
return object : IntrinsicCallable(type, listOf(Type.INT_TYPE), null, null) {
override fun invokeIntrinsic(v: InstructionAdapter) {
codegen.newArrayInstruction(jetType)
}
}
}
} }
@@ -14,34 +14,29 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.org.objectweb.asm.Type
import java.util.List; public class Not : LazyIntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): StackValue {
public class Not extends LazyIntrinsicMethod { val stackValue: StackValue
@NotNull
@Override
public StackValue generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull Type returnType,
PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
StackValue stackValue;
if (arguments.size() == 1) { if (arguments.size() == 1) {
stackValue = codegen.gen(arguments.get(0)); stackValue = codegen.gen(arguments.get(0))
} }
else { else {
stackValue = receiver; stackValue = receiver
} }
return StackValue.not(StackValue.coercion(stackValue, Type.BOOLEAN_TYPE)); return StackValue.not(StackValue.coercion(stackValue, Type.BOOLEAN_TYPE))
}
override fun supportCallable(): Boolean {
return false
} }
} }
@@ -14,27 +14,25 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.kotlin.codegen.ExtendedCallable
import org.jetbrains.kotlin.psi.JetExpression; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.org.objectweb.asm.Type
import java.util.List; public class NumberCast : LazyIntrinsicMethod() {
public class NumberCast extends LazyIntrinsicMethod { override fun generateImpl(codegen: ExpressionCodegen, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): StackValue {
@NotNull return StackValue.coercion(receiver, returnType)
@Override }
public StackValue generateImpl(
@NotNull ExpressionCodegen codegen, override fun toCallable(method: CallableMethod): ExtendedCallable {
@NotNull Type returnType, return UnaryIntrinsic(method) {
PsiElement element, StackValue.coerce(calcReceiverType()!!, getReturnType(), it)
@NotNull List<JetExpression> arguments, }
@NotNull StackValue receiver
) {
return StackValue.coercion(receiver, returnType);
} }
} }
@@ -14,38 +14,34 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.codegen.intrinsics; package org.jetbrains.kotlin.codegen.intrinsics
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.ExpressionCodegen
import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.StackValue
import org.jetbrains.kotlin.codegen.ExpressionCodegen; import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.codegen.StackValue; import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.kotlin.psi.JetExpression;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.List; import org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive
import org.jetbrains.kotlin.codegen.CallableMethod
import org.jetbrains.kotlin.codegen.ExtendedCallable
import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive; public class UnaryPlus : LazyIntrinsicMethod() {
override fun generateImpl(codegen: ExpressionCodegen, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): StackValue {
public class UnaryPlus extends LazyIntrinsicMethod { assert(isPrimitive(returnType)) { "Return type of UnaryPlus intrinsic should be of primitive type : " + returnType }
@NotNull
@Override
public StackValue generateImpl(
@NotNull ExpressionCodegen codegen,
@NotNull Type returnType,
@Nullable PsiElement element,
@NotNull List<JetExpression> arguments,
@NotNull StackValue receiver
) {
assert isPrimitive(returnType) : "Return type of UnaryPlus intrinsic should be of primitive type : " + returnType;
if (receiver != StackValue.none()) { if (receiver != StackValue.none()) {
return receiver; return receiver
} }
else { else {
assert !arguments.isEmpty(); assert(!arguments.isEmpty())
return codegen.gen(arguments.get(0)); return codegen.gen(arguments.get(0))
}
}
override fun toCallable(method: CallableMethod): ExtendedCallable {
return UnaryIntrinsic(method, needPrimitiveCheck = true) {
//nothing
} }
} }
} }