bool DoTransformMultiDim(Block body, int pos)
        {
            if (pos >= body.Instructions.Count - 2)
            {
                return(false);
            }
            ILVariable    v;
            ILInstruction newarrExpr;
            IType         arrayType;

            int[]         length;
            ILInstruction instr = body.Instructions[pos];

            if (instr.MatchStLoc(out v, out newarrExpr) && MatchNewArr(newarrExpr, out arrayType, out length))
            {
                ILInstruction[] values;
                int             initArrayPos;
                if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, arrayType, length, out values, out initArrayPos))
                {
                    var block = BlockFromInitializer(v, arrayType, length, values);
                    body.Instructions[pos].ReplaceWith(new StLoc(v, block));
                    body.Instructions.RemoveAt(initArrayPos);
                    ILInlining.InlineIfPossible(body, pos, context);
                    return(true);
                }
            }
            return(false);
        }
Example #2
0
        public static bool defs(ILInstruction node, ILVariable variable)
        {
            // simple assignement
            if (node.MatchStLoc(variable, out ILInstruction value))
            {
                return(true);
            }

            return(false);
        }
        bool DoTransform(Block body, int pos)
        {
            if (pos >= body.Instructions.Count - 2)
            {
                return(false);
            }
            ILInstruction inst = body.Instructions[pos];
            ILVariable    v;
            ILInstruction newarrExpr;
            IType         elementType;

            int[] arrayLength;
            if (inst.MatchStLoc(out v, out newarrExpr) && MatchNewArr(newarrExpr, out elementType, out arrayLength))
            {
                ILInstruction[] values;
                int             initArrayPos;
                if (ForwardScanInitializeArrayRuntimeHelper(body, pos + 1, v, elementType, arrayLength, out values, out initArrayPos))
                {
                    context.Step("ForwardScanInitializeArrayRuntimeHelper", inst);
                    var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type);
                    var block     = BlockFromInitializer(tempStore, elementType, arrayLength, values);
                    body.Instructions[pos] = new StLoc(v, block);
                    body.Instructions.RemoveAt(initArrayPos);
                    ILInlining.InlineIfPossible(body, pos, context);
                    return(true);
                }
                if (arrayLength.Length == 1)
                {
                    int instructionsToRemove;
                    if (HandleSimpleArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out values, out instructionsToRemove))
                    {
                        context.Step("HandleSimpleArrayInitializer", inst);
                        var block     = new Block(BlockKind.ArrayInitializer);
                        var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type);
                        block.Instructions.Add(new StLoc(tempStore, new NewArr(elementType, arrayLength.Select(l => new LdcI4(l)).ToArray())));
                        block.Instructions.AddRange(values.SelectWithIndex(
                                                        (i, value) => {
                            if (value == null)
                            {
                                value = GetNullExpression(elementType);
                            }
                            return(StElem(new LdLoc(tempStore), new[] { new LdcI4(i) }, value, elementType));
                        }
                                                        ));
                        block.FinalInstruction = new LdLoc(tempStore);
                        body.Instructions[pos] = new StLoc(v, block);
                        body.Instructions.RemoveRange(pos + 1, instructionsToRemove);
                        ILInlining.InlineIfPossible(body, pos, context);
                        return(true);
                    }
                    if (HandleJaggedArrayInitializer(body, pos + 1, v, elementType, arrayLength[0], out ILVariable finalStore, out values, out instructionsToRemove))
                    {
                        context.Step("HandleJaggedArrayInitializer", inst);
                        var block     = new Block(BlockKind.ArrayInitializer);
                        var tempStore = context.Function.RegisterVariable(VariableKind.InitializerTarget, v.Type);
                        block.Instructions.Add(new StLoc(tempStore, new NewArr(elementType, arrayLength.Select(l => new LdcI4(l)).ToArray())));
                        block.Instructions.AddRange(values.SelectWithIndex((i, value) => StElem(new LdLoc(tempStore), new[] { new LdcI4(i) }, value, elementType)));
                        block.FinalInstruction = new LdLoc(tempStore);
                        body.Instructions[pos] = new StLoc(finalStore, block);
                        body.Instructions.RemoveRange(pos + 1, instructionsToRemove);
                        ILInlining.InlineIfPossible(body, pos, context);
                        return(true);
                    }
                }
                // Put in a limit so that we don't consume too much memory if the code allocates a huge array
                // and populates it extremely sparsly. However, 255 "null" elements in a row actually occur in the Mono C# compiler!
//				const int maxConsecutiveDefaultValueExpressions = 300;
//				var operands = new List<ILInstruction>();
//				int numberOfInstructionsToRemove = 0;
//				for (int j = pos + 1; j < body.Instructions.Count; j++) {
//					var nextExpr = body.Instructions[j] as Void;
//					int arrayPos;
//					if (nextExpr != null && nextExpr is a.IsStoreToArray() &&
//					    nextExpr.Arguments[0].Match(ILCode.Ldloc, out v3) &&
//					    v == v3 &&
//					    nextExpr.Arguments[1].Match(ILCode.Ldc_I4, out arrayPos) &&
//					    arrayPos >= operands.Count &&
//					    arrayPos <= operands.Count + maxConsecutiveDefaultValueExpressions &&
//					    !nextExpr.Arguments[2].ContainsReferenceTo(v3))
//					{
//						while (operands.Count < arrayPos)
//							operands.Add(new ILExpression(ILCode.DefaultValue, elementType));
//						operands.Add(nextExpr.Arguments[2]);
//						numberOfInstructionsToRemove++;
//					} else {
//						break;
//					}
//				}
            }
            return(false);
        }