diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 528abe9412e5e5281f61d9cae4690ab64c0f6ec6..3ce2c9101f1a2c2b02160d5355285c88a9c7b0ae 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "llvm-intrinsics-types.h" #include "interp/interp.h" @@ -1483,7 +1484,7 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets) gpointer iter; MonoClassField *field; MonoType *ftype, *prev_ftype = NULL; - int i, nfields = 0; + int nfields = 0; klass = mono_class_from_mono_type_internal (t); iter = NULL; @@ -1497,8 +1498,22 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets) int nested_nfields, nested_esize; int nested_field_offsets [16]; - if (!is_hfa (ftype, &nested_nfields, &nested_esize, nested_field_offsets)) - return FALSE; + MonoType *fixed_etype; + int fixed_len; + if (mono_marshal_shared_get_fixed_buffer_attr (field, &fixed_etype, &fixed_len)) { + if (fixed_etype->type != MONO_TYPE_R4 && fixed_etype->type != MONO_TYPE_R8) + return FALSE; + if (fixed_len > 16) + return FALSE; + nested_nfields = fixed_len; + nested_esize = fixed_etype->type == MONO_TYPE_R4 ? 4 : 8; + for (int i = 0; i < nested_nfields; ++i) + nested_field_offsets [i] = i * nested_esize; + } else { + if (!is_hfa (ftype, &nested_nfields, &nested_esize, nested_field_offsets)) + return FALSE; + } + if (nested_esize == 4) ftype = m_class_get_byval_arg (mono_defaults.single_class); else @@ -1506,7 +1521,7 @@ is_hfa (MonoType *t, int *out_nfields, int *out_esize, int *field_offsets) if (prev_ftype && prev_ftype->type != ftype->type) return FALSE; prev_ftype = ftype; - for (i = 0; i < nested_nfields; ++i) { + for (int i = 0; i < nested_nfields; ++i) { if (nfields + i < 4) field_offsets [nfields + i] = field->offset - MONO_ABI_SIZEOF (MonoObject) + nested_field_offsets [i]; } diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.cs b/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.cs new file mode 100644 index 0000000000000000000000000000000000000000..029fa5891864c696a6afa9605ddaafa56fddb8fd --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.cs @@ -0,0 +1,58 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using System.Runtime.Intrinsics.X86; +using Xunit; + +using System; + +public class Runtime_90423 +{ + public static BaconClass.BaconStruct foo; + + [Fact] + public unsafe static int EntryPoint() + { + foo = BaconClass.GetBacon(); + + for (int i = 0; i < BaconClass.BaconStruct.RESOLUTION; i++) + { + if (Math.Abs(foo.table[i] - BaconClass.foo.table[i]) > float.Epsilon) + return 101; + } + return 100; + } + + public class BaconClass + { + public unsafe struct BaconStruct + { + public float length; + public const int RESOLUTION = 5; + public fixed float table[RESOLUTION]; + } + + public static BaconStruct foo; + + public unsafe static BaconStruct GetBacon() + { + const int resolution = BaconStruct.RESOLUTION; + var length = 1; + BaconStruct lut = new BaconStruct() + { + length = length + }; + foo = new BaconStruct(){length = length}; + + float[] bacon = new float[] { 1.1f, 1.2f, 1.3f, 1.4f, 1.5f }; + for (int x = 0; x < BaconStruct.RESOLUTION; x++) + { + lut.table[x] = bacon[x]; + foo.table[x] = bacon[x]; + } + return lut; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.csproj new file mode 100644 index 0000000000000000000000000000000000000000..1981001110bbe0e142fafd5d3e112906baa8e49e --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_90423/Runtime_90423.csproj @@ -0,0 +1,9 @@ + + + True + true + + + + +