[IR] Support reflection for MFVC

Signed-off-by: Evgeniy.Zhelenskiy <Evgeniy.Zhelenskiy@jetbrains.com>

#KT-1179
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
index 2180694..978d241 100644
--- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
+++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirLightTreeBlackBoxCodegenTestGenerated.java
@@ -43521,6 +43521,100 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("constructorWithMfvcParameters.kt")
+                public void testConstructorWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("fieldAccessors.kt")
+                public void testFieldAccessors() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
+                }
+
+                @Test
+                @TestMetadata("functionsWithMfvcParameters.kt")
+                public void testFunctionsWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("internalPrimaryValOfMfvc.kt")
+                public void testInternalPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFieldInObject.kt")
+                public void testJvmStaticFieldInObject() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFunction.kt")
+                public void testJvmStaticFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcConstructor.kt")
+                public void testMfvcConstructor() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingFunOfMfvc.kt")
+                public void testNonOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingVarOfMfvc.kt")
+                public void testNonOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingFunOfMfvc.kt")
+                public void testOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingVarOfMfvc.kt")
+                public void testOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("primaryValOfMfvc.kt")
+                public void testPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("properties.kt")
+                public void testProperties() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunction.kt")
+                public void testSuspendFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
+                }
+            }
         }
 
         @Nested
@@ -43641,6 +43735,24 @@
             }
 
             @Test
+            @TestMetadata("mfvcDefaultArguments.kt")
+            public void testMfvcDefaultArguments() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcFunctionsAndConstructors.kt")
+            public void testMfvcFunctionsAndConstructors() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcMembers.kt")
+            public void testMfvcMembers() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
+            }
+
+            @Test
             @TestMetadata("nonDefaultParameterOmitted.kt")
             public void testNonDefaultParameterOmitted() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/callBy/nonDefaultParameterOmitted.kt");
@@ -44485,6 +44597,12 @@
             }
 
             @Test
+            @TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
+            public void testReflectOnDefaultWithMfvcArgument() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
+            }
+
+            @Test
             @TestMetadata("reflectOnLambdaInArrayConstructor.kt")
             public void testReflectOnLambdaInArrayConstructor() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt");
@@ -44555,6 +44673,12 @@
             }
 
             @Test
+            @TestMetadata("constructorWithMfvcParameters.kt")
+            public void testConstructorWithMfvcParameters() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
+            }
+
+            @Test
             @TestMetadata("extensionProperty.kt")
             public void testExtensionProperty() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/mapping/extensionProperty.kt");
@@ -44816,6 +44940,18 @@
                 }
 
                 @Test
+                @TestMetadata("mfvcInSignature.kt")
+                public void testMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
+                }
+
+                @Test
                 @TestMetadata("overrideAnyWithPrimitive.kt")
                 public void testOverrideAnyWithPrimitive() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/overrideAnyWithPrimitive.kt");
@@ -44881,6 +45017,28 @@
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunctionWithMfvcInSignature.kt")
+                public void testSuspendFunctionWithMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
+                }
+            }
         }
 
         @Nested
@@ -45095,6 +45253,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("properties.kt")
             public void testProperties() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/modifiers/properties.kt");
@@ -45905,6 +46069,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("multipleLayers.kt")
             public void testMultipleLayers() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
@@ -46014,6 +46184,12 @@
                 }
 
                 @Test
+                @TestMetadata("mfvc.kt")
+                public void testMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
+                }
+
+                @Test
                 @TestMetadata("mutableCollections_after.kt")
                 public void testMutableCollections_after() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt");
diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
index 5ae50c5e..d1611ba 100644
--- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
+++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirPsiBlackBoxCodegenTestGenerated.java
@@ -43521,6 +43521,100 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("constructorWithMfvcParameters.kt")
+                public void testConstructorWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("fieldAccessors.kt")
+                public void testFieldAccessors() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
+                }
+
+                @Test
+                @TestMetadata("functionsWithMfvcParameters.kt")
+                public void testFunctionsWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("internalPrimaryValOfMfvc.kt")
+                public void testInternalPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFieldInObject.kt")
+                public void testJvmStaticFieldInObject() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFunction.kt")
+                public void testJvmStaticFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcConstructor.kt")
+                public void testMfvcConstructor() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingFunOfMfvc.kt")
+                public void testNonOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingVarOfMfvc.kt")
+                public void testNonOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingFunOfMfvc.kt")
+                public void testOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingVarOfMfvc.kt")
+                public void testOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("primaryValOfMfvc.kt")
+                public void testPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("properties.kt")
+                public void testProperties() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunction.kt")
+                public void testSuspendFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
+                }
+            }
         }
 
         @Nested
@@ -43641,6 +43735,24 @@
             }
 
             @Test
+            @TestMetadata("mfvcDefaultArguments.kt")
+            public void testMfvcDefaultArguments() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcFunctionsAndConstructors.kt")
+            public void testMfvcFunctionsAndConstructors() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcMembers.kt")
+            public void testMfvcMembers() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
+            }
+
+            @Test
             @TestMetadata("nonDefaultParameterOmitted.kt")
             public void testNonDefaultParameterOmitted() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/callBy/nonDefaultParameterOmitted.kt");
@@ -44485,6 +44597,12 @@
             }
 
             @Test
+            @TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
+            public void testReflectOnDefaultWithMfvcArgument() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
+            }
+
+            @Test
             @TestMetadata("reflectOnLambdaInArrayConstructor.kt")
             public void testReflectOnLambdaInArrayConstructor() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt");
@@ -44555,6 +44673,12 @@
             }
 
             @Test
+            @TestMetadata("constructorWithMfvcParameters.kt")
+            public void testConstructorWithMfvcParameters() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
+            }
+
+            @Test
             @TestMetadata("extensionProperty.kt")
             public void testExtensionProperty() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/mapping/extensionProperty.kt");
@@ -44816,6 +44940,18 @@
                 }
 
                 @Test
+                @TestMetadata("mfvcInSignature.kt")
+                public void testMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
+                }
+
+                @Test
                 @TestMetadata("overrideAnyWithPrimitive.kt")
                 public void testOverrideAnyWithPrimitive() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/overrideAnyWithPrimitive.kt");
@@ -44881,6 +45017,28 @@
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunctionWithMfvcInSignature.kt")
+                public void testSuspendFunctionWithMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
+                }
+            }
         }
 
         @Nested
@@ -45095,6 +45253,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("properties.kt")
             public void testProperties() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/modifiers/properties.kt");
@@ -45905,6 +46069,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("multipleLayers.kt")
             public void testMultipleLayers() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
@@ -46014,6 +46184,12 @@
                 }
 
                 @Test
+                @TestMetadata("mfvc.kt")
+                public void testMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
+                }
+
+                @Test
                 @TestMetadata("mutableCollections_after.kt")
                 public void testMutableCollections_after() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt");
diff --git a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
index 7b2d4ad..79c96ea 100644
--- a/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
+++ b/compiler/ir/backend.jvm/lower/src/org/jetbrains/kotlin/backend/jvm/lower/JvmMultiFieldValueClassLowering.kt
@@ -105,15 +105,14 @@
             return expressions.subList(0, expressions.size - repeatable.size) to repeatable
         }
 
-        private fun IrBuilderWithScope.castedToNotNull(expression: IrExpression) =
-            if (expression.type.isNullable()) irImplicitCast(expression, expression.type.makeNotNull()) else expression
-
         fun IrBlockBuilder.addReplacement(expression: IrSetValue, safe: Boolean): IrExpression? {
             oldValueSymbol2NewValueSymbol[expression.symbol]?.let {
                 return irSet(it.owner, expression.value).also { irSet -> +irSet }
             }
             val instance = oldSymbol2MfvcNodeInstance[expression.symbol] ?: return null
-            val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(instance.node, safe, castedToNotNull(expression.value))
+            val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(
+                instance.node, safe, castExpressionToNotNullTypeIfNeeded(expression.value, instance.type)
+            )
             val setterExpressions = instance.makeSetterExpressions(this, values)
             expression2MfvcNodeInstanceAccessor[setterExpressions] = MfvcNodeInstanceAccessor.Setter(instance, values)
             +setterExpressions
@@ -166,7 +165,9 @@
                 accessType = AccessType.AlwaysPrivate,
                 saveVariable = ::variablesSaver
             )
-            val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(node, safe, castedToNotNull(expression.value))
+            val values: List<IrExpression> = makeFlattenedExpressionsWithGivenSafety(
+                node, safe, castExpressionToNotNullTypeIfNeeded(expression.value, node.type)
+            )
             val setterExpressions = instance.makeSetterExpressions(this, values)
             expression2MfvcNodeInstanceAccessor[setterExpressions] = MfvcNodeInstanceAccessor.Setter(instance, values)
             +setterExpressions
@@ -318,6 +319,12 @@
                 if (replacingDeclaration in possibleExtraBoxUsageGenerated) removeAllExtraBoxes()
             } as IrBlockBody
 
+            is IrField -> replacingDeclaration.initializer = replacingDeclaration.initializer?.makeBodyWithAddedVariables(
+                context, variablesToAdd[replacingDeclaration] ?: emptySet(), replacingDeclaration.symbol
+            )?.apply {
+                if (replacingDeclaration in possibleExtraBoxUsageGenerated) removeAllExtraBoxes()
+            } as IrExpressionBody?
+
             else -> Unit
         }
     }
@@ -326,13 +333,15 @@
         irClass.primaryConstructor?.let {
             replacements.getReplacementForRegularClassConstructor(it)?.let { replacement -> addBindingsFor(it, replacement) }
         }
