Пример #1
0
        public void ComputeReturnValueTreatment(CorElementType type, TypeHandle thRetType, bool isVarArgMethod, out bool usesRetBuffer, out uint fpReturnSize)
        {
            usesRetBuffer = false;
            fpReturnSize  = 0;

            switch (type)
            {
            case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
                throw new NotSupportedException();

            case CorElementType.ELEMENT_TYPE_R4:
                fpReturnSize = sizeof(float);
                break;

            case CorElementType.ELEMENT_TYPE_R8:
                fpReturnSize = sizeof(double);
                break;

            case CorElementType.ELEMENT_TYPE_VALUETYPE:
            {
                Debug.Assert(!thRetType.IsNull() && thRetType.IsValueType());

                if ((Architecture == TargetArchitecture.X64) && IsX64UnixABI)
                {
                    SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR descriptor;
                    SystemVStructClassificator.GetSystemVAmd64PassStructInRegisterDescriptor(thRetType.GetRuntimeTypeHandle(), out descriptor);

                    if (descriptor.passedInRegisters)
                    {
                        if (descriptor.eightByteCount == 1)
                        {
                            if (descriptor.eightByteClassifications0 == SystemVClassificationType.SystemVClassificationTypeSSE)
                            {
                                fpReturnSize = sizeof(double);
                            }
                        }
                        else
                        {
                            fpReturnSize = 16;
                            if (descriptor.eightByteClassifications0 == SystemVClassificationType.SystemVClassificationTypeSSE)
                            {
                                fpReturnSize += 1;
                            }

                            if (descriptor.eightByteClassifications0 == SystemVClassificationType.SystemVClassificationTypeSSE)
                            {
                                fpReturnSize += 2;
                            }
                        }

                        break;
                    }
                }
                else
                {
                    if (thRetType.IsHFA() && !isVarArgMethod)
                    {
                        CorElementType hfaType = thRetType.GetHFAType();

                        switch (Architecture)
                        {
                        case TargetArchitecture.ARM:
                            fpReturnSize = (hfaType == CorElementType.ELEMENT_TYPE_R4) ?
                                           (4 * (uint)sizeof(float)) :
                                           (4 * (uint)sizeof(double));
                            break;

                        case TargetArchitecture.ARM64:
                            // DESKTOP BEHAVIOR fpReturnSize = (hfaType == CorElementType.ELEMENT_TYPE_R4) ? (4 * (uint)sizeof(float)) : (4 * (uint)sizeof(double));
                            // S and D registers overlap. Since we copy D registers in the UniversalTransitionThunk, we'll
                            // treat floats like doubles during copying.
                            fpReturnSize = 4 * (uint)sizeof(double);
                            break;

                        default:
                            throw new NotImplementedException();
                        }
                        break;
                    }

                    uint size = (uint)thRetType.GetSize();

                    if (IsX86 || IsX64)
                    {
                        // Return value types of size which are not powers of 2 using a RetBuffArg
                        if ((size & (size - 1)) != 0)
                        {
                            usesRetBuffer = true;
                            break;
                        }
                    }

                    if (size <= EnregisteredReturnTypeIntegerMaxSize)
                    {
                        break;
                    }
                }
            }

                // Value types are returned using return buffer by default
                usesRetBuffer = true;
                break;

            default:
                break;
            }
        }
Пример #2
0
        public void ComputeReturnValueTreatment(CorElementType type, TypeHandle thRetType, bool isVarArgMethod, out bool usesRetBuffer, out uint fpReturnSize)
        {
            usesRetBuffer = false;
            fpReturnSize  = 0;

            switch (type)
            {
            case CorElementType.ELEMENT_TYPE_TYPEDBYREF:
                throw new NotSupportedException();

            case CorElementType.ELEMENT_TYPE_R4:
                fpReturnSize = sizeof(float);
                break;

            case CorElementType.ELEMENT_TYPE_R8:
                fpReturnSize = sizeof(double);
                break;

            case CorElementType.ELEMENT_TYPE_VALUETYPE:
            {
                Debug.Assert(!thRetType.IsNull() && thRetType.IsValueType());

                if (thRetType.IsHFA() && !isVarArgMethod)
                {
                    CorElementType hfaType = thRetType.GetHFAType();

                    switch (Architecture)
                    {
                    case TargetArchitecture.ARM:
                        fpReturnSize = (hfaType == CorElementType.ELEMENT_TYPE_R4) ?
                                       (4 * (uint)sizeof(float)) :
                                       (4 * (uint)sizeof(double));
                        break;

                    case TargetArchitecture.ARM64:
                        // DESKTOP BEHAVIOR fpReturnSize = (hfaType == CorElementType.ELEMENT_TYPE_R4) ? (4 * (uint)sizeof(float)) : (4 * (uint)sizeof(double));
                        // S and D registers overlap. Since we copy D registers in the UniversalTransitionThunk, we'll
                        // thread floats like doubles during copying.
                        fpReturnSize = 4 * (uint)sizeof(double);
                        break;

                    default:
                        throw new NotImplementedException();
                    }
                    break;
                }

                uint size = (uint)thRetType.GetSize();

                if (IsX86 || IsX64)
                {
                    // Return value types of size which are not powers of 2 using a RetBuffArg
                    if ((size & (size - 1)) != 0)
                    {
                        usesRetBuffer = true;
                        break;
                    }
                }

                if (size <= EnregisteredReturnTypeIntegerMaxSize)
                {
                    break;
                }
            }

                // Value types are returned using return buffer by default
                usesRetBuffer = true;
                break;

            default:
                break;
            }
        }