From 498c952ae195dcb9881c6d67aeb2d6532e3e4678 Mon Sep 17 00:00:00 2001 From: Fadi Hanna Date: Thu, 24 May 2018 15:12:46 -0700 Subject: [PATCH] Fixing a bug with handling HFA of floats for arm64. When passing HFAs, if the struct fits in the SIMD registers, given that the S and D registers overlap and how the UniversalTransitionThunk and CallDescrWorker copy D values, we treat the HFA struct as an HFA of doubles instead of floats (And we double the size of the struct during this processing). The issue however is when there aren't enough SIMD registers to fit the HFA struct, and we're forced to pass it on the stack. In that case, we shouldn't double the size of the struct and treat the floats as doubles. Also fixing the test to exclude invalid scenarios from arm64 (the scenario is invalid because the return buffer pointer is passed using a special x8 register, and not using the x0-7 registers like the rest of the arguments) [tfs-changeset: 1701853] --- .../Runtime/TypeLoader/CallingConventions.cs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs index 25ee7b1daf5..f40dedb4677 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/CallingConventions.cs @@ -935,9 +935,14 @@ public unsafe int GetNextOffset() #if _TARGET_ARM64_ // NOT DESKTOP BEHAVIOR: The S and D registers overlap, and the UniversalTransitionThunk copies D registers to the transition blocks. We'll need // to work with the D registers here as well. + bool processingFloatsAsDoublesFromTransitionBlock = false; if (argType == CorElementType.ELEMENT_TYPE_VALUETYPE && _argTypeHandle.IsHFA() && _argTypeHandle.GetHFAType() == CorElementType.ELEMENT_TYPE_R4) { - argSize *= 2; + if ((argSize / sizeof(float)) + _idxFPReg <= 8) + { + argSize *= 2; + processingFloatsAsDoublesFromTransitionBlock = true; + } } #endif @@ -1239,8 +1244,10 @@ public unsafe int GetNextOffset() if (_argTypeHandle.IsHFA()) { CorElementType type = _argTypeHandle.GetHFAType(); - // DESKTOP BEHAVIOR cFPRegs = (type == CorElementType.ELEMENT_TYPE_R4) ? (argSize / sizeof(float)) : (argSize / sizeof(double)); - cFPRegs = argSize / sizeof(double); + if (processingFloatsAsDoublesFromTransitionBlock) + cFPRegs = argSize / sizeof(double); + else + cFPRegs = (type == CorElementType.ELEMENT_TYPE_R4) ? (argSize / sizeof(float)) : (argSize / sizeof(double)); } else {