~ubuntu-branches/ubuntu/trusty/monodevelop/trusty-proposed

« back to all changes in this revision

Viewing changes to contrib/ICSharpCode.Decompiler/ILAst/TypeAnalysis.cs

  • Committer: Package Import Robot
  • Author(s): Jo Shields
  • Date: 2013-05-12 09:46:03 UTC
  • mto: This revision was merged to the branch mainline in revision 29.
  • Revision ID: package-import@ubuntu.com-20130512094603-mad323bzcxvmcam0
Tags: upstream-4.0.5+dfsg
ImportĀ upstreamĀ versionĀ 4.0.5+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
385
385
                                case ILCode.Ldobj:
386
386
                                        {
387
387
                                                TypeReference type = (TypeReference)expr.Operand;
388
 
                                                if (expectedType != null) {
389
 
                                                        int infoAmount = GetInformationAmount(expectedType);
 
388
                                                var argType = InferTypeForExpression(expr.Arguments[0], null);
 
389
                                                if (argType is PointerType || argType is ByReferenceType) {
 
390
                                                        var elementType = ((TypeSpecification)argType).ElementType;
 
391
                                                        int infoAmount = GetInformationAmount(elementType);
390
392
                                                        if (infoAmount == 1 && GetInformationAmount(type) == 8) {
391
393
                                                                // A bool can be loaded from both bytes and sbytes.
392
 
                                                                type = expectedType;
 
394
                                                                type = elementType;
393
395
                                                        }
394
396
                                                        if (infoAmount >= 8 && infoAmount <= 64 && infoAmount == GetInformationAmount(type)) {
395
397
                                                                // An integer can be loaded as another integer of the same size.
396
398
                                                                // For integers smaller than 32 bit, the signs must match (as loading performs sign extension)
397
 
                                                                if (infoAmount >= 32 || IsSigned(expectedType) == IsSigned(type))
398
 
                                                                        type = expectedType;
 
399
                                                                bool? elementTypeIsSigned = IsSigned(elementType);
 
400
                                                                bool? typeIsSigned = IsSigned(type);
 
401
                                                                if (elementTypeIsSigned != null && typeIsSigned != null) {
 
402
                                                                        if (infoAmount >= 32 || elementTypeIsSigned == typeIsSigned)
 
403
                                                                                type = elementType;
 
404
                                                                }
399
405
                                                        }
400
406
                                                }
401
 
                                                if (forceInferChildren) {
402
 
                                                        if (InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type)) is PointerType)
403
 
                                                                InferTypeForExpression(expr.Arguments[0], new PointerType(type));
404
 
                                                }
 
407
                                                if (argType is PointerType)
 
408
                                                        InferTypeForExpression(expr.Arguments[0], new PointerType(type));
 
409
                                                else
 
410
                                                        InferTypeForExpression(expr.Arguments[0], new ByReferenceType(type));
405
411
                                                return type;
406
412
                                        }
407
413
                                case ILCode.Stobj:
606
612
                                        #endregion
607
613
                                        #region Array instructions
608
614
                                case ILCode.Newarr:
609
 
                                        if (forceInferChildren)
610
 
                                                InferTypeForExpression(expr.Arguments.Single(), typeSystem.Int32);
 
615
                                        if (forceInferChildren) {
 
616
                                                var lengthType = InferTypeForExpression(expr.Arguments.Single(), null);
 
617
                                                if (lengthType == typeSystem.IntPtr) {
 
618
                                                        lengthType = typeSystem.Int64;
 
619
                                                } else if (lengthType == typeSystem.UIntPtr) {
 
620
                                                        lengthType = typeSystem.UInt64;
 
621
                                                } else if (lengthType != typeSystem.UInt32 && lengthType != typeSystem.Int64 && lengthType != typeSystem.UInt64) {
 
622
                                                        lengthType = typeSystem.Int32;
 
623
                                                }
 
624
                                                if (forceInferChildren) {
 
625
                                                        InferTypeForExpression(expr.Arguments.Single(), lengthType);
 
626
                                                }
 
627
                                        }
