RenageTo convertion & before call
This commit is contained in:
@@ -181,4 +181,9 @@ public class CallableMethod implements ExtendedCallable {
|
||||
public boolean isStaticCall() {
|
||||
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 ArgumentGenerator argumentGenerator
|
||||
) {
|
||||
StackValue.SafeCall safeCallReceiver = receiver instanceof StackValue.SafeCall ? (StackValue.SafeCall) receiver : null;
|
||||
if (!(resolvedCall.getResultingDescriptor() instanceof ConstructorDescriptor)) { // otherwise already
|
||||
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();
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
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.commons.InstructionAdapter;
|
||||
|
||||
@@ -55,4 +56,7 @@ public interface ExtendedCallable extends Callable {
|
||||
|
||||
@Nullable
|
||||
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.CallableMethod
|
||||
import org.jetbrains.kotlin.codegen.ExtendedCallable
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.context.CodegenContext
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
@@ -112,6 +113,10 @@ public abstract class IntrinsicCallable(val returnType1: Type,
|
||||
public fun calcReceiverType(): Type? {
|
||||
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) {
|
||||
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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen.intrinsics;
|
||||
package org.jetbrains.kotlin.codegen.intrinsics
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen;
|
||||
import org.jetbrains.kotlin.codegen.StackValue;
|
||||
import org.jetbrains.kotlin.psi.JetBinaryExpression;
|
||||
import org.jetbrains.kotlin.psi.JetExpression;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.ExtendedCallable
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.psi.JetBinaryExpression
|
||||
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;
|
||||
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 {
|
||||
@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;
|
||||
val type: Type
|
||||
if (arguments.size() == 1) {
|
||||
assert receiver instanceof StackValue.CallReceiver :
|
||||
"Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element.getText();
|
||||
type = parameterType(receiver.type, codegen.expressionType(arguments.get(0)));
|
||||
receiver.put(type, v);
|
||||
codegen.gen(arguments.get(0), type);
|
||||
assert(receiver is StackValue.CallReceiver) { "Receiver in an intrinsic qualified expression should be CallReceiver: " + receiver + " on " + element!!.getText() }
|
||||
type = parameterType(receiver.type, codegen.expressionType(arguments.get(0)))
|
||||
receiver.put(type, v)
|
||||
codegen.gen(arguments.get(0), type)
|
||||
}
|
||||
else {
|
||||
JetBinaryExpression expression = (JetBinaryExpression) element;
|
||||
type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight()));
|
||||
codegen.gen(expression.getLeft(), type);
|
||||
codegen.gen(expression.getRight(), type);
|
||||
val expression = element as JetBinaryExpression
|
||||
type = parameterType(codegen.expressionType(expression.getLeft()), codegen.expressionType(expression.getRight()))
|
||||
codegen.gen(expression.getLeft(), 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 static Type parameterType(@NotNull Type leftType, @NotNull Type rightType) {
|
||||
int left = leftType.getSort();
|
||||
int right = rightType.getSort();
|
||||
private fun nameToPrimitive(name: String) : Type {
|
||||
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: " + name)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parameterType(leftType: Type, rightType: Type): Type {
|
||||
val left = leftType.getSort()
|
||||
val right = rightType.getSort()
|
||||
if (left == DOUBLE || right == DOUBLE) {
|
||||
return DOUBLE_TYPE;
|
||||
return DOUBLE_TYPE
|
||||
}
|
||||
else if (left == FLOAT || right == FLOAT) {
|
||||
return FLOAT_TYPE;
|
||||
return FLOAT_TYPE
|
||||
}
|
||||
else if (left == LONG || right == LONG) {
|
||||
return LONG_TYPE;
|
||||
return LONG_TYPE
|
||||
}
|
||||
else if (left == INT || right == INT) {
|
||||
return INT_TYPE;
|
||||
return INT_TYPE
|
||||
}
|
||||
else if (left == SHORT || right == SHORT) {
|
||||
return SHORT_TYPE;
|
||||
return SHORT_TYPE
|
||||
}
|
||||
else if (left == CHAR || right == CHAR) {
|
||||
return CHAR_TYPE;
|
||||
return CHAR_TYPE
|
||||
}
|
||||
else if (left == BYTE || right == BYTE) {
|
||||
return BYTE_TYPE;
|
||||
return BYTE_TYPE
|
||||
}
|
||||
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