File: System\Xml\Xsl\IlGen\GenerateHelper.cs
Web Access
Project: src\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.Versioning;
using System.Security;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using System.Xml.XPath;
using System.Xml.Xsl.Qil;
using System.Xml.Xsl.Runtime;
 
namespace System.Xml.Xsl.IlGen
{
    /// <summary>
    /// List of all XmlIL runtime constructors.
    /// </summary>
    [RequiresDynamicCode("Calls MakeGenericType on value types")]
    internal sealed class XmlILStorageMethods
    {
        // Aggregates
        public readonly MethodInfo? AggAvg;
        public readonly MethodInfo? AggAvgResult;
        public readonly MethodInfo? AggCreate;
        public readonly MethodInfo? AggIsEmpty;
        public readonly MethodInfo? AggMax;
        public readonly MethodInfo? AggMaxResult;
        public readonly MethodInfo? AggMin;
        public readonly MethodInfo? AggMinResult;
        public readonly MethodInfo? AggSum;
        public readonly MethodInfo? AggSumResult;
 
        // Sequences
        public readonly Type SeqType;
        public readonly FieldInfo SeqEmpty;
        public readonly MethodInfo SeqReuse;
        public readonly MethodInfo SeqReuseSgl;
        public readonly MethodInfo SeqAdd;
        public readonly MethodInfo SeqSortByKeys;
 
        // IList<>
        public readonly Type IListType;
        public readonly MethodInfo IListCount;
        public readonly MethodInfo IListItem;
 
        // XPathItem
        public readonly MethodInfo? ValueAs;
 
        // ToAtomicValue
        public readonly MethodInfo? ToAtomicValue;
 
        public XmlILStorageMethods(Type storageType)
        {
            // Aggregates
            Type? aggType = null;
            if (storageType == typeof(int))
            {
                aggType = typeof(Int32Aggregator);
            }
            else if (storageType == typeof(long))
            {
                aggType = typeof(Int64Aggregator);
            }
            else if (storageType == typeof(decimal))
            {
                aggType = typeof(DecimalAggregator);
            }
            else if (storageType == typeof(double))
            {
                aggType = typeof(DoubleAggregator);
            }
 
            if (aggType != null)
            {
                AggAvg = aggType.GetMethod("Average");
                AggAvgResult = aggType.GetMethod("get_AverageResult");
                AggCreate = aggType.GetMethod("Create");
                AggIsEmpty = aggType.GetMethod("get_IsEmpty");
                AggMax = aggType.GetMethod("Maximum");
                AggMaxResult = aggType.GetMethod("get_MaximumResult");
                AggMin = aggType.GetMethod("Minimum");
                AggMinResult = aggType.GetMethod("get_MinimumResult");
                AggSum = aggType.GetMethod("Sum");
                AggSumResult = aggType.GetMethod("get_SumResult");
            }
 
            // Sequences
            // use local 'sequenceType' variable to work around https://github.com/mono/linker/issues/1664
            Type sequenceType;
            if (storageType == typeof(XPathNavigator))
            {
                sequenceType = typeof(XmlQueryNodeSequence);
                SeqAdd = sequenceType.GetMethod("AddClone")!;
            }
            else if (storageType == typeof(XPathItem))
            {
                sequenceType = typeof(XmlQueryItemSequence);
                SeqAdd = sequenceType.GetMethod("AddClone")!;
            }
            else
            {
                sequenceType = typeof(XmlQuerySequence<>).MakeGenericType(storageType);
                SeqAdd = sequenceType.GetMethod("Add")!;
            }
 
            FieldInfo? seqEmpty = sequenceType.GetField("Empty");
            Debug.Assert(seqEmpty != null, "Field `Empty` could not be found");
            SeqEmpty = seqEmpty;
            SeqReuse = sequenceType.GetMethod("CreateOrReuse", new[] { sequenceType })!;
            SeqReuseSgl = sequenceType.GetMethod("CreateOrReuse", new[] { sequenceType, storageType })!;
            SeqSortByKeys = sequenceType.GetMethod("SortByKeys")!;
            SeqType = sequenceType;
 
            // IList<>
            Type listType = typeof(IList<>).MakeGenericType(storageType);
            IListItem = listType.GetMethod("get_Item")!;
            IListType = listType;
            IListCount = typeof(ICollection<>).MakeGenericType(storageType).GetMethod("get_Count")!;
 
            // XPathItem.ValueAsXXX
            if (storageType == typeof(string))
                ValueAs = typeof(XPathItem).GetMethod("get_Value");
            else if (storageType == typeof(int))
                ValueAs = typeof(XPathItem).GetMethod("get_ValueAsInt");
            else if (storageType == typeof(long))
                ValueAs = typeof(XPathItem).GetMethod("get_ValueAsLong");
            else if (storageType == typeof(DateTime))
                ValueAs = typeof(XPathItem).GetMethod("get_ValueAsDateTime");
            else if (storageType == typeof(double))
                ValueAs = typeof(XPathItem).GetMethod("get_ValueAsDouble");
            else if (storageType == typeof(bool))
                ValueAs = typeof(XPathItem).GetMethod("get_ValueAsBoolean");
 
            // XmlILStorageConverter.XXXToAtomicValue
            if (storageType == typeof(byte[]))
                ToAtomicValue = typeof(XmlILStorageConverter).GetMethod("BytesToAtomicValue");
            else if (storageType != typeof(XPathItem) && storageType != typeof(XPathNavigator))
                ToAtomicValue = typeof(XmlILStorageConverter).GetMethod($"{storageType.Name}ToAtomicValue");
        }
    }
 
