예제 #1
0
        public override void Visit(IMetadataConstant literal)
        {
            ITypeReference type = literal.Type;
            Visit(type);

            base.Visit(literal);
        }
예제 #2
0
        public LocalConstantDefinition(string name, Location location, IMetadataConstant compileTimeValue, bool isDynamic = false,
            ImmutableArray<TypedConstant> dynamicTransformFlags = default(ImmutableArray<TypedConstant>))
        {
            Debug.Assert(!string.IsNullOrEmpty(name));
            Debug.Assert(compileTimeValue != null);

            this.name = name;
            this.location = location;
            this.compileTimeValue = compileTimeValue;
            this.isDynamic = isDynamic;
            this.dynamicTransformFlags = dynamicTransformFlags;
        }
예제 #3
0
 /// <summary>
 /// Allocates a mutable object that represents a local variable or constant.
 /// </summary>
 public GeneratorLocal()
 {
     this.compileTimeValue = Dummy.Constant;
       this.customModifiers = new List<ICustomModifier>();
       this.isModified = false;
       this.isPinned = false;
       this.isReference = false;
       this.locations = new List<ILocation>();
       this.name = Dummy.Name;
       this.methodDefinition = Dummy.Method;
       this.type = Dummy.TypeReference;
 }
예제 #4
0
 public static bool IsIntegralMinusOne(IMetadataConstant constExpression) {
   IConvertible/*?*/ ic = constExpression.Value as IConvertible;
   if (ic == null) return false;
   switch (ic.GetTypeCode()) {
     case System.TypeCode.SByte: return ic.ToSByte(null) == -1;
     case System.TypeCode.Int16: return ic.ToInt16(null) == -1;
     case System.TypeCode.Int32: return ic.ToInt32(null) == -1;
     case System.TypeCode.Int64: return ic.ToInt64(null) == -1;
     case System.TypeCode.Byte: return ic.ToByte(null) == byte.MaxValue;
     case System.TypeCode.UInt16: return ic.ToUInt16(null) == ushort.MaxValue;
     case System.TypeCode.UInt32: return ic.ToUInt32(null) == uint.MaxValue;
     case System.TypeCode.UInt64: return ic.ToUInt64(null) == ulong.MaxValue;
   }
   return false;
 }
예제 #5
0
 public static bool IsIntegralOne(IMetadataConstant constExpression) {
   IConvertible/*?*/ ic = constExpression.Value as IConvertible;
   if (ic == null) return false;
   switch (ic.GetTypeCode()) {
     case System.TypeCode.SByte: return ic.ToSByte(null) == 1;
     case System.TypeCode.Int16: return ic.ToInt16(null) == 1;
     case System.TypeCode.Int32: return ic.ToInt32(null) == 1;
     case System.TypeCode.Int64: return ic.ToInt64(null) == 1;
     case System.TypeCode.Byte: return ic.ToByte(null) == 1;
     case System.TypeCode.UInt16: return ic.ToUInt16(null) == 1;
     case System.TypeCode.UInt32: return ic.ToUInt32(null) == 1;
     case System.TypeCode.UInt64: return ic.ToUInt64(null) == 1;
     case System.TypeCode.Boolean: return ic.ToBoolean(null);
   }
   return false;
 }
예제 #6
0
 /// <summary>
 /// Returns true if the given constant expression contains a finite numeric value. In other words, infinities and NaN are excluded.
 /// </summary>
 /// <param name="constExpression"></param>
 /// <returns></returns>
 public static bool IsFiniteNumeric(IMetadataConstant constExpression) {
   IConvertible/*?*/ ic = constExpression.Value as IConvertible;
   if (ic == null) return false;
   switch (ic.GetTypeCode()) {
     case System.TypeCode.SByte:
     case System.TypeCode.Int16:
     case System.TypeCode.Int32:
     case System.TypeCode.Int64:
     case System.TypeCode.Byte:
     case System.TypeCode.UInt16:
     case System.TypeCode.UInt32:
     case System.TypeCode.UInt64:
       return true;
     case System.TypeCode.Double:
       var d = ic.ToDouble(null);
       return !(Double.IsNaN(d) || Double.IsInfinity(d));
     case System.TypeCode.Single:
       var s = ic.ToSingle(null);
       return !(Single.IsNaN(s) || Single.IsInfinity(s));
   }
   return false;
 }
