コード例 #1
0
ファイル: TypeInference.cs プロジェクト: th3ptuga/OldRod
        private bool TryInferVariableType(CilVariable variable)
        {
            // Do not update the type of the flags variable.
            if (_context.FlagVariable == variable)
            {
                return(false);
            }

            // Collect expected types.
            var expectedTypes = CollectExpectedTypes(variable);

            ITypeDescriptor newVariableType = null;

            if (expectedTypes.Any(t => t.IsTypeOf("System", "Array")))
            {
                newVariableType = TryInferArrayType(variable);
            }

            if (newVariableType == null)
            {
                newVariableType = _helper.GetCommonBaseType(expectedTypes);
            }

            return(TrySetVariableType(variable, newVariableType));
        }
コード例 #2
0
ファイル: TypeInference.cs プロジェクト: th3ptuga/OldRod
        private bool TrySetVariableType(CilVariable variable, ITypeDescriptor variableType)
        {
            if (variableType != null && variable.VariableType.FullName != variableType.FullName)
            {
                var newType = _context.TargetImage.TypeSystem.GetMscorlibType(variableType)
                              ?? _context.ReferenceImporter.ImportTypeSignature(variableType.ToTypeSignature());
                variable.VariableType = newType;

                // Update the expression type of all references to the variable.
                foreach (var use in variable.UsedBy)
                {
                    use.ExpressionType = use.IsReference
                        ? new ByReferenceTypeSignature(newType)
                        : newType;
                }

                // Update the expected type of all expressions that are assigned to the variable.
                foreach (var assign in variable.AssignedBy)
                {
                    assign.Value.ExpectedType = newType;
                }

                return(true);
            }

            return(false);
        }
コード例 #3
0
        /// <inheritdoc />
        public IConcreteValue this[IVariable variable]
        {
            get
            {
                if (!_variables.TryGetValue(variable, out var value))
                {
                    value = variable switch
                    {
                        CilVariable cilVariable => _valueFactory.CreateValue(cilVariable.Variable.VariableType, false),
                        CilParameter cilParameter => _valueFactory.CreateValue(cilParameter.Parameter.ParameterType,
                                                                               false),
                        _ => throw new NotSupportedException($"IVariable implementation {variable.GetType()} is not supported.")
                    };
                    _variables[variable] = value;
                }

                return(value);
            }
            set
            {
                if (!(variable is CilParameter) && !(variable is CilVariable))
                {
                    throw new NotSupportedException($"IVariable implementation {variable.GetType()} is not supported.");
                }

                _variables[variable] = value;
            }
        }
コード例 #4
0
        public CodeGenerationContext(CilMethodBody methodBody, VMConstants constants, CilVariable flagVariable,
                                     TypeDefinition flagHelperType)
        {
            MethodBody    = methodBody;
            Constants     = constants;
            _flagVariable = flagVariable;
            VmHelperType  = flagHelperType;

            ReferenceImporter = new ReferenceImporter(TargetModule);

            _arg0   = new CilVariable("__arg0", TargetModule.CorLibTypeFactory.UInt32);
            _arg1   = new CilVariable("__arg1", TargetModule.CorLibTypeFactory.UInt32);
            _result = new CilVariable("__result", TargetModule.CorLibTypeFactory.UInt32);
        }
コード例 #5
0
        private bool TryInferVariableType(CilVariable variable)
        {
            // Do not update the type of the flags variable.
            if (_context.FlagVariable == variable)
            {
                return(false);
            }

            var expectedTypes = variable.UsedBy
                                .Select(use => use.IsReference // If ldloca/ldarga, get the underlying type of the expected byref type.
                        ? ((ByReferenceTypeSignature)use.ExpectedType).BaseType
                        : use.ExpectedType)
                                .Where(t => t != null)
#if DEBUG
                                .ToArray()
#endif
            ;

            var commonBaseType = _helper.GetCommonBaseType(expectedTypes);

            if (commonBaseType != null && variable.VariableType.FullName != commonBaseType.FullName)
            {
                var newType = _context.TargetImage.TypeSystem.GetMscorlibType(commonBaseType)
                              ?? _context.ReferenceImporter.ImportTypeSignature(commonBaseType.ToTypeSignature());
                variable.VariableType = newType;

                // Update the expression type of all references to the variable.
                foreach (var use in variable.UsedBy)
                {
                    use.ExpressionType = use.IsReference
                        ? new ByReferenceTypeSignature(newType)
                        : newType;
                }

                // Update the expected type of all expressions that are assigned to the variable.
                foreach (var assign in variable.AssignedBy)
                {
                    assign.Value.ExpectedType = newType;
                }

                return(true);
            }

            return(false);
        }
