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); }
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); }