예제 #7
0
 /// <summary>
 /// Specifies the symbol table elements on which it is valid to apply this attribute.
 /// This information is obtained from an attribute on the attribute type definition.
 /// </summary>
 public static AttributeTargets ValidOn(ITypeDefinition attributeType)
 {
     foreach (ICustomAttribute ca in attributeType.Attributes)
     {
         if (!TypeHelper.TypesAreEquivalent(ca.Type, attributeType.PlatformType.SystemAttributeUsageAttribute))
         {
             continue;
         }
         foreach (IMetadataExpression expr in ca.Arguments)
         {
             IMetadataConstant /*?*/ ctorParam = expr as IMetadataConstant;
             if (ctorParam == null || ctorParam.Value == null || !(ctorParam.Value is int))
             {
                 break;
             }
             //^ assume false; //Unboxing cast might fail
             int val = (int)ctorParam.Value;
             return((AttributeTargets)val);
         }
     }
     return(AttributeTargets.All);
 }
예제 #8
0
 /// <summary>
 /// Specifies whether this attribute applies to derived types and/or overridden methods.
 /// This information is obtained from an attribute on the attribute type definition.
 /// </summary>
 public static bool Inherited(ITypeDefinition attributeType, INameTable nameTable)
 {
     foreach (ICustomAttribute ca in attributeType.Attributes)
     {
         if (!TypeHelper.TypesAreEquivalent(ca.Type, attributeType.PlatformType.SystemAttributeUsageAttribute))
         {
             continue;
         }
         foreach (IMetadataNamedArgument namedArgument in ca.NamedArguments)
         {
             if (namedArgument.ArgumentName.UniqueKey == nameTable.AllowMultiple.UniqueKey)
             {
                 IMetadataConstant /*?*/ compileTimeConst = namedArgument.ArgumentValue as IMetadataConstant;
                 if (compileTimeConst == null || compileTimeConst.Value == null || !(compileTimeConst.Value is bool))
                 {
                     continue;
                 }
                 //^ assume false; //Unboxing cast might fail
                 return((bool)compileTimeConst.Value);
             }
         }
     }
     return(false);
 }
예제 #9
0
        private static ulong ConvertToUlong(IMetadataConstant c)
        {
            IConvertible /*?*/ ic = c.Value as IConvertible;

            if (ic == null)
            {
                return(0);      //TODO: error
            }
            switch (ic.GetTypeCode())
            {
            case TypeCode.SByte:
            case TypeCode.Int16:
            case TypeCode.Int32:
            case TypeCode.Int64:
                return((ulong)ic.ToInt64(null)); //TODO: error if < 0

            case TypeCode.Byte:
            case TypeCode.UInt16:
            case TypeCode.UInt32:
            case TypeCode.UInt64:
                return(ic.ToUInt64(null));
            }
            return(0); //TODO: error
        }
예제 #10
0
 public void Visit(IMetadataConstant constant)
 {
     throw new NotImplementedException();
 }
예제 #11
0
        private void ReplaceLocalArrayInitializerPattern(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 4)
            {
                return;
            }
            PushStatement /*?*/ push = statements[i] as PushStatement;

            if (push == null)
            {
                return;
            }
            var pushDup = statements[i + 1] as PushStatement;

            if (pushDup == null || !(pushDup.ValueToPush is Dup))
            {
                return;
            }
            CreateArray /*?*/ createArray = push.ValueToPush as CreateArray;

            if (createArray == null)
            {
                return;
            }
            ExpressionStatement /*?*/ expressionStatement = statements[i + 2] as ExpressionStatement;

            if (expressionStatement == null)
            {
                return;
            }
            MethodCall /*?*/ methodCall = expressionStatement.Expression as MethodCall;

            if (methodCall == null || !methodCall.IsStaticCall || methodCall.IsJumpCall || methodCall.Arguments.Count != 2)
            {
                return;
            }
            var pop = methodCall.Arguments[0] as Pop;

            if (pop == null)
            {
                return;
            }
            TokenOf /*?*/ tokenOf = methodCall.Arguments[1] as TokenOf;

            if (tokenOf == null)
            {
                return;
            }
            IFieldDefinition /*?*/ initialValueField = tokenOf.Definition as IFieldDefinition;

            if (initialValueField == null || !initialValueField.IsMapped)
            {
                return;
            }
            if (methodCall.MethodToCall.Name.UniqueKey != this.InitializeArray.UniqueKey)
            {
                return;
            }
            List <ulong> sizes = new List <ulong>();

            foreach (IExpression expr in createArray.Sizes)
            {
                IMetadataConstant mdc = expr as IMetadataConstant;
                if (mdc == null)
                {
                    return;
                }
                sizes.Add(ConvertToUlong(mdc));
            }
            AddArrayInitializers(createArray, initialValueField, sizes.ToArray());
            expressionStatement = statements[i + 3] as ExpressionStatement;
            if (expressionStatement != null)
            {
                Assignment /*?*/ assignment = expressionStatement.Expression as Assignment;
                if (assignment != null)
                {
                    var pop2 = assignment.Source as Pop;
                    if (pop2 != null)
                    {
                        assignment.Source = createArray;
                        statements[i]     = expressionStatement;
                        statements.RemoveRange(i + 1, 3);
                        return;
                    }
                }
            }
            push.ValueToPush = createArray;
            statements.RemoveRange(i + 1, 2);
        }