-        val propertiesOrFields = collectPropertiesOrFieldsAfterLowering(irClass)
-        val oldBackingFields = propertiesOrFields.mapNotNull { propertyOrField ->
-            val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: return@mapNotNull null
-            property.backingField?.let { property to it }
-        }.toMap()
-        val propertiesOrFieldsReplacement =
-            collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields) // resets backing fields
+        val propertiesOrFields = collectPropertiesOrFieldsAfterLowering(irClass, context)
+        val oldBackingFields = buildMap {
+            for (propertyOrField in propertiesOrFields) {
+                val property = (propertyOrField as? IrPropertyOrIrField.Property)?.property ?: continue
+                val field = property.backingField ?: continue
+                put(property, field)
+            }
+        }
+        val propertiesOrFieldsReplacement = collectRegularClassMfvcPropertiesOrFieldsReplacement(propertiesOrFields)
 
         val fieldsToRemove = propertiesOrFieldsReplacement.keys.mapNotNull {
             when (it) {
@@ -390,12 +399,15 @@
         context.irFactory.createAnonymousInitializer(
             startOffset = UNDEFINED_OFFSET,
             endOffset = UNDEFINED_OFFSET, origin = IrDeclarationOrigin.GENERATED_MULTI_FIELD_VALUE_CLASS_MEMBER,
-            symbol = IrAnonymousInitializerSymbolImpl()
+            symbol = IrAnonymousInitializerSymbolImpl(),
+            isStatic = element.isStatic,
         ).apply {
             parent = irClass
             body = context.createJvmIrBuilder(symbol).irBlockBody {
                 +irSetField(
-                    irClass.thisReceiver!!.takeUnless { element.isStatic }?.let { irGet(it) }, element, initializer.expression,
+                    receiver = irClass.thisReceiver!!.takeUnless { element.isStatic }?.let { irGet(it) },
+                    field = element,
+                    value = initializer.expression.patchDeclarationParents(irClass),
                     origin = UNSAFE_MFVC_SET_ORIGIN
                 )
             }
@@ -800,18 +812,18 @@
     }
 
     override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
-        val originalFunction = expression.symbol.owner
-        if (originalFunction.getReplacement() == null) return super.visitFunctionReference(expression)
-        return makeNewLambda(originalFunction, expression, makeBody = { wrapper ->
-            with(context.createJvmIrBuilder(wrapper.symbol)) {
-                irExprBody(irCall(originalFunction).apply {
-                    passTypeArgumentsFrom(wrapper)
-                    for ((newParam, originalParam) in wrapper.explicitParameters zip originalFunction.explicitParameters) {
-                        putArgument(originalParam, irGet(newParam))
-                    }
-                }).transform(this@JvmMultiFieldValueClassLowering, null)
+        val function = expression.symbol.owner
+        val replacement = function.getReplacement() ?: return super.visitFunctionReference(expression)
+        return context.createJvmIrBuilder(expression.symbol, expression).irBlock {
+            // Bridge call is added in BridgeLowering
+            buildReplacement(function, expression, replacement) {
+                IrFunctionReferenceImpl(
+                    expression.startOffset, expression.endOffset,
+                    expression.type, replacement.symbol, function.typeParameters.size, replacement.valueParameters.size,
+                    expression.reflectionTarget, expression.origin
+                ).copyAttributes(expression)
             }
-        })
+        }.unwrapBlock()
     }
 
     private fun IrFunction.getReplacement(): IrFunction? =
@@ -995,7 +1007,7 @@
         require(parameter2expression.size == structure.size)
         require(structure.sumOf { it.valueParameters.size } == replacement.explicitParametersCount)
         val newArguments: List<IrExpression?> =
-            makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure.map { it.valueParameters })
+            makeNewArguments(parameter2expression.map { (_, argument) -> argument }, structure)
         val resultExpression = makeMemberAccessExpression(replacement.symbol).apply {
             passTypeArgumentsWithOffsets(replacement, originalFunction) { original.getTypeArgument(it)!! }
             for ((parameter, argument) in replacement.explicitParameters zip newArguments) {
@@ -1023,21 +1035,15 @@
         return super.visitStringConcatenation(expression)
     }
 
-    private fun IrBlockBuilder.makeNewArguments(
-        oldArguments: List<IrExpression?>,
-        structure: List<List<IrValueParameter>>
-    ): List<IrExpression?> {
-        val argumentSizes: List<Int> = structure.map { argTemplate -> argTemplate.size }
-        val newArguments = (oldArguments zip argumentSizes).flatMap { (oldArgument, parametersCount) ->
+    private fun IrBlockBuilder.makeNewArguments(oldArguments: List<IrExpression?>, structure: List<RemappedParameter>): List<IrExpression?> {
+        val argumentSizes: List<Int> = structure.map { argTemplate -> argTemplate.valueParameters.size }
+        val newArguments = (oldArguments zip argumentSizes).flatMapIndexed { index, (oldArgument, parametersCount) ->
             when {
                 oldArgument == null -> List(parametersCount) { null }
                 parametersCount == 1 -> listOf(oldArgument.transform(this@JvmMultiFieldValueClassLowering, null))
                 else -> {
-                    val castedIfNeeded = when {
-                        oldArgument.type.needsMfvcFlattening() -> oldArgument
-                        oldArgument.type.makeNotNull().needsMfvcFlattening() -> irImplicitCast(oldArgument, oldArgument.type.makeNotNull())
-                        else -> error("Unexpected type: ${oldArgument.type.render()}")
-                    }
+                    val expectedType = (structure[index] as MultiFieldValueClassMapping).boxedType
+                    val castedIfNeeded = castExpressionToNotNullTypeIfNeeded(oldArgument, expectedType)
                     flattenExpression(castedIfNeeded).also {
                         require(it.size == parametersCount) { "Expected $parametersCount arguments but got ${it.size}" }
                     }
@@ -1047,6 +1053,12 @@
         return newArguments
     }
 
+    private fun IrBuilderWithScope.castExpressionToNotNullTypeIfNeeded(expression: IrExpression, type: IrType) = when (type) {
+        expression.type -> expression
+        expression.type.makeNotNull() -> irImplicitCast(expression, type)
+        else -> irAs(expression, type)
+    }
+
     /**
      * Inlines initialization of variables when possible and returns their values
      *
@@ -1212,7 +1224,7 @@
         )
         val type = if (expression is IrConstructorCall) expression.symbol.owner.constructedClass.defaultType else expression.type
         val lowering = this@JvmMultiFieldValueClassLowering
-        if (rootNode == null || !type.needsMfvcFlattening()) {
+        if (rootNode == null || !type.needsMfvcFlattening() || instance.size == 1) {
             require(instance.size == 1) { "Required 1 variable/field to store regular value but got ${instance.size}" }
             instance.addSetterStatements(this, listOf(expression.transform(lowering, null)))
             return
@@ -1263,11 +1275,7 @@
             }
         }
         val nullableTransformedExpression = expression.transform(this@JvmMultiFieldValueClassLowering, null)
-        val transformedExpression =
-            if (nullableTransformedExpression.type.isNullable())
-                irImplicitCast(nullableTransformedExpression, nullableTransformedExpression.type.makeNotNull())
-            else
-                nullableTransformedExpression
+        val transformedExpression = castExpressionToNotNullTypeIfNeeded(nullableTransformedExpression, instance.type)
         val addedSettersToFlattened = valueDeclarationsRemapper.handleFlattenedGetterExpressions(this, transformedExpression) {
             require(it.size == instance.size) { "Incompatible assignment sizes: ${it.size}, ${instance.size}" }
             instance.makeSetterExpressions(this, it)
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt
index 2fec1b8..e4d814e 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/MfvcNodeFactory.kt
@@ -32,7 +32,6 @@
 import org.jetbrains.kotlin.ir.types.IrType
 import org.jetbrains.kotlin.ir.types.defaultType
 import org.jetbrains.kotlin.ir.util.*
-import org.jetbrains.kotlin.load.java.JvmAbi
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.util.OperatorNameConventions
 
@@ -61,7 +60,7 @@
             this.name = fullFieldName
             this.type = type
             this.visibility = DescriptorVisibilities.PRIVATE
-            this.metadata = null
+            oldBackingField.metadata = null
         }.apply {
             this.parent = oldBackingField.parent
             this.annotations = fieldAnnotations.map { it.deepCopyWithVariables() }
@@ -246,19 +245,27 @@
     )
 }
 
-fun collectPropertiesAfterLowering(irClass: IrClass): LinkedHashSet<IrProperty> =
-    LinkedHashSet(collectPropertiesOrFieldsAfterLowering(irClass).map { (it as Property).property })
+fun collectPropertiesAfterLowering(irClass: IrClass, context: JvmBackendContext): LinkedHashSet<IrProperty> =
+    LinkedHashSet(collectPropertiesOrFieldsAfterLowering(irClass, context).map { (it as Property).property })
 
 sealed class IrPropertyOrIrField {
     data class Property(val property: IrProperty) : IrPropertyOrIrField()
     data class Field(val field: IrField) : IrPropertyOrIrField()
 }
 
-fun collectPropertiesOrFieldsAfterLowering(irClass: IrClass): LinkedHashSet<IrPropertyOrIrField> =
+fun collectPropertiesOrFieldsAfterLowering(irClass: IrClass, context: JvmBackendContext): LinkedHashSet<IrPropertyOrIrField> =
     LinkedHashSet<IrPropertyOrIrField>().apply {
         for (element in irClass.declarations) {
             if (element is IrField) {
-                element.correspondingPropertySymbol?.owner?.takeUnless { it.isDelegated }?.let { add(Property(it)) } ?: add(Field(element))
+                val property = element.correspondingPropertySymbol?.owner
+                if (
+                    property != null && !property.isDelegated &&
+                    !context.multiFieldValueClassReplacements.getFieldsToRemove(element.parentAsClass).contains(element)
+                ) {
+                    add(Property(property))
+                } else {
+                    add(Field(element))
+                }
             } else if (element is IrSimpleFunction && element.extensionReceiverParameter == null && element.contextReceiverParametersCount == 0) {
                 element.correspondingPropertySymbol?.owner?.let { add(Property(it)) }
             }
@@ -275,7 +282,7 @@
     val oldPrimaryConstructor = mfvc.primaryConstructor!!
     val oldFields = mfvc.fields.filter { !it.isStatic }.toList()
     val representation = mfvc.multiFieldValueClassRepresentation!!
-    val properties = collectPropertiesAfterLowering(mfvc).associateBy { it.isStatic(mfvc) to it.name }
+    val properties = collectPropertiesAfterLowering(mfvc, context).associateBy { it.isStatic(mfvc) to it.name }
 
     val subnodes = makeRootMfvcNodeSubnodes(representation, properties, context, mfvc)
 
@@ -394,6 +401,11 @@
         }
     }
     annotations = oldPrimaryConstructor.annotations
+    if (oldPrimaryConstructor.metadata != null) {
+        metadata = oldPrimaryConstructor.metadata
+        oldPrimaryConstructor.metadata = null
+    }
+    copyAttributes(oldPrimaryConstructor as? IrAttributeContainer)
     // body is added in the Lowering file as it needs to be lowered
 }
 
@@ -448,20 +460,18 @@
         Modality.FINAL,
         oldBackingField,
     ).also {
-        updateAnnotationsAndPropertyFromOldProperty(oldProperty)
+        updateAnnotationsAndPropertyFromOldProperty(oldProperty, context, it)
         it.unboxMethod.overriddenSymbols = listOf() // the getter is saved so it overrides itself
     }
 }
 
 private fun updateAnnotationsAndPropertyFromOldProperty(
-    oldProperty: IrProperty
+    oldProperty: IrProperty,
+    context: JvmBackendContext,
+    node: MfvcNode,
 ) {
-    oldProperty.setter?.apply {
-        name = Name.identifier(JvmAbi.setterName(oldProperty.name.asString()))
-        correspondingPropertySymbol = null
-        origin = IrDeclarationOrigin.DEFINED
-    }
-    oldProperty.setter = null
+    if (node is LeafMfvcNode) return
+    oldProperty.backingField?.let { context.multiFieldValueClassReplacements.addFieldToRemove(it.parentAsClass, it) }
     oldProperty.backingField = null
 }
 
@@ -482,7 +492,7 @@
         parent, context, type, makeTypeArgumentsFromType(type), MethodFullNameMode.Getter, listOf(oldProperty.name),
         fieldAnnotations, static, overriddenNode, null, oldGetter, modality, oldField
     ).also {
-        updateAnnotationsAndPropertyFromOldProperty(oldProperty)
+        updateAnnotationsAndPropertyFromOldProperty(oldProperty, context, it)
     }
 }
 
diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt
index a4a995f..3d2490d 100644
--- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt
+++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/ir/JvmIrUtils.kt
@@ -243,9 +243,11 @@
 fun IrProperty.needsAccessor(accessor: IrSimpleFunction): Boolean = when {
     // Properties in annotation classes become abstract methods named after the property.
     (parent as? IrClass)?.kind == ClassKind.ANNOTATION_CLASS -> true
-    // Multi-field value class getters must always be added. Getters for properties of MFVC itself follow general rules.
+    // Multi-field value class accessors must always be added.
     accessor.isGetter && accessor.contextReceiverParametersCount == 0 && accessor.extensionReceiverParameter == null &&
-            !accessor.parent.let { it is IrClass && it.isMultiFieldValueClass } && accessor.returnType.needsMfvcFlattening() -> true
+            accessor.returnType.needsMfvcFlattening() -> true
+    accessor.isSetter && accessor.contextReceiverParametersCount == 0 && accessor.extensionReceiverParameter == null &&
+            accessor.valueParameters.single().type.needsMfvcFlattening() -> true
     // @JvmField properties have no getters/setters
     resolveFakeOverride()?.backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
     // We do not produce default accessors for private fields
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt
new file mode 100644
index 0000000..996e5b3
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt
@@ -0,0 +1,51 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int)
+
+class Outer(val z1: Z, val z2: Z?) {
+    inner class Inner(val z3: Z, val z4: Z?) {
+        val test = "$z1 $z2 $z3 $z4"
+    }
+}
+
+@JvmInline
+value class ValueNonNullOuter(val z11: Z, val z12: Z) {
+    class Inner(val t: ValueNonNullOuter, val z2: Z, val z3: Z?) {
+        val test = "${t.z11} ${t.z12} $z2 $z3"
+    }
+}
+
+@JvmInline
+value class ValueNullableOuter(val z11: Z?, val z12: Z?) {
+    class Inner(val t: ValueNullableOuter, val z2: Z, val z3: Z?) {
+        val test = "${t.z11} ${t.z12} $z2 $z3"
+    }
+}
+
+fun box(): String {
+    val z1 = Z(1U, -1)
+    val z2 = Z(2U, -2)
+    val z3 = Z(3U, -3)
+    val z4 = Z(4U, -4)
+
+    val outer = ::Outer.call(z1, z2)
+    assertEquals(z1, outer.z1)
+    assertEquals(z2, outer.z2)
+
+    assertEquals("Z(x1=1, x2=-1) Z(x1=2, x2=-2) Z(x1=3, x2=-3) Z(x1=4, x2=-4)", Outer::Inner.call(outer, z3, z4).test)
+    assertEquals("Z(x1=1, x2=-1) Z(x1=2, x2=-2) Z(x1=2, x2=-2) Z(x1=4, x2=-4)", outer::Inner.call(z2, z4).test)
+
+    val valueNonNullOuter = ValueNonNullOuter(z1, z4)
+    assertEquals("Z(x1=1, x2=-1) Z(x1=4, x2=-4) Z(x1=2, x2=-2) Z(x1=3, x2=-3)", ValueNonNullOuter::Inner.call(valueNonNullOuter, z2, z3).test)
+
+    val valueNullableOuter = ValueNullableOuter(z1, z4)
+    assertEquals("Z(x1=1, x2=-1) Z(x1=4, x2=-4) Z(x1=2, x2=-2) Z(x1=3, x2=-3)", ValueNullableOuter::Inner.call(valueNullableOuter, z2, z3).test)
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt
new file mode 100644
index 0000000..20b97fd
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt
@@ -0,0 +1,59 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.jvm.isAccessible
+import kotlin.test.assertEquals
+
+@JvmInline
+value class S(val value1: UInt, val value2: Int) {
+    operator fun plus(other: S): S = S(this.value1 + other.value1, this.value2 + other.value2)
+}
+
+class C {
+    private var nonNullMember: S = S(UInt.MAX_VALUE, -10)
+    private var nullableMember: S? = S(UInt.MAX_VALUE, -10)
+
+    fun nonNullUnboundRef() = C::nonNullMember.apply { isAccessible = true }
+    fun nonNullBoundRef() = this::nonNullMember.apply { isAccessible = true }
+    fun nullableUnboundRef() = C::nullableMember.apply { isAccessible = true }
+    fun nullableBoundRef() = this::nullableMember.apply { isAccessible = true }
+}
+
+private var nonNullTopLevel: S = S(UInt.MAX_VALUE, -10)
+private var nullableTopLevel: S? = S(UInt.MAX_VALUE, -10)
+
+fun box(): String {
+    val c = C()
+    val zero = S(0U, 5)
+    val one = S(1U, 10)
+    val two = S(2U, 20)
+
+    assertEquals(Unit, c.nonNullUnboundRef().setter.call(c, zero))
+    assertEquals(zero, c.nonNullUnboundRef().call(c))
+    assertEquals(zero, c.nonNullUnboundRef().getter.call(c))
+
+    assertEquals(Unit, c.nonNullBoundRef().setter.call(one))
+    assertEquals(one, c.nonNullBoundRef().call())
+    assertEquals(one, c.nonNullBoundRef().getter.call())
+
+    assertEquals(Unit, c.nullableUnboundRef().setter.call(c, zero))
+    assertEquals(zero, c.nullableUnboundRef().call(c))
+    assertEquals(zero, c.nullableUnboundRef().getter.call(c))
+
+    assertEquals(Unit, c.nullableBoundRef().setter.call(one))
+    assertEquals(one, c.nullableBoundRef().call())
+    assertEquals(one, c.nullableBoundRef().getter.call())
+
+    val nonNullTopLevel = ::nonNullTopLevel.apply { isAccessible = true }
+    assertEquals(Unit, nonNullTopLevel.setter.call(two))
+    assertEquals(two, nonNullTopLevel.call())
+    assertEquals(two, nonNullTopLevel.getter.call())
+
+    val nullableTopLevel = ::nullableTopLevel.apply { isAccessible = true }
+    assertEquals(Unit, nullableTopLevel.setter.call(two))
+    assertEquals(two, nullableTopLevel.call())
+    assertEquals(two, nullableTopLevel.getter.call())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt
new file mode 100644
index 0000000..e157ba2
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt
@@ -0,0 +1,53 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+@JvmInline
+value class S(val value1: UInt, val value2: Int) {
+    operator fun plus(other: S): S = S(this.value1 + other.value1, this.value2 + other.value2)
+}
+
+class C {
+    fun member(x: S, y1: UInt, y2: Int, z: S?): S = x + S(y1, y2) + z!!
+}
+
+fun topLevel(x1: UInt, x2: Int, y: S, z: S?): S = S(x1, x2) + y + z!!
+
+fun S.extension1(y: S, z: S?): S = this + y + z!!
+
+fun S?.extension2(y: S, z: S?) = this!! + y + z!!
+
+fun S.extension3_1(): UInt = value1
+fun S.extension3_2(): Int = value2
+
+fun S?.extension4_1(): UInt = this!!.value1
+fun S?.extension4_2(): Int = this!!.value2
+
+fun box(): String {
+    val zero = S(0U, 1000)
+    val one = S(1U, -1)
+    val two = S(2U, -2)
+    val four = S(4U, -4)
+    val seven = S(7U, -7)
+
+    assertEquals(seven, C::member.call(C(), one, 2U, -2, four))
+    assertEquals(seven, ::topLevel.call(1U, -1, two, four))
+    assertEquals(seven, S::extension1.call(one, two, four))
+    assertEquals(seven, S::extension2.call(one, two, four))
+    assertEquals(0U, S::extension3_1.call(zero))
+    assertEquals(1000, S::extension3_2.call(zero))
+    assertEquals(0U, S?::extension4_1.call(zero))
+    assertEquals(1000, S?::extension4_2.call(zero))
+
+    assertEquals(seven, C()::member.call(one, 2U, -2, four))
+    assertEquals(seven, one::extension1.call(two, four))
+    assertEquals(seven, one::extension2.call(two, four))
+    assertEquals(0U, zero::extension3_1.call())
+    assertEquals(1000, zero::extension3_2.call())
+    assertEquals(0U, zero::extension4_1.call())
+    assertEquals(1000, zero::extension4_2.call())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt
new file mode 100644
index 0000000..681b223
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt
@@ -0,0 +1,74 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(internal val x1: UInt, internal val x2: Int)
+@JvmInline
+value class Z2(internal val x1: Z, internal val x2: Z)
+
+@JvmInline
+value class L(internal val x1: ULong, internal val x2: Long)
+@JvmInline
+value class L2(internal val x1: L, internal val x2: L)
+
+@JvmInline
+value class A1(internal val x1: Any?, internal val x2: Any?)
+@JvmInline
+value class A1_2(internal val x1: A1, internal val x2: A1)
+@JvmInline
+value class A2(internal val x1: Any, internal val x2: Any)
+@JvmInline
+value class A2_2(internal val x1: A2, internal val x2: A2)
+
+fun box(): String {
+    assertEquals(42U, Z::x1.call(Z(42U, 43)))
+    assertEquals(43, Z::x2.call(Z(42U, 43)))
+    assertEquals(42U, Z(42U, 43)::x1.call())
+    assertEquals(43, Z(42U, 43)::x2.call())
+
+    assertEquals(1234UL, L::x1.call(L(1234UL, 5678L)))
+    assertEquals(5678L, L::x2.call(L(1234UL, 5678L)))
+    assertEquals(1234UL, L(1234UL, 5678L)::x1.call())
+    assertEquals(5678L, L(1234UL, 5678L)::x2.call())
+
+    assertEquals("abc", A1::x1.call(A1("abc", "def")))
+    assertEquals("def", A1::x2.call(A1("abc", "def")))
+    assertEquals("abc", A1("abc", "def")::x1.call())
+    assertEquals("def", A1("abc", "def")::x2.call())
+    assertEquals(null, A1::x1.call(A1(null, null)))
+    assertEquals(null, A1::x2.call(A1(null, null)))
+    assertEquals(null, A1(null, null)::x1.call())
+    assertEquals(null, A1(null, null)::x2.call())
+    assertEquals("abc", A2::x1.call(A2("abc", "def")))
+    assertEquals("def", A2::x2.call(A2("abc", "def")))
+    assertEquals("abc", A2("abc", "def")::x1.call())
+    assertEquals("def", A2("abc", "def")::x2.call())
+
+    assertEquals(Z(42U, 43), Z2::x1.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Z(44U, 45), Z2::x2.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x1.call())
+    assertEquals(Z(44U, 45), Z2(Z(42U, 43), Z(44U, 45))::x2.call())
+
+    assertEquals(L(1234UL, 5678L), L2::x1.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(L(12340UL, -5678L), L2::x2.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x1.call())
+    assertEquals(L(12340UL, -5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x2.call())
+
+    assertEquals(A1("abc", "def"), A1_2::x1.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(A1("geh", "ijk"), A1_2::x2.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x1.call())
+    assertEquals(A1("geh", "ijk"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x2.call())
+    assertEquals(A1(null, null), A1_2::x1.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(A1(null, null), A1_2::x2.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x1.call())
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x2.call())
+    assertEquals(A2("abc", "def"), A2_2::x1.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(A2("geh", "ijk"), A2_2::x2.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x1.call())
+    assertEquals(A2("geh", "ijk"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x2.call())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt
new file mode 100644
index 0000000..3784db6
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt
@@ -0,0 +1,53 @@
+// TARGET_BACKEND: JVM_IR
+// JVM_TARGET: 1.8
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.KMutableProperty1
+import kotlin.reflect.jvm.isAccessible
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val value1: UInt, val value2: Int) {
+    operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
+}
+
+object C {
+    @JvmStatic
+    private var p1: Z = Z(UInt.MAX_VALUE, -10)
+
+    @JvmStatic
+    private var p2: Z? = Z(UInt.MAX_VALUE, -10)
+
+    fun nonNullBoundRef() = this::p1.apply { isAccessible = true }
+    fun nullableBoundRef() = this::p2.apply { isAccessible = true }
+}
+
+fun box(): String {
+    val one = Z(1U, 10)
+    val two = Z(2U, 20)
+
+    val nonNullUnboundRef = C::class.members.single { it.name == "p1" } as KMutableProperty1<C, Z>
+    nonNullUnboundRef.isAccessible = true
+    assertEquals(Unit, nonNullUnboundRef.setter.call(C, one))
+    assertEquals(one, nonNullUnboundRef.call(C))
+    assertEquals(one, nonNullUnboundRef.getter.call(C))
+
+    val nullableUnboundRef = C::class.members.single { it.name == "p2" } as KMutableProperty1<C, Z?>
+    nullableUnboundRef.isAccessible = true
+    assertEquals(Unit, nullableUnboundRef.setter.call(C, one))
+    assertEquals(one, nullableUnboundRef.call(C))
+    assertEquals(one, nullableUnboundRef.getter.call(C))
+
+    val nonNullBoundRef = C.nonNullBoundRef()
+    assertEquals(Unit, nonNullBoundRef.setter.call(two))
+    assertEquals(two, nonNullBoundRef.call())
+    assertEquals(two, nonNullBoundRef.getter.call())
+
+    val nullableBoundRef = C.nullableBoundRef()
+    assertEquals(Unit, nullableBoundRef.setter.call(two))
+    assertEquals(two, nullableBoundRef.call())
+    assertEquals(two, nullableBoundRef.getter.call())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt
new file mode 100644
index 0000000..d6617fa
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt
@@ -0,0 +1,42 @@
+// TARGET_BACKEND: JVM_IR
+// JVM_TARGET: 1.8
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.KFunction
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val value1: UInt, val value2: Int) {
+    operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
+}
+
+object C {
+    @JvmStatic
+    fun foo(x: Z, y1: UInt, y2: Int, z: Z?): Z = x + Z(y1, y2) + z!!
+}
+
+interface I {
+    companion object {
+        @JvmStatic
+        fun bar(x1: UInt, x2: Int, y: Z, z: Z?): Z = Z(x1, x2) + y + z!!
+    }
+}
+
+fun box(): String {
+    val one = Z(1U, -1)
+    val two = Z(2U, -2)
+    val four = Z(4U, -4)
+    val seven = Z(7U, -7)
+
+    assertEquals(seven, C::foo.call(one, 2U, -2, four))
+    assertEquals(seven, (I)::bar.call(1U, -1, two, four))
+
+    val unboundFoo = C::class.members.single { it.name == "foo" } as KFunction<*>
+    assertEquals(seven, unboundFoo.call(C, one, 2U, -2, four))
+
+    val unboundBar = I.Companion::class.members.single { it.name == "bar" } as KFunction<*>
+    assertEquals(seven, unboundBar.call(I, 1U, -1, two, four))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt
new file mode 100644
index 0000000..25a446d
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt
@@ -0,0 +1,82 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.KCallable
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) {
+    constructor(a: UInt, b: UInt, c: Int, d: Int) : this(a + b, c + d)
+}
+
+@JvmInline
+value class L(val x1: ULong, val x2: Long) {
+    constructor(a: ULong, b: ULong, c: Long, d: Long) : this(a + b, c + d)
+}
+
+@JvmInline
+value class S1(val x1: String, val x2: String) {
+    constructor(a: String, b: String, c: String, d: String) : this(a + b, c + d)
+}
+
+@JvmInline
+value class S2(val x1: String?, val x2: String?) {
+    constructor(a: String?, b: String?, c: String?, d: String?) : this(a!! + b!!, c!! + d!!)
+}
+
+@JvmInline
+value class A(val x1: Any, val x2: Any) {
+    constructor(a: String, b: String, c: String, d: String) : this(a + b, c + d)
+}
+
+@JvmInline
+value class Z2(val z1: Z, val z2: Z) {
+    constructor(z1: Z, z2: Z, z3: Z, z4: Z) : this(Z(z1.x1 + z2.x1, z1.x2 + z2.x2), Z(z3.x1 + z4.x1, z3.x2 + z4.x2))
+}
+
+@JvmInline
+value class Z3(val z1: Z?, val z2: Z?) {
+    constructor(z1: Z?, z2: Z?, z3: Z?, z4: Z?) : this(Z(z1!!.x1 + z2!!.x1, z1!!.x2 + z2!!.x2), Z(z3!!.x1 + z4!!.x1, z3!!.x2 + z4!!.x2))
+}
+
+fun box(): String {
+    val ctorZ1_1: (UInt, Int) -> Z = ::Z
+    val ctorZ1_2: (UInt, UInt, Int, Int) -> Z = ::Z
+    val ctorL1: (ULong, Long) -> L = ::L
+    val ctorL2: (ULong, ULong, Long, Long) -> L = ::L
+    val ctorS1_1: (String, String) -> S1 = ::S1
+    val ctorS1_2: (String, String, String, String) -> S1 = ::S1
+    val ctorS2_1: (String, String) -> S2 = ::S2
+    val ctorS2_2: (String, String, String, String) -> S2 = ::S2
+    val ctorA1: (Any, Any) -> A = ::A
+    val ctorA2: (String, String, String, String) -> A = ::A
+    val ctorZ2_2: (Z, Z) -> Z2 = ::Z2
+    val ctorZ2_4: (Z, Z, Z, Z) -> Z2 = ::Z2
+    val ctorZ3_2: (Z, Z) -> Z3 = ::Z3
+    val ctorZ3_4: (Z, Z, Z, Z) -> Z3 = ::Z3
+
+    assertEquals(Z(42U, 43), (ctorZ1_1 as KCallable<Z>).call(42U, 43))
+    assertEquals(Z(123U, 224), (ctorZ1_2 as KCallable<Z>).call(100U, 23U, 200, 24))
+    assertEquals(L(1UL, 2L), (ctorL1 as KCallable<L>).call(1UL, 2L))
+    assertEquals(L(123UL, 224L), (ctorL2 as KCallable<L>).call(100UL, 23UL, 200L, 24L))
+    assertEquals(S1("abc", "def"), (ctorS1_1 as KCallable<S1>).call("abc", "def"))
+    assertEquals(S1("abc", "def"), (ctorS1_2 as KCallable<S1>).call("ab", "c", "de", "f"))
+    assertEquals(S2("abc", "def"), (ctorS2_1 as KCallable<S2>).call("abc", "def"))
+    assertEquals(S2("abc", "def"), (ctorS2_2 as KCallable<S2>).call("ab", "c", "de", "f"))
+    assertEquals(A("abc", "def"), (ctorA1 as KCallable<A>).call("abc", "def"))
+    assertEquals(A("abc", "def"), (ctorA2 as KCallable<A>).call("a", "bc", "d", "ef"))
+
+    assertEquals(Z2(Z(42U, 43), Z(44U, 45)), (ctorZ2_2 as KCallable<Z2>).call(Z(42U, 43), Z(44U, 45)))
+    assertEquals(Z3(Z(42U, 43), Z(44U, 45)), (ctorZ3_2 as KCallable<Z3>).call(Z(42U, 43), Z(44U, 45)))
+    assertEquals(
+        Z2(Z(142U, 243), Z(344U, 445)),
+        (ctorZ2_4 as KCallable<Z2>).call(Z(42U, 43), Z(100U, 200), Z(44U, 45), Z(300U, 400))
+    )
+    assertEquals(
+        Z3(Z(142U, 243), Z(344U, 445)),
+        (ctorZ3_4 as KCallable<Z3>).call(Z(42U, 43), Z(100U, 200), Z(44U, 45), Z(300U, 400))
+    )
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt
new file mode 100644
index 0000000..0bc1b30
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt
@@ -0,0 +1,37 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) {
+    fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+@JvmInline
+value class S(val x1: String, val x2: String) {
+    fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+@JvmInline
+value class A(val x1: Any, val x2: Any) {
+    fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+fun box(): String {
+    val two = Z(2U, 3)
+    val four = Z(4U, 5)
+
+    val expected = "0912345"
+    assertEquals(expected, Z::test.call(Z(0U, 9), 1, two, four))
+    assertEquals(expected, Z(0U, 9)::test.call(1, two, four))
+
+    assertEquals(expected, S::test.call(S("0", "9"), 1, two, four))
+    assertEquals(expected, S("0", "9")::test.call(1, two, four))
+
+    assertEquals(expected, A::test.call(A(0U, 9), 1, two, four))
+    assertEquals(expected, A(0U, 9)::test.call(1, two, four))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt
new file mode 100644
index 0000000..dd8b4f5
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt
@@ -0,0 +1,127 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+var global = Z(0U, 0)
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) {
+    var nonNullTest: Z
+        get() = Z(global.x1 + this.x1, global.x2 + this.x2)
+        set(value) {
+            global = Z(this.x1 + value.x1, this.x2 + value.x2)
+        }
+
+    var nullableTest: Z?
+        get() = Z(global.x1 + this.x1, global.x2 + this.x2)
+        set(value) {
+            global = Z(this.x1 + value!!.x1, this.x2 + value!!.x2)
+        }
+}
+
+@JvmInline
+value class S(val x1: String, val x2: String) {
+    var nonNullTest: Z
+        get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
+        set(value) {
+            global = Z(this.x1.toUInt() + value.x1, this.x2.toInt() + value.x2)
+        }
+
+    var nullableTest: Z?
+        get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
+        set(value) {
+            global = Z(this.x1.toUInt() + value!!.x1, this.x2.toInt() + value!!.x2)
+        }
+}
+
+@JvmInline
+value class A(val x1: Any, val x2: Any) {
+    var nonNullTest: Z
+        get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
+        set(value) {
+            global = Z(this.x1 as UInt + value.x1, this.x2 as Int + value.x2)
+        }
+
+    var nullableTest: Z?
+        get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
+        set(value) {
+            global = Z(this.x1 as UInt + value!!.x1, this.x2 as Int + value!!.x2)
+        }
+
+}
+
+fun box(): String {
+    val zZero = Z(0U, 0)
+    val zOne = Z(1U, -1)
+    val zTwo = Z(2U, -2)
+    val zThree = Z(3U, -3)
+    val zFour = Z(4U, -4)
+
+    val sOne = S("1", "-1")
+
+    val aOne = A(1U, -1)
+
+    global = zZero
+    assertEquals(zOne, Z::nonNullTest.call(zOne))
+    assertEquals(zOne, zOne::nonNullTest.call())
+    assertEquals(zOne, Z::nonNullTest.getter.call(zOne))
+    assertEquals(zOne, zOne::nonNullTest.getter.call())
+    Z::nonNullTest.setter.call(zOne, zTwo)
+    assertEquals(zThree, global)
+    zOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, Z::nullableTest.call(zOne))
+    assertEquals(zOne, zOne::nullableTest.call())
+    assertEquals(zOne, Z::nullableTest.getter.call(zOne))
+    assertEquals(zOne, zOne::nullableTest.getter.call())
+    Z::nullableTest.setter.call(zOne, zTwo)
+    assertEquals(zThree, global)
+    zOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, S::nonNullTest.call(sOne))
+    assertEquals(zOne, sOne::nonNullTest.call())
+    assertEquals(zOne, S::nonNullTest.getter.call(sOne))
+    assertEquals(zOne, sOne::nonNullTest.getter.call())
+    S::nonNullTest.setter.call(sOne, zTwo)
+    assertEquals(zThree, global)
+    sOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, S::nullableTest.call(sOne))
+    assertEquals(zOne, sOne::nullableTest.call())
+    assertEquals(zOne, S::nullableTest.getter.call(sOne))
+    assertEquals(zOne, sOne::nullableTest.getter.call())
+    S::nullableTest.setter.call(sOne, zTwo)
+    assertEquals(zThree, global)
+    sOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, A::nonNullTest.call(aOne))
+    assertEquals(zOne, aOne::nonNullTest.call())
+    assertEquals(zOne, A::nonNullTest.getter.call(aOne))
+    assertEquals(zOne, aOne::nonNullTest.getter.call())
+    A::nonNullTest.setter.call(aOne, zTwo)
+    assertEquals(zThree, global)
+    aOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, A::nullableTest.call(aOne))
+    assertEquals(zOne, aOne::nullableTest.call())
+    assertEquals(zOne, A::nullableTest.getter.call(aOne))
+    assertEquals(zOne, aOne::nullableTest.getter.call())
+    A::nullableTest.setter.call(aOne, zTwo)
+    assertEquals(zThree, global)
+    aOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt
new file mode 100644
index 0000000..6dc55f7
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt
@@ -0,0 +1,40 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+interface ITest {
+    fun test(a: Int, b: Z, c: Z?): String
+}
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) : ITest {
+    override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+@JvmInline
+value class S(val x1: String, val x2: String) : ITest {
+    override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+@JvmInline
+value class A(val x1: Any, val x2: Any) : ITest {
+    override fun test(a: Int, b: Z, c: Z?) = "$x1$x2$a${b.x1}${b.x2}${c!!.x1}${c!!.x2}"
+}
+
+fun box(): String {
+    val two = Z(2U, 3)
+    val four = Z(4U, 5)
+
+    assertEquals("0912345", Z::test.call(Z(0U, 9), 1, two, four))
+    assertEquals("0912345", Z(0U, 9)::test.call(1, two, four))
+
+    assertEquals("0912345", S::test.call(S("0", "9"), 1, two, four))
+    assertEquals("0912345", S("0", "9")::test.call(1, two, four))
+
+    assertEquals("0912345", A::test.call(A(0U, 9), 1, two, four))
+    assertEquals("0912345", A(0U, 9)::test.call(1, two, four))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt
new file mode 100644
index 0000000..44c811b
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt
@@ -0,0 +1,132 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+var global = Z(0U, 0)
+
+interface ITest {
+    var nonNullTest: Z
+    var nullableTest: Z?
+}
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) : ITest {
+    override var nonNullTest: Z
+        get() = Z(global.x1 + this.x1, global.x2 + this.x2)
+        set(value) {
+            global = Z(this.x1 + value.x1, this.x2 + value.x2)
+        }
+
+    override var nullableTest: Z?
+        get() = Z(global.x1 + this.x1, global.x2 + this.x2)
+        set(value) {
+            global = Z(this.x1 + value!!.x1, this.x2 + value!!.x2)
+        }
+}
+
+@JvmInline
+value class S(val x1: String, val x2: String) : ITest {
+    override var nonNullTest: Z
+        get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
+        set(value) {
+            global = Z(this.x1.toUInt() + value.x1, this.x2.toInt() + value.x2)
+        }
+
+    override var nullableTest: Z?
+        get() = Z(global.x1 + x1.toUInt(), global.x2 + x2.toInt())
+        set(value) {
+            global = Z(this.x1.toUInt() + value!!.x1, this.x2.toInt() + value!!.x2)
+        }
+}
+
+@JvmInline
+value class A(val x1: Any, val x2: Any) : ITest {
+    override var nonNullTest: Z
+        get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
+        set(value) {
+            global = Z(this.x1 as UInt + value.x1, this.x2 as Int + value.x2)
+        }
+
+    override var nullableTest: Z?
+        get() = Z(global.x1 + this.x1 as UInt, global.x2 + this.x2 as Int)
+        set(value) {
+            global = Z(this.x1 as UInt + value!!.x1, this.x2 as Int + value!!.x2)
+        }
+
+}
+
+fun box(): String {
+    val zZero = Z(0U, 0)
+    val zOne = Z(1U, -1)
+    val zTwo = Z(2U, -2)
+    val zThree = Z(3U, -3)
+    val zFour = Z(4U, -4)
+
+    val sOne = S("1", "-1")
+
+    val aOne = A(1U, -1)
+
+    global = zZero
+    assertEquals(zOne, Z::nonNullTest.call(zOne))
+    assertEquals(zOne, zOne::nonNullTest.call())
+    assertEquals(zOne, Z::nonNullTest.getter.call(zOne))
+    assertEquals(zOne, zOne::nonNullTest.getter.call())
+    Z::nonNullTest.setter.call(zOne, zTwo)
+    assertEquals(zThree, global)
+    zOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, Z::nullableTest.call(zOne))
+    assertEquals(zOne, zOne::nullableTest.call())
+    assertEquals(zOne, Z::nullableTest.getter.call(zOne))
+    assertEquals(zOne, zOne::nullableTest.getter.call())
+    Z::nullableTest.setter.call(zOne, zTwo)
+    assertEquals(zThree, global)
+    zOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, S::nonNullTest.call(sOne))
+    assertEquals(zOne, sOne::nonNullTest.call())
+    assertEquals(zOne, S::nonNullTest.getter.call(sOne))
+    assertEquals(zOne, sOne::nonNullTest.getter.call())
+    S::nonNullTest.setter.call(sOne, zTwo)
+    assertEquals(zThree, global)
+    sOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, S::nullableTest.call(sOne))
+    assertEquals(zOne, sOne::nullableTest.call())
+    assertEquals(zOne, S::nullableTest.getter.call(sOne))
+    assertEquals(zOne, sOne::nullableTest.getter.call())
+    S::nullableTest.setter.call(sOne, zTwo)
+    assertEquals(zThree, global)
+    sOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, A::nonNullTest.call(aOne))
+    assertEquals(zOne, aOne::nonNullTest.call())
+    assertEquals(zOne, A::nonNullTest.getter.call(aOne))
+    assertEquals(zOne, aOne::nonNullTest.getter.call())
+    A::nonNullTest.setter.call(aOne, zTwo)
+    assertEquals(zThree, global)
+    aOne::nonNullTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    global = zZero
+    assertEquals(zOne, A::nullableTest.call(aOne))
+    assertEquals(zOne, aOne::nullableTest.call())
+    assertEquals(zOne, A::nullableTest.getter.call(aOne))
+    assertEquals(zOne, aOne::nullableTest.getter.call())
+    A::nullableTest.setter.call(aOne, zTwo)
+    assertEquals(zThree, global)
+    aOne::nullableTest.setter.call(zThree)
+    assertEquals(zFour, global)
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt
new file mode 100644
index 0000000..d25127d
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt
@@ -0,0 +1,180 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+@JvmInline
+value class Z2(val x1: Z, val x2: Z) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+
+@JvmInline
+value class L(val x1: ULong, val x2: Long) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+@JvmInline
+value class L2(val x1: L, val x2: L) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+
+@JvmInline
+value class A1(val x1: Any?, val x2: Any?) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+@JvmInline
+value class A1_2(val x1: A1, val x2: A1) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+@JvmInline
+value class A2(val x1: Any, val x2: Any) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+@JvmInline
+value class A2_2(val x1: A2, val x2: A2) {
+    var x3
+        get() = x1
+        set(value) = Unit
+}
+
+fun box(): String {
+    assertEquals(42U, Z::x1.call(Z(42U, 43)))
+    assertEquals(43, Z::x2.call(Z(42U, 43)))
+    assertEquals(42U, Z::x3.call(Z(42U, 43)))
+    assertEquals(42U, Z::x3.getter.call(Z(42U, 43)))
+    assertEquals(Unit, Z::x3.setter.call(Z(42U, 43), 42U))
+    
+    assertEquals(42U, Z(42U, 43)::x1.call())
+    assertEquals(43, Z(42U, 43)::x2.call())
+    assertEquals(42U, Z(42U, 43)::x3.call())
+    assertEquals(42U, Z(42U, 43)::x3.getter.call())
+    assertEquals(Unit, Z(42U, 43)::x3.setter.call(42U))
+
+    assertEquals(1234UL, L::x1.call(L(1234UL, 5678L)))
+    assertEquals(5678L, L::x2.call(L(1234UL, 5678L)))
+    assertEquals(1234UL, L::x3.call(L(1234UL, 5678L)))
+    assertEquals(1234UL, L::x3.getter.call(L(1234UL, 5678L)))
+    assertEquals(Unit, L::x3.setter.call(L(1234UL, 5678L), 1234UL))
+    
+    assertEquals(1234UL, L(1234UL, 5678L)::x1.call())
+    assertEquals(5678L, L(1234UL, 5678L)::x2.call())
+    assertEquals(1234UL, L(1234UL, 5678L)::x3.call())
+    assertEquals(1234UL, L(1234UL, 5678L)::x3.getter.call())
+    assertEquals(Unit, L(1234UL, 5678L)::x3.setter.call(1234UL))
+
+    assertEquals("abc", A1::x1.call(A1("abc", "def")))
+    assertEquals("def", A1::x2.call(A1("abc", "def")))
+    assertEquals("abc", A1::x3.call(A1("abc", "def")))
+    assertEquals("abc", A1::x3.getter.call(A1("abc", "def")))
+    assertEquals(Unit, A1::x3.setter.call(A1("abc", "def"), "abc"))
+    
+    assertEquals("abc", A1("abc", "def")::x1.call())
+    assertEquals("def", A1("abc", "def")::x2.call())
+    assertEquals("abc", A1("abc", "def")::x3.call())
+    assertEquals("abc", A1("abc", "def")::x3.getter.call())
+    assertEquals(Unit, A1("abc", "def")::x3.setter.call("abc"))
+    
+    assertEquals(null, A1::x1.call(A1(null, null)))
+    assertEquals(null, A1::x2.call(A1(null, null)))
+    assertEquals(null, A1::x3.call(A1(null, null)))
+    assertEquals(null, A1::x3.getter.call(A1(null, null)))
+    assertEquals(Unit, A1::x3.setter.call(A1(null, null), null))
+    
+    assertEquals(null, A1(null, null)::x1.call())
+    assertEquals(null, A1(null, null)::x2.call())
+    assertEquals(null, A1(null, null)::x3.call())
+    assertEquals(null, A1(null, null)::x3.getter.call())
+    assertEquals(Unit, A1(null, null)::x3.setter.call(null))
+    
+    assertEquals("abc", A2::x1.call(A2("abc", "def")))
+    assertEquals("def", A2::x2.call(A2("abc", "def")))
+    assertEquals("abc", A2::x3.call(A2("abc", "def")))
+    assertEquals("abc", A2::x3.getter.call(A2("abc", "def")))
+    assertEquals(Unit, A2::x3.setter.call(A2("abc", "def"), "abc"))
+    
+    assertEquals("abc", A2("abc", "def")::x1.call())
+    assertEquals("def", A2("abc", "def")::x2.call())
+    assertEquals("abc", A2("abc", "def")::x3.call())
+    assertEquals("abc", A2("abc", "def")::x3.getter.call())
+    assertEquals(Unit, A2("abc", "def")::x3.setter.call("abc"))
+
+    assertEquals(Z(42U, 43), Z2::x1.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Z(44U, 45), Z2::x2.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Z(42U, 43), Z2::x3.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Z(42U, 43), Z2::x3.getter.call(Z2(Z(42U, 43), Z(44U, 45))))
+    assertEquals(Unit, Z2::x3.setter.call(Z2(Z(42U, 43), Z(44U, 45)), Z(42U, 43)))
+    
+    assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x1.call())
+    assertEquals(Z(44U, 45), Z2(Z(42U, 43), Z(44U, 45))::x2.call())
+    assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x3.call())
+    assertEquals(Z(42U, 43), Z2(Z(42U, 43), Z(44U, 45))::x3.getter.call())
+    assertEquals(Unit, Z2(Z(42U, 43), Z(44U, 45))::x3.setter.call(Z(42U, 43)))
+
+    assertEquals(L(1234UL, 5678L), L2::x1.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(L(12340UL, -5678L), L2::x2.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(L(1234UL, 5678L), L2::x3.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(L(1234UL, 5678L), L2::x3.getter.call(L2(L(1234UL, 5678L), L(12340UL, -5678L))))
+    assertEquals(Unit, L2::x3.setter.call(L2(L(1234UL, 5678L), L(12340UL, -5678L)), L(1234UL, 5678L)))
+    
+    assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x1.call())
+    assertEquals(L(12340UL, -5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x2.call())
+    assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.call())
+    assertEquals(L(1234UL, 5678L), L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.getter.call())
+    assertEquals(Unit, L2(L(1234UL, 5678L), L(12340UL, -5678L))::x3.setter.call(L(1234UL, 5678L)))
+
+    assertEquals(A1("abc", "def"), A1_2::x1.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(A1("geh", "ijk"), A1_2::x2.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(A1("abc", "def"), A1_2::x3.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(A1("abc", "def"), A1_2::x3.getter.call(A1_2(A1("abc", "def"), A1("geh", "ijk"))))
+    assertEquals(Unit, A1_2::x3.setter.call(A1_2(A1("abc", "def"), A1("geh", "ijk")), A1("abc", "def")))
+    
+    assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x1.call())
+    assertEquals(A1("geh", "ijk"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x2.call())
+    assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.call())
+    assertEquals(A1("abc", "def"), A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.getter.call())
+    assertEquals(Unit, A1_2(A1("abc", "def"), A1("geh", "ijk"))::x3.setter.call(A1("abc", "def")))
+    
+    assertEquals(A1(null, null), A1_2::x1.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(A1(null, null), A1_2::x2.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(A1(null, null), A1_2::x3.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(A1(null, null), A1_2::x3.getter.call(A1_2(A1(null, null), A1(null, null))))
+    assertEquals(Unit, A1_2::x3.setter.call(A1_2(A1(null, null), A1(null, null)), A1(null, null)))
+    
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x1.call())
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x2.call())
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x3.call())
+    assertEquals(A1(null, null), A1_2(A1(null, null), A1(null, null))::x3.getter.call())
+    assertEquals(Unit, A1_2(A1(null, null), A1(null, null))::x3.setter.call(A1(null, null)))
+    
+    assertEquals(A2("abc", "def"), A2_2::x1.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(A2("geh", "ijk"), A2_2::x2.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(A2("abc", "def"), A2_2::x3.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(A2("abc", "def"), A2_2::x3.getter.call(A2_2(A2("abc", "def"), A2("geh", "ijk"))))
+    assertEquals(Unit, A2_2::x3.setter.call(A2_2(A2("abc", "def"), A2("geh", "ijk")), A2("abc", "def")))
+    
+    assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x1.call())
+    assertEquals(A2("geh", "ijk"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x2.call())
+    assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.call())
+    assertEquals(A2("abc", "def"), A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.getter.call())
+    assertEquals(Unit, A2_2(A2("abc", "def"), A2("geh", "ijk"))::x3.setter.call(A2("abc", "def")))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt
new file mode 100644
index 0000000..3e37c63
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt
@@ -0,0 +1,122 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.KMutableProperty2
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val value1: UInt, val value2: Int) {
+    operator fun plus(other: Z): Z = Z(this.value1 + other.value1, this.value2 + other.value2)
+}
+
+class C {
+    var nonNullMember: Z = Z(0U, 0)
+    var nullableMember: Z? = Z(0U, 0)
+
+    private var offset = Z(0U, 0)
+    var Z.nonNull_nonNullMemExt: Z
+        get() = this + offset
+        set(value) { offset = this + value }
+
+    var Z.nonNull_nullableMemExt: Z?
+        get() = this + offset
+        set(value) { offset = this + value!! }
+
+    var Z?.nullable_nonNullMemExt: Z
+        get() = this!! + offset
+        set(value) { offset = this!! + value }
+
+    var Z?.nullable_nullableMemExt: Z?
+        get() = this!! + offset
+        set(value) { offset = this!! + value!! }
+}
+
+var nonNullTopLevel: Z = Z(0U, 0)
+var nullableTopLevel: Z? = Z(0U, 0)
+
+private var offset = Z(0U, 0)
+var Z.nonNull_nonNullExt: Z
+    get() = this + offset
+    set(value) { offset = this + value }
+
+var Z.nonNull_nullableExt: Z?
+    get() = this + offset
+    set(value) { offset = this + value!! }
+
+var Z?.nullable_nonNullExt: Z
+    get() = this!! + offset
+    set(value) { offset = this!! + value }
+
+var Z?.nullable_nullableExt: Z?
+    get() = this!! + offset
+    set(value) { offset = this!! + value!! }
+
+fun box(): String {
+    val one = Z(1U, -1)
+    val two = Z(2U, -2)
+    val three = Z(3U, -3)
+
+    val c = C()
+    assertEquals(Unit, C::nonNullMember.setter.call(c, one))
+    assertEquals(one, C::nonNullMember.call(c))
+    assertEquals(one, C::nonNullMember.getter.call(c))
+
+    assertEquals(Unit, c::nonNullMember.setter.call(two))
+    assertEquals(two, c::nonNullMember.call())
+    assertEquals(two, c::nonNullMember.getter.call())
+
+    assertEquals(Unit, C::nullableMember.setter.call(c, one))
+    assertEquals(one, C::nullableMember.call(c))
+    assertEquals(one, C::nullableMember.getter.call(c))
+
+    assertEquals(Unit, c::nullableMember.setter.call(two))
+    assertEquals(two, c::nullableMember.call())
+    assertEquals(two, c::nullableMember.getter.call())
+
+    val nonNull_nonNullMemExt = C::class.members.single { it.name == "nonNull_nonNullMemExt" } as KMutableProperty2<C, Z, Z>
+    assertEquals(Unit, nonNull_nonNullMemExt.setter.call(c, Z(0U, 0), two))
+    assertEquals(three, nonNull_nonNullMemExt.call(c, one))
+    assertEquals(three, nonNull_nonNullMemExt.getter.call(c, one))
+
+    val nonNull_nullableMemExt = C::class.members.single { it.name == "nonNull_nullableMemExt" } as KMutableProperty2<C, Z, Z?>
+    assertEquals(Unit, nonNull_nullableMemExt.setter.call(c, Z(0U, 0), two))
+    assertEquals(three, nonNull_nullableMemExt.call(c, one))
+    assertEquals(three, nonNull_nullableMemExt.getter.call(c, one))
+
+    val nullable_nonNullMemExt = C::class.members.single { it.name == "nullable_nonNullMemExt" } as KMutableProperty2<C, Z?, Z>
+    assertEquals(Unit, nullable_nonNullMemExt.setter.call(c, Z(0U, 0), two))
+    assertEquals(three, nullable_nonNullMemExt.call(c, one))
+    assertEquals(three, nullable_nonNullMemExt.getter.call(c, one))
+
+    val nullable_nullableMemExt = C::class.members.single { it.name == "nullable_nullableMemExt" } as KMutableProperty2<C, Z?, Z?>
+    assertEquals(Unit, nullable_nullableMemExt.setter.call(c, Z(0U, 0), two))
+    assertEquals(three, nullable_nullableMemExt.call(c, one))
+    assertEquals(three, nullable_nullableMemExt.getter.call(c, one))
+
+    assertEquals(Unit, ::nonNullTopLevel.setter.call(one))
+    assertEquals(one, ::nonNullTopLevel.call())
+    assertEquals(one, ::nonNullTopLevel.getter.call())
+
+    assertEquals(Unit, ::nullableTopLevel.setter.call(one))
+    assertEquals(one, ::nullableTopLevel.call())
+    assertEquals(one, ::nullableTopLevel.getter.call())
+
+    assertEquals(Unit, Z::nonNull_nonNullExt.setter.call(Z(0U, 0), two))
+    assertEquals(three, Z::nonNull_nonNullExt.call(one))
+    assertEquals(three, Z::nonNull_nonNullExt.getter.call(one))
+
+    assertEquals(Unit, Z::nonNull_nullableExt.setter.call(Z(0U, 0), two))
+    assertEquals(three, Z::nonNull_nullableExt.call(one))
+    assertEquals(three, Z::nonNull_nullableExt.getter.call(one))
+
+    assertEquals(Unit, Z?::nullable_nonNullExt.setter.call(Z(0U, 0), two))
+    assertEquals(three, Z?::nullable_nonNullExt.call(one))
+    assertEquals(three, Z?::nullable_nonNullExt.getter.call(one))
+
+    assertEquals(Unit, Z?::nullable_nullableExt.setter.call(Z(0U, 0), two))
+    assertEquals(three, Z?::nullable_nullableExt.call(one))
+    assertEquals(three, Z?::nullable_nullableExt.getter.call(one))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt b/compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt
new file mode 100644
index 0000000..5b19e09
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt
@@ -0,0 +1,91 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// WITH_COROUTINES
+// LANGUAGE: +ValueClasses
+
+import kotlin.coroutines.startCoroutine
+import kotlin.reflect.full.callSuspend
+import kotlin.test.assertEquals
+import kotlin.test.assertFailsWith
+import helpers.*
+
+@JvmInline
+value class Z(val value1: UInt, val value2: Int)
+
+class C {
+    private var value: Z = Z(0U, 0)
+
+    suspend fun nonNullConsume(z: Z) { value = z }
+    suspend fun nonNullProduce(): Z = value
+    suspend fun nullableConsume(z: Z?) { value = z!! }
+    suspend fun nullableProduce(): Z? = value
+    suspend fun nonNull_nonNullConsumeAndProduce(z: Z): Z = z
+    suspend fun nonNull_nullableConsumeAndProduce(z: Z): Z? = z
+    suspend fun nullable_nonNullConsumeAndProduce(z: Z?): Z = z!!
+    suspend fun nullable_nullableConsumeAndProduce(z: Z?): Z? = z
+}
+
+private fun run0(f: suspend () -> Int): Int {
+    var result = -1
+    f.startCoroutine(handleResultContinuation { result = it })
+    return result
+}
+
+private fun run0U(f: suspend () -> UInt): UInt {
+    var result = UInt.MAX_VALUE
+    f.startCoroutine(handleResultContinuation { result = it })
+    return result
+}
+
+fun box(): String {
+    val c = C()
+
+    run0U {
+        C::nonNullConsume.callSuspend(c, Z(1U, -1))
+        C::nonNullProduce.callSuspend(c).value1
+    }.let { assertEquals(1U, it) }
+
+    run0 {
+        C::nonNullConsume.callSuspend(c, Z(1U, -1))
+        C::nonNullProduce.callSuspend(c).value2
+    }.let { assertEquals(-1, it) }
+
+    run0U {
+        C::nullableConsume.callSuspend(c, Z(2U, -2))
+        C::nullableProduce.callSuspend(c)!!.value1
+    }.let { assertEquals(2U, it) }
+    run0 {
+        C::nullableConsume.callSuspend(c, Z(2U, -2))
+        C::nullableProduce.callSuspend(c)!!.value2
+    }.let { assertEquals(-2, it) }
+
+    run0U {
+        C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3U, -3)).value1
+    }.let { assertEquals(3U, it) }
+    run0 {
+        C::nonNull_nonNullConsumeAndProduce.callSuspend(c, Z(3U, -3)).value2
+    }.let { assertEquals(-3, it) }
+
+    run0U {
+        C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4U, -4))!!.value1
+    }.let { assertEquals(4U, it) }
+    run0 {
+        C::nonNull_nullableConsumeAndProduce.callSuspend(c, Z(4U, -4))!!.value2
+    }.let { assertEquals(-4, it) }
+
+    run0U {
+        C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5U, -5)).value1
+    }.let { assertEquals(5U, it) }
+    run0 {
+        C::nullable_nonNullConsumeAndProduce.callSuspend(c, Z(5U, -5)).value2
+    }.let { assertEquals(-5, it) }
+
+    run0U {
+        C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6U, -6))!!.value1
+    }.let { assertEquals(6U, it) }
+    run0 {
+        C::nullable_nullableConsumeAndProduce.callSuspend(c, Z(6U, -6))!!.value2
+    }.let { assertEquals(-6, it) }
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt b/compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt
new file mode 100644
index 0000000..9de476a
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt
@@ -0,0 +1,72 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+
+@JvmInline
+value class A(val x: UInt, val y: Int)
+
+fun test1(x: A = A(0U, 1)) = "OK"
+
+fun test32(
+    arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
+    arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
+    arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
+    arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
+    arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
+    arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
+    arg30: Long = 0L, x: A = A(0U, 1)
+) = "OK"
+
+fun test33(
+    arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
+    arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
+    arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
+    arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
+    arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
+    arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
+    arg30: Long = 0L, arg31: Long = 0L, x: A = A(0U, 1)
+) = "OK"
+
+fun test64(
+    arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
+    arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
+    arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
+    arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
+    arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
+    arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
+    arg30: Long = 0L, arg31: Long = 0L, arg32: Long = 0L, arg33: Long = 0L, arg34: Long = 0L,
+    arg35: Long = 0L, arg36: Long = 0L, arg37: Long = 0L, arg38: Long = 0L, arg39: Long = 0L,
+    arg40: Long = 0L, arg41: Long = 0L, arg42: Long = 0L, arg43: Long = 0L, arg44: Long = 0L,
+    arg45: Long = 0L, arg46: Long = 0L, arg47: Long = 0L, arg48: Long = 0L, arg49: Long = 0L,
+    arg50: Long = 0L, arg51: Long = 0L, arg52: Long = 0L, arg53: Long = 0L, arg54: Long = 0L,
+    arg55: Long = 0L, arg56: Long = 0L, arg57: Long = 0L, arg58: Long = 0L, arg59: Long = 0L,
+    arg60: Long = 0L, arg61: Long = 0L, arg62: Long = 0L, x: A = A(0U, 1)
+) = "OK"
+
+fun test65(
+    arg00: Long = 0L, arg01: Long = 0L, arg02: Long = 0L, arg03: Long = 0L, arg04: Long = 0L,
+    arg05: Long = 0L, arg06: Long = 0L, arg07: Long = 0L, arg08: Long = 0L, arg09: Long = 0L,
+    arg10: Long = 0L, arg11: Long = 0L, arg12: Long = 0L, arg13: Long = 0L, arg14: Long = 0L,
+    arg15: Long = 0L, arg16: Long = 0L, arg17: Long = 0L, arg18: Long = 0L, arg19: Long = 0L,
+    arg20: Long = 0L, arg21: Long = 0L, arg22: Long = 0L, arg23: Long = 0L, arg24: Long = 0L,
+    arg25: Long = 0L, arg26: Long = 0L, arg27: Long = 0L, arg28: Long = 0L, arg29: Long = 0L,
+    arg30: Long = 0L, arg31: Long = 0L, arg32: Long = 0L, arg33: Long = 0L, arg34: Long = 0L,
+    arg35: Long = 0L, arg36: Long = 0L, arg37: Long = 0L, arg38: Long = 0L, arg39: Long = 0L,
+    arg40: Long = 0L, arg41: Long = 0L, arg42: Long = 0L, arg43: Long = 0L, arg44: Long = 0L,
+    arg45: Long = 0L, arg46: Long = 0L, arg47: Long = 0L, arg48: Long = 0L, arg49: Long = 0L,
+    arg50: Long = 0L, arg51: Long = 0L, arg52: Long = 0L, arg53: Long = 0L, arg54: Long = 0L,
+    arg55: Long = 0L, arg56: Long = 0L, arg57: Long = 0L, arg58: Long = 0L, arg59: Long = 0L,
+    arg60: Long = 0L, arg61: Long = 0L, arg62: Long = 0L, arg63: Long = 0L, x: A = A(0U, 1)
+) = "OK"
+
+fun box(): String {
+    assertEquals("OK", ::test1.callBy(mapOf()))
+    assertEquals("OK", ::test32.callBy(mapOf()))
+    assertEquals("OK", ::test33.callBy(mapOf()))
+    assertEquals("OK", ::test64.callBy(mapOf()))
+    assertEquals("OK", ::test65.callBy(mapOf()))
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt b/compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt
new file mode 100644
index 0000000..f84056a
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt
@@ -0,0 +1,53 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+@JvmInline
+value class S(val value1: UInt, val value2: String) {
+    operator fun plus(other: S): S = S(this.value1 * 10U + other.value1, this.value2 + other.value2)
+}
+
+class C {
+    fun member(a: S, b: S = S(1U, "b2")): S = a + b
+}
+
+fun topLevel(c: S, d: S = S(1U, "d2")): S = c + d
+
+class D(e: S, f: S = S(1U, "f2")) {
+    val result = e + f
+}
+
+fun S.extension(h: S = S(1U, "h2")): S = this + h
+
+fun box(): String {
+    assertEquals(S(11U, "a2b2"), C().member(S(1U, "a2")))
+    assertEquals(
+        S(11U, "a2b2"),
+        C::member.callBy(C::member.parameters.filter { it.name != "b" }.associateWith { (if (it.name == "a") S(1U, "a2") else C()) })
+    )
+
+    assertEquals(S(11U, "c2d2"), topLevel(S(1U, "c2")))
+    assertEquals(S(11U, "c2d2"), ::topLevel.callBy(::topLevel.parameters.filter { it.name != "d" }.associateWith { S(1U, "c2") }))
+
+    assertEquals(S(11U, "e2f2"), ::D.callBy(::D.parameters.filter { it.name != "f" }.associateWith { S(1U, "e2") }).result)
+
+    assertEquals(S(11U, "g2h2"), S(1U, "g2").extension())
+    assertEquals(S(11U, "g2h2"), S::extension.callBy(S::extension.parameters.filter { it.name != "h" }.associateWith { S(1U, "g2") }))
+
+    val boundMember = C()::member
+    assertEquals(S(11U, "a2b2"), boundMember.callBy(boundMember.parameters.associateWith { S(1U, it.name!! + "2") }))
+
+    val boundExtension = S(1U, "g2")::extension
+    assertEquals(S(11U, "g2h2"), boundExtension.callBy(boundExtension.parameters.associateWith { S(1U, it.name!! + "2") }))
+
+    val mfvcConstructor = ::S
+    val exception = runCatching { mfvcConstructor.callBy(mapOf(mfvcConstructor.parameters.first() to 1U)) }.exceptionOrNull()!!
+    assertTrue(exception is IllegalArgumentException)
+    assertTrue(exception.message!!.startsWith("No argument provided for a required parameter: parameter #1 value2 of fun `<init>`(kotlin.UInt, kotlin.String): "), exception.message)
+    assertTrue(exception.message!!.endsWith("S"), exception.message)
+    
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt b/compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt
new file mode 100644
index 0000000..6fb4129
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt
@@ -0,0 +1,77 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+import kotlin.test.assertEquals
+
+interface IFoo {
+    fun fooFun(z: Z): Z
+    var fooVar: Z
+}
+
+var global = Z(0U, 0)
+
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int) : IFoo {
+
+    override fun fooFun(z: Z): Z = Z(z.x1 + x1, z.x2 + x2)
+
+    override var fooVar: Z
+        get() = Z(global.x1 + x1, global.x2 + x2)
+        set(value) {
+            global = Z(value.x1 + x1, value.x2 + x2)
+        }
+
+    fun barFun(z: Z): Z = Z(z.x1 * 100U + x1, z.x2 * 100 + x2)
+
+    var barVar: Z
+        get() = Z(global.x1 * 100U + x1, global.x2 * 100 + x2)
+        set(value) {
+            global = Z(value.x1 * 100U + x1, value.x2 * 100 + x2)
+        }
+}
+
+
+fun box(): String {
+    val fooFunR = Z::fooFun
+    assertEquals(Z(53U, -53), fooFunR.callBy(mapOf(fooFunR.parameters[0] to Z(42U, -42), fooFunR.parameters[1] to Z(11U, -11))))
+
+    val fooFunBR = Z(42U, -42)::fooFun
+    assertEquals(Z(142U, -142), fooFunBR.callBy(mapOf(fooFunBR.parameters[0] to Z(100U, -100))))
+
+    global = Z(0U, 0)
+    val fooVarR = Z::fooVar
+    assertEquals(Z(42U, -42), fooVarR.callBy(mapOf(fooVarR.parameters[0] to Z(42U, -42))))
+    assertEquals(Z(42U, -42), fooVarR.getter.callBy(mapOf(fooVarR.getter.parameters[0] to Z(42U, -42))))
+    fooVarR.setter.callBy(mapOf(fooVarR.setter.parameters[0] to Z(42U, -42), fooVarR.setter.parameters[1] to Z(1U, -1)))
+    assertEquals(Z(43U, -43), global)
+
+    global = Z(100U, -100)
+    val fooVarBR = Z(42U, -42)::fooVar
+    assertEquals(Z(142U, -142), fooVarBR.callBy(mapOf()))
+    assertEquals(Z(142U, -142), fooVarBR.getter.callBy(mapOf()))
+    fooVarBR.setter.callBy(mapOf(fooVarBR.setter.parameters[0] to Z(1U, -1)))
+    assertEquals(Z(43U, -43), global)
+
+    val barFunR = Z::barFun
+    assertEquals(Z(1142U, -1142), barFunR.callBy(mapOf(barFunR.parameters[0] to Z(42U, -42), barFunR.parameters[1] to Z(11U, -11))))
+
+    val barFunBR = Z(42U, -42)::barFun
+    assertEquals(Z(2242U, -2242), barFunBR.callBy(mapOf(barFunBR.parameters[0] to Z(22U, -22))))
+
+    global = Z(1U, -1)
+    val barVarR = Z::barVar
+    assertEquals(Z(142U, -142), barVarR.callBy(mapOf(barVarR.parameters[0] to Z(42U, -42))))
+    assertEquals(Z(142U, -142), barVarR.getter.callBy(mapOf(barVarR.getter.parameters[0] to Z(42U, -42))))
+    barVarR.setter.callBy(mapOf(barVarR.setter.parameters[0] to Z(42U, -42), barVarR.setter.parameters[1] to Z(3U, -3)))
+    assertEquals(Z(342U, -342), global)
+
+    global = Z(2U, -2)
+    val barVarBR = Z(42U, -42)::barVar
+    assertEquals(Z(242U, -242), barVarBR.callBy(mapOf()))
+    assertEquals(Z(242U, -242), barVarBR.getter.callBy(mapOf()))
+    barVarBR.setter.callBy(mapOf(barVarBR.setter.parameters[0] to Z(4U, -4)))
+    assertEquals(Z(442U, -442), global)
+
+    return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt
new file mode 100644
index 0000000..7256f40
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt
@@ -0,0 +1,14 @@
+// LAMBDAS: CLASS
+// !OPT_IN: kotlin.reflect.jvm.ExperimentalReflectionOnLambdas
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.jvm.reflect
+
+@JvmInline
+value class C(val x1: UInt, val x2: Int)
+
+fun C.f(x: (String) -> Unit = { OK: String -> }) = x.reflect()?.parameters?.singleOrNull()?.name
+
+fun box(): String = C(0U, 1).f() ?: "null"
diff --git a/compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt b/compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt
new file mode 100644
index 0000000..cfefc53
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt
@@ -0,0 +1,23 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+import kotlin.reflect.full.primaryConstructor
+import kotlin.reflect.jvm.javaConstructor
+import kotlin.reflect.jvm.kotlinFunction
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val x1: UInt, val x2: Int)
+
+class Test(val x: Z)
+
+fun box(): String {
+    val kctor1 = Test::class.primaryConstructor ?: throw AssertionError("No primary constructor")
+    val jctor1 = kctor1.javaConstructor ?: throw AssertionError("No javaConstructor for $kctor1")
+    val kctor2 = jctor1.kotlinFunction ?: throw AssertionError("No kotlinFunction for $jctor1")
+
+    assertEquals(kctor1, kctor2)
+    assertEquals("[x]", kctor2.parameters.map { it.name }.toString())
+
+    return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/reflection/mapping/types/inlineClassInSignature.kt b/compiler/testData/codegen/box/reflection/mapping/types/inlineClassInSignature.kt
index d9f90b9..eb9ddc0 100644
--- a/compiler/testData/codegen/box/reflection/mapping/types/inlineClassInSignature.kt
+++ b/compiler/testData/codegen/box/reflection/mapping/types/inlineClassInSignature.kt
@@ -8,20 +8,16 @@
 
 fun S.foo(x: Int, s: S): S = this
 
-/* TODO: Support calling members of inline classes in reflection (KT-26748)
 inline class T(val s: S) {
     fun bar(u: S): T = this
 }
-*/
 
 fun box(): String {
     assertEquals(listOf(String::class.java, Int::class.java, String::class.java), S::foo.parameters.map { it.type.javaType })
     assertEquals(String::class.java, S::foo.returnType.javaType)
 
-/*
-    assertEquals(listOf(), T::bar.parameters.map { it.type.javaType })
+    assertEquals(listOf(String::class.java, String::class.java), T::bar.parameters.map { it.type.javaType })
     assertEquals(String::class.java, T::bar.returnType.javaType)
-*/
 
     return "OK"
 }
diff --git a/compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt b/compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt
new file mode 100644
index 0000000..e7b0a61
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt
@@ -0,0 +1,46 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.jvm.*
+import kotlin.test.assertEquals
+import java.lang.reflect.Type
+
+@JvmInline
+value class S(val value1: UInt, val value2: String)
+
+fun S.foo(x: Int, s: S): S = this
+
+fun compoundType(vararg types: Type) = listOf(*types).toString()
+
+@JvmInline
+value class T(val s: S) {
+    fun bar(u: S): T = this
+}
+data class U(val s: S) {
+    fun bar(u: S): U = this
+}
+
+@kotlin.ExperimentalStdlibApi
+fun box(): String {
+    assertEquals(listOf(Int::class.java, String::class.java), ::S.parameters.map { it.type.javaType })
+    assertEquals(S::class.java, ::S.returnType.javaType)
+
+    assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::T.parameters.map { it.type.javaType.toString() })
+    assertEquals(T::class.java, ::T.returnType.javaType)
+
+    assertEquals(listOf(compoundType(Int::class.java, String::class.java)), ::U.parameters.map { it.type.javaType.toString() })
+    assertEquals(U::class.java, ::U.returnType.javaType)
+
+    
+    assertEquals(listOf(compoundType(Int::class.java, String::class.java), Int::class.java.toString(), compoundType(Int::class.java, String::class.java)), S::foo.parameters.map { it.type.javaType.toString() })
+    assertEquals(S::class.java, S::foo.returnType.javaType)
+
+    assertEquals(listOf(compoundType(Int::class.java, String::class.java), compoundType(Int::class.java, String::class.java)), T::bar.parameters.map { it.type.javaType.toString() })
+    assertEquals(T::class.java, T::bar.returnType.javaType)
+
+    assertEquals(listOf(U::class.java.toString(), compoundType(Int::class.java, String::class.java)), U::bar.parameters.map { it.type.javaType.toString() })
+    assertEquals(U::class.java, U::bar.returnType.javaType)
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt b/compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt
new file mode 100644
index 0000000..154089b
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt
@@ -0,0 +1,85 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+package test
+
+import kotlin.reflect.KCallable
+import kotlin.reflect.jvm.*
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z1(val publicX1: UInt, val publicX2: Int) {
+    companion object {
+        val publicX1Ref = Z1::publicX1
+        val publicX2Ref = Z1::publicX2
+        val publicX1BoundRef = Z1(42U, 43)::publicX1
+        val publicX2BoundRef = Z1(42U, 43)::publicX2
+    }
+}
+
+@JvmInline
+value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
+    companion object {
+        val internalX1Ref = Z2::internalX1
+        val internalX2Ref = Z2::internalX2
+        val internalX1BoundRef = Z2(42U, 43)::internalX1
+        val internalX2BoundRef = Z2(42U, 43)::internalX2
+    }
+}
+
+@JvmInline
+value class Z3(private val privateX1: UInt, private val privateX2: Int) {
+    companion object {
+        val privateX1Ref = Z3::privateX1
+        val privateX2Ref = Z3::privateX2
+        val privateX1BoundRef = Z3(42U, 43)::privateX1
+        val privateX2BoundRef = Z3(42U, 43)::privateX2
+    }
+}
+
+@JvmInline
+value class ZZ(val x1: Z1, val x2: Z1)
+
+fun KCallable<*>.getJavaTypesOfParams() = parameters.map { it.type.javaType }.toString()
+fun KCallable<*>.getJavaTypeOfResult() = returnType.javaType.toString()
+
+fun box(): String {
+    assertEquals("[class test.Z1]", Z1.publicX1Ref.getJavaTypesOfParams())
+    assertEquals("[class test.Z1]", Z1.publicX2Ref.getJavaTypesOfParams())
+    assertEquals("int", Z1.publicX1Ref.getJavaTypeOfResult())
+    assertEquals("int", Z1.publicX2Ref.getJavaTypeOfResult())
+
+    assertEquals("[]", Z1.publicX1BoundRef.getJavaTypesOfParams())
+    assertEquals("[]", Z1.publicX2BoundRef.getJavaTypesOfParams())
+    assertEquals("int", Z1.publicX1BoundRef.getJavaTypeOfResult())
+    assertEquals("int", Z1.publicX2BoundRef.getJavaTypeOfResult())
+
+    assertEquals("[class test.Z2]", Z2.internalX1Ref.getJavaTypesOfParams())
+    assertEquals("[class test.Z2]", Z2.internalX2Ref.getJavaTypesOfParams())
+    assertEquals("int", Z2.internalX1Ref.getJavaTypeOfResult())
+    assertEquals("int", Z2.internalX2Ref.getJavaTypeOfResult())
+
+    assertEquals("[]", Z2.internalX1BoundRef.getJavaTypesOfParams())
+    assertEquals("[]", Z2.internalX2BoundRef.getJavaTypesOfParams())
+    assertEquals("int", Z2.internalX1BoundRef.getJavaTypeOfResult())
+    assertEquals("int", Z2.internalX2BoundRef.getJavaTypeOfResult())
+
+    assertEquals("[class test.Z3]", Z3.privateX1Ref.getJavaTypesOfParams())
+    assertEquals("[class test.Z3]", Z3.privateX2Ref.getJavaTypesOfParams())
+    assertEquals("int", Z3.privateX1Ref.getJavaTypeOfResult())
+    assertEquals("int", Z3.privateX2Ref.getJavaTypeOfResult())
+
+    assertEquals("[]", Z3.privateX1BoundRef.getJavaTypesOfParams())
+    assertEquals("[]", Z3.privateX2BoundRef.getJavaTypesOfParams())
+    assertEquals("int", Z3.privateX1BoundRef.getJavaTypeOfResult())
+    assertEquals("int", Z3.privateX2BoundRef.getJavaTypeOfResult())
+
+
+    assertEquals("[class test.ZZ]", ZZ::x1.getJavaTypesOfParams())
+    assertEquals("[class test.ZZ]", ZZ::x2.getJavaTypesOfParams())
+    assertEquals("class test.Z1", ZZ::x1.getJavaTypeOfResult())
+    assertEquals("class test.Z1", ZZ::x2.getJavaTypeOfResult())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt b/compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt
new file mode 100644
index 0000000..e903677
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt
@@ -0,0 +1,90 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+import kotlin.reflect.jvm.*
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+@JvmInline
+value class Z1(val publicX1: UInt, val publicX2: Int) {
+    companion object {
+        val publicX1Ref = Z1::publicX1
+        val publicX2Ref = Z1::publicX2
+        val publicX1BoundRef = Z1(42U, -42)::publicX1
+        val publicX2BoundRef = Z1(42U, -42)::publicX2
+    }
+}
+
+@JvmInline
+value class Z2(internal val internalX1: UInt, internal val internalX2: Int) {
+    companion object {
+        val internalX1Ref = Z2::internalX1
+        val internalX2Ref = Z2::internalX2
+        val internalX1BoundRef = Z2(42U, -42)::internalX1
+        val internalX2BoundRef = Z2(42U, -42)::internalX2
+    }
+}
+
+@JvmInline
+value class Z3(private val privateX1: UInt, private val privateX2: Int) {
+    companion object {
+        val privateX1Ref = Z3::privateX1
+        val privateX2Ref = Z3::privateX2
+        val privateX1BoundRef = Z3(42U, -42)::privateX1
+        val privateX2BoundRef = Z3(42U, -42)::privateX2
+    }
+}
+@JvmInline
+value class Z1_2(val publicX: Z1) {
+    companion object {
+        val publicXRef = Z1_2::publicX
+        val publicXBoundRef = Z1_2(Z1(42U, -42))::publicX
+    }
+}
+
+@JvmInline
+value class Z2_2(internal val internalX: Z2) {
+    companion object {
+        val internalXRef = Z2_2::internalX
+        val internalXBoundRef = Z2_2(Z2(42U, -42))::internalX
+    }
+}
+
+@JvmInline
+value class Z3_2(private val privateX: Z3) {
+    companion object {
+        val privateXRef = Z3_2::privateX
+        val privateXBoundRef = Z3_2(Z3(42U, -42))::privateX
+    }
+}
+
+fun box(): String {
+    val suffix = "-pVg5ArA"
+    assertEquals("getPublicX1$suffix", Z1.publicX1Ref.javaGetter!!.name)
+    assertEquals("getPublicX2", Z1.publicX2Ref.javaGetter!!.name)
+    assertEquals("getPublicX1$suffix", Z1.publicX1BoundRef.javaGetter!!.name)
+    assertEquals("getPublicX2", Z1.publicX2BoundRef.javaGetter!!.name)
+
+    assertTrue(Z2.internalX1Ref.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1Ref.javaGetter!!.name)
+    assertTrue(Z2.internalX2Ref.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2Ref.javaGetter!!.name)
+    assertTrue(Z2.internalX1BoundRef.javaGetter!!.name.startsWith("getInternalX1$suffix\$"), Z2.internalX1BoundRef.javaGetter!!.name)
+    assertTrue(Z2.internalX2BoundRef.javaGetter!!.name.startsWith("getInternalX2\$"), Z2.internalX2BoundRef.javaGetter!!.name)
+
+    assertEquals(null, Z3.privateX1Ref.javaGetter)
+    assertEquals(null, Z3.privateX2Ref.javaGetter)
+    assertEquals(null, Z3.privateX1BoundRef.javaGetter)
+    assertEquals(null, Z3.privateX2BoundRef.javaGetter)
+    
+    
+    assertEquals("getPublicX", Z1_2.publicXRef.javaGetter!!.name)
+    assertEquals("getPublicX", Z1_2.publicXBoundRef.javaGetter!!.name)
+
+    assertTrue(Z2_2.internalXRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXRef.javaGetter!!.name)
+    assertTrue(Z2_2.internalXBoundRef.javaGetter!!.name.startsWith("getInternalX\$"), Z2_2.internalXBoundRef.javaGetter!!.name)
+
+    assertEquals("getPrivateX", Z3_2.privateXRef.javaGetter!!.name)
+    assertEquals("getPrivateX", Z3_2.privateXBoundRef.javaGetter!!.name)
+
+    return "OK"
+}
\ No newline at end of file
diff --git a/compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt b/compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt
new file mode 100644
index 0000000..293076a
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt
@@ -0,0 +1,49 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+package test
+
+import kotlin.reflect.*
+import kotlin.reflect.jvm.*
+import kotlin.test.assertEquals
+import kotlin.test.assertTrue
+
+@JvmInline
+value class Z(val value1: UInt, val value2: String)
+
+class S {
+    suspend fun consumeZ(z: Z) {}
+    suspend fun produceZ(): Z = Z(0U, "")
+    suspend fun consumeAndProduceZ(z: Z): Z = z
+}
+
+fun box(): String {
+    val members = S::class.members.filterIsInstance<KFunction<*>>().associateBy(KFunction<*>::name)
+
+    members["consumeZ"]!!.let { cz ->
+        val czj = cz.javaMethod!!
+        assertTrue(czj.name.startsWith("consumeZ-"), czj.name)
+        assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", czj.parameterTypes.joinToString { it.name })
+        val czjk = czj.kotlinFunction
+        assertEquals(cz, czjk)
+    }
+
+    members["produceZ"]!!.let { pz ->
+        val pzj = pz.javaMethod!!
+        assertEquals("produceZ", pzj.name)
+        assertEquals("kotlin.coroutines.Continuation", pzj.parameterTypes.joinToString { it.name })
+        val pzjk = pzj!!.kotlinFunction
+        assertEquals(pz, pzjk)
+    }
+
+    members["consumeAndProduceZ"]!!.let { cpz ->
+        val cpzj = cpz.javaMethod!!
+        assertTrue(cpzj.name.startsWith("consumeAndProduceZ-"), cpzj.name)
+        assertEquals("int, java.lang.String, kotlin.coroutines.Continuation", cpzj.parameterTypes.joinToString { it.name })
+        val cpzjk = cpzj!!.kotlinFunction
+        assertEquals(cpz, cpzjk)
+    }
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/modifiers/mfvc.kt b/compiler/testData/codegen/box/reflection/modifiers/mfvc.kt
new file mode 100644
index 0000000..77aae13
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/modifiers/mfvc.kt
@@ -0,0 +1,20 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+// FILE: box.kt
+
+import kotlin.test.assertTrue
+import kotlin.test.assertFalse
+@JvmInline
+value class V(val value: String, val value1: String)
+
+fun box(): String {
+    assertFalse(V::class.isSealed)
+    assertFalse(V::class.isData)
+    assertFalse(V::class.isInner)
+    assertFalse(V::class.isCompanion)
+    assertFalse(V::class.isFun)
+    assertTrue(V::class.isValue)
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/typeOf/mfvc.kt b/compiler/testData/codegen/box/reflection/typeOf/mfvc.kt
new file mode 100644
index 0000000..e58b179
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/mfvc.kt
@@ -0,0 +1,25 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_REFLECT
+// LANGUAGE: +ValueClasses
+
+package test
+
+import kotlin.reflect.KType
+import kotlin.reflect.typeOf
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val value1: String, val value2: String)
+
+fun check(expected: String, actual: KType) {
+    assertEquals(expected, actual.toString())
+}
+
+fun box(): String {
+    check("test.Z", typeOf<Z>())
+    check("test.Z?", typeOf<Z?>())
+    check("kotlin.Array<test.Z>", typeOf<Array<Z>>())
+    check("kotlin.Array<test.Z?>", typeOf<Array<Z?>>())
+
+    return "OK"
+}
diff --git a/compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt
new file mode 100644
index 0000000..3fcf991
--- /dev/null
+++ b/compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt
@@ -0,0 +1,25 @@
+// TARGET_BACKEND: JVM_IR
+// WITH_STDLIB
+// LANGUAGE: +ValueClasses
+
+package test
+
+import kotlin.reflect.KType
+import kotlin.reflect.typeOf
+import kotlin.test.assertEquals
+
+@JvmInline
+value class Z(val value1: String, val value2: String)
+
+fun check(expected: String, actual: KType) {
+    assertEquals(expected + " (Kotlin reflection is not available)", actual.toString())
+}
+
+fun box(): String {
+    check("test.Z", typeOf<Z>())
+    check("test.Z?", typeOf<Z?>())
+    check("kotlin.Array<test.Z>", typeOf<Array<Z>>())
+    check("kotlin.Array<test.Z?>", typeOf<Array<Z?>>())
+
+    return "OK"
+}
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
index 800237d..f7b3397 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java
@@ -41385,6 +41385,16 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+                }
+            }
         }
 
         @Nested
@@ -42739,6 +42749,16 @@
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+                }
+            }
         }
 
         @Nested
diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
index 08b2222..59ed627 100644
--- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
+++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java
@@ -43521,6 +43521,100 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("constructorWithMfvcParameters.kt")
+                public void testConstructorWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/constructorWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("fieldAccessors.kt")
+                public void testFieldAccessors() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/fieldAccessors.kt");
+                }
+
+                @Test
+                @TestMetadata("functionsWithMfvcParameters.kt")
+                public void testFunctionsWithMfvcParameters() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/functionsWithMfvcParameters.kt");
+                }
+
+                @Test
+                @TestMetadata("internalPrimaryValOfMfvc.kt")
+                public void testInternalPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/internalPrimaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFieldInObject.kt")
+                public void testJvmStaticFieldInObject() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFieldInObject.kt");
+                }
+
+                @Test
+                @TestMetadata("jvmStaticFunction.kt")
+                public void testJvmStaticFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/jvmStaticFunction.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcConstructor.kt")
+                public void testMfvcConstructor() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/mfvcConstructor.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingFunOfMfvc.kt")
+                public void testNonOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("nonOverridingVarOfMfvc.kt")
+                public void testNonOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/nonOverridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingFunOfMfvc.kt")
+                public void testOverridingFunOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingFunOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("overridingVarOfMfvc.kt")
+                public void testOverridingVarOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/overridingVarOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("primaryValOfMfvc.kt")
+                public void testPrimaryValOfMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/primaryValOfMfvc.kt");
+                }
+
+                @Test
+                @TestMetadata("properties.kt")
+                public void testProperties() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/properties.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunction.kt")
+                public void testSuspendFunction() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/call/valueClasses/suspendFunction.kt");
+                }
+            }
         }
 
         @Nested
