Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / IlGen / GenerateHelper.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="GenerateHelper.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
7 using System;
8 using System.Globalization;
9 using System.Xml;
10 using System.Xml.XPath;
11 using System.Xml.Schema;
12 using System.Text;
13 using System.IO;
14 using System.Collections;
15 using System.Collections.Generic;
16 using System.Reflection;
17 using System.Reflection.Emit;
18 using System.Security;
19 using System.Diagnostics;
20 using System.Diagnostics.SymbolStore;
21 using System.Xml.Xsl.Qil;
22 using System.Xml.Xsl.Runtime;
23 using System.Runtime.Versioning;
24
25 namespace System.Xml.Xsl.IlGen {
26     using Res = System.Xml.Utils.Res;
27
28     /// <summary>
29     /// List of all XmlIL runtime constructors.
30     /// </summary>
31     internal class XmlILStorageMethods {
32         // Aggregates
33         public MethodInfo AggAvg;
34         public MethodInfo AggAvgResult;
35         public MethodInfo AggCreate;
36         public MethodInfo AggIsEmpty;
37         public MethodInfo AggMax;
38         public MethodInfo AggMaxResult;
39         public MethodInfo AggMin;
40         public MethodInfo AggMinResult;
41         public MethodInfo AggSum;
42         public MethodInfo AggSumResult;
43
44         // Sequences
45         public Type SeqType;
46         public FieldInfo SeqEmpty;
47         public MethodInfo SeqReuse;
48         public MethodInfo SeqReuseSgl;
49         public MethodInfo SeqAdd;
50         public MethodInfo SeqSortByKeys;
51
52         // IList<>
53         public Type IListType;
54         public MethodInfo IListCount;
55         public MethodInfo IListItem;
56
57         // XPathItem
58         public MethodInfo ValueAs;
59
60         // ToAtomicValue
61         public MethodInfo ToAtomicValue;
62
63         public XmlILStorageMethods(Type storageType) {
64             // Aggregates
65             if (storageType == typeof(int) || storageType == typeof(long) ||
66                 storageType == typeof(decimal) || storageType == typeof(double)) {
67
68                 Type aggType = Type.GetType("System.Xml.Xsl.Runtime." + storageType.Name + "Aggregator");
69                 AggAvg = XmlILMethods.GetMethod(aggType, "Average");
70                 AggAvgResult = XmlILMethods.GetMethod(aggType, "get_AverageResult");
71                 AggCreate = XmlILMethods.GetMethod(aggType, "Create");
72                 AggIsEmpty = XmlILMethods.GetMethod(aggType, "get_IsEmpty");
73                 AggMax = XmlILMethods.GetMethod(aggType, "Maximum");
74                 AggMaxResult = XmlILMethods.GetMethod(aggType, "get_MaximumResult");
75                 AggMin = XmlILMethods.GetMethod(aggType, "Minimum");
76                 AggMinResult = XmlILMethods.GetMethod(aggType, "get_MinimumResult");
77                 AggSum = XmlILMethods.GetMethod(aggType, "Sum");
78                 AggSumResult = XmlILMethods.GetMethod(aggType, "get_SumResult");
79             }
80
81             // Sequences
82             if (storageType == typeof(XPathNavigator)) {
83                 SeqType = typeof(XmlQueryNodeSequence);
84                 SeqAdd = XmlILMethods.GetMethod(SeqType, "AddClone");
85             }
86             else if (storageType == typeof(XPathItem)) {
87                 SeqType = typeof(XmlQueryItemSequence);
88                 SeqAdd = XmlILMethods.GetMethod(SeqType, "AddClone");
89             }
90             else {
91                 SeqType = typeof(XmlQuerySequence<>).MakeGenericType(storageType);
92                 SeqAdd = XmlILMethods.GetMethod(SeqType, "Add");
93             }
94
95             SeqEmpty = SeqType.GetField("Empty");
96             SeqReuse = XmlILMethods.GetMethod(SeqType, "CreateOrReuse", SeqType);
97             SeqReuseSgl = XmlILMethods.GetMethod(SeqType, "CreateOrReuse", SeqType, storageType);
98             SeqSortByKeys = XmlILMethods.GetMethod(SeqType, "SortByKeys");
99
100             // IList<>
101             IListType = typeof(IList<>).MakeGenericType(storageType);
102             IListItem = XmlILMethods.GetMethod(IListType, "get_Item");
103             IListCount = XmlILMethods.GetMethod(typeof(ICollection<>).MakeGenericType(storageType), "get_Count");
104
105             // XPathItem.ValueAsXXX
106             if (storageType == typeof(string))
107                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_Value");
108             else if (storageType == typeof(int))
109                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_ValueAsInt");
110             else if (storageType == typeof(long))
111                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_ValueAsLong");
112             else if (storageType == typeof(DateTime))
113                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_ValueAsDateTime");
114             else if (storageType == typeof(double))
115                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_ValueAsDouble");
116             else if (storageType == typeof(bool))
117                 ValueAs = XmlILMethods.GetMethod(typeof(XPathItem), "get_ValueAsBoolean");
118
119             // XmlILStorageConverter.XXXToAtomicValue
120             if (storageType == typeof(byte[]))
121                 ToAtomicValue = XmlILMethods.GetMethod(typeof(XmlILStorageConverter), "BytesToAtomicValue");
122             else if (storageType != typeof(XPathItem) && storageType != typeof(XPathNavigator))
123                 ToAtomicValue = XmlILMethods.GetMethod(typeof(XmlILStorageConverter), storageType.Name + "ToAtomicValue");
124         }
125     }
126
127     /// <summary>
128     /// List of all XmlIL runtime constructors.
129     /// </summary>
130     internal static class XmlILConstructors {
131         public static readonly ConstructorInfo DecFromParts = GetConstructor(typeof(decimal), typeof(int), typeof(int), typeof(int), typeof(bool), typeof(byte));
132         public static readonly ConstructorInfo DecFromInt32 = GetConstructor(typeof(decimal), typeof(int));
133         public static readonly ConstructorInfo DecFromInt64 = GetConstructor(typeof(decimal), typeof(long));
134         public static readonly ConstructorInfo Debuggable = GetConstructor(typeof(DebuggableAttribute), typeof(DebuggableAttribute.DebuggingModes));
135         public static readonly ConstructorInfo NonUserCode = GetConstructor(typeof(DebuggerNonUserCodeAttribute));
136         public static readonly ConstructorInfo QName = GetConstructor(typeof(XmlQualifiedName), typeof(string), typeof(string));
137         public static readonly ConstructorInfo StepThrough = GetConstructor(typeof(DebuggerStepThroughAttribute));
138         public static readonly ConstructorInfo Transparent = GetConstructor(typeof(SecurityTransparentAttribute));
139
140         private static ConstructorInfo GetConstructor(Type className) {
141             ConstructorInfo constrInfo = className.GetConstructor(new Type[] {});
142             Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
143             return constrInfo;
144         }
145
146         private static ConstructorInfo GetConstructor(Type className, params Type[] args) {
147             ConstructorInfo constrInfo = className.GetConstructor(args);
148             Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
149             return constrInfo;
150         }
151     }
152
153
154     /// <summary>
155     /// List of all XmlIL runtime methods.
156     /// </summary>
157     internal static class XmlILMethods {
158         // Iterators
159         public static readonly MethodInfo AncCreate = GetMethod(typeof(AncestorIterator), "Create");
160         public static readonly MethodInfo AncNext = GetMethod(typeof(AncestorIterator), "MoveNext");
161         public static readonly MethodInfo AncDOCreate = GetMethod(typeof(AncestorDocOrderIterator), "Create");
162         public static readonly MethodInfo AncDONext = GetMethod(typeof(AncestorDocOrderIterator), "MoveNext");
163         public static readonly MethodInfo AttrContentCreate = GetMethod(typeof(AttributeContentIterator), "Create");
164         public static readonly MethodInfo AttrContentNext = GetMethod(typeof(AttributeContentIterator), "MoveNext");
165         public static readonly MethodInfo AttrCreate = GetMethod(typeof(AttributeIterator), "Create");
166         public static readonly MethodInfo AttrNext = GetMethod(typeof(AttributeIterator), "MoveNext");
167         public static readonly MethodInfo ContentCreate = GetMethod(typeof(ContentIterator), "Create");
168         public static readonly MethodInfo ContentNext = GetMethod(typeof(ContentIterator), "MoveNext");
169         public static readonly MethodInfo ContentMergeCreate = GetMethod(typeof(ContentMergeIterator), "Create");
170         public static readonly MethodInfo ContentMergeNext = GetMethod(typeof(ContentMergeIterator), "MoveNext");
171         public static readonly MethodInfo DescCreate = GetMethod(typeof(DescendantIterator), "Create");
172         public static readonly MethodInfo DescNext = GetMethod(typeof(DescendantIterator), "MoveNext");
173         public static readonly MethodInfo DescMergeCreate = GetMethod(typeof(DescendantMergeIterator), "Create");
174         public static readonly MethodInfo DescMergeNext = GetMethod(typeof(DescendantMergeIterator), "MoveNext");
175         public static readonly MethodInfo DiffCreate = GetMethod(typeof(DifferenceIterator), "Create");
176         public static readonly MethodInfo DiffNext = GetMethod(typeof(DifferenceIterator), "MoveNext");
177         public static readonly MethodInfo DodMergeCreate = GetMethod(typeof(DodSequenceMerge), "Create");
178         public static readonly MethodInfo DodMergeAdd = GetMethod(typeof(DodSequenceMerge), "AddSequence");
179         public static readonly MethodInfo DodMergeSeq = GetMethod(typeof(DodSequenceMerge), "MergeSequences");
180         public static readonly MethodInfo ElemContentCreate = GetMethod(typeof(ElementContentIterator), "Create");
181         public static readonly MethodInfo ElemContentNext = GetMethod(typeof(ElementContentIterator), "MoveNext");
182         public static readonly MethodInfo FollSibCreate = GetMethod(typeof(FollowingSiblingIterator), "Create");
183         public static readonly MethodInfo FollSibNext = GetMethod(typeof(FollowingSiblingIterator), "MoveNext");
184         public static readonly MethodInfo FollSibMergeCreate = GetMethod(typeof(FollowingSiblingMergeIterator), "Create");
185         public static readonly MethodInfo FollSibMergeNext = GetMethod(typeof(FollowingSiblingMergeIterator), "MoveNext");
186         public static readonly MethodInfo IdCreate = GetMethod(typeof(IdIterator), "Create");
187         public static readonly MethodInfo IdNext = GetMethod(typeof(IdIterator), "MoveNext");
188         public static readonly MethodInfo InterCreate = GetMethod(typeof(IntersectIterator), "Create");
189         public static readonly MethodInfo InterNext = GetMethod(typeof(IntersectIterator), "MoveNext");
190         public static readonly MethodInfo KindContentCreate = GetMethod(typeof(NodeKindContentIterator), "Create");
191         public static readonly MethodInfo KindContentNext = GetMethod(typeof(NodeKindContentIterator), "MoveNext");
192         public static readonly MethodInfo NmspCreate = GetMethod(typeof(NamespaceIterator), "Create");
193         public static readonly MethodInfo NmspNext = GetMethod(typeof(NamespaceIterator), "MoveNext");
194         public static readonly MethodInfo NodeRangeCreate = GetMethod(typeof(NodeRangeIterator), "Create");
195         public static readonly MethodInfo NodeRangeNext = GetMethod(typeof(NodeRangeIterator), "MoveNext");
196         public static readonly MethodInfo ParentCreate = GetMethod(typeof(ParentIterator), "Create");
197         public static readonly MethodInfo ParentNext = GetMethod(typeof(ParentIterator), "MoveNext");
198         public static readonly MethodInfo PrecCreate = GetMethod(typeof(PrecedingIterator), "Create");
199         public static readonly MethodInfo PrecNext = GetMethod(typeof(PrecedingIterator), "MoveNext");
200         public static readonly MethodInfo PreSibCreate = GetMethod(typeof(PrecedingSiblingIterator), "Create");
201         public static readonly MethodInfo PreSibNext = GetMethod(typeof(PrecedingSiblingIterator), "MoveNext");
202         public static readonly MethodInfo PreSibDOCreate = GetMethod(typeof(PrecedingSiblingDocOrderIterator), "Create");
203         public static readonly MethodInfo PreSibDONext = GetMethod(typeof(PrecedingSiblingDocOrderIterator), "MoveNext");
204         public static readonly MethodInfo SortKeyCreate = GetMethod(typeof(XmlSortKeyAccumulator), "Create");
205         public static readonly MethodInfo SortKeyDateTime = GetMethod(typeof(XmlSortKeyAccumulator), "AddDateTimeSortKey");
206         public static readonly MethodInfo SortKeyDecimal = GetMethod(typeof(XmlSortKeyAccumulator), "AddDecimalSortKey");
207         public static readonly MethodInfo SortKeyDouble = GetMethod(typeof(XmlSortKeyAccumulator), "AddDoubleSortKey");
208         public static readonly MethodInfo SortKeyEmpty = GetMethod(typeof(XmlSortKeyAccumulator), "AddEmptySortKey");
209         public static readonly MethodInfo SortKeyFinish = GetMethod(typeof(XmlSortKeyAccumulator), "FinishSortKeys");
210         public static readonly MethodInfo SortKeyInt = GetMethod(typeof(XmlSortKeyAccumulator), "AddIntSortKey");
211         public static readonly MethodInfo SortKeyInteger = GetMethod(typeof(XmlSortKeyAccumulator), "AddIntegerSortKey");
212         public static readonly MethodInfo SortKeyKeys = GetMethod(typeof(XmlSortKeyAccumulator), "get_Keys");
213         public static readonly MethodInfo SortKeyString = GetMethod(typeof(XmlSortKeyAccumulator), "AddStringSortKey");
214         public static readonly MethodInfo UnionCreate = GetMethod(typeof(UnionIterator), "Create");
215         public static readonly MethodInfo UnionNext = GetMethod(typeof(UnionIterator), "MoveNext");
216         public static readonly MethodInfo XPFollCreate = GetMethod(typeof(XPathFollowingIterator), "Create");
217         public static readonly MethodInfo XPFollNext = GetMethod(typeof(XPathFollowingIterator), "MoveNext");
218         public static readonly MethodInfo XPFollMergeCreate = GetMethod(typeof(XPathFollowingMergeIterator), "Create");
219         public static readonly MethodInfo XPFollMergeNext = GetMethod(typeof(XPathFollowingMergeIterator), "MoveNext");
220         public static readonly MethodInfo XPPrecCreate = GetMethod(typeof(XPathPrecedingIterator), "Create");
221         public static readonly MethodInfo XPPrecNext = GetMethod(typeof(XPathPrecedingIterator), "MoveNext");
222         public static readonly MethodInfo XPPrecDOCreate = GetMethod(typeof(XPathPrecedingDocOrderIterator), "Create");
223         public static readonly MethodInfo XPPrecDONext = GetMethod(typeof(XPathPrecedingDocOrderIterator), "MoveNext");
224         public static readonly MethodInfo XPPrecMergeCreate = GetMethod(typeof(XPathPrecedingMergeIterator), "Create");
225         public static readonly MethodInfo XPPrecMergeNext = GetMethod(typeof(XPathPrecedingMergeIterator), "MoveNext");
226
227         // XmlQueryRuntime
228         public static readonly MethodInfo AddNewIndex = GetMethod(typeof(XmlQueryRuntime), "AddNewIndex");
229         public static readonly MethodInfo ChangeTypeXsltArg = GetMethod(typeof(XmlQueryRuntime), "ChangeTypeXsltArgument", typeof(int), typeof(object), typeof(Type));
230         public static readonly MethodInfo ChangeTypeXsltResult = GetMethod(typeof(XmlQueryRuntime), "ChangeTypeXsltResult");
231         public static readonly MethodInfo CompPos = GetMethod(typeof(XmlQueryRuntime), "ComparePosition");
232         public static readonly MethodInfo Context = GetMethod(typeof(XmlQueryRuntime), "get_ExternalContext");
233         public static readonly MethodInfo CreateCollation = GetMethod(typeof(XmlQueryRuntime), "CreateCollation");
234         public static readonly MethodInfo DocOrder = GetMethod(typeof(XmlQueryRuntime), "DocOrderDistinct");
235         public static readonly MethodInfo EndRtfConstr = GetMethod(typeof(XmlQueryRuntime), "EndRtfConstruction");
236         public static readonly MethodInfo EndSeqConstr = GetMethod(typeof(XmlQueryRuntime), "EndSequenceConstruction");
237         public static readonly MethodInfo FindIndex = GetMethod(typeof(XmlQueryRuntime), "FindIndex");
238         public static readonly MethodInfo GenId = GetMethod(typeof(XmlQueryRuntime), "GenerateId");
239         public static readonly MethodInfo GetAtomizedName = GetMethod(typeof(XmlQueryRuntime), "GetAtomizedName");
240         public static readonly MethodInfo GetCollation = GetMethod(typeof(XmlQueryRuntime), "GetCollation");
241         public static readonly MethodInfo GetEarly = GetMethod(typeof(XmlQueryRuntime), "GetEarlyBoundObject");
242         public static readonly MethodInfo GetNameFilter = GetMethod(typeof(XmlQueryRuntime), "GetNameFilter");
243         public static readonly MethodInfo GetOutput = GetMethod(typeof(XmlQueryRuntime), "get_Output");
244         public static readonly MethodInfo GetGlobalValue = GetMethod(typeof(XmlQueryRuntime), "GetGlobalValue");
245         public static readonly MethodInfo GetTypeFilter = GetMethod(typeof(XmlQueryRuntime), "GetTypeFilter");
246         public static readonly MethodInfo GlobalComputed = GetMethod(typeof(XmlQueryRuntime), "IsGlobalComputed");
247         public static readonly MethodInfo ItemMatchesCode = GetMethod(typeof(XmlQueryRuntime), "MatchesXmlType", typeof(XPathItem), typeof(XmlTypeCode));
248         public static readonly MethodInfo ItemMatchesType = GetMethod(typeof(XmlQueryRuntime), "MatchesXmlType", typeof(XPathItem), typeof(int));
249         public static readonly MethodInfo QNameEqualLit = GetMethod(typeof(XmlQueryRuntime), "IsQNameEqual", typeof(XPathNavigator), typeof(int), typeof(int));
250         public static readonly MethodInfo QNameEqualNav = GetMethod(typeof(XmlQueryRuntime), "IsQNameEqual", typeof(XPathNavigator), typeof(XPathNavigator));
251         public static readonly MethodInfo RtfConstr = GetMethod(typeof(XmlQueryRuntime), "TextRtfConstruction");
252         public static readonly MethodInfo SendMessage = GetMethod(typeof(XmlQueryRuntime), "SendMessage");
253         public static readonly MethodInfo SeqMatchesCode = GetMethod(typeof(XmlQueryRuntime), "MatchesXmlType", typeof(IList<XPathItem>), typeof(XmlTypeCode));
254         public static readonly MethodInfo SeqMatchesType = GetMethod(typeof(XmlQueryRuntime), "MatchesXmlType", typeof(IList<XPathItem>), typeof(int));
255         public static readonly MethodInfo SetGlobalValue = GetMethod(typeof(XmlQueryRuntime), "SetGlobalValue");
256         public static readonly MethodInfo StartRtfConstr = GetMethod(typeof(XmlQueryRuntime), "StartRtfConstruction");
257         public static readonly MethodInfo StartSeqConstr = GetMethod(typeof(XmlQueryRuntime), "StartSequenceConstruction");
258         public static readonly MethodInfo TagAndMappings = GetMethod(typeof(XmlQueryRuntime), "ParseTagName", typeof(string), typeof(int));
259         public static readonly MethodInfo TagAndNamespace = GetMethod(typeof(XmlQueryRuntime), "ParseTagName", typeof(string), typeof(string));
260         public static readonly MethodInfo ThrowException = GetMethod(typeof(XmlQueryRuntime), "ThrowException");
261         public static readonly MethodInfo XsltLib = GetMethod(typeof(XmlQueryRuntime), "get_XsltFunctions");
262
263         // XmlQueryContext
264         public static readonly MethodInfo GetDataSource = GetMethod(typeof(XmlQueryContext), "GetDataSource");
265         public static readonly MethodInfo GetDefaultDataSource = GetMethod(typeof(XmlQueryContext), "get_DefaultDataSource");
266         public static readonly MethodInfo GetParam = GetMethod(typeof(XmlQueryContext), "GetParameter");
267         public static readonly MethodInfo InvokeXsltLate = GetMethod(typeof(XmlQueryContext), "InvokeXsltLateBoundFunction");
268
269         // XmlILIndex
270         public static readonly MethodInfo IndexAdd = GetMethod(typeof(XmlILIndex), "Add");
271         public static readonly MethodInfo IndexLookup = GetMethod(typeof(XmlILIndex), "Lookup");
272
273         // XPathItem
274         public static readonly MethodInfo ItemIsNode = GetMethod(typeof(XPathItem), "get_IsNode");
275         public static readonly MethodInfo Value = GetMethod(typeof(XPathItem), "get_Value");
276         public static readonly MethodInfo ValueAsAny = GetMethod(typeof(XPathItem), "ValueAs", typeof(Type), typeof(IXmlNamespaceResolver));
277
278         // XPathNavigator
279         public static readonly MethodInfo NavClone = GetMethod(typeof(XPathNavigator), "Clone");
280         public static readonly MethodInfo NavLocalName = GetMethod(typeof(XPathNavigator), "get_LocalName");
281         public static readonly MethodInfo NavMoveAttr = GetMethod(typeof(XPathNavigator), "MoveToAttribute", typeof(string), typeof(string));
282         public static readonly MethodInfo NavMoveId = GetMethod(typeof(XPathNavigator), "MoveToId");
283         public static readonly MethodInfo NavMoveParent = GetMethod(typeof(XPathNavigator), "MoveToParent");
284         public static readonly MethodInfo NavMoveRoot = GetMethod(typeof(XPathNavigator), "MoveToRoot");
285         public static readonly MethodInfo NavMoveTo = GetMethod(typeof(XPathNavigator), "MoveTo");
286         public static readonly MethodInfo NavNmsp = GetMethod(typeof(XPathNavigator), "get_NamespaceURI");
287         public static readonly MethodInfo NavPrefix = GetMethod(typeof(XPathNavigator), "get_Prefix");
288         public static readonly MethodInfo NavSamePos = GetMethod(typeof(XPathNavigator), "IsSamePosition");
289         public static readonly MethodInfo NavType = GetMethod(typeof(XPathNavigator), "get_NodeType");
290
291         // XmlQueryOutput methods
292         public static readonly MethodInfo StartElemLitName = GetMethod(typeof(XmlQueryOutput), "WriteStartElement", typeof(string), typeof(string), typeof(string));
293         public static readonly MethodInfo StartElemLocName = GetMethod(typeof(XmlQueryOutput), "WriteStartElementLocalName", typeof(string));
294         public static readonly MethodInfo EndElemStackName = GetMethod(typeof(XmlQueryOutput), "WriteEndElement");
295         public static readonly MethodInfo StartAttrLitName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttribute", typeof(string), typeof(string), typeof(string));
296         public static readonly MethodInfo StartAttrLocName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeLocalName", typeof(string));
297         public static readonly MethodInfo EndAttr = GetMethod(typeof(XmlQueryOutput), "WriteEndAttribute");
298         public static readonly MethodInfo Text = GetMethod(typeof(XmlQueryOutput), "WriteString");
299         public static readonly MethodInfo NoEntText = GetMethod(typeof(XmlQueryOutput), "WriteRaw", typeof(string));
300
301         public static readonly MethodInfo StartTree = GetMethod(typeof(XmlQueryOutput), "StartTree");
302         public static readonly MethodInfo EndTree = GetMethod(typeof(XmlQueryOutput), "EndTree");
303
304         public static readonly MethodInfo StartElemLitNameUn = GetMethod(typeof(XmlQueryOutput), "WriteStartElementUnchecked", typeof(string), typeof(string), typeof(string));
305         public static readonly MethodInfo StartElemLocNameUn = GetMethod(typeof(XmlQueryOutput), "WriteStartElementUnchecked", typeof(string));
306         public static readonly MethodInfo StartContentUn = GetMethod(typeof(XmlQueryOutput), "StartElementContentUnchecked");
307         public static readonly MethodInfo EndElemLitNameUn = GetMethod(typeof(XmlQueryOutput), "WriteEndElementUnchecked", typeof(string), typeof(string), typeof(string));
308         public static readonly MethodInfo EndElemLocNameUn = GetMethod(typeof(XmlQueryOutput), "WriteEndElementUnchecked", typeof(string));
309         public static readonly MethodInfo StartAttrLitNameUn = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeUnchecked", typeof(string), typeof(string), typeof(string));
310         public static readonly MethodInfo StartAttrLocNameUn = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeUnchecked", typeof(string));
311         public static readonly MethodInfo EndAttrUn = GetMethod(typeof(XmlQueryOutput), "WriteEndAttributeUnchecked");
312         public static readonly MethodInfo NamespaceDeclUn = GetMethod(typeof(XmlQueryOutput), "WriteNamespaceDeclarationUnchecked");
313         public static readonly MethodInfo TextUn = GetMethod(typeof(XmlQueryOutput), "WriteStringUnchecked");
314         public static readonly MethodInfo NoEntTextUn = GetMethod(typeof(XmlQueryOutput), "WriteRawUnchecked");
315
316         public static readonly MethodInfo StartRoot = GetMethod(typeof(XmlQueryOutput), "WriteStartRoot");
317         public static readonly MethodInfo EndRoot = GetMethod(typeof(XmlQueryOutput), "WriteEndRoot");
318         public static readonly MethodInfo StartElemCopyName = GetMethod(typeof(XmlQueryOutput), "WriteStartElementComputed", typeof(XPathNavigator));
319         public static readonly MethodInfo StartElemMapName = GetMethod(typeof(XmlQueryOutput), "WriteStartElementComputed", typeof(string), typeof(int));
320         public static readonly MethodInfo StartElemNmspName = GetMethod(typeof(XmlQueryOutput), "WriteStartElementComputed", typeof(string), typeof(string));
321         public static readonly MethodInfo StartElemQName = GetMethod(typeof(XmlQueryOutput), "WriteStartElementComputed", typeof(XmlQualifiedName));
322         public static readonly MethodInfo StartAttrCopyName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeComputed", typeof(XPathNavigator));
323         public static readonly MethodInfo StartAttrMapName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeComputed", typeof(string), typeof(int));
324         public static readonly MethodInfo StartAttrNmspName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeComputed", typeof(string), typeof(string));
325         public static readonly MethodInfo StartAttrQName = GetMethod(typeof(XmlQueryOutput), "WriteStartAttributeComputed", typeof(XmlQualifiedName));
326         public static readonly MethodInfo NamespaceDecl = GetMethod(typeof(XmlQueryOutput), "WriteNamespaceDeclaration");
327         public static readonly MethodInfo StartComment = GetMethod(typeof(XmlQueryOutput), "WriteStartComment");
328         public static readonly MethodInfo CommentText = GetMethod(typeof(XmlQueryOutput), "WriteCommentString");
329         public static readonly MethodInfo EndComment = GetMethod(typeof(XmlQueryOutput), "WriteEndComment");
330         public static readonly MethodInfo StartPI = GetMethod(typeof(XmlQueryOutput), "WriteStartProcessingInstruction");
331         public static readonly MethodInfo PIText = GetMethod(typeof(XmlQueryOutput), "WriteProcessingInstructionString");
332         public static readonly MethodInfo EndPI = GetMethod(typeof(XmlQueryOutput), "WriteEndProcessingInstruction");
333         public static readonly MethodInfo WriteItem = GetMethod(typeof(XmlQueryOutput), "WriteItem");
334         public static readonly MethodInfo CopyOf = GetMethod(typeof(XmlQueryOutput), "XsltCopyOf");
335         public static readonly MethodInfo StartCopy = GetMethod(typeof(XmlQueryOutput), "StartCopy");
336         public static readonly MethodInfo EndCopy = GetMethod(typeof(XmlQueryOutput), "EndCopy");
337
338         // Datatypes
339         public static readonly MethodInfo DecAdd = GetMethod(typeof(decimal), "Add");
340         public static readonly MethodInfo DecCmp = GetMethod(typeof(decimal), "Compare", typeof(decimal), typeof(decimal));
341         public static readonly MethodInfo DecEq = GetMethod(typeof(decimal), "Equals", typeof(decimal), typeof(decimal));
342         public static readonly MethodInfo DecSub = GetMethod(typeof(decimal), "Subtract");
343         public static readonly MethodInfo DecMul = GetMethod(typeof(decimal), "Multiply");
344         public static readonly MethodInfo DecDiv = GetMethod(typeof(decimal), "Divide");
345         public static readonly MethodInfo DecRem = GetMethod(typeof(decimal), "Remainder");
346         public static readonly MethodInfo DecNeg = GetMethod(typeof(decimal), "Negate");
347         public static readonly MethodInfo QNameEq = GetMethod(typeof(XmlQualifiedName), "Equals");
348         public static readonly MethodInfo StrEq = GetMethod(typeof(string), "Equals", typeof(string), typeof(string));
349         public static readonly MethodInfo StrCat2 = GetMethod(typeof(string), "Concat", typeof(string), typeof(string));
350         public static readonly MethodInfo StrCat3 = GetMethod(typeof(string), "Concat", typeof(string), typeof(string), typeof(string));
351         public static readonly MethodInfo StrCat4 = GetMethod(typeof(string), "Concat", typeof(string), typeof(string), typeof(string), typeof(string));
352         public static readonly MethodInfo StrCmp = GetMethod(typeof(string), "CompareOrdinal", typeof(string), typeof(string));
353         public static readonly MethodInfo StrLen = GetMethod(typeof(string), "get_Length");
354
355         // XsltConvert
356         public static readonly MethodInfo DblToDec = GetMethod(typeof(XsltConvert), "ToDecimal", typeof(double));
357         public static readonly MethodInfo DblToInt = GetMethod(typeof(XsltConvert), "ToInt", typeof(double));
358         public static readonly MethodInfo DblToLng = GetMethod(typeof(XsltConvert), "ToLong", typeof(double));
359         public static readonly MethodInfo DblToStr = GetMethod(typeof(XsltConvert), "ToString", typeof(double));
360         public static readonly MethodInfo DecToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(decimal));
361         public static readonly MethodInfo DTToStr = GetMethod(typeof(XsltConvert), "ToString", typeof(DateTime));
362         public static readonly MethodInfo IntToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(int));
363         public static readonly MethodInfo LngToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(long));
364         public static readonly MethodInfo StrToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(string));
365         public static readonly MethodInfo StrToDT = GetMethod(typeof(XsltConvert), "ToDateTime", typeof(string));
366
367         public static readonly MethodInfo ItemToBool = GetMethod(typeof(XsltConvert), "ToBoolean", typeof(XPathItem));
368         public static readonly MethodInfo ItemToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(XPathItem));
369         public static readonly MethodInfo ItemToStr = GetMethod(typeof(XsltConvert), "ToString", typeof(XPathItem));
370         public static readonly MethodInfo ItemToNode = GetMethod(typeof(XsltConvert), "ToNode", typeof(XPathItem));
371         public static readonly MethodInfo ItemToNodes = GetMethod(typeof(XsltConvert), "ToNodeSet", typeof(XPathItem));
372
373         public static readonly MethodInfo ItemsToBool = GetMethod(typeof(XsltConvert), "ToBoolean", typeof(IList<XPathItem>));
374         public static readonly MethodInfo ItemsToDbl = GetMethod(typeof(XsltConvert), "ToDouble", typeof(IList<XPathItem>));
375         public static readonly MethodInfo ItemsToNode = GetMethod(typeof(XsltConvert), "ToNode", typeof(IList<XPathItem>));
376         public static readonly MethodInfo ItemsToNodes = GetMethod(typeof(XsltConvert), "ToNodeSet", typeof(IList<XPathItem>));
377         public static readonly MethodInfo ItemsToStr = GetMethod(typeof(XsltConvert), "ToString", typeof(IList<XPathItem>));
378
379         // StringConcat
380         public static readonly MethodInfo StrCatCat = GetMethod(typeof(StringConcat), "Concat");
381         public static readonly MethodInfo StrCatClear = GetMethod(typeof(StringConcat), "Clear");
382         public static readonly MethodInfo StrCatResult = GetMethod(typeof(StringConcat), "GetResult");
383         public static readonly MethodInfo StrCatDelim = GetMethod(typeof(StringConcat), "set_Delimiter");
384
385         // XmlILStorageConverter
386         public static readonly MethodInfo NavsToItems = GetMethod(typeof(XmlILStorageConverter), "NavigatorsToItems");
387         public static readonly MethodInfo ItemsToNavs = GetMethod(typeof(XmlILStorageConverter), "ItemsToNavigators");
388
389         // XmlQueryNodeSequence
390         public static readonly MethodInfo SetDod = GetMethod(typeof(XmlQueryNodeSequence), "set_IsDocOrderDistinct");
391
392         // Miscellaneous
393         public static readonly MethodInfo GetTypeFromHandle = GetMethod(typeof(Type), "GetTypeFromHandle");
394         public static readonly MethodInfo InitializeArray = GetMethod(typeof(System.Runtime.CompilerServices.RuntimeHelpers), "InitializeArray");
395         public static readonly Dictionary<Type, XmlILStorageMethods> StorageMethods;
396
397         static XmlILMethods() {
398             StorageMethods = new Dictionary<Type, XmlILStorageMethods>();
399             StorageMethods[typeof(string)] = new XmlILStorageMethods(typeof(string));
400             StorageMethods[typeof(bool)] = new XmlILStorageMethods(typeof(bool));
401             StorageMethods[typeof(int)] = new XmlILStorageMethods(typeof(int));
402             StorageMethods[typeof(long)] = new XmlILStorageMethods(typeof(long));
403             StorageMethods[typeof(decimal)] = new XmlILStorageMethods(typeof(decimal));
404             StorageMethods[typeof(double)] = new XmlILStorageMethods(typeof(double));
405             StorageMethods[typeof(float)] = new XmlILStorageMethods(typeof(float));
406             StorageMethods[typeof(DateTime)] = new XmlILStorageMethods(typeof(DateTime));
407             StorageMethods[typeof(byte[])] = new XmlILStorageMethods(typeof(byte[]));
408             StorageMethods[typeof(XmlQualifiedName)] = new XmlILStorageMethods(typeof(XmlQualifiedName));
409             StorageMethods[typeof(TimeSpan)] = new XmlILStorageMethods(typeof(TimeSpan));
410             StorageMethods[typeof(XPathItem)] = new XmlILStorageMethods(typeof(XPathItem));
411             StorageMethods[typeof(XPathNavigator)] = new XmlILStorageMethods(typeof(XPathNavigator));
412         }
413
414         public static MethodInfo GetMethod(Type className, string methName) {
415             MethodInfo methInfo = className.GetMethod(methName);
416             Debug.Assert(methInfo != null, "Method " + className.Name + "." + methName + " cannot be null.");
417             return methInfo;
418         }
419
420         public static MethodInfo GetMethod(Type className, string methName, params Type[] args) {
421             MethodInfo methInfo = className.GetMethod(methName, args);
422             Debug.Assert(methInfo != null, "Method " + methName + " cannot be null.");
423             return methInfo;
424         }
425     }
426
427
428     /// <summary>
429     /// When named nodes are constructed, there are several possible ways for their names to be created.
430     /// </summary>
431     internal enum GenerateNameType {
432         LiteralLocalName,       // Local name is a literal string; namespace is null
433         LiteralName,            // All parts of the name are literal strings
434         CopiedName,             // Name should be copied from a navigator
435         TagNameAndMappings,     // Tagname contains prefix:localName and prefix is mapped to a namespace
436         TagNameAndNamespace,    // Tagname contains prefix:localName and namespace is provided
437         QName,                  // Name is computed QName (no prefix available)
438         StackName,              // Element name has already been pushed onto XmlQueryOutput stack
439     }
440
441     /// <summary>
442     /// Contains helper methods used during the code generation phase.
443     /// </summary>
444     internal class GenerateHelper {
445         private MethodBase methInfo;
446         private ILGenerator ilgen;
447         private LocalBuilder locXOut;
448         private XmlILModule module;
449         private bool isDebug, initWriters;
450         private StaticDataManager staticData;
451         private ISourceLineInfo lastSourceInfo;
452         private MethodInfo methSyncToNav;
453
454     #if DEBUG
455         private int lblNum;
456         private Hashtable symbols;
457         private int numLocals;
458         private string sourceFile;
459         private TextWriter writerDump;
460     #endif
461
462         /// <summary>
463         /// Cache metadata used during code-generation phase.
464         /// </summary>
465         // SxS note: Using hardcoded "dump.il" is an SxS issue. Since we are doing this ONLY in debug builds 
466         // and only for tracing purposes and MakeVersionSafeName does not seem to be able to handle file 
467         // extensions correctly I decided to suppress the SxS message (as advised by SxS guys).
468         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
469         [ResourceExposure(ResourceScope.None)]
470         public GenerateHelper(XmlILModule module, bool isDebug) {
471             this.isDebug = isDebug;
472             this.module = module;
473             this.staticData = new StaticDataManager();
474
475         #if DEBUG
476             if (XmlILTrace.IsEnabled)
477                 XmlILTrace.PrepareTraceWriter("dump.il");
478         #endif
479         }
480
481         /// <summary>
482         /// Begin generating code within a new method.
483         /// </summary>
484         // SxS note: Using hardcoded "dump.il" is an SxS issue. Since we are doing this ONLY in debug builds 
485         // and only for tracing purposes and MakeVersionSafeName does not seem to be able to handle file 
486         // extensions correctly I decided to suppress the SxS message (as advised by SxS guys).
487         [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
488         [ResourceExposure(ResourceScope.None)]
489         public void MethodBegin(MethodBase methInfo, ISourceLineInfo sourceInfo, bool initWriters) {
490             this.methInfo = methInfo;
491             this.ilgen = XmlILModule.DefineMethodBody(methInfo);
492             this.lastSourceInfo = null;
493
494         #if DEBUG
495             if (XmlILTrace.IsEnabled) {
496                 this.numLocals = 0;
497                 this.symbols = new Hashtable();
498                 this.lblNum = 0;
499                 this.sourceFile = null;
500
501                 this.writerDump = XmlILTrace.GetTraceWriter("dump.il");
502                 this.writerDump.WriteLine(".method {0}()", methInfo.Name);
503                 this.writerDump.WriteLine("{");
504             }
505         #endif
506
507             if (this.isDebug) {
508                 DebugStartScope();
509
510                 // DebugInfo: Sequence point just before generating code for this function
511                 if (sourceInfo != null) {
512                     // Don't call DebugSequencePoint, as it puts Nop *before* the sequence point.  That is
513                     // wrong in this case, because we need source line information to be emitted before any
514                     // IL instruction so that stepping into this function won't end up in the assembly window.
515                     // We still guarantee that:
516                     //   1. Two sequence points are never adjacent, since this is the 1st sequence point
517                     //   2. Stack depth is 0, since this is the very beginning of the method
518                     MarkSequencePoint(sourceInfo);
519                     Emit(OpCodes.Nop);
520                 }
521             }
522             else if (this.module.EmitSymbols) {
523                 // For a retail build, put source information on methods only
524                 if (sourceInfo != null) {
525                     MarkSequencePoint(sourceInfo);
526                     // Set this.lastSourceInfo back to null to prevent generating additional sequence points
527                     // in this method.
528                     this.lastSourceInfo = null;
529                 }
530             }
531
532             this.initWriters = false;
533             if (initWriters) {
534                 EnsureWriter();
535                 LoadQueryRuntime();
536                 Call(XmlILMethods.GetOutput);
537                 Emit(OpCodes.Stloc, this.locXOut);
538             }
539         }
540
541         /// <summary>
542         /// Generate "ret" instruction and branch fixup jump table.
543         /// </summary>
544         public void MethodEnd() {
545             Emit(OpCodes.Ret);
546
547         #if DEBUG
548             if (XmlILTrace.IsEnabled) {
549                 this.writerDump.WriteLine("}");
550                 this.writerDump.WriteLine("");
551                 this.writerDump.Close();
552             }
553         #endif
554
555             if (this.isDebug)
556                 DebugEndScope();
557         }
558
559
560         //-----------------------------------------------
561         // Helper Global Methods
562         //-----------------------------------------------
563
564         /// <summary>
565         /// Call a static method which attempts to reuse a navigator.
566         /// </summary>
567         public void CallSyncToNavigator() {
568             // Get helper method from module
569             if (this.methSyncToNav == null)
570                 this.methSyncToNav = this.module.FindMethod("SyncToNavigator");
571
572             Call(this.methSyncToNav);
573         }
574
575         //-----------------------------------------------
576         // StaticDataManager
577         //-----------------------------------------------
578
579         /// <summary>
580         /// This internal class manages literal names, literal types, and storage for global variables.
581         /// </summary>
582         public StaticDataManager StaticData {
583             get { return this.staticData; }
584         }
585
586
587         //-----------------------------------------------
588         // Constants
589         //-----------------------------------------------
590
591         /// <summary>
592         /// Generate the optimal Ldc_I4 instruction based on intVal.
593         /// </summary>
594         public void LoadInteger(int intVal) {
595             OpCode opcode;
596
597             if (intVal >= -1 && intVal < 9) {
598                 switch (intVal) {
599                     case -1: opcode = OpCodes.Ldc_I4_M1; break;
600                     case 0: opcode = OpCodes.Ldc_I4_0; break;
601                     case 1: opcode = OpCodes.Ldc_I4_1; break;
602                     case 2: opcode = OpCodes.Ldc_I4_2; break;
603                     case 3: opcode = OpCodes.Ldc_I4_3; break;
604                     case 4: opcode = OpCodes.Ldc_I4_4; break;
605                     case 5: opcode = OpCodes.Ldc_I4_5; break;
606                     case 6: opcode = OpCodes.Ldc_I4_6; break;
607                     case 7: opcode = OpCodes.Ldc_I4_7; break;
608                     case 8: opcode = OpCodes.Ldc_I4_8; break;
609                     default: Debug.Assert(false); return;
610                 }
611                 Emit(opcode);
612             }
613             else if (intVal >= -128 && intVal <= 127)
614                 Emit(OpCodes.Ldc_I4_S, (sbyte) intVal);
615             else
616                 Emit(OpCodes.Ldc_I4, intVal);
617         }
618
619         public void LoadBoolean(bool boolVal) {
620             Emit(boolVal ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
621         }
622
623         public void LoadType(Type clrTyp) {
624             Emit(OpCodes.Ldtoken, clrTyp);
625             Call(XmlILMethods.GetTypeFromHandle);
626         }
627
628
629         //-----------------------------------------------
630         // Local variables
631         //-----------------------------------------------
632
633         /// <summary>
634         /// Generate a new local variable.  Add a numeric suffix to name that ensures that all
635         /// local variable names will be unique (for readability).
636         /// </summary>
637         public LocalBuilder DeclareLocal(string name, Type type) {
638             LocalBuilder locBldr = this.ilgen.DeclareLocal(type);
639         #if DEBUG
640             if (XmlILTrace.IsEnabled) {
641                 // Set name for internal MS debugging.  This is not the user-defined name--that will be set later
642                 if (this.isDebug)
643                     locBldr.SetLocalSymInfo(name + this.numLocals.ToString(CultureInfo.InvariantCulture));
644
645                 this.symbols.Add(locBldr, name + this.numLocals.ToString(CultureInfo.InvariantCulture));
646                 this.numLocals++;
647             }
648         #endif
649             return locBldr;
650         }
651
652         public void LoadQueryRuntime() {
653             Emit(OpCodes.Ldarg_0);
654         }
655
656         public void LoadQueryContext() {
657             Emit(OpCodes.Ldarg_0);
658             Call(XmlILMethods.Context);
659         }
660
661         public void LoadXsltLibrary() {
662             Emit(OpCodes.Ldarg_0);
663             Call(XmlILMethods.XsltLib);
664         }
665
666         public void LoadQueryOutput() {
667             Emit(OpCodes.Ldloc, this.locXOut);
668         }
669
670
671         //-----------------------------------------------
672         // Parameters
673         //-----------------------------------------------
674
675         public void LoadParameter(int paramPos) {
676             switch (paramPos) {
677                 case 0: Emit(OpCodes.Ldarg_0); break;
678                 case 1: Emit(OpCodes.Ldarg_1); break;
679                 case 2: Emit(OpCodes.Ldarg_2); break;
680                 case 3: Emit(OpCodes.Ldarg_3); break;
681                 default:
682                     if (paramPos <= 255) {
683                         Emit(OpCodes.Ldarg_S, (byte) paramPos);
684                     }
685                     else if (paramPos <= ushort.MaxValue) {
686                         Emit(OpCodes.Ldarg, paramPos);
687                     }
688                     else {
689                         throw new XslTransformException(Res.XmlIl_TooManyParameters);
690                     }
691                     break;
692             }
693         }
694
695         public void SetParameter(object paramId) {
696             int paramPos = (int) paramId;
697
698             if (paramPos <= 255) {
699                 Emit(OpCodes.Starg_S, (byte) paramPos);
700             }
701             else if (paramPos <= ushort.MaxValue) {
702                 Emit(OpCodes.Starg, (int) paramPos);
703             }
704             else {
705                 throw new XslTransformException(Res.XmlIl_TooManyParameters);
706             }
707         }
708
709         //-----------------------------------------------
710         // Labels
711         //-----------------------------------------------
712
713         /// <summary>
714         /// Branch to lblBranch and anchor lblMark.  If lblBranch = lblMark, then no need
715         /// to generate a "br" to the next instruction.
716         /// </summary>
717         public void BranchAndMark(Label lblBranch, Label lblMark) {
718             if (!lblBranch.Equals(lblMark)) {
719                 EmitUnconditionalBranch(OpCodes.Br, lblBranch);
720             }
721             MarkLabel(lblMark);
722         }
723
724
725         //-----------------------------------------------
726         // Comparison
727         //-----------------------------------------------
728
729         /// <summary>
730         /// Compare the top value on the stack with the specified i4 using the specified relational
731         /// comparison opcode, and branch to lblBranch if the result is true.
732         /// </summary>
733         public void TestAndBranch(int i4, Label lblBranch, OpCode opcodeBranch) {
734             switch (i4) {
735                 case 0:
736                     // Beq or Bne can be shortened to Brfalse or Brtrue if comparing to 0
737                     if (opcodeBranch.Value == OpCodes.Beq.Value)
738                         opcodeBranch = OpCodes.Brfalse;
739                     else if (opcodeBranch.Value == OpCodes.Beq_S.Value)
740                         opcodeBranch = OpCodes.Brfalse_S;
741                     else if (opcodeBranch.Value == OpCodes.Bne_Un.Value)
742                         opcodeBranch = OpCodes.Brtrue;
743                     else if (opcodeBranch.Value == OpCodes.Bne_Un_S.Value)
744                         opcodeBranch = OpCodes.Brtrue_S;
745                     else
746                         goto default;
747                     break;
748
749                 default:
750                     // Cannot use shortcut, so push integer onto the stack
751                     LoadInteger(i4);
752                     break;
753             }
754
755             Emit(opcodeBranch, lblBranch);
756         }
757
758         /// <summary>
759         /// Assume a branch instruction has already been issued.  If isTrueBranch is true, then the
760         /// true path is linked to lblBranch.  Otherwise, the false path is linked to lblBranch.
761         /// Convert this "branching" boolean logic into an explicit push of 1 or 0 onto the stack.
762         /// </summary>
763         public void ConvBranchToBool(Label lblBranch, bool isTrueBranch) {
764             Label lblDone = DefineLabel();
765
766             Emit(isTrueBranch ? OpCodes.Ldc_I4_0 : OpCodes.Ldc_I4_1);
767             EmitUnconditionalBranch(OpCodes.Br_S, lblDone);
768             MarkLabel(lblBranch);
769             Emit(isTrueBranch ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
770             MarkLabel(lblDone);
771         }
772
773
774         //-----------------------------------------------
775         // Frequently used method and function calls
776         //-----------------------------------------------
777
778         public void TailCall(MethodInfo meth) {
779             Emit(OpCodes.Tailcall);
780             Call(meth);
781             Emit(OpCodes.Ret);
782         }
783
784         [Conditional("DEBUG")]
785         private void TraceCall(OpCode opcode, MethodInfo meth) {
786         #if DEBUG
787             if (XmlILTrace.IsEnabled) {
788                 StringBuilder strBldr = new StringBuilder();
789                 bool isFirst = true;
790                 string retType = "";
791
792                 if (!(meth is MethodBuilder)) {
793                     foreach (ParameterInfo paramInfo in meth.GetParameters()) {
794                         if (isFirst)
795                             isFirst = false;
796                         else
797                             strBldr.Append(", ");
798                         strBldr.Append(paramInfo.ParameterType.Name);
799                     }
800                     retType = meth.ReturnType.Name;
801                 }
802
803                 this.writerDump.WriteLine("  {0, -10} {1} {2}({3})", new object[] {opcode.Name, retType, meth.Name, strBldr.ToString()});
804             }
805         #endif
806         }
807
808         public void Call(MethodInfo meth) {
809             OpCode opcode = meth.IsVirtual || meth.IsAbstract ? OpCodes.Callvirt : OpCodes.Call;
810
811             TraceCall(opcode, meth);
812             this.ilgen.Emit(opcode, meth);
813
814             if (this.lastSourceInfo != null) {
815                 // Emit a "no source" sequence point, otherwise the debugger would return to the wrong line
816                 // once the call has finished.  We are guaranteed not to emit adjacent sequence points because
817                 // the Call instruction precedes this sequence point, and a nop instruction precedes other
818                 // sequence points.
819                 MarkSequencePoint(SourceLineInfo.NoSource);
820             }
821         }
822
823         // 
824         public void CallToken(MethodInfo meth) {
825             Debug.Assert(!(methInfo is ConstructorBuilder));
826             MethodBuilder methBldr = this.methInfo as MethodBuilder;
827
828             if (methBldr != null) {
829                 // Using regular reflection emit, so get a token for the specified method.
830                 // The token is only valid within scope of this method's body.
831                 OpCode opcode = meth.IsVirtual || meth.IsAbstract ? OpCodes.Callvirt : OpCodes.Call;
832
833                 TraceCall(opcode, meth);
834                 this.ilgen.Emit(opcode, ((ModuleBuilder) methBldr.GetModule()).GetMethodToken(meth).Token);
835
836                 if (this.lastSourceInfo != null) {
837                     // Emit a "no source" sequence point, otherwise the debugger would return to the wrong line
838                     // once the call has finished.  We are guaranteed not to emit adjacent sequence points because
839                     // the Call instruction precedes this sequence point, and a nop instruction precedes other
840                     // sequence points.
841                     MarkSequencePoint(SourceLineInfo.NoSource);
842                 }
843             }
844             else {
845                 // Using LCG, so no need to workaround
846                 Call(meth);
847             }
848         }
849
850         public void Construct(ConstructorInfo constr) {
851             Emit(OpCodes.Newobj, constr);
852         }
853
854         public void CallConcatStrings(int cStrings) {
855             switch (cStrings) {
856                 case 0:
857                     Emit(OpCodes.Ldstr, "");
858                     break;
859                 case 1:
860                     break;
861                 case 2:
862                     Call(XmlILMethods.StrCat2);
863                     break;
864                 case 3:
865                     Call(XmlILMethods.StrCat3);
866                     break;
867                 case 4:
868                     Call(XmlILMethods.StrCat4);
869                     break;
870                 default:
871                     Debug.Assert(false, "Shouldn't be called");
872                     break;
873             }
874         }
875
876         /// <summary>
877         /// Assume that an object reference is on the IL stack.  Change the static Clr type from "clrTypeSrc" to "clrTypeDst"
878         /// </summary>
879         public void TreatAs(Type clrTypeSrc, Type clrTypeDst) {
880             // If source = destination, then no-op
881             if (clrTypeSrc == clrTypeDst)
882                 return;
883
884             if (clrTypeSrc.IsValueType) {
885                 // If source is a value type, then destination may only be typeof(object), so box
886                 Debug.Assert(clrTypeDst == typeof(object), "Invalid cast, since value types do not allow inheritance.");
887                 Emit(OpCodes.Box, clrTypeSrc);
888             }
889             else if (clrTypeDst.IsValueType) {
890                 // If destination type is value type, then source may only be typeof(object), so unbox
891                 Debug.Assert(clrTypeSrc == typeof(object), "Invalid cast, since value types do not allow inheritance.");
892                 Emit(OpCodes.Unbox, clrTypeDst);
893                 Emit(OpCodes.Ldobj, clrTypeDst);
894             }
895             else if (clrTypeDst != typeof(object)) {
896                 // If source is not a value type, and destination type is typeof(object), then no-op
897                 // Otherwise, use Castclass to change the static type
898                 Debug.Assert(clrTypeSrc.IsAssignableFrom(clrTypeDst) || clrTypeDst.IsAssignableFrom(clrTypeSrc),
899                              "Invalid cast, since source type and destination type are not in same inheritance hierarchy.");
900                 Emit(OpCodes.Castclass, clrTypeDst);
901             }
902         }
903
904
905         //-----------------------------------------------
906         // Datatype methods
907         //-----------------------------------------------
908
909         public void ConstructLiteralDecimal(decimal dec) {
910             if (dec >= (decimal) int.MinValue && dec <= (decimal) int.MaxValue && decimal.Truncate(dec) == dec) {
911                 // Decimal can be constructed from a 32-bit integer
912                 LoadInteger((int) dec);
913                 Construct(XmlILConstructors.DecFromInt32);
914             }
915             else {
916                 int[] bits = Decimal.GetBits(dec);
917
918                 LoadInteger(bits[0]);
919                 LoadInteger(bits[1]);
920                 LoadInteger(bits[2]);
921                 LoadBoolean(bits[3] < 0);
922                 LoadInteger(bits[3] >> 16);
923                 Construct(XmlILConstructors.DecFromParts);
924             }
925         }
926
927         public void ConstructLiteralQName(string localName, string namespaceName) {
928             Emit(OpCodes.Ldstr, localName);
929             Emit(OpCodes.Ldstr, namespaceName);
930             Construct(XmlILConstructors.QName);
931         }
932
933         public void CallArithmeticOp(QilNodeType opType, XmlTypeCode code) {
934             MethodInfo meth = null;
935
936             switch (code) {
937                 case XmlTypeCode.Int:
938                 case XmlTypeCode.Integer:
939                 case XmlTypeCode.Double:
940                 case XmlTypeCode.Float:
941                     switch (opType) {
942                         case QilNodeType.Add: Emit(OpCodes.Add); break;
943                         case QilNodeType.Subtract: Emit(OpCodes.Sub); break;
944                         case QilNodeType.Multiply: Emit(OpCodes.Mul); break;
945                         case QilNodeType.Divide: Emit(OpCodes.Div); break;
946                         case QilNodeType.Modulo: Emit(OpCodes.Rem); break;
947                         case QilNodeType.Negate: Emit(OpCodes.Neg); break;
948                         default: Debug.Assert(false, opType + " must be an arithmetic operation."); break;
949                     }
950                     break;
951
952                 case XmlTypeCode.Decimal:
953                     switch (opType) {
954                         case QilNodeType.Add: meth = XmlILMethods.DecAdd; break;
955                         case QilNodeType.Subtract: meth = XmlILMethods.DecSub; break;
956                         case QilNodeType.Multiply: meth = XmlILMethods.DecMul; break;
957                         case QilNodeType.Divide: meth = XmlILMethods.DecDiv; break;
958                         case QilNodeType.Modulo: meth = XmlILMethods.DecRem; break;
959                         case QilNodeType.Negate: meth = XmlILMethods.DecNeg; break;
960                         default: Debug.Assert(false, opType + " must be an arithmetic operation."); break;
961                     }
962
963                     Call(meth);
964                     break;
965
966                 default:
967                     Debug.Assert(false, "The " + opType + " arithmetic operation cannot be performed on values of type " + code + ".");
968                     break;
969             }
970         }
971
972         public void CallCompareEquals(XmlTypeCode code) {
973             MethodInfo meth = null;
974
975             switch (code) {
976                 case XmlTypeCode.String: meth = XmlILMethods.StrEq; break;
977                 case XmlTypeCode.QName: meth = XmlILMethods.QNameEq; break;
978                 case XmlTypeCode.Decimal: meth = XmlILMethods.DecEq; break;
979                 default:
980                     Debug.Assert(false, "Type " + code + " does not support the equals operation.");
981                     break;
982             }
983
984             Call(meth);
985         }
986
987         public void CallCompare(XmlTypeCode code) {
988             MethodInfo meth = null;
989
990             switch (code) {
991                 case XmlTypeCode.String: meth = XmlILMethods.StrCmp; break;
992                 case XmlTypeCode.Decimal: meth = XmlILMethods.DecCmp; break;
993                 default:
994                     Debug.Assert(false, "Type " + code + " does not support the equals operation.");
995                     break;
996             }
997
998             Call(meth);
999         }
1000
1001
1002         //-----------------------------------------------
1003         // XmlQueryRuntime function calls
1004         //-----------------------------------------------
1005
1006         public void CallStartRtfConstruction(string baseUri) {
1007             EnsureWriter();
1008             LoadQueryRuntime();
1009             Emit(OpCodes.Ldstr, baseUri);
1010             Emit(OpCodes.Ldloca, this.locXOut);
1011             Call(XmlILMethods.StartRtfConstr);
1012         }
1013
1014         public void CallEndRtfConstruction() {
1015             LoadQueryRuntime();
1016             Emit(OpCodes.Ldloca, this.locXOut);
1017             Call(XmlILMethods.EndRtfConstr);
1018         }
1019
1020         public void CallStartSequenceConstruction() {
1021             EnsureWriter();
1022             LoadQueryRuntime();
1023             Emit(OpCodes.Ldloca, this.locXOut);
1024             Call(XmlILMethods.StartSeqConstr);
1025         }
1026
1027         public void CallEndSequenceConstruction() {
1028             LoadQueryRuntime();
1029             Emit(OpCodes.Ldloca, this.locXOut);
1030             Call(XmlILMethods.EndSeqConstr);
1031         }
1032
1033         public void CallGetEarlyBoundObject(int idxObj, Type clrType) {
1034             LoadQueryRuntime();
1035             LoadInteger(idxObj);
1036             Call(XmlILMethods.GetEarly);
1037             TreatAs(typeof(object), clrType);
1038         }
1039
1040         public void CallGetAtomizedName(int idxName) {
1041             LoadQueryRuntime();
1042             LoadInteger(idxName);
1043             Call(XmlILMethods.GetAtomizedName);
1044         }
1045
1046         public void CallGetNameFilter(int idxFilter) {
1047             LoadQueryRuntime();
1048             LoadInteger(idxFilter);
1049             Call(XmlILMethods.GetNameFilter);
1050         }
1051
1052         public void CallGetTypeFilter(XPathNodeType nodeType) {
1053             LoadQueryRuntime();
1054             LoadInteger((int) nodeType);
1055             Call(XmlILMethods.GetTypeFilter);
1056         }
1057
1058         public void CallParseTagName(GenerateNameType nameType) {
1059             if (nameType == GenerateNameType.TagNameAndMappings) {
1060                 Call(XmlILMethods.TagAndMappings);
1061             }
1062             else {
1063                 Debug.Assert(nameType == GenerateNameType.TagNameAndNamespace);
1064                 Call(XmlILMethods.TagAndNamespace);
1065             }
1066         }
1067
1068         public void CallGetGlobalValue(int idxValue, Type clrType) {
1069             LoadQueryRuntime();
1070             LoadInteger(idxValue);
1071             Call(XmlILMethods.GetGlobalValue);
1072             TreatAs(typeof(object), clrType);
1073         }
1074
1075         public void CallSetGlobalValue(Type clrType) {
1076             TreatAs(clrType, typeof(object));
1077             Call(XmlILMethods.SetGlobalValue);
1078         }
1079
1080         public void CallGetCollation(int idxName) {
1081             LoadQueryRuntime();
1082             LoadInteger(idxName);
1083             Call(XmlILMethods.GetCollation);
1084         }
1085
1086         private void EnsureWriter() {
1087             // If write variable has not yet been initialized, do it now
1088             if (!this.initWriters) {
1089                 this.locXOut = DeclareLocal("$$$xwrtChk", typeof(XmlQueryOutput));
1090                 this.initWriters = true;
1091             }
1092         }
1093
1094
1095         //-----------------------------------------------
1096         // XmlQueryContext function calls
1097         //-----------------------------------------------
1098
1099         public void CallGetParameter(string localName, string namespaceUri) {
1100             LoadQueryContext();
1101             Emit(OpCodes.Ldstr, localName);
1102             Emit(OpCodes.Ldstr, namespaceUri);
1103             Call(XmlILMethods.GetParam);
1104         }
1105
1106         //-----------------------------------------------
1107         // XmlQueryOutput function calls
1108         //-----------------------------------------------
1109
1110         public void CallStartTree(XPathNodeType rootType) {
1111             LoadQueryOutput();
1112             LoadInteger((int) rootType);
1113             Call(XmlILMethods.StartTree);
1114         }
1115
1116         public void CallEndTree() {
1117             LoadQueryOutput();
1118             Call(XmlILMethods.EndTree);
1119         }
1120
1121         public void CallWriteStartRoot() {
1122             // Call XmlQueryOutput.WriteStartRoot
1123             LoadQueryOutput();
1124             Call(XmlILMethods.StartRoot);
1125         }
1126
1127         public void CallWriteEndRoot() {
1128             // Call XmlQueryOutput.WriteEndRoot
1129             LoadQueryOutput();
1130             Call(XmlILMethods.EndRoot);
1131         }
1132
1133         public void CallWriteStartElement(GenerateNameType nameType, bool callChk) {
1134             MethodInfo meth = null;
1135
1136             // If runtime checks need to be made,
1137             if (callChk) {
1138                 // Then call XmlQueryOutput.WriteStartElement
1139                 switch (nameType) {
1140                     case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartElemLocName; break;
1141                     case GenerateNameType.LiteralName: meth = XmlILMethods.StartElemLitName; break;
1142                     case GenerateNameType.CopiedName: meth = XmlILMethods.StartElemCopyName; break;
1143                     case GenerateNameType.TagNameAndMappings: meth = XmlILMethods.StartElemMapName; break;
1144                     case GenerateNameType.TagNameAndNamespace: meth = XmlILMethods.StartElemNmspName; break;
1145                     case GenerateNameType.QName: meth = XmlILMethods.StartElemQName; break;
1146                     default: Debug.Assert(false, nameType + " is invalid here."); break;
1147                 }
1148             }
1149             else {
1150                 // Else call XmlQueryOutput.WriteStartElementUnchecked
1151                 switch (nameType) {
1152                     case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartElemLocNameUn; break;
1153                     case GenerateNameType.LiteralName: meth = XmlILMethods.StartElemLitNameUn; break;
1154                     default: Debug.Assert(false, nameType + " is invalid here."); break;
1155                 }
1156             }
1157
1158             Call(meth);
1159         }
1160
1161         public void CallWriteEndElement(GenerateNameType nameType, bool callChk) {
1162             MethodInfo meth = null;
1163
1164             // If runtime checks need to be made,
1165             if (callChk) {
1166                 // Then call XmlQueryOutput.WriteEndElement
1167                 meth = XmlILMethods.EndElemStackName;
1168             }
1169             else {
1170                 // Else call XmlQueryOutput.WriteEndElementUnchecked
1171                 switch (nameType) {
1172                     case GenerateNameType.LiteralLocalName: meth = XmlILMethods.EndElemLocNameUn; break;
1173                     case GenerateNameType.LiteralName: meth = XmlILMethods.EndElemLitNameUn; break;
1174                     default: Debug.Assert(false, nameType + " is invalid here."); break;
1175                 }
1176             }
1177
1178             Call(meth);
1179         }
1180
1181         public void CallStartElementContent() {
1182             LoadQueryOutput();
1183             Call(XmlILMethods.StartContentUn);
1184         }
1185
1186         public void CallWriteStartAttribute(GenerateNameType nameType, bool callChk) {
1187             MethodInfo meth = null;
1188
1189             // If runtime checks need to be made,
1190             if (callChk) {
1191                 // Then call XmlQueryOutput.WriteStartAttribute
1192                 switch (nameType) {
1193                     case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartAttrLocName; break;
1194                     case GenerateNameType.LiteralName: meth = XmlILMethods.StartAttrLitName; break;
1195                     case GenerateNameType.CopiedName: meth = XmlILMethods.StartAttrCopyName; break;
1196                     case GenerateNameType.TagNameAndMappings: meth = XmlILMethods.StartAttrMapName; break;
1197                     case GenerateNameType.TagNameAndNamespace: meth = XmlILMethods.StartAttrNmspName; break;
1198                     case GenerateNameType.QName: meth = XmlILMethods.StartAttrQName; break;
1199                     default: Debug.Assert(false, nameType + " is invalid here."); break;
1200                 }
1201             }
1202             else {
1203                 // Else call XmlQueryOutput.WriteStartAttributeUnchecked
1204                 switch (nameType) {
1205                     case GenerateNameType.LiteralLocalName: meth = XmlILMethods.StartAttrLocNameUn; break;
1206                     case GenerateNameType.LiteralName: meth = XmlILMethods.StartAttrLitNameUn; break;
1207                     default: Debug.Assert(false, nameType + " is invalid here."); break;
1208                 }
1209             }
1210
1211             Call(meth);
1212         }
1213
1214         public void CallWriteEndAttribute(bool callChk) {
1215             LoadQueryOutput();
1216
1217             // If runtime checks need to be made,
1218             if (callChk) {
1219                 // Then call XmlQueryOutput.WriteEndAttribute
1220                 Call(XmlILMethods.EndAttr);
1221             }
1222             else {
1223                 // Else call XmlQueryOutput.WriteEndAttributeUnchecked
1224                 Call(XmlILMethods.EndAttrUn);
1225             }
1226         }
1227
1228         public void CallWriteNamespaceDecl(bool callChk) {
1229             // If runtime checks need to be made,
1230             if (callChk) {
1231                 // Then call XmlQueryOutput.WriteNamespaceDeclaration
1232                 Call(XmlILMethods.NamespaceDecl);
1233             }
1234             else {
1235                 // Else call XmlQueryOutput.WriteNamespaceDeclarationUnchecked
1236                 Call(XmlILMethods.NamespaceDeclUn);
1237             }
1238         }
1239
1240         public void CallWriteString(bool disableOutputEscaping, bool callChk) {
1241             // If runtime checks need to be made,
1242             if (callChk) {
1243                 // Then call XmlQueryOutput.WriteString, or XmlQueryOutput.WriteRaw
1244                 if (disableOutputEscaping)
1245                     Call(XmlILMethods.NoEntText);
1246                 else
1247                     Call(XmlILMethods.Text);
1248             }
1249             else {
1250                 // Else call XmlQueryOutput.WriteStringUnchecked, or XmlQueryOutput.WriteRawUnchecked
1251                 if (disableOutputEscaping)
1252                     Call(XmlILMethods.NoEntTextUn);
1253                 else
1254                     Call(XmlILMethods.TextUn);
1255             }
1256         }
1257
1258         public void CallWriteStartPI() {
1259             Call(XmlILMethods.StartPI);
1260         }
1261
1262         public void CallWriteEndPI() {
1263             LoadQueryOutput();
1264             Call(XmlILMethods.EndPI);
1265         }
1266
1267         public void CallWriteStartComment() {
1268             LoadQueryOutput();
1269             Call(XmlILMethods.StartComment);
1270         }
1271
1272         public void CallWriteEndComment() {
1273             LoadQueryOutput();
1274             Call(XmlILMethods.EndComment);
1275         }
1276
1277
1278         //-----------------------------------------------
1279         // Item caching methods
1280         //-----------------------------------------------
1281
1282         public void CallCacheCount(Type itemStorageType) {
1283             XmlILStorageMethods meth = XmlILMethods.StorageMethods[itemStorageType];
1284             Call(meth.IListCount);
1285         }
1286
1287         public void CallCacheItem(Type itemStorageType) {
1288             Call(XmlILMethods.StorageMethods[itemStorageType].IListItem);
1289         }
1290
1291
1292         //-----------------------------------------------
1293         // XPathItem properties and methods
1294         //-----------------------------------------------
1295
1296         public void CallValueAs(Type clrType) {
1297             MethodInfo meth;
1298
1299             meth = XmlILMethods.StorageMethods[clrType].ValueAs;
1300             if (meth == null) {
1301                 // Call (Type) item.ValueAs(Type, null)
1302                 LoadType(clrType);
1303                 Emit(OpCodes.Ldnull);
1304                 Call(XmlILMethods.ValueAsAny);
1305
1306                 // Unbox or down-cast
1307                 TreatAs(typeof(object), clrType);
1308             }
1309             else {
1310                 // Call strongly typed ValueAs method
1311                 Call(meth);
1312             }
1313         }
1314
1315
1316         //-----------------------------------------------
1317         // XmlSortKeyAccumulator methods
1318         //-----------------------------------------------
1319
1320         public void AddSortKey(XmlQueryType keyType) {
1321             MethodInfo meth = null;
1322
1323             if (keyType == null) {
1324                 meth = XmlILMethods.SortKeyEmpty;
1325             }
1326             else {
1327                 Debug.Assert(keyType.IsAtomicValue, "Sort key must have atomic value type.");
1328
1329                 switch (keyType.TypeCode) {
1330                     case XmlTypeCode.String: meth = XmlILMethods.SortKeyString; break;
1331                     case XmlTypeCode.Decimal: meth = XmlILMethods.SortKeyDecimal; break;
1332                     case XmlTypeCode.Integer: meth = XmlILMethods.SortKeyInteger; break;
1333                     case XmlTypeCode.Int: meth = XmlILMethods.SortKeyInt; break;
1334                     case XmlTypeCode.Boolean: meth = XmlILMethods.SortKeyInt; break;
1335                     case XmlTypeCode.Double: meth = XmlILMethods.SortKeyDouble; break;
1336                     case XmlTypeCode.DateTime: meth = XmlILMethods.SortKeyDateTime; break;
1337
1338                     case XmlTypeCode.None:
1339                         // Empty sequence, so this path will never actually be taken
1340                         Emit(OpCodes.Pop);
1341                         meth = XmlILMethods.SortKeyEmpty;
1342                         break;
1343
1344                     case XmlTypeCode.AnyAtomicType:
1345                         Debug.Assert(false, "Heterogenous sort key is not allowed.");
1346                         return;
1347
1348                     default:
1349                         Debug.Assert(false, "Sorting over datatype " + keyType.TypeCode + " is not allowed.");
1350                         break;
1351                 }
1352             }
1353
1354             Call(meth);
1355         }
1356
1357
1358         //-----------------------------------------------
1359         // Debugging information output
1360         //-----------------------------------------------
1361
1362         /// <summary>
1363         /// Begin a new variable debugging scope.
1364         /// </summary>
1365         public void DebugStartScope() {
1366             this.ilgen.BeginScope();
1367         }
1368
1369         /// <summary>
1370         /// End a new debugging scope.
1371         /// </summary>
1372         public void DebugEndScope() {
1373             this.ilgen.EndScope();
1374         }
1375
1376         /// <summary>
1377         /// Correlate the current IL generation position with the current source position.
1378         /// </summary>
1379         public void DebugSequencePoint(ISourceLineInfo sourceInfo) {
1380             Debug.Assert(this.isDebug && this.lastSourceInfo != null);
1381             Debug.Assert(sourceInfo != null);
1382
1383             // When emitting sequence points, be careful to always follow two rules:
1384             // 1. Never emit adjacent sequence points, as this messes up the debugger.  We guarantee this by
1385             //    always emitting a Nop before every sequence point.
1386             // 2. The runtime enforces a rule that BP sequence points can only appear at zero stack depth,
1387             //    or if a NOP instruction is placed before them.  We guarantee this by always emitting a Nop
1388             //    before every sequence point.
1389             //    <spec>http://devdiv/Documents/Whidbey/CLR/CurrentSpecs/Debugging%20and%20Profiling/JIT-Determined%20Sequence%20Points.doc</spec>
1390             Emit(OpCodes.Nop);
1391             MarkSequencePoint(sourceInfo);
1392         }
1393
1394         private string  lastUriString = null;
1395         private string  lastFileName  = null;
1396
1397         // SQLBUDT 278010: debugger does not work with network paths in uri format, like file://server/share/dir/file
1398         private string GetFileName(ISourceLineInfo sourceInfo) {
1399             string uriString = sourceInfo.Uri;
1400             if ((object)uriString == (object)lastUriString) {
1401                 return lastFileName;
1402             }
1403
1404             lastUriString = uriString;
1405             lastFileName = SourceLineInfo.GetFileName(uriString);
1406             return lastFileName;
1407         }
1408
1409         private void MarkSequencePoint(ISourceLineInfo sourceInfo) {
1410             Debug.Assert(this.module.EmitSymbols);
1411
1412             // Do not emit adjacent 0xfeefee sequence points, as that slows down stepping in the debugger
1413             if (sourceInfo.IsNoSource && this.lastSourceInfo != null && this.lastSourceInfo.IsNoSource) {
1414                 return;
1415             }
1416
1417             string sourceFile = GetFileName(sourceInfo);
1418
1419         #if DEBUG
1420             if (XmlILTrace.IsEnabled) {
1421                 if (sourceInfo.IsNoSource)
1422                     this.writerDump.WriteLine("//[no source]");
1423                 else {
1424                     if (sourceFile != this.sourceFile) {
1425                         this.sourceFile = sourceFile;
1426                         this.writerDump.WriteLine("// Source File '{0}'", this.sourceFile);
1427                     }
1428                     this.writerDump.WriteLine("//[{0},{1} -- {2},{3}]", sourceInfo.Start.Line, sourceInfo.Start.Pos, sourceInfo.End.Line, sourceInfo.End.Pos);
1429                 }
1430             }
1431         #endif
1432             ISymbolDocumentWriter symDoc = this.module.AddSourceDocument(sourceFile);
1433             this.ilgen.MarkSequencePoint(symDoc, sourceInfo.Start.Line, sourceInfo.Start.Pos, sourceInfo.End.Line, sourceInfo.End.Pos);
1434             this.lastSourceInfo = sourceInfo;
1435         }
1436
1437
1438         //-----------------------------------------------
1439         // Pass through to ILGenerator
1440         //-----------------------------------------------
1441
1442         public Label DefineLabel() {
1443             Label lbl = this.ilgen.DefineLabel();
1444
1445         #if DEBUG
1446             if (XmlILTrace.IsEnabled)
1447                 this.symbols.Add(lbl, ++this.lblNum);
1448         #endif
1449
1450             return lbl;
1451         }
1452
1453         public void MarkLabel(Label lbl) {
1454             if (this.lastSourceInfo != null && !this.lastSourceInfo.IsNoSource) {
1455                 // Emit a "no source" sequence point, otherwise the debugger would show
1456                 // a wrong line if we jumped to this label from another place
1457                 DebugSequencePoint(SourceLineInfo.NoSource);
1458             }
1459
1460         #if DEBUG
1461             if (XmlILTrace.IsEnabled)
1462                 this.writerDump.WriteLine("Label {0}:", this.symbols[lbl]);
1463         #endif
1464
1465             this.ilgen.MarkLabel(lbl);
1466         }
1467
1468         public void Emit(OpCode opcode) {
1469         #if DEBUG
1470             if (XmlILTrace.IsEnabled)
1471                 this.writerDump.WriteLine("  {0}", opcode.Name);
1472         #endif
1473             this.ilgen.Emit(opcode);
1474         }
1475
1476         public void Emit(OpCode opcode, byte byteVal) {
1477         #if DEBUG
1478             if (XmlILTrace.IsEnabled)
1479                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, byteVal);
1480         #endif
1481             this.ilgen.Emit(opcode, byteVal);
1482         }
1483
1484         public void Emit(OpCode opcode, ConstructorInfo constrInfo) {
1485         #if DEBUG
1486             if (XmlILTrace.IsEnabled)
1487                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, constrInfo);
1488         #endif
1489             this.ilgen.Emit(opcode, constrInfo);
1490         }
1491
1492         public void Emit(OpCode opcode, double dblVal) {
1493         #if DEBUG
1494             if (XmlILTrace.IsEnabled)
1495                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, dblVal);
1496         #endif
1497             this.ilgen.Emit(opcode, dblVal);
1498         }
1499
1500         public void Emit(OpCode opcode, float fltVal) {
1501         #if DEBUG
1502             if (XmlILTrace.IsEnabled)
1503                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, fltVal);
1504         #endif
1505             this.ilgen.Emit(opcode, fltVal);
1506         }
1507
1508         public void Emit(OpCode opcode, FieldInfo fldInfo) {
1509         #if DEBUG
1510             if (XmlILTrace.IsEnabled)
1511                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, fldInfo.Name);
1512         #endif
1513             this.ilgen.Emit(opcode, fldInfo);
1514         }
1515
1516         public void Emit(OpCode opcode, short shrtVal) {
1517             Debug.Assert(opcode.OperandType == OperandType.ShortInlineI);
1518         #if DEBUG
1519             if (XmlILTrace.IsEnabled)
1520                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, shrtVal);
1521         #endif
1522             this.ilgen.Emit(opcode, shrtVal);
1523         }
1524
1525         public void Emit(OpCode opcode, int intVal) {
1526             Debug.Assert(opcode.OperandType == OperandType.InlineI || opcode.OperandType == OperandType.InlineVar);
1527         #if DEBUG
1528             if (XmlILTrace.IsEnabled)
1529                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, intVal);
1530         #endif
1531             this.ilgen.Emit(opcode, intVal);
1532         }
1533
1534         public void Emit(OpCode opcode, long longVal) {
1535             Debug.Assert(opcode.OperandType == OperandType.InlineI8);
1536         #if DEBUG
1537             if (XmlILTrace.IsEnabled)
1538                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, longVal);
1539         #endif
1540             this.ilgen.Emit(opcode, longVal);
1541         }
1542
1543         public void Emit(OpCode opcode, Label lblVal) {
1544             Debug.Assert(!opcode.Equals(OpCodes.Br) && !opcode.Equals(OpCodes.Br_S), "Use EmitUnconditionalBranch and be careful not to emit unverifiable code.");
1545         #if DEBUG
1546             if (XmlILTrace.IsEnabled)
1547                 this.writerDump.WriteLine("  {0, -10} Label {1}", opcode.Name, this.symbols[lblVal]);
1548         #endif
1549             this.ilgen.Emit(opcode, lblVal);
1550         }
1551
1552         public void Emit(OpCode opcode, Label[] arrLabels) {
1553         #if DEBUG
1554             if (XmlILTrace.IsEnabled) {
1555                 this.writerDump.Write("  {0, -10} (Label {1}", opcode.Name, arrLabels.Length != 0 ? this.symbols[arrLabels[0]].ToString() : "");
1556                 for (int i = 1; i < arrLabels.Length; i++) {
1557                     this.writerDump.Write(", Label {0}", this.symbols[arrLabels[i]]);
1558                 }
1559                 this.writerDump.WriteLine(")");
1560             }
1561         #endif
1562             this.ilgen.Emit(opcode, arrLabels);
1563         }
1564
1565         public void Emit(OpCode opcode, LocalBuilder locBldr) {
1566         #if DEBUG
1567             if (XmlILTrace.IsEnabled)
1568                 this.writerDump.WriteLine("  {0, -10} {1} ({2})", opcode.Name, this.symbols[locBldr], locBldr.LocalType.Name);
1569         #endif
1570             this.ilgen.Emit(opcode, locBldr);
1571         }
1572
1573         public void Emit(OpCode opcode, MethodInfo methInfo) {
1574             Debug.Assert(!opcode.Equals(OpCodes.Call) && !opcode.Equals(OpCodes.Callvirt), "Use Call so that debug information will be output correctly.");
1575         #if DEBUG
1576             if (XmlILTrace.IsEnabled)
1577                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, methInfo.Name);
1578         #endif
1579             this.ilgen.Emit(opcode, methInfo);
1580         }
1581
1582         public void Emit(OpCode opcode, sbyte sbyteVal) {
1583         #if DEBUG
1584             if (XmlILTrace.IsEnabled)
1585                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, sbyteVal);
1586         #endif
1587             this.ilgen.Emit(opcode, sbyteVal);
1588         }
1589
1590         public void Emit(OpCode opcode, string strVal) {
1591         #if DEBUG
1592             if (XmlILTrace.IsEnabled)
1593                 this.writerDump.WriteLine("  {0, -10} \"{1}\"", opcode.Name, strVal);
1594         #endif
1595             this.ilgen.Emit(opcode, strVal);
1596         }
1597
1598         public void Emit(OpCode opcode, Type typVal) {
1599         #if DEBUG
1600             if (XmlILTrace.IsEnabled)
1601                 this.writerDump.WriteLine("  {0, -10} {1}", opcode.Name, typVal);
1602         #endif
1603             this.ilgen.Emit(opcode, typVal);
1604         }
1605
1606         /// <summary>
1607         /// Unconditional branch opcodes (OpCode.Br, OpCode.Br_S) can lead to unverifiable code in the following cases:
1608         ///
1609         ///   # DEAD CODE CASE
1610         ///     ldc_i4  1       # Stack depth == 1
1611         ///     br      Label2
1612         ///   Label1:
1613         ///     nop             # Dead code, so IL rules assume stack depth == 0.  This causes a verification error,
1614         ///                     # since next instruction has depth == 1
1615         ///   Label2:
1616         ///     pop             # Stack depth == 1
1617         ///     ret
1618         ///
1619         ///   # LATE BRANCH CASE
1620         ///     ldc_i4  1       # Stack depth == 1
1621         ///     br      Label2
1622         ///   Label1:
1623         ///     nop             # Not dead code, but since branch comes from below, IL rules assume stack depth = 0.
1624         ///                     # This causes a verification error, since next instruction has depth == 1
1625         ///   Label2:
1626         ///     pop             # Stack depth == 1
1627         ///     ret
1628         ///   Label3:
1629         ///     br      Label1  # Stack depth == 1
1630         ///
1631         /// This method works around the above limitations by using Brtrue or Brfalse in the following way:
1632         ///
1633         ///     ldc_i4  1       # Since this test is always true, this is a way of creating a path to the code that
1634         ///     brtrue  Label   # follows the brtrue instruction.
1635         ///
1636         ///     ldc_i4  1       # Since this test is always false, this is a way of creating a path to the code that
1637         ///     brfalse Label   # starts at Label.
1638         ///
1639         /// 1. If opcode == Brtrue or Brtrue_S, then 1 will be pushed and brtrue instruction will be generated.
1640         /// 2. If opcode == Brfalse or Brfalse_S, then 1 will be pushed and brfalse instruction will be generated.
1641         /// 3. If opcode == Br or Br_S, then a br instruction will be generated.
1642         /// </summary>
1643         public void EmitUnconditionalBranch(OpCode opcode, Label lblTarget) {
1644             if (!opcode.Equals(OpCodes.Br) && !opcode.Equals(OpCodes.Br_S)) {
1645                 Debug.Assert(opcode.Equals(OpCodes.Brtrue) || opcode.Equals(OpCodes.Brtrue_S) ||
1646                              opcode.Equals(OpCodes.Brfalse) || opcode.Equals(OpCodes.Brfalse_S));
1647                 Emit(OpCodes.Ldc_I4_1);
1648             }
1649
1650         #if DEBUG
1651             if (XmlILTrace.IsEnabled)
1652                 this.writerDump.WriteLine("  {0, -10} Label {1}", opcode.Name, this.symbols[lblTarget]);
1653         #endif
1654             this.ilgen.Emit(opcode, lblTarget);
1655
1656             if (this.lastSourceInfo != null && (opcode.Equals(OpCodes.Br) || opcode.Equals(OpCodes.Br_S))) {
1657                 // Emit a "no source" sequence point, otherwise the following label will be preceded
1658                 // with a dead Nop operation, which may lead to unverifiable code (SQLBUDT 423393).
1659                 // We are guaranteed not to emit adjacent sequence points because Br or Br_S
1660                 // instruction precedes this sequence point, and a Nop instruction precedes other
1661                 // sequence points.
1662                 MarkSequencePoint(SourceLineInfo.NoSource);
1663             }
1664         }
1665     }
1666 }