예제 #12
0
        public override void TraverseChildren(IMetadataConstant constant)
{ MethodEnter(constant);
            base.TraverseChildren(constant);
     MethodExit();   }
        private void WriteMetadataConstant(IMetadataConstant constant, ITypeReference constantType = null)
        {
            object value = constant.Value;
            ITypeReference type = (constantType == null ? constant.Type : constantType);

            if (value == null)
            {
                if (type.IsValueType)
                {
                    // Write default(T) for value types
                    WriteDefaultOf(type);
                }
                else
                {
                    WriteKeyword("null", noSpace: true);
                }
            }
            else if (type.ResolvedType.IsEnum)
            {
                //TODO: Do a better job translating the Enum value.
                WriteSymbol("(");
                WriteTypeName(type, noSpace: true);
                WriteSymbol(")");
                WriteSymbol("("); // Wrap value in parens to avoid issues with negative values
                Write(value.ToString());
                WriteSymbol(")");
            }
            else if (value is string)
            {
                Write(QuoteString((string)value));
            }
            else if (value is char)
            {
                Write(String.Format("'{0}'", EscapeChar((char)value, false)));
            }
            else if (value is double)
            {
                double val = (double)value;
                if (double.IsNegativeInfinity(val))
                    Write("-1.0 / 0.0");
                else if (double.IsPositiveInfinity(val))
                    Write("1.0 / 0.0");
                else if (double.IsNaN(val))
                    Write("0.0 / 0.0");
                else
                    Write(((double)value).ToString("R", CultureInfo.InvariantCulture));
            }
            else if (value is float)
            {
                float val = (float)value;
                if (float.IsNegativeInfinity(val))
                    Write("-1.0f / 0.0f");
                else if (float.IsPositiveInfinity(val))
                    Write("1.0f / 0.0f");
                else if (float.IsNaN(val))
                    Write("0.0f / 0.0f");
                else
                    Write(((float)value).ToString("R", CultureInfo.InvariantCulture) + "f");
            }
            else if (value is bool)
            {
                if ((bool)value)
                    WriteKeyword("true", noSpace: true);
                else
                    WriteKeyword("false", noSpace: true);
            }
            else if (value is int)
            {
                // int is the default and most used constant value so lets 
                // special case int to avoid a bunch of useless casts.
                Write(value.ToString());
            }
            else
            {
                // Explicitly cast the value so that we avoid any signed/unsigned resolution issues
                WriteSymbol("(");
                WriteTypeName(type, noSpace: true);
                WriteSymbol(")");
                Write(value.ToString());
            }

            // Might need to add support for other types...
        }
예제 #14
0
 /// <summary>
 /// Traverses the children of the metadata constant.
 /// </summary>
 public virtual void TraverseChildren(IMetadataConstant constant)
 {
     Contract.Requires(constant != null);
       this.TraverseChildren((IMetadataExpression)constant);
 }
예제 #15
0
 /// <summary>
 /// Performs some computation with the given metadata constant.
 /// </summary>
 public virtual void Visit(IMetadataConstant constant)
 {
     this.Visit((IMetadataExpression)constant);
 }
        private void WriteMetadataConstant(IMetadataConstant constant, ITypeReference constantType = null)
        {
            object         value = constant.Value;
            ITypeReference type  = (constantType == null ? constant.Type : constantType);

            if (value == null)
            {
                if (type.IsValueType)
                {
                    // Write default(T) for value types
                    WriteDefaultOf(type);
                }
                else
                {
                    WriteKeyword("null", noSpace: true);
                }
            }
            else if (type.ResolvedType.IsEnum)
            {
                //TODO: Do a better job translating the Enum value.
                WriteSymbol("(");
                WriteTypeName(type, noSpace: true);
                WriteSymbol(")");
                WriteSymbol("("); // Wrap value in parens to avoid issues with negative values
                Write(value.ToString());
                WriteSymbol(")");
            }
            else if (value is string)
            {
                Write(QuoteString((string)value));
            }
            else if (value is char)
            {
                Write(String.Format("'{0}'", EscapeChar((char)value, false)));
            }
            else if (value is double)
            {
                double val = (double)value;
                if (double.IsNegativeInfinity(val))
                {
                    Write("-1.0 / 0.0");
                }
                else if (double.IsPositiveInfinity(val))
                {
                    Write("1.0 / 0.0");
                }
                else if (double.IsNaN(val))
                {
                    Write("0.0 / 0.0");
                }
                else
                {
                    Write(((double)value).ToString("R", CultureInfo.InvariantCulture));
                }
            }
            else if (value is float)
            {
                float val = (float)value;
                if (float.IsNegativeInfinity(val))
                {
                    Write("-1.0f / 0.0f");
                }
                else if (float.IsPositiveInfinity(val))
                {
                    Write("1.0f / 0.0f");
                }
                else if (float.IsNaN(val))
                {
                    Write("0.0f / 0.0f");
                }
                else
                {
                    Write(((float)value).ToString("R", CultureInfo.InvariantCulture) + "f");
                }
            }
            else if (value is bool)
            {
                if ((bool)value)
                {
                    WriteKeyword("true", noSpace: true);
                }
                else
                {
                    WriteKeyword("false", noSpace: true);
                }
            }
            else if (value is int)
            {
                // int is the default and most used constant value so lets
                // special case int to avoid a bunch of useless casts.
                Write(value.ToString());
            }
            else
            {
                // Explicitly cast the value so that we avoid any signed/unsigned resolution issues
                WriteSymbol("(");
                WriteTypeName(type, noSpace: true);
                WriteSymbol(")");
                Write(value.ToString());
            }

            // Might need to add support for other types...
        }