@@ -43641,6 +43735,24 @@
             }
 
             @Test
+            @TestMetadata("mfvcDefaultArguments.kt")
+            public void testMfvcDefaultArguments() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcDefaultArguments.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcFunctionsAndConstructors.kt")
+            public void testMfvcFunctionsAndConstructors() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcFunctionsAndConstructors.kt");
+            }
+
+            @Test
+            @TestMetadata("mfvcMembers.kt")
+            public void testMfvcMembers() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/callBy/mfvcMembers.kt");
+            }
+
+            @Test
             @TestMetadata("nonDefaultParameterOmitted.kt")
             public void testNonDefaultParameterOmitted() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/callBy/nonDefaultParameterOmitted.kt");
@@ -44485,6 +44597,12 @@
             }
 
             @Test
+            @TestMetadata("reflectOnDefaultWithMfvcArgument.kt")
+            public void testReflectOnDefaultWithMfvcArgument() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnDefaultWithMfvcArgument.kt");
+            }
+
+            @Test
             @TestMetadata("reflectOnLambdaInArrayConstructor.kt")
             public void testReflectOnLambdaInArrayConstructor() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/lambdaClasses/reflectOnLambdaInArrayConstructor.kt");
@@ -44555,6 +44673,12 @@
             }
 
             @Test
