Box values of inline class types when passing to function as varargs

This commit is contained in:
Mikhail Zarechenskiy
2018-02-12 05:33:12 +03:00
parent 6687751cf5
commit 3919dc94e1
11 changed files with 87 additions and 10 deletions
@@ -2832,13 +2832,16 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
} }
} }
else { else {
return StackValue.operation(type, adapter -> { return StackValue.operation(type, outType, adapter -> {
v.iconst(arguments.size()); v.iconst(arguments.size());
newArrayInstruction(outType); newArrayInstruction(outType);
KotlinType elementKotlinType = outType.getConstructor().getBuiltIns().getArrayElementType(outType);
for (int i = 0; i != size; ++i) { for (int i = 0; i != size; ++i) {
v.dup(); v.dup();
StackValue rightSide = gen(arguments.get(i).getArgumentExpression()); StackValue rightSide = gen(arguments.get(i).getArgumentExpression());
StackValue.arrayElement(elementType, StackValue.onStack(type), StackValue.constant(i, Type.INT_TYPE)).store(rightSide, v); StackValue
.arrayElement(elementType, elementKotlinType, StackValue.onStack(type, outType), StackValue.constant(i, Type.INT_TYPE))
.store(rightSide, v);
} }
return Unit.INSTANCE; return Unit.INSTANCE;
}); });
@@ -4056,7 +4059,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
elementJetType, elementJetType,
ReifiedTypeInliner.OperationKind.NEW_ARRAY ReifiedTypeInliner.OperationKind.NEW_ARRAY
); );
v.newarray(boxType(asmType(elementJetType))); v.newarray(boxType(typeMapper.mapTypeAsDeclaration(elementJetType)));
} }
else { else {
Type type = typeMapper.mapType(arrayType); Type type = typeMapper.mapType(arrayType);
@@ -4089,7 +4092,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue arrayValue = genLazy(array, arrayType); StackValue arrayValue = genLazy(array, arrayType);
StackValue index = genLazy(indices.get(0), Type.INT_TYPE); StackValue index = genLazy(indices.get(0), Type.INT_TYPE);
return StackValue.arrayElement(elementType, arrayValue, index); return StackValue.arrayElement(elementType, null, arrayValue, index);
} }
else { else {
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression); ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression);
@@ -584,7 +584,7 @@ public class PropertyCodegen {
StackValue.Field array = StackValue.field( StackValue.Field array = StackValue.field(
Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none() Type.getType("[" + K_PROPERTY_TYPE), owner, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, true, StackValue.none()
); );
return StackValue.arrayElement(K_PROPERTY_TYPE, array, StackValue.constant(index, Type.INT_TYPE)); return StackValue.arrayElement(K_PROPERTY_TYPE, null, array, StackValue.constant(index, Type.INT_TYPE));
} }
private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased { private static class DelegatedPropertyAccessorStrategy extends FunctionGenerationStrategy.CodegenBased {
@@ -279,8 +279,8 @@ public abstract class StackValue {
} }
@NotNull @NotNull
public static StackValue arrayElement(@NotNull Type type, StackValue array, StackValue index) { public static StackValue arrayElement(@NotNull Type type, @Nullable KotlinType kotlinType, StackValue array, StackValue index) {
return new ArrayElement(type, array, index); return new ArrayElement(type, kotlinType, array, index);
} }
@NotNull @NotNull
@@ -1004,8 +1004,8 @@ public abstract class StackValue {
private static class ArrayElement extends StackValueWithSimpleReceiver { private static class ArrayElement extends StackValueWithSimpleReceiver {
private final Type type; private final Type type;
public ArrayElement(Type type, StackValue array, StackValue index) { public ArrayElement(Type type, KotlinType kotlinType, StackValue array, StackValue index) {
super(type, null, false, false, new Receiver(Type.LONG_TYPE, array, index), true); super(type, kotlinType, false, false, new Receiver(Type.LONG_TYPE, array, index), true);
this.type = type; this.type = type;
} }
@@ -472,11 +472,14 @@ class ExpressionCodegen(
else { else {
mv.iconst(size) mv.iconst(size)
newArrayInstruction(expression.type) newArrayInstruction(expression.type)
val elementKotlinType = outType.constructor.builtIns.getArrayElementType(outType)
for ((i, element) in expression.elements.withIndex()) { for ((i, element) in expression.elements.withIndex()) {
mv.dup() mv.dup()
StackValue.constant(i, Type.INT_TYPE).put(Type.INT_TYPE, mv) StackValue.constant(i, Type.INT_TYPE).put(Type.INT_TYPE, mv)
val rightSide = gen(element, elementType, data) val rightSide = gen(element, elementType, data)
StackValue.arrayElement(elementType, StackValue.onStack(elementType), StackValue.onStack(Type.INT_TYPE)).store(rightSide, mv) StackValue
.arrayElement(elementType, elementKotlinType, StackValue.onStack(elementType, outType), StackValue.onStack(Type.INT_TYPE))
.store(rightSide, mv)
} }
} }
return expression.onStack return expression.onStack
@@ -0,0 +1,24 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val value: Int)
fun <T> takeVarargs(vararg e: T): T {
return e[e.size - 1]
}
fun test(u1: UInt, u2: UInt, u3: UInt?): Int {
val a = takeVarargs(u1, u2)
val b = takeVarargs(u3) ?: UInt(-1)
val c = takeVarargs(u1, u3) ?: UInt(-1)
return a.value + b.value + c.value
}
fun box(): String {
val u1 = UInt(0)
val u2 = UInt(1)
val u3 = UInt(2)
if (test(u1, u2, u3) != 1 + 2 + 2) return "fail"
return "OK"
}
@@ -0,0 +1,17 @@
// !LANGUAGE: +InlineClasses
inline class UInt(val u: Int)
fun <T> takeVarargs(vararg e: T) {}
fun test(u1: UInt, u2: UInt, u3: UInt?) {
takeVarargs(u1, u2) // 2 box
takeVarargs(u3)
takeVarargs(u1, u3) // box
}
// 3 INVOKESTATIC UInt\$Erased.box
// 0 INVOKEVIRTUAL UInt.unbox
// 0 valueOf
// 0 intValue
@@ -10491,6 +10491,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
doTest(fileName);
}
@TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt") @TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception { public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -10491,6 +10491,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
doTest(fileName);
}
@TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt") @TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception { public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -1920,6 +1920,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("boxInlineClassesOnPassingToVarargs.kt")
public void testBoxInlineClassesOnPassingToVarargs() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxInlineClassesOnPassingToVarargs.kt");
doTest(fileName);
}
@TestMetadata("boxResultAfterConstructorCall.kt") @TestMetadata("boxResultAfterConstructorCall.kt")
public void testBoxResultAfterConstructorCall() throws Exception { public void testBoxResultAfterConstructorCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxResultAfterConstructorCall.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxResultAfterConstructorCall.kt");
@@ -10491,6 +10491,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName); doTest(fileName);
} }
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
doTest(fileName);
}
@TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt") @TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception { public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -11475,6 +11475,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
doTest(fileName);
}
@TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt") @TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception { public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");