예제 #17
0
 private static ulong ConvertToUlong(IMetadataConstant c) {
   Contract.Requires(c != null);
   IConvertible/*?*/ ic = c.Value as IConvertible;
   if (ic == null) return 0; //TODO: error
   switch (ic.GetTypeCode()) {
     case TypeCode.SByte:
     case TypeCode.Int16:
     case TypeCode.Int32:
     case TypeCode.Int64:
       return (ulong)ic.ToInt64(null); //TODO: error if < 0
     case TypeCode.Byte:
     case TypeCode.UInt16:
     case TypeCode.UInt32:
     case TypeCode.UInt64:
       return ic.ToUInt64(null);
   }
   return 0; //TODO: error
 }
예제 #18
0
 public override void TraverseChildren(IMetadataConstant constant) {
   //The type should already be filled in
 }
 /// <summary>
 /// Rewrites the given metadata constant.
 /// </summary>
 public virtual IMetadataConstant Rewrite(IMetadataConstant constant)
 {
     return constant;
 }
예제 #20
0
 public override void Visit(IMetadataConstant constant) {
   this.value = constant.Value;
 }
예제 #21
0
 public override void Visit(IMetadataConstant constant)
 {
     allElements.Add(new InvokInfo(Traverser, "IMetadataConstant", constant));
 }
예제 #22
0
        private void WriteEnumValue(IMetadataConstant constant, ITypeReference constantType = null)
        {
            ITypeReference enumType     = (constantType == null ? constant.Type : constantType);
            var            resolvedType = enumType.ResolvedType;

            if (resolvedType != null)
            {
                // First look for exact match
                foreach (var enumField in resolvedType.Fields)
                {
                    var enumFieldValue = enumField?.Constant?.Value;
                    if (enumFieldValue != null && enumFieldValue.Equals(constant.Value))
                    {
                        WriteTypeName(enumType, noSpace: true);
                        WriteSymbol(".");
                        WriteIdentifier(enumField.Name);
                        return;
                    }
                }

                // if flags and we didn't find an exact match, find a combination of flags that match
                if (resolvedType.Attributes.Any(a => a.Type.GetTypeName() == "System.FlagsAttribute"))
                {
                    ulong value          = ToULongUnchecked(constant.Value);
                    ulong satisfiedValue = 0;

                    // keep track of candidate flags
                    List <IFieldDefinition> candidateFlagFields = new List <IFieldDefinition>();

                    // ensure stable sort
                    IEnumerable <IFieldDefinition> sortedFields = resolvedType.Fields.OrderBy(f => f.Name.Value, StringComparer.OrdinalIgnoreCase);

                    foreach (var candidateFlagField in sortedFields)
                    {
                        object candidateFlagObj = candidateFlagField?.Constant?.Value;
                        if (candidateFlagObj == null)
                        {
                            continue;
                        }

                        ulong candidateFlag = ToULongUnchecked(candidateFlagObj);

                        if ((value & candidateFlag) == candidateFlag)
                        {
                            // reduce: find out if the current flag is better or worse
                            // than any of those we've already seen
                            bool shouldAdd = true;
                            for (int i = 0; i < candidateFlagFields.Count; i++)
                            {
                                ulong otherFlagValue = ToULongUnchecked(candidateFlagFields[i].Constant.Value);

                                ulong intersectingFlagValue = candidateFlag & otherFlagValue;

                                if (intersectingFlagValue == otherFlagValue)
                                {
                                    // other flag is completely redundant
                                    // remove it, but continue looking as other
                                    // flags may also be redundant
                                    candidateFlagFields.RemoveAt(i--);
                                }
                                else if (intersectingFlagValue == candidateFlag)
                                {
                                    // this flag is redundant, don't add it and stop
                                    // comparing
                                    shouldAdd = false;
                                    break;
                                }
                            }

                            if (shouldAdd)
                            {
                                candidateFlagFields.Add(candidateFlagField);
                                satisfiedValue |= candidateFlag;

                                if (value == satisfiedValue)
                                {
                                    break;
                                }
                            }
                        }
                    }

                    // we found a valid combination of flags
                    if (value == satisfiedValue && candidateFlagFields.Count > 0)
                    {
                        for (int i = 0; i < candidateFlagFields.Count; i++)
                        {
                            if (i != 0)
                            {
                                WriteSymbol(" | ");
                            }
                            WriteTypeName(enumType, noSpace: true);
                            WriteSymbol(".");
                            WriteIdentifier(candidateFlagFields[i].Name);
                        }

                        return;
                    }
                }
            }

            if (constant.Value == null || ToULongUnchecked(constant.Value) == 0) // default(T) on an enum is 0
            {
                if (enumType.IsValueType)
                {
                    // Write default(T) for value types
                    WriteDefaultOf(enumType);
                }
                else
                {
                    WriteKeyword("null", noSpace: true);
                }
            }
            else
            {
                // couldn't find a symbol for enum, just cast it
                WriteSymbol("(");
                WriteTypeName(enumType, noSpace: true);
                WriteSymbol(")");
                WriteSymbol("("); // Wrap value in parens to avoid issues with negative values
                Write(constant.Value.ToString());
                WriteSymbol(")");
            }
        }