+            @TestMetadata("constructorWithMfvcParameters.kt")
+            public void testConstructorWithMfvcParameters() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/mapping/constructorWithMfvcParameters.kt");
+            }
+
+            @Test
             @TestMetadata("extensionProperty.kt")
             public void testExtensionProperty() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/mapping/extensionProperty.kt");
@@ -44816,6 +44940,18 @@
                 }
 
                 @Test
+                @TestMetadata("mfvcInSignature.kt")
+                public void testMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcInSignature.kt");
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/types/mfvcPrimaryVal.kt");
+                }
+
+                @Test
                 @TestMetadata("overrideAnyWithPrimitive.kt")
                 public void testOverrideAnyWithPrimitive() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/overrideAnyWithPrimitive.kt");
@@ -44881,6 +45017,28 @@
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
+                }
+
+                @Test
+                @TestMetadata("mfvcPrimaryVal.kt")
+                public void testMfvcPrimaryVal() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/mfvcPrimaryVal.kt");
+                }
+
+                @Test
+                @TestMetadata("suspendFunctionWithMfvcInSignature.kt")
+                public void testSuspendFunctionWithMfvcInSignature() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/mapping/valueClasses/suspendFunctionWithMfvcInSignature.kt");
+                }
+            }
         }
 
         @Nested