611
628
                                        return new ArrayType((TypeReference)expr.Operand);
612
629
                                case ILCode.InitArray:
613
630
                                        var operandAsArrayType = (ArrayType)expr.Operand;
779
796
                                case ILCode.YieldBreak:
780
797
                                        return null;
781
798
                                case ILCode.Ret:
782
 
                                        if (forceInferChildren && expr.Arguments.Count == 1)
783
 
                                                InferTypeForExpression(expr.Arguments[0], context.CurrentMethod.ReturnType);
 
799
                                        if (forceInferChildren && expr.Arguments.Count == 1) {
 
800
                                                TypeReference returnType = context.CurrentMethod.ReturnType;
 
801
                                                if (context.CurrentMethodIsAsync && returnType != null && returnType.Namespace == "System.Threading.Tasks") {
 
802
                                                        if (returnType.Name == "Task") {
 
803
                                                                returnType = typeSystem.Void;
 
804
                                                        } else if (returnType.Name == "Task`1" && returnType.IsGenericInstance) {
 
805
                                                                returnType = ((GenericInstanceType)returnType).GenericArguments[0];
 
806
                                                        }
 
807
                                                }
 
808
                                                InferTypeForExpression(expr.Arguments[0], returnType);
 
809
                                        }
784
810
                                        return null;
785
811
                                case ILCode.YieldReturn:
786
812
                                        if (forceInferChildren) {
792
818
                                                }
793
819
                                        }
794
820
                                        return null;
 
821
                                case ILCode.Await:
 
822
                                        {
 
823
                                                TypeReference taskType = InferTypeForExpression(expr.Arguments[0], null);
 
824
                                                if (taskType.Name == "Task`1" && taskType.IsGenericInstance && taskType.Namespace == "System.Threading.Tasks") {
 
825
                                                        return ((GenericInstanceType)taskType).GenericArguments[0];
 
826
                                                }
 
827
                                                return null;
 
828
                                        }
795
829
                                        #endregion
796
830
                                case ILCode.Pop:
797
831
                                        return null;
974
1008
                                InferTypeForExpression(right, typeSystem.IntPtr);
975
1009
                                return leftPreferred;
976
1010
                        }
 
1011
                        if (IsEnum(leftPreferred)) {
 
1012
                                //E+U=E
 
1013
                                left.InferredType = left.ExpectedType = leftPreferred;
 
1014
                                InferTypeForExpression(right, GetEnumUnderlyingType(leftPreferred));
 
1015
                                return leftPreferred;
 
1016
                        }
977
1017
                        TypeReference rightPreferred = DoInferTypeForExpression(right, expectedType);
978
1018
                        if (rightPreferred is PointerType) {
979
1019
                                InferTypeForExpression(left, typeSystem.IntPtr);
980
1020
                                right.InferredType = right.ExpectedType = rightPreferred;
981
1021
                                return rightPreferred;
982
1022
                        }
 
1023
                        if (IsEnum(rightPreferred)) {
 
1024
                                //U+E=E
 
1025
                                right.InferredType = right.ExpectedType = rightPreferred;
 
1026
                                InferTypeForExpression(left, GetEnumUnderlyingType(rightPreferred));
 
1027
                                return rightPreferred;
 
1028
                        }
983
1029
                        return InferBinaryArguments(left, right, expectedType, leftPreferred: leftPreferred, rightPreferred: rightPreferred);
984
1030
                }
985
1031
                
993
1039
                                InferTypeForExpression(right, typeSystem.IntPtr);
994
1040
                                return leftPreferred;
995
1041
                        }
 
