internal static FindResult CanExtendNamedArgument(Block block, ILVariable v, ILInstruction expressionBeingMoved) { Debug.Assert(block.Kind == BlockKind.CallWithNamedArgs); var firstArg = ((StLoc)block.Instructions[0]).Value; var r = ILInlining.FindLoadInNext(firstArg, v, expressionBeingMoved, InliningOptions.IntroduceNamedArguments); if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) { return(r); // OK, inline into first instruction of block } var call = (CallInstruction)block.FinalInstruction; if (call.IsInstanceCall) { // For instance calls, block.Instructions[0] is the argument // for the 'this' pointer. We can only insert at position 1. if (r.Type == FindResultType.Stop) { // error: can't move expressionBeingMoved after block.Instructions[0] return(FindResult.Stop); } // Because we always ensure block.Instructions[0] is the 'this' argument, // it's possible that the place we actually need to inline into // is within block.Instructions[1]: if (block.Instructions.Count > 1) { r = ILInlining.FindLoadInNext(block.Instructions[1], v, expressionBeingMoved, InliningOptions.IntroduceNamedArguments); if (r.Type == FindResultType.Found || r.Type == FindResultType.NamedArgument) { return(r); // OK, inline into block.Instructions[1] } } } foreach (var arg in call.Arguments) { if (arg.MatchLdLoc(v)) { return(FindResult.NamedArgument(arg, arg)); } } return(FindResult.Stop); }
internal static FindResult CanIntroduceNamedArgument(CallInstruction call, ILInstruction child, ILVariable v, ILInstruction expressionBeingMoved) { Debug.Assert(child.Parent == call); if (call.IsInstanceCall && child.ChildIndex == 0) { return(FindResult.Stop); // cannot use named arg to move expressionBeingMoved before this pointer } if (call.Method.IsOperator || call.Method.IsAccessor) { return(FindResult.Stop); // cannot use named arg for operators or accessors } if (call.Method is VarArgInstanceMethod) { return(FindResult.Stop); // CallBuilder doesn't support named args when using varargs } if (call.Method.IsConstructor) { IType type = call.Method.DeclaringType; if (type.Kind == TypeKind.Delegate || type.IsAnonymousType()) { return(FindResult.Stop); } } if (call.Method.Parameters.Any(p => string.IsNullOrEmpty(p.Name))) { return(FindResult.Stop); // cannot use named arguments } for (int i = child.ChildIndex; i < call.Arguments.Count; i++) { var r = ILInlining.FindLoadInNext(call.Arguments[i], v, expressionBeingMoved, InliningOptions.None); if (r.Type == FindResultType.Found) { return(FindResult.NamedArgument(r.LoadInst, call.Arguments[i])); } } return(FindResult.Stop); }