@@ -45095,6 +45253,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/modifiers/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("properties.kt")
             public void testProperties() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/modifiers/properties.kt");
@@ -45905,6 +46069,12 @@
             }
 
             @Test
+            @TestMetadata("mfvc.kt")
+            public void testMfvc() throws Exception {
+                runTest("compiler/testData/codegen/box/reflection/typeOf/mfvc.kt");
+            }
+
+            @Test
             @TestMetadata("multipleLayers.kt")
             public void testMultipleLayers() throws Exception {
                 runTest("compiler/testData/codegen/box/reflection/typeOf/multipleLayers.kt");
@@ -46014,6 +46184,12 @@
                 }
 
                 @Test
+                @TestMetadata("mfvc.kt")
+                public void testMfvc() throws Exception {
+                    runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mfvc.kt");
+                }
+
+                @Test
                 @TestMetadata("mutableCollections_after.kt")
                 public void testMutableCollections_after() throws Exception {
                     runTest("compiler/testData/codegen/box/reflection/typeOf/noReflect/mutableCollections_after.kt");
diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
index 20ebb55..f7ace6d 100644
--- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
+++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java
@@ -33110,6 +33110,19 @@
                     }
                 }
             }
+
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            @RunWith(JUnit3RunnerWithInners.class)
+            public static class ValueClasses extends AbstractLightAnalysisModeTest {
+                private void runTest(String testDataFilePath) throws Exception {
+                    KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
+                }
+
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+                }
+            }
         }
 
         @TestMetadata("compiler/testData/codegen/box/reflection/callBy")
