From ba66eeab4b8306ac11feb19d09c19fd2d8e5aa95 Mon Sep 17 00:00:00 2001 From: Hanjoung Lee Date: Wed, 13 Jul 2016 19:39:21 +0900 Subject: [ARM-softfp/Linux] Get precise type for pointer-size struct Compiler::getPrimitiveTypeForStruct may return TYP_FLOAT but is off on softfp. So we need to check that in another way rather than `IsHfa()`. Otherwise struct types with single float32 will make inconsistency in gentree. Which ends up with assert failure "Bad IL: Illegal assignment of float into integer!". Check is done in Compiler::getPrimitiveTypeForStruct, by isSingleFloat32Struct. Fix #6051 --- src/jit/compiler.cpp | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- src/jit/compiler.h | 4 ++++ src/jit/morph.cpp | 4 ++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/src/jit/compiler.cpp b/src/jit/compiler.cpp index b7b332598f..04c90d78af 100644 --- a/src/jit/compiler.cpp +++ b/src/jit/compiler.cpp @@ -447,6 +447,49 @@ void Compiler::getStructGcPtrsFromOp(GenTreePtr op, BYTE *gcPtrsOut) } #endif // FEATURE_MULTIREG_ARGS +#ifdef ARM_SOFTFP +//--------------------------------------------------------------------------- +// IsSingleFloat32Struct: +// Check if the given struct type contains only one float32 value type +// +// Arguments: +// clsHnd - the handle for the struct type +// +// Return Value: +// true if the given struct type contains only one float32 value type, +// false otherwise. +// + +bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd) +{ + for (;;) + { + // all of class chain must be of value type and must have only one field + if (!info.compCompHnd->isValueClass(clsHnd) && + info.compCompHnd->getClassNumInstanceFields(clsHnd) != 1) + { + return false; + } + + CORINFO_CLASS_HANDLE* pClsHnd = &clsHnd; + CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0); + CorInfoType fieldType = info.compCompHnd->getFieldType(fldHnd, pClsHnd); + + switch (fieldType) + { + case CORINFO_TYPE_VALUECLASS: + clsHnd = *pClsHnd; + break; + + case CORINFO_TYPE_FLOAT: + return true; + + default: + return false; + } + } +} +#endif // ARM_SOFTFP //----------------------------------------------------------------------------- // getPrimitiveTypeForStruct: @@ -521,8 +564,15 @@ var_types Compiler::getPrimitiveTypeForStruct( unsigned structSize, #endif // _TARGET_XARCH_ #endif // _TARGET_64BIT_ + case TARGET_POINTER_SIZE: +#ifdef ARM_SOFTFP + // For ARM_SOFTFP, HFA is unsupported so we need to check in another way + // This matters only for size-4 struct cause bigger structs would be processed with RetBuf + if (isSingleFloat32Struct(clsHnd)) +#else // !ARM_SOFTFP if (IsHfa(clsHnd)) +#endif // ARM_SOFTFP { #ifdef _TARGET_64BIT_ var_types hfaType = GetHfaType(clsHnd); @@ -547,7 +597,7 @@ var_types Compiler::getPrimitiveTypeForStruct( unsigned structSize, #else // a 32BIT target // A structSize of 4 with IsHfa, it must be an HFA of one float useType = TYP_FLOAT; -#endif +#endif // _TARGET_64BIT_ } else { diff --git a/src/jit/compiler.h b/src/jit/compiler.h index 26f028508d..c96defb9a7 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -1443,6 +1443,10 @@ public: GenTreePtr impAssignMultiRegTypeToVar(GenTreePtr op, CORINFO_CLASS_HANDLE hClass); #endif // FEATURE_MULTIREG_RET +#ifdef ARM_SOFTFP + bool isSingleFloat32Struct(CORINFO_CLASS_HANDLE hClass); +#endif // ARM_SOFTFP + //------------------------------------------------------------------------- // Functions to handle homogeneous floating-point aggregates (HFAs) in ARM. // HFAs are one to four element structs where each element is the same diff --git a/src/jit/morph.cpp b/src/jit/morph.cpp index 12ee7791e3..c65b51b251 100644 --- a/src/jit/morph.cpp +++ b/src/jit/morph.cpp @@ -16010,7 +16010,11 @@ Compiler::fgWalkResult Compiler::fgMorphLocalField(GenTreePtr tree, fgWalkD tree->gtLclFld.SetLclNum(fieldLclIndex); // We need to keep the types 'compatible'. If we can switch back to a GT_LCL_VAR +#ifdef ARM_SOFTFP + assert(varTypeIsIntegralOrI(tree->TypeGet()) || varTypeIsFloating(tree->TypeGet())); +#else assert(varTypeIsIntegralOrI(tree->TypeGet())); +#endif if (varTypeCanReg(fldVarDsc->TypeGet())) { // If the type is integer-ish, then we can use it as-is -- cgit v1.2.3