예제 #23
0
 public virtual void Visit(IMetadataConstant constant)
 {
 }
예제 #24
0
      /// <summary>
      /// Returns true if the given compile time constant does not match the type of the definition that it provides the initial value for.
      /// </summary>
      private static bool CompileTimeConstantTypeDoesNotMatchDefinitionType(IMetadataConstant compileTimeConstant, ITypeReference definitionType) {
        Contract.Requires(compileTimeConstant != null);
        Contract.Requires(definitionType != null);

        if (TypeHelper.TypesAreEquivalent(compileTimeConstant.Type, definitionType)) return false;
        if (definitionType.IsEnum || definitionType.ResolvedType.IsEnum)
          return CompileTimeConstantTypeDoesNotMatchDefinitionType(compileTimeConstant, definitionType.ResolvedType.UnderlyingType);
        if (compileTimeConstant.Value == null && TypeHelper.TypesAreEquivalent(compileTimeConstant.Type, compileTimeConstant.Type.PlatformType.SystemObject)) {
          if (definitionType.IsValueType || definitionType.ResolvedType.IsValueType) {
            var genericInstance = definitionType as IGenericTypeInstanceReference;
            if (genericInstance == null) return true;
            return !TypeHelper.TypesAreEquivalent(genericInstance.GenericType, definitionType.PlatformType.SystemNullable);
          }
          return false;
        }
        return true;
      }
예제 #25
0
 public virtual void onMetadataElement(IMetadataConstant constant) { }
예제 #26
0
 /// <summary>
 /// Traverses the metadata constant.
 /// </summary>
 public void Traverse(IMetadataConstant constant)
 {
     Contract.Requires(constant != null);
       if (this.preorderVisitor != null) this.preorderVisitor.Visit(constant);
       if (this.stopTraversal) return;
       this.TraverseChildren(constant);
       if (this.stopTraversal) return;
       if (this.postorderVisitor != null) this.postorderVisitor.Visit(constant);
 }
 public override void Visit(IMetadataConstant constant)
 {
     if(Process(constant)){visitor.Visit(constant);}
     base.Visit(constant);
 }
예제 #28
0
 public void Visit(IMetadataConstant constant)
 {
     this.traverser.Traverse(constant);
 }
예제 #29
0
 public override void TraverseChildren(IMetadataConstant constant)
 {
     //The type should already be filled in
 }
예제 #30
0
 //^ ensures this.path.Count == old(this.path.Count);
 /// <summary>
 /// Performs some computation with the given metadata constant.
 /// </summary>
 /// <param name="constant"></param>
 public virtual void Visit(IMetadataConstant constant)
 {
 }
예제 #31
0
 /// <summary>
 /// Performs some computation with the given metadata constant.
 /// </summary>
 /// <param name="constant"></param>
 public virtual void Visit(IMetadataConstant constant)
   //^ ensures this.path.Count == old(this.path.Count);
 {
 }
