1 //------------------------------------------------------------------------------
2 // <copyright file="GenerateHelper.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System.Globalization;
10 using System.Xml.XPath;
11 using System.Xml.Schema;
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;
25 namespace System.Xml.Xsl.IlGen {
26 using Res = System.Xml.Utils.Res;
29 /// List of all XmlIL runtime constructors.
31 internal class XmlILStorageMethods {
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;
46 public FieldInfo SeqEmpty;
47 public MethodInfo SeqReuse;
48 public MethodInfo SeqReuseSgl;
49 public MethodInfo SeqAdd;
50 public MethodInfo SeqSortByKeys;
53 public Type IListType;
54 public MethodInfo IListCount;
55 public MethodInfo IListItem;
58 public MethodInfo ValueAs;
61 public MethodInfo ToAtomicValue;
63 public XmlILStorageMethods(Type storageType) {
65 if (storageType == typeof(int) || storageType == typeof(long) ||
66 storageType == typeof(decimal) || storageType == typeof(double)) {
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");
82 if (storageType == typeof(XPathNavigator)) {
83 SeqType = typeof(XmlQueryNodeSequence);
84 SeqAdd = XmlILMethods.GetMethod(SeqType, "AddClone");
86 else if (storageType == typeof(XPathItem)) {
87 SeqType = typeof(XmlQueryItemSequence);
88 SeqAdd = XmlILMethods.GetMethod(SeqType, "AddClone");
91 SeqType = typeof(XmlQuerySequence<>).MakeGenericType(storageType);
92 SeqAdd = XmlILMethods.GetMethod(SeqType, "Add");
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");
101 IListType = typeof(IList<>).MakeGenericType(storageType);
102 IListItem = XmlILMethods.GetMethod(IListType, "get_Item");
103 IListCount = XmlILMethods.GetMethod(typeof(ICollection<>).MakeGenericType(storageType), "get_Count");
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");
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");
128 /// List of all XmlIL runtime constructors.
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));
140 private static ConstructorInfo GetConstructor(Type className) {
141 ConstructorInfo constrInfo = className.GetConstructor(new Type[] {});
142 Debug.Assert(constrInfo != null, "Constructor " + className + " cannot be null.");
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.");
155 /// List of all XmlIL runtime methods.
157 internal static class XmlILMethods {
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");
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");
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");
270 public static readonly MethodInfo IndexAdd = GetMethod(typeof(XmlILIndex), "Add");
271 public static readonly MethodInfo IndexLookup = GetMethod(typeof(XmlILIndex), "Lookup");
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));
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");
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));
301 public static readonly MethodInfo StartTree = GetMethod(typeof(XmlQueryOutput), "StartTree");
302 public static readonly MethodInfo EndTree = GetMethod(typeof(XmlQueryOutput), "EndTree");
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");
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");
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");
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));
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));
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>));
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");
385 // XmlILStorageConverter
386 public static readonly MethodInfo NavsToItems = GetMethod(typeof(XmlILStorageConverter), "NavigatorsToItems");
387 public static readonly MethodInfo ItemsToNavs = GetMethod(typeof(XmlILStorageConverter), "ItemsToNavigators");
389 // XmlQueryNodeSequence
390 public static readonly MethodInfo SetDod = GetMethod(typeof(XmlQueryNodeSequence), "set_IsDocOrderDistinct");
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;
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));
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.");
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.");
429 /// When named nodes are constructed, there are several possible ways for their names to be created.
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
442 /// Contains helper methods used during the code generation phase.
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;
456 private Hashtable symbols;
457 private int numLocals;
458 private string sourceFile;
459 private TextWriter writerDump;
463 /// Cache metadata used during code-generation phase.
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();
476 if (XmlILTrace.IsEnabled)
477 XmlILTrace.PrepareTraceWriter("dump.il");
482 /// Begin generating code within a new method.
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;
495 if (XmlILTrace.IsEnabled) {
497 this.symbols = new Hashtable();
499 this.sourceFile = null;
501 this.writerDump = XmlILTrace.GetTraceWriter("dump.il");
502 this.writerDump.WriteLine(".method {0}()", methInfo.Name);
503 this.writerDump.WriteLine("{");
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);
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
528 this.lastSourceInfo = null;
532 this.initWriters = false;
536 Call(XmlILMethods.GetOutput);
537 Emit(OpCodes.Stloc, this.locXOut);
542 /// Generate "ret" instruction and branch fixup jump table.
544 public void MethodEnd() {
548 if (XmlILTrace.IsEnabled) {
549 this.writerDump.WriteLine("}");
550 this.writerDump.WriteLine("");
551 this.writerDump.Close();
560 //-----------------------------------------------
561 // Helper Global Methods
562 //-----------------------------------------------
565 /// Call a static method which attempts to reuse a navigator.
567 public void CallSyncToNavigator() {
568 // Get helper method from module
569 if (this.methSyncToNav == null)
570 this.methSyncToNav = this.module.FindMethod("SyncToNavigator");
572 Call(this.methSyncToNav);
575 //-----------------------------------------------
577 //-----------------------------------------------
580 /// This internal class manages literal names, literal types, and storage for global variables.
582 public StaticDataManager StaticData {
583 get { return this.staticData; }
587 //-----------------------------------------------
589 //-----------------------------------------------
592 /// Generate the optimal Ldc_I4 instruction based on intVal.
594 public void LoadInteger(int intVal) {
597 if (intVal >= -1 && intVal < 9) {
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;
613 else if (intVal >= -128 && intVal <= 127)
614 Emit(OpCodes.Ldc_I4_S, (sbyte) intVal);
616 Emit(OpCodes.Ldc_I4, intVal);
619 public void LoadBoolean(bool boolVal) {
620 Emit(boolVal ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0);
623 public void LoadType(Type clrTyp) {
624 Emit(OpCodes.Ldtoken, clrTyp);
625 Call(XmlILMethods.GetTypeFromHandle);
629 //-----------------------------------------------
631 //-----------------------------------------------
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).
637 public LocalBuilder DeclareLocal(string name, Type type) {
638 LocalBuilder locBldr = this.ilgen.DeclareLocal(type);
640 if (XmlILTrace.IsEnabled) {
641 // Set name for internal MS debugging. This is not the user-defined name--that will be set later
643 locBldr.SetLocalSymInfo(name + this.numLocals.ToString(CultureInfo.InvariantCulture));
645 this.symbols.Add(locBldr, name + this.numLocals.ToString(CultureInfo.InvariantCulture));
652 public void LoadQueryRuntime() {
653 Emit(OpCodes.Ldarg_0);
656 public void LoadQueryContext() {
657 Emit(OpCodes.Ldarg_0);
658 Call(XmlILMethods.Context);
661 public void LoadXsltLibrary() {
662 Emit(OpCodes.Ldarg_0);
663 Call(XmlILMethods.XsltLib);
666 public void LoadQueryOutput() {
667 Emit(OpCodes.Ldloc, this.locXOut);
671 //-----------------------------------------------
673 //-----------------------------------------------
675 public void LoadParameter(int 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;
682 if (paramPos <= 255) {
683 Emit(OpCodes.Ldarg_S, (byte) paramPos);
685 else if (paramPos <= ushort.MaxValue) {
686 Emit(OpCodes.Ldarg, paramPos);
689 throw new XslTransformException(Res.XmlIl_TooManyParameters);
695 public void SetParameter(object paramId) {
696 int paramPos = (int) paramId;
698 if (paramPos <= 255) {
699 Emit(OpCodes.Starg_S, (byte) paramPos);
701 else if (paramPos <= ushort.MaxValue) {
702 Emit(OpCodes.Starg, (int) paramPos);
705 throw new XslTransformException(Res.XmlIl_TooManyParameters);
709 //-----------------------------------------------
711 //-----------------------------------------------
714 /// Branch to lblBranch and anchor lblMark. If lblBranch = lblMark, then no need
715 /// to generate a "br" to the next instruction.
717 public void BranchAndMark(Label lblBranch, Label lblMark) {
718 if (!lblBranch.Equals(lblMark)) {
719 EmitUnconditionalBranch(OpCodes.Br, lblBranch);
725 //-----------------------------------------------
727 //-----------------------------------------------
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.
733 public void TestAndBranch(int i4, Label lblBranch, OpCode opcodeBranch) {
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;
750 // Cannot use shortcut, so push integer onto the stack
755 Emit(opcodeBranch, lblBranch);
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.
763 public void ConvBranchToBool(Label lblBranch, bool isTrueBranch) {
764 Label lblDone = DefineLabel();
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);
774 //-----------------------------------------------
775 // Frequently used method and function calls
776 //-----------------------------------------------
778 public void TailCall(MethodInfo meth) {
779 Emit(OpCodes.Tailcall);
784 [Conditional("DEBUG")]
785 private void TraceCall(OpCode opcode, MethodInfo meth) {
787 if (XmlILTrace.IsEnabled) {
788 StringBuilder strBldr = new StringBuilder();
792 if (!(meth is MethodBuilder)) {
793 foreach (ParameterInfo paramInfo in meth.GetParameters()) {
797 strBldr.Append(", ");
798 strBldr.Append(paramInfo.ParameterType.Name);
800 retType = meth.ReturnType.Name;
803 this.writerDump.WriteLine(" {0, -10} {1} {2}({3})", new object[] {opcode.Name, retType, meth.Name, strBldr.ToString()});
808 public void Call(MethodInfo meth) {
809 OpCode opcode = meth.IsVirtual || meth.IsAbstract ? OpCodes.Callvirt : OpCodes.Call;
811 TraceCall(opcode, meth);
812 this.ilgen.Emit(opcode, meth);
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
819 MarkSequencePoint(SourceLineInfo.NoSource);
824 public void CallToken(MethodInfo meth) {
825 Debug.Assert(!(methInfo is ConstructorBuilder));
826 MethodBuilder methBldr = this.methInfo as MethodBuilder;
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;
833 TraceCall(opcode, meth);
834 this.ilgen.Emit(opcode, ((ModuleBuilder) methBldr.GetModule()).GetMethodToken(meth).Token);
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
841 MarkSequencePoint(SourceLineInfo.NoSource);
845 // Using LCG, so no need to workaround
850 public void Construct(ConstructorInfo constr) {
851 Emit(OpCodes.Newobj, constr);
854 public void CallConcatStrings(int cStrings) {
857 Emit(OpCodes.Ldstr, "");
862 Call(XmlILMethods.StrCat2);
865 Call(XmlILMethods.StrCat3);
868 Call(XmlILMethods.StrCat4);
871 Debug.Assert(false, "Shouldn't be called");
877 /// Assume that an object reference is on the IL stack. Change the static Clr type from "clrTypeSrc" to "clrTypeDst"
879 public void TreatAs(Type clrTypeSrc, Type clrTypeDst) {
880 // If source = destination, then no-op
881 if (clrTypeSrc == clrTypeDst)
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);
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);
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);
905 //-----------------------------------------------
907 //-----------------------------------------------
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);
916 int[] bits = Decimal.GetBits(dec);
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);
927 public void ConstructLiteralQName(string localName, string namespaceName) {
928 Emit(OpCodes.Ldstr, localName);
929 Emit(OpCodes.Ldstr, namespaceName);
930 Construct(XmlILConstructors.QName);
933 public void CallArithmeticOp(QilNodeType opType, XmlTypeCode code) {
934 MethodInfo meth = null;
937 case XmlTypeCode.Int:
938 case XmlTypeCode.Integer:
939 case XmlTypeCode.Double:
940 case XmlTypeCode.Float:
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;
952 case XmlTypeCode.Decimal:
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;
967 Debug.Assert(false, "The " + opType + " arithmetic operation cannot be performed on values of type " + code + ".");
972 public void CallCompareEquals(XmlTypeCode code) {
973 MethodInfo meth = null;
976 case XmlTypeCode.String: meth = XmlILMethods.StrEq; break;
977 case XmlTypeCode.QName: meth = XmlILMethods.QNameEq; break;
978 case XmlTypeCode.Decimal: meth = XmlILMethods.DecEq; break;
980 Debug.Assert(false, "Type " + code + " does not support the equals operation.");
987 public void CallCompare(XmlTypeCode code) {
988 MethodInfo meth = null;
991 case XmlTypeCode.String: meth = XmlILMethods.StrCmp; break;
992 case XmlTypeCode.Decimal: meth = XmlILMethods.DecCmp; break;
994 Debug.Assert(false, "Type " + code + " does not support the equals operation.");
1002 //-----------------------------------------------
1003 // XmlQueryRuntime function calls
1004 //-----------------------------------------------
1006 public void CallStartRtfConstruction(string baseUri) {
1009 Emit(OpCodes.Ldstr, baseUri);
1010 Emit(OpCodes.Ldloca, this.locXOut);
1011 Call(XmlILMethods.StartRtfConstr);
1014 public void CallEndRtfConstruction() {
1016 Emit(OpCodes.Ldloca, this.locXOut);
1017 Call(XmlILMethods.EndRtfConstr);
1020 public void CallStartSequenceConstruction() {
1023 Emit(OpCodes.Ldloca, this.locXOut);
1024 Call(XmlILMethods.StartSeqConstr);
1027 public void CallEndSequenceConstruction() {
1029 Emit(OpCodes.Ldloca, this.locXOut);
1030 Call(XmlILMethods.EndSeqConstr);
1033 public void CallGetEarlyBoundObject(int idxObj, Type clrType) {
1035 LoadInteger(idxObj);
1036 Call(XmlILMethods.GetEarly);
1037 TreatAs(typeof(object), clrType);
1040 public void CallGetAtomizedName(int idxName) {
1042 LoadInteger(idxName);
1043 Call(XmlILMethods.GetAtomizedName);
1046 public void CallGetNameFilter(int idxFilter) {
1048 LoadInteger(idxFilter);
1049 Call(XmlILMethods.GetNameFilter);
1052 public void CallGetTypeFilter(XPathNodeType nodeType) {
1054 LoadInteger((int) nodeType);
1055 Call(XmlILMethods.GetTypeFilter);
1058 public void CallParseTagName(GenerateNameType nameType) {
1059 if (nameType == GenerateNameType.TagNameAndMappings) {
1060 Call(XmlILMethods.TagAndMappings);
1063 Debug.Assert(nameType == GenerateNameType.TagNameAndNamespace);
1064 Call(XmlILMethods.TagAndNamespace);
1068 public void CallGetGlobalValue(int idxValue, Type clrType) {
1070 LoadInteger(idxValue);
1071 Call(XmlILMethods.GetGlobalValue);
1072 TreatAs(typeof(object), clrType);
1075 public void CallSetGlobalValue(Type clrType) {
1076 TreatAs(clrType, typeof(object));
1077 Call(XmlILMethods.SetGlobalValue);
1080 public void CallGetCollation(int idxName) {
1082 LoadInteger(idxName);
1083 Call(XmlILMethods.GetCollation);
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;
1095 //-----------------------------------------------
1096 // XmlQueryContext function calls
1097 //-----------------------------------------------
1099 public void CallGetParameter(string localName, string namespaceUri) {
1101 Emit(OpCodes.Ldstr, localName);
1102 Emit(OpCodes.Ldstr, namespaceUri);
1103 Call(XmlILMethods.GetParam);
1106 //-----------------------------------------------
1107 // XmlQueryOutput function calls
1108 //-----------------------------------------------
1110 public void CallStartTree(XPathNodeType rootType) {
1112 LoadInteger((int) rootType);
1113 Call(XmlILMethods.StartTree);
1116 public void CallEndTree() {
1118 Call(XmlILMethods.EndTree);
1121 public void CallWriteStartRoot() {
1122 // Call XmlQueryOutput.WriteStartRoot
1124 Call(XmlILMethods.StartRoot);
1127 public void CallWriteEndRoot() {
1128 // Call XmlQueryOutput.WriteEndRoot
1130 Call(XmlILMethods.EndRoot);
1133 public void CallWriteStartElement(GenerateNameType nameType, bool callChk) {
1134 MethodInfo meth = null;
1136 // If runtime checks need to be made,
1138 // Then call XmlQueryOutput.WriteStartElement
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;
1150 // Else call XmlQueryOutput.WriteStartElementUnchecked
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;
1161 public void CallWriteEndElement(GenerateNameType nameType, bool callChk) {
1162 MethodInfo meth = null;
1164 // If runtime checks need to be made,
1166 // Then call XmlQueryOutput.WriteEndElement
1167 meth = XmlILMethods.EndElemStackName;
1170 // Else call XmlQueryOutput.WriteEndElementUnchecked
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;
1181 public void CallStartElementContent() {
1183 Call(XmlILMethods.StartContentUn);
1186 public void CallWriteStartAttribute(GenerateNameType nameType, bool callChk) {
1187 MethodInfo meth = null;
1189 // If runtime checks need to be made,
1191 // Then call XmlQueryOutput.WriteStartAttribute
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;
1203 // Else call XmlQueryOutput.WriteStartAttributeUnchecked
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;
1214 public void CallWriteEndAttribute(bool callChk) {
1217 // If runtime checks need to be made,
1219 // Then call XmlQueryOutput.WriteEndAttribute
1220 Call(XmlILMethods.EndAttr);
1223 // Else call XmlQueryOutput.WriteEndAttributeUnchecked
1224 Call(XmlILMethods.EndAttrUn);
1228 public void CallWriteNamespaceDecl(bool callChk) {
1229 // If runtime checks need to be made,
1231 // Then call XmlQueryOutput.WriteNamespaceDeclaration
1232 Call(XmlILMethods.NamespaceDecl);
1235 // Else call XmlQueryOutput.WriteNamespaceDeclarationUnchecked
1236 Call(XmlILMethods.NamespaceDeclUn);
1240 public void CallWriteString(bool disableOutputEscaping, bool callChk) {
1241 // If runtime checks need to be made,
1243 // Then call XmlQueryOutput.WriteString, or XmlQueryOutput.WriteRaw
1244 if (disableOutputEscaping)
1245 Call(XmlILMethods.NoEntText);
1247 Call(XmlILMethods.Text);
1250 // Else call XmlQueryOutput.WriteStringUnchecked, or XmlQueryOutput.WriteRawUnchecked
1251 if (disableOutputEscaping)
1252 Call(XmlILMethods.NoEntTextUn);
1254 Call(XmlILMethods.TextUn);
1258 public void CallWriteStartPI() {
1259 Call(XmlILMethods.StartPI);
1262 public void CallWriteEndPI() {
1264 Call(XmlILMethods.EndPI);
1267 public void CallWriteStartComment() {
1269 Call(XmlILMethods.StartComment);
1272 public void CallWriteEndComment() {
1274 Call(XmlILMethods.EndComment);
1278 //-----------------------------------------------
1279 // Item caching methods
1280 //-----------------------------------------------
1282 public void CallCacheCount(Type itemStorageType) {
1283 XmlILStorageMethods meth = XmlILMethods.StorageMethods[itemStorageType];
1284 Call(meth.IListCount);
1287 public void CallCacheItem(Type itemStorageType) {
1288 Call(XmlILMethods.StorageMethods[itemStorageType].IListItem);
1292 //-----------------------------------------------
1293 // XPathItem properties and methods
1294 //-----------------------------------------------
1296 public void CallValueAs(Type clrType) {
1299 meth = XmlILMethods.StorageMethods[clrType].ValueAs;
1301 // Call (Type) item.ValueAs(Type, null)
1303 Emit(OpCodes.Ldnull);
1304 Call(XmlILMethods.ValueAsAny);
1306 // Unbox or down-cast
1307 TreatAs(typeof(object), clrType);
1310 // Call strongly typed ValueAs method
1316 //-----------------------------------------------
1317 // XmlSortKeyAccumulator methods
1318 //-----------------------------------------------
1320 public void AddSortKey(XmlQueryType keyType) {
1321 MethodInfo meth = null;
1323 if (keyType == null) {
1324 meth = XmlILMethods.SortKeyEmpty;
1327 Debug.Assert(keyType.IsAtomicValue, "Sort key must have atomic value type.");
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;
1338 case XmlTypeCode.None:
1339 // Empty sequence, so this path will never actually be taken
1341 meth = XmlILMethods.SortKeyEmpty;
1344 case XmlTypeCode.AnyAtomicType:
1345 Debug.Assert(false, "Heterogenous sort key is not allowed.");
1349 Debug.Assert(false, "Sorting over datatype " + keyType.TypeCode + " is not allowed.");
1358 //-----------------------------------------------
1359 // Debugging information output
1360 //-----------------------------------------------
1363 /// Begin a new variable debugging scope.
1365 public void DebugStartScope() {
1366 this.ilgen.BeginScope();
1370 /// End a new debugging scope.
1372 public void DebugEndScope() {
1373 this.ilgen.EndScope();
1377 /// Correlate the current IL generation position with the current source position.
1379 public void DebugSequencePoint(ISourceLineInfo sourceInfo) {
1380 Debug.Assert(this.isDebug && this.lastSourceInfo != null);
1381 Debug.Assert(sourceInfo != null);
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>
1391 MarkSequencePoint(sourceInfo);
1394 private string lastUriString = null;
1395 private string lastFileName = null;
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;
1404 lastUriString = uriString;
1405 lastFileName = SourceLineInfo.GetFileName(uriString);
1406 return lastFileName;
1409 private void MarkSequencePoint(ISourceLineInfo sourceInfo) {
1410 Debug.Assert(this.module.EmitSymbols);
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) {
1417 string sourceFile = GetFileName(sourceInfo);
1420 if (XmlILTrace.IsEnabled) {
1421 if (sourceInfo.IsNoSource)
1422 this.writerDump.WriteLine("//[no source]");
1424 if (sourceFile != this.sourceFile) {
1425 this.sourceFile = sourceFile;
1426 this.writerDump.WriteLine("// Source File '{0}'", this.sourceFile);
1428 this.writerDump.WriteLine("//[{0},{1} -- {2},{3}]", sourceInfo.Start.Line, sourceInfo.Start.Pos, sourceInfo.End.Line, sourceInfo.End.Pos);
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;
1438 //-----------------------------------------------
1439 // Pass through to ILGenerator
1440 //-----------------------------------------------
1442 public Label DefineLabel() {
1443 Label lbl = this.ilgen.DefineLabel();
1446 if (XmlILTrace.IsEnabled)
1447 this.symbols.Add(lbl, ++this.lblNum);
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);
1461 if (XmlILTrace.IsEnabled)
1462 this.writerDump.WriteLine("Label {0}:", this.symbols[lbl]);
1465 this.ilgen.MarkLabel(lbl);
1468 public void Emit(OpCode opcode) {
1470 if (XmlILTrace.IsEnabled)
1471 this.writerDump.WriteLine(" {0}", opcode.Name);
1473 this.ilgen.Emit(opcode);
1476 public void Emit(OpCode opcode, byte byteVal) {
1478 if (XmlILTrace.IsEnabled)
1479 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, byteVal);
1481 this.ilgen.Emit(opcode, byteVal);
1484 public void Emit(OpCode opcode, ConstructorInfo constrInfo) {
1486 if (XmlILTrace.IsEnabled)
1487 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, constrInfo);
1489 this.ilgen.Emit(opcode, constrInfo);
1492 public void Emit(OpCode opcode, double dblVal) {
1494 if (XmlILTrace.IsEnabled)
1495 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, dblVal);
1497 this.ilgen.Emit(opcode, dblVal);
1500 public void Emit(OpCode opcode, float fltVal) {
1502 if (XmlILTrace.IsEnabled)
1503 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, fltVal);
1505 this.ilgen.Emit(opcode, fltVal);
1508 public void Emit(OpCode opcode, FieldInfo fldInfo) {
1510 if (XmlILTrace.IsEnabled)
1511 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, fldInfo.Name);
1513 this.ilgen.Emit(opcode, fldInfo);
1516 public void Emit(OpCode opcode, short shrtVal) {
1517 Debug.Assert(opcode.OperandType == OperandType.ShortInlineI);
1519 if (XmlILTrace.IsEnabled)
1520 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, shrtVal);
1522 this.ilgen.Emit(opcode, shrtVal);
1525 public void Emit(OpCode opcode, int intVal) {
1526 Debug.Assert(opcode.OperandType == OperandType.InlineI || opcode.OperandType == OperandType.InlineVar);
1528 if (XmlILTrace.IsEnabled)
1529 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, intVal);
1531 this.ilgen.Emit(opcode, intVal);
1534 public void Emit(OpCode opcode, long longVal) {
1535 Debug.Assert(opcode.OperandType == OperandType.InlineI8);
1537 if (XmlILTrace.IsEnabled)
1538 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, longVal);
1540 this.ilgen.Emit(opcode, longVal);
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.");
1546 if (XmlILTrace.IsEnabled)
1547 this.writerDump.WriteLine(" {0, -10} Label {1}", opcode.Name, this.symbols[lblVal]);
1549 this.ilgen.Emit(opcode, lblVal);
1552 public void Emit(OpCode opcode, Label[] arrLabels) {
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]]);
1559 this.writerDump.WriteLine(")");
1562 this.ilgen.Emit(opcode, arrLabels);
1565 public void Emit(OpCode opcode, LocalBuilder locBldr) {
1567 if (XmlILTrace.IsEnabled)
1568 this.writerDump.WriteLine(" {0, -10} {1} ({2})", opcode.Name, this.symbols[locBldr], locBldr.LocalType.Name);
1570 this.ilgen.Emit(opcode, locBldr);
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.");
1576 if (XmlILTrace.IsEnabled)
1577 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, methInfo.Name);
1579 this.ilgen.Emit(opcode, methInfo);
1582 public void Emit(OpCode opcode, sbyte sbyteVal) {
1584 if (XmlILTrace.IsEnabled)
1585 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, sbyteVal);
1587 this.ilgen.Emit(opcode, sbyteVal);
1590 public void Emit(OpCode opcode, string strVal) {
1592 if (XmlILTrace.IsEnabled)
1593 this.writerDump.WriteLine(" {0, -10} \"{1}\"", opcode.Name, strVal);
1595 this.ilgen.Emit(opcode, strVal);
1598 public void Emit(OpCode opcode, Type typVal) {
1600 if (XmlILTrace.IsEnabled)
1601 this.writerDump.WriteLine(" {0, -10} {1}", opcode.Name, typVal);
1603 this.ilgen.Emit(opcode, typVal);
1607 /// Unconditional branch opcodes (OpCode.Br, OpCode.Br_S) can lead to unverifiable code in the following cases:
1609 /// # DEAD CODE CASE
1610 /// ldc_i4 1 # Stack depth == 1
1613 /// nop # Dead code, so IL rules assume stack depth == 0. This causes a verification error,
1614 /// # since next instruction has depth == 1
1616 /// pop # Stack depth == 1
1619 /// # LATE BRANCH CASE
1620 /// ldc_i4 1 # Stack depth == 1
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
1626 /// pop # Stack depth == 1
1629 /// br Label1 # Stack depth == 1
1631 /// This method works around the above limitations by using Brtrue or Brfalse in the following way:
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.
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.
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.
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);
1651 if (XmlILTrace.IsEnabled)
1652 this.writerDump.WriteLine(" {0, -10} Label {1}", opcode.Name, this.symbols[lblTarget]);
1654 this.ilgen.Emit(opcode, lblTarget);
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
1662 MarkSequencePoint(SourceLineInfo.NoSource);