protected override QilNode VisitInvoke(QilInvoke ndInvoke) {
QilFunction ndFunc = ndInvoke.Function;
MethodInfo methInfo = XmlILAnnotation.Write(ndFunc).FunctionBinding;
bool useWriter = (XmlILConstructInfo.Read(ndFunc).ConstructMethod == XmlILConstructMethod.Writer);
Debug.Assert(!XmlILConstructInfo.Read(ndInvoke).PushToWriterFirst || useWriter);
// Push XmlQueryRuntime onto the stack as the first parameter
this.helper.LoadQueryRuntime();
// Generate code to push each Invoke argument onto the stack
for (int iArg = 0; iArg < ndInvoke.Arguments.Count; iArg++) {
QilNode ndActualArg = ndInvoke.Arguments[iArg];
QilNode ndFormalArg = ndInvoke.Function.Arguments[iArg];
NestedVisitEnsureStack(ndActualArg, GetItemStorageType(ndFormalArg), !ndFormalArg.XmlType.IsSingleton);
}
// Check whether this call should compiled using the .tailcall instruction
if (OptimizerPatterns.Read(ndInvoke).MatchesPattern(OptimizerPatternName.TailCall))
this.helper.TailCall(methInfo);
else
this.helper.Call(methInfo);
// If function's results are not pushed to Writer,
if (!useWriter) {
// Return value is on the stack; ensure it has the correct storage type
this.iterCurr.Storage = StorageDescriptor.Stack(GetItemStorageType(ndInvoke), !ndInvoke.XmlType.IsSingleton);
}
else {
this.iterCurr.Storage = StorageDescriptor.None();
}
return ndInvoke;
}