예제 #1
0
        public static void Transform(ILBlock method)
        {
            // TODO: move this somewhere else
            // Eliminate 'dups':
            foreach (ILExpression expr in method.GetSelfAndChildrenRecursive<ILExpression>()) {
                for (int i = 0; i < expr.Arguments.Count; i++) {
                    if (expr.Arguments[i].Code == ILCode.Dup)
                        expr.Arguments[i] = expr.Arguments[i].Arguments[0];
                }
            }

            var newArrPattern = new StoreToVariable(new ILExpression(ILCode.Newarr, ILExpression.AnyOperand, new ILExpression(ILCode.Ldc_I4, ILExpression.AnyOperand)));
            var arg1 = new StoreToVariable(new LoadFromVariable(newArrPattern)) { MustBeGenerated = true };
            var arg2 = new StoreToVariable(new LoadFromVariable(newArrPattern)) { MustBeGenerated = true };
            var initializeArrayPattern = new ILCall(
                "System.Runtime.CompilerServices.RuntimeHelpers", "InitializeArray",
                new LoadFromVariable(arg1), new ILExpression(ILCode.Ldtoken, ILExpression.AnyOperand));
            foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>()) {
                for (int i = block.Body.Count - 1; i >= 0; i--) {
                    if (!newArrPattern.Match(block.Body[i]))
                        continue;
                    ILExpression newArrInst = ((ILExpression)block.Body[i]).Arguments[0];
                    int arrayLength = (int)newArrInst.Arguments[0].Operand;
                    if (arrayLength == 0)
                        continue;
                    if (arg1.Match(block.Body.ElementAtOrDefault(i + 1)) && arg2.Match(block.Body.ElementAtOrDefault(i + 2))) {
                        if (initializeArrayPattern.Match(block.Body.ElementAtOrDefault(i + 3))) {
                            if (HandleStaticallyInitializedArray(arg2, block, i, newArrInst, arrayLength)) {
                                i -= ILInlining.InlineInto(block, i + 1, method) - 1;
                            }
                            continue;
                        }
                    }
                    if (i + 1 + arrayLength > block.Body.Count)
                        continue;
                    List<ILExpression> operands = new List<ILExpression>();
                    for (int j = 0; j < arrayLength; j++) {
                        ILExpression expr = block.Body[i + 1 + j] as ILExpression;
                        if (expr == null || !IsStoreToArray(expr.Code))
                            break;
                        if (!(expr.Arguments[0].Code == ILCode.Ldloc && expr.Arguments[0].Operand == newArrPattern.LastVariable))
                            break;
                        if (!(expr.Arguments[1].Code == ILCode.Ldc_I4 && (int)expr.Arguments[1].Operand == j))
                            break;
                        operands.Add(expr.Arguments[2]);
                    }
                    if (operands.Count == arrayLength) {
                        ((ILExpression)block.Body[i]).Arguments[0] = new ILExpression(
                            ILCode.InitArray, newArrInst.Operand, operands.ToArray());
                        block.Body.RemoveRange(i + 1, arrayLength);
                        i -= ILInlining.InlineInto(block, i + 1, method) - 1;
                    }
                }
            }
        }
예제 #2
0
 static bool HandleStaticallyInitializedArray(StoreToVariable arg2, ILBlock block, int i, ILExpression newArrInst, int arrayLength)
 {
     FieldDefinition field = ((ILExpression)block.Body[i + 3]).Arguments[1].Operand as FieldDefinition;
     if (field == null || field.InitialValue == null)
         return false;
     switch (TypeAnalysis.GetTypeCode(newArrInst.Operand as TypeReference)) {
         case TypeCode.Int32:
         case TypeCode.UInt32:
             if (field.InitialValue.Length == arrayLength * 4) {
                 ILExpression[] newArr = new ILExpression[arrayLength];
                 for (int j = 0; j < newArr.Length; j++) {
                     newArr[j] = new ILExpression(ILCode.Ldc_I4, BitConverter.ToInt32(field.InitialValue, j * 4));
                 }
                 block.Body[i] = new ILExpression(ILCode.Stloc, arg2.LastVariable, new ILExpression(ILCode.InitArray, newArrInst.Operand, newArr));
                 block.Body.RemoveRange(i + 1, 3);
                 return true;
             }
             break;
     }
     return false;
 }