1 //------------------------------------------------------------------------------
2 // <copyright file="CodeGenerator.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 // <owner current="true" primary="true">Microsoft</owner>
6 //------------------------------------------------------------------------------
9 using System
.Reflection
;
10 using System
.Resources
;
11 using System
.Runtime
.CompilerServices
;
14 namespace System
.Xml
.Serialization
{
16 using System
.Collections
;
17 using System
.Collections
.Generic
;
18 using System
.Configuration
;
19 using System
.Globalization
;
21 using System
.Xml
.Serialization
.Configuration
;
22 using System
.Reflection
;
23 using System
.Reflection
.Emit
;
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
;
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
;
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
) {
69 Debug
.Assert(iType
.IsInterface
);
70 foreach (Type iFace
in type
.GetInterfaces()) {
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
) {
86 methodBuilderInfo
.Validate(returnType
, argTypes
, methodAttributes
);
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)
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
);
115 MethodBuilder retVal
= null;
116 retVal
= methodBuilder
;
117 methodBuilder
= null;
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
{
151 if (retLocal
== null)
152 retLocal
= DeclareLocal(this.methodBuilder
.ReturnType
, "_ret");
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
);
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
;
176 return var.GetType();
179 internal object GetVariable(string name
) {
181 if (TryGetVariable(name
, out var))
183 System
.Diagnostics
.Debug
.Assert(false);
187 internal bool TryGetVariable(string name
, out object variable
) {
189 if (currentScope
!= null && currentScope
.TryGetValue(name
, out loc
)) {
194 if (argList
!= null && argList
.TryGetValue(name
, out arg
)) {
199 if (Int32
.TryParse(name
, out val
)) {
208 internal LocalBuilder
DeclareLocal(Type type
, string name
, object initialValue
) {
209 LocalBuilder local
= DeclareLocal(type
, name
);
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
239 if (freeLocalQueue
.Count
== 0) {
240 freeLocals
.Remove(key
);
248 internal LocalBuilder
DeclareLocal(Type type
, string name
) {
249 Debug
.Assert(!currentScope
.ContainsKey(name
));
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
;
260 internal LocalBuilder
DeclareOrGetLocal(Type type
, string name
) {
262 if (!currentScope
.TryGetValue(name
, out local
))
263 local
= DeclareLocal(type
, name
);
265 Debug
.Assert(local
.LocalType
== type
);
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)
288 internal object For(LocalBuilder local
, object start
, object end
) {
289 ForState forState
= new ForState(local
, DefineLabel(), DefineLabel(), end
);
290 if (forState
.Index
!= null) {
292 Stloc(forState
.Index
);
293 Br(forState
.TestLabel
);
295 MarkLabel(forState
.BeginLabel
);
296 blockStack
.Push(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
);
308 Stloc(forState
.Index
);
309 MarkLabel(forState
.TestLabel
);
310 Ldloc(forState
.Index
);
312 Type varType
= GetVariableType(forState
.End
);
313 if (varType
.IsArray
) {
318 CodeGenerator
.AssertHasInterface(varType
, typeof(ICollection
));
320 MethodInfo ICollection_get_Count
= typeof(ICollection
).GetMethod(
322 CodeGenerator
.InstanceBindingFlags
,
324 CodeGenerator
.EmptyTypeArray
,
327 Call(ICollection_get_Count
);
329 Blt(forState
.BeginLabel
);
332 Br(forState
.BeginLabel
);
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
);
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
));
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
);
412 ConvertValue(type
, Globals
.TypeOfObject
);
418 LoadDefaultValue(type
);
429 internal void IfNot() {
433 static OpCode
[] BranchCodes
= new OpCode
[] {
442 OpCode
GetBranchCode(Cmp cmp
) {
443 return BranchCodes
[(int)cmp
];
447 Cmp
GetCmpInverse(Cmp cmp
)
451 return Cmp
.GreaterThanOrEqualTo
;
453 return Cmp
.NotEqualTo
;
454 case Cmp
.LessThanOrEqualTo
:
455 return Cmp
.GreaterThan
;
456 case Cmp
.GreaterThan
:
457 return Cmp
.LessThanOrEqualTo
;
461 Debug
.Assert(cmp
== Cmp
.GreaterThanOrEqualTo
, "Unexpected cmp");
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
) {
481 internal void Else() {
482 IfState ifState
= PopIfState();
484 MarkLabel(ifState
.ElseBegin
);
486 ifState
.ElseBegin
= ifState
.EndIf
;
487 blockStack
.Push(ifState
);
491 internal void ElseIf(object value1
, Cmp cmpOp
, object value2
)
493 IfState ifState
= (IfState
)blockStack
.Pop();
495 MarkLabel(ifState
.ElseBegin
);
499 ifState
.ElseBegin
= DefineLabel();
500 ilGen
.Emit(GetBranchCode(cmpOp
), ifState
.ElseBegin
);
501 blockStack
.Push(ifState
);
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());
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
);
545 internal void Call(object thisObj
, MethodInfo methodInfo
, object param1
)
547 VerifyParameterCount(methodInfo
, 1);
548 LoadThis(thisObj
, methodInfo
);
549 LoadParam(param1
, 1, 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
);
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
);
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
);
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
);
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
);
609 internal void Call(MethodInfo methodInfo
) {
610 Debug
.Assert(methodInfo
!= null);
611 if (methodInfo
.IsVirtual
&& !methodInfo
.DeclaringType
.IsValueType
)
612 ilGen
.Emit(OpCodes
.Callvirt
, methodInfo
);
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
);
628 internal void New(ConstructorInfo constructorInfo
, object param1
)
630 LoadParam(param1
, 1, constructorInfo
);
631 New(constructorInfo
);
635 internal void InitObj(Type valueType
) {
636 ilGen
.Emit(OpCodes
.Initobj
, valueType
);
639 internal void NewArray(Type elementType
, object len
) {
641 ilGen
.Emit(OpCodes
.Newarr
, elementType
);
645 internal void IgnoreReturnValue()
651 internal void LoadArrayElement(object obj
, object arrayIndex
) {
652 Type objType
= GetVariableType(obj
).GetElementType();
655 if (IsStruct(objType
)) {
663 internal void StoreArrayElement(object obj
, object arrayIndex
, object value) {
664 Type arrayType
= GetVariableType(obj
);
665 if (arrayType
== typeof(Array
)) {
667 Call(typeof(Array
).GetMethod("SetValue", new Type
[] { typeof(object), typeof(int) }
));
670 Type objType
= arrayType
.GetElementType();
673 if (IsStruct(objType
))
676 ConvertValue(GetVariableType(value), objType
);
677 if (IsStruct(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
)
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) {
709 result
= currentProperty
.GetGetMethod(true);
712 result
= currentProperty
.GetSetMethod(true);
715 if (result
!= null) {
716 // we found the GetMethod/SetMethod on the type closest to the current declaring type
721 // keep looking at the base type like compiler does
722 currentType
= currentType
.BaseType
;
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
);
737 ilGen
.Emit(OpCodes
.Ldfld
, fieldInfo
);
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);
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
);
769 ilGen
.Emit(OpCodes
.Ldflda
, fieldInfo
);
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);
787 LocalBuilder tmpLoc
= GetTempLocal(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
);
803 ilGen
.Emit(OpCodes
.Stfld
, fieldInfo
);
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);
824 internal void LoadDefaultValue(Type type
)
826 if (type
.IsValueType
)
828 switch (Type
.GetTypeCode(type
))
830 case TypeCode
.Boolean
:
837 case TypeCode
.UInt16
:
839 case TypeCode
.UInt32
:
843 case TypeCode
.UInt64
:
846 case TypeCode
.Single
:
849 case TypeCode
.Double
:
852 case TypeCode
.Decimal
:
853 case TypeCode
.DateTime
:
855 LocalBuilder zero
= DeclareLocal(type
, "zero");
867 internal void Load(object obj
) {
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
);
879 internal void Store(object var)
881 if (var is ArgBuilder
)
882 Starg((ArgBuilder
)var);
885 System
.Diagnostics
.Debug
.Assert(var is LocalBuilder
);
886 Stloc((LocalBuilder
)var);
890 internal void Dec(object var)
898 internal void Inc(object var)
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
);
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,
956 OpCodes
.Ldind_Ref
,//String = 18,
960 OpCode
GetLdindOpCode(TypeCode typeCode
) {
961 return LdindOpCodes
[(int)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:
991 // return OpCodes.Nop;
996 internal void Ldobj(Type type
) {
997 OpCode opCode
= GetLdindOpCode(Type
.GetTypeCode(type
));
998 if (!opCode
.Equals(OpCodes
.Nop
)) {
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() {
1025 internal void Bgt(Label label
)
1027 ilGen
.Emit(OpCodes
.Bgt
, label
);
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();
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));
1053 switch (Type
.GetTypeCode(valueType
)) {
1054 case TypeCode
.Boolean
:
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
:
1062 case TypeCode
.Int16
:
1063 case TypeCode
.UInt16
:
1064 Ldc(((IConvertible
)o
).ToInt32(CultureInfo
.InvariantCulture
));
1066 case TypeCode
.Int32
:
1069 case TypeCode
.UInt32
:
1072 case TypeCode
.UInt64
:
1073 Ldc((long)(ulong)o
);
1075 case TypeCode
.Int64
:
1078 case TypeCode
.Single
:
1081 case TypeCode
.Double
:
1084 case TypeCode
.String
:
1087 case TypeCode
.Decimal
:
1088 ConstructorInfo Decimal_ctor
= typeof(Decimal
).GetConstructor(
1089 CodeGenerator
.InstanceBindingFlags
,
1091 new Type
[] { typeof(Int32), typeof(Int32), typeof(Int32), typeof(Boolean), typeof(Byte) }
,
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
1102 case TypeCode
.DateTime
:
1103 ConstructorInfo DateTime_ctor
= typeof(DateTime
).GetConstructor(
1104 CodeGenerator
.InstanceBindingFlags
,
1106 new Type
[] { typeof(Int64) }
,
1109 Ldc(((DateTime
)o
).Ticks
); // ticks
1112 case TypeCode
.Object
:
1113 case TypeCode
.Empty
:
1114 case TypeCode
.DBNull
:
1116 if (valueType
== typeof(TimeSpan
) && LocalAppContextSwitches
.EnableTimeSpanSerialization
)
1118 ConstructorInfo TimeSpan_ctor
= typeof(TimeSpan
).GetConstructor(
1119 CodeGenerator
.InstanceBindingFlags
,
1121 new Type
[] { typeof(Int64) }
,
1124 Ldc(((TimeSpan
)o
).Ticks
); // ticks
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
) {
1139 ilGen
.Emit(OpCodes
.Ldc_I4_1
);
1142 ilGen
.Emit(OpCodes
.Ldc_I4_0
);
1146 internal void Ldc(int intVar
) {
1149 ilGen
.Emit(OpCodes
.Ldc_I4_M1
);
1152 ilGen
.Emit(OpCodes
.Ldc_I4_0
);
1155 ilGen
.Emit(OpCodes
.Ldc_I4_1
);
1158 ilGen
.Emit(OpCodes
.Ldc_I4_2
);
1161 ilGen
.Emit(OpCodes
.Ldc_I4_3
);
1164 ilGen
.Emit(OpCodes
.Ldc_I4_4
);
1167 ilGen
.Emit(OpCodes
.Ldc_I4_5
);
1170 ilGen
.Emit(OpCodes
.Ldc_I4_6
);
1173 ilGen
.Emit(OpCodes
.Ldc_I4_7
);
1176 ilGen
.Emit(OpCodes
.Ldc_I4_8
);
1179 ilGen
.Emit(OpCodes
.Ldc_I4
, intVar
);
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
) {
1198 ilGen
.Emit(OpCodes
.Ldnull
);
1200 ilGen
.Emit(OpCodes
.Ldstr
, strVar
);
1203 internal void LdlocAddress(LocalBuilder localBuilder
) {
1204 if (localBuilder
.LocalType
.IsValueType
)
1205 Ldloca(localBuilder
);
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
];
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
);
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
);
1241 internal void Ldloc(int slot
)
1246 ilGen
.Emit(OpCodes
.Ldloc_0
);
1249 ilGen
.Emit(OpCodes
.Ldloc_1
);
1252 ilGen
.Emit(OpCodes
.Ldloc_2
);
1255 ilGen
.Emit(OpCodes
.Ldloc_3
);
1259 ilGen
.Emit(OpCodes
.Ldloc_S
, slot
);
1261 ilGen
.Emit(OpCodes
.Ldloc
, slot
);
1266 internal void Stloc(int slot
)
1271 ilGen
.Emit(OpCodes
.Stloc_0
);
1274 ilGen
.Emit(OpCodes
.Stloc_1
);
1277 ilGen
.Emit(OpCodes
.Stloc_2
);
1280 ilGen
.Emit(OpCodes
.Stloc_3
);
1284 ilGen
.Emit(OpCodes
.Stloc_S
, slot
);
1286 ilGen
.Emit(OpCodes
.Stloc
, slot
);
1291 internal void Ldloca(int slot
)
1294 ilGen
.Emit(OpCodes
.Ldloca_S
, slot
);
1296 ilGen
.Emit(OpCodes
.Ldloca
, slot
);
1300 internal void Ldloca(LocalBuilder localBuilder
) {
1301 ilGen
.Emit(OpCodes
.Ldloca
, localBuilder
);
1304 internal void LdargAddress(ArgBuilder argBuilder
) {
1305 if (argBuilder
.ArgType
.IsValueType
)
1311 internal void Ldarg(string arg
) {
1315 internal void Ldarg(ArgBuilder arg
) {
1319 internal void Ldarg(int slot
) {
1322 ilGen
.Emit(OpCodes
.Ldarg_0
);
1325 ilGen
.Emit(OpCodes
.Ldarg_1
);
1328 ilGen
.Emit(OpCodes
.Ldarg_2
);
1331 ilGen
.Emit(OpCodes
.Ldarg_3
);
1335 ilGen
.Emit(OpCodes
.Ldarg_S
, slot
);
1337 ilGen
.Emit(OpCodes
.Ldarg
, slot
);
1343 internal void Starg(ArgBuilder arg
)
1348 internal void Starg(int slot
)
1351 ilGen
.Emit(OpCodes
.Starg_S
, slot
);
1353 ilGen
.Emit(OpCodes
.Starg
, slot
);
1357 internal void Ldarga(ArgBuilder argBuilder
) {
1358 Ldarga(argBuilder
.Index
);
1361 internal void Ldarga(int slot
) {
1363 ilGen
.Emit(OpCodes
.Ldarga_S
, slot
);
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,
1392 OpCodes
.Ldelem_Ref
,//String = 18,
1395 OpCode
GetLdelemOpCode(TypeCode typeCode
) {
1396 return LdelemOpCodes
[(int)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:
1429 // return OpCodes.Nop;
1433 internal void Ldelem(Type arrayElementType
) {
1434 if (arrayElementType
.IsEnum
) {
1435 Ldelem(Enum
.GetUnderlyingType(arrayElementType
));
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))));
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,
1469 OpCodes
.Stelem_Ref
,//String = 18,
1472 OpCode
GetStelemOpCode(TypeCode typeCode
) {
1473 return StelemOpCodes
[(int)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:
1506 // return OpCodes.Nop;
1510 internal void Stelem(Type arrayElementType
) {
1511 if (arrayElementType
.IsEnum
)
1512 Stelem(Enum
.GetUnderlyingType(arrayElementType
));
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))));
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
);
1538 internal void Subtract()
1540 ilGen
.Emit(OpCodes
.Sub
);
1545 ilGen
.Emit(OpCodes
.And
);
1549 ilGen
.Emit(OpCodes
.Or
);
1554 ilGen
.Emit(OpCodes
.Not
);
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
);
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
)
1610 ConvertValue(GetVariableType(arg
), methodInfo
.GetParameters()[oneBasedArgIndex
- 1].ParameterType
);
1614 void InternalIf(bool negate
) {
1615 IfState ifState
= new IfState();
1616 ifState
.EndIf
= DefineLabel();
1617 ifState
.ElseBegin
= DefineLabel();
1619 Brtrue(ifState
.ElseBegin
);
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,
1644 OpCodes
.Nop
,//String = 18,
1647 OpCode
GetConvOpCode(TypeCode typeCode
) {
1648 return ConvOpCodes
[(int)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:
1676 // return OpCodes.Nop;
1680 void InternalConvert(Type source
, Type target
, bool isAddress
) {
1681 if (target
== source
)
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");
1694 else if (source
.IsAssignableFrom(target
)) {
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
) {
1711 else if (source
.IsAssignableFrom(target
)) {
1712 //assert(source.IsValueType == false);
1715 else if (target
.IsInterface
|| source
.IsInterface
) {
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);
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
);
1738 return appDomain
.DefineDynamicAssembly(assemblyName
, AssemblyBuilderAccess
.Run
);
1741 static string tempFilesLocation
= null;
1742 internal static string TempFilesLocation
{
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
;
1756 string location
= null;
1758 if (location
!= null) {
1759 tempFilesLocation
= location
.Trim();
1762 tempFilesLocation
= Path
.GetTempPath();
1765 return tempFilesLocation
;
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);
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
);
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
)
1816 codeGenTrace
= CodeGenTrace
.None
;
1818 ToString(stackTopType
);
1819 LocalBuilder topValue
= DeclareLocal(Globals
.TypeOfString
, "topValue");
1824 Call(XmlFormatGeneratorStatics
.TraceInstructionMethod
);
1825 codeGenTrace
= CodeGenTrace
.Tron
;
1828 internal void ToString(Type type
)
1830 if (type
.IsValueType
)
1833 Call(ObjectToString
);
1845 LocalBuilder arrayVar
= DeclareLocal(type
, "arrayVar");
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());
1857 Store(arrayValueString
);
1859 Load(arrayValueString
);
1864 Call(ObjectToString
);
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
);
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
]);
1949 Load(stringFormatArray
);
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]);
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
) {
1981 if (initElseIfStack
== blockStack
.Count
) {
1982 initElseIfStack
= -1;
1983 elseIfState
.ElseBegin
= DefineLabel();
1984 ilGen
.Emit(GetBranchCode(cmpOp
), elseIfState
.ElseBegin
);
1985 blockStack
.Push(elseIfState
);
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
) {
1999 if (initElseIfStack
== blockStack
.Count
) {
2000 initElseIfStack
= -1;
2001 elseIfState
.ElseBegin
= DefineLabel();
2002 Brfalse(elseIfState
.ElseBegin
);
2003 blockStack
.Push(elseIfState
);
2006 Debug
.Assert(initIfStack
== -1 && initElseIfStack
== -1);
2007 IfState ifState
= (IfState
)blockStack
.Peek();
2008 Brfalse(ifState
.ElseBegin
);
2012 internal void ElseIf(object boolVal
)
2014 InternalElseIf(boolVal
, false);
2016 void InternalElseIf(object boolVal
, bool negate
)
2018 IfState ifState
= (IfState
)blockStack
.Pop();
2020 MarkLabel(ifState
.ElseBegin
);
2023 ifState
.ElseBegin
= DefineLabel();
2025 Brtrue(ifState
.ElseBegin
);
2027 Brfalse(ifState
.ElseBegin
);
2028 blockStack
.Push(ifState
);
2031 internal void IfString(object s1
, Cmp cmpOp
, object s2
)
2035 Call(stringCompare
);
2040 internal void ElseIfString(object s1
, Cmp cmpOp
, object s2
)
2042 IfState ifState
= (IfState
)blockStack
.Pop();
2044 MarkLabel(ifState
.ElseBegin
);
2048 Call(stringCompare
);
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
);
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
);
2107 internal void IsInst(Type type
) {
2108 ilGen
.Emit(OpCodes
.Isinst
, type
);
2114 if (codeGenTrace
!= CodeGenTrace
.None
)
2115 EmitSourceInstruction("Clt");
2116 ilGen
.Emit(OpCodes
.Clt
);
2119 internal void StringEquals()
2124 internal void StringEquals(object s1
, object s2
)
2127 ConvertValue(GetVariableType(s1
), typeof(string));
2129 ConvertValue(GetVariableType(s2
), typeof(string));
2133 internal void Bge(Label label
)
2135 if (codeGenTrace
!= CodeGenTrace
.None
)
2136 EmitSourceInstruction("Bge " + label
.GetHashCode());
2137 ilGen
.Emit(OpCodes
.Bge
, label
);
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
);
2150 internal void ResizeArray(object arrayVar
, object sizeVar
)
2152 if (codeGenTrace
!= CodeGenTrace
.None
)
2153 EmitSourceComment("ResizeArray() {");
2155 Label doResize
= DefineLabel();
2162 MarkLabel(doResize
);
2163 Type arrayType
= GetVariableType(arrayVar
);
2164 Type elementType
= arrayType
.GetElementType();
2165 LocalBuilder tempArray
= DeclareLocal(arrayType
, "tempArray");
2166 NewArray(elementType
, sizeVar
);
2168 CopyArray(arrayVar
, tempArray
, sizeVar
);
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);
2189 Load(lastElementVar
);
2191 If(Cmp
.GreaterThanOrEqualTo
);
2192 LocalBuilder tempArray
= DeclareLocal(arrayType
, "tempArray");
2193 if (resizeLen
== null)
2194 resizeLen
= DeclareLocal(typeof(int), "resizeLen");
2195 Load(lastElementVar
);
2199 NewArray(elementType
, resizeLen
);
2201 CopyArray(arrayVar
, tempArray
, arrayVar
);
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
);
2218 Load(resizeCounter
);
2219 LoadArrayElement(sourceArray
, resizeCounter
);
2220 Stelem(GetVariableType(destArray
).GetElementType());
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();
2247 // WhileBeginCondition()
2249 // WhileEndCondition()
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.
2280 MarkLabel(whileState
.CondLabel
);
2283 internal void WhileEndCondition() {
2284 WhileState whileState
= (WhileState
)whileStack
.Peek();
2285 Brtrue(whileState
.StartLabel
);
2289 internal void AndWhile(Cmp cmpOp
)
2291 object startWhile
= blockStack
.Pop();
2293 blockStack
.Push(startWhile
);
2296 internal void BeginWhileBody()
2298 Label startWhile
= (Label
) blockStack
.Pop();
2300 blockStack
.Push(startWhile
);
2303 internal void BeginWhileBody(Cmp cmpOp
)
2305 Label startWhile
= (Label
) blockStack
.Pop();
2307 blockStack
.Push(startWhile
);
2310 internal Label
BeginWhileCondition()
2312 Label startWhile
= DefineLabel();
2313 MarkLabel(startWhile
);
2314 blockStack
.Push(startWhile
);
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());
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();
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();
2369 if (sourceType
!= null)
2370 ConvertAddress(sourceType
, destType
);
2373 void CheckSecurity(FieldInfo field
)
2375 if (fullTrustDemanded
)
2377 if (IsProtectedWithSecurity(field
))
2381 void CheckSecurity(MethodBase method
)
2383 if (fullTrustDemanded
)
2385 if (IsProtectedWithSecurity(method
))
2389 void CheckSecurity(Type type
)
2391 if (fullTrustDemanded
)
2393 if (IsProtectedWithSecurity(type
))
2397 void CheckSecurity(Assembly assembly
)
2399 if (fullTrustDemanded
)
2401 if (IsProtectedWithSecurity(assembly
))
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;
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
)
2441 //return (method.Attributes & MethodAttributes.HasSecurity) != 0;
2449 internal class ArgBuilder
{
2450 internal string Name
;
2452 internal Type ArgType
;
2453 internal ArgBuilder(string name
, int index
, Type argType
) {
2456 this.ArgType
= argType
;
2460 internal class ForState
{
2461 LocalBuilder indexVar
;
2466 internal ForState(LocalBuilder indexVar
, Label beginLabel
, Label testLabel
, object end
) {
2467 this.indexVar
= indexVar
;
2468 this.beginLabel
= beginLabel
;
2469 this.testLabel
= testLabel
;
2473 internal LocalBuilder Index
{
2479 internal Label BeginLabel
{
2485 internal Label TestLabel
{
2491 internal object End
{
2498 internal enum Cmp
: int {
2504 GreaterThanOrEqualTo
2507 internal class IfState
{
2511 internal Label EndIf
{
2520 internal Label ElseBegin
{
2522 return this.elseBegin
;
2525 this.elseBegin
= value;
2531 internal class LocalScope
{
2532 public readonly LocalScope parent
;
2533 readonly Dictionary
<string, LocalBuilder
> locals
;
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)) {
2556 else if (parent
!= null) {
2557 return parent
.TryGetValue(key
, out value);
2565 public LocalBuilder
this[string key
] {
2568 TryGetValue(key
, out value);
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
2583 freeLocalQueue
.Enqueue(item
.Value
);
2586 freeLocalQueue
= new Queue
<LocalBuilder
>();
2587 freeLocalQueue
.Enqueue(item
.Value
);
2588 freeLocals
.Add(key
, freeLocalQueue
);
2595 internal class BitFlagsGenerator
2597 LocalBuilder
[] locals
;
2600 internal BitFlagsGenerator(int bitCount
, CodeGenerator ilg
, string localName
)
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
);
2630 internal void Load(int bitIndex
)
2632 LocalBuilder local
= locals
[GetByteIndex(bitIndex
)];
2633 byte bitValue
= GetBitValue(bitIndex
);
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()
2661 internal LocalBuilder
GetLocal(int 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
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;
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
) {
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
]);
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
)
2761 this.sourceType
= sourceType
;
2762 this.targetType
= targetType
;
2763 this.isAddress
= isAddress
;
2764 this.reason
= reason
;