1042
                        if (IsEnum(leftPreferred)) {
 
1043
                                if (expectedType != null && IsEnum(expectedType)) {
 
1044
                                        // E-U=E
 
1045
                                        left.InferredType = left.ExpectedType = leftPreferred;
 
1046
                                        InferTypeForExpression(right, GetEnumUnderlyingType(leftPreferred));
 
1047
                                        return leftPreferred;
 
1048
                                } else {
 
1049
                                        // E-E=U
 
1050
                                        left.InferredType = left.ExpectedType = leftPreferred;
 
1051
                                        InferTypeForExpression(right, leftPreferred);
 
1052
                                        return GetEnumUnderlyingType(leftPreferred);
 
1053
                                }
 
1054
                        }
996
1055
                        return InferBinaryArguments(left, right, expectedType, leftPreferred: leftPreferred);
997
1056
                }
998
1057
 
1035
1094
                /// </summary>
1036
1095
                public const int NativeInt = 33; // treat native int as between int32 and int64
1037
1096
                
 
1097
                /// <summary>
 
1098
                /// Gets the underlying type, if the specified type is an enum.
 
1099
                /// Otherwise, returns null.
 
1100
                /// </summary>
 
1101
                public static TypeReference GetEnumUnderlyingType(TypeReference enumType)
 
1102
                {
 
1103
                        // unfortunately we cannot rely on enumType.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
 
1104
                        if (enumType != null && !IsArrayPointerOrReference(enumType)) {
 
1105
                                // value type might be an enum
 
1106
                                TypeDefinition typeDef = enumType.Resolve() as TypeDefinition;
 
1107
                                if (typeDef != null && typeDef.IsEnum) {
 
1108
                                        return typeDef.Fields.Single(f => !f.IsStatic).FieldType;
 
1109
                                }
 
1110
                        }
 
1111
                        return null;
 
1112
                }
 
1113
                
1038
1114
                public static int GetInformationAmount(TypeReference type)
1039
1115
                {
 
1116
                        type = GetEnumUnderlyingType(type) ?? type;
1040
1117
                        if (type == null)
1041
1118
                                return 0;
1042
 
                        if (type.IsValueType && !IsArrayPointerOrReference(type)) {
1043
 
                                // value type might be an enum
1044
 
                                TypeDefinition typeDef = type.Resolve() as TypeDefinition;
1045
 
                                if (typeDef != null && typeDef.IsEnum) {
1046
 
                                        TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
1047
 
                                        return GetInformationAmount(underlyingType);
1048
 
                                }
1049
 
                        }
1050
1119
                        switch (type.MetadataType) {
1051
1120
                                case MetadataType.Void:
1052
1121
                                        return 0;
1098
1167
                
1099
1168
                static bool? IsSigned(TypeReference type)
1100
1169
                {
1101
 
                        if (type == null || IsArrayPointerOrReference(type))
 
1170
                        type = GetEnumUnderlyingType(type) ?? type;
 
1171
                        if (type == null)
1102
1172
                                return null;
1103
 
                        // unfortunately we cannot rely on type.IsValueType here - it's not set when the instruction operand is a typeref (as opposed to a typespec)
1104
 
                        TypeDefinition typeDef = type.Resolve() as TypeDefinition;
1105
 
                        if (typeDef != null && typeDef.IsEnum) {
1106
 
                                TypeReference underlyingType = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
1107
 
                                return IsSigned(underlyingType);
1108
 
                        }
1109
1173
                        switch (type.MetadataType) {
1110
1174
                                case MetadataType.SByte:
1111
1175
                                case MetadataType.Int16:
1127
1191
                
1128
1192
                static bool OperandFitsInType(TypeReference type, int num)
1129
1193
                {
1130
 
                        TypeDefinition typeDef = type.Resolve() as TypeDefinition;
1131
 
                        if (typeDef != null && typeDef.IsEnum) {
1132
 
                                type = typeDef.Fields.Single(f => f.IsRuntimeSpecialName && !f.IsStatic).FieldType;
1133
 
                        }
 
1194
                        type = GetEnumUnderlyingType(type) ?? type;
1134
1195
                        switch (type.MetadataType) {
1135
1196
                                case MetadataType.SByte:
1136
1197
                                        return sbyte.MinValue <= num && num <= sbyte.MaxValue;