RenageTo convertion & before call
This commit is contained in:
@@ -181,4 +181,9 @@ public class CallableMethod implements ExtendedCallable {
|
|||||||
public boolean isStaticCall() {
|
public boolean isStaticCall() {
|
||||||
return invokeOpcode == Opcodes.INVOKESTATIC;
|
return invokeOpcode == Opcodes.INVOKESTATIC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeParameterGeneration(@NotNull InstructionAdapter v, @Nullable StackValue value) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2347,6 +2347,7 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
@NotNull CallGenerator callGenerator,
|
@NotNull CallGenerator callGenerator,
|
||||||
@NotNull ArgumentGenerator argumentGenerator
|
@NotNull ArgumentGenerator argumentGenerator
|
||||||
) {
|
) {
|
||||||
|
StackValue.SafeCall safeCallReceiver = receiver instanceof StackValue.SafeCall ? (StackValue.SafeCall) receiver : null;
|
||||||
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
||||||
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
|
receiver = StackValue.receiver(resolvedCall, receiver, this, callableMethod);
|
||||||
|
|
||||||
@@ -2358,7 +2359,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
receiver.put(receiver.type, v);
|
if (safeCallReceiver != null) {
|
||||||
|
//justCoerce
|
||||||
|
receiver.put(receiver.type, v);
|
||||||
|
callableMethod.beforeParameterGeneration(v, StackValue.onStack(receiver.type));
|
||||||
|
} else {
|
||||||
|
callableMethod.beforeParameterGeneration(v, null);
|
||||||
|
receiver.put(receiver.type, v);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callGenerator.putHiddenParams();
|
callGenerator.putHiddenParams();
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument;
|
||||||
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;
|
||||||
|
|
||||||
@@ -55,4 +56,7 @@ public interface ExtendedCallable extends Callable {
|
|||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
Type getReceiverClass();
|
Type getReceiverClass();
|
||||||
|
|
||||||
|
void beforeParameterGeneration(@NotNull InstructionAdapter v, @Nullable StackValue value);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.intrinsics
|
|||||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||||
import org.jetbrains.kotlin.codegen.CallableMethod
|
import org.jetbrains.kotlin.codegen.CallableMethod
|
||||||
import org.jetbrains.kotlin.codegen.ExtendedCallable
|
import org.jetbrains.kotlin.codegen.ExtendedCallable
|
||||||
|
import org.jetbrains.kotlin.codegen.StackValue
|
||||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
@@ -112,6 +113,10 @@ public abstract class IntrinsicCallable(val returnType1: Type,
|
|||||||
public fun calcReceiverType(): Type? {
|
public fun calcReceiverType(): Type? {
|
||||||
return getReceiverClass() ?: getThisType()
|
return getReceiverClass() ?: getThisType()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,13 @@ public abstract class IntrinsicMethod implements Callable {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type nullOrObject(Type type) {
|
public Type nullOrObject(Type type) {
|
||||||
return type == null ? null : AsmTypes.OBJECT_TYPE;
|
return nullOr(type, AsmTypes.OBJECT_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Type nullOr(Type type, Type newType) {
|
||||||
|
return type == null ? null : newType;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,82 +14,104 @@
|
|||||||
* 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.JetBinaryExpression;
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.psi.JetExpression;
|
import org.jetbrains.kotlin.psi.JetBinaryExpression
|
||||||
import org.jetbrains.org.objectweb.asm.Type;
|
import org.jetbrains.kotlin.psi.JetExpression
|
||||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
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;
|
import org.jetbrains.org.objectweb.asm.Type.*
|
||||||
|
|
||||||
import static org.jetbrains.org.objectweb.asm.Type.*;
|
public class RangeTo : IntrinsicMethod() {
|
||||||
|
override fun generateImpl(codegen: ExpressionCodegen, v: InstructionAdapter, returnType: Type, element: PsiElement?, arguments: List<JetExpression>, receiver: StackValue): Type {
|
||||||
|
v.anew(returnType)
|
||||||
|
v.dup()
|
||||||
|
|
||||||
public class RangeTo extends IntrinsicMethod {
|
val type: Type
|
||||||
@NotNull
|
|
||||||
@Override
|
|
||||||
public Type generateImpl(
|
|
||||||
@NotNull ExpressionCodegen codegen,
|
|
||||||
@NotNull InstructionAdapter v,
|
|
||||||
@NotNull Type returnType,
|
|
||||||
PsiElement element,
|
|
||||||
@NotNull List<JetExpression> arguments,
|
|
||||||
@NotNull StackValue receiver
|
|
||||||
) {
|
|
||||||
v.anew(returnType);
|
|
||||||
v.dup();
|
|
||||||
|
|
||||||
Type type;
|
|
||||||
if (arguments.size() == 1) {
|
if (arguments.size() == 1) {
|
||||||
assert receiver instanceof StackValue.CallReceiver :
|
assert(receiver is StackValue.CallReceiver) { "Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element!!.getText() }
|
||||||
"Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element.getText();
|
type = parameterType(receiver.type, codegen.expressionType(arguments.get(0)))
|
||||||
type = parameterType(receiver.type, codegen.expressionType(arguments.get(0)));
|
receiver.put(type, v)
|
||||||
receiver.put(type, v);
|
codegen.gen(arguments.get(0), type)
|
||||||
codegen.gen(arguments.get(0), type);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
val expression = element as JetBinaryExpression
|
||||||
type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight()));
|
type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight()))
|
||||||
codegen.gen(expression.getLeft(), type);
|
codegen.gen(expression.getLeft(), type)
|
||||||
codegen.gen(expression.getRight(), type);
|
codegen.gen(expression.getRight(), type)
|
||||||
}
|
}
|
||||||
|
|
||||||
v.invokespecial(returnType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, type, type), false);
|
v.invokespecial(returnType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, type, type), false)
|
||||||
|
|
||||||
return returnType;
|
return returnType
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
private fun nameToPrimitive(name: String) : Type {
|
||||||
private static Type parameterType(@NotNull Type leftType, @NotNull Type rightType) {
|
return when (name) {
|
||||||
int left = leftType.getSort();
|
"Double" -> DOUBLE_TYPE;
|
||||||
int right = rightType.getSort();
|
"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: " + name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parameterType(leftType: Type, rightType: Type): Type {
|
||||||
|
val left = leftType.getSort()
|
||||||
|
val right = rightType.getSort()
|
||||||
if (left == DOUBLE || right == DOUBLE) {
|
if (left == DOUBLE || right == DOUBLE) {
|
||||||
return DOUBLE_TYPE;
|
return DOUBLE_TYPE
|
||||||
}
|
}
|
||||||
else if (left == FLOAT || right == FLOAT) {
|
else if (left == FLOAT || right == FLOAT) {
|
||||||
return FLOAT_TYPE;
|
return FLOAT_TYPE
|
||||||
}
|
}
|
||||||
else if (left == LONG || right == LONG) {
|
else if (left == LONG || right == LONG) {
|
||||||
return LONG_TYPE;
|
return LONG_TYPE
|
||||||
}
|
}
|
||||||
else if (left == INT || right == INT) {
|
else if (left == INT || right == INT) {
|
||||||
return INT_TYPE;
|
return INT_TYPE
|
||||||
}
|
}
|
||||||
else if (left == SHORT || right == SHORT) {
|
else if (left == SHORT || right == SHORT) {
|
||||||
return SHORT_TYPE;
|
return SHORT_TYPE
|
||||||
}
|
}
|
||||||
else if (left == CHAR || right == CHAR) {
|
else if (left == CHAR || right == CHAR) {
|
||||||
return CHAR_TYPE;
|
return CHAR_TYPE
|
||||||
}
|
}
|
||||||
else if (left == BYTE || right == BYTE) {
|
else if (left == BYTE || right == BYTE) {
|
||||||
return BYTE_TYPE;
|
return BYTE_TYPE
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new IllegalStateException("RangeTo intrinsic can only work for primitive types: " + leftType + ", " + rightType);
|
throw IllegalStateException("RangeTo intrinsic can only work for primitive types: " + leftType + ", " + rightType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
override fun supportCallable(): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toCallable(fd: FunctionDescriptor, isSuper: Boolean, resolvedCall: ResolvedCall<*>, codegen: ExpressionCodegen): ExtendedCallable {
|
||||||
|
val method = codegen.getState().getTypeMapper().mapToCallableMethod(fd, false, codegen.getContext())
|
||||||
|
val argType = nameToPrimitive(method.getReturnType().getInternalName().substringAfter("kotlin/").substringBefore("Range"))
|
||||||
|
return object : IntrinsicCallable(method.getReturnType(), method.getValueParameterTypes().map { argType }, nullOr(method.getThisType(), argType), nullOr(method.getReceiverClass(), argType)) {
|
||||||
|
override fun beforeParameterGeneration(v: InstructionAdapter, value: StackValue?) {
|
||||||
|
v.anew(getReturnType())
|
||||||
|
v.dup()
|
||||||
|
value?.moveToTopOfStack(value!!.type, v, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun invokeIntrinsic(v: InstructionAdapter) {
|
||||||
|
v.invokespecial(getReturnType().getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, argType, argType), false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user