@@ -34313,6 +34326,19 @@
                     runTest("compiler/testData/codegen/box/reflection/mapping/types/withNullability.kt");
                 }
             }
+
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            @RunWith(JUnit3RunnerWithInners.class)
+            public static class ValueClasses extends AbstractLightAnalysisModeTest {
+                private void runTest(String testDataFilePath) throws Exception {
+                    KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
+                }
+
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
+                }
+            }
         }
 
         @TestMetadata("compiler/testData/codegen/box/reflection/methodsFromAny")
diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/inlineClassesUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/inlineClassesUtils.kt
index 40ca3fe..ef0baa2 100644
--- a/core/descriptors/src/org/jetbrains/kotlin/resolve/inlineClassesUtils.kt
+++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/inlineClassesUtils.kt
@@ -9,6 +9,7 @@
 import org.jetbrains.kotlin.name.ClassId
 import org.jetbrains.kotlin.name.FqName
 import org.jetbrains.kotlin.resolve.descriptorUtil.inlineClassRepresentation
+import org.jetbrains.kotlin.resolve.descriptorUtil.multiFieldValueClassRepresentation
 import org.jetbrains.kotlin.types.KotlinType
 import org.jetbrains.kotlin.types.TypeSubstitutor
 import org.jetbrains.kotlin.types.TypeUtils
@@ -42,6 +43,8 @@
 
 
 fun KotlinType.isInlineClassType(): Boolean = constructor.declarationDescriptor?.isInlineClass() ?: false
+fun KotlinType.isMultiFieldValueClassType(): Boolean = constructor.declarationDescriptor?.isMultiFieldValueClass() ?: false
+fun KotlinType.isValueClassType(): Boolean = constructor.declarationDescriptor?.isValueClass() ?: false
 
 fun KotlinType.needsMfvcFlattening(): Boolean =
     constructor.declarationDescriptor?.run { isMultiFieldValueClass() && !isNullableType() } == true
@@ -77,6 +80,20 @@
 fun CallableDescriptor.isGetterOfUnderlyingPropertyOfInlineClass() =
     this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfInlineClass()
 
+fun CallableDescriptor.isGetterOfUnderlyingPropertyOfMultiFieldValueClass() =
+    this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfMultiFieldValueClass()
+
+fun CallableDescriptor.isGetterOfUnderlyingPropertyOfValueClass() =
+    this is PropertyGetterDescriptor && correspondingProperty.isUnderlyingPropertyOfValueClass()
+
 fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean =
     extensionReceiverParameter == null &&
             (containingDeclaration as? ClassDescriptor)?.inlineClassRepresentation?.underlyingPropertyName == this.name
+
+fun VariableDescriptor.isUnderlyingPropertyOfMultiFieldValueClass(): Boolean =
+    extensionReceiverParameter == null &&
+            (containingDeclaration as? ClassDescriptor)?.multiFieldValueClassRepresentation?.containsPropertyWithName(this.name) == true
+
+fun VariableDescriptor.isUnderlyingPropertyOfValueClass(): Boolean =
+    extensionReceiverParameter == null &&
+            (containingDeclaration as? ClassDescriptor)?.valueClassRepresentation?.containsPropertyWithName(this.name) == true
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt
index 9763c6f..a6162dc 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KCallableImpl.kt
@@ -8,13 +8,14 @@
 import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
 import org.jetbrains.kotlin.descriptors.Modality
 import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
+import org.jetbrains.kotlin.types.asSimpleType
 import java.lang.reflect.ParameterizedType
 import java.lang.reflect.Type
 import java.lang.reflect.WildcardType
-import java.util.*
 import kotlin.coroutines.Continuation
 import kotlin.reflect.*
 import kotlin.reflect.jvm.internal.calls.Caller
+import kotlin.reflect.jvm.internal.calls.getMfvcUnboxMethods
 import kotlin.reflect.jvm.javaType
 import kotlin.reflect.jvm.jvmErasure
 import java.lang.reflect.Array as ReflectArray
@@ -113,7 +114,9 @@
 
     private val _absentArguments = ReflectProperties.lazySoft {
         val parameterSize = parameters.size + (if (isSuspend) 1 else 0)
-        val maskSize = (parameters.size + Integer.SIZE - 1) / Integer.SIZE
+        val flattenedParametersSize =
+            if (parametersNeedMFVCFlattening.value) parameters.sumOf { getParameterTypeSize(it) } else parameters.size
+        val maskSize = (flattenedParametersSize + Integer.SIZE - 1) / Integer.SIZE
 
         // Array containing the actual function arguments, masks, and +1 for DefaultConstructorMarker or MethodHandle.
         val arguments = arrayOfNulls<Any?>(parameterSize + maskSize + 1)
@@ -161,14 +164,23 @@
         var valueParameterIndex = 0
         var anyOptional = false
 
+        val hasMfvcParameters = parametersNeedMFVCFlattening.value
         for (parameter in parameters) {
+            val parameterTypeSize = if (hasMfvcParameters) getParameterTypeSize(parameter) else 1
             when {
                 args.containsKey(parameter) -> {
                     arguments[parameter.index] = args[parameter]
                 }
                 parameter.isOptional -> {
-                    val maskIndex = parameterSize + (valueParameterIndex / Integer.SIZE)
-                    arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueParameterIndex % Integer.SIZE))
+                    if (hasMfvcParameters) {
+                        for (valueSubParameterIndex in valueParameterIndex until (valueParameterIndex + parameterTypeSize)) {
+                            val maskIndex = parameterSize + (valueSubParameterIndex / Integer.SIZE)
+                            arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueSubParameterIndex % Integer.SIZE))
+                        }
+                    } else {
+                        val maskIndex = parameterSize + (valueParameterIndex / Integer.SIZE)
+                        arguments[maskIndex] = (arguments[maskIndex] as Int) or (1 shl (valueParameterIndex % Integer.SIZE))
+                    }
                     anyOptional = true
                 }
                 parameter.isVararg -> {}
@@ -178,7 +190,7 @@
             }
 
             if (parameter.kind == KParameter.Kind.VALUE) {
-                valueParameterIndex++
+                valueParameterIndex += parameterTypeSize
             }
         }
 
@@ -197,6 +209,20 @@
         }
     }
 