コード例 #6
0
ファイル: TypeInference.cs プロジェクト: th3ptuga/OldRod
        private ITypeDescriptor TryInferArrayType(CilVariable variable)
        {
            if (variable.AssignedBy.Count == 0)
            {
                return(null);
            }

            var types = variable.AssignedBy
                        .Select(a => a.Value.ExpressionType)
                        .ToArray();

            if (types[0] is SzArrayTypeSignature arrayType &&
                types.All(t => Comparer.Equals(t, arrayType)))
            {
                return(arrayType);
            }

            return(null);
        }
コード例 #7
0
ファイル: TypeInference.cs プロジェクト: th3ptuga/OldRod
        private ICollection <ITypeDescriptor> CollectExpectedTypes(CilVariable variable)
        {
            var expectedTypes = new List <ITypeDescriptor>();

            foreach (var use in variable.UsedBy)
            {
                var expectedType = use.ExpectedType;
                if (expectedType == null)
                {
                    continue;
                }

                if (!use.IsReference)
                {
                    // Normal read reference to the variable (e.g. using a ldloc or ldarg).
                    expectedTypes.Add(expectedType);
                }
                else if (expectedType is ByReferenceTypeSignature byRefType)
                {
                    // The variable's address was used (e.g. using a ldloca or ldarga). To avoid the type inference
                    // to think that the variable is supposed to be a byref type, we get the base type instead.
                    expectedTypes.Add(byRefType.BaseType);
                }
                else
                {
                    // If this happens, we probably have an error somewhere in an earlier stage of the recompiler.
                    // Variable loaded by reference should always have a byref type sig as expected type.

                    throw new RecompilerException(
                              $"Variable {use.Variable.Name} in the expression `{use.Parent}` in "
                              + $"{_context.MethodBody.Method.Name} ({_context.MethodBody.Method.MetadataToken}) was passed on " +
                              $"by reference, but does not have a by-reference expected type.");
                }
            }

            return(expectedTypes);
        }
コード例 #8
0
ファイル: TypeInference.cs プロジェクト: heartingrass/OldRod
        private bool TryInferVariableType(CilVariable variable)
        {
            // Do not update the type of the flags variable.
            if (_context.FlagVariable == variable)
            {
                return(false);
            }

            // Collect expected types.
            var expectedTypes = new List <ITypeDescriptor>();

            foreach (var use in variable.UsedBy)
            {
                var expectedType = use.ExpectedType;

                if (!use.IsReference)
                {
                    // Normal read reference to the variable (e.g. using a ldloc or ldarg).
                    expectedTypes.Add(expectedType);
                }
                else if (expectedType is ByReferenceTypeSignature byRefType)
                {
                    // The variable's address was used (e.g. using a ldloca or ldarga). To avoid the type inference
                    // to think that the variable is supposed to be a byref type, we get the base type instead.
                    expectedTypes.Add(byRefType.BaseType);
                }
                else
                {
                    // If this happens, we probably have an error somewhere in an earlier stage of the recompiler.
                    // Variable loaded by reference should always have a byref type sig as expected type.

                    throw new RecompilerException(
                              $"Variable {use.Variable.Name} in the expression `{use.Parent}` in "
                              + $"{_context.MethodBody.Method.Name} ({_context.MethodBody.Method.MetadataToken}) was passed on " +
                              $"by reference, but does not have a by-reference expected type.");
                }
            }

            var commonBaseType = _helper.GetCommonBaseType(expectedTypes);

            if (commonBaseType != null && variable.VariableType.FullName != commonBaseType.FullName)
            {
                var newType = _context.TargetImage.TypeSystem.GetMscorlibType(commonBaseType)
                              ?? _context.ReferenceImporter.ImportTypeSignature(commonBaseType.ToTypeSignature());
                variable.VariableType = newType;

                // Update the expression type of all references to the variable.
                foreach (var use in variable.UsedBy)
                {
                    use.ExpressionType = use.IsReference
                        ? new ByReferenceTypeSignature(newType)
                        : newType;
                }

                // Update the expected type of all expressions that are assigned to the variable.
                foreach (var assign in variable.AssignedBy)
                {
                    assign.Value.ExpectedType = newType;
                }

                return(true);
            }

            return(false);
        }