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 {
return StackValue.operation(type, adapter -> {
return StackValue.operation(type, outType, adapter -> {
v.iconst(arguments.size());
newArrayInstruction(outType);
KotlinType elementKotlinType = outType.getConstructor().getBuiltIns().getArrayElementType(outType);
for (int i = 0; i != size; ++i) {
v.dup();
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;
});
@@ -4056,7 +4059,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
elementJetType,
ReifiedTypeInliner.OperationKind.NEW_ARRAY
);
v.newarray(boxType(asmType(elementJetType)));
v.newarray(boxType(typeMapper.mapTypeAsDeclaration(elementJetType)));
}
else {
Type type = typeMapper.mapType(arrayType);
@@ -4089,7 +4092,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
StackValue arrayValue = genLazy(array, arrayType);
StackValue index = genLazy(indices.get(0), Type.INT_TYPE);
return StackValue.arrayElement(elementType, arrayValue, index);
return StackValue.arrayElement(elementType, null, arrayValue, index);
}
else {
ResolvedCall<FunctionDescriptor> resolvedSetCall = bindingContext.get(INDEXED_LVALUE_SET, expression);
@@ -584,7 +584,7 @@ public class PropertyCodegen {
StackValue.Field array = StackValue.field(
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 {
@@ -279,8 +279,8 @@ public abstract class StackValue {
}
@NotNull
public static StackValue arrayElement(@NotNull Type type, StackValue array, StackValue index) {
return new ArrayElement(type, array, index);
public static StackValue arrayElement(@NotNull Type type, @Nullable KotlinType kotlinType, StackValue array, StackValue index) {
return new ArrayElement(type, kotlinType, array, index);
}
@NotNull
@@ -1004,8 +1004,8 @@ public abstract class StackValue {
private static class ArrayElement extends StackValueWithSimpleReceiver {
private final Type type;
public ArrayElement(Type type, StackValue array, StackValue index) {
super(type, null, false, false, new Receiver(Type.LONG_TYPE, array, index), true);
public ArrayElement(Type type, KotlinType kotlinType, StackValue array, StackValue index) {
super(type, kotlinType, false, false, new Receiver(Type.LONG_TYPE, array, index), true);
this.type = type;
}
@@ -472,11 +472,14 @@ class ExpressionCodegen(
else {
mv.iconst(size)
newArrayInstruction(expression.type)
val elementKotlinType = outType.constructor.builtIns.getArrayElementType(outType)
for ((i, element) in expression.elements.withIndex()) {
mv.dup()
StackValue.constant(i, Type.INT_TYPE).put(Type.INT_TYPE, mv)
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
@@ -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);
}
@TestMetadata("passInlineClassAsVararg.kt")
public void testPassInlineClassAsVararg() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/passInlineClassAsVararg.kt");
doTest(fileName);
}
@TestMetadata("referToPropertyInCompanionObjectOfInlineClass.kt")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -10491,6 +10491,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -1920,6 +1920,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
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")
public void testBoxResultAfterConstructorCall() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/inlineClasses/boxResultAfterConstructorCall.kt");
@@ -10491,6 +10491,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
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")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");
@@ -11475,6 +11475,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
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")
public void testReferToPropertyInCompanionObjectOfInlineClass() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/inlineClasses/referToPropertyInCompanionObjectOfInlineClass.kt");