+    private val parametersNeedMFVCFlattening = lazy(LazyThreadSafetyMode.PUBLICATION) {
+        parameters.any { it.type.needsMultiFieldValueClassFlattening }
+    }
+
+    private fun getParameterTypeSize(parameter: KParameter): Int {
+        require(parametersNeedMFVCFlattening.value) { "Check if parametersNeedMFVCFlattening is true before" }
+        return if (parameter.type.needsMultiFieldValueClassFlattening) {
+            val type = (parameter.type as KTypeImpl).type.asSimpleType()
+            getMfvcUnboxMethods(type)!!.size
+        } else {
+            1
+        }
+    }
+
     private fun callAnnotationConstructor(args: Map<KParameter, Any?>): R {
         val arguments = parameters.map { parameter ->
             when {
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt
index d4e7739..7064a14 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KDeclarationContainerImpl.kt
@@ -24,10 +24,12 @@
 import org.jetbrains.kotlin.load.java.JvmAbi
 import org.jetbrains.kotlin.name.Name
 import org.jetbrains.kotlin.renderer.DescriptorRenderer
+import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
 import org.jetbrains.kotlin.resolve.scopes.MemberScope
 import java.lang.reflect.Constructor
 import java.lang.reflect.Method
 import kotlin.jvm.internal.ClassBasedDeclarationContainer
+import kotlin.reflect.jvm.internal.calls.toJvmDescriptor
 
 internal abstract class KDeclarationContainerImpl : ClassBasedDeclarationContainer {
     abstract inner class Data {
@@ -119,9 +121,25 @@
     }
 
     fun findFunctionDescriptor(name: String, signature: String): FunctionDescriptor {
-        val members = if (name == "<init>") constructorDescriptors.toList() else getFunctions(Name.identifier(name))
-        val functions = members.filter { descriptor ->
-            RuntimeTypeMapper.mapSignature(descriptor).asString() == signature
+        val members: Collection<FunctionDescriptor>
+        val functions: List<FunctionDescriptor>
+        if (name == "<init>") {
+            members = constructorDescriptors.toList()
+            functions = members.filter { descriptor ->
+                val descriptorSignature = if (descriptor.isPrimary && descriptor.containingDeclaration.isMultiFieldValueClass()) {
+                    val initial = RuntimeTypeMapper.mapSignature(descriptor).asString()
+                    require(initial.startsWith("constructor-impl") && initial.endsWith(")V")) {
+                        "Invalid signature of $descriptor: $initial"
+                    }
+                    initial.removeSuffix("V") + descriptor.containingDeclaration.toJvmDescriptor()
+                } else {
+                    RuntimeTypeMapper.mapSignature(descriptor).asString()
+                }
+                descriptorSignature == signature
+            }
+        } else {
+            members = getFunctions(Name.identifier(name))
+            functions = members.filter { descriptor -> RuntimeTypeMapper.mapSignature(descriptor).asString() == signature }
         }
 
         if (functions.size != 1) {
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt
index dce795c..0d2ee46 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KFunctionImpl.kt
@@ -17,8 +17,10 @@
 package kotlin.reflect.jvm.internal
 
 import org.jetbrains.kotlin.descriptors.ClassDescriptor
+import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
 import org.jetbrains.kotlin.descriptors.FunctionDescriptor
-import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToInlineClassTypeValueParameters
+import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
+import org.jetbrains.kotlin.resolve.jvm.shouldHideConstructorDueToValueClassTypeValueParameters
 import java.lang.reflect.Constructor
 import java.lang.reflect.Member
 import java.lang.reflect.Method
@@ -66,7 +68,14 @@
                     return@caller AnnotationConstructorCaller(container.jClass, parameters.map { it.name!! }, POSITIONAL_CALL, KOTLIN)
                 container.findConstructorBySignature(jvmSignature.constructorDesc)
             }
-            is KotlinFunction -> container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc)
+            is KotlinFunction -> {
+                if (descriptor.let { it.containingDeclaration.isMultiFieldValueClass() && it is ConstructorDescriptor && it.isPrimary }) {
+                    return@caller ValueClassAwareCaller.MultiFieldValueClassPrimaryConstructorCaller(
+                        descriptor, container, jvmSignature.methodDesc, descriptor.valueParameters
+                    )
+                }
+                container.findMethodBySignature(jvmSignature.methodName, jvmSignature.methodDesc)
+            }
             is JavaMethod -> jvmSignature.method
             is JavaConstructor -> jvmSignature.constructor
             is FakeJavaAnnotationConstructor -> {
@@ -87,13 +96,16 @@
                     createStaticMethodCaller(member)
             }
             else -> throw KotlinReflectionInternalError("Could not compute caller for function: $descriptor (member = $member)")
-        }.createInlineClassAwareCallerIfNeeded(descriptor)
+        }.createValueClassAwareCallerIfNeeded(descriptor)
     }
 
     override val defaultCaller: Caller<*>? by lazy(PUBLICATION) defaultCaller@{
         val jvmSignature = RuntimeTypeMapper.mapSignature(descriptor)
         val member: Member? = when (jvmSignature) {
             is KotlinFunction -> {
+                if (descriptor.let { it.containingDeclaration.isMultiFieldValueClass() && it is ConstructorDescriptor && it.isPrimary }) {
+                    throw KotlinReflectionInternalError("${descriptor.containingDeclaration} cannot have default arguments")
+                }
                 container.findDefaultMethod(jvmSignature.methodName, jvmSignature.methodDesc, !Modifier.isStatic(caller.member!!.modifiers))
             }
             is KotlinConstructor -> {
@@ -126,7 +138,7 @@
                     createStaticMethodCaller(member)
             }
             else -> null
-        }?.createInlineClassAwareCallerIfNeeded(descriptor, isDefault = true)
+        }?.createValueClassAwareCallerIfNeeded(descriptor, isDefault = true)
     }
 
     private val boundReceiver
@@ -144,7 +156,7 @@
     private fun createConstructorCaller(
         member: Constructor<*>, descriptor: FunctionDescriptor, isDefault: Boolean
     ): CallerImpl<Constructor<*>> {
-        return if (!isDefault && shouldHideConstructorDueToInlineClassTypeValueParameters(descriptor)) {
+        return if (!isDefault && shouldHideConstructorDueToValueClassTypeValueParameters(descriptor)) {
             if (isBound)
                 CallerImpl.AccessorForHiddenBoundConstructor(member, boundReceiver)
             else
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt
index 7906172..b6319c3 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KParameterImpl.kt
@@ -18,8 +18,10 @@
 
 import org.jetbrains.kotlin.descriptors.*
 import org.jetbrains.kotlin.resolve.descriptorUtil.declaresOrInheritsDefaultValue
+import java.lang.reflect.Type
 import kotlin.reflect.KParameter
 import kotlin.reflect.KType
+import kotlin.reflect.jvm.internal.calls.ValueClassAwareCaller
 
 internal class KParameterImpl(
     val callable: KCallableImpl<*>,
@@ -39,6 +41,27 @@
             return if (name.isSpecial) null else name.asString()
         }
 
+
+    private fun compoundType(vararg types: Type): Type = when (types.size) {
+        0 -> throw KotlinReflectionNotSupportedError("Expected at least 1 type for compound type")
+        1 -> types.single()
+        else -> CompoundTypeImpl(types)
+    }
+
+    private class CompoundTypeImpl(val types: Array<out Type>) : Type {
+        private val hashCode = types.contentHashCode()
+        override fun getTypeName(): String {
+            return types.joinToString(", ", "[", "]")
+        }
+
+        override fun equals(other: Any?): Boolean =
+            other is CompoundTypeImpl && this.types contentEquals other.types
+
+        override fun hashCode(): Int = hashCode
+
+        override fun toString(): String = typeName
+    }
+
     override val type: KType
         get() = KTypeImpl(descriptor.type) {
             val descriptor = descriptor
@@ -53,7 +76,16 @@
                 (callable.descriptor.containingDeclaration as ClassDescriptor).toJavaClass()
                     ?: throw KotlinReflectionInternalError("Cannot determine receiver Java type of inherited declaration: $descriptor")
             } else {
-                callable.caller.parameterTypes[index]
+                when (val caller = callable.caller) {
+                    is ValueClassAwareCaller -> {
+                        val slice = caller.getRealSlicesOfParameters(index)
+                        val parameterTypes = caller.parameterTypes.slice(slice)
+                        compoundType(*parameterTypes.toTypedArray())
+                    }
+                    is ValueClassAwareCaller.MultiFieldValueClassPrimaryConstructorCaller ->
+                        compoundType(*caller.originalParametersGroups[index].toTypedArray())
+                    else -> caller.parameterTypes[index]
+                }
             }
         }
 
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt
index eeaa98d..fa9596a 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/KPropertyImpl.kt
@@ -271,8 +271,9 @@
                     if (property.descriptor.isUnderlyingPropertyOfInlineClass() &&
                         property.descriptor.visibility == DescriptorVisibilities.INTERNAL
                     ) {
-                        val unboxMethod = property.descriptor.containingDeclaration.toInlineClass()?.getUnboxMethod(property.descriptor)
-                            ?: throw KotlinReflectionInternalError("Underlying property of inline class $property should have a field")
+                        val unboxMethod =
+                            property.descriptor.containingDeclaration.toInlineClass()?.getInlineClassUnboxMethod(property.descriptor)
+                                ?: throw KotlinReflectionInternalError("Underlying property of inline class $property should have a field")
                         if (isBound) InternalUnderlyingValOfInlineClass.Bound(unboxMethod, boundReceiver)
                         else InternalUnderlyingValOfInlineClass.Unbound(unboxMethod)
                     } else {
@@ -316,7 +317,7 @@
             return if (isBound) CallerImpl.Method.BoundInstance(accessor, boundReceiver)
             else CallerImpl.Method.Instance(accessor)
         }
-    }.createInlineClassAwareCallerIfNeeded(descriptor)
+    }.createValueClassAwareCallerIfNeeded(descriptor)
 }
 
 private fun PropertyDescriptor.isJvmFieldPropertyInCompanionObject(): Boolean {
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt
index 5d64815..8d117df 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/RuntimeTypeMapper.kt
@@ -44,6 +44,7 @@
 import org.jetbrains.kotlin.resolve.DescriptorUtils
 import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor
 import org.jetbrains.kotlin.resolve.isInlineClass
+import org.jetbrains.kotlin.resolve.isMultiFieldValueClass
 import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
 import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
@@ -51,6 +52,7 @@
 import java.lang.reflect.Constructor
 import java.lang.reflect.Field
 import java.lang.reflect.Method
+import kotlin.reflect.jvm.internal.calls.toJvmDescriptor
 
 internal sealed class JvmFunctionSignature {
     abstract fun asString(): String
@@ -174,10 +176,27 @@
                 }
                 if (proto is ProtoBuf.Constructor) {
                     JvmProtoBufUtil.getJvmConstructorSignature(proto, function.nameResolver, function.typeTable)?.let { signature ->
-                        return if (possiblySubstitutedFunction.containingDeclaration.isInlineClass())
-                            JvmFunctionSignature.KotlinFunction(signature)
-                        else
-                            JvmFunctionSignature.KotlinConstructor(signature)
+                        return when {
+                            possiblySubstitutedFunction.containingDeclaration.isInlineClass() ->
+                                JvmFunctionSignature.KotlinFunction(signature)
+                            possiblySubstitutedFunction.containingDeclaration.isMultiFieldValueClass() -> {
+                                val realSignature = if ((possiblySubstitutedFunction as ConstructorDescriptor).isPrimary) {
+                                    require(signature.name == "constructor-impl" && signature.desc.endsWith(")V")) { "Invalid signature: $signature" }
+                                    signature
+                                } else {
+                                    require(signature.name == "constructor-impl") { "Invalid signature: $signature" }
+                                    val constructedClass = possiblySubstitutedFunction.constructedClass.toJvmDescriptor()
+                                    if (signature.desc.endsWith(")V")) {
+                                        signature.copy(desc = signature.desc.removeSuffix("V") + constructedClass)
+                                    } else {
+                                        require(signature.desc.endsWith(constructedClass)) { "Invalid signature: $signature" }
+                                        signature
+                                    }
+                                }
+                                JvmFunctionSignature.KotlinFunction(realSignature)
+                            }
+                            else -> JvmFunctionSignature.KotlinConstructor(signature)
+                        }
                     }
                 }
                 return mapJvmFunctionSignature(function)
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/CallerImpl.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/CallerImpl.kt
index 6665636..7b52532 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/CallerImpl.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/CallerImpl.kt
@@ -122,7 +122,7 @@
             }
         }
 
