[bcl] Updates referencesource to 4.7.1
[mono-project.git] / mcs / class / referencesource / System.Xml / System / Xml / Serialization / CodeGenerator.cs
blobbfc07babb6aa8a4c1a0f1c8d9c061812fb5453fc
1 //------------------------------------------------------------------------------
2 // <copyright file="CodeGenerator.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
8 using System;
9 using System.Reflection;
10 using System.Resources;
11 using System.Runtime.CompilerServices;
14 namespace System.Xml.Serialization {
15 using System;
16 using System.Collections;
17 using System.Collections.Generic;
18 using System.Configuration;
19 using System.Globalization;
20 using System.Xml;
21 using System.Xml.Serialization.Configuration;
22 using System.Reflection;
23 using System.Reflection.Emit;
24 using System.IO;
25 using System.Security;
26 using System.Security.Permissions;
27 using System.Text.RegularExpressions;
28 using System.Diagnostics;
29 using System.Diagnostics.CodeAnalysis;
31 internal class CodeGenerator {
33 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method does validation only without any user input")]
34 internal static bool IsValidLanguageIndependentIdentifier(string ident) { return System.CodeDom.Compiler.CodeGenerator.IsValidLanguageIndependentIdentifier(ident); }
35 [SuppressMessage("Microsoft.Security", "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands", Justification = "Method does validation only without any user input")]
36 internal static void ValidateIdentifiers(System.CodeDom.CodeObject e) { System.CodeDom.Compiler.CodeGenerator.ValidateIdentifiers(e); }
37 internal static BindingFlags InstancePublicBindingFlags = BindingFlags.Instance | BindingFlags.Public;
38 internal static BindingFlags InstanceBindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
39 internal static BindingFlags StaticBindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
40 internal static MethodAttributes PublicMethodAttributes = MethodAttributes.Public | MethodAttributes.HideBySig;
41 internal static MethodAttributes PublicOverrideMethodAttributes = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig;
42 internal static MethodAttributes ProtectedOverrideMethodAttributes = MethodAttributes.Family | MethodAttributes.Virtual | MethodAttributes.HideBySig;
43 internal static MethodAttributes PrivateMethodAttributes = MethodAttributes.Private | MethodAttributes.HideBySig;
44 internal static Type[] EmptyTypeArray = new Type[] { };
45 internal static string[] EmptyStringArray = new string[] { };
47 TypeBuilder typeBuilder;
48 MethodBuilder methodBuilder;
49 ILGenerator ilGen;
50 Dictionary<string, ArgBuilder> argList;
51 LocalScope currentScope;
52 // Stores a queue of free locals available in the context of the method, keyed by
53 // type and name of the local
54 Dictionary<Tuple<Type, string>, Queue<LocalBuilder>> freeLocals;
55 Stack blockStack;
56 Label methodEndLabel;
58 internal CodeGenerator(TypeBuilder typeBuilder) {
59 System.Diagnostics.Debug.Assert(typeBuilder != null);
60 this.typeBuilder = typeBuilder;
63 internal static bool IsNullableGenericType(Type type) {
64 return type.Name == "Nullable`1";
67 internal static void AssertHasInterface(Type type, Type iType) {
68 #if DEBUG
69 Debug.Assert(iType.IsInterface);
70 foreach (Type iFace in type.GetInterfaces()) {
71 if (iFace == iType)
72 return;
74 Debug.Assert(false);
75 #endif
78 internal void BeginMethod(Type returnType, string methodName, Type[] argTypes, string[] argNames, MethodAttributes methodAttributes) {
79 this.methodBuilder = typeBuilder.DefineMethod(methodName, methodAttributes, returnType, argTypes);
80 this.ilGen = methodBuilder.GetILGenerator();
81 InitILGeneration(argTypes, argNames, (methodBuilder.Attributes & MethodAttributes.Static) == MethodAttributes.Static);
84 internal void BeginMethod(Type returnType, MethodBuilderInfo methodBuilderInfo, Type[] argTypes, string[] argNames, MethodAttributes methodAttributes) {
85 #if DEBUG
86 methodBuilderInfo.Validate(returnType, argTypes, methodAttributes);
87 #endif
88 this.methodBuilder = methodBuilderInfo.MethodBuilder;
89 this.ilGen = methodBuilder.GetILGenerator();
90 InitILGeneration(argTypes, argNames, (methodBuilder.Attributes & MethodAttributes.Static) == MethodAttributes.Static);
93 void InitILGeneration(Type[] argTypes, string[] argNames, bool isStatic) {
94 this.methodEndLabel = ilGen.DefineLabel();
95 this.retLabel = ilGen.DefineLabel();
96 this.blockStack = new Stack();
97 this.whileStack = new Stack();
98 this.currentScope = new LocalScope();
99 this.freeLocals = new Dictionary<Tuple<Type, string>, Queue<LocalBuilder>>();
100 this.argList = new Dictionary<string, ArgBuilder>();
101 // this ptr is arg 0 for non static, assuming ref type (not value type)
102 if (!isStatic)
103 argList.Add("this", new ArgBuilder("this", 0, this.typeBuilder.BaseType));
104 for (int i = 0; i < argTypes.Length; i++) {
105 ArgBuilder arg = new ArgBuilder(argNames[i], argList.Count, argTypes[i]);
106 argList.Add(arg.Name, arg);
107 this.methodBuilder.DefineParameter(arg.Index, ParameterAttributes.None, arg.Name);
111 internal MethodBuilder EndMethod() {
112 MarkLabel(methodEndLabel);
113 Ret();
115 MethodBuilder retVal = null;
116 retVal = methodBuilder;
117 methodBuilder = null;
118 ilGen = null;
119 freeLocals = null;
120 blockStack = null;
121 whileStack = null;
122 argList = null;
123 currentScope = null;
124 retLocal = null;
125 return retVal;
128 internal MethodBuilder MethodBuilder {
129 get { return this.methodBuilder; }
132 internal static Exception NotSupported(string msg) {
133 System.Diagnostics.Debug.Assert(false, msg);
134 return new NotSupportedException(msg);
137 internal ArgBuilder GetArg(string name) {
138 System.Diagnostics.Debug.Assert(argList != null && argList.ContainsKey(name));
139 return (ArgBuilder)argList[name];
142 internal LocalBuilder GetLocal(string name) {
143 System.Diagnostics.Debug.Assert(currentScope != null && currentScope.ContainsKey(name));
144 return currentScope[name];
147 internal LocalBuilder retLocal;
148 internal Label retLabel;
149 internal LocalBuilder ReturnLocal {
150 get {
151 if (retLocal == null)
152 retLocal = DeclareLocal(this.methodBuilder.ReturnType, "_ret");
153 return retLocal;
156 internal Label ReturnLabel {
157 get { return retLabel; }
160 Dictionary<Type, LocalBuilder> TmpLocals = new Dictionary<Type, LocalBuilder>();
161 internal LocalBuilder GetTempLocal(Type type) {
162 LocalBuilder localTmp;
163 if (!TmpLocals.TryGetValue(type, out localTmp)) {
164 localTmp = DeclareLocal(type, "_tmp" + TmpLocals.Count);
165 TmpLocals.Add(type, localTmp);
167 return localTmp;
170 internal Type GetVariableType(object var) {
171 if (var is ArgBuilder)
172 return ((ArgBuilder)var).ArgType;
173 else if (var is LocalBuilder)
174 return ((LocalBuilder)var).LocalType;
175 else
176 return var.GetType();
179 internal object GetVariable(string name) {
180 object var;
181 if (TryGetVariable(name, out var))
182 return var;
183 System.Diagnostics.Debug.Assert(false);
184 return null;
187 internal bool TryGetVariable(string name, out object variable) {
188 LocalBuilder loc;
189 if (currentScope != null && currentScope.TryGetValue(name, out loc)) {
190 variable = loc;
191 return true;
193 ArgBuilder arg;
194 if (argList != null && argList.TryGetValue(name, out arg)) {
195 variable = arg;
196 return true;
198 int val;
199 if (Int32.TryParse(name, out val)) {
200 variable = val;
201 return true;
203 variable = null;
204 return false;
207 #if NotUsed
208 internal LocalBuilder DeclareLocal(Type type, string name, object initialValue) {
209 LocalBuilder local = DeclareLocal(type, name);
210 Load(initialValue);
211 Store(local);
212 return local;
214 #endif
215 internal void EnterScope() {
216 LocalScope newScope = new LocalScope(this.currentScope);
217 this.currentScope = newScope;
220 internal void ExitScope()
222 Debug.Assert(this.currentScope.parent != null);
223 this.currentScope.AddToFreeLocals(freeLocals);
224 this.currentScope = this.currentScope.parent;
227 private bool TryDequeueLocal(Type type, string name, out LocalBuilder local) {
228 // This method can only be called between BeginMethod and EndMethod (i.e.
229 // while we are emitting code for a method
230 Debug.Assert(freeLocals != null);
232 Queue<LocalBuilder> freeLocalQueue;
233 Tuple<Type, string> key = new Tuple<Type, string>(type, name);
234 if (freeLocals.TryGetValue(key, out freeLocalQueue)) {
235 local = freeLocalQueue.Dequeue();
237 // If the queue is empty, remove this key from the dictionary
238 // of free locals
239 if (freeLocalQueue.Count == 0) {
240 freeLocals.Remove(key);
242 return true;
244 local = null;
245 return false;
248 internal LocalBuilder DeclareLocal(Type type, string name) {
249 Debug.Assert(!currentScope.ContainsKey(name));
250 LocalBuilder local;
251 if (!TryDequeueLocal(type, name, out local)) {
252 local = ilGen.DeclareLocal(type, false);
253 if (DiagnosticsSwitches.KeepTempFiles.Enabled)
254 local.SetLocalSymInfo(name);
256 currentScope[name] = local;
257 return local;
260 internal LocalBuilder DeclareOrGetLocal(Type type, string name) {
261 LocalBuilder local;
262 if (!currentScope.TryGetValue(name, out local))
263 local = DeclareLocal(type, name);
264 else
265 Debug.Assert(local.LocalType == type);
266 return local;
269 #if NotUsed
270 Dictionary<string, int> parameterMapping = new Dictionary<string, int>();
271 internal Dictionary<string, int> ParameterMapping { get { return this.parameterMapping; } }
272 internal ParameterBuilder DefineParameter(int index, ParameterAttributes attributes, string name)
274 if (this.parameterMapping == null)
276 this.parameterMapping = new Dictionary<string, int>();
278 this.parameterMapping.Add(name, index);
279 return this.methodBuilder.DefineParameter(index, attributes, name);
282 internal void Set(LocalBuilder local, object value)
284 Load(value);
285 Store(local);
287 #endif
288 internal object For(LocalBuilder local, object start, object end) {
289 ForState forState = new ForState(local, DefineLabel(), DefineLabel(), end);
290 if (forState.Index != null) {
291 Load(start);
292 Stloc(forState.Index);
293 Br(forState.TestLabel);
295 MarkLabel(forState.BeginLabel);
296 blockStack.Push(forState);
297 return forState;
300 internal void EndFor() {
301 object stackTop = blockStack.Pop();
302 ForState forState = stackTop as ForState;
303 Debug.Assert(forState != null);
304 if (forState.Index != null) {
305 Ldloc(forState.Index);
306 Ldc(1);
307 Add();
308 Stloc(forState.Index);
309 MarkLabel(forState.TestLabel);
310 Ldloc(forState.Index);
311 Load(forState.End);
312 Type varType = GetVariableType(forState.End);
313 if (varType.IsArray) {
314 Ldlen();
316 else {
317 #if DEBUG
318 CodeGenerator.AssertHasInterface(varType, typeof(ICollection));
319 #endif
320 MethodInfo ICollection_get_Count = typeof(ICollection).GetMethod(
321 "get_Count",
322 CodeGenerator.InstanceBindingFlags,
323 null,
324 CodeGenerator.EmptyTypeArray,
325 null
327 Call(ICollection_get_Count);
329 Blt(forState.BeginLabel);
331 else
332 Br(forState.BeginLabel);
335 #if NotUsed
336 internal void Break(object forState)
338 InternalBreakFor(forState, OpCodes.Br);
341 internal void IfTrueBreak(object forState)
343 InternalBreakFor(forState, OpCodes.Brtrue);
346 internal void IfFalseBreak(object forState)
348 InternalBreakFor(forState, OpCodes.Brfalse);
351 internal void InternalBreakFor(object userForState, OpCode branchInstruction)
353 foreach (object block in blockStack)
355 ForState forState = block as ForState;
356 if (forState != null && (object)forState == userForState)
358 if (!forState.RequiresEndLabel)
360 forState.EndLabel = DefineLabel();
361 forState.RequiresEndLabel = true;
363 ilGen.Emit(branchInstruction, forState.EndLabel);
364 break;
369 internal void ForEach(LocalBuilder local, Type elementType, Type enumeratorType,
370 LocalBuilder enumerator, MethodInfo getCurrentMethod)
372 ForState forState = new ForState(local, DefineLabel(), DefineLabel(), enumerator);
374 Br(forState.TestLabel);
375 MarkLabel(forState.BeginLabel);
377 Call(enumerator, getCurrentMethod);
379 ConvertValue(elementType, GetVariableType(local));
380 Stloc(local);
381 blockStack.Push(forState);
384 internal void EndForEach(MethodInfo moveNextMethod)
386 object stackTop = blockStack.Pop();
387 ForState forState = stackTop as ForState;
388 if (forState == null)
389 ThrowMismatchException(stackTop);
391 MarkLabel(forState.TestLabel);
393 object enumerator = forState.End;
394 Call(enumerator, moveNextMethod);
397 Brtrue(forState.BeginLabel);
398 if (forState.RequiresEndLabel)
399 MarkLabel(forState.EndLabel);
402 internal void IfNotDefaultValue(object value)
404 Type type = GetVariableType(value);
405 TypeCode typeCode = Type.GetTypeCode(type);
406 if ((typeCode == TypeCode.Object && type.IsValueType) ||
407 typeCode == TypeCode.DateTime || typeCode == TypeCode.Decimal)
409 LoadDefaultValue(type);
410 ConvertValue(type, Globals.TypeOfObject);
411 Load(value);
412 ConvertValue(type, Globals.TypeOfObject);
413 Call(ObjectEquals);
414 IfNot();
416 else
418 LoadDefaultValue(type);
419 Load(value);
420 If(Cmp.NotEqualTo);
423 #endif
425 internal void If() {
426 InternalIf(false);
429 internal void IfNot() {
430 InternalIf(true);
433 static OpCode[] BranchCodes = new OpCode[] {
434 OpCodes.Bge,
435 OpCodes.Bne_Un,
436 OpCodes.Bgt,
437 OpCodes.Ble,
438 OpCodes.Beq,
439 OpCodes.Blt,
442 OpCode GetBranchCode(Cmp cmp) {
443 return BranchCodes[(int)cmp];
446 #if NotUsed
447 Cmp GetCmpInverse(Cmp cmp)
449 switch (cmp) {
450 case Cmp.LessThan:
451 return Cmp.GreaterThanOrEqualTo;
452 case Cmp.EqualTo:
453 return Cmp.NotEqualTo;
454 case Cmp.LessThanOrEqualTo:
455 return Cmp.GreaterThan;
456 case Cmp.GreaterThan:
457 return Cmp.LessThanOrEqualTo;
458 case Cmp.NotEqualTo:
459 return Cmp.EqualTo;
460 default:
461 Debug.Assert(cmp == Cmp.GreaterThanOrEqualTo, "Unexpected cmp");
462 return Cmp.LessThan;
465 #endif
467 internal void If(Cmp cmpOp) {
468 IfState ifState = new IfState();
469 ifState.EndIf = DefineLabel();
470 ifState.ElseBegin = DefineLabel();
471 ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
472 blockStack.Push(ifState);
475 internal void If(object value1, Cmp cmpOp, object value2) {
476 Load(value1);
477 Load(value2);
478 If(cmpOp);
481 internal void Else() {
482 IfState ifState = PopIfState();
483 Br(ifState.EndIf);
484 MarkLabel(ifState.ElseBegin);
486 ifState.ElseBegin = ifState.EndIf;
487 blockStack.Push(ifState);
490 #if NotUsed
491 internal void ElseIf(object value1, Cmp cmpOp, object value2)
493 IfState ifState = (IfState)blockStack.Pop();
494 Br(ifState.EndIf);
495 MarkLabel(ifState.ElseBegin);
497 Load(value1);
498 Load(value2);
499 ifState.ElseBegin = DefineLabel();
500 ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
501 blockStack.Push(ifState);
503 #endif
505 internal void EndIf() {
506 IfState ifState = PopIfState();
507 if (!ifState.ElseBegin.Equals(ifState.EndIf))
508 MarkLabel(ifState.ElseBegin);
509 MarkLabel(ifState.EndIf);
512 Stack leaveLabels = new Stack();
513 internal void BeginExceptionBlock() {
514 leaveLabels.Push(DefineLabel());
515 ilGen.BeginExceptionBlock();
518 internal void BeginCatchBlock(Type exception) {
519 ilGen.BeginCatchBlock(exception);
522 internal void EndExceptionBlock() {
523 ilGen.EndExceptionBlock();
524 ilGen.MarkLabel((Label)leaveLabels.Pop());
527 internal void Leave() {
528 ilGen.Emit(OpCodes.Leave, (Label)leaveLabels.Peek());
531 #if NotUsed
532 internal void VerifyParameterCount(MethodInfo methodInfo, int expectedCount)
534 if (methodInfo.GetParameters().Length != expectedCount)
535 throw Utility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ParameterCountMismatch, methodInfo.Name, methodInfo.GetParameters().Length, expectedCount)));
538 internal void Call(object thisObj, MethodInfo methodInfo)
540 VerifyParameterCount(methodInfo, 0);
541 LoadThis(thisObj, methodInfo);
542 Call(methodInfo);
545 internal void Call(object thisObj, MethodInfo methodInfo, object param1)
547 VerifyParameterCount(methodInfo, 1);
548 LoadThis(thisObj, methodInfo);
549 LoadParam(param1, 1, methodInfo);
550 Call(methodInfo);
553 internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2)
555 VerifyParameterCount(methodInfo, 2);
556 LoadThis(thisObj, methodInfo);
557 LoadParam(param1, 1, methodInfo);
558 LoadParam(param2, 2, methodInfo);
559 Call(methodInfo);
562 internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3)
564 VerifyParameterCount(methodInfo, 3);
565 LoadThis(thisObj, methodInfo);
566 LoadParam(param1, 1, methodInfo);
567 LoadParam(param2, 2, methodInfo);
568 LoadParam(param3, 3, methodInfo);
569 Call(methodInfo);
572 internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4)
574 VerifyParameterCount(methodInfo, 4);
575 LoadThis(thisObj, methodInfo);
576 LoadParam(param1, 1, methodInfo);
577 LoadParam(param2, 2, methodInfo);
578 LoadParam(param3, 3, methodInfo);
579 LoadParam(param4, 4, methodInfo);
580 Call(methodInfo);
583 internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5)
585 VerifyParameterCount(methodInfo, 5);
586 LoadThis(thisObj, methodInfo);
587 LoadParam(param1, 1, methodInfo);
588 LoadParam(param2, 2, methodInfo);
589 LoadParam(param3, 3, methodInfo);
590 LoadParam(param4, 4, methodInfo);
591 LoadParam(param5, 5, methodInfo);
592 Call(methodInfo);
595 internal void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5, object param6)
597 VerifyParameterCount(methodInfo, 6);
598 LoadThis(thisObj, methodInfo);
599 LoadParam(param1, 1, methodInfo);
600 LoadParam(param2, 2, methodInfo);
601 LoadParam(param3, 3, methodInfo);
602 LoadParam(param4, 4, methodInfo);
603 LoadParam(param5, 5, methodInfo);
604 LoadParam(param6, 6, methodInfo);
605 Call(methodInfo);
607 #endif
609 internal void Call(MethodInfo methodInfo) {
610 Debug.Assert(methodInfo != null);
611 if (methodInfo.IsVirtual && !methodInfo.DeclaringType.IsValueType)
612 ilGen.Emit(OpCodes.Callvirt, methodInfo);
613 else
614 ilGen.Emit(OpCodes.Call, methodInfo);
617 internal void Call(ConstructorInfo ctor) {
618 Debug.Assert(ctor != null);
619 ilGen.Emit(OpCodes.Call, ctor);
622 internal void New(ConstructorInfo constructorInfo) {
623 Debug.Assert(constructorInfo != null);
624 ilGen.Emit(OpCodes.Newobj, constructorInfo);
627 #if NotUsed
628 internal void New(ConstructorInfo constructorInfo, object param1)
630 LoadParam(param1, 1, constructorInfo);
631 New(constructorInfo);
633 #endif
635 internal void InitObj(Type valueType) {
636 ilGen.Emit(OpCodes.Initobj, valueType);
639 internal void NewArray(Type elementType, object len) {
640 Load(len);
641 ilGen.Emit(OpCodes.Newarr, elementType);
644 #if NotUsed
645 internal void IgnoreReturnValue()
647 Pop();
649 #endif
651 internal void LoadArrayElement(object obj, object arrayIndex) {
652 Type objType = GetVariableType(obj).GetElementType();
653 Load(obj);
654 Load(arrayIndex);
655 if (IsStruct(objType)) {
656 Ldelema(objType);
657 Ldobj(objType);
659 else
660 Ldelem(objType);
663 internal void StoreArrayElement(object obj, object arrayIndex, object value) {
664 Type arrayType = GetVariableType(obj);
665 if (arrayType == typeof(Array)) {
666 Load(obj);
667 Call(typeof(Array).GetMethod("SetValue", new Type[] { typeof(object), typeof(int) }));
669 else {
670 Type objType = arrayType.GetElementType();
671 Load(obj);
672 Load(arrayIndex);
673 if (IsStruct(objType))
674 Ldelema(objType);
675 Load(value);
676 ConvertValue(GetVariableType(value), objType);
677 if (IsStruct(objType))
678 Stobj(objType);
679 else
680 Stelem(objType);
684 static bool IsStruct(Type objType) {
685 return objType.IsValueType && !objType.IsPrimitive;
688 internal Type LoadMember(object obj, MemberInfo memberInfo) {
689 if (GetVariableType(obj).IsValueType)
690 LoadAddress(obj);
691 else
692 Load(obj);
693 return LoadMember(memberInfo);
696 private static MethodInfo GetPropertyMethodFromBaseType(PropertyInfo propertyInfo, bool isGetter) {
697 // we only invoke this when the propertyInfo does not have a GET or SET method on it
699 Type currentType = propertyInfo.DeclaringType.BaseType;
700 PropertyInfo currentProperty;
701 string propertyName = propertyInfo.Name;
702 MethodInfo result = null;
704 while (currentType != null) {
705 currentProperty = currentType.GetProperty(propertyName);
707 if (currentProperty != null) {
708 if (isGetter) {
709 result = currentProperty.GetGetMethod(true);
711 else {
712 result = currentProperty.GetSetMethod(true);
715 if (result != null) {
716 // we found the GetMethod/SetMethod on the type closest to the current declaring type
717 break;
721 // keep looking at the base type like compiler does
722 currentType = currentType.BaseType;
725 return result;
728 internal Type LoadMember(MemberInfo memberInfo) {
729 Type memberType = null;
730 if (memberInfo.MemberType == MemberTypes.Field) {
731 FieldInfo fieldInfo = (FieldInfo)memberInfo;
732 memberType = fieldInfo.FieldType;
733 if (fieldInfo.IsStatic) {
734 ilGen.Emit(OpCodes.Ldsfld, fieldInfo);
736 else {
737 ilGen.Emit(OpCodes.Ldfld, fieldInfo);
740 else {
741 System.Diagnostics.Debug.Assert(memberInfo.MemberType == MemberTypes.Property);
742 PropertyInfo property = (PropertyInfo)memberInfo;
743 memberType = property.PropertyType;
744 if (property != null) {
745 MethodInfo getMethod = property.GetGetMethod(true);
747 if (getMethod == null)
749 getMethod = GetPropertyMethodFromBaseType(property, true);
752 System.Diagnostics.Debug.Assert(getMethod != null);
753 Call(getMethod);
757 return memberType;
760 internal Type LoadMemberAddress(MemberInfo memberInfo) {
761 Type memberType = null;
762 if (memberInfo.MemberType == MemberTypes.Field) {
763 FieldInfo fieldInfo = (FieldInfo)memberInfo;
764 memberType = fieldInfo.FieldType;
765 if (fieldInfo.IsStatic) {
766 ilGen.Emit(OpCodes.Ldsflda, fieldInfo);
768 else {
769 ilGen.Emit(OpCodes.Ldflda, fieldInfo);
772 else {
773 System.Diagnostics.Debug.Assert(memberInfo.MemberType == MemberTypes.Property);
774 PropertyInfo property = (PropertyInfo)memberInfo;
775 memberType = property.PropertyType;
776 if (property != null) {
777 MethodInfo getMethod = property.GetGetMethod(true);
779 if (getMethod == null)
781 getMethod = GetPropertyMethodFromBaseType(property, true);
784 System.Diagnostics.Debug.Assert(getMethod != null);
785 Call(getMethod);
787 LocalBuilder tmpLoc = GetTempLocal(memberType);
788 Stloc(tmpLoc);
789 Ldloca(tmpLoc);
793 return memberType;
796 internal void StoreMember(MemberInfo memberInfo) {
797 if (memberInfo.MemberType == MemberTypes.Field) {
798 FieldInfo fieldInfo = (FieldInfo)memberInfo;
799 if (fieldInfo.IsStatic) {
800 ilGen.Emit(OpCodes.Stsfld, fieldInfo);
802 else {
803 ilGen.Emit(OpCodes.Stfld, fieldInfo);
806 else {
807 System.Diagnostics.Debug.Assert(memberInfo.MemberType == MemberTypes.Property);
808 PropertyInfo property = (PropertyInfo)memberInfo;
809 if (property != null) {
810 MethodInfo setMethod = property.GetSetMethod(true);
812 if (setMethod == null)
814 setMethod = GetPropertyMethodFromBaseType(property, false);
817 System.Diagnostics.Debug.Assert(setMethod != null);
818 Call(setMethod);
823 #if NotUsed
824 internal void LoadDefaultValue(Type type)
826 if (type.IsValueType)
828 switch (Type.GetTypeCode(type))
830 case TypeCode.Boolean:
831 Ldc(false);
832 break;
833 case TypeCode.Char:
834 case TypeCode.SByte:
835 case TypeCode.Byte:
836 case TypeCode.Int16:
837 case TypeCode.UInt16:
838 case TypeCode.Int32:
839 case TypeCode.UInt32:
840 Ldc(0);
841 break;
842 case TypeCode.Int64:
843 case TypeCode.UInt64:
844 Ldc(0L);
845 break;
846 case TypeCode.Single:
847 Ldc(0.0F);
848 break;
849 case TypeCode.Double:
850 Ldc(0.0);
851 break;
852 case TypeCode.Decimal:
853 case TypeCode.DateTime:
854 default:
855 LocalBuilder zero = DeclareLocal(type, "zero");
856 LoadAddress(zero);
857 InitObj(type);
858 Load(zero);
859 break;
862 else
863 Load(null);
865 #endif
867 internal void Load(object obj) {
868 if (obj == null)
869 ilGen.Emit(OpCodes.Ldnull);
870 else if (obj is ArgBuilder)
871 Ldarg((ArgBuilder)obj);
872 else if (obj is LocalBuilder)
873 Ldloc((LocalBuilder)obj);
874 else
875 Ldc(obj);
878 #if NotUsed
879 internal void Store(object var)
881 if (var is ArgBuilder)
882 Starg((ArgBuilder)var);
883 else
885 System.Diagnostics.Debug.Assert(var is LocalBuilder);
886 Stloc((LocalBuilder)var);
890 internal void Dec(object var)
892 Load(var);
893 Load(1);
894 Subtract();
895 Store(var);
898 internal void Inc(object var)
900 Load(var);
901 Load(1);
902 Add();
903 Store(var);
905 #endif
907 internal void LoadAddress(object obj) {
908 if (obj is ArgBuilder)
909 LdargAddress((ArgBuilder)obj);
910 else if (obj is LocalBuilder)
911 LdlocAddress((LocalBuilder)obj);
912 else
913 Load(obj);
917 internal void ConvertAddress(Type source, Type target) {
918 InternalConvert(source, target, true);
921 internal void ConvertValue(Type source, Type target) {
922 InternalConvert(source, target, false);
925 internal void Castclass(Type target) {
926 ilGen.Emit(OpCodes.Castclass, target);
929 internal void Box(Type type) {
930 ilGen.Emit(OpCodes.Box, type);
933 internal void Unbox(Type type) {
934 ilGen.Emit(OpCodes.Unbox, type);
937 static OpCode[] LdindOpCodes = new OpCode[] {
938 OpCodes.Nop,//Empty = 0,
939 OpCodes.Nop,//Object = 1,
940 OpCodes.Nop,//DBNull = 2,
941 OpCodes.Ldind_I1,//Boolean = 3,
942 OpCodes.Ldind_I2,//Char = 4,
943 OpCodes.Ldind_I1,//SByte = 5,
944 OpCodes.Ldind_U1,//Byte = 6,
945 OpCodes.Ldind_I2,//Int16 = 7,
946 OpCodes.Ldind_U2,//UInt16 = 8,
947 OpCodes.Ldind_I4,//Int32 = 9,
948 OpCodes.Ldind_U4,//UInt32 = 10,
949 OpCodes.Ldind_I8,//Int64 = 11,
950 OpCodes.Ldind_I8,//UInt64 = 12,
951 OpCodes.Ldind_R4,//Single = 13,
952 OpCodes.Ldind_R8,//Double = 14,
953 OpCodes.Nop,//Decimal = 15,
954 OpCodes.Nop,//DateTime = 16,
955 OpCodes.Nop,//17
956 OpCodes.Ldind_Ref,//String = 18,
960 OpCode GetLdindOpCode(TypeCode typeCode) {
961 return LdindOpCodes[(int)typeCode];
962 //switch (typeCode)
964 //case TypeCode.Boolean:
965 // return OpCodes.Ldind_I1; // TypeCode.Boolean:
966 //case TypeCode.Char:
967 // return OpCodes.Ldind_I2; // TypeCode.Char:
968 //case TypeCode.SByte:
969 // return OpCodes.Ldind_I1; // TypeCode.SByte:
970 //case TypeCode.Byte:
971 // return OpCodes.Ldind_U1; // TypeCode.Byte:
972 //case TypeCode.Int16:
973 // return OpCodes.Ldind_I2; // TypeCode.Int16:
974 //case TypeCode.UInt16:
975 // return OpCodes.Ldind_U2; // TypeCode.UInt16:
976 //case TypeCode.Int32:
977 // return OpCodes.Ldind_I4; // TypeCode.Int32:
978 //case TypeCode.UInt32:
979 // return OpCodes.Ldind_U4; // TypeCode.UInt32:
980 //case TypeCode.Int64:
981 // return OpCodes.Ldind_I8; // TypeCode.Int64:
982 //case TypeCode.UInt64:
983 // return OpCodes.Ldind_I8; // TypeCode.UInt64:
984 //case TypeCode.Single:
985 // return OpCodes.Ldind_R4; // TypeCode.Single:
986 //case TypeCode.Double:
987 // return OpCodes.Ldind_R8; // TypeCode.Double:
988 //case TypeCode.String:
989 // return OpCodes.Ldind_Ref; // TypeCode.String:
990 //default:
991 // return OpCodes.Nop;
996 internal void Ldobj(Type type) {
997 OpCode opCode = GetLdindOpCode(Type.GetTypeCode(type));
998 if (!opCode.Equals(OpCodes.Nop)) {
999 ilGen.Emit(opCode);
1001 else {
1002 ilGen.Emit(OpCodes.Ldobj, type);
1006 internal void Stobj(Type type) {
1007 ilGen.Emit(OpCodes.Stobj, type);
1010 internal void Ceq() {
1011 ilGen.Emit(OpCodes.Ceq);
1014 internal void Clt() {
1015 ilGen.Emit(OpCodes.Clt);
1018 internal void Cne() {
1019 Ceq();
1020 Ldc(0);
1021 Ceq();
1024 #if NotUsed
1025 internal void Bgt(Label label)
1027 ilGen.Emit(OpCodes.Bgt, label);
1029 #endif
1031 internal void Ble(Label label) {
1032 ilGen.Emit(OpCodes.Ble, label);
1035 internal void Throw() {
1036 ilGen.Emit(OpCodes.Throw);
1039 internal void Ldtoken(Type t) {
1040 ilGen.Emit(OpCodes.Ldtoken, t);
1043 internal void Ldc(object o) {
1044 Type valueType = o.GetType();
1045 if (o is Type) {
1046 Ldtoken((Type)o);
1047 Call(typeof(Type).GetMethod("GetTypeFromHandle", BindingFlags.Static | BindingFlags.Public, null, new Type[] { typeof(RuntimeTypeHandle) }, null));
1049 else if (valueType.IsEnum) {
1050 Ldc(((IConvertible)o).ToType(Enum.GetUnderlyingType(valueType), null));
1052 else {
1053 switch (Type.GetTypeCode(valueType)) {
1054 case TypeCode.Boolean:
1055 Ldc((bool)o);
1056 break;
1057 case TypeCode.Char:
1058 Debug.Assert(false, "Char is not a valid schema primitive and should be treated as int in DataContract");
1059 throw new NotSupportedException("Char is not a valid schema primitive and should be treated as int in DataContract");
1060 case TypeCode.SByte:
1061 case TypeCode.Byte:
1062 case TypeCode.Int16:
1063 case TypeCode.UInt16:
1064 Ldc(((IConvertible)o).ToInt32(CultureInfo.InvariantCulture));
1065 break;
1066 case TypeCode.Int32:
1067 Ldc((int)o);
1068 break;
1069 case TypeCode.UInt32:
1070 Ldc((int)(uint)o);
1071 break;
1072 case TypeCode.UInt64:
1073 Ldc((long)(ulong)o);
1074 break;
1075 case TypeCode.Int64:
1076 Ldc((long)o);
1077 break;
1078 case TypeCode.Single:
1079 Ldc((float)o);
1080 break;
1081 case TypeCode.Double:
1082 Ldc((double)o);
1083 break;
1084 case TypeCode.String:
1085 Ldstr((string)o);
1086 break;
1087 case TypeCode.Decimal:
1088 ConstructorInfo Decimal_ctor = typeof(Decimal).GetConstructor(
1089 CodeGenerator.InstanceBindingFlags,
1090 null,
1091 new Type[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Boolean), typeof(Byte) },
1092 null
1094 int[] bits = Decimal.GetBits((decimal)o);
1095 Ldc(bits[0]); // digit
1096 Ldc(bits[1]); // digit
1097 Ldc(bits[2]); // digit
1098 Ldc((bits[3] & 0x80000000) == 0x80000000); // sign
1099 Ldc((Byte)((bits[3] >> 16) & 0xFF)); // decimal location
1100 New(Decimal_ctor);
1101 break;
1102 case TypeCode.DateTime:
1103 ConstructorInfo DateTime_ctor = typeof(DateTime).GetConstructor(
1104 CodeGenerator.InstanceBindingFlags,
1105 null,
1106 new Type[] { typeof(Int64) },
1107 null
1109 Ldc(((DateTime)o).Ticks); // ticks
1110 New(DateTime_ctor);
1111 break;
1112 case TypeCode.Object:
1113 case TypeCode.Empty:
1114 case TypeCode.DBNull:
1115 default:
1116 if (valueType == typeof(TimeSpan) && LocalAppContextSwitches.EnableTimeSpanSerialization)
1118 ConstructorInfo TimeSpan_ctor = typeof(TimeSpan).GetConstructor(
1119 CodeGenerator.InstanceBindingFlags,
1120 null,
1121 new Type[] { typeof(Int64) },
1122 null
1124 Ldc(((TimeSpan)o).Ticks); // ticks
1125 New(TimeSpan_ctor);
1126 break;
1128 else
1130 Debug.Assert(false, "UnknownConstantType");
1131 throw new NotSupportedException("UnknownConstantType"); //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.UnknownConstantType, DataContract.GetClrTypeFullName(valueType))));
1137 internal void Ldc(bool boolVar) {
1138 if (boolVar) {
1139 ilGen.Emit(OpCodes.Ldc_I4_1);
1141 else {
1142 ilGen.Emit(OpCodes.Ldc_I4_0);
1146 internal void Ldc(int intVar) {
1147 switch (intVar) {
1148 case -1:
1149 ilGen.Emit(OpCodes.Ldc_I4_M1);
1150 break;
1151 case 0:
1152 ilGen.Emit(OpCodes.Ldc_I4_0);
1153 break;
1154 case 1:
1155 ilGen.Emit(OpCodes.Ldc_I4_1);
1156 break;
1157 case 2:
1158 ilGen.Emit(OpCodes.Ldc_I4_2);
1159 break;
1160 case 3:
1161 ilGen.Emit(OpCodes.Ldc_I4_3);
1162 break;
1163 case 4:
1164 ilGen.Emit(OpCodes.Ldc_I4_4);
1165 break;
1166 case 5:
1167 ilGen.Emit(OpCodes.Ldc_I4_5);
1168 break;
1169 case 6:
1170 ilGen.Emit(OpCodes.Ldc_I4_6);
1171 break;
1172 case 7:
1173 ilGen.Emit(OpCodes.Ldc_I4_7);
1174 break;
1175 case 8:
1176 ilGen.Emit(OpCodes.Ldc_I4_8);
1177 break;
1178 default:
1179 ilGen.Emit(OpCodes.Ldc_I4, intVar);
1180 break;
1184 internal void Ldc(long l) {
1185 ilGen.Emit(OpCodes.Ldc_I8, l);
1188 internal void Ldc(float f) {
1189 ilGen.Emit(OpCodes.Ldc_R4, f);
1192 internal void Ldc(double d) {
1193 ilGen.Emit(OpCodes.Ldc_R8, d);
1196 internal void Ldstr(string strVar) {
1197 if (strVar == null)
1198 ilGen.Emit(OpCodes.Ldnull);
1199 else
1200 ilGen.Emit(OpCodes.Ldstr, strVar);
1203 internal void LdlocAddress(LocalBuilder localBuilder) {
1204 if (localBuilder.LocalType.IsValueType)
1205 Ldloca(localBuilder);
1206 else
1207 Ldloc(localBuilder);
1210 internal void Ldloc(LocalBuilder localBuilder) {
1211 ilGen.Emit(OpCodes.Ldloc, localBuilder);
1214 internal void Ldloc(string name) {
1215 Debug.Assert(currentScope.ContainsKey(name));
1216 LocalBuilder local = currentScope[name];
1217 Ldloc(local);
1220 internal void Stloc(Type type, string name) {
1221 LocalBuilder local = null;
1222 if (!currentScope.TryGetValue(name, out local)) {
1223 local = DeclareLocal(type, name);
1225 Debug.Assert(local.LocalType == type);
1226 Stloc(local);
1229 internal void Stloc(LocalBuilder local) {
1230 ilGen.Emit(OpCodes.Stloc, local);
1233 internal void Ldloc(Type type, string name) {
1234 Debug.Assert(currentScope.ContainsKey(name));
1235 LocalBuilder local = currentScope[name];
1236 Debug.Assert(local.LocalType == type);
1237 Ldloc(local);
1240 #if NotUsed
1241 internal void Ldloc(int slot)
1243 switch (slot)
1245 case 0:
1246 ilGen.Emit(OpCodes.Ldloc_0);
1247 break;
1248 case 1:
1249 ilGen.Emit(OpCodes.Ldloc_1);
1250 break;
1251 case 2:
1252 ilGen.Emit(OpCodes.Ldloc_2);
1253 break;
1254 case 3:
1255 ilGen.Emit(OpCodes.Ldloc_3);
1256 break;
1257 default:
1258 if (slot <= 255)
1259 ilGen.Emit(OpCodes.Ldloc_S, slot);
1260 else
1261 ilGen.Emit(OpCodes.Ldloc, slot);
1262 break;
1266 internal void Stloc(int slot)
1268 switch (slot)
1270 case 0:
1271 ilGen.Emit(OpCodes.Stloc_0);
1272 break;
1273 case 1:
1274 ilGen.Emit(OpCodes.Stloc_1);
1275 break;
1276 case 2:
1277 ilGen.Emit(OpCodes.Stloc_2);
1278 break;
1279 case 3:
1280 ilGen.Emit(OpCodes.Stloc_3);
1281 break;
1282 default:
1283 if (slot <= 255)
1284 ilGen.Emit(OpCodes.Stloc_S, slot);
1285 else
1286 ilGen.Emit(OpCodes.Stloc, slot);
1287 break;
1291 internal void Ldloca(int slot)
1293 if (slot <= 255)
1294 ilGen.Emit(OpCodes.Ldloca_S, slot);
1295 else
1296 ilGen.Emit(OpCodes.Ldloca, slot);
1298 #endif
1300 internal void Ldloca(LocalBuilder localBuilder) {
1301 ilGen.Emit(OpCodes.Ldloca, localBuilder);
1304 internal void LdargAddress(ArgBuilder argBuilder) {
1305 if (argBuilder.ArgType.IsValueType)
1306 Ldarga(argBuilder);
1307 else
1308 Ldarg(argBuilder);
1311 internal void Ldarg(string arg) {
1312 Ldarg(GetArg(arg));
1315 internal void Ldarg(ArgBuilder arg) {
1316 Ldarg(arg.Index);
1319 internal void Ldarg(int slot) {
1320 switch (slot) {
1321 case 0:
1322 ilGen.Emit(OpCodes.Ldarg_0);
1323 break;
1324 case 1:
1325 ilGen.Emit(OpCodes.Ldarg_1);
1326 break;
1327 case 2:
1328 ilGen.Emit(OpCodes.Ldarg_2);
1329 break;
1330 case 3:
1331 ilGen.Emit(OpCodes.Ldarg_3);
1332 break;
1333 default:
1334 if (slot <= 255)
1335 ilGen.Emit(OpCodes.Ldarg_S, slot);
1336 else
1337 ilGen.Emit(OpCodes.Ldarg, slot);
1338 break;
1342 #if NotUsed
1343 internal void Starg(ArgBuilder arg)
1345 Starg(arg.Index);
1348 internal void Starg(int slot)
1350 if (slot <= 255)
1351 ilGen.Emit(OpCodes.Starg_S, slot);
1352 else
1353 ilGen.Emit(OpCodes.Starg, slot);
1355 #endif
1357 internal void Ldarga(ArgBuilder argBuilder) {
1358 Ldarga(argBuilder.Index);
1361 internal void Ldarga(int slot) {
1362 if (slot <= 255)
1363 ilGen.Emit(OpCodes.Ldarga_S, slot);
1364 else
1365 ilGen.Emit(OpCodes.Ldarga, slot);
1368 internal void Ldlen() {
1369 ilGen.Emit(OpCodes.Ldlen);
1370 ilGen.Emit(OpCodes.Conv_I4);
1373 static OpCode[] LdelemOpCodes = new OpCode[] {
1374 OpCodes.Nop,//Empty = 0,
1375 OpCodes.Ldelem_Ref,//Object = 1,
1376 OpCodes.Ldelem_Ref,//DBNull = 2,
1377 OpCodes.Ldelem_I1,//Boolean = 3,
1378 OpCodes.Ldelem_I2,//Char = 4,
1379 OpCodes.Ldelem_I1,//SByte = 5,
1380 OpCodes.Ldelem_U1,//Byte = 6,
1381 OpCodes.Ldelem_I2,//Int16 = 7,
1382 OpCodes.Ldelem_U2,//UInt16 = 8,
1383 OpCodes.Ldelem_I4,//Int32 = 9,
1384 OpCodes.Ldelem_U4,//UInt32 = 10,
1385 OpCodes.Ldelem_I8,//Int64 = 11,
1386 OpCodes.Ldelem_I8,//UInt64 = 12,
1387 OpCodes.Ldelem_R4,//Single = 13,
1388 OpCodes.Ldelem_R8,//Double = 14,
1389 OpCodes.Nop,//Decimal = 15,
1390 OpCodes.Nop,//DateTime = 16,
1391 OpCodes.Nop,//17
1392 OpCodes.Ldelem_Ref,//String = 18,
1395 OpCode GetLdelemOpCode(TypeCode typeCode) {
1396 return LdelemOpCodes[(int)typeCode];
1397 //switch (typeCode)
1399 //case TypeCode.Object:
1400 //case TypeCode.DBNull:
1401 // return OpCodes.Ldelem_Ref;// TypeCode.Object:
1402 //case TypeCode.Boolean:
1403 // return OpCodes.Ldelem_I1;// TypeCode.Boolean:
1404 //case TypeCode.Char:
1405 // return OpCodes.Ldelem_I2;// TypeCode.Char:
1406 //case TypeCode.SByte:
1407 // return OpCodes.Ldelem_I1;// TypeCode.SByte:
1408 //case TypeCode.Byte:
1409 // return OpCodes.Ldelem_U1;// TypeCode.Byte:
1410 //case TypeCode.Int16:
1411 // return OpCodes.Ldelem_I2;// TypeCode.Int16:
1412 //case TypeCode.UInt16:
1413 // return OpCodes.Ldelem_U2;// TypeCode.UInt16:
1414 //case TypeCode.Int32:
1415 // return OpCodes.Ldelem_I4;// TypeCode.Int32:
1416 //case TypeCode.UInt32:
1417 // return OpCodes.Ldelem_U4;// TypeCode.UInt32:
1418 //case TypeCode.Int64:
1419 // return OpCodes.Ldelem_I8;// TypeCode.Int64:
1420 //case TypeCode.UInt64:
1421 // return OpCodes.Ldelem_I8;// TypeCode.UInt64:
1422 //case TypeCode.Single:
1423 // return OpCodes.Ldelem_R4;// TypeCode.Single:
1424 //case TypeCode.Double:
1425 // return OpCodes.Ldelem_R8;// TypeCode.Double:
1426 //case TypeCode.String:
1427 // return OpCodes.Ldelem_Ref;// TypeCode.String:
1428 //default:
1429 // return OpCodes.Nop;
1433 internal void Ldelem(Type arrayElementType) {
1434 if (arrayElementType.IsEnum) {
1435 Ldelem(Enum.GetUnderlyingType(arrayElementType));
1437 else {
1438 OpCode opCode = GetLdelemOpCode(Type.GetTypeCode(arrayElementType));
1439 Debug.Assert(!opCode.Equals(OpCodes.Nop));
1440 if (opCode.Equals(OpCodes.Nop))
1441 throw new InvalidOperationException("ArrayTypeIsNotSupported"); //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
1442 ilGen.Emit(opCode);
1445 internal void Ldelema(Type arrayElementType) {
1446 OpCode opCode = OpCodes.Ldelema;
1447 ilGen.Emit(opCode, arrayElementType);
1450 static OpCode[] StelemOpCodes = new OpCode[] {
1451 OpCodes.Nop,//Empty = 0,
1452 OpCodes.Stelem_Ref,//Object = 1,
1453 OpCodes.Stelem_Ref,//DBNull = 2,
1454 OpCodes.Stelem_I1,//Boolean = 3,
1455 OpCodes.Stelem_I2,//Char = 4,
1456 OpCodes.Stelem_I1,//SByte = 5,
1457 OpCodes.Stelem_I1,//Byte = 6,
1458 OpCodes.Stelem_I2,//Int16 = 7,
1459 OpCodes.Stelem_I2,//UInt16 = 8,
1460 OpCodes.Stelem_I4,//Int32 = 9,
1461 OpCodes.Stelem_I4,//UInt32 = 10,
1462 OpCodes.Stelem_I8,//Int64 = 11,
1463 OpCodes.Stelem_I8,//UInt64 = 12,
1464 OpCodes.Stelem_R4,//Single = 13,
1465 OpCodes.Stelem_R8,//Double = 14,
1466 OpCodes.Nop,//Decimal = 15,
1467 OpCodes.Nop,//DateTime = 16,
1468 OpCodes.Nop,//17
1469 OpCodes.Stelem_Ref,//String = 18,
1472 OpCode GetStelemOpCode(TypeCode typeCode) {
1473 return StelemOpCodes[(int)typeCode];
1474 //switch (typeCode)
1476 //case TypeCode.Object:
1477 //case TypeCode.DBNull:
1478 // return OpCodes.Stelem_Ref;// TypeCode.Object:
1479 //case TypeCode.Boolean:
1480 // return OpCodes.Stelem_I1;// TypeCode.Boolean:
1481 //case TypeCode.Char:
1482 // return OpCodes.Stelem_I2;// TypeCode.Char:
1483 //case TypeCode.SByte:
1484 // return OpCodes.Stelem_I1;// TypeCode.SByte:
1485 //case TypeCode.Byte:
1486 // return OpCodes.Stelem_I1;// TypeCode.Byte:
1487 //case TypeCode.Int16:
1488 // return OpCodes.Stelem_I2;// TypeCode.Int16:
1489 //case TypeCode.UInt16:
1490 // return OpCodes.Stelem_I2;// TypeCode.UInt16:
1491 //case TypeCode.Int32:
1492 // return OpCodes.Stelem_I4;// TypeCode.Int32:
1493 //case TypeCode.UInt32:
1494 // return OpCodes.Stelem_I4;// TypeCode.UInt32:
1495 //case TypeCode.Int64:
1496 // return OpCodes.Stelem_I8;// TypeCode.Int64:
1497 //case TypeCode.UInt64:
1498 // return OpCodes.Stelem_I8;// TypeCode.UInt64:
1499 //case TypeCode.Single:
1500 // return OpCodes.Stelem_R4;// TypeCode.Single:
1501 //case TypeCode.Double:
1502 // return OpCodes.Stelem_R8;// TypeCode.Double:
1503 //case TypeCode.String:
1504 // return OpCodes.Stelem_Ref;// TypeCode.String:
1505 //default:
1506 // return OpCodes.Nop;
1510 internal void Stelem(Type arrayElementType) {
1511 if (arrayElementType.IsEnum)
1512 Stelem(Enum.GetUnderlyingType(arrayElementType));
1513 else {
1514 OpCode opCode = GetStelemOpCode(Type.GetTypeCode(arrayElementType));
1515 if (opCode.Equals(OpCodes.Nop))
1516 throw new InvalidOperationException("ArrayTypeIsNotSupported"); //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.ArrayTypeIsNotSupported, DataContract.GetClrTypeFullName(arrayElementType))));
1517 ilGen.Emit(opCode);
1521 internal Label DefineLabel() {
1522 return ilGen.DefineLabel();
1525 internal void MarkLabel(Label label) {
1526 ilGen.MarkLabel(label);
1529 internal void Nop() {
1530 ilGen.Emit(OpCodes.Nop);
1533 internal void Add() {
1534 ilGen.Emit(OpCodes.Add);
1537 #if NotUsed
1538 internal void Subtract()
1540 ilGen.Emit(OpCodes.Sub);
1543 internal void And()
1545 ilGen.Emit(OpCodes.And);
1547 internal void Or()
1549 ilGen.Emit(OpCodes.Or);
1552 internal void Not()
1554 ilGen.Emit(OpCodes.Not);
1556 #endif
1558 internal void Ret() {
1559 ilGen.Emit(OpCodes.Ret);
1562 internal void Br(Label label) {
1563 ilGen.Emit(OpCodes.Br, label);
1566 internal void Br_S(Label label) {
1567 ilGen.Emit(OpCodes.Br_S, label);
1570 internal void Blt(Label label) {
1571 ilGen.Emit(OpCodes.Blt, label);
1574 internal void Brfalse(Label label) {
1575 ilGen.Emit(OpCodes.Brfalse, label);
1578 internal void Brtrue(Label label) {
1579 ilGen.Emit(OpCodes.Brtrue, label);
1582 internal void Pop() {
1583 ilGen.Emit(OpCodes.Pop);
1586 internal void Dup() {
1587 ilGen.Emit(OpCodes.Dup);
1590 #if !SILVERLIGHT // Not in SL
1591 internal void Ldftn(MethodInfo methodInfo) {
1592 ilGen.Emit(OpCodes.Ldftn, methodInfo);
1594 #endif
1596 #if NotUsed
1597 void LoadThis(object thisObj, MethodInfo methodInfo)
1599 if (thisObj != null && !methodInfo.IsStatic)
1601 LoadAddress(thisObj);
1602 ConvertAddress(GetVariableType(thisObj), methodInfo.DeclaringType);
1606 void LoadParam(object arg, int oneBasedArgIndex, MethodBase methodInfo)
1608 Load(arg);
1609 if (arg != null)
1610 ConvertValue(GetVariableType(arg), methodInfo.GetParameters()[oneBasedArgIndex - 1].ParameterType);
1612 #endif
1614 void InternalIf(bool negate) {
1615 IfState ifState = new IfState();
1616 ifState.EndIf = DefineLabel();
1617 ifState.ElseBegin = DefineLabel();
1618 if (negate)
1619 Brtrue(ifState.ElseBegin);
1620 else
1621 Brfalse(ifState.ElseBegin);
1622 blockStack.Push(ifState);
1625 static OpCode[] ConvOpCodes = new OpCode[] {
1626 OpCodes.Nop,//Empty = 0,
1627 OpCodes.Nop,//Object = 1,
1628 OpCodes.Nop,//DBNull = 2,
1629 OpCodes.Conv_I1,//Boolean = 3,
1630 OpCodes.Conv_I2,//Char = 4,
1631 OpCodes.Conv_I1,//SByte = 5,
1632 OpCodes.Conv_U1,//Byte = 6,
1633 OpCodes.Conv_I2,//Int16 = 7,
1634 OpCodes.Conv_U2,//UInt16 = 8,
1635 OpCodes.Conv_I4,//Int32 = 9,
1636 OpCodes.Conv_U4,//UInt32 = 10,
1637 OpCodes.Conv_I8,//Int64 = 11,
1638 OpCodes.Conv_U8,//UInt64 = 12,
1639 OpCodes.Conv_R4,//Single = 13,
1640 OpCodes.Conv_R8,//Double = 14,
1641 OpCodes.Nop,//Decimal = 15,
1642 OpCodes.Nop,//DateTime = 16,
1643 OpCodes.Nop,//17
1644 OpCodes.Nop,//String = 18,
1647 OpCode GetConvOpCode(TypeCode typeCode) {
1648 return ConvOpCodes[(int)typeCode];
1649 //switch (typeCode)
1651 //case TypeCode.Boolean:
1652 // return OpCodes.Conv_I1;// TypeCode.Boolean:
1653 //case TypeCode.Char:
1654 // return OpCodes.Conv_I2;// TypeCode.Char:
1655 //case TypeCode.SByte:
1656 // return OpCodes.Conv_I1;// TypeCode.SByte:
1657 //case TypeCode.Byte:
1658 // return OpCodes.Conv_U1;// TypeCode.Byte:
1659 //case TypeCode.Int16:
1660 // return OpCodes.Conv_I2;// TypeCode.Int16:
1661 //case TypeCode.UInt16:
1662 // return OpCodes.Conv_U2;// TypeCode.UInt16:
1663 //case TypeCode.Int32:
1664 // return OpCodes.Conv_I4;// TypeCode.Int32:
1665 //case TypeCode.UInt32:
1666 // return OpCodes.Conv_U4;// TypeCode.UInt32:
1667 //case TypeCode.Int64:
1668 // return OpCodes.Conv_I8;// TypeCode.Int64:
1669 //case TypeCode.UInt64:
1670 // return OpCodes.Conv_U8;// TypeCode.UInt64:
1671 //case TypeCode.Single:
1672 // return OpCodes.Conv_R4;// TypeCode.Single:
1673 //case TypeCode.Double:
1674 // return OpCodes.Conv_R8;// TypeCode.Double:
1675 //default:
1676 // return OpCodes.Nop;
1680 void InternalConvert(Type source, Type target, bool isAddress) {
1681 if (target == source)
1682 return;
1683 if (target.IsValueType) {
1684 if (source.IsValueType) {
1685 OpCode opCode = GetConvOpCode(Type.GetTypeCode(target));
1686 if (opCode.Equals(OpCodes.Nop)) {
1687 //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.NoConversionPossibleTo, DataContract.GetClrTypeFullName(target))));
1688 throw new CodeGeneratorConversionException(source, target, isAddress,"NoConversionPossibleTo");
1690 else {
1691 ilGen.Emit(opCode);
1694 else if (source.IsAssignableFrom(target)) {
1695 Unbox(target);
1696 if (!isAddress)
1697 Ldobj(target);
1699 else {
1700 //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
1701 throw new CodeGeneratorConversionException(source, target, isAddress, "IsNotAssignableFrom");
1704 else if (target.IsAssignableFrom(source)) {
1705 if (source.IsValueType) {
1706 if (isAddress)
1707 Ldobj(source);
1708 Box(source);
1711 else if (source.IsAssignableFrom(target)) {
1712 //assert(source.IsValueType == false);
1713 Castclass(target);
1715 else if (target.IsInterface || source.IsInterface) {
1716 Castclass(target);
1718 else {
1719 //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.IsNotAssignableFrom, DataContract.GetClrTypeFullName(target), DataContract.GetClrTypeFullName(source))));
1720 throw new CodeGeneratorConversionException(source, target, isAddress, "IsNotAssignableFrom");
1724 IfState PopIfState() {
1725 object stackTop = blockStack.Pop();
1726 IfState ifState = stackTop as IfState;
1727 Debug.Assert(ifState != null);
1728 return ifState;
1731 static internal AssemblyBuilder CreateAssemblyBuilder(AppDomain appDomain, string name) {
1732 AssemblyName assemblyName = new AssemblyName();
1733 assemblyName.Name = name;
1734 assemblyName.Version = new Version(1, 0, 0, 0);
1735 if (DiagnosticsSwitches.KeepTempFiles.Enabled)
1736 return appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave, TempFilesLocation);
1737 else
1738 return appDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
1741 static string tempFilesLocation = null;
1742 internal static string TempFilesLocation {
1743 get {
1744 if (tempFilesLocation == null) {
1745 #if CONFIGURATION_DEP
1746 // Return different XmlSerializerSection from legacy assembly due to its register config handlers
1747 object section = ConfigurationManager.GetSection(ConfigurationStrings.XmlSerializerSectionPath);
1748 string location = null;
1749 if (section != null) {
1750 XmlSerializerSection configSection = section as XmlSerializerSection;
1751 if (configSection != null) {
1752 location = configSection.TempFilesLocation;
1755 #else
1756 string location = null;
1757 #endif
1758 if (location != null) {
1759 tempFilesLocation = location.Trim();
1761 else {
1762 tempFilesLocation = Path.GetTempPath();
1765 return tempFilesLocation;
1767 set {
1768 tempFilesLocation = value;
1772 static internal ModuleBuilder CreateModuleBuilder(AssemblyBuilder assemblyBuilder, string name) {
1773 if (DiagnosticsSwitches.KeepTempFiles.Enabled)
1774 return assemblyBuilder.DefineDynamicModule(name, name + ".dll", true);
1775 else
1776 return assemblyBuilder.DefineDynamicModule(name);
1778 static internal TypeBuilder CreateTypeBuilder(ModuleBuilder moduleBuilder, string name, TypeAttributes attributes, Type parent, Type[] interfaces) {
1779 // parent is nullable if no base class
1780 return moduleBuilder.DefineType(TempAssembly.GeneratedAssemblyNamespace + "." + name,
1781 attributes, parent, interfaces);
1784 #if NotUsed
1785 internal void EmitSourceInstruction(string line)
1787 EmitSourceLine(" " + line);
1790 internal void EmitSourceLabel(string line)
1792 EmitSourceLine(line);
1795 internal void EmitSourceComment(string comment)
1797 EmitSourceInstruction("// " + comment);
1800 internal void EmitSourceLine(string line)
1802 if (codeGenTrace != CodeGenTrace.None)
1803 Console.WriteLine(String.Format("{0:X4}: {1}", lineNo++, line));
1804 SerializationTrace.WriteInstruction(lineNo++, line);
1805 if (ilGen != null && codeGenTrace == CodeGenTrace.Tron)
1807 ilGen.Emit(OpCodes.Ldstr, string.Format(CultureInfo.InvariantCulture, "{0:00000}: {1}", lineNo-1, line));
1808 ilGen.Emit(OpCodes.Call, XmlFormatGeneratorStatics.TraceInstructionMethod);
1812 internal void EmitStackTop(Type stackTopType)
1814 if (codeGenTrace != CodeGenTrace.Tron)
1815 return;
1816 codeGenTrace = CodeGenTrace.None;
1817 Dup();
1818 ToString(stackTopType);
1819 LocalBuilder topValue = DeclareLocal(Globals.TypeOfString, "topValue");
1820 Store(topValue);
1821 Load("//value = ");
1822 Load(topValue);
1823 Concat2();
1824 Call(XmlFormatGeneratorStatics.TraceInstructionMethod);
1825 codeGenTrace = CodeGenTrace.Tron;
1828 internal void ToString(Type type)
1830 if (type.IsValueType)
1832 Box(type);
1833 Call(ObjectToString);
1835 else
1837 Dup();
1838 Load(null);
1839 If(Cmp.EqualTo);
1840 Pop();
1841 Load("<null>");
1842 Else();
1843 if (type.IsArray)
1845 LocalBuilder arrayVar = DeclareLocal(type, "arrayVar");
1846 Store(arrayVar);
1847 Load("{ ");
1848 LocalBuilder arrayValueString = DeclareLocal(typeof(string), "arrayValueString");
1849 Store(arrayValueString);
1850 LocalBuilder i = DeclareLocal(typeof(int), "i");
1851 For(i, 0, arrayVar);
1852 Load(arrayValueString);
1853 LoadArrayElement(arrayVar, i);
1854 ToString(arrayVar.LocalType.GetElementType());
1855 Load(", ");
1856 Concat3();
1857 Store(arrayValueString);
1858 EndFor();
1859 Load(arrayValueString);
1860 Load("}");
1861 Concat2();
1863 else
1864 Call(ObjectToString);
1865 EndIf();
1869 internal void Concat2()
1871 Call(StringConcat2);
1874 internal void Concat3()
1876 Call(StringConcat3);
1879 internal Label[] Switch(int labelCount)
1881 SwitchState switchState = new SwitchState(DefineLabel(), DefineLabel());
1882 Label[] caseLabels = new Label[labelCount];
1883 for (int i = 0; i < caseLabels.Length; i++)
1884 caseLabels[i] = DefineLabel();
1886 if (codeGenTrace != CodeGenTrace.None)
1888 EmitSourceInstruction("switch (");
1889 foreach (Label l in caseLabels)
1890 EmitSourceInstruction(" " + l.GetHashCode());
1891 EmitSourceInstruction(") {");
1893 ilGen.Emit(OpCodes.Switch, caseLabels);
1894 Br(switchState.DefaultLabel);
1895 blockStack.Push(switchState);
1896 return caseLabels;
1898 internal void Case(Label caseLabel1, string caseLabelName)
1900 if (codeGenTrace != CodeGenTrace.None)
1901 EmitSourceInstruction("case " + caseLabelName + "{");
1902 MarkLabel(caseLabel1);
1905 internal void EndCase()
1907 object stackTop = blockStack.Peek();
1908 SwitchState switchState = stackTop as SwitchState;
1909 if (switchState == null)
1910 ThrowMismatchException(stackTop);
1911 Br(switchState.EndOfSwitchLabel);
1912 if (codeGenTrace != CodeGenTrace.None)
1913 EmitSourceInstruction("} //end case ");
1916 internal void DefaultCase()
1918 object stackTop = blockStack.Peek();
1919 SwitchState switchState = stackTop as SwitchState;
1920 if (switchState == null)
1921 ThrowMismatchException(stackTop);
1922 MarkLabel(switchState.DefaultLabel);
1923 switchState.DefaultDefined = true;
1926 internal void EndSwitch()
1928 object stackTop = blockStack.Pop();
1929 SwitchState switchState = stackTop as SwitchState;
1930 if (switchState == null)
1931 ThrowMismatchException(stackTop);
1932 if (codeGenTrace != CodeGenTrace.None)
1933 EmitSourceInstruction("} //end switch");
1934 if (!switchState.DefaultDefined)
1935 MarkLabel(switchState.DefaultLabel);
1936 MarkLabel(switchState.EndOfSwitchLabel);
1939 internal void CallStringFormat(string msg, params object[] values)
1941 NewArray(typeof(object), values.Length);
1942 if (stringFormatArray == null)
1943 stringFormatArray = DeclareLocal(typeof(object[]), "stringFormatArray");
1944 Stloc(stringFormatArray);
1945 for (int i = 0; i < values.Length; i++)
1946 StoreArrayElement(stringFormatArray, i, values[i]);
1948 Load(msg);
1949 Load(stringFormatArray);
1950 Call(StringFormat);
1953 static MethodInfo stringEquals = typeof(string).GetMethod("Equals", new Type[]{ typeof(string), typeof(string)});
1954 static MethodInfo stringCompare = typeof(string).GetMethod("Compare", new Type[]{ typeof(string), typeof(string)});
1955 static ConstructorInfo permissionSetCtor = typeof(PermissionSet).GetConstructor(new Type[]{ typeof(PermissionState)});
1956 static MethodInfo permissionSetDemand = typeof(PermissionSet).GetMethod("Demand", new Type[0]);
1957 #endif
1959 int initElseIfStack = -1;
1960 IfState elseIfState;
1961 internal void InitElseIf() {
1962 Debug.Assert(initElseIfStack == -1);
1963 elseIfState = (IfState)blockStack.Pop();
1964 initElseIfStack = blockStack.Count;
1965 Br(elseIfState.EndIf);
1966 MarkLabel(elseIfState.ElseBegin);
1969 int initIfStack = -1;
1970 internal void InitIf() {
1971 Debug.Assert(initIfStack == -1);
1972 initIfStack = blockStack.Count;
1975 internal void AndIf(Cmp cmpOp) {
1976 if (initIfStack == blockStack.Count) {
1977 initIfStack = -1;
1978 If(cmpOp);
1979 return;
1981 if (initElseIfStack == blockStack.Count) {
1982 initElseIfStack = -1;
1983 elseIfState.ElseBegin = DefineLabel();
1984 ilGen.Emit(GetBranchCode(cmpOp), elseIfState.ElseBegin);
1985 blockStack.Push(elseIfState);
1986 return;
1988 Debug.Assert(initIfStack == -1 && initElseIfStack == -1);
1989 IfState ifState = (IfState)blockStack.Peek();
1990 ilGen.Emit(GetBranchCode(cmpOp), ifState.ElseBegin);
1993 internal void AndIf() {
1994 if (initIfStack == blockStack.Count) {
1995 initIfStack = -1;
1996 If();
1997 return;
1999 if (initElseIfStack == blockStack.Count) {
2000 initElseIfStack = -1;
2001 elseIfState.ElseBegin = DefineLabel();
2002 Brfalse(elseIfState.ElseBegin);
2003 blockStack.Push(elseIfState);
2004 return;
2006 Debug.Assert(initIfStack == -1 && initElseIfStack == -1);
2007 IfState ifState = (IfState)blockStack.Peek();
2008 Brfalse(ifState.ElseBegin);
2011 #if NotUsed
2012 internal void ElseIf(object boolVal)
2014 InternalElseIf(boolVal, false);
2016 void InternalElseIf(object boolVal, bool negate)
2018 IfState ifState = (IfState)blockStack.Pop();
2019 Br(ifState.EndIf);
2020 MarkLabel(ifState.ElseBegin);
2022 Load(boolVal);
2023 ifState.ElseBegin = DefineLabel();
2024 if (negate)
2025 Brtrue(ifState.ElseBegin);
2026 else
2027 Brfalse(ifState.ElseBegin);
2028 blockStack.Push(ifState);
2031 internal void IfString(object s1, Cmp cmpOp, object s2)
2033 Load(s1);
2034 Load(s2);
2035 Call(stringCompare);
2036 Load(0);
2037 If(cmpOp);
2040 internal void ElseIfString(object s1, Cmp cmpOp, object s2)
2042 IfState ifState = (IfState)blockStack.Pop();
2043 Br(ifState.EndIf);
2044 MarkLabel(ifState.ElseBegin);
2046 Load(s1);
2047 Load(s2);
2048 Call(stringCompare);
2049 Load(0);
2050 ifState.ElseBegin = DefineLabel();
2052 if (codeGenTrace != CodeGenTrace.None)
2053 EmitSourceInstruction("Branch if " + CmpInverse[(int) cmpOp].ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString(NumberFormatInfo.InvariantInfo));
2055 ilGen.Emit(BranchCode[(int)cmpOp], ifState.ElseBegin);
2056 blockStack.Push(ifState);
2059 internal void While(object value1, Cmp cmpOp, object value2)
2061 IfState ifState = new IfState();
2062 ifState.EndIf = DefineLabel();
2063 ifState.ElseBegin = DefineLabel();
2064 ilGen.MarkLabel(ifState.ElseBegin);
2065 Load(value1);
2066 Load(value2);
2067 if (codeGenTrace != CodeGenTrace.None)
2068 EmitSourceInstruction("Branch if " + CmpInverse[(int) cmpOp].ToString() + " to " + ifState.ElseBegin.GetHashCode().ToString());
2069 ilGen.Emit(BranchCode[(int)cmpOp], ifState.EndIf);
2070 blockStack.Push(ifState);
2073 internal void EndWhile()
2075 IfState ifState = PopIfState();
2076 Br(ifState.ElseBegin);
2077 MarkLabel(ifState.EndIf);
2080 internal void ElseIfNot(object boolVal)
2082 InternalElseIf(boolVal, true);
2085 internal void Ldc(long l)
2087 if (codeGenTrace != CodeGenTrace.None)
2088 EmitSourceInstruction("Ldc.i8 " + l);
2089 ilGen.Emit(OpCodes.Ldc_I8, l);
2092 internal void Ldc(float f)
2094 if (codeGenTrace != CodeGenTrace.None)
2095 EmitSourceInstruction("Ldc.r4 " + f);
2096 ilGen.Emit(OpCodes.Ldc_R4, f);
2099 internal void Ldc(double d)
2101 if (codeGenTrace != CodeGenTrace.None)
2102 EmitSourceInstruction("Ldc.r8 " + d);
2103 ilGen.Emit(OpCodes.Ldc_R8, d);
2105 #endif
2107 internal void IsInst(Type type) {
2108 ilGen.Emit(OpCodes.Isinst, type);
2111 #if NotUsed
2112 internal void Clt()
2114 if (codeGenTrace != CodeGenTrace.None)
2115 EmitSourceInstruction("Clt");
2116 ilGen.Emit(OpCodes.Clt);
2119 internal void StringEquals()
2121 Call(stringEquals);
2124 internal void StringEquals(object s1, object s2)
2126 Load(s1);
2127 ConvertValue(GetVariableType(s1), typeof(string));
2128 Load(s2);
2129 ConvertValue(GetVariableType(s2), typeof(string));
2130 StringEquals();
2133 internal void Bge(Label label)
2135 if (codeGenTrace != CodeGenTrace.None)
2136 EmitSourceInstruction("Bge " + label.GetHashCode());
2137 ilGen.Emit(OpCodes.Bge, label);
2139 #endif
2141 internal void Beq(Label label) {
2142 ilGen.Emit(OpCodes.Beq, label);
2145 internal void Bne(Label label) {
2146 ilGen.Emit(OpCodes.Bne_Un, label);
2149 #if NotUsed
2150 internal void ResizeArray(object arrayVar, object sizeVar)
2152 if (codeGenTrace != CodeGenTrace.None)
2153 EmitSourceComment("ResizeArray() {");
2155 Label doResize = DefineLabel();
2156 Load(arrayVar);
2157 Load(null);
2158 Beq(doResize);
2159 Ldlen(arrayVar);
2160 Load(sizeVar);
2161 If(Cmp.NotEqualTo);
2162 MarkLabel(doResize);
2163 Type arrayType = GetVariableType(arrayVar);
2164 Type elementType = arrayType.GetElementType();
2165 LocalBuilder tempArray = DeclareLocal(arrayType, "tempArray");
2166 NewArray(elementType, sizeVar);
2167 Store(tempArray);
2168 CopyArray(arrayVar, tempArray, sizeVar);
2169 Load(tempArray);
2170 Store(arrayVar);
2171 EndIf();
2173 if (codeGenTrace != CodeGenTrace.None)
2174 EmitSourceComment("} // ResizeArray");
2177 LocalBuilder resizeLen, resizeCounter;
2178 internal void EnsureArrayCapacity(object arrayVar, object lastElementVar)
2180 if (codeGenTrace != CodeGenTrace.None)
2181 EmitSourceComment("EnsureArrayCapacity() {");
2183 Type arrayType = GetVariableType(arrayVar);
2184 Type elementType = arrayType.GetElementType();
2185 If(arrayVar, Cmp.EqualTo, null);
2186 NewArray(elementType, 4);
2187 Store(arrayVar);
2188 Else();
2189 Load(lastElementVar);
2190 Ldlen(arrayVar);
2191 If(Cmp.GreaterThanOrEqualTo);
2192 LocalBuilder tempArray = DeclareLocal(arrayType, "tempArray");
2193 if (resizeLen == null)
2194 resizeLen = DeclareLocal(typeof(int), "resizeLen");
2195 Load(lastElementVar);
2196 Load(2);
2197 Mul();
2198 Store(resizeLen);
2199 NewArray(elementType, resizeLen);
2200 Store(tempArray);
2201 CopyArray(arrayVar, tempArray, arrayVar);
2202 Load(tempArray);
2203 Store(arrayVar);
2204 EndIf();
2205 EndIf();
2207 if (codeGenTrace != CodeGenTrace.None)
2208 EmitSourceComment("} // EnsureArrayCapacity");
2211 internal void CopyArray(object sourceArray, object destArray, object length)
2213 If(sourceArray, Cmp.NotEqualTo, null);
2214 if (resizeCounter == null)
2215 resizeCounter = DeclareLocal(typeof(int), "resizeCounter");
2216 For(resizeCounter, 0, length);
2217 Load(destArray);
2218 Load(resizeCounter);
2219 LoadArrayElement(sourceArray, resizeCounter);
2220 Stelem(GetVariableType(destArray).GetElementType());
2221 EndFor();
2222 EndIf();
2224 #endif
2226 internal void GotoMethodEnd() {
2227 //limit to only short forward (127 CIL instruction)
2228 //Br_S(this.methodEndLabel);
2229 Br(this.methodEndLabel);
2232 internal class WhileState {
2233 public Label StartLabel;
2234 public Label CondLabel;
2235 public Label EndLabel;
2236 public WhileState(CodeGenerator ilg) {
2237 StartLabel = ilg.DefineLabel();
2238 CondLabel = ilg.DefineLabel();
2239 EndLabel = ilg.DefineLabel();
2243 // Usage:
2244 // WhileBegin()
2245 // WhileBreak()
2246 // WhileContinue()
2247 // WhileBeginCondition()
2248 // (bool on stack)
2249 // WhileEndCondition()
2250 // WhileEnd()
2251 Stack whileStack;
2252 internal void WhileBegin() {
2253 WhileState whileState = new WhileState(this);
2254 Br(whileState.CondLabel);
2255 MarkLabel(whileState.StartLabel);
2256 whileStack.Push(whileState);
2259 internal void WhileEnd() {
2260 WhileState whileState = (WhileState)whileStack.Pop();
2261 MarkLabel(whileState.EndLabel);
2264 internal void WhileBreak() {
2265 WhileState whileState = (WhileState)whileStack.Peek();
2266 Br(whileState.EndLabel);
2269 internal void WhileContinue() {
2270 WhileState whileState = (WhileState)whileStack.Peek();
2271 Br(whileState.CondLabel);
2274 internal void WhileBeginCondition() {
2275 WhileState whileState = (WhileState)whileStack.Peek();
2276 // If there are two MarkLabel ILs consecutively, Labels will converge to one label.
2277 // This could cause the code to look different. We insert Nop here specifically
2278 // that the While label stands out.
2279 Nop();
2280 MarkLabel(whileState.CondLabel);
2283 internal void WhileEndCondition() {
2284 WhileState whileState = (WhileState)whileStack.Peek();
2285 Brtrue(whileState.StartLabel);
2288 #if NotUsed
2289 internal void AndWhile(Cmp cmpOp)
2291 object startWhile = blockStack.Pop();
2292 AndIf(cmpOp);
2293 blockStack.Push(startWhile);
2296 internal void BeginWhileBody()
2298 Label startWhile = (Label) blockStack.Pop();
2299 If();
2300 blockStack.Push(startWhile);
2303 internal void BeginWhileBody(Cmp cmpOp)
2305 Label startWhile = (Label) blockStack.Pop();
2306 If(cmpOp);
2307 blockStack.Push(startWhile);
2310 internal Label BeginWhileCondition()
2312 Label startWhile = DefineLabel();
2313 MarkLabel(startWhile);
2314 blockStack.Push(startWhile);
2315 return startWhile;
2318 internal void Cne()
2320 Ceq();
2321 Load(0);
2322 Ceq();
2325 internal void New(ConstructorInfo constructorInfo, object param1, object param2)
2327 LoadParam(param1, 1, constructorInfo);
2328 LoadParam(param2, 2, constructorInfo);
2329 New(constructorInfo);
2332 //This code is not tested
2333 internal void Stind(Type type)
2335 OpCode opCode = StindOpCodes[(int) Type.GetTypeCode(type)];
2336 if (!opCode.Equals(OpCodes.Nop))
2338 if (codeGenTrace != CodeGenTrace.None)
2339 EmitSourceInstruction(opCode.ToString());
2340 ilGen.Emit(opCode);
2342 else
2344 if (codeGenTrace != CodeGenTrace.None)
2345 EmitSourceInstruction("Stobj " + type);
2346 ilGen.Emit(OpCodes.Stobj, type);
2349 //This code is not tested
2350 internal void StoreOutParam(ArgBuilder arg, object value)
2352 Type destType = arg.ArgType;
2353 if (!destType.IsByRef)
2354 throw new InvalidOperationException("OutParametersMustBeByRefTypeReceived"); //.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlObjectSerializer.CreateSerializationException(SR.GetString(SR.OutParametersMustBeByRefTypeReceived, DataContract.GetClrTypeFullName(destType))));
2355 destType = destType.GetElementType();
2357 Type sourceType;
2358 if (value is ArgBuilder)
2359 sourceType = ((ArgBuilder) value).ArgType;
2360 else if (value is LocalBuilder)
2361 sourceType = ((LocalBuilder) value).LocalType;
2362 else if (value != null)
2363 sourceType = value.GetType();
2364 else
2365 sourceType = null;
2367 Load(arg);
2368 Load(value);
2369 if (sourceType != null)
2370 ConvertAddress(sourceType, destType);
2371 Stind(destType);
2373 void CheckSecurity(FieldInfo field)
2375 if (fullTrustDemanded)
2376 return;
2377 if (IsProtectedWithSecurity(field))
2378 DemandFullTrust();
2381 void CheckSecurity(MethodBase method)
2383 if (fullTrustDemanded)
2384 return;
2385 if (IsProtectedWithSecurity(method))
2386 DemandFullTrust();
2389 void CheckSecurity(Type type)
2391 if (fullTrustDemanded)
2392 return;
2393 if (IsProtectedWithSecurity(type))
2394 DemandFullTrust();
2397 void CheckSecurity(Assembly assembly)
2399 if (fullTrustDemanded)
2400 return;
2401 if (IsProtectedWithSecurity(assembly))
2402 DemandFullTrust();
2405 static bool IsProtectedWithSecurity(FieldInfo field)
2407 return IsProtectedWithSecurity(field.DeclaringType);
2410 static bool IsProtectedWithSecurity(Type type)
2412 return IsProtectedWithSecurity(type.Assembly) || (type.Attributes & TypeAttributes.HasSecurity) != 0;
2415 static bool IsProtectedWithSecurity(Assembly assembly)
2417 object[] attrs = assembly.GetCustomAttributes(typeof(AllowPartiallyTrustedCallersAttribute), true);
2418 bool hasAptca = attrs != null && attrs.Length > 0;
2419 return !hasAptca;
2422 void DemandFullTrust()
2424 fullTrustDemanded = true;
2426 if (codeGenTrace != CodeGenTrace.None)
2427 EmitSourceComment("DemandFullTrust() {");
2429 Ldc(PermissionState.Unrestricted);
2430 New(permissionSetCtor);
2431 Call(permissionSetDemand);
2433 if (codeGenTrace != CodeGenTrace.None)
2434 EmitSourceComment("}");
2438 static bool IsProtectedWithSecurity(MethodBase method)
2440 return false;
2441 //return (method.Attributes & MethodAttributes.HasSecurity) != 0;
2444 #endif
2449 internal class ArgBuilder {
2450 internal string Name;
2451 internal int Index;
2452 internal Type ArgType;
2453 internal ArgBuilder(string name, int index, Type argType) {
2454 this.Name = name;
2455 this.Index = index;
2456 this.ArgType = argType;
2460 internal class ForState {
2461 LocalBuilder indexVar;
2462 Label beginLabel;
2463 Label testLabel;
2464 object end;
2466 internal ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end) {
2467 this.indexVar = indexVar;
2468 this.beginLabel = beginLabel;
2469 this.testLabel = testLabel;
2470 this.end = end;
2473 internal LocalBuilder Index {
2474 get {
2475 return indexVar;
2479 internal Label BeginLabel {
2480 get {
2481 return beginLabel;
2485 internal Label TestLabel {
2486 get {
2487 return testLabel;
2491 internal object End {
2492 get {
2493 return end;
2498 internal enum Cmp : int {
2499 LessThan = 0,
2500 EqualTo,
2501 LessThanOrEqualTo,
2502 GreaterThan,
2503 NotEqualTo,
2504 GreaterThanOrEqualTo
2507 internal class IfState {
2508 Label elseBegin;
2509 Label endIf;
2511 internal Label EndIf {
2512 get {
2513 return this.endIf;
2515 set {
2516 this.endIf = value;
2520 internal Label ElseBegin {
2521 get {
2522 return this.elseBegin;
2524 set {
2525 this.elseBegin = value;
2531 internal class LocalScope {
2532 public readonly LocalScope parent;
2533 readonly Dictionary<string, LocalBuilder> locals;
2535 // Root scope
2536 public LocalScope() {
2537 this.locals = new Dictionary<string, LocalBuilder>();
2540 public LocalScope(LocalScope parent) : this() {
2541 this.parent = parent;
2544 public void Add(string key, LocalBuilder value) {
2545 locals.Add(key, value);
2548 public bool ContainsKey(string key) {
2549 return locals.ContainsKey(key) || (parent != null && parent.ContainsKey(key));
2552 public bool TryGetValue(string key, out LocalBuilder value) {
2553 if (locals.TryGetValue(key, out value)) {
2554 return true;
2556 else if (parent != null) {
2557 return parent.TryGetValue(key, out value);
2559 else {
2560 value = null;
2561 return false;
2565 public LocalBuilder this[string key] {
2566 get {
2567 LocalBuilder value;
2568 TryGetValue(key, out value);
2569 return value;
2571 set {
2572 locals[key] = value;
2576 public void AddToFreeLocals(Dictionary<Tuple<Type, string>, Queue<LocalBuilder>> freeLocals) {
2577 foreach (var item in locals) {
2578 Tuple<Type, string> key = new Tuple<Type, string>(item.Value.LocalType, item.Key);
2579 Queue<LocalBuilder> freeLocalQueue;
2580 if (freeLocals.TryGetValue(key, out freeLocalQueue)) {
2581 // Add to end of the queue so that it will be re-used in
2582 // FIFO manner
2583 freeLocalQueue.Enqueue(item.Value);
2585 else {
2586 freeLocalQueue = new Queue<LocalBuilder>();
2587 freeLocalQueue.Enqueue(item.Value);
2588 freeLocals.Add(key, freeLocalQueue);
2594 #if NotUsed
2595 internal class BitFlagsGenerator
2597 LocalBuilder[] locals;
2598 CodeGenerator ilg;
2599 int bitCount;
2600 internal BitFlagsGenerator(int bitCount, CodeGenerator ilg, string localName)
2602 this.ilg = ilg;
2603 this.bitCount = bitCount;
2604 int localCount = (bitCount+7)/8;
2605 locals = new LocalBuilder[localCount];
2606 for (int i=0;i<locals.Length;i++)
2607 locals[i] = ilg.DeclareLocal(Globals.TypeOfByte, localName+i, (byte)0);
2609 internal void Store(int bitIndex, bool value)
2611 LocalBuilder local = locals[GetByteIndex(bitIndex)];
2612 byte bitValue = GetBitValue(bitIndex);
2613 if (value)
2615 ilg.Load(local);
2616 ilg.Load(bitValue);
2617 ilg.Or();
2618 ilg.Stloc(local);
2620 else
2622 ilg.Load(local);
2623 ilg.Load(bitValue);
2624 ilg.Not();
2625 ilg.And();
2626 ilg.Stloc(local);
2630 internal void Load(int bitIndex)
2632 LocalBuilder local = locals[GetByteIndex(bitIndex)];
2633 byte bitValue = GetBitValue(bitIndex);
2634 ilg.Load(local);
2635 ilg.Load(bitValue);
2636 ilg.And();
2637 ilg.Load(bitValue);
2638 ilg.Ceq();
2641 internal void LoadArray()
2643 LocalBuilder localArray = ilg.DeclareLocal(Globals.TypeOfByteArray, "localArray");
2644 ilg.NewArray(Globals.TypeOfByte, locals.Length);
2645 ilg.Store(localArray);
2646 for (int i=0;i<locals.Length;i++)
2647 ilg.StoreArrayElement(localArray, i, locals[i]);
2648 ilg.Load(localArray);
2651 internal int GetLocalCount()
2653 return locals.Length;
2656 internal int GetBitCount()
2658 return bitCount;
2661 internal LocalBuilder GetLocal(int i)
2663 return locals[i];
2666 internal static bool IsBitSet(byte[] bytes, int bitIndex)
2668 int byteIndex = GetByteIndex(bitIndex);
2669 byte bitValue = GetBitValue(bitIndex);
2670 return (bytes[byteIndex] & bitValue) == bitValue;
2673 internal static void SetBit(byte[] bytes, int bitIndex)
2675 int byteIndex = GetByteIndex(bitIndex);
2676 byte bitValue = GetBitValue(bitIndex);
2677 bytes[byteIndex] |= bitValue;
2680 static int GetByteIndex(int bitIndex)
2682 return bitIndex >> 3;
2685 static byte GetBitValue(int bitIndex)
2687 return (byte)(1 << (bitIndex & 7));
2691 internal class SwitchState
2693 Label defaultLabel;
2694 Label endOfSwitchLabel;
2695 bool defaultDefined;
2696 internal SwitchState(Label defaultLabel, Label endOfSwitchLabel)
2698 this.defaultLabel = defaultLabel;
2699 this.endOfSwitchLabel = endOfSwitchLabel;
2700 this.defaultDefined = false;
2702 internal Label DefaultLabel
2706 return defaultLabel;
2710 internal Label EndOfSwitchLabel
2714 return endOfSwitchLabel;
2717 internal bool DefaultDefined
2721 return defaultDefined;
2725 defaultDefined = value;
2729 #endif
2731 internal class MethodBuilderInfo {
2732 public readonly MethodBuilder MethodBuilder;
2733 public readonly Type[] ParameterTypes;
2734 public MethodBuilderInfo(MethodBuilder methodBuilder, Type[] parameterTypes) {
2735 this.MethodBuilder = methodBuilder;
2736 this.ParameterTypes = parameterTypes;
2739 public void Validate(Type returnType, Type[] parameterTypes, MethodAttributes attributes) {
2740 #if DEBUG
2741 Debug.Assert(this.MethodBuilder.ReturnType == returnType);
2742 Debug.Assert(this.MethodBuilder.Attributes == attributes);
2743 Debug.Assert(this.ParameterTypes.Length == parameterTypes.Length);
2744 for (int i = 0; i < parameterTypes.Length; ++i) {
2745 Debug.Assert(this.ParameterTypes[i] == parameterTypes[i]);
2747 #endif
2751 internal class CodeGeneratorConversionException : Exception {
2753 private Type sourceType;
2754 private Type targetType;
2755 private bool isAddress;
2756 private string reason;
2758 public CodeGeneratorConversionException(Type sourceType, Type targetType, bool isAddress, string reason)
2759 : base() {
2761 this.sourceType = sourceType;
2762 this.targetType = targetType;
2763 this.isAddress = isAddress;
2764 this.reason = reason;