1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4 
5 using System;
6 using System.Collections;
7 using System.Collections.Generic;
8 using System.Globalization;
9 using System.Xml;
10 using System.Reflection;
11 using System.Reflection.Emit;
12 using System.IO;
13 using System.Security;
14 using System.Diagnostics;
15 
16 #if !uapaot
17 namespace System.Runtime.Serialization
18 {
19     internal class CodeGenerator
20     {
21         private static MethodInfo s_getTypeFromHandle;
22         private static MethodInfo GetTypeFromHandle
23         {
24             get
25             {
26                 if (s_getTypeFromHandle == null)
27                 {
28                     s_getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
29                     Debug.Assert(s_getTypeFromHandle != null);
30                 }
31                 return s_getTypeFromHandle;
32             }
33         }
34 
35         private static MethodInfo s_objectEquals;
36         private static MethodInfo ObjectEquals
37         {
38             get
39             {
40                 if (s_objectEquals == null)
41                 {
42                     s_objectEquals = Globals.TypeOfObject.GetMethod("Equals", BindingFlags.Public | BindingFlags.Static);
43                     Debug.Assert(s_objectEquals != null);
44                 }
45                 return s_objectEquals;
46             }
47         }
48 
49         private static MethodInfo s_arraySetValue;
50         private static MethodInfo ArraySetValue
51         {
52             get
53             {
54                 if (s_arraySetValue == null)
55                 {
56                     s_arraySetValue = typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int) });
57                     Debug.Assert(s_arraySetValue != null);
58                 }
59                 return s_arraySetValue;
60             }
61         }
62 
63 #if !uapaot
64         private static MethodInfo s_objectToString;
65         private static MethodInfo ObjectToString
66         {
67             get
68             {
69                 if (s_objectToString == null)
70                 {
71                     s_objectToString = typeof(object).GetMethod("ToString", Array.Empty<Type>());
72                     Debug.Assert(s_objectToString != null);
73                 }
74                 return s_objectToString;
75             }
76         }
77 
78         private static MethodInfo s_stringFormat;
79         private static MethodInfo StringFormat
80         {
81             get
82             {
83                 if (s_stringFormat == null)
84                 {
85                     s_stringFormat = typeof(string).GetMethod("Format", new Type[] { typeof(string), typeof(object[]) });
86                     Debug.Assert(s_stringFormat != null);
87                 }
88                 return s_stringFormat;
89             }
90         }
91 #endif
92 
93         private Type _delegateType;
94 
95 #if USE_REFEMIT
96         AssemblyBuilder assemblyBuilder;
97         ModuleBuilder moduleBuilder;
98         TypeBuilder typeBuilder;
99         static int typeCounter;
100         MethodBuilder methodBuilder;
101 #else
102         private static Module s_serializationModule;
103         private static Module SerializationModule
104         {
105             get
106             {
107                 if (s_serializationModule == null)
108                 {
109                     s_serializationModule = typeof(CodeGenerator).Module;   // could to be replaced by different dll that has SkipVerification set to false
110                 }
111                 return s_serializationModule;
112             }
113         }
114         private DynamicMethod _dynamicMethod;
115 #endif
116 
117         private ILGenerator _ilGen;
118         private List<ArgBuilder> _argList;
119         private Stack<object> _blockStack;
120         private Label _methodEndLabel;
121 
122         private Dictionary<LocalBuilder, string> _localNames = new Dictionary<LocalBuilder, string>();
123 
124         private enum CodeGenTrace { None, Save, Tron };
125         private CodeGenTrace _codeGenTrace;
126 
127 #if !uapaot
128         private LocalBuilder _stringFormatArray;
129 #endif
130 
CodeGenerator()131         internal CodeGenerator()
132         {
133             //Defaulting to None as thats the default value in WCF
134             _codeGenTrace = CodeGenTrace.None;
135         }
136 
137 #if !USE_REFEMIT
BeginMethod(DynamicMethod dynamicMethod, Type delegateType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)138         internal void BeginMethod(DynamicMethod dynamicMethod, Type delegateType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
139         {
140             _dynamicMethod = dynamicMethod;
141             _ilGen = _dynamicMethod.GetILGenerator();
142             _delegateType = delegateType;
143 
144             InitILGeneration(methodName, argTypes);
145         }
146 #endif
147 
BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)148         internal void BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)
149         {
150             MethodInfo signature = delegateType.GetMethod("Invoke");
151             ParameterInfo[] parameters = signature.GetParameters();
152             Type[] paramTypes = new Type[parameters.Length];
153             for (int i = 0; i < parameters.Length; i++)
154                 paramTypes[i] = parameters[i].ParameterType;
155             BeginMethod(signature.ReturnType, methodName, paramTypes, allowPrivateMemberAccess);
156             _delegateType = delegateType;
157         }
158 
BeginMethod(Type returnType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)159         private void BeginMethod(Type returnType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
160         {
161 #if USE_REFEMIT
162             string typeName = "Type" + (typeCounter++);
163             InitAssemblyBuilder(typeName + "." + methodName);
164             this.typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
165             this.methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public|MethodAttributes.Static, returnType, argTypes);
166             this.ilGen = this.methodBuilder.GetILGenerator();
167 #else
168             _dynamicMethod = new DynamicMethod(methodName, returnType, argTypes, SerializationModule, allowPrivateMemberAccess);
169 
170             _ilGen = _dynamicMethod.GetILGenerator();
171 #endif
172 
173             InitILGeneration(methodName, argTypes);
174         }
175 
InitILGeneration(string methodName, Type[] argTypes)176         private void InitILGeneration(string methodName, Type[] argTypes)
177         {
178             _methodEndLabel = _ilGen.DefineLabel();
179             _blockStack = new Stack<object>();
180             _argList = new List<ArgBuilder>();
181             for (int i = 0; i < argTypes.Length; i++)
182                 _argList.Add(new ArgBuilder(i, argTypes[i]));
183             if (_codeGenTrace != CodeGenTrace.None)
184                 EmitSourceLabel("Begin method " + methodName + " {");
185         }
186 
EndMethod()187         internal Delegate EndMethod()
188         {
189             MarkLabel(_methodEndLabel);
190             if (_codeGenTrace != CodeGenTrace.None)
191                 EmitSourceLabel("} End method");
192             Ret();
193 
194             Delegate retVal = null;
195 #if USE_REFEMIT
196             Type type = typeBuilder.CreateType();
197             MethodInfo method = type.GetMethod(methodBuilder.Name);
198             retVal = Delegate.CreateDelegate(delegateType, method);
199             methodBuilder = null;
200 #else
201             retVal = _dynamicMethod.CreateDelegate(_delegateType);
202             _dynamicMethod = null;
203 #endif
204             _delegateType = null;
205 
206             _ilGen = null;
207             _blockStack = null;
208             _argList = null;
209             return retVal;
210         }
211 
212         internal MethodInfo CurrentMethod
213         {
214             get
215             {
216 #if USE_REFEMIT
217                 return methodBuilder;
218 #else
219                 return _dynamicMethod;
220 #endif
221             }
222         }
223 
GetArg(int index)224         internal ArgBuilder GetArg(int index)
225         {
226             return (ArgBuilder)_argList[index];
227         }
228 
GetVariableType(object var)229         internal Type GetVariableType(object var)
230         {
231             if (var is ArgBuilder)
232                 return ((ArgBuilder)var).ArgType;
233             else if (var is LocalBuilder)
234                 return ((LocalBuilder)var).LocalType;
235             else
236                 return var.GetType();
237         }
238 
DeclareLocal(Type type, string name, object initialValue)239         internal LocalBuilder DeclareLocal(Type type, string name, object initialValue)
240         {
241             LocalBuilder local = DeclareLocal(type, name);
242             Load(initialValue);
243             Store(local);
244             return local;
245         }
246 
DeclareLocal(Type type, string name)247         internal LocalBuilder DeclareLocal(Type type, string name)
248         {
249             return DeclareLocal(type, name, false);
250         }
251 
DeclareLocal(Type type, string name, bool isPinned)252         internal LocalBuilder DeclareLocal(Type type, string name, bool isPinned)
253         {
254             LocalBuilder local = _ilGen.DeclareLocal(type, isPinned);
255             if (_codeGenTrace != CodeGenTrace.None)
256             {
257                 _localNames[local] = name;
258                 EmitSourceComment("Declare local '" + name + "' of type " + type);
259             }
260             return local;
261         }
262 
Set(LocalBuilder local, object value)263         internal void Set(LocalBuilder local, object value)
264         {
265             Load(value);
266             Store(local);
267         }
268 
For(LocalBuilder local, object start, object end)269         internal object For(LocalBuilder local, object start, object end)
270         {
271             ForState forState = new ForState(local, DefineLabel(), DefineLabel(), end);
272             if (forState.Index != null)
273             {
274                 Load(start);
275                 Stloc(forState.Index);
276                 Br(forState.TestLabel);
277             }
278             MarkLabel(forState.BeginLabel);
279             _blockStack.Push(forState);
280             return forState;
281         }
282 
EndFor()283         internal void EndFor()
284         {
285             object stackTop = _blockStack.Pop();
286             ForState forState = stackTop as ForState;
287             if (forState == null)
288                 ThrowMismatchException(stackTop);
289 
290             if (forState.Index != null)
291             {
292                 Ldloc(forState.Index);
293                 Ldc(1);
294                 Add();
295                 Stloc(forState.Index);
296                 MarkLabel(forState.TestLabel);
297                 Ldloc(forState.Index);
298                 Load(forState.End);
299                 if (GetVariableType(forState.End).IsArray)
300                     Ldlen();
301                 Blt(forState.BeginLabel);
302             }
303             else
304                 Br(forState.BeginLabel);
305             if (forState.RequiresEndLabel)
306                 MarkLabel(forState.EndLabel);
307         }
308 
Break(object forState)309         internal void Break(object forState)
310         {
311             InternalBreakFor(forState, OpCodes.Br);
312         }
313 
IfFalseBreak(object forState)314         internal void IfFalseBreak(object forState)
315         {
316             InternalBreakFor(forState, OpCodes.Brfalse);
317         }
318 
InternalBreakFor(object userForState, OpCode branchInstruction)319         internal void InternalBreakFor(object userForState, OpCode branchInstruction)
320         {
321             foreach (object block in _blockStack)
322             {
323                 ForState forState = block as ForState;
324                 if (forState != null && (object)forState == userForState)
325                 {
326                     if (!forState.RequiresEndLabel)
327                     {
328                         forState.EndLabel = DefineLabel();
329                         forState.RequiresEndLabel = true;
330                     }
331                     if (_codeGenTrace != CodeGenTrace.None)
332                         EmitSourceInstruction(branchInstruction + " " + forState.EndLabel.GetHashCode());
333                     _ilGen.Emit(branchInstruction, forState.EndLabel);
334                     break;
335                 }
336             }
337         }
338 
ForEach(LocalBuilder local, Type elementType, Type enumeratorType, LocalBuilder enumerator, MethodInfo getCurrentMethod)339         internal void ForEach(LocalBuilder local, Type elementType, Type enumeratorType,
340             LocalBuilder enumerator, MethodInfo getCurrentMethod)
341         {
342             ForState forState = new ForState(local, DefineLabel(), DefineLabel(), enumerator);
343 
344             Br(forState.TestLabel);
345             MarkLabel(forState.BeginLabel);
346 
347             Call(enumerator, getCurrentMethod);
348 
349             ConvertValue(elementType, GetVariableType(local));
350             Stloc(local);
351             _blockStack.Push(forState);
352         }
353 
EndForEach(MethodInfo moveNextMethod)354         internal void EndForEach(MethodInfo moveNextMethod)
355         {
356             object stackTop = _blockStack.Pop();
357             ForState forState = stackTop as ForState;
358             if (forState == null)
359                 ThrowMismatchException(stackTop);
360 
361             MarkLabel(forState.TestLabel);
362 
363             object enumerator = forState.End;
364             Call(enumerator, moveNextMethod);
365 
366 
367             Brtrue(forState.BeginLabel);
368             if (forState.RequiresEndLabel)
369                 MarkLabel(forState.EndLabel);
370         }
371 
IfNotDefaultValue(object value)372         internal void IfNotDefaultValue(object value)
373         {
374             Type type = GetVariableType(value);
375             TypeCode typeCode = type.GetTypeCode();
376             if ((typeCode == TypeCode.Object && type.IsValueType) ||
377                 typeCode == TypeCode.DateTime || typeCode == TypeCode.Decimal)
378             {
379                 LoadDefaultValue(type);
380                 ConvertValue(type, Globals.TypeOfObject);
381                 Load(value);
382                 ConvertValue(type, Globals.TypeOfObject);
383                 Call(ObjectEquals);
384                 IfNot();
385             }
386             else
387             {
388                 LoadDefaultValue(type);
389                 Load(value);
390                 If(Cmp.NotEqualTo);
391             }
392         }
393 
If()394         internal void If()
395         {
396             InternalIf(false);
397         }
398 
IfNot()399         internal void IfNot()
400         {
401             InternalIf(true);
402         }
403 
GetBranchCode(Cmp cmp)404         private OpCode GetBranchCode(Cmp cmp)
405         {
406             switch (cmp)
407             {
408                 case Cmp.LessThan:
409                     return OpCodes.Bge;
410                 case Cmp.EqualTo:
411                     return OpCodes.Bne_Un;
412                 case Cmp.LessThanOrEqualTo:
413                     return OpCodes.Bgt;
414                 case Cmp.GreaterThan:
415                     return OpCodes.Ble;
416                 case Cmp.NotEqualTo:
417                     return OpCodes.Beq;
418                 default:
419                     DiagnosticUtility.DebugAssert(cmp == Cmp.GreaterThanOrEqualTo, "Unexpected cmp");
420                     return OpCodes.Blt;
421             }
422         }
423 
If(Cmp cmpOp)424         internal void If(Cmp cmpOp)
425         {
426             IfState ifState = new IfState();
427             ifState.EndIf = DefineLabel();
428             ifState.ElseBegin = DefineLabel();
429             _ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
430             _blockStack.Push(ifState);
431         }
432 
433 
If(object value1, Cmp cmpOp, object value2)434         internal void If(object value1, Cmp cmpOp, object value2)
435         {
436             Load(value1);
437             Load(value2);
438             If(cmpOp);
439         }
Else()440         internal void Else()
441         {
442             IfState ifState = PopIfState();
443             Br(ifState.EndIf);
444             MarkLabel(ifState.ElseBegin);
445 
446             ifState.ElseBegin = ifState.EndIf;
447             _blockStack.Push(ifState);
448         }
449 
ElseIf(object value1, Cmp cmpOp, object value2)450         internal void ElseIf(object value1, Cmp cmpOp, object value2)
451         {
452             IfState ifState = (IfState)_blockStack.Pop();
453             Br(ifState.EndIf);
454             MarkLabel(ifState.ElseBegin);
455 
456             Load(value1);
457             Load(value2);
458             ifState.ElseBegin = DefineLabel();
459 
460             _ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
461             _blockStack.Push(ifState);
462         }
463 
464 
EndIf()465         internal void EndIf()
466         {
467             IfState ifState = PopIfState();
468             if (!ifState.ElseBegin.Equals(ifState.EndIf))
469                 MarkLabel(ifState.ElseBegin);
470             MarkLabel(ifState.EndIf);
471         }
472 
VerifyParameterCount(MethodInfo methodInfo, int expectedCount)473         internal void VerifyParameterCount(MethodInfo methodInfo, int expectedCount)
474         {
475             if (methodInfo.GetParameters().Length != expectedCount)
476                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ParameterCountMismatch, methodInfo.Name, methodInfo.GetParameters().Length, expectedCount)));
477         }
478 
Call(object thisObj, MethodInfo methodInfo)479         internal void Call(object thisObj, MethodInfo methodInfo)
480         {
481             VerifyParameterCount(methodInfo, 0);
482             LoadThis(thisObj, methodInfo);
483             Call(methodInfo);
484         }
485 
Call(object thisObj, MethodInfo methodInfo, object param1)486         internal void Call(object thisObj, MethodInfo methodInfo, object param1)
487         {
488             VerifyParameterCount(methodInfo, 1);
489             LoadThis(thisObj, methodInfo);
490             LoadParam(param1, 1, methodInfo);
491             Call(methodInfo);
492         }
493 
Call(object thisObj, MethodInfo methodInfo, object param1, object param2)494         internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2)
495         {
496             VerifyParameterCount(methodInfo, 2);
497             LoadThis(thisObj, methodInfo);
498             LoadParam(param1, 1, methodInfo);
499             LoadParam(param2, 2, methodInfo);
500             Call(methodInfo);
501         }
502 
Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3)503         internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3)
504         {
505             VerifyParameterCount(methodInfo, 3);
506             LoadThis(thisObj, methodInfo);
507             LoadParam(param1, 1, methodInfo);
508             LoadParam(param2, 2, methodInfo);
509             LoadParam(param3, 3, methodInfo);
510             Call(methodInfo);
511         }
512 
Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4)513         internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4)
514         {
515             VerifyParameterCount(methodInfo, 4);
516             LoadThis(thisObj, methodInfo);
517             LoadParam(param1, 1, methodInfo);
518             LoadParam(param2, 2, methodInfo);
519             LoadParam(param3, 3, methodInfo);
520             LoadParam(param4, 4, methodInfo);
521             Call(methodInfo);
522         }
523 
Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5)524         internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5)
525         {
526             VerifyParameterCount(methodInfo, 5);
527             LoadThis(thisObj, methodInfo);
528             LoadParam(param1, 1, methodInfo);
529             LoadParam(param2, 2, methodInfo);
530             LoadParam(param3, 3, methodInfo);
531             LoadParam(param4, 4, methodInfo);
532             LoadParam(param5, 5, methodInfo);
533             Call(methodInfo);
534         }
535 
Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5, object param6)536         internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5, object param6)
537         {
538             VerifyParameterCount(methodInfo, 6);
539             LoadThis(thisObj, methodInfo);
540             LoadParam(param1, 1, methodInfo);
541             LoadParam(param2, 2, methodInfo);
542             LoadParam(param3, 3, methodInfo);
543             LoadParam(param4, 4, methodInfo);
544             LoadParam(param5, 5, methodInfo);
545             LoadParam(param6, 6, methodInfo);
546             Call(methodInfo);
547         }
548 
Call(MethodInfo methodInfo)549         internal void Call(MethodInfo methodInfo)
550         {
551             if (methodInfo.IsVirtual && !methodInfo.DeclaringType.IsValueType)
552             {
553                 if (_codeGenTrace != CodeGenTrace.None)
554                     EmitSourceInstruction("Callvirt " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
555                 _ilGen.Emit(OpCodes.Callvirt, methodInfo);
556             }
557             else if (methodInfo.IsStatic)
558             {
559                 if (_codeGenTrace != CodeGenTrace.None)
560                     EmitSourceInstruction("Static Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
561                 _ilGen.Emit(OpCodes.Call, methodInfo);
562             }
563             else
564             {
565                 if (_codeGenTrace != CodeGenTrace.None)
566                     EmitSourceInstruction("Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
567                 _ilGen.Emit(OpCodes.Call, methodInfo);
568             }
569         }
570 
Call(ConstructorInfo ctor)571         internal void Call(ConstructorInfo ctor)
572         {
573             if (_codeGenTrace != CodeGenTrace.None)
574                 EmitSourceInstruction("Call " + ctor.ToString() + " on type " + ctor.DeclaringType.ToString());
575             _ilGen.Emit(OpCodes.Call, ctor);
576         }
577 
New(ConstructorInfo constructorInfo)578         internal void New(ConstructorInfo constructorInfo)
579         {
580             if (_codeGenTrace != CodeGenTrace.None)
581                 EmitSourceInstruction("Newobj " + constructorInfo.ToString() + " on type " + constructorInfo.DeclaringType.ToString());
582             _ilGen.Emit(OpCodes.Newobj, constructorInfo);
583         }
584 
585 
InitObj(Type valueType)586         internal void InitObj(Type valueType)
587         {
588             if (_codeGenTrace != CodeGenTrace.None)
589                 EmitSourceInstruction("Initobj " + valueType);
590             _ilGen.Emit(OpCodes.Initobj, valueType);
591         }
592 
NewArray(Type elementType, object len)593         internal void NewArray(Type elementType, object len)
594         {
595             Load(len);
596             if (_codeGenTrace != CodeGenTrace.None)
597                 EmitSourceInstruction("Newarr " + elementType);
598             _ilGen.Emit(OpCodes.Newarr, elementType);
599         }
600 
LoadArrayElement(object obj, object arrayIndex)601         internal void LoadArrayElement(object obj, object arrayIndex)
602         {
603             Type objType = GetVariableType(obj).GetElementType();
604             Load(obj);
605             Load(arrayIndex);
606             if (IsStruct(objType))
607             {
608                 Ldelema(objType);
609                 Ldobj(objType);
610             }
611             else
612                 Ldelem(objType);
613         }
614 
StoreArrayElement(object obj, object arrayIndex, object value)615         internal void StoreArrayElement(object obj, object arrayIndex, object value)
616         {
617             Type arrayType = GetVariableType(obj);
618             if (arrayType == Globals.TypeOfArray)
619             {
620                 Call(obj, ArraySetValue, value, arrayIndex);
621             }
622             else
623             {
624                 Type objType = arrayType.GetElementType();
625                 Load(obj);
626                 Load(arrayIndex);
627                 if (IsStruct(objType))
628                     Ldelema(objType);
629                 Load(value);
630                 ConvertValue(GetVariableType(value), objType);
631                 if (IsStruct(objType))
632                     Stobj(objType);
633                 else
634                     Stelem(objType);
635             }
636         }
637 
IsStruct(Type objType)638         private static bool IsStruct(Type objType)
639         {
640             return objType.IsValueType && !objType.IsPrimitive;
641         }
642 
LoadMember(MemberInfo memberInfo)643         internal Type LoadMember(MemberInfo memberInfo)
644         {
645             Type memberType = null;
646             if (memberInfo is FieldInfo)
647             {
648                 FieldInfo fieldInfo = (FieldInfo)memberInfo;
649                 memberType = fieldInfo.FieldType;
650                 if (fieldInfo.IsStatic)
651                 {
652                     if (_codeGenTrace != CodeGenTrace.None)
653                         EmitSourceInstruction("Ldsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
654                     _ilGen.Emit(OpCodes.Ldsfld, fieldInfo);
655                 }
656                 else
657                 {
658                     if (_codeGenTrace != CodeGenTrace.None)
659                         EmitSourceInstruction("Ldfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
660                     _ilGen.Emit(OpCodes.Ldfld, fieldInfo);
661                 }
662             }
663             else if (memberInfo is PropertyInfo)
664             {
665                 PropertyInfo property = memberInfo as PropertyInfo;
666                 memberType = property.PropertyType;
667                 if (property != null)
668                 {
669                     MethodInfo getMethod = property.GetMethod;
670                     if (getMethod == null)
671                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoGetMethodForProperty, property.DeclaringType, property)));
672                     Call(getMethod);
673                 }
674             }
675             else if (memberInfo is MethodInfo)
676             {
677                 MethodInfo method = (MethodInfo)memberInfo;
678                 memberType = method.ReturnType;
679                 Call(method);
680             }
681             else
682                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotLoadMemberType, "Unknown", memberInfo.DeclaringType, memberInfo.Name)));
683 
684             EmitStackTop(memberType);
685             return memberType;
686         }
687 
StoreMember(MemberInfo memberInfo)688         internal void StoreMember(MemberInfo memberInfo)
689         {
690             if (memberInfo is FieldInfo)
691             {
692                 FieldInfo fieldInfo = (FieldInfo)memberInfo;
693                 if (fieldInfo.IsStatic)
694                 {
695                     if (_codeGenTrace != CodeGenTrace.None)
696                         EmitSourceInstruction("Stsfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
697                     _ilGen.Emit(OpCodes.Stsfld, fieldInfo);
698                 }
699                 else
700                 {
701                     if (_codeGenTrace != CodeGenTrace.None)
702                         EmitSourceInstruction("Stfld " + fieldInfo + " on type " + fieldInfo.DeclaringType);
703                     _ilGen.Emit(OpCodes.Stfld, fieldInfo);
704                 }
705             }
706             else if (memberInfo is PropertyInfo)
707             {
708                 PropertyInfo property = memberInfo as PropertyInfo;
709                 if (property != null)
710                 {
711                     MethodInfo setMethod = property.SetMethod;
712                     if (setMethod == null)
713                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoSetMethodForProperty, property.DeclaringType, property)));
714                     Call(setMethod);
715                 }
716             }
717             else if (memberInfo is MethodInfo)
718                 Call((MethodInfo)memberInfo);
719             else
720                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CannotLoadMemberType, "Unknown")));
721         }
722 
LoadDefaultValue(Type type)723         internal void LoadDefaultValue(Type type)
724         {
725             if (type.IsValueType)
726             {
727                 switch (type.GetTypeCode())
728                 {
729                     case TypeCode.Boolean:
730                         Ldc(false);
731                         break;
732                     case TypeCode.Char:
733                     case TypeCode.SByte:
734                     case TypeCode.Byte:
735                     case TypeCode.Int16:
736                     case TypeCode.UInt16:
737                     case TypeCode.Int32:
738                     case TypeCode.UInt32:
739                         Ldc(0);
740                         break;
741                     case TypeCode.Int64:
742                     case TypeCode.UInt64:
743                         Ldc(0L);
744                         break;
745                     case TypeCode.Single:
746                         Ldc(0.0F);
747                         break;
748                     case TypeCode.Double:
749                         Ldc(0.0);
750                         break;
751                     case TypeCode.Decimal:
752                     case TypeCode.DateTime:
753                     default:
754                         LocalBuilder zero = DeclareLocal(type, "zero");
755                         LoadAddress(zero);
756                         InitObj(type);
757                         Load(zero);
758                         break;
759                 }
760             }
761             else
762                 Load(null);
763         }
764 
Load(object obj)765         internal void Load(object obj)
766         {
767             if (obj == null)
768             {
769                 if (_codeGenTrace != CodeGenTrace.None)
770                     EmitSourceInstruction("Ldnull");
771                 _ilGen.Emit(OpCodes.Ldnull);
772             }
773             else if (obj is ArgBuilder)
774                 Ldarg((ArgBuilder)obj);
775             else if (obj is LocalBuilder)
776                 Ldloc((LocalBuilder)obj);
777             else
778                 Ldc(obj);
779         }
780 
Store(object var)781         internal void Store(object var)
782         {
783             if (var is ArgBuilder)
784                 Starg((ArgBuilder)var);
785             else if (var is LocalBuilder)
786                 Stloc((LocalBuilder)var);
787             else
788             {
789                 DiagnosticUtility.DebugAssert("Data can only be stored into ArgBuilder or LocalBuilder.");
790                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.CanOnlyStoreIntoArgOrLocGot0, DataContract.GetClrTypeFullName(var.GetType()))));
791             }
792         }
793 
Dec(object var)794         internal void Dec(object var)
795         {
796             Load(var);
797             Load(1);
798             Subtract();
799             Store(var);
800         }
801 
LoadAddress(object obj)802         internal void LoadAddress(object obj)
803         {
804             if (obj is ArgBuilder)
805                 LdargAddress((ArgBuilder)obj);
806             else if (obj is LocalBuilder)
807                 LdlocAddress((LocalBuilder)obj);
808             else
809                 Load(obj);
810         }
811 
812 
ConvertAddress(Type source, Type target)813         internal void ConvertAddress(Type source, Type target)
814         {
815             InternalConvert(source, target, true);
816         }
817 
ConvertValue(Type source, Type target)818         internal void ConvertValue(Type source, Type target)
819         {
820             InternalConvert(source, target, false);
821         }
822 
823 
Castclass(Type target)824         internal void Castclass(Type target)
825         {
826             if (_codeGenTrace != CodeGenTrace.None)
827                 EmitSourceInstruction("Castclass " + target);
828             _ilGen.Emit(OpCodes.Castclass, target);
829         }
830 
Box(Type type)831         internal void Box(Type type)
832         {
833             if (_codeGenTrace != CodeGenTrace.None)
834                 EmitSourceInstruction("Box " + type);
835             _ilGen.Emit(OpCodes.Box, type);
836         }
837 
Unbox(Type type)838         internal void Unbox(Type type)
839         {
840             if (_codeGenTrace != CodeGenTrace.None)
841                 EmitSourceInstruction("Unbox " + type);
842             _ilGen.Emit(OpCodes.Unbox, type);
843         }
844 
GetLdindOpCode(TypeCode typeCode)845         private OpCode GetLdindOpCode(TypeCode typeCode)
846         {
847             switch (typeCode)
848             {
849                 case TypeCode.Boolean:
850                     return OpCodes.Ldind_I1; // TypeCode.Boolean:
851                 case TypeCode.Char:
852                     return OpCodes.Ldind_I2; // TypeCode.Char:
853                 case TypeCode.SByte:
854                     return OpCodes.Ldind_I1; // TypeCode.SByte:
855                 case TypeCode.Byte:
856                     return OpCodes.Ldind_U1; // TypeCode.Byte:
857                 case TypeCode.Int16:
858                     return OpCodes.Ldind_I2; // TypeCode.Int16:
859                 case TypeCode.UInt16:
860                     return OpCodes.Ldind_U2; // TypeCode.UInt16:
861                 case TypeCode.Int32:
862                     return OpCodes.Ldind_I4; // TypeCode.Int32:
863                 case TypeCode.UInt32:
864                     return OpCodes.Ldind_U4; // TypeCode.UInt32:
865                 case TypeCode.Int64:
866                     return OpCodes.Ldind_I8; // TypeCode.Int64:
867                 case TypeCode.UInt64:
868                     return OpCodes.Ldind_I8; // TypeCode.UInt64:
869                 case TypeCode.Single:
870                     return OpCodes.Ldind_R4; // TypeCode.Single:
871                 case TypeCode.Double:
872                     return OpCodes.Ldind_R8; // TypeCode.Double:
873                 case TypeCode.String:
874                     return OpCodes.Ldind_Ref; // TypeCode.String:
875                 default:
876                     return OpCodes.Nop;
877             }
878         }
879 
Ldobj(Type type)880         internal void Ldobj(Type type)
881         {
882             OpCode opCode = GetLdindOpCode(type.GetTypeCode());
883             if (!opCode.Equals(OpCodes.Nop))
884             {
885                 if (_codeGenTrace != CodeGenTrace.None)
886                     EmitSourceInstruction(opCode.ToString());
887                 _ilGen.Emit(opCode);
888             }
889             else
890             {
891                 if (_codeGenTrace != CodeGenTrace.None)
892                     EmitSourceInstruction("Ldobj " + type);
893                 _ilGen.Emit(OpCodes.Ldobj, type);
894             }
895         }
896 
Stobj(Type type)897         internal void Stobj(Type type)
898         {
899             if (_codeGenTrace != CodeGenTrace.None)
900                 EmitSourceInstruction("Stobj " + type);
901             _ilGen.Emit(OpCodes.Stobj, type);
902         }
903 
904 
Ceq()905         internal void Ceq()
906         {
907             if (_codeGenTrace != CodeGenTrace.None)
908                 EmitSourceInstruction("Ceq");
909             _ilGen.Emit(OpCodes.Ceq);
910         }
911 
Throw()912         internal void Throw()
913         {
914             if (_codeGenTrace != CodeGenTrace.None)
915                 EmitSourceInstruction("Throw");
916             _ilGen.Emit(OpCodes.Throw);
917         }
918 
Ldtoken(Type t)919         internal void Ldtoken(Type t)
920         {
921             if (_codeGenTrace != CodeGenTrace.None)
922                 EmitSourceInstruction("Ldtoken " + t);
923             _ilGen.Emit(OpCodes.Ldtoken, t);
924         }
925 
Ldc(object o)926         internal void Ldc(object o)
927         {
928             Type valueType = o.GetType();
929             if (o is Type)
930             {
931                 Ldtoken((Type)o);
932                 Call(GetTypeFromHandle);
933             }
934             else if (valueType.IsEnum)
935             {
936                 if (_codeGenTrace != CodeGenTrace.None)
937                     EmitSourceComment("Ldc " + o.GetType() + "." + o);
938                 Ldc(Convert.ChangeType(o, Enum.GetUnderlyingType(valueType), null));
939             }
940             else
941             {
942                 switch (valueType.GetTypeCode())
943                 {
944                     case TypeCode.Boolean:
945                         Ldc((bool)o);
946                         break;
947                     case TypeCode.Char:
948                         DiagnosticUtility.DebugAssert("Char is not a valid schema primitive and should be treated as int in DataContract");
949                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.Format(SR.CharIsInvalidPrimitive)));
950                     case TypeCode.SByte:
951                     case TypeCode.Byte:
952                     case TypeCode.Int16:
953                     case TypeCode.UInt16:
954                         Ldc(Convert.ToInt32(o, CultureInfo.InvariantCulture));
955                         break;
956                     case TypeCode.Int32:
957                         Ldc((int)o);
958                         break;
959                     case TypeCode.UInt32:
960                         Ldc((int)(uint)o);
961                         break;
962                     case TypeCode.UInt64:
963                         Ldc((long)(ulong)o);
964                         break;
965                     case TypeCode.Int64:
966                         Ldc((long)o);
967                         break;
968                     case TypeCode.Single:
969                         Ldc((float)o);
970                         break;
971                     case TypeCode.Double:
972                         Ldc((double)o);
973                         break;
974                     case TypeCode.String:
975                         Ldstr((string)o);
976                         break;
977                     case TypeCode.Object:
978                     case TypeCode.Decimal:
979                     case TypeCode.DateTime:
980                     case TypeCode.Empty:
981                     default:
982                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.UnknownConstantType, DataContract.GetClrTypeFullName(valueType))));
983                 }
984             }
985         }
986 
Ldc(bool boolVar)987         internal void Ldc(bool boolVar)
988         {
989             if (boolVar)
990             {
991                 if (_codeGenTrace != CodeGenTrace.None)
992                     EmitSourceInstruction("Ldc.i4 1");
993                 _ilGen.Emit(OpCodes.Ldc_I4_1);
994             }
995             else
996             {
997                 if (_codeGenTrace != CodeGenTrace.None)
998                     EmitSourceInstruction("Ldc.i4 0");
999                 _ilGen.Emit(OpCodes.Ldc_I4_0);
1000             }
1001         }
1002 
Ldc(int intVar)1003         internal void Ldc(int intVar)
1004         {
1005             if (_codeGenTrace != CodeGenTrace.None)
1006                 EmitSourceInstruction("Ldc.i4 " + intVar);
1007             switch (intVar)
1008             {
1009                 case -1:
1010                     _ilGen.Emit(OpCodes.Ldc_I4_M1);
1011                     break;
1012                 case 0:
1013                     _ilGen.Emit(OpCodes.Ldc_I4_0);
1014                     break;
1015                 case 1:
1016                     _ilGen.Emit(OpCodes.Ldc_I4_1);
1017                     break;
1018                 case 2:
1019                     _ilGen.Emit(OpCodes.Ldc_I4_2);
1020                     break;
1021                 case 3:
1022                     _ilGen.Emit(OpCodes.Ldc_I4_3);
1023                     break;
1024                 case 4:
1025                     _ilGen.Emit(OpCodes.Ldc_I4_4);
1026                     break;
1027                 case 5:
1028                     _ilGen.Emit(OpCodes.Ldc_I4_5);
1029                     break;
1030                 case 6:
1031                     _ilGen.Emit(OpCodes.Ldc_I4_6);
1032                     break;
1033                 case 7:
1034                     _ilGen.Emit(OpCodes.Ldc_I4_7);
1035                     break;
1036                 case 8:
1037                     _ilGen.Emit(OpCodes.Ldc_I4_8);
1038                     break;
1039                 default:
1040                     _ilGen.Emit(OpCodes.Ldc_I4, intVar);
1041                     break;
1042             }
1043         }
1044 
Ldc(long l)1045         internal void Ldc(long l)
1046         {
1047             if (_codeGenTrace != CodeGenTrace.None)
1048                 EmitSourceInstruction("Ldc.i8 " + l);
1049             _ilGen.Emit(OpCodes.Ldc_I8, l);
1050         }
1051 
Ldc(float f)1052         internal void Ldc(float f)
1053         {
1054             if (_codeGenTrace != CodeGenTrace.None)
1055                 EmitSourceInstruction("Ldc.r4 " + f);
1056             _ilGen.Emit(OpCodes.Ldc_R4, f);
1057         }
1058 
Ldc(double d)1059         internal void Ldc(double d)
1060         {
1061             if (_codeGenTrace != CodeGenTrace.None)
1062                 EmitSourceInstruction("Ldc.r8 " + d);
1063             _ilGen.Emit(OpCodes.Ldc_R8, d);
1064         }
1065 
Ldstr(string strVar)1066         internal void Ldstr(string strVar)
1067         {
1068             if (_codeGenTrace != CodeGenTrace.None)
1069                 EmitSourceInstruction("Ldstr " + strVar);
1070             _ilGen.Emit(OpCodes.Ldstr, strVar);
1071         }
1072 
LdlocAddress(LocalBuilder localBuilder)1073         internal void LdlocAddress(LocalBuilder localBuilder)
1074         {
1075             if (localBuilder.LocalType.IsValueType)
1076                 Ldloca(localBuilder);
1077             else
1078                 Ldloc(localBuilder);
1079         }
1080 
Ldloc(LocalBuilder localBuilder)1081         internal void Ldloc(LocalBuilder localBuilder)
1082         {
1083             if (_codeGenTrace != CodeGenTrace.None)
1084                 EmitSourceInstruction("Ldloc " + _localNames[localBuilder]);
1085             _ilGen.Emit(OpCodes.Ldloc, localBuilder);
1086             EmitStackTop(localBuilder.LocalType);
1087         }
1088 
Stloc(LocalBuilder local)1089         internal void Stloc(LocalBuilder local)
1090         {
1091             if (_codeGenTrace != CodeGenTrace.None)
1092                 EmitSourceInstruction("Stloc " + _localNames[local]);
1093             EmitStackTop(local.LocalType);
1094             _ilGen.Emit(OpCodes.Stloc, local);
1095         }
1096 
1097 
Ldloca(LocalBuilder localBuilder)1098         internal void Ldloca(LocalBuilder localBuilder)
1099         {
1100             if (_codeGenTrace != CodeGenTrace.None)
1101                 EmitSourceInstruction("Ldloca " + _localNames[localBuilder]);
1102             _ilGen.Emit(OpCodes.Ldloca, localBuilder);
1103             EmitStackTop(localBuilder.LocalType);
1104         }
1105 
LdargAddress(ArgBuilder argBuilder)1106         internal void LdargAddress(ArgBuilder argBuilder)
1107         {
1108             if (argBuilder.ArgType.IsValueType)
1109                 Ldarga(argBuilder);
1110             else
1111                 Ldarg(argBuilder);
1112         }
1113 
Ldarg(ArgBuilder arg)1114         internal void Ldarg(ArgBuilder arg)
1115         {
1116             Ldarg(arg.Index);
1117         }
1118 
Starg(ArgBuilder arg)1119         internal void Starg(ArgBuilder arg)
1120         {
1121             Starg(arg.Index);
1122         }
1123 
Ldarg(int slot)1124         internal void Ldarg(int slot)
1125         {
1126             if (_codeGenTrace != CodeGenTrace.None)
1127                 EmitSourceInstruction("Ldarg " + slot);
1128             switch (slot)
1129             {
1130                 case 0:
1131                     _ilGen.Emit(OpCodes.Ldarg_0);
1132                     break;
1133                 case 1:
1134                     _ilGen.Emit(OpCodes.Ldarg_1);
1135                     break;
1136                 case 2:
1137                     _ilGen.Emit(OpCodes.Ldarg_2);
1138                     break;
1139                 case 3:
1140                     _ilGen.Emit(OpCodes.Ldarg_3);
1141                     break;
1142                 default:
1143                     if (slot <= 255)
1144                         _ilGen.Emit(OpCodes.Ldarg_S, slot);
1145                     else
1146                         _ilGen.Emit(OpCodes.Ldarg, slot);
1147                     break;
1148             }
1149         }
1150 
Starg(int slot)1151         internal void Starg(int slot)
1152         {
1153             if (_codeGenTrace != CodeGenTrace.None)
1154                 EmitSourceInstruction("Starg " + slot);
1155             if (slot <= 255)
1156                 _ilGen.Emit(OpCodes.Starg_S, slot);
1157             else
1158                 _ilGen.Emit(OpCodes.Starg, slot);
1159         }
1160 
Ldarga(ArgBuilder argBuilder)1161         internal void Ldarga(ArgBuilder argBuilder)
1162         {
1163             Ldarga(argBuilder.Index);
1164         }
1165 
Ldarga(int slot)1166         internal void Ldarga(int slot)
1167         {
1168             if (_codeGenTrace != CodeGenTrace.None)
1169                 EmitSourceInstruction("Ldarga " + slot);
1170             if (slot <= 255)
1171                 _ilGen.Emit(OpCodes.Ldarga_S, slot);
1172             else
1173                 _ilGen.Emit(OpCodes.Ldarga, slot);
1174         }
1175 
Ldlen()1176         internal void Ldlen()
1177         {
1178             if (_codeGenTrace != CodeGenTrace.None)
1179                 EmitSourceInstruction("Ldlen");
1180             _ilGen.Emit(OpCodes.Ldlen);
1181             if (_codeGenTrace != CodeGenTrace.None)
1182                 EmitSourceInstruction("Conv.i4");
1183             _ilGen.Emit(OpCodes.Conv_I4);
1184         }
1185 
GetLdelemOpCode(TypeCode typeCode)1186         private OpCode GetLdelemOpCode(TypeCode typeCode)
1187         {
1188             switch (typeCode)
1189             {
1190                 case TypeCode.Object:
1191                     return OpCodes.Ldelem_Ref;// TypeCode.Object:
1192                 case TypeCode.Boolean:
1193                     return OpCodes.Ldelem_I1;// TypeCode.Boolean:
1194                 case TypeCode.Char:
1195                     return OpCodes.Ldelem_I2;// TypeCode.Char:
1196                 case TypeCode.SByte:
1197                     return OpCodes.Ldelem_I1;// TypeCode.SByte:
1198                 case TypeCode.Byte:
1199                     return OpCodes.Ldelem_U1;// TypeCode.Byte:
1200                 case TypeCode.Int16:
1201                     return OpCodes.Ldelem_I2;// TypeCode.Int16:
1202                 case TypeCode.UInt16:
1203                     return OpCodes.Ldelem_U2;// TypeCode.UInt16:
1204                 case TypeCode.Int32:
1205                     return OpCodes.Ldelem_I4;// TypeCode.Int32:
1206                 case TypeCode.UInt32:
1207                     return OpCodes.Ldelem_U4;// TypeCode.UInt32:
1208                 case TypeCode.Int64:
1209                     return OpCodes.Ldelem_I8;// TypeCode.Int64:
1210                 case TypeCode.UInt64:
1211                     return OpCodes.Ldelem_I8;// TypeCode.UInt64:
1212                 case TypeCode.Single:
1213                     return OpCodes.Ldelem_R4;// TypeCode.Single:
1214                 case TypeCode.Double:
1215                     return OpCodes.Ldelem_R8;// TypeCode.Double:
1216                 case TypeCode.String:
1217                     return OpCodes.Ldelem_Ref;// TypeCode.String:
1218                 default:
1219                     return OpCodes.Nop;
1220             }
1221         }
1222 
Ldelem(Type arrayElementType)1223         internal void Ldelem(Type arrayElementType)
1224         {
1225             if (arrayElementType.IsEnum)
1226             {
1227                 Ldelem(Enum.GetUnderlyingType(arrayElementType));
1228             }
1229             else
1230             {
1231                 OpCode opCode = GetLdelemOpCode(arrayElementType.GetTypeCode());
1232                 if (opCode.Equals(OpCodes.Nop))
1233                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
1234                 if (_codeGenTrace != CodeGenTrace.None)
1235                     EmitSourceInstruction(opCode.ToString());
1236                 _ilGen.Emit(opCode);
1237                 EmitStackTop(arrayElementType);
1238             }
1239         }
Ldelema(Type arrayElementType)1240         internal void Ldelema(Type arrayElementType)
1241         {
1242             OpCode opCode = OpCodes.Ldelema;
1243             if (_codeGenTrace != CodeGenTrace.None)
1244                 EmitSourceInstruction(opCode.ToString());
1245             _ilGen.Emit(opCode, arrayElementType);
1246 
1247             EmitStackTop(arrayElementType);
1248         }
1249 
GetStelemOpCode(TypeCode typeCode)1250         private OpCode GetStelemOpCode(TypeCode typeCode)
1251         {
1252             switch (typeCode)
1253             {
1254                 case TypeCode.Object:
1255                     return OpCodes.Stelem_Ref;// TypeCode.Object:
1256                 case TypeCode.Boolean:
1257                     return OpCodes.Stelem_I1;// TypeCode.Boolean:
1258                 case TypeCode.Char:
1259                     return OpCodes.Stelem_I2;// TypeCode.Char:
1260                 case TypeCode.SByte:
1261                     return OpCodes.Stelem_I1;// TypeCode.SByte:
1262                 case TypeCode.Byte:
1263                     return OpCodes.Stelem_I1;// TypeCode.Byte:
1264                 case TypeCode.Int16:
1265                     return OpCodes.Stelem_I2;// TypeCode.Int16:
1266                 case TypeCode.UInt16:
1267                     return OpCodes.Stelem_I2;// TypeCode.UInt16:
1268                 case TypeCode.Int32:
1269                     return OpCodes.Stelem_I4;// TypeCode.Int32:
1270                 case TypeCode.UInt32:
1271                     return OpCodes.Stelem_I4;// TypeCode.UInt32:
1272                 case TypeCode.Int64:
1273                     return OpCodes.Stelem_I8;// TypeCode.Int64:
1274                 case TypeCode.UInt64:
1275                     return OpCodes.Stelem_I8;// TypeCode.UInt64:
1276                 case TypeCode.Single:
1277                     return OpCodes.Stelem_R4;// TypeCode.Single:
1278                 case TypeCode.Double:
1279                     return OpCodes.Stelem_R8;// TypeCode.Double:
1280                 case TypeCode.String:
1281                     return OpCodes.Stelem_Ref;// TypeCode.String:
1282                 default:
1283                     return OpCodes.Nop;
1284             }
1285         }
1286 
Stelem(Type arrayElementType)1287         internal void Stelem(Type arrayElementType)
1288         {
1289             if (arrayElementType.IsEnum)
1290                 Stelem(Enum.GetUnderlyingType(arrayElementType));
1291             else
1292             {
1293                 OpCode opCode = GetStelemOpCode(arrayElementType.GetTypeCode());
1294                 if (opCode.Equals(OpCodes.Nop))
1295                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
1296                 if (_codeGenTrace != CodeGenTrace.None)
1297                     EmitSourceInstruction(opCode.ToString());
1298                 EmitStackTop(arrayElementType);
1299                 _ilGen.Emit(opCode);
1300             }
1301         }
1302 
DefineLabel()1303         internal Label DefineLabel()
1304         {
1305             return _ilGen.DefineLabel();
1306         }
1307 
MarkLabel(Label label)1308         internal void MarkLabel(Label label)
1309         {
1310             _ilGen.MarkLabel(label);
1311             if (_codeGenTrace != CodeGenTrace.None)
1312                 EmitSourceLabel(label.GetHashCode() + ":");
1313         }
1314 
Add()1315         internal void Add()
1316         {
1317             if (_codeGenTrace != CodeGenTrace.None)
1318                 EmitSourceInstruction("Add");
1319             _ilGen.Emit(OpCodes.Add);
1320         }
1321 
Subtract()1322         internal void Subtract()
1323         {
1324             if (_codeGenTrace != CodeGenTrace.None)
1325                 EmitSourceInstruction("Sub");
1326             _ilGen.Emit(OpCodes.Sub);
1327         }
1328 
And()1329         internal void And()
1330         {
1331             if (_codeGenTrace != CodeGenTrace.None)
1332                 EmitSourceInstruction("And");
1333             _ilGen.Emit(OpCodes.And);
1334         }
Or()1335         internal void Or()
1336         {
1337             if (_codeGenTrace != CodeGenTrace.None)
1338                 EmitSourceInstruction("Or");
1339             _ilGen.Emit(OpCodes.Or);
1340         }
1341 
Not()1342         internal void Not()
1343         {
1344             if (_codeGenTrace != CodeGenTrace.None)
1345                 EmitSourceInstruction("Not");
1346             _ilGen.Emit(OpCodes.Not);
1347         }
1348 
Ret()1349         internal void Ret()
1350         {
1351             if (_codeGenTrace != CodeGenTrace.None)
1352                 EmitSourceInstruction("Ret");
1353             _ilGen.Emit(OpCodes.Ret);
1354         }
1355 
Br(Label label)1356         internal void Br(Label label)
1357         {
1358             if (_codeGenTrace != CodeGenTrace.None)
1359                 EmitSourceInstruction("Br " + label.GetHashCode());
1360             _ilGen.Emit(OpCodes.Br, label);
1361         }
1362 
Blt(Label label)1363         internal void Blt(Label label)
1364         {
1365             if (_codeGenTrace != CodeGenTrace.None)
1366                 EmitSourceInstruction("Blt " + label.GetHashCode());
1367             _ilGen.Emit(OpCodes.Blt, label);
1368         }
1369 
Brfalse(Label label)1370         internal void Brfalse(Label label)
1371         {
1372             if (_codeGenTrace != CodeGenTrace.None)
1373                 EmitSourceInstruction("Brfalse " + label.GetHashCode());
1374             _ilGen.Emit(OpCodes.Brfalse, label);
1375         }
1376 
Brtrue(Label label)1377         internal void Brtrue(Label label)
1378         {
1379             if (_codeGenTrace != CodeGenTrace.None)
1380                 EmitSourceInstruction("Brtrue " + label.GetHashCode());
1381             _ilGen.Emit(OpCodes.Brtrue, label);
1382         }
1383 
1384 
1385 
Pop()1386         internal void Pop()
1387         {
1388             if (_codeGenTrace != CodeGenTrace.None)
1389                 EmitSourceInstruction("Pop");
1390             _ilGen.Emit(OpCodes.Pop);
1391         }
1392 
Dup()1393         internal void Dup()
1394         {
1395             if (_codeGenTrace != CodeGenTrace.None)
1396                 EmitSourceInstruction("Dup");
1397             _ilGen.Emit(OpCodes.Dup);
1398         }
1399 
LoadThis(object thisObj, MethodInfo methodInfo)1400         private void LoadThis(object thisObj, MethodInfo methodInfo)
1401         {
1402             if (thisObj != null && !methodInfo.IsStatic)
1403             {
1404                 LoadAddress(thisObj);
1405                 ConvertAddress(GetVariableType(thisObj), methodInfo.DeclaringType);
1406             }
1407         }
1408 
LoadParam(object arg, int oneBasedArgIndex, MethodBase methodInfo)1409         private void LoadParam(object arg, int oneBasedArgIndex, MethodBase methodInfo)
1410         {
1411             Load(arg);
1412             if (arg != null)
1413                 ConvertValue(GetVariableType(arg), methodInfo.GetParameters()[oneBasedArgIndex - 1].ParameterType);
1414         }
1415 
InternalIf(bool negate)1416         private void InternalIf(bool negate)
1417         {
1418             IfState ifState = new IfState();
1419             ifState.EndIf = DefineLabel();
1420             ifState.ElseBegin = DefineLabel();
1421             if (negate)
1422                 Brtrue(ifState.ElseBegin);
1423             else
1424                 Brfalse(ifState.ElseBegin);
1425             _blockStack.Push(ifState);
1426         }
1427 
GetConvOpCode(TypeCode typeCode)1428         private OpCode GetConvOpCode(TypeCode typeCode)
1429         {
1430             switch (typeCode)
1431             {
1432                 case TypeCode.Boolean:
1433                     return OpCodes.Conv_I1;// TypeCode.Boolean:
1434                 case TypeCode.Char:
1435                     return OpCodes.Conv_I2;// TypeCode.Char:
1436                 case TypeCode.SByte:
1437                     return OpCodes.Conv_I1;// TypeCode.SByte:
1438                 case TypeCode.Byte:
1439                     return OpCodes.Conv_U1;// TypeCode.Byte:
1440                 case TypeCode.Int16:
1441                     return OpCodes.Conv_I2;// TypeCode.Int16:
1442                 case TypeCode.UInt16:
1443                     return OpCodes.Conv_U2;// TypeCode.UInt16:
1444                 case TypeCode.Int32:
1445                     return OpCodes.Conv_I4;// TypeCode.Int32:
1446                 case TypeCode.UInt32:
1447                     return OpCodes.Conv_U4;// TypeCode.UInt32:
1448                 case TypeCode.Int64:
1449                     return OpCodes.Conv_I8;// TypeCode.Int64:
1450                 case TypeCode.UInt64:
1451                     return OpCodes.Conv_I8;// TypeCode.UInt64:
1452                 case TypeCode.Single:
1453                     return OpCodes.Conv_R4;// TypeCode.Single:
1454                 case TypeCode.Double:
1455                     return OpCodes.Conv_R8;// TypeCode.Double:
1456                 default:
1457                     return OpCodes.Nop;
1458             }
1459         }
1460 
InternalConvert(Type source, Type target, bool isAddress)1461         private void InternalConvert(Type source, Type target, bool isAddress)
1462         {
1463             if (target == source)
1464                 return;
1465             if (target.IsValueType)
1466             {
1467                 if (source.IsValueType)
1468                 {
1469                     OpCode opCode = GetConvOpCode(target.GetTypeCode());
1470                     if (opCode.Equals(OpCodes.Nop))
1471                         throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.NoConversionPossibleTo, DataContract.GetClrTypeFullName(target))));
1472                     else
1473                     {
1474                         if (_codeGenTrace != CodeGenTrace.None)
1475                             EmitSourceInstruction(opCode.ToString());
1476                         _ilGen.Emit(opCode);
1477                     }
1478                 }
1479                 else if (source.IsAssignableFrom(target))
1480                 {
1481                     Unbox(target);
1482                     if (!isAddress)
1483                         Ldobj(target);
1484                 }
1485                 else
1486                     throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
1487             }
1488             else if (target.IsAssignableFrom(source))
1489             {
1490                 if (source.IsValueType)
1491                 {
1492                     if (isAddress)
1493                         Ldobj(source);
1494                     Box(source);
1495                 }
1496             }
1497             else if (source.IsAssignableFrom(target))
1498             {
1499                 Castclass(target);
1500             }
1501             else if (target.IsInterface || source.IsInterface)
1502             {
1503                 Castclass(target);
1504             }
1505             else
1506                 throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
1507         }
1508 
PopIfState()1509         private IfState PopIfState()
1510         {
1511             object stackTop = _blockStack.Pop();
1512             IfState ifState = stackTop as IfState;
1513             if (ifState == null)
1514                 ThrowMismatchException(stackTop);
1515             return ifState;
1516         }
1517 
1518 #if USE_REFEMIT
InitAssemblyBuilder(string methodName)1519         void InitAssemblyBuilder(string methodName)
1520         {
1521             AssemblyName name = new AssemblyName();
1522             name.Name = "Microsoft.GeneratedCode."+methodName;
1523             //Add SecurityCritical and SecurityTreatAsSafe attributes to the generated method
1524             assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
1525             moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name + ".dll", false);
1526         }
1527 #endif
1528 
ThrowMismatchException(object expected)1529         private void ThrowMismatchException(object expected)
1530         {
1531             throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.Format(SR.ExpectingEnd, expected.ToString())));
1532         }
1533 
1534 
1535         [Conditional("NOT_SILVERLIGHT")]
EmitSourceInstruction(string line)1536         internal void EmitSourceInstruction(string line)
1537         {
1538         }
1539 
1540         [Conditional("NOT_SILVERLIGHT")]
EmitSourceLabel(string line)1541         internal void EmitSourceLabel(string line)
1542         {
1543         }
1544 
1545         [Conditional("NOT_SILVERLIGHT")]
EmitSourceComment(string comment)1546         internal void EmitSourceComment(string comment)
1547         {
1548         }
1549 
1550 
EmitStackTop(Type stackTopType)1551         internal void EmitStackTop(Type stackTopType)
1552         {
1553             if (_codeGenTrace != CodeGenTrace.Tron)
1554                 return;
1555         }
1556 
Switch(int labelCount)1557         internal Label[] Switch(int labelCount)
1558         {
1559             SwitchState switchState = new SwitchState(DefineLabel(), DefineLabel());
1560             Label[] caseLabels = new Label[labelCount];
1561             for (int i = 0; i < caseLabels.Length; i++)
1562                 caseLabels[i] = DefineLabel();
1563 
1564             _ilGen.Emit(OpCodes.Switch, caseLabels);
1565             Br(switchState.DefaultLabel);
1566             _blockStack.Push(switchState);
1567             return caseLabels;
1568         }
Case(Label caseLabel1, string caseLabelName)1569         internal void Case(Label caseLabel1, string caseLabelName)
1570         {
1571             if (_codeGenTrace != CodeGenTrace.None)
1572                 EmitSourceInstruction("case " + caseLabelName + "{");
1573             MarkLabel(caseLabel1);
1574         }
1575 
EndCase()1576         internal void EndCase()
1577         {
1578             object stackTop = _blockStack.Peek();
1579             SwitchState switchState = stackTop as SwitchState;
1580             if (switchState == null)
1581                 ThrowMismatchException(stackTop);
1582             Br(switchState.EndOfSwitchLabel);
1583             if (_codeGenTrace != CodeGenTrace.None)
1584                 EmitSourceInstruction("} //end case ");
1585         }
1586 
EndSwitch()1587         internal void EndSwitch()
1588         {
1589             object stackTop = _blockStack.Pop();
1590             SwitchState switchState = stackTop as SwitchState;
1591             if (switchState == null)
1592                 ThrowMismatchException(stackTop);
1593             if (_codeGenTrace != CodeGenTrace.None)
1594                 EmitSourceInstruction("} //end switch");
1595             if (!switchState.DefaultDefined)
1596                 MarkLabel(switchState.DefaultLabel);
1597             MarkLabel(switchState.EndOfSwitchLabel);
1598         }
1599 
1600         private static MethodInfo s_stringLength = typeof(string).GetProperty("Length").GetMethod;
ElseIfIsEmptyString(LocalBuilder strLocal)1601         internal void ElseIfIsEmptyString(LocalBuilder strLocal)
1602         {
1603             IfState ifState = (IfState)_blockStack.Pop();
1604             Br(ifState.EndIf);
1605             MarkLabel(ifState.ElseBegin);
1606 
1607             Load(strLocal);
1608             Call(s_stringLength);
1609             Load(0);
1610             ifState.ElseBegin = DefineLabel();
1611             _ilGen.Emit(GetBranchCode(Cmp.EqualTo), ifState.ElseBegin);
1612             _blockStack.Push(ifState);
1613         }
1614 
IfNotIsEmptyString(LocalBuilder strLocal)1615         internal void IfNotIsEmptyString(LocalBuilder strLocal)
1616         {
1617             Load(strLocal);
1618             Call(s_stringLength);
1619             Load(0);
1620             If(Cmp.NotEqualTo);
1621         }
1622 
1623 #if !uapaot
BeginWhileCondition()1624         internal void BeginWhileCondition()
1625         {
1626             Label startWhile = DefineLabel();
1627             MarkLabel(startWhile);
1628             _blockStack.Push(startWhile);
1629         }
1630 
BeginWhileBody(Cmp cmpOp)1631         internal void BeginWhileBody(Cmp cmpOp)
1632         {
1633             Label startWhile = (Label)_blockStack.Pop();
1634             If(cmpOp);
1635             _blockStack.Push(startWhile);
1636         }
1637 
EndWhile()1638         internal void EndWhile()
1639         {
1640             Label startWhile = (Label)_blockStack.Pop();
1641             Br(startWhile);
1642             EndIf();
1643         }
1644 
CallStringFormat(string msg, params object[] values)1645         internal void CallStringFormat(string msg, params object[] values)
1646         {
1647             NewArray(typeof(object), values.Length);
1648             if (_stringFormatArray == null)
1649                 _stringFormatArray = DeclareLocal(typeof(object[]), "stringFormatArray");
1650             Stloc(_stringFormatArray);
1651             for (int i = 0; i < values.Length; i++)
1652                 StoreArrayElement(_stringFormatArray, i, values[i]);
1653 
1654             Load(msg);
1655             Load(_stringFormatArray);
1656             Call(StringFormat);
1657         }
1658 
ToString(Type type)1659         internal void ToString(Type type)
1660         {
1661             if (type != Globals.TypeOfString)
1662             {
1663                 if (type.IsValueType)
1664                 {
1665                     Box(type);
1666                 }
1667                 Call(ObjectToString);
1668             }
1669         }
1670 #endif
1671     }
1672 
1673 
1674     internal class ArgBuilder
1675     {
1676         internal int Index;
1677         internal Type ArgType;
ArgBuilder(int index, Type argType)1678         internal ArgBuilder(int index, Type argType)
1679         {
1680             this.Index = index;
1681             this.ArgType = argType;
1682         }
1683     }
1684 
1685     internal class ForState
1686     {
1687         private LocalBuilder _indexVar;
1688         private Label _beginLabel;
1689         private Label _testLabel;
1690         private Label _endLabel;
1691         private bool _requiresEndLabel;
1692         private object _end;
1693 
ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end)1694         internal ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end)
1695         {
1696             _indexVar = indexVar;
1697             _beginLabel = beginLabel;
1698             _testLabel = testLabel;
1699             _end = end;
1700         }
1701 
1702         internal LocalBuilder Index
1703         {
1704             get
1705             {
1706                 return _indexVar;
1707             }
1708         }
1709 
1710         internal Label BeginLabel
1711         {
1712             get
1713             {
1714                 return _beginLabel;
1715             }
1716         }
1717 
1718         internal Label TestLabel
1719         {
1720             get
1721             {
1722                 return _testLabel;
1723             }
1724         }
1725 
1726         internal Label EndLabel
1727         {
1728             get
1729             {
1730                 return _endLabel;
1731             }
1732             set
1733             {
1734                 _endLabel = value;
1735             }
1736         }
1737 
1738         internal bool RequiresEndLabel
1739         {
1740             get
1741             {
1742                 return _requiresEndLabel;
1743             }
1744             set
1745             {
1746                 _requiresEndLabel = value;
1747             }
1748         }
1749 
1750         internal object End
1751         {
1752             get
1753             {
1754                 return _end;
1755             }
1756         }
1757     }
1758 
1759     internal enum Cmp
1760     {
1761         LessThan,
1762         EqualTo,
1763         LessThanOrEqualTo,
1764         GreaterThan,
1765         NotEqualTo,
1766         GreaterThanOrEqualTo
1767     }
1768 
1769     internal class IfState
1770     {
1771         private Label _elseBegin;
1772         private Label _endIf;
1773 
1774         internal Label EndIf
1775         {
1776             get
1777             {
1778                 return _endIf;
1779             }
1780             set
1781             {
1782                 _endIf = value;
1783             }
1784         }
1785 
1786         internal Label ElseBegin
1787         {
1788             get
1789             {
1790                 return _elseBegin;
1791             }
1792             set
1793             {
1794                 _elseBegin = value;
1795             }
1796         }
1797     }
1798 
1799 
1800     internal class SwitchState
1801     {
1802         private Label _defaultLabel;
1803         private Label _endOfSwitchLabel;
1804         private bool _defaultDefined;
SwitchState(Label defaultLabel, Label endOfSwitchLabel)1805         internal SwitchState(Label defaultLabel, Label endOfSwitchLabel)
1806         {
1807             _defaultLabel = defaultLabel;
1808             _endOfSwitchLabel = endOfSwitchLabel;
1809             _defaultDefined = false;
1810         }
1811         internal Label DefaultLabel
1812         {
1813             get
1814             {
1815                 return _defaultLabel;
1816             }
1817         }
1818 
1819         internal Label EndOfSwitchLabel
1820         {
1821             get
1822             {
1823                 return _endOfSwitchLabel;
1824             }
1825         }
1826         internal bool DefaultDefined
1827         {
1828             get
1829             {
1830                 return _defaultDefined;
1831             }
1832             set
1833             {
1834                 _defaultDefined = value;
1835             }
1836         }
1837     }
1838 }
1839 #endif
1840