-        class BoundStatic(method: ReflectMethod, private val boundReceiver: Any?) : BoundCaller, Method(
+        class BoundStatic(method: ReflectMethod, internal val boundReceiver: Any?) : BoundCaller, Method(
             method, requiresInstance = false, parameterTypes = method.genericParameterTypes.dropFirst()
         ) {
             override fun call(args: Array<*>): Any? {
@@ -131,6 +131,21 @@
             }
         }
 
+        class BoundStaticMultiFieldValueClass(
+            method: ReflectMethod, internal val boundReceiverComponents: Array<Any?>
+        ) : BoundCaller, Method(
+            method = method,
+            requiresInstance = false,
+            parameterTypes = method.genericParameterTypes.drop(boundReceiverComponents.size).toTypedArray()
+        ) {
+            override fun call(args: Array<*>): Any? {
+                checkArguments(args)
+                return callMethod(null, arrayOf(*boundReceiverComponents, *args))
+            }
+
+            val receiverComponentsCount: Int get() = boundReceiverComponents.size
+        }
+
         class BoundInstance(method: ReflectMethod, private val boundReceiver: Any?) : BoundCaller,
             Method(method, requiresInstance = false) {
             override fun call(args: Array<*>): Any? {
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt
index dd3540a..feacd27 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/calls/ValueClassAwareCaller.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
  * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
  */
 
@@ -7,29 +7,50 @@
 
 import org.jetbrains.kotlin.builtins.KotlinBuiltIns
 import org.jetbrains.kotlin.descriptors.*
+import org.jetbrains.kotlin.descriptors.runtime.structure.desc
 import org.jetbrains.kotlin.load.java.JvmAbi
+import org.jetbrains.kotlin.metadata.jvm.deserialization.ClassMapperLite
 import org.jetbrains.kotlin.resolve.*
 import org.jetbrains.kotlin.resolve.descriptorUtil.classId
+import org.jetbrains.kotlin.resolve.descriptorUtil.multiFieldValueClassRepresentation
 import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.SimpleType
 import org.jetbrains.kotlin.types.TypeUtils
+import org.jetbrains.kotlin.types.asSimpleType
 import java.lang.reflect.Member
 import java.lang.reflect.Method
 import java.lang.reflect.Type
+import kotlin.reflect.jvm.internal.KDeclarationContainerImpl
 import kotlin.reflect.jvm.internal.KotlinReflectionInternalError
 import kotlin.reflect.jvm.internal.defaultPrimitiveValue
 import kotlin.reflect.jvm.internal.toJavaClass
 
 /**
- * A caller that is used whenever the declaration has inline classes in its parameter types or return type.
- * Each argument of an inline class type is unboxed, and the return value (if it's of an inline class type) is boxed.
+ * A caller that is used whenever the declaration has value classes in its parameter types or inline class in return type.
+ * Each argument of an value class type is unboxed, and the return value (if it's of an inline class type) is boxed.
  */
-internal class InlineClassAwareCaller<out M : Member?>(
+internal class ValueClassAwareCaller<out M : Member?>(
     descriptor: CallableMemberDescriptor,
-    private val caller: Caller<M>,
+    oldCaller: Caller<M>,
     private val isDefault: Boolean
 ) : Caller<M> {
-    override val member: M
-        get() = caller.member
+
+    private val caller: Caller<M> = if (oldCaller is CallerImpl.Method.BoundStatic) {
+        val receiverType = (descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter)?.type
+        if (receiverType != null && receiverType.needsMfvcFlattening()) {
+            val unboxMethods = getMfvcUnboxMethods(receiverType.asSimpleType())!!
+            val boundReceiverComponents = unboxMethods.map { it.invoke(oldCaller.boundReceiver) }.toTypedArray()
+            @Suppress("UNCHECKED_CAST")
+            CallerImpl.Method.BoundStaticMultiFieldValueClass(oldCaller.member, boundReceiverComponents) as Caller<M>
+        } else {
+            oldCaller
+        }
+    } else {
+        oldCaller
+    }
+
+    override val member: M = caller.member
+
 
     override val returnType: Type
         get() = caller.returnType
@@ -37,24 +58,18 @@
     override val parameterTypes: List<Type>
         get() = caller.parameterTypes
 
-    private class BoxUnboxData(val argumentRange: IntRange, val unbox: Array<Method?>, val box: Method?) {
-        operator fun component1(): IntRange = argumentRange
-        operator fun component2(): Array<Method?> = unbox
-        operator fun component3(): Method? = box
-    }
+    private class BoxUnboxData(val argumentRange: IntRange, val unboxParameters: Array<List<Method>?>, val box: Method?)
 
     private val data: BoxUnboxData = run {
         val box = descriptor.returnType!!.toInlineClass()?.getBoxMethod(descriptor)
-
-        if (descriptor.isGetterOfUnderlyingPropertyOfInlineClass()) {
-            // Getter of the underlying val of an inline class is always called on a boxed receiver,
-            // no argument boxing/unboxing is required.
-            // However, its result might require boxing if it is an inline class type.
+        if (descriptor.isGetterOfUnderlyingPropertyOfValueClass()) {
+            // Getter of the underlying val of a value class is always called on a boxed receiver,
+            // no argument unboxing is required.
             return@run BoxUnboxData(IntRange.EMPTY, emptyArray(), box)
         }
 
         val shift = when {
-            caller is CallerImpl.Method.BoundStatic -> {
+            caller is CallerImpl.Method.BoundStatic || caller is CallerImpl.Method.BoundStaticMultiFieldValueClass -> {
                 // Bound reference to a static method is only possible for a top level extension function/property,
                 // and in that case the number of expected arguments is one less than usual, hence -1
                 -1
@@ -64,9 +79,9 @@
                 if (caller is BoundCaller) -1 else 0
 
             descriptor.dispatchReceiverParameter != null && caller !is BoundCaller -> {
-                // If we have an unbound reference to the inline class member,
+                // If we have an unbound reference to the value class member,
                 // its receiver (which is passed as argument 0) should also be unboxed.
-                if (descriptor.containingDeclaration.isInlineClass())
+                if (descriptor.containingDeclaration.isValueClass())
                     0
                 else
                     1
@@ -75,117 +90,229 @@
             else -> 0
         }
 
-        val kotlinParameterTypes: List<KotlinType> = ArrayList<KotlinType>().also { kotlinParameterTypes ->
-            val extensionReceiverType = descriptor.extensionReceiverParameter?.type
-            if (extensionReceiverType != null) {
-                kotlinParameterTypes.add(extensionReceiverType)
-            } else if (descriptor is ConstructorDescriptor) {
-                val constructedClass = descriptor.constructedClass
-                if (constructedClass.isInner) {
-                    kotlinParameterTypes.add((constructedClass.containingDeclaration as ClassDescriptor).defaultType)
-                }
-            } else {
-                val containingDeclaration = descriptor.containingDeclaration
-                if (containingDeclaration is ClassDescriptor && containingDeclaration.isInlineClass()) {
-                    kotlinParameterTypes.add(containingDeclaration.defaultType)
-                }
-            }
+        val flattenedShift = if (caller is CallerImpl.Method.BoundStaticMultiFieldValueClass) -caller.receiverComponentsCount else shift
 
-            descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType)
-        }
+        val kotlinParameterTypes: List<KotlinType> = makeKotlinParameterTypes(descriptor) { isValueClass() }
+
+        fun typeSize(type: KotlinType): Int = getMfvcUnboxMethods(type.asSimpleType())?.size ?: 1
 
         // If the default argument is set,
-        // (kotlinParameterTypes.size + Integer.SIZE - 1) / Integer.SIZE masks and one marker are added to the end of the argument.
-        val extraArgumentsTail = (if (isDefault) ((kotlinParameterTypes.size + Integer.SIZE - 1) / Integer.SIZE) + 1 else 0) +
-                (if (descriptor is FunctionDescriptor && descriptor.isSuspend) 1 else 0)
-        val expectedArgsSize = kotlinParameterTypes.size + shift + extraArgumentsTail
-        if (arity != expectedArgsSize) {
-            throw KotlinReflectionInternalError(
-                "Inconsistent number of parameters in the descriptor and Java reflection object: $arity != $expectedArgsSize\n" +
-                        "Calling: $descriptor\n" +
-                        "Parameter types: ${this.parameterTypes})\n" +
-                        "Default: $isDefault"
-            )
-        }
+        // (kotlinParameterTypes.size + Int.SIZE_BITS - 1) / Int.SIZE_BITS masks and one marker are added to the end of the argument.
+        val extraArgumentsTail =
+            (if (isDefault) ((kotlinParameterTypes.sumOf(::typeSize) + Int.SIZE_BITS - 1) / Int.SIZE_BITS) + 1 else 0) +
+                    (if (descriptor is FunctionDescriptor && descriptor.isSuspend) 1 else 0)
+        val expectedArgsSize = kotlinParameterTypes.sumOf(::typeSize) + flattenedShift + extraArgumentsTail
+        checkParametersSize(expectedArgsSize, descriptor, isDefault)
 
         // maxOf is needed because in case of a bound top level extension, shift can be -1 (see above). But in that case, we need not unbox
         // the extension receiver argument, since it has already been unboxed at compile time and generated into the reference
         val argumentRange = maxOf(shift, 0) until (kotlinParameterTypes.size + shift)
 
         val unbox = Array(expectedArgsSize) { i ->
-            if (i in argumentRange) {
-                kotlinParameterTypes[i - shift].toInlineClass()?.getUnboxMethod(descriptor)
-            } else null
+            if (i in argumentRange)
+                getValueClassUnboxMethods(kotlinParameterTypes[i - shift].asSimpleType(), descriptor)
+            else null
         }
 
         BoxUnboxData(argumentRange, unbox, box)
     }
 
+    private val slices = buildList {
+        var currentOffset = when (caller) {
+            is CallerImpl.Method.BoundStaticMultiFieldValueClass -> caller.boundReceiverComponents.size
+            is CallerImpl.Method.BoundStatic -> 1
+            else -> 0
+        }
+        if (currentOffset > 0) {
+            add(0 until currentOffset)
+        }
+        for (parameterUnboxMethods in data.unboxParameters) {
+            val length = parameterUnboxMethods?.size ?: 1
+            add(currentOffset until (currentOffset + length))
+            currentOffset += length
+        }
+    }.toTypedArray()
+
+    fun getRealSlicesOfParameters(index: Int): IntRange = when {
+        index in slices.indices -> slices[index]
+        slices.isEmpty() -> index..index
+        else -> {
+            val start = (index - slices.size) + (slices.last().last + 1)
+            start..start
+        }
+    }
+
+    private val hasMfvcParameters = data.argumentRange.any { (data.unboxParameters[it] ?: return@any false).size > 1 }
+
     override fun call(args: Array<*>): Any? {
-        val (range, unbox, box) = data
+        val range = data.argumentRange
+        val unbox = data.unboxParameters
+        val box = data.box
 
-        @Suppress("UNCHECKED_CAST")
-        val unboxed = Array(args.size) { index ->
-            val arg = args[index]
-
-            if (index in range) {
-                // Note that arg may be null in case we're calling a $default method and it's an optional parameter of an inline class type
-                val method = unbox[index]
-
-                if (method != null) {
-                    if (arg != null) {
-                        method.invoke(arg)
+        val unboxedArguments = when {
+            range.isEmpty() -> args
+            hasMfvcParameters -> buildList(args.size) {
+                for (index in 0 until range.first) {
+                    add(args[index])
+                }
+                for (index in range) {
+                    val methods = unbox[index]
+                    val arg = args[index]
+                    // Note that arg may be null in case we're calling a $default method, and it's an optional parameter of a value class type
+                    if (methods != null) {
+                        methods.mapTo(this) { if (arg != null) it.invoke(arg) else defaultPrimitiveValue(it.returnType) }
                     } else {
-                        defaultPrimitiveValue(method.returnType)
+                        add(arg)
+                    }
+                }
+                for (index in (range.last + 1)..args.lastIndex) {
+                    add(args[index])
+                }
+            }.toTypedArray()
+            else -> Array(args.size) { index ->
+                if (index in range) {
+                    val method = unbox[index]?.single()
+                    val arg = args[index]
+                    // Note that arg may be null in case we're calling a $default method, and it's an optional parameter of a inline class type
+                    when {
+                        method == null -> arg
+                        arg != null -> method.invoke(arg)
+                        else -> defaultPrimitiveValue(method.returnType)
                     }
                 } else {
-                    arg
+                    args[index]
                 }
-            } else {
-                arg
             }
         }
 
-        val result = caller.call(unboxed)
+        val result = caller.call(unboxedArguments)
 
+        // box is not null only for inline classes
         return box?.invoke(null, result) ?: result
     }
+
+    class MultiFieldValueClassPrimaryConstructorCaller(
+        descriptor: FunctionDescriptor,
+        container: KDeclarationContainerImpl,
+        constructorDesc: String,
+        originalParameters: List<ParameterDescriptor>
+    ) : Caller<Nothing?> {
+        private val constructorImpl = container.findMethodBySignature("constructor-impl", constructorDesc)!!
+        private val boxMethod = container.findMethodBySignature("box-impl", constructorDesc.removeSuffix("V") + container.jClass.desc)!!
+        private val parameterUnboxMethods: List<List<Method>?> = originalParameters.map { parameter ->
+            getValueClassUnboxMethods(parameter.type.asSimpleType(), descriptor)
+        }
+        override val member: Nothing?
+            get() = null
+        override val returnType: Type
+            get() = boxMethod.returnType
+
+        val originalParametersGroups: List<List<Class<*>>> = originalParameters.mapIndexed { index, it ->
+            val classDescriptor = it.type.constructor.declarationDescriptor as ClassDescriptor
+            parameterUnboxMethods[index]?.map { it.returnType } ?: listOf(classDescriptor.toJavaClass()!!)
+        }
+
+        override val parameterTypes: List<Type> = originalParametersGroups.flatten()
+
+        override fun call(args: Array<*>): Any? {
+            val newArgs = (args zip parameterUnboxMethods)
+                .flatMap { (arg, unboxMethods) -> unboxMethods?.map { it.invoke(arg) } ?: listOf(arg) }.toTypedArray()
+            constructorImpl.invoke(null, *newArgs)
+            return boxMethod.invoke(null, *newArgs)
+        }
+    }
 }
 
-internal fun <M : Member?> Caller<M>.createInlineClassAwareCallerIfNeeded(
+internal fun ClassifierDescriptor.toJvmDescriptor(): String = ClassMapperLite.mapClass(classId!!.asString())
+
+
+private fun getValueClassUnboxMethods(type: SimpleType, descriptor: CallableMemberDescriptor): List<Method>? =
+    getMfvcUnboxMethods(type) ?: type.toInlineClass()?.getInlineClassUnboxMethod(descriptor)?.let(::listOf)
+
+internal fun getMfvcUnboxMethods(type: SimpleType): List<Method>? {
+    fun getUnboxMethodNameSuffixes(type: SimpleType): List<String>? =
+        if (type.needsMfvcFlattening()) (type.constructor.declarationDescriptor as ClassDescriptor)
+            .multiFieldValueClassRepresentation!!.underlyingPropertyNamesToTypes.flatMap { (name, innerType) ->
+                getUnboxMethodNameSuffixes(innerType)?.map { "${name.identifier}-${it}" } ?: listOf(name.identifier)
+            }
+        else null
+
+    val unboxMethodsNames = getUnboxMethodNameSuffixes(type.asSimpleType())?.map { "unbox-impl-$it" } ?: return null
+    val javaClass = (type.constructor.declarationDescriptor as ClassDescriptor).toJavaClass()!!
+    return unboxMethodsNames.map { javaClass.getDeclaredMethod(it) }
+}
+
+private fun Caller<*>.checkParametersSize(
+    expectedArgsSize: Int,
+    descriptor: CallableMemberDescriptor,
+    isDefault: Boolean,
+) {
+    if (arity != expectedArgsSize) {
+        throw KotlinReflectionInternalError(
+            "Inconsistent number of parameters in the descriptor and Java reflection object: $arity != $expectedArgsSize\n" +
+                    "Calling: $descriptor\n" +
+                    "Parameter types: ${this.parameterTypes})\n" +
+                    "Default: $isDefault"
+        )
+    }
+}
+
+private fun makeKotlinParameterTypes(
+    descriptor: CallableMemberDescriptor, isSpecificClass: ClassDescriptor.() -> Boolean
+): List<KotlinType> = ArrayList<KotlinType>().also { kotlinParameterTypes ->
+    val extensionReceiverType = descriptor.extensionReceiverParameter?.type
+    if (extensionReceiverType != null) {
+        kotlinParameterTypes.add(extensionReceiverType)
+    } else if (descriptor is ConstructorDescriptor) {
+        val constructedClass = descriptor.constructedClass
+        if (constructedClass.isInner) {
+            kotlinParameterTypes.add((constructedClass.containingDeclaration as ClassDescriptor).defaultType)
+        }
+    } else {
+        val containingDeclaration = descriptor.containingDeclaration
+        if (containingDeclaration is ClassDescriptor && containingDeclaration.isSpecificClass()) {
+            kotlinParameterTypes.add(containingDeclaration.defaultType)
+        }
+    }
+
+    descriptor.valueParameters.mapTo(kotlinParameterTypes, ValueParameterDescriptor::getType)
+}
+
+internal fun <M : Member?> Caller<M>.createValueClassAwareCallerIfNeeded(
     descriptor: CallableMemberDescriptor,
     isDefault: Boolean = false
 ): Caller<M> {
-    val needsInlineAwareCaller: Boolean =
-        descriptor.isGetterOfUnderlyingPropertyOfInlineClass() ||
-                descriptor.valueParameters.any { it.type.isInlineClassType() } ||
+    val needsValueClassAwareCaller: Boolean =
+        descriptor.isGetterOfUnderlyingPropertyOfValueClass() ||
+                descriptor.contextReceiverParameters.any { it.type.isValueClassType() } ||
+                descriptor.valueParameters.any { it.type.isValueClassType() } ||
                 descriptor.returnType?.isInlineClassType() == true ||
-                this !is BoundCaller && descriptor.hasInlineClassReceiver()
+                descriptor.hasValueClassReceiver()
 
-    return if (needsInlineAwareCaller) InlineClassAwareCaller(descriptor, this, isDefault) else this
+    return if (needsValueClassAwareCaller) ValueClassAwareCaller(descriptor, this, isDefault) else this
 }
 
-private fun CallableMemberDescriptor.hasInlineClassReceiver() =
-    expectedReceiverType?.isInlineClassType() == true
+private fun CallableMemberDescriptor.hasValueClassReceiver() =
+    expectedReceiverType?.isValueClassType() == true
 
-internal fun Class<*>.getUnboxMethod(descriptor: CallableMemberDescriptor): Method =
+internal fun Class<*>.getInlineClassUnboxMethod(descriptor: CallableMemberDescriptor): Method =
     try {
         getDeclaredMethod("unbox" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS)
     } catch (e: NoSuchMethodException) {
         throw KotlinReflectionInternalError("No unbox method found in inline class: $this (calling $descriptor)")
     }
 
-internal fun Class<*>.getBoxMethod(descriptor: CallableMemberDescriptor): Method =
+private fun Class<*>.getBoxMethod(descriptor: CallableMemberDescriptor): Method =
     try {
-        getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getUnboxMethod(descriptor).returnType)
+        getDeclaredMethod("box" + JvmAbi.IMPL_SUFFIX_FOR_INLINE_CLASS_MEMBERS, getInlineClassUnboxMethod(descriptor).returnType)
     } catch (e: NoSuchMethodException) {
         throw KotlinReflectionInternalError("No box method found in inline class: $this (calling $descriptor)")
     }
 
-internal fun KotlinType.toInlineClass(): Class<*>? {
+private fun KotlinType.toInlineClass(): Class<*>? {
     // See computeExpandedTypeForInlineClass.
-    // TODO: add tests on type parameters with inline class bounds.
-    // TODO: add tests on usages of inline classes in Java.
+    // TODO: add tests on type parameters with value class bounds.
+    // TODO: add tests on usages of value classes in Java.
     val klass = constructor.declarationDescriptor.toInlineClass() ?: return null
     if (!TypeUtils.isNullableType(this)) return klass
 
@@ -217,7 +344,7 @@
     if (descriptor is PropertyDescriptor && descriptor.isUnderlyingPropertyOfInlineClass()) return this
 
     val expectedReceiverType = descriptor.expectedReceiverType
-    val unboxMethod = expectedReceiverType?.toInlineClass()?.getUnboxMethod(descriptor) ?: return this
+    val unboxMethod = expectedReceiverType?.toInlineClass()?.getInlineClassUnboxMethod(descriptor) ?: return this
 
     return unboxMethod.invoke(this)
 }
diff --git a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
index e09ed34..b848204 100644
--- a/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
+++ b/core/reflection.jvm/src/kotlin/reflect/jvm/internal/util.kt
@@ -44,6 +44,7 @@
 import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
 import org.jetbrains.kotlin.resolve.descriptorUtil.classId
 import org.jetbrains.kotlin.resolve.isInlineClassType
+import org.jetbrains.kotlin.resolve.needsMfvcFlattening
 import org.jetbrains.kotlin.serialization.deserialization.DeserializationContext
 import org.jetbrains.kotlin.serialization.deserialization.MemberDeserializer
 import java.lang.reflect.Field
@@ -268,6 +269,8 @@
 
 internal val KType.isInlineClassType: Boolean
     get() = (this as? KTypeImpl)?.type?.isInlineClassType() == true
+internal val KType.needsMultiFieldValueClassFlattening: Boolean
+    get() = (this as? KTypeImpl)?.type?.needsMfvcFlattening() == true
 
 internal fun defaultPrimitiveValue(type: Type): Any? =
     if (type is Class<*> && type.isPrimitive) {
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
index 037751e..c0d77ef 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java
@@ -31931,6 +31931,16 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
+                }
+            }
         }
 
         @Nested
@@ -32391,6 +32401,16 @@
                     KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
+                }
+            }
         }
 
         @Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
index 22e5a53..3f973ee 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/fir/FirJsCodegenBoxTestGenerated.java
@@ -32117,6 +32117,16 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+                }
+            }
         }
 
         @Nested
@@ -32577,6 +32587,16 @@
                     KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+                }
+            }
         }
 
         @Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
index 53e4cda..79aa547 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java
@@ -32117,6 +32117,16 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+                }
+            }
         }
 
         @Nested
@@ -32577,6 +32587,16 @@
                     KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
+                }
+            }
         }
 
         @Nested
diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
index 2ce5a51..e519b2e 100644
--- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
+++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsES6CodegenBoxTestGenerated.java
@@ -32117,6 +32117,16 @@
                     }
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
+                }
+            }
         }
 
         @Nested
@@ -32577,6 +32587,16 @@
                     KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
                 }
             }
+
+            @Nested
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            public class ValueClasses {
+                @Test
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
+                }
+            }
         }
 
         @Nested
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java
index ec8207c..0f458e0 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/K2NativeCodegenBoxTestGenerated.java
@@ -35571,6 +35571,19 @@
                         }
                     }
                 }
+
+                @Nested
+                @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+                @TestDataPath("$PROJECT_ROOT")
+                @Tag("codegenK2")
+                @UseExtTestCaseGroupProvider()
+                @K2Pipeline()
+                public class ValueClasses {
+                    @Test
+                    public void testAllFilesPresentInValueClasses() throws Exception {
+                        KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+                    }
+                }
             }
 
             @Nested
@@ -36091,6 +36104,19 @@
                         KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
                     }
                 }
+
+                @Nested
+                @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+                @TestDataPath("$PROJECT_ROOT")
+                @Tag("codegenK2")
+                @UseExtTestCaseGroupProvider()
+                @K2Pipeline()
+                public class ValueClasses {
+                    @Test
+                    public void testAllFilesPresentInValueClasses() throws Exception {
+                        KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+                    }
+                }
             }
 
             @Nested
diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
index 9891efe..b43c618 100644
--- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
+++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java
@@ -35148,6 +35148,18 @@
                         }
                     }
                 }
+
+                @Nested
+                @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+                @TestDataPath("$PROJECT_ROOT")
+                @Tag("codegen")
+                @UseExtTestCaseGroupProvider()
+                public class ValueClasses {
+                    @Test
+                    public void testAllFilesPresentInValueClasses() throws Exception {
+                        KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+                    }
+                }
             }
 
             @Nested
@@ -35652,6 +35664,18 @@
                         KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
                     }
                 }
+
+                @Nested
+                @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+                @TestDataPath("$PROJECT_ROOT")
+                @Tag("codegen")
+                @UseExtTestCaseGroupProvider()
+                public class ValueClasses {
+                    @Test
+                    public void testAllFilesPresentInValueClasses() throws Exception {
+                        KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true);
+                    }
+                }
             }
 
             @Nested
diff --git a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
index 40b7cae..c80d55a 100644
--- a/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
+++ b/wasm/wasm.tests/tests-gen/org/jetbrains/kotlin/wasm/test/IrCodegenBoxWasmTestGenerated.java
@@ -28720,6 +28720,19 @@
                     }
                 }
             }
+
+            @TestMetadata("compiler/testData/codegen/box/reflection/call/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            @RunWith(JUnit3RunnerWithInners.class)
+            public static class ValueClasses extends AbstractIrCodegenBoxWasmTest {
+                private void runTest(String testDataFilePath) throws Exception {
+                    KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
+                }
+
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/call/valueClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
+                }
+            }
         }
 
         @TestMetadata("compiler/testData/codegen/box/reflection/callBy")
@@ -29178,6 +29191,19 @@
                     KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
                 }
             }
+
+            @TestMetadata("compiler/testData/codegen/box/reflection/mapping/valueClasses")
+            @TestDataPath("$PROJECT_ROOT")
+            @RunWith(JUnit3RunnerWithInners.class)
+            public static class ValueClasses extends AbstractIrCodegenBoxWasmTest {
+                private void runTest(String testDataFilePath) throws Exception {
+                    KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
+                }
+
+                public void testAllFilesPresentInValueClasses() throws Exception {
+                    KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/valueClasses"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
+                }
+            }
         }
 
         @TestMetadata("compiler/testData/codegen/box/reflection/methodsFromAny")