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