    /// <summary>
    /// List of all XmlIL runtime constructors.
    /// </summary>
    internal static class XmlILConstructors
    {
        public static readonly ConstructorInfo DecFromParts = typeof(decimal).GetConstructor(new[] { typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte) })!;
        public static readonly ConstructorInfo DecFromInt32 = typeof(decimal).GetConstructor(new[] { typeof(int) })!;
        public static readonly ConstructorInfo DecFromInt64 = typeof(decimal).GetConstructor(new[] { typeof(long) })!;
        public static readonly ConstructorInfo Debuggable = typeof(DebuggableAttribute).GetConstructor(new[] { typeof(DebuggableAttribute.DebuggingModes) })!;
        public static readonly ConstructorInfo NonUserCode = typeof(DebuggerNonUserCodeAttribute).GetConstructor(Type.EmptyTypes)!;
        public static readonly ConstructorInfo QName = typeof(XmlQualifiedName).GetConstructor(new[] { typeof(string), typeof(string) })!;
        public static readonly ConstructorInfo StepThrough = typeof(DebuggerStepThroughAttribute).GetConstructor(Type.EmptyTypes)!;
        public static readonly ConstructorInfo Transparent = typeof(SecurityTransparentAttribute).GetConstructor(Type.EmptyTypes)!;
    }
 
    /// <summary>
    /// List of all XmlIL runtime methods.
    /// </summary>
    [RequiresDynamicCode("Calls MakeGenericType on value types")]
    internal static class XmlILMethods
    {
        // Iterators
        public static readonly MethodInfo AncCreate = typeof(AncestorIterator).GetMethod("Create")!;
        public static readonly MethodInfo AncNext = typeof(AncestorIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo AncCurrent = typeof(AncestorIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo AncDOCreate = typeof(AncestorDocOrderIterator).GetMethod("Create")!;
        public static readonly MethodInfo AncDONext = typeof(AncestorDocOrderIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo AncDOCurrent = typeof(AncestorDocOrderIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo AttrContentCreate = typeof(AttributeContentIterator).GetMethod("Create")!;
        public static readonly MethodInfo AttrContentNext = typeof(AttributeContentIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo AttrContentCurrent = typeof(AttributeContentIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo AttrCreate = typeof(AttributeIterator).GetMethod("Create")!;
        public static readonly MethodInfo AttrNext = typeof(AttributeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo AttrCurrent = typeof(AttributeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo ContentCreate = typeof(ContentIterator).GetMethod("Create")!;
        public static readonly MethodInfo ContentNext = typeof(ContentIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo ContentCurrent = typeof(ContentIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo ContentMergeCreate = typeof(ContentMergeIterator).GetMethod("Create")!;
        public static readonly MethodInfo ContentMergeNext = typeof(ContentMergeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo ContentMergeCurrent = typeof(ContentMergeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo DescCreate = typeof(DescendantIterator).GetMethod("Create")!;
        public static readonly MethodInfo DescNext = typeof(DescendantIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo DescCurrent = typeof(DescendantIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo DescMergeCreate = typeof(DescendantMergeIterator).GetMethod("Create")!;
        public static readonly MethodInfo DescMergeNext = typeof(DescendantMergeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo DescMergeCurrent = typeof(DescendantMergeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo DiffCreate = typeof(DifferenceIterator).GetMethod("Create")!;
        public static readonly MethodInfo DiffNext = typeof(DifferenceIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo DiffCurrent = typeof(DifferenceIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo DodMergeCreate = typeof(DodSequenceMerge).GetMethod("Create")!;
        public static readonly MethodInfo DodMergeAdd = typeof(DodSequenceMerge).GetMethod("AddSequence")!;
        public static readonly MethodInfo DodMergeSeq = typeof(DodSequenceMerge).GetMethod("MergeSequences")!;
        public static readonly MethodInfo ElemContentCreate = typeof(ElementContentIterator).GetMethod("Create")!;
        public static readonly MethodInfo ElemContentNext = typeof(ElementContentIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo ElemContentCurrent = typeof(ElementContentIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo FollSibCreate = typeof(FollowingSiblingIterator).GetMethod("Create")!;
        public static readonly MethodInfo FollSibNext = typeof(FollowingSiblingIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo FollSibCurrent = typeof(FollowingSiblingIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo FollSibMergeCreate = typeof(FollowingSiblingMergeIterator).GetMethod("Create")!;
        public static readonly MethodInfo FollSibMergeNext = typeof(FollowingSiblingMergeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo FollSibMergeCurrent = typeof(FollowingSiblingMergeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo IdCreate = typeof(IdIterator).GetMethod("Create")!;
        public static readonly MethodInfo IdNext = typeof(IdIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo IdCurrent = typeof(IdIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo InterCreate = typeof(IntersectIterator).GetMethod("Create")!;
        public static readonly MethodInfo InterNext = typeof(IntersectIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo InterCurrent = typeof(IntersectIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo KindContentCreate = typeof(NodeKindContentIterator).GetMethod("Create")!;
        public static readonly MethodInfo KindContentNext = typeof(NodeKindContentIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo KindContentCurrent = typeof(NodeKindContentIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo NmspCreate = typeof(NamespaceIterator).GetMethod("Create")!;
        public static readonly MethodInfo NmspNext = typeof(NamespaceIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo NmspCurrent = typeof(NamespaceIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo NodeRangeCreate = typeof(NodeRangeIterator).GetMethod("Create")!;
        public static readonly MethodInfo NodeRangeNext = typeof(NodeRangeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo NodeRangeCurrent = typeof(NodeRangeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo ParentCreate = typeof(ParentIterator).GetMethod("Create")!;
        public static readonly MethodInfo ParentNext = typeof(ParentIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo ParentCurrent = typeof(ParentIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo PrecCreate = typeof(PrecedingIterator).GetMethod("Create")!;
        public static readonly MethodInfo PrecNext = typeof(PrecedingIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo PrecCurrent = typeof(PrecedingIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo PreSibCreate = typeof(PrecedingSiblingIterator).GetMethod("Create")!;
        public static readonly MethodInfo PreSibNext = typeof(PrecedingSiblingIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo PreSibCurrent = typeof(PrecedingSiblingIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo PreSibDOCreate = typeof(PrecedingSiblingDocOrderIterator).GetMethod("Create")!;
        public static readonly MethodInfo PreSibDONext = typeof(PrecedingSiblingDocOrderIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo PreSibDOCurrent = typeof(PrecedingSiblingDocOrderIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo SortKeyCreate = typeof(XmlSortKeyAccumulator).GetMethod("Create")!;
        public static readonly MethodInfo SortKeyDateTime = typeof(XmlSortKeyAccumulator).GetMethod("AddDateTimeSortKey")!;
        public static readonly MethodInfo SortKeyDecimal = typeof(XmlSortKeyAccumulator).GetMethod("AddDecimalSortKey")!;
        public static readonly MethodInfo SortKeyDouble = typeof(XmlSortKeyAccumulator).GetMethod("AddDoubleSortKey")!;
        public static readonly MethodInfo SortKeyEmpty = typeof(XmlSortKeyAccumulator).GetMethod("AddEmptySortKey")!;
        public static readonly MethodInfo SortKeyFinish = typeof(XmlSortKeyAccumulator).GetMethod("FinishSortKeys")!;
        public static readonly MethodInfo SortKeyInt = typeof(XmlSortKeyAccumulator).GetMethod("AddIntSortKey")!;
        public static readonly MethodInfo SortKeyInteger = typeof(XmlSortKeyAccumulator).GetMethod("AddIntegerSortKey")!;
        public static readonly MethodInfo SortKeyKeys = typeof(XmlSortKeyAccumulator).GetMethod("get_Keys")!;
        public static readonly MethodInfo SortKeyString = typeof(XmlSortKeyAccumulator).GetMethod("AddStringSortKey")!;
        public static readonly MethodInfo UnionCreate = typeof(UnionIterator).GetMethod("Create")!;
        public static readonly MethodInfo UnionNext = typeof(UnionIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo UnionCurrent = typeof(UnionIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo XPFollCreate = typeof(XPathFollowingIterator).GetMethod("Create")!;
        public static readonly MethodInfo XPFollNext = typeof(XPathFollowingIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo XPFollCurrent = typeof(XPathFollowingIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo XPFollMergeCreate = typeof(XPathFollowingMergeIterator).GetMethod("Create")!;
        public static readonly MethodInfo XPFollMergeNext = typeof(XPathFollowingMergeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo XPFollMergeCurrent = typeof(XPathFollowingMergeIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo XPPrecCreate = typeof(XPathPrecedingIterator).GetMethod("Create")!;
        public static readonly MethodInfo XPPrecNext = typeof(XPathPrecedingIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo XPPrecCurrent = typeof(XPathPrecedingIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo XPPrecDOCreate = typeof(XPathPrecedingDocOrderIterator).GetMethod("Create")!;
        public static readonly MethodInfo XPPrecDONext = typeof(XPathPrecedingDocOrderIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo XPPrecDOCurrent = typeof(XPathPrecedingDocOrderIterator).GetMethod("get_Current")!;
        public static readonly MethodInfo XPPrecMergeCreate = typeof(XPathPrecedingMergeIterator).GetMethod("Create")!;
        public static readonly MethodInfo XPPrecMergeNext = typeof(XPathPrecedingMergeIterator).GetMethod("MoveNext")!;
        public static readonly MethodInfo XPPrecMergeCurrent = typeof(XPathPrecedingMergeIterator).GetMethod("get_Current")!;
 
        // XmlQueryRuntime
        public static readonly MethodInfo AddNewIndex = typeof(XmlQueryRuntime).GetMethod("AddNewIndex")!;
        public static readonly MethodInfo ChangeTypeXsltArg = typeof(XmlQueryRuntime).GetMethod("ChangeTypeXsltArgument", new[] { typeof(int), typeof(object), typeof(Type) })!;
        public static readonly MethodInfo ChangeTypeXsltResult = typeof(XmlQueryRuntime).GetMethod("ChangeTypeXsltResult")!;
        public static readonly MethodInfo CompPos = typeof(XmlQueryRuntime).GetMethod("ComparePosition")!;
        public static readonly MethodInfo Context = typeof(XmlQueryRuntime).GetMethod("get_ExternalContext")!;
        public static readonly MethodInfo CreateCollation = typeof(XmlQueryRuntime).GetMethod("CreateCollation")!;
        public static readonly MethodInfo DocOrder = typeof(XmlQueryRuntime).GetMethod("DocOrderDistinct")!;
        public static readonly MethodInfo EndRtfConstr = typeof(XmlQueryRuntime).GetMethod("EndRtfConstruction")!;
        public static readonly MethodInfo EndSeqConstr = typeof(XmlQueryRuntime).GetMethod("EndSequenceConstruction")!;
        public static readonly MethodInfo FindIndex = typeof(XmlQueryRuntime).GetMethod("FindIndex")!;
        public static readonly MethodInfo GenId = typeof(XmlQueryRuntime).GetMethod("GenerateId")!;
        public static readonly MethodInfo GetAtomizedName = typeof(XmlQueryRuntime).GetMethod("GetAtomizedName")!;
        public static readonly MethodInfo GetCollation = typeof(XmlQueryRuntime).GetMethod("GetCollation")!;
        public static readonly MethodInfo GetEarly = typeof(XmlQueryRuntime).GetMethod("GetEarlyBoundObject")!;
        public static readonly MethodInfo GetNameFilter = typeof(XmlQueryRuntime).GetMethod("GetNameFilter")!;
        public static readonly MethodInfo GetOutput = typeof(XmlQueryRuntime).GetMethod("get_Output")!;
        public static readonly MethodInfo GetGlobalValue = typeof(XmlQueryRuntime).GetMethod("GetGlobalValue")!;
        public static readonly MethodInfo GetTypeFilter = typeof(XmlQueryRuntime).GetMethod("GetTypeFilter")!;
        public static readonly MethodInfo GlobalComputed = typeof(XmlQueryRuntime).GetMethod("IsGlobalComputed")!;
        public static readonly MethodInfo ItemMatchesCode = typeof(XmlQueryRuntime).GetMethod("MatchesXmlType", new[] { typeof(XPathItem), typeof(XmlTypeCode) })!;
        public static readonly MethodInfo ItemMatchesType = typeof(XmlQueryRuntime).GetMethod("MatchesXmlType", new[] { typeof(XPathItem), typeof(int) })!;
        public static readonly MethodInfo QNameEqualLit = typeof(XmlQueryRuntime).GetMethod("IsQNameEqual", new[] { typeof(XPathNavigator), typeof(int), typeof(int) })!;
        public static readonly MethodInfo QNameEqualNav = typeof(XmlQueryRuntime).GetMethod("IsQNameEqual", new[] { typeof(XPathNavigator), typeof(XPathNavigator) })!;
        public static readonly MethodInfo RtfConstr = typeof(XmlQueryRuntime).GetMethod("TextRtfConstruction")!;
        public static readonly MethodInfo SendMessage = typeof(XmlQueryRuntime).GetMethod("SendMessage")!;
        public static readonly MethodInfo SeqMatchesCode = typeof(XmlQueryRuntime).GetMethod("MatchesXmlType", new[] { typeof(IList<XPathItem>), typeof(XmlTypeCode) })!;
        public static readonly MethodInfo SeqMatchesType = typeof(XmlQueryRuntime).GetMethod("MatchesXmlType", new[] { typeof(IList<XPathItem>), typeof(int) })!;
        public static readonly MethodInfo SetGlobalValue = typeof(XmlQueryRuntime).GetMethod("SetGlobalValue")!;
        public static readonly MethodInfo StartRtfConstr = typeof(XmlQueryRuntime).GetMethod("StartRtfConstruction")!;
        public static readonly MethodInfo StartSeqConstr = typeof(XmlQueryRuntime).GetMethod("StartSequenceConstruction")!;
        public static readonly MethodInfo TagAndMappings = typeof(XmlQueryRuntime).GetMethod("ParseTagName", new[] { typeof(string), typeof(int) })!;
        public static readonly MethodInfo TagAndNamespace = typeof(XmlQueryRuntime).GetMethod("ParseTagName", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo ThrowException = typeof(XmlQueryRuntime).GetMethod("ThrowException")!;
        public static readonly MethodInfo XsltLib = typeof(XmlQueryRuntime).GetMethod("get_XsltFunctions")!;
 
        // XmlQueryContext
        public static readonly MethodInfo GetDataSource = typeof(XmlQueryContext).GetMethod("GetDataSource")!;
        public static readonly MethodInfo GetDefaultDataSource = typeof(XmlQueryContext).GetMethod("get_DefaultDataSource")!;
        public static readonly MethodInfo GetParam = typeof(XmlQueryContext).GetMethod("GetParameter")!;
        public static readonly MethodInfo InvokeXsltLate = GetInvokeXsltLateBoundFunction();
        [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:RequiresUnreferencedCode",
            Justification = "Suppressing warning about not having the RequiresUnreferencedCode attribute since this code path " +
            "will only be emitting IL that will later be called by Transform() method which is already annotated as RequiresUnreferencedCode")]
        private static MethodInfo GetInvokeXsltLateBoundFunction() => typeof(XmlQueryContext).GetMethod("InvokeXsltLateBoundFunction")!;
 
        // XmlILIndex
        public static readonly MethodInfo IndexAdd = typeof(XmlILIndex).GetMethod("Add")!;
        public static readonly MethodInfo IndexLookup = typeof(XmlILIndex).GetMethod("Lookup")!;
 
        // XPathItem
        public static readonly MethodInfo ItemIsNode = typeof(XPathItem).GetMethod("get_IsNode")!;
        public static readonly MethodInfo Value = typeof(XPathItem).GetMethod("get_Value")!;
        public static readonly MethodInfo ValueAsAny = typeof(XPathItem).GetMethod("ValueAs", new[] { typeof(Type), typeof(IXmlNamespaceResolver) })!;
 
        // XPathNavigator
        public static readonly MethodInfo NavClone = typeof(XPathNavigator).GetMethod("Clone")!;
        public static readonly MethodInfo NavLocalName = typeof(XPathNavigator).GetMethod("get_LocalName")!;
        public static readonly MethodInfo NavMoveAttr = typeof(XPathNavigator).GetMethod("MoveToAttribute", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo NavMoveId = typeof(XPathNavigator).GetMethod("MoveToId")!;
        public static readonly MethodInfo NavMoveParent = typeof(XPathNavigator).GetMethod("MoveToParent")!;
        public static readonly MethodInfo NavMoveRoot = typeof(XPathNavigator).GetMethod("MoveToRoot")!;
        public static readonly MethodInfo NavMoveTo = typeof(XPathNavigator).GetMethod("MoveTo")!;
        public static readonly MethodInfo NavNmsp = typeof(XPathNavigator).GetMethod("get_NamespaceURI")!;
        public static readonly MethodInfo NavPrefix = typeof(XPathNavigator).GetMethod("get_Prefix")!;
        public static readonly MethodInfo NavSamePos = typeof(XPathNavigator).GetMethod("IsSamePosition")!;
        public static readonly MethodInfo NavType = typeof(XPathNavigator).GetMethod("get_NodeType")!;
 
        // XmlQueryOutput methods
        public static readonly MethodInfo StartElemLitName = typeof(XmlQueryOutput).GetMethod("WriteStartElement", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartElemLocName = typeof(XmlQueryOutput).GetMethod("WriteStartElementLocalName", new[] { typeof(string) })!;
        public static readonly MethodInfo EndElemStackName = typeof(XmlQueryOutput).GetMethod("WriteEndElement")!;
        public static readonly MethodInfo StartAttrLitName = typeof(XmlQueryOutput).GetMethod("WriteStartAttribute", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartAttrLocName = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeLocalName", new[] { typeof(string) })!;
        public static readonly MethodInfo EndAttr = typeof(XmlQueryOutput).GetMethod("WriteEndAttribute")!;
        public static readonly MethodInfo Text = typeof(XmlQueryOutput).GetMethod("WriteString")!;
        public static readonly MethodInfo NoEntText = typeof(XmlQueryOutput).GetMethod("WriteRaw", new[] { typeof(string) })!;
 
        public static readonly MethodInfo StartTree = typeof(XmlQueryOutput).GetMethod("StartTree")!;
        public static readonly MethodInfo EndTree = typeof(XmlQueryOutput).GetMethod("EndTree")!;
 
        public static readonly MethodInfo StartElemLitNameUn = typeof(XmlQueryOutput).GetMethod("WriteStartElementUnchecked", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartElemLocNameUn = typeof(XmlQueryOutput).GetMethod("WriteStartElementUnchecked", new[] { typeof(string) })!;
        public static readonly MethodInfo StartContentUn = typeof(XmlQueryOutput).GetMethod("StartElementContentUnchecked")!;
        public static readonly MethodInfo EndElemLitNameUn = typeof(XmlQueryOutput).GetMethod("WriteEndElementUnchecked", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo EndElemLocNameUn = typeof(XmlQueryOutput).GetMethod("WriteEndElementUnchecked", new[] { typeof(string) })!;
        public static readonly MethodInfo StartAttrLitNameUn = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeUnchecked", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartAttrLocNameUn = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeUnchecked", new[] { typeof(string) })!;
        public static readonly MethodInfo EndAttrUn = typeof(XmlQueryOutput).GetMethod("WriteEndAttributeUnchecked")!;
        public static readonly MethodInfo NamespaceDeclUn = typeof(XmlQueryOutput).GetMethod("WriteNamespaceDeclarationUnchecked")!;
        public static readonly MethodInfo TextUn = typeof(XmlQueryOutput).GetMethod("WriteStringUnchecked")!;
        public static readonly MethodInfo NoEntTextUn = typeof(XmlQueryOutput).GetMethod("WriteRawUnchecked")!;
 
        public static readonly MethodInfo StartRoot = typeof(XmlQueryOutput).GetMethod("WriteStartRoot")!;
        public static readonly MethodInfo EndRoot = typeof(XmlQueryOutput).GetMethod("WriteEndRoot")!;
        public static readonly MethodInfo StartElemCopyName = typeof(XmlQueryOutput).GetMethod("WriteStartElementComputed", new[] { typeof(XPathNavigator) })!;
        public static readonly MethodInfo StartElemMapName = typeof(XmlQueryOutput).GetMethod("WriteStartElementComputed", new[] { typeof(string), typeof(int) })!;
        public static readonly MethodInfo StartElemNmspName = typeof(XmlQueryOutput).GetMethod("WriteStartElementComputed", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartElemQName = typeof(XmlQueryOutput).GetMethod("WriteStartElementComputed", new[] { typeof(XmlQualifiedName) })!;
        public static readonly MethodInfo StartAttrCopyName = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeComputed", new[] { typeof(XPathNavigator) })!;
        public static readonly MethodInfo StartAttrMapName = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeComputed", new[] { typeof(string), typeof(int) })!;
        public static readonly MethodInfo StartAttrNmspName = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeComputed", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo StartAttrQName = typeof(XmlQueryOutput).GetMethod("WriteStartAttributeComputed", new[] { typeof(XmlQualifiedName) })!;
        public static readonly MethodInfo NamespaceDecl = typeof(XmlQueryOutput).GetMethod("WriteNamespaceDeclaration")!;
        public static readonly MethodInfo StartComment = typeof(XmlQueryOutput).GetMethod("WriteStartComment")!;
        public static readonly MethodInfo CommentText = typeof(XmlQueryOutput).GetMethod("WriteCommentString")!;
        public static readonly MethodInfo EndComment = typeof(XmlQueryOutput).GetMethod("WriteEndComment")!;
        public static readonly MethodInfo StartPI = typeof(XmlQueryOutput).GetMethod("WriteStartProcessingInstruction")!;
        public static readonly MethodInfo PIText = typeof(XmlQueryOutput).GetMethod("WriteProcessingInstructionString")!;
        public static readonly MethodInfo EndPI = typeof(XmlQueryOutput).GetMethod("WriteEndProcessingInstruction")!;
        public static readonly MethodInfo WriteItem = typeof(XmlQueryOutput).GetMethod("WriteItem")!;
        public static readonly MethodInfo CopyOf = typeof(XmlQueryOutput).GetMethod("XsltCopyOf")!;
        public static readonly MethodInfo StartCopy = typeof(XmlQueryOutput).GetMethod("StartCopy")!;
        public static readonly MethodInfo EndCopy = typeof(XmlQueryOutput).GetMethod("EndCopy")!;
 
        // Datatypes
        public static readonly MethodInfo DecAdd = typeof(decimal).GetMethod("Add")!;
        public static readonly MethodInfo DecCmp = typeof(decimal).GetMethod("Compare", new[] { typeof(decimal), typeof(decimal) })!;
        public static readonly MethodInfo DecEq = typeof(decimal).GetMethod("Equals", new[] { typeof(decimal), typeof(decimal) })!;
        public static readonly MethodInfo DecSub = typeof(decimal).GetMethod("Subtract")!;
        public static readonly MethodInfo DecMul = typeof(decimal).GetMethod("Multiply")!;
        public static readonly MethodInfo DecDiv = typeof(decimal).GetMethod("Divide")!;
        public static readonly MethodInfo DecRem = typeof(decimal).GetMethod("Remainder")!;
        public static readonly MethodInfo DecNeg = typeof(decimal).GetMethod("Negate")!;
        public static readonly MethodInfo QNameEq = typeof(XmlQualifiedName).GetMethod("Equals")!;
        public static readonly MethodInfo StrEq = typeof(string).GetMethod("Equals", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo StrCat2 = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo StrCat3 = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StrCat4 = typeof(string).GetMethod("Concat", new[] { typeof(string), typeof(string), typeof(string), typeof(string) })!;
        public static readonly MethodInfo StrCmp = typeof(string).GetMethod("CompareOrdinal", new[] { typeof(string), typeof(string) })!;
        public static readonly MethodInfo StrLen = typeof(string).GetMethod("get_Length")!;
 
        // XsltConvert
        public static readonly MethodInfo DblToDec = typeof(XsltConvert).GetMethod("ToDecimal", new[] { typeof(double) })!;
        public static readonly MethodInfo DblToInt = typeof(XsltConvert).GetMethod("ToInt", new[] { typeof(double) })!;
        public static readonly MethodInfo DblToLng = typeof(XsltConvert).GetMethod("ToLong", new[] { typeof(double) })!;
        public static readonly MethodInfo DblToStr = typeof(XsltConvert).GetMethod("ToString", new[] { typeof(double) })!;
        public static readonly MethodInfo DecToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(decimal) })!;
        public static readonly MethodInfo DTToStr = typeof(XsltConvert).GetMethod("ToString", new[] { typeof(DateTime) })!;
        public static readonly MethodInfo IntToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(int) })!;
        public static readonly MethodInfo LngToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(long) })!;
        public static readonly MethodInfo StrToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(string) })!;
        public static readonly MethodInfo StrToDT = typeof(XsltConvert).GetMethod("ToDateTime", new[] { typeof(string) })!;
 
        public static readonly MethodInfo ItemToBool = typeof(XsltConvert).GetMethod("ToBoolean", new[] { typeof(XPathItem) })!;
        public static readonly MethodInfo ItemToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(XPathItem) })!;
        public static readonly MethodInfo ItemToStr = typeof(XsltConvert).GetMethod("ToString", new[] { typeof(XPathItem) })!;
        public static readonly MethodInfo ItemToNode = typeof(XsltConvert).GetMethod("ToNode", new[] { typeof(XPathItem) })!;
        public static readonly MethodInfo ItemToNodes = typeof(XsltConvert).GetMethod("ToNodeSet", new[] { typeof(XPathItem) })!;
 
        public static readonly MethodInfo ItemsToBool = typeof(XsltConvert).GetMethod("ToBoolean", new[] { typeof(IList<XPathItem>) })!;
        public static readonly MethodInfo ItemsToDbl = typeof(XsltConvert).GetMethod("ToDouble", new[] { typeof(IList<XPathItem>) })!;
        public static readonly MethodInfo ItemsToNode = typeof(XsltConvert).GetMethod("ToNode", new[] { typeof(IList<XPathItem>) })!;
        public static readonly MethodInfo ItemsToNodes = typeof(XsltConvert).GetMethod("ToNodeSet", new[] { typeof(IList<XPathItem>) })!;
        public static readonly MethodInfo ItemsToStr = typeof(XsltConvert).GetMethod("ToString", new[] { typeof(IList<XPathItem>) })!;
 
        // StringConcat
        public static readonly MethodInfo StrCatCat = typeof(StringConcat).GetMethod("Concat")!;
        public static readonly MethodInfo StrCatClear = typeof(StringConcat).GetMethod("Clear")!;
        public static readonly MethodInfo StrCatResult = typeof(StringConcat).GetMethod("GetResult")!;
        public static readonly MethodInfo StrCatDelim = typeof(StringConcat).GetMethod("set_Delimiter")!;
 
        // XmlILStorageConverter
        public static readonly MethodInfo NavsToItems = typeof(XmlILStorageConverter).GetMethod("NavigatorsToItems")!;
        public static readonly MethodInfo ItemsToNavs = typeof(XmlILStorageConverter).GetMethod("ItemsToNavigators")!;
 
        // XmlQueryNodeSequence
        public static readonly MethodInfo SetDod = typeof(XmlQueryNodeSequence).GetMethod("set_IsDocOrderDistinct")!;
 
        // Miscellaneous
        public static readonly MethodInfo GetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle")!;
        public static readonly MethodInfo InitializeArray = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("InitializeArray")!;
        public static readonly Dictionary<Type, XmlILStorageMethods> StorageMethods = new Dictionary<Type, XmlILStorageMethods>(13)
        {
            { typeof(string), new XmlILStorageMethods(typeof(string)) },
            { typeof(bool), new XmlILStorageMethods(typeof(bool)) },
            { typeof(int), new XmlILStorageMethods(typeof(int)) },
            { typeof(long), new XmlILStorageMethods(typeof(long)) },
            { typeof(decimal), new XmlILStorageMethods(typeof(decimal)) },
            { typeof(double), new XmlILStorageMethods(typeof(double)) },
            { typeof(float), new XmlILStorageMethods(typeof(float)) },
            { typeof(DateTime), new XmlILStorageMethods(typeof(DateTime)) },
            { typeof(byte[]), new XmlILStorageMethods(typeof(byte[])) },
            { typeof(XmlQualifiedName), new XmlILStorageMethods(typeof(XmlQualifiedName)) },
            { typeof(TimeSpan), new XmlILStorageMethods(typeof(TimeSpan)) },
            { typeof(XPathItem), new XmlILStorageMethods(typeof(XPathItem)) },
            { typeof(XPathNavigator), new XmlILStorageMethods(typeof(XPathNavigator)) },
        };
    }
 
 
    /// <summary>
    /// When named nodes are constructed, there are several possible ways for their names to be created.
    /// </summary>
    internal enum GenerateNameType
    {
        LiteralLocalName,       // Local name is a literal string; namespace is null
        LiteralName,            // All parts of the name are literal strings
        CopiedName,             // Name should be copied from a navigator
        TagNameAndMappings,     // Tagname contains prefix:localName and prefix is mapped to a namespace
        TagNameAndNamespace,    // Tagname contains prefix:localName and namespace is provided
        QName,                  // Name is computed QName (no prefix available)
        StackName,              // Element name has already been pushed onto XmlQueryOutput stack
    }
 
    /// <summary>
    /// Contains helper methods used during the code generation phase.
    /// </summary>
    [RequiresDynamicCode("Creates DynamicMethods")]
    internal sealed class GenerateHelper
    {
        private MethodBase? _methInfo;
        private ILGenerator? _ilgen;
        private LocalBuilder? _locXOut;
        private readonly XmlILModule _module;
        private readonly bool _isDebug;
        private bool _initWriters;
        private readonly StaticDataManager _staticData;
        private ISourceLineInfo? _lastSourceInfo;
        private MethodInfo? _methSyncToNav;
 
#if DEBUG
        private int _lblNum;
        private Hashtable? _symbols;
        private int _numLocals;
        private string? _sourceFile;
        private TextWriter? _writerDump;
#endif
 
        /// <summary>
        /// Cache metadata used during code-generation phase.
        /// </summary>
        // SxS note: Using hardcoded "dump.il" is an SxS issue. Since we are doing this ONLY in debug builds
        // and only for tracing purposes and MakeVersionSafeName does not seem to be able to handle file
        // extensions correctly I decided to suppress the SxS message (as advised by SxS guys).
        public GenerateHelper(XmlILModule module, bool isDebug)
        {
            _isDebug = isDebug;
            _module = module;
            _staticData = new StaticDataManager();
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
                XmlILTrace.PrepareTraceWriter("dump.il");
#endif
        }
 
        /// <summary>
        /// Begin generating code within a new method.
        /// </summary>
        // SxS note: Using hardcoded "dump.il" is an SxS issue. Since we are doing this ONLY in debug builds
        // and only for tracing purposes and MakeVersionSafeName does not seem to be able to handle file
        // extensions correctly I decided to suppress the SxS message (as advised by SxS guys).
        public void MethodBegin(MethodBase methInfo, ISourceLineInfo? sourceInfo, bool initWriters)
        {
            _methInfo = methInfo;
            _ilgen = XmlILModule.DefineMethodBody(methInfo);
            _lastSourceInfo = null;
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                _numLocals = 0;
                _symbols = new Hashtable();
                _lblNum = 0;
                _sourceFile = null;
 
                _writerDump = XmlILTrace.GetTraceWriter("dump.il");
                _writerDump!.WriteLine(".method {0}()", methInfo.Name);
                _writerDump.WriteLine("{");
            }
#endif
 
            if (_isDebug)
            {
                DebugStartScope();
 
                // DebugInfo: Sequence point just before generating code for this function
                if (sourceInfo != null)
                {
                    // Don't call DebugSequencePoint, as it puts Nop *before* the sequence point.  That is
                    // wrong in this case, because we need source line information to be emitted before any
                    // IL instruction so that stepping into this function won't end up in the assembly window.
                    // We still guarantee that:
                    //   1. Two sequence points are never adjacent, since this is the 1st sequence point
                    //   2. Stack depth is 0, since this is the very beginning of the method
                    MarkSequencePoint(sourceInfo);
                    Emit(OpCodes.Nop);
                }
            }
            else if (_module.EmitSymbols)
            {
                // For a retail build, put source information on methods only
                if (sourceInfo != null)
                {
                    MarkSequencePoint(sourceInfo);
                    // Set this.lastSourceInfo back to null to prevent generating additional sequence points
                    // in this method.
                    _lastSourceInfo = null;
                }
            }
 
            _initWriters = false;
            if (initWriters)
            {
                EnsureWriter();
                LoadQueryRuntime();
                Call(XmlILMethods.GetOutput);
                Emit(OpCodes.Stloc, _locXOut);
            }
        }
 
        /// <summary>
        /// Generate "ret" instruction and branch fixup jump table.
        /// </summary>
        public void MethodEnd()
        {
            Emit(OpCodes.Ret);
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                _writerDump!.WriteLine("}");
                _writerDump.WriteLine("");
                _writerDump.Close();
            }
#endif
 
            if (_isDebug)
                DebugEndScope();
        }
 
 
        //-----------------------------------------------
        // Helper Global Methods
        //-----------------------------------------------
 
        /// <summary>
        /// Call a static method which attempts to reuse a navigator.
        /// </summary>
        public void CallSyncToNavigator()
        {
            // Get helper method from module
            _methSyncToNav ??= _module.FindMethod("SyncToNavigator");
 
            Call(_methSyncToNav!);
        }
 
        //-----------------------------------------------
        // StaticDataManager
        //-----------------------------------------------
 
        /// <summary>
        /// This internal class manages literal names, literal types, and storage for global variables.
        /// </summary>
        public StaticDataManager StaticData
        {
            get { return _staticData; }
        }
 
 
        //-----------------------------------------------
        // Constants
        //-----------------------------------------------
 
        /// <summary>
        /// Generate the optimal Ldc_I4 instruction based on intVal.
        /// </summary>
        public void LoadInteger(int intVal)
        {
            Emit(OpCodes.Ldc_I4, intVal);
        }
 
        public void LoadBoolean(bool boolVal)
        {
            Emit(boolVal ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
        }
 
        public void LoadType(Type clrTyp)
        {
            Emit(OpCodes.Ldtoken, clrTyp);
            Call(XmlILMethods.GetTypeFromHandle);
        }
 
 
        //-----------------------------------------------
        // Local variables
        //-----------------------------------------------
 
        /// <summary>
        /// Generate a new local variable.  Add a numeric suffix to name that ensures that all
        /// local variable names will be unique (for readability).
        /// </summary>
        public LocalBuilder DeclareLocal(string name, Type type)
        {
            LocalBuilder locBldr = _ilgen!.DeclareLocal(type);
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                _symbols!.Add(locBldr, name + _numLocals.ToString(CultureInfo.InvariantCulture));
                _numLocals++;
            }
#endif
            return locBldr;
        }
 
        public void LoadQueryRuntime()
        {
            Emit(OpCodes.Ldarg_0);
        }
 
        public void LoadQueryContext()
        {
            Emit(OpCodes.Ldarg_0);
            Call(XmlILMethods.Context);
        }
 
        public void LoadXsltLibrary()
        {
            Emit(OpCodes.Ldarg_0);
            Call(XmlILMethods.XsltLib);
        }
 
        public void LoadQueryOutput()
        {
            Emit(OpCodes.Ldloc, _locXOut!);
        }
 
 
        //-----------------------------------------------
        // Parameters
        //-----------------------------------------------
 
        public void LoadParameter(int paramPos)
        {
            if (paramPos <= ushort.MaxValue)
            {
                Emit(OpCodes.Ldarg, paramPos);
            }
            else
            {
                throw new XslTransformException(SR.XmlIl_TooManyParameters);
            }
        }
 
        public void SetParameter(object paramId)
        {
            int paramPos = (int)paramId;
 
            if (paramPos <= ushort.MaxValue)
            {
                Emit(OpCodes.Starg, (int)paramPos);
            }
            else
            {
                throw new XslTransformException(SR.XmlIl_TooManyParameters);
            }
        }
 
        //-----------------------------------------------
        // Labels
        //-----------------------------------------------
 
        /// <summary>
        /// Branch to lblBranch and anchor lblMark.  If lblBranch = lblMark, then no need
        /// to generate a "br" to the next instruction.
        /// </summary>
        public void BranchAndMark(Label lblBranch, Label lblMark)
        {
            if (!lblBranch.Equals(lblMark))
            {
                EmitUnconditionalBranch(OpCodes.Br, lblBranch);
            }
            MarkLabel(lblMark);
        }
 
 
        //-----------------------------------------------
        // Comparison
        //-----------------------------------------------
 
        /// <summary>
        /// Compare the top value on the stack with the specified i4 using the specified relational
        /// comparison opcode, and branch to lblBranch if the result is true.
        /// </summary>
        public void TestAndBranch(int i4, Label lblBranch, OpCode opcodeBranch)
        {
            switch (i4)
            {
                case 0:
                    // Beq or Bne can be shortened to Brfalse or Brtrue if comparing to 0
                    if (opcodeBranch.Value == OpCodes.Beq.Value)
                        opcodeBranch = OpCodes.Brfalse;
                    else if (opcodeBranch.Value == OpCodes.Beq_S.Value)
                        opcodeBranch = OpCodes.Brfalse_S;
                    else if (opcodeBranch.Value == OpCodes.Bne_Un.Value)
                        opcodeBranch = OpCodes.Brtrue;
                    else if (opcodeBranch.Value == OpCodes.Bne_Un_S.Value)
                        opcodeBranch = OpCodes.Brtrue_S;
                    else
                        goto default;
                    break;
 
                default:
                    // Cannot use shortcut, so push integer onto the stack
                    LoadInteger(i4);
                    break;
            }
 
            Emit(opcodeBranch, lblBranch);
        }
 
        /// <summary>
        /// Assume a branch instruction has already been issued.  If isTrueBranch is true, then the
        /// true path is linked to lblBranch.  Otherwise, the false path is linked to lblBranch.
        /// Convert this "branching" boolean logic into an explicit push of 1 or 0 onto the stack.
        /// </summary>
        public void ConvBranchToBool(Label lblBranch, bool isTrueBranch)
        {
            Label lblDone = DefineLabel();
 
            Emit(isTrueBranch ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
            EmitUnconditionalBranch(OpCodes.Br_S, lblDone);
            MarkLabel(lblBranch);
            Emit(isTrueBranch ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
            MarkLabel(lblDone);
        }
 
 
        //-----------------------------------------------
        // Frequently used method and function calls
        //-----------------------------------------------
 
        public void TailCall(MethodInfo meth)
        {
            Emit(OpCodes.Tailcall);
            Call(meth);
            Emit(OpCodes.Ret);
        }
 
#pragma warning disable CA1822
        [Conditional("DEBUG")]
        private void TraceCall(OpCode opcode, MethodInfo meth)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                StringBuilder strBldr = new StringBuilder();
                bool isFirst = true;
                string retType = "";
 
                if (!(meth is MethodBuilder))
                {
                    foreach (ParameterInfo paramInfo in meth.GetParameters())
                    {
                        if (isFirst)
                            isFirst = false;
                        else
                            strBldr.Append(", ");
                        strBldr.Append(paramInfo.ParameterType.Name);
                    }
                    retType = meth.ReturnType.Name;
                }
 
                _writerDump!.WriteLine("  {0, -10} {1} {2}({3})", new object?[] { opcode.Name, retType, meth.Name, strBldr.ToString() });
            }
#endif
        }
#pragma warning restore CA1822
 
        public void Call(MethodInfo meth)
        {
            OpCode opcode = meth.IsVirtual || meth.IsAbstract ? OpCodes.Callvirt : OpCodes.Call;
 
            TraceCall(opcode, meth);
            _ilgen!.Emit(opcode, meth);
 
            if (_lastSourceInfo != null)
            {
                // Emit a "no source" sequence point, otherwise the debugger would return to the wrong line
                // once the call has finished.  We are guaranteed not to emit adjacent sequence points because
                // the Call instruction precedes this sequence point, and a nop instruction precedes other
                // sequence points.
                MarkSequencePoint(SourceLineInfo.NoSource);
            }
        }
 
        public void Construct(ConstructorInfo constr)
        {
            Emit(OpCodes.Newobj, constr);
        }
 
        public void CallConcatStrings(int cStrings)
        {
            switch (cStrings)
            {
                case 0:
                    Emit(OpCodes.Ldstr, "");
                    break;
                case 1:
                    break;
                case 2:
                    Call(XmlILMethods.StrCat2);
                    break;
                case 3:
                    Call(XmlILMethods.StrCat3);
                    break;
                case 4:
                    Call(XmlILMethods.StrCat4);
                    break;
                default:
                    Debug.Fail("Shouldn't be called");
                    break;
            }
        }
 
        /// <summary>
        /// Assume that an object reference is on the IL stack.  Change the static Clr type from "clrTypeSrc" to "clrTypeDst"
        /// </summary>
        public void TreatAs(Type clrTypeSrc, Type clrTypeDst)
        {
            // If source = destination, then no-op
            if (clrTypeSrc == clrTypeDst)
                return;
 
            if (clrTypeSrc.IsValueType)
            {
                // If source is a value type, then destination may only be typeof(object), so box
                Debug.Assert(clrTypeDst == typeof(object), "Invalid cast, since value types do not allow inheritance.");
                Emit(OpCodes.Box, clrTypeSrc);
            }
            else if (clrTypeDst.IsValueType)
            {
                // If destination type is value type, then source may only be typeof(object), so unbox
                Debug.Assert(clrTypeSrc == typeof(object), "Invalid cast, since value types do not allow inheritance.");
                Emit(OpCodes.Unbox, clrTypeDst);
                Emit(OpCodes.Ldobj, clrTypeDst);
            }
            else if (clrTypeDst != typeof(object))
            {
                // If source is not a value type, and destination type is typeof(object), then no-op
                // Otherwise, use Castclass to change the static type
                Debug.Assert(clrTypeSrc.IsAssignableFrom(clrTypeDst) || clrTypeDst.IsAssignableFrom(clrTypeSrc),
                             "Invalid cast, since source type and destination type are not in same inheritance hierarchy.");
                Emit(OpCodes.Castclass, clrTypeDst);
            }
        }
 
 
        //-----------------------------------------------
        // Datatype methods
        //-----------------------------------------------
 
        public void ConstructLiteralDecimal(decimal dec)
        {
            if (dec >= (decimal)int.MinValue && dec <= (decimal)int.MaxValue && decimal.Truncate(dec) == dec)
            {
                // Decimal can be constructed from a 32-bit integer
                LoadInteger((int)dec);
                Construct(XmlILConstructors.DecFromInt32);
            }
            else
            {
                int[] bits = decimal.GetBits(dec);
 
                LoadInteger(bits[0]);
                LoadInteger(bits[1]);
                LoadInteger(bits[2]);
                LoadBoolean(bits[3] < 0);
                LoadInteger(bits[3] >> 16);
                Construct(XmlILConstructors.DecFromParts);
            }
        }
 
        public void ConstructLiteralQName(string localName, string namespaceName)
        {
            Emit(OpCodes.Ldstr, localName);
            Emit(OpCodes.Ldstr, namespaceName);
            Construct(XmlILConstructors.QName);
        }
 
        public void CallArithmeticOp(QilNodeType opType, XmlTypeCode code)
        {
            MethodInfo? meth = null;
 
            switch (code)
            {
                case XmlTypeCode.Int:
                case XmlTypeCode.Integer:
                case XmlTypeCode.Double:
                case XmlTypeCode.Float:
                    switch (opType)
                    {
                        case QilNodeType.Add: Emit(OpCodes.Add); break;
                        case QilNodeType.Subtract: Emit(OpCodes.Sub); break;
                        case QilNodeType.Multiply: Emit(OpCodes.Mul); break;
                        case QilNodeType.Divide: Emit(OpCodes.Div); break;
                        case QilNodeType.Modulo: Emit(OpCodes.Rem); break;
                        case QilNodeType.Negate: Emit(OpCodes.Neg); break;
                        default: Debug.Fail($"{opType} must be an arithmetic operation."); break;
                    }
                    break;
 
                case XmlTypeCode.Decimal:
                    switch (opType)
                    {
                        case QilNodeType.Add: meth = XmlILMethods.DecAdd; break;
                        case QilNodeType.Subtract: meth = XmlILMethods.DecSub; break;
                        case QilNodeType.Multiply: meth = XmlILMethods.DecMul; break;
                        case QilNodeType.Divide: meth = XmlILMethods.DecDiv; break;
                        case QilNodeType.Modulo: meth = XmlILMethods.DecRem; break;
                        case QilNodeType.Negate: meth = XmlILMethods.DecNeg; break;
                        default: Debug.Fail($"{opType} must be an arithmetic operation."); break;
                    }
 
                    Call(meth);
                    break;
 
                default:
                    Debug.Fail($"The {opType} arithmetic operation cannot be performed on values of type {code}.");
                    break;
            }
        }
 
        public void CallCompareEquals(XmlTypeCode code)
        {
            MethodInfo? meth = null;
 
            switch (code)
            {
                case XmlTypeCode.String: meth = XmlILMethods.StrEq; break;
                case XmlTypeCode.QName: meth = XmlILMethods.QNameEq; break;
                case XmlTypeCode.Decimal: meth = XmlILMethods.DecEq; break;
                default:
                    Debug.Fail($"Type {code} does not support the equals operation.");
                    break;
            }
 
            Call(meth);
        }
 
        public void CallCompare(XmlTypeCode code)
        {
            MethodInfo? meth = null;
 
            switch (code)
            {
                case XmlTypeCode.String: meth = XmlILMethods.StrCmp; break;
                case XmlTypeCode.Decimal: meth = XmlILMethods.DecCmp; break;
                default:
                    Debug.Fail($"Type {code} does not support the equals operation.");
                    break;
            }
 
            Call(meth);
        }
 
 
        //-----------------------------------------------
        // XmlQueryRuntime function calls
        //-----------------------------------------------
 
        public void CallStartRtfConstruction(string baseUri)
        {
            EnsureWriter();
            LoadQueryRuntime();
            Emit(OpCodes.Ldstr, baseUri);
            Emit(OpCodes.Ldloca, _locXOut);
            Call(XmlILMethods.StartRtfConstr);
        }
 
        public void CallEndRtfConstruction()
        {
            LoadQueryRuntime();
            Emit(OpCodes.Ldloca, _locXOut!);
            Call(XmlILMethods.EndRtfConstr);
        }
 
        public void CallStartSequenceConstruction()
        {
            EnsureWriter();
            LoadQueryRuntime();
            Emit(OpCodes.Ldloca, _locXOut);
            Call(XmlILMethods.StartSeqConstr);
        }
 
        public void CallEndSequenceConstruction()
        {
            LoadQueryRuntime();
            Emit(OpCodes.Ldloca, _locXOut!);
            Call(XmlILMethods.EndSeqConstr);
        }
 
        public void CallGetEarlyBoundObject(int idxObj, Type clrType)
        {
            LoadQueryRuntime();
            LoadInteger(idxObj);
            Call(XmlILMethods.GetEarly);
            TreatAs(typeof(object), clrType);
        }
 
        public void CallGetAtomizedName(int idxName)
        {
            LoadQueryRuntime();
            LoadInteger(idxName);
            Call(XmlILMethods.GetAtomizedName);
        }
 
        public void CallGetNameFilter(int idxFilter)
        {
            LoadQueryRuntime();
            LoadInteger(idxFilter);
            Call(XmlILMethods.GetNameFilter);
        }
 
        public void CallGetTypeFilter(XPathNodeType nodeType)
        {
            LoadQueryRuntime();
            LoadInteger((int)nodeType);
            Call(XmlILMethods.GetTypeFilter);
        }
 
        public void CallParseTagName(GenerateNameType nameType)
        {
            if (nameType == GenerateNameType.TagNameAndMappings)
            {
                Call(XmlILMethods.TagAndMappings);
            }
            else
            {
                Debug.Assert(nameType == GenerateNameType.TagNameAndNamespace);
                Call(XmlILMethods.TagAndNamespace);
            }
        }
 
        public void CallGetGlobalValue(int idxValue, Type clrType)
        {
            LoadQueryRuntime();
            LoadInteger(idxValue);
            Call(XmlILMethods.GetGlobalValue);
            TreatAs(typeof(object), clrType);
        }
 
        public void CallSetGlobalValue(Type clrType)
        {
            TreatAs(clrType, typeof(object));
            Call(XmlILMethods.SetGlobalValue);
        }
 
        public void CallGetCollation(int idxName)
        {
            LoadQueryRuntime();
            LoadInteger(idxName);
            Call(XmlILMethods.GetCollation);
        }
 
        [MemberNotNull(nameof(_locXOut))]
        private void EnsureWriter()
        {
            // If write variable has not yet been initialized, do it now
            if (!_initWriters)
            {
                _locXOut = DeclareLocal("$$$xwrtChk", typeof(XmlQueryOutput));
                _initWriters = true;
            }
 
            Debug.Assert(_locXOut != null);
        }
 
 
        //-----------------------------------------------
        // XmlQueryContext function calls
        //-----------------------------------------------
 
        public void CallGetParameter(string localName, string namespaceUri)
        {
            LoadQueryContext();
            Emit(OpCodes.Ldstr, localName);
            Emit(OpCodes.Ldstr, namespaceUri);
            Call(XmlILMethods.GetParam);
        }
 
        //-----------------------------------------------
        // XmlQueryOutput function calls
        //-----------------------------------------------
 
        public void CallStartTree(XPathNodeType rootType)
        {
            LoadQueryOutput();
            LoadInteger((int)rootType);
            Call(XmlILMethods.StartTree);
        }
 
        public void CallEndTree()
        {
            LoadQueryOutput();
            Call(XmlILMethods.EndTree);
        }
 
        public void CallWriteStartRoot()
        {
            // Call XmlQueryOutput.WriteStartRoot
            LoadQueryOutput();
            Call(XmlILMethods.StartRoot);
        }
 
        public void CallWriteEndRoot()
        {
            // Call XmlQueryOutput.WriteEndRoot
            LoadQueryOutput();
            Call(XmlILMethods.EndRoot);
        }
 
        public void CallWriteStartElement(GenerateNameType nameType, bool callChk)
        {
            MethodInfo? meth = null;
 
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteStartElement
                switch (nameType)
                {
                    case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartElemLocName; break;
                    case GenerateNameType.LiteralName: meth = XmlILMethods.StartElemLitName; break;
                    case GenerateNameType.CopiedName: meth = XmlILMethods.StartElemCopyName; break;
                    case GenerateNameType.TagNameAndMappings: meth = XmlILMethods.StartElemMapName; break;
                    case GenerateNameType.TagNameAndNamespace: meth = XmlILMethods.StartElemNmspName; break;
                    case GenerateNameType.QName: meth = XmlILMethods.StartElemQName; break;
                    default: Debug.Fail($"{nameType} is invalid here."); break;
                }
            }
            else
            {
                // Else call XmlQueryOutput.WriteStartElementUnchecked
                switch (nameType)
                {
                    case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartElemLocNameUn; break;
                    case GenerateNameType.LiteralName: meth = XmlILMethods.StartElemLitNameUn; break;
                    default: Debug.Fail($"{nameType} is invalid here."); break;
                }
            }
 
            Call(meth);
        }
 
        public void CallWriteEndElement(GenerateNameType nameType, bool callChk)
        {
            MethodInfo? meth = null;
 
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteEndElement
                meth = XmlILMethods.EndElemStackName;
            }
            else
            {
                // Else call XmlQueryOutput.WriteEndElementUnchecked
                switch (nameType)
                {
                    case GenerateNameType.LiteralLocalName: meth = XmlILMethods.EndElemLocNameUn; break;
                    case GenerateNameType.LiteralName: meth = XmlILMethods.EndElemLitNameUn; break;
                    default: Debug.Fail($"{nameType} is invalid here."); break;
                }
            }
 
            Call(meth);
        }
 
        public void CallStartElementContent()
        {
            LoadQueryOutput();
            Call(XmlILMethods.StartContentUn);
        }
 
        public void CallWriteStartAttribute(GenerateNameType nameType, bool callChk)
        {
            MethodInfo? meth = null;
 
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteStartAttribute
                switch (nameType)
                {
                    case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartAttrLocName; break;
                    case GenerateNameType.LiteralName: meth = XmlILMethods.StartAttrLitName; break;
                    case GenerateNameType.CopiedName: meth = XmlILMethods.StartAttrCopyName; break;
                    case GenerateNameType.TagNameAndMappings: meth = XmlILMethods.StartAttrMapName; break;
                    case GenerateNameType.TagNameAndNamespace: meth = XmlILMethods.StartAttrNmspName; break;
                    case GenerateNameType.QName: meth = XmlILMethods.StartAttrQName; break;
                    default: Debug.Fail($"{nameType} is invalid here."); break;
                }
            }
            else
            {
                // Else call XmlQueryOutput.WriteStartAttributeUnchecked
                switch (nameType)
                {
                    case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartAttrLocNameUn; break;
                    case GenerateNameType.LiteralName: meth = XmlILMethods.StartAttrLitNameUn; break;
                    default: Debug.Fail($"{nameType} is invalid here."); break;
                }
            }
 
            Call(meth);
        }
 
        public void CallWriteEndAttribute(bool callChk)
        {
            LoadQueryOutput();
 
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteEndAttribute
                Call(XmlILMethods.EndAttr);
            }
            else
            {
                // Else call XmlQueryOutput.WriteEndAttributeUnchecked
                Call(XmlILMethods.EndAttrUn);
            }
        }
 
        public void CallWriteNamespaceDecl(bool callChk)
        {
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteNamespaceDeclaration
                Call(XmlILMethods.NamespaceDecl);
            }
            else
            {
                // Else call XmlQueryOutput.WriteNamespaceDeclarationUnchecked
                Call(XmlILMethods.NamespaceDeclUn);
            }
        }
 
        public void CallWriteString(bool disableOutputEscaping, bool callChk)
        {
            // If runtime checks need to be made,
            if (callChk)
            {
                // Then call XmlQueryOutput.WriteString, or XmlQueryOutput.WriteRaw
                if (disableOutputEscaping)
                    Call(XmlILMethods.NoEntText);
                else
                    Call(XmlILMethods.Text);
            }
            else
            {
                // Else call XmlQueryOutput.WriteStringUnchecked, or XmlQueryOutput.WriteRawUnchecked
                if (disableOutputEscaping)
                    Call(XmlILMethods.NoEntTextUn);
                else
                    Call(XmlILMethods.TextUn);
            }
        }
 
        public void CallWriteStartPI()
        {
            Call(XmlILMethods.StartPI);
        }
 
        public void CallWriteEndPI()
        {
            LoadQueryOutput();
            Call(XmlILMethods.EndPI);
        }
 
        public void CallWriteStartComment()
        {
            LoadQueryOutput();
            Call(XmlILMethods.StartComment);
        }
 
        public void CallWriteEndComment()
        {
            LoadQueryOutput();
            Call(XmlILMethods.EndComment);
        }
 
 
        //-----------------------------------------------
        // Item caching methods
        //-----------------------------------------------
 
        public void CallCacheCount(Type itemStorageType)
        {
            XmlILStorageMethods meth = XmlILMethods.StorageMethods[itemStorageType];
            Call(meth.IListCount);
        }
 
        public void CallCacheItem(Type itemStorageType)
        {
            Call(XmlILMethods.StorageMethods[itemStorageType].IListItem);
        }
 
 
        //-----------------------------------------------
        // XPathItem properties and methods
        //-----------------------------------------------
 
        public void CallValueAs(Type clrType)
        {
            MethodInfo? meth;
 
            meth = XmlILMethods.StorageMethods[clrType].ValueAs;
            if (meth == null)
            {
                // Call (Type) item.ValueAs(Type, null)
                LoadType(clrType);
                Emit(OpCodes.Ldnull);
                Call(XmlILMethods.ValueAsAny);
 
                // Unbox or down-cast
                TreatAs(typeof(object), clrType);
            }
            else
            {
                // Call strongly typed ValueAs method
                Call(meth);
            }
        }
 
 
        //-----------------------------------------------
        // XmlSortKeyAccumulator methods
        //-----------------------------------------------
 
        public void AddSortKey(XmlQueryType? keyType)
        {
            MethodInfo? meth = null;
 
            if (keyType == null)
            {
                meth = XmlILMethods.SortKeyEmpty;
            }
            else
            {
                Debug.Assert(keyType.IsAtomicValue, "Sort key must have atomic value type.");
 
                switch (keyType.TypeCode)
                {
                    case XmlTypeCode.String: meth = XmlILMethods.SortKeyString; break;
                    case XmlTypeCode.Decimal: meth = XmlILMethods.SortKeyDecimal; break;
                    case XmlTypeCode.Integer: meth = XmlILMethods.SortKeyInteger; break;
                    case XmlTypeCode.Int: meth = XmlILMethods.SortKeyInt; break;
                    case XmlTypeCode.Boolean: meth = XmlILMethods.SortKeyInt; break;
                    case XmlTypeCode.Double: meth = XmlILMethods.SortKeyDouble; break;
                    case XmlTypeCode.DateTime: meth = XmlILMethods.SortKeyDateTime; break;
 
                    case XmlTypeCode.None:
                        // Empty sequence, so this path will never actually be taken
                        Emit(OpCodes.Pop);
                        meth = XmlILMethods.SortKeyEmpty;
                        break;
 
                    case XmlTypeCode.AnyAtomicType:
                        Debug.Fail("Heterogenous sort key is not allowed.");
                        return;
 
                    default:
                        Debug.Fail($"Sorting over datatype {keyType.TypeCode} is not allowed.");
                        break;
                }
            }
 
            Call(meth);
        }
 
 
        //-----------------------------------------------
        // Debugging information output
        //-----------------------------------------------
 
        /// <summary>
        /// Begin a new variable debugging scope.
        /// </summary>
        public void DebugStartScope()
        {
            _ilgen!.BeginScope();
        }
 
        /// <summary>
        /// End a new debugging scope.
        /// </summary>
        public void DebugEndScope()
        {
            _ilgen!.EndScope();
        }
 
        /// <summary>
        /// Correlate the current IL generation position with the current source position.
        /// </summary>
        public void DebugSequencePoint(ISourceLineInfo sourceInfo)
        {
            Debug.Assert(_isDebug && _lastSourceInfo != null);
            Debug.Assert(sourceInfo != null);
 
            // When emitting sequence points, be careful to always follow two rules:
            // 1. Never emit adjacent sequence points, as this messes up the debugger.  We guarantee this by
            //    always emitting a Nop before every sequence point.
            // 2. The runtime enforces a rule that BP sequence points can only appear at zero stack depth,
            //    or if a NOP instruction is placed before them.  We guarantee this by always emitting a Nop
            //    before every sequence point.
            //    <spec>http://devdiv/Documents/Whidbey/CLR/CurrentSpecs/Debugging%20and%20Profiling/JIT-Determined%20Sequence%20Points.doc</spec>
            Emit(OpCodes.Nop);
            MarkSequencePoint(sourceInfo);
        }
 
        private string? _lastUriString;
        private string? _lastFileName;
 
        // SQLBUDT 278010: debugger does not work with network paths in uri format, like file://server/share/dir/file
        private string GetFileName(ISourceLineInfo sourceInfo)
        {
            string uriString = sourceInfo.Uri!;
            if ((object)uriString == (object?)_lastUriString)
            {
                return _lastFileName!;
            }
 
            _lastUriString = uriString;
            _lastFileName = SourceLineInfo.GetFileName(uriString);
            return _lastFileName;
        }
 
        private void MarkSequencePoint(ISourceLineInfo sourceInfo)
        {
            Debug.Assert(_module.EmitSymbols);
 
            // Do not emit adjacent 0xfeefee sequence points, as that slows down stepping in the debugger
            if (sourceInfo.IsNoSource && _lastSourceInfo != null && _lastSourceInfo.IsNoSource)
            {
                return;
            }
 
            string sourceFile = GetFileName(sourceInfo);
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                if (sourceInfo.IsNoSource)
                    _writerDump!.WriteLine("//[no source]");
                else
                {
                    if (sourceFile != _sourceFile)
                    {
                        _sourceFile = sourceFile;
                        _writerDump!.WriteLine("// Source File '{0}'", _sourceFile);
                    }
                    _writerDump!.WriteLine("//[{0},{1} -- {2},{3}]", sourceInfo.Start.Line, sourceInfo.Start.Pos, sourceInfo.End.Line, sourceInfo.End.Pos);
                }
            }
#endif
            //ISymbolDocumentWriter symDoc = this.module.AddSourceDocument(sourceFile);
            //this.ilgen.MarkSequencePoint(symDoc, sourceInfo.Start.Line, sourceInfo.Start.Pos, sourceInfo.End.Line, sourceInfo.End.Pos);
            _lastSourceInfo = sourceInfo;
        }
 
 
        //-----------------------------------------------
        // Pass through to ILGenerator
        //-----------------------------------------------
 
        public Label DefineLabel()
        {
            Label lbl = _ilgen!.DefineLabel();
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _symbols!.Add(lbl, ++_lblNum);
#endif
 
            return lbl;
        }
 
        public void MarkLabel(Label lbl)
        {
            if (_lastSourceInfo != null && !_lastSourceInfo.IsNoSource)
            {
                // Emit a "no source" sequence point, otherwise the debugger would show
                // a wrong line if we jumped to this label from another place
                DebugSequencePoint(SourceLineInfo.NoSource);
            }
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("Label {0}:", _symbols![lbl]);
#endif
 
            _ilgen!.MarkLabel(lbl);
        }
 
        public void Emit(OpCode opcode)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0}", opcode.Name);
#endif
            _ilgen!.Emit(opcode);
        }
 
        public void Emit(OpCode opcode, byte byteVal)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, byteVal);
#endif
            _ilgen!.Emit(opcode, byteVal);
        }
 
        public void Emit(OpCode opcode, ConstructorInfo constrInfo)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, constrInfo);
#endif
            _ilgen!.Emit(opcode, constrInfo);
        }
 
        public void Emit(OpCode opcode, double dblVal)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, dblVal);
#endif
            _ilgen!.Emit(opcode, dblVal);
        }
 
        public void Emit(OpCode opcode, FieldInfo fldInfo)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, fldInfo.Name);
#endif
            _ilgen!.Emit(opcode, fldInfo);
        }
 
        public void Emit(OpCode opcode, int intVal)
        {
            Debug.Assert(opcode.OperandType == OperandType.InlineI || opcode.OperandType == OperandType.InlineVar);
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, intVal);
#endif
            _ilgen!.Emit(opcode, intVal);
        }
 
        public void Emit(OpCode opcode, long longVal)
        {
            Debug.Assert(opcode.OperandType == OperandType.InlineI8);
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, longVal);
#endif
            _ilgen!.Emit(opcode, longVal);
        }
 
        public void Emit(OpCode opcode, Label lblVal)
        {
            Debug.Assert(!opcode.Equals(OpCodes.Br) && !opcode.Equals(OpCodes.Br_S), "Use EmitUnconditionalBranch and be careful not to emit unverifiable code.");
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} Label {1}", opcode.Name, _symbols![lblVal]);
#endif
            _ilgen!.Emit(opcode, lblVal);
        }
 
        public void Emit(OpCode opcode, Label[] arrLabels)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
            {
                _writerDump!.Write("  {0, -10} (Label {1}", opcode.Name, arrLabels.Length != 0 ? _symbols![arrLabels[0]]!.ToString() : "");
                for (int i = 1; i < arrLabels.Length; i++)
                {
                    _writerDump.Write(", Label {0}", _symbols![arrLabels[i]]);
                }
                _writerDump.WriteLine(")");
            }
#endif
            _ilgen!.Emit(opcode, arrLabels);
        }
 
        public void Emit(OpCode opcode, LocalBuilder locBldr)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1} ({2})", opcode.Name, _symbols![locBldr], locBldr.LocalType.Name);
#endif
            _ilgen!.Emit(opcode, locBldr);
        }
 
        public void Emit(OpCode opcode, sbyte sbyteVal)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, sbyteVal);
#endif
            _ilgen!.Emit(opcode, sbyteVal);
        }
 
        public void Emit(OpCode opcode, string strVal)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} \"{1}\"", opcode.Name, strVal);
#endif
            _ilgen!.Emit(opcode, strVal);
        }
 
        public void Emit(OpCode opcode, Type typVal)
        {
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} {1}", opcode.Name, typVal);
#endif
            _ilgen!.Emit(opcode, typVal);
        }
 
        /// <summary>
        /// Unconditional branch opcodes (OpCode.Br, OpCode.Br_S) can lead to unverifiable code in the following cases:
        ///
        ///   # DEAD CODE CASE
        ///     ldc_i4  1       # Stack depth == 1
        ///     br      Label2
        ///   Label1:
        ///     nop             # Dead code, so IL rules assume stack depth == 0.  This causes a verification error,
        ///                     # since next instruction has depth == 1
        ///   Label2:
        ///     pop             # Stack depth == 1
        ///     ret
        ///
        ///   # LATE BRANCH CASE
        ///     ldc_i4  1       # Stack depth == 1
        ///     br      Label2
        ///   Label1:
        ///     nop             # Not dead code, but since branch comes from below, IL rules assume stack depth = 0.
        ///                     # This causes a verification error, since next instruction has depth == 1
        ///   Label2:
        ///     pop             # Stack depth == 1
        ///     ret
        ///   Label3:
        ///     br      Label1  # Stack depth == 1
        ///
        /// This method works around the above limitations by using Brtrue or Brfalse in the following way:
        ///
        ///     ldc_i4  1       # Since this test is always true, this is a way of creating a path to the code that
        ///     brtrue  Label   # follows the brtrue instruction.
        ///
        ///     ldc_i4  1       # Since this test is always false, this is a way of creating a path to the code that
        ///     brfalse Label   # starts at Label.
        ///
        /// 1. If opcode == Brtrue or Brtrue_S, then 1 will be pushed and brtrue instruction will be generated.
        /// 2. If opcode == Brfalse or Brfalse_S, then 1 will be pushed and brfalse instruction will be generated.
        /// 3. If opcode == Br or Br_S, then a br instruction will be generated.
        /// </summary>
        public void EmitUnconditionalBranch(OpCode opcode, Label lblTarget)
        {
            if (!opcode.Equals(OpCodes.Br) && !opcode.Equals(OpCodes.Br_S))
            {
                Debug.Assert(opcode.Equals(OpCodes.Brtrue) || opcode.Equals(OpCodes.Brtrue_S) ||
                             opcode.Equals(OpCodes.Brfalse) || opcode.Equals(OpCodes.Brfalse_S));
                Emit(OpCodes.Ldc_I4_1);
            }
 
#if DEBUG
            if (XmlILTrace.IsEnabled)
                _writerDump!.WriteLine("  {0, -10} Label {1}", opcode.Name, _symbols![lblTarget]);
#endif
            _ilgen!.Emit(opcode, lblTarget);
 
            if (_lastSourceInfo != null && (opcode.Equals(OpCodes.Br) || opcode.Equals(OpCodes.Br_S)))
            {
                // Emit a "no source" sequence point, otherwise the following label will be preceded
                // with a dead Nop operation, which may lead to unverifiable code (SQLBUDT 423393).
                // We are guaranteed not to emit adjacent sequence points because Br or Br_S
                // instruction precedes this sequence point, and a Nop instruction precedes other
                // sequence points.
                MarkSequencePoint(SourceLineInfo.NoSource);
            }
        }
    }
}