예제 #32
0
 /// <summary>
 /// Performs some computation with the given metadata constant.
 /// </summary>
 public void Visit(IMetadataConstant constant)
 {
     this.Visit((IMetadataExpression)constant);
     ITypeReference ctype = constant.Type;
     var rctype = constant.Type.ResolvedType;
     if (rctype != Dummy.Type) {
       if (rctype.IsEnum)
     ctype = rctype.UnderlyingType;
       else
     ctype = rctype;
     }
     bool validValue = false;
     switch (ctype.TypeCode) {
       case PrimitiveTypeCode.Boolean:
     validValue = constant.Value is bool; break;
       case PrimitiveTypeCode.Char:
     validValue = constant.Value is char; break;
       case PrimitiveTypeCode.Int8:
     validValue = constant.Value is sbyte; break;
       case PrimitiveTypeCode.UInt8:
     validValue = constant.Value is byte; break;
       case PrimitiveTypeCode.Int16:
     validValue = constant.Value is short; break;
       case PrimitiveTypeCode.UInt16:
     validValue = constant.Value is ushort; break;
       case PrimitiveTypeCode.Int32:
     validValue = constant.Value is int; break;
       case PrimitiveTypeCode.UInt32:
     validValue = constant.Value is uint; break;
       case PrimitiveTypeCode.Int64:
     validValue = constant.Value is long; break;
       case PrimitiveTypeCode.UInt64:
     validValue = constant.Value is ulong; break;
       case PrimitiveTypeCode.Float32:
     validValue = constant.Value is float; break;
       case PrimitiveTypeCode.Float64:
     validValue = constant.Value is double; break;
       case PrimitiveTypeCode.String:
     validValue = constant.Value is string || constant.Value == null; break;
       case PrimitiveTypeCode.NotPrimitive:
     validValue = constant.Value == null || rctype == Dummy.Type; break; //TODO: check that value can be enum val
     }
     if (!validValue)
       this.ReportError(MetadataError.InvalidMetadataConstant, constant);
 }
예제 #33
0
        /// <summary>
        /// Uses Arithmetic and Boolean laws to simplify expressions.
        /// </summary>
        /// <typeparam name="Instruction"></typeparam>
        /// <param name="instruction"></param>
        /// <param name="mappings"></param>
        /// <param name="canonicalizer"></param>
        /// <returns></returns>
        internal static Instruction SimplifyBinary <Instruction>(Instruction instruction, ValueMappings <Instruction> mappings, ExpressionCanonicalizer <Instruction> canonicalizer)
            where Instruction : Microsoft.Cci.Analysis.Instruction, new()
        {
            Contract.Requires(instruction != null);
            Contract.Requires(mappings != null);
            Contract.Requires(canonicalizer != null);
            Contract.Ensures(Contract.Result <Instruction>() != null);

            var operation = instruction.Operation;

            Contract.Assume(instruction.Operand1 is Instruction);
            var operand1 = (Instruction)instruction.Operand1;

            Contract.Assume(instruction.Operand2 is Instruction);
            var operand2 = (Instruction)instruction.Operand2;
            IMetadataConstant constantResult = null;
            var compileTimeConstant1         = mappings.GetCompileTimeConstantValueFor(operand1);
            var compileTimeConstant2         = mappings.GetCompileTimeConstantValueFor(operand2);

            if (compileTimeConstant1 != null)
            {
                if (compileTimeConstant2 != null)
                {
                    constantResult = Evaluator.Evaluate(instruction.Operation, compileTimeConstant1, compileTimeConstant2);
                }
                else
                {
                    constantResult = Evaluator.Evaluate(instruction.Operation, compileTimeConstant1, operand2, mappings);
                }
            }
            else if (compileTimeConstant2 != null)
            {
                constantResult = Evaluator.Evaluate(instruction.Operation, operand1, compileTimeConstant2, mappings);
            }
            else
            {
                constantResult = Evaluator.Evaluate(instruction.Operation, operand1, operand2, mappings);
            }
            if (constantResult != null)
            {
                return(canonicalizer.GetAsCanonicalizedLoadConstant(constantResult, instruction));
            }

            //If we get here, the instruction does not simplify to a constant, but it could still simplify to a simpler expression.
            bool operand1IsZero     = compileTimeConstant1 != null && MetadataExpressionHelper.IsIntegralZero(compileTimeConstant1);
            bool operand1IsOne      = compileTimeConstant1 != null && (operand1IsZero ? false : MetadataExpressionHelper.IsIntegralOne(compileTimeConstant1));
            bool operand1IsMinusOne = compileTimeConstant1 != null && ((operand1IsZero || operand1IsOne) ? false : MetadataExpressionHelper.IsIntegralMinusOne(compileTimeConstant1));
            bool operand2IsZero     = compileTimeConstant2 != null && MetadataExpressionHelper.IsIntegralZero(compileTimeConstant2);
            bool operand2IsOne      = compileTimeConstant2 != null && (operand1IsZero ? false : MetadataExpressionHelper.IsIntegralOne(compileTimeConstant2));
            bool operand2IsMinusOne = compileTimeConstant2 != null && ((operand2IsZero || operand2IsOne) ? false : MetadataExpressionHelper.IsIntegralMinusOne(compileTimeConstant2));

            operand1 = Simplify(operand1, mappings, canonicalizer);
            operand2 = Simplify(operand2, mappings, canonicalizer);

            switch (operation.OperationCode)
            {
            case OperationCode.Add:
            case OperationCode.Add_Ovf:
            case OperationCode.Add_Ovf_Un:
                if (operand1IsZero)
                {
                    return(operand2);
                }
                if (operand2IsZero)
                {
                    return(operand1);
                }
                //TODO: factor out common mults/divs/etc (subject to overflow checks).
                break;

            case OperationCode.And:
                if (operand1IsZero)
                {
                    return(operand1);
                }
                if (operand2IsZero)
                {
                    return(operand2);
                }
                if (operand1IsMinusOne)
                {
                    return(operand2);
                }
                if (operand2IsMinusOne)
                {
                    return(operand1);
                }
                if (operand1.Operation.OperationCode == OperationCode.Not && operand2.Operation.OperationCode == OperationCode.Not)
                {
                    var opnd11 = operand1.Operand1 as Instruction;
                    var opnd21 = operand2.Operand1 as Instruction;
                    Contract.Assume(opnd11 != null && opnd21 != null);
                    var or = new Operation()
                    {
                        OperationCode = OperationCode.Or, Location = operation.Location, Offset = operation.Offset
                    };
                    var orInst = new Instruction()
                    {
                        Operation = or, Operand1 = opnd11, Operand2 = opnd21, Type = instruction.Type
                    };
                    var not = new Operation {
                        OperationCode = OperationCode.Not, Location = operation.Location, Offset = operation.Offset
                    };
                    return(new Instruction()
                    {
                        Operation = not, Operand1 = orInst, Type = instruction.Type
                    });
                }
                break;

            case OperationCode.Ceq:
                //If one of the operands is const 0 and the other is a boolean expression, invert the boolean expression
                if (operand2IsZero && operand1.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    var not = new Operation()
                    {
                        Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Not
                    };
                    instruction = new Instruction()
                    {
                        Operation = not, Operand1 = operand1, Type = instruction.Type
                    };
                    return(SimplifyUnary(instruction, mappings, canonicalizer));
                }
                else if (operand1IsZero && operand2.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    var not = new Operation()
                    {
                        Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Not
                    };
                    instruction = new Instruction()
                    {
                        Operation = not, Operand1 = operand2, Type = instruction.Type
                    };
                    return(SimplifyUnary(instruction, mappings, canonicalizer));
                }
                else
                {
                    operation = new Operation()
                    {
                        Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Beq
                    };
                }
                break;

            case OperationCode.Cgt:
                operation = new Operation()
                {
                    Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Bgt
                };
                break;

            case OperationCode.Cgt_Un:
                operation = new Operation()
                {
                    Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Bgt_Un
                };
                break;

            case OperationCode.Clt:
                operation = new Operation()
                {
                    Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Blt
                };
                break;

            case OperationCode.Clt_Un:
                operation = new Operation()
                {
                    Location = instruction.Operation.Location, Offset = instruction.Operation.Offset, OperationCode = OperationCode.Blt_Un
                };
                break;

            case OperationCode.Div:
            case OperationCode.Div_Un:
                if (operand2IsOne)
                {
                    return(operand1);
                }
                break;

            case OperationCode.Mul:
            case OperationCode.Mul_Ovf:
            case OperationCode.Mul_Ovf_Un:
                if (operand1IsOne)
                {
                    return(operand2);
                }
                if (operand2IsOne)
                {
                    return(operand1);
                }
                break;

            case OperationCode.Or:
                if (operand1IsZero)
                {
                    return(operand2);
                }
                if (operand2IsZero)
                {
                    return(operand1);
                }
                if (operand1.Operation.OperationCode == OperationCode.Not && operand2.Operation.OperationCode == OperationCode.Not)
                {
                    var opnd11 = operand1.Operand1 as Instruction;
                    var opnd21 = operand2.Operand1 as Instruction;
                    Contract.Assume(opnd11 != null && opnd21 != null);
                    var and = new Operation()
                    {
                        OperationCode = OperationCode.And, Location = operation.Location, Offset = operation.Offset
                    };
                    var andInst = new Instruction()
                    {
                        Operation = and, Operand1 = opnd11, Operand2 = opnd21, Type = instruction.Type
                    };
                    var not = new Operation {
                        OperationCode = OperationCode.Not, Location = operation.Location, Offset = operation.Offset
                    };
                    return(new Instruction()
                    {
                        Operation = not, Operand1 = andInst, Type = instruction.Type
                    });
                }
                if (operand1.Operand1 == operand2.Operand1 && operand1.Operand2 == operand2.Operand2 &&
                    operand1.Operation.OperationCode != operand2.Operation.OperationCode && operand2.Operand1 != null &&
                    operand1.Operation.OperationCode == GetInverse(operand2.Operation.OperationCode,
                                                                   operand2.Operand1.Type.TypeCode == PrimitiveTypeCode.Float32 || operand2.Operand1.Type.TypeCode == PrimitiveTypeCode.Float64))
                {
                    return(canonicalizer.GetAsCanonicalizedLoadConstant(new MetadataConstant()
                    {
                        Value = true, Type = instruction.Type
                    }, instruction));
                }
                break;

            case OperationCode.Rem:
            case OperationCode.Rem_Un:
                break;

            case OperationCode.Shl:
            case OperationCode.Shr:
            case OperationCode.Shr_Un:
                if (operand2IsZero)
                {
                    return(operand1);
                }
                break;

            case OperationCode.Sub:
            case OperationCode.Sub_Ovf:
            case OperationCode.Sub_Ovf_Un:
                if (operand2IsZero)
                {
                    return(operand1);
                }
                break;

            case OperationCode.Xor:
                break;

            case OperationCode.Beq:
            case OperationCode.Beq_S:
                if (operand1IsZero && operand2.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    var operand2inv = TryToGetSimplerLogicalInverse(operand2);
                    if (operand2inv != null)
                    {
                        return(operand2inv);
                    }
                }
                else if (operand2IsZero && operand1.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    var operand1inv = TryToGetSimplerLogicalInverse(operand1);
                    if (operand1inv != null)
                    {
                        return(operand1inv);
                    }
                }
                goto case OperationCode.Bge_S;

            case OperationCode.Bne_Un:
            case OperationCode.Bne_Un_S:
                if (operand1IsZero && operand2.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    return(operand2);
                }
                if (operand2IsZero && operand1.Type.TypeCode == PrimitiveTypeCode.Boolean)
                {
                    return(operand1);
                }
                goto case OperationCode.Bge_S;

            case OperationCode.Bge_S:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un_S:
                operation = new Operation()
                {
                    Location      = operation.Location, Offset = operation.Offset,
                    OperationCode = LongVersionOf(operation.OperationCode), Value = operation.Value
                };
                break;
            }
            if (operation != instruction.Operation || operand1 != instruction.Operand1 || operand2 != instruction.Operand2)
            {
                return new Instruction()
                       {
                           Operation = operation, Operand1 = operand1, Operand2 = operand2, Type = instruction.Type
                       }
            }
            ;
            return(instruction);
        }
 public override void TraverseChildren(IMetadataConstant constant) {
   var val = constant.Value;
   if (val == null)
     this.PrintToken(CSharpToken.Null);
   else if (constant.Type.ResolvedType.IsEnum)
     PrintEnumValue(constant.Type.ResolvedType, val);
   else if (val is string)
     PrintString((string)val);
   else if (val is bool)
     PrintToken((bool)val ? CSharpToken.True : CSharpToken.False);
   else if (val is char)
     this.sourceEmitterOutput.Write(String.Format("'{0}'", EscapeChar((char)val, false)));
   else if (val is float)
     PrintFloat((float)val);
   else if (val is double)
     PrintDouble((double)val);
   else if (val is int)
     PrintInt((int)val);
   else if (val is uint)
     PrintUint((uint)val);
   else if (val is long)
     PrintLong((long)val);
   else if (val is ulong)
     PrintUlong((ulong)val);
   else
     this.sourceEmitterOutput.Write(constant.Value.ToString());
 }
예제 #35
0
 public virtual void onMetadataElement(IMetadataConstant constant)
 {
 }
예제 #36
0
 public override void TraverseChildren(IMetadataConstant constant)
 {
     MethodEnter(constant);
     base.TraverseChildren(constant);
     MethodExit();
 }
예제 #37
0
 /// <summary>
 /// Traverses the children of the metadata constant.
 /// </summary>
 public virtual void TraverseChildren(IMetadataConstant constant)
 {
     this.TraverseChildren((IMetadataExpression)constant);
 }