PageRenderTime 85ms CodeModel.GetById 12ms app.highlight 64ms RepoModel.GetById 1ms app.codeStats 1ms

/WCFWebApi/prototype/Microsoft.ApplicationServer.HttpEnhancements/System/ServiceModel/Dispatcher/CodeGenerator.cs

#
C# | 1481 lines | 1309 code | 165 blank | 7 comment | 190 complexity | c545bf363a038adeb716b2ea6d8eda46 MD5 | raw file
   1// <copyright>
   2//   Copyright (c) Microsoft Corporation.  All rights reserved.
   3// </copyright>
   4
   5namespace System.ServiceModel.Dispatcher
   6{
   7    using System;
   8    using Collections;
   9    using System.Diagnostics;
  10    using Globalization;
  11    using Reflection;
  12    using Reflection.Emit;
  13    using System.Security;
  14    using Diagnostics;
  15    using Microsoft.Server.Common;
  16    using Microsoft.ApplicationServer.HttpEnhancements;
  17
  18    [Fx.Tag.SecurityNote(Critical = "Generates IL into an ILGenerator that was created under an Assert."
  19        + "Generated IL must be correct and must not subvert the type system.")]
  20#pragma warning disable 618 // have not moved to the v4 security model yet
  21    [SecurityCritical(SecurityCriticalScope.Everything)]
  22#pragma warning restore 618
  23    internal class CodeGenerator
  24    {
  25        static MethodInfo getTypeFromHandle;
  26        static MethodInfo stringConcat2;
  27        static MethodInfo objectToString;
  28        static MethodInfo boxPointer;
  29        static MethodInfo unboxPointer;
  30
  31#if USE_REFEMIT
  32        AssemblyBuilder assemblyBuilder;
  33        ModuleBuilder moduleBuilder;
  34        TypeBuilder typeBuilder;
  35        static int typeCounter;
  36        MethodBuilder methodBuilder;
  37#else
  38        static Module SerializationModule = typeof(CodeGenerator).Module;   // Can be replaced by different assembly with SkipVerification set to false
  39        DynamicMethod dynamicMethod;
  40
  41#if DEBUG
  42        bool allowPrivateMemberAccess;
  43#endif
  44#endif
  45
  46        Type delegateType;
  47        ILGenerator ilGen;
  48        ArrayList argList;
  49        Stack blockStack;
  50        Label methodEndLabel;
  51
  52        Hashtable localNames;
  53        int lineNo = 1;
  54
  55        enum CodeGenTrace { None, Save, Tron };
  56        CodeGenTrace codeGenTrace;
  57
  58        internal CodeGenerator()
  59        {
  60            SourceSwitch codeGenSwitch = OperationInvokerTrace.CodeGenerationSwitch;
  61            if ((codeGenSwitch.Level & SourceLevels.Verbose) == SourceLevels.Verbose)
  62            {
  63                codeGenTrace = CodeGenTrace.Tron;
  64            }
  65            else if ((codeGenSwitch.Level & SourceLevels.Information) == SourceLevels.Information)
  66            {
  67                codeGenTrace = CodeGenTrace.Save;
  68            }
  69            else
  70            {
  71                codeGenTrace = CodeGenTrace.None;
  72            }
  73        }
  74
  75        static MethodInfo GetTypeFromHandle
  76        {
  77            get
  78            {
  79                if (getTypeFromHandle == null)
  80                {
  81                    getTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
  82                }
  83
  84                return getTypeFromHandle;
  85            }
  86        }
  87
  88        static MethodInfo StringConcat2
  89        {
  90            get
  91            {
  92                if (stringConcat2 == null)
  93                {
  94                    stringConcat2 = typeof(string).GetMethod("Concat", new Type[] { typeof(string), typeof(string) });
  95                }
  96
  97                return stringConcat2;
  98            }
  99        }
 100
 101        static MethodInfo ObjectToString
 102        {
 103            get
 104            {
 105                if (objectToString == null)
 106                {
 107                    objectToString = typeof(object).GetMethod("ToString", new Type[0]);
 108                }
 109
 110                return objectToString;
 111            }
 112        }
 113
 114        static MethodInfo BoxPointer
 115        {
 116            get
 117            {
 118                if (boxPointer == null)
 119                {
 120                    boxPointer = typeof(Pointer).GetMethod("Box");
 121                }
 122
 123                return boxPointer;
 124            }
 125        }
 126
 127        static MethodInfo UnboxPointer
 128        {
 129            get
 130            {
 131                if (unboxPointer == null)
 132                {
 133                    unboxPointer = typeof(Pointer).GetMethod("Unbox");
 134                }
 135
 136                return unboxPointer;
 137            }
 138        }
 139
 140        internal void BeginMethod(string methodName, Type delegateType, bool allowPrivateMemberAccess)
 141        {
 142            MethodInfo signature = delegateType.GetMethod("Invoke");
 143            ParameterInfo[] parameters = signature.GetParameters();
 144            Type[] paramTypes = new Type[parameters.Length];
 145            for (int i = 0; i < parameters.Length; i++)
 146            {
 147                paramTypes[i] = parameters[i].ParameterType;
 148            }
 149
 150            BeginMethod(signature.ReturnType, methodName, paramTypes, allowPrivateMemberAccess);
 151            this.delegateType = delegateType;
 152        }
 153
 154        void BeginMethod(Type returnType, string methodName, Type[] argTypes, bool allowPrivateMemberAccess)
 155        {
 156#if USE_REFEMIT
 157            string typeName = "Type" + (typeCounter++);
 158            InitAssemblyBuilder(typeName + "." + methodName);
 159            this.typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
 160            this.methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public|MethodAttributes.Static, returnType, argTypes);
 161            this.ilGen = this.methodBuilder.GetILGenerator();
 162#else
 163            this.dynamicMethod = new DynamicMethod(methodName, returnType, argTypes, SerializationModule, allowPrivateMemberAccess);
 164            this.ilGen = this.dynamicMethod.GetILGenerator();
 165#if DEBUG
 166            this.allowPrivateMemberAccess = allowPrivateMemberAccess;
 167#endif
 168#endif
 169
 170            this.methodEndLabel = ilGen.DefineLabel();
 171            this.blockStack = new Stack();
 172            this.argList = new ArrayList();
 173            for (int i = 0; i < argTypes.Length; i++)
 174            {
 175                argList.Add(new ArgBuilder(i, argTypes[i]));
 176            }
 177
 178            if (codeGenTrace != CodeGenTrace.None)
 179            {
 180                EmitSourceLabel("Begin method " + methodName + " {");
 181            }
 182        }
 183
 184        internal Delegate EndMethod()
 185        {
 186            MarkLabel(methodEndLabel);
 187            if (codeGenTrace != CodeGenTrace.None)
 188            {
 189                EmitSourceLabel("} End method");
 190            }
 191
 192            Ret();
 193
 194            Delegate retVal = null;
 195#if USE_REFEMIT
 196            Type type = typeBuilder.CreateType();
 197            if (codeGenTrace != CodeGenTrace.None)
 198                assemblyBuilder.Save(assemblyBuilder.GetName().Name+".dll");
 199
 200            MethodInfo method = type.GetMethod(methodBuilder.Name);
 201            retVal = Delegate.CreateDelegate(delegateType, method);
 202            methodBuilder = null;
 203#else
 204            retVal = dynamicMethod.CreateDelegate(delegateType);
 205            dynamicMethod = null;
 206#endif
 207            delegateType = null;
 208
 209            ilGen = null;
 210            blockStack = null;
 211            argList = null;
 212            return retVal;
 213        }
 214
 215        internal MethodInfo CurrentMethod
 216        {
 217            get
 218            {
 219#if USE_REFEMIT
 220                return methodBuilder;
 221#else
 222                return dynamicMethod;
 223#endif
 224            }
 225        }
 226
 227        internal ArgBuilder GetArg(int index)
 228        {
 229            return (ArgBuilder)argList[index];
 230        }
 231
 232        internal Type GetVariableType(object var)
 233        {
 234            if (var is ArgBuilder)
 235            {
 236                return ((ArgBuilder)var).ArgType;
 237            }
 238            else if (var is LocalBuilder)
 239            {
 240                return ((LocalBuilder)var).LocalType;
 241            }
 242            else
 243            {
 244                return var.GetType();
 245            }
 246        }
 247
 248        internal LocalBuilder DeclareLocal(Type type, string name)
 249        {
 250            return DeclareLocal(type, name, false);
 251        }
 252
 253        internal LocalBuilder DeclareLocal(Type type, string name, bool isPinned)
 254        {
 255            LocalBuilder local = ilGen.DeclareLocal(type, isPinned);
 256            if (codeGenTrace != CodeGenTrace.None)
 257            {
 258                LocalNames[local] = name;
 259                EmitSourceComment("Declare local '" + name + "' of type " + type);
 260            }
 261
 262            return local;
 263        }
 264
 265        internal void If()
 266        {
 267            InternalIf(false);
 268        }
 269
 270        internal void IfNot()
 271        {
 272            InternalIf(true);
 273        }
 274
 275        internal void Else()
 276        {
 277            IfState ifState = PopIfState();
 278            Br(ifState.EndIf);
 279            MarkLabel(ifState.ElseBegin);
 280
 281            ifState.ElseBegin = ifState.EndIf;
 282            blockStack.Push(ifState);
 283        }
 284
 285        internal void EndIf()
 286        {
 287            IfState ifState = PopIfState();
 288            if (!ifState.ElseBegin.Equals(ifState.EndIf))
 289            {
 290                MarkLabel(ifState.ElseBegin);
 291            }
 292
 293            MarkLabel(ifState.EndIf);
 294        }
 295
 296        internal void Call(MethodInfo methodInfo)
 297        {
 298            if (methodInfo.IsVirtual)
 299            {
 300                if (codeGenTrace != CodeGenTrace.None)
 301                {
 302                    EmitSourceInstruction("Callvirt " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
 303                }
 304
 305                ilGen.Emit(OpCodes.Callvirt, methodInfo);
 306            }
 307            else if (methodInfo.IsStatic)
 308            {
 309                if (codeGenTrace != CodeGenTrace.None)
 310                {
 311                    EmitSourceInstruction("Static Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
 312                }
 313
 314                ilGen.Emit(OpCodes.Call, methodInfo);
 315            }
 316            else
 317            {
 318                if (codeGenTrace != CodeGenTrace.None)
 319                {
 320                    EmitSourceInstruction("Call " + methodInfo.ToString() + " on type " + methodInfo.DeclaringType.ToString());
 321                }
 322
 323                ilGen.Emit(OpCodes.Call, methodInfo);
 324            }
 325        }
 326
 327        internal void New(ConstructorInfo constructor)
 328        {
 329            if (codeGenTrace != CodeGenTrace.None)
 330            {
 331                EmitSourceInstruction("Newobj " + constructor.ToString() + " on type " + constructor.DeclaringType.ToString());
 332            }
 333
 334            ilGen.Emit(OpCodes.Newobj, constructor);
 335        }
 336
 337        internal void InitObj(Type valueType)
 338        {
 339            if (codeGenTrace != CodeGenTrace.None)
 340            {
 341                EmitSourceInstruction("Initobj " + valueType);
 342            }
 343
 344            ilGen.Emit(OpCodes.Initobj, valueType);
 345        }
 346
 347        internal void LoadArrayElement(object obj, object arrayIndex)
 348        {
 349            Type objType = GetVariableType(obj).GetElementType();
 350            Load(obj);
 351            Load(arrayIndex);
 352            if (IsStruct(objType))
 353            {
 354                Ldelema(objType);
 355                Ldobj(objType);
 356            }
 357            else
 358            {
 359                Ldelem(objType);
 360            }
 361        }
 362
 363        internal void StoreArrayElement(object obj, object arrayIndex, object value)
 364        {
 365            Type objType = GetVariableType(obj).GetElementType();
 366            Load(obj);
 367            Load(arrayIndex);
 368            if (IsStruct(objType))
 369            {
 370                Ldelema(objType);
 371            }
 372
 373            Load(value);
 374            ConvertValue(GetVariableType(value), objType);
 375            if (IsStruct(objType))
 376            {
 377                Stobj(objType);
 378            }
 379            else
 380            {
 381                Stelem(objType);
 382            }
 383        }
 384
 385        static bool IsStruct(Type objType)
 386        {
 387            return objType.IsValueType && !objType.IsPrimitive;
 388        }
 389
 390        internal void Load(object obj)
 391        {
 392            if (obj == null)
 393            {
 394                if (codeGenTrace != CodeGenTrace.None)
 395                {
 396                    EmitSourceInstruction("Ldnull");
 397                }
 398
 399                ilGen.Emit(OpCodes.Ldnull);
 400            }
 401            else if (obj is ArgBuilder)
 402            {
 403                Ldarg((ArgBuilder)obj);
 404            }
 405            else if (obj is LocalBuilder)
 406            {
 407                Ldloc((LocalBuilder)obj);
 408            }
 409            else
 410            {
 411                Ldc(obj);
 412            }
 413        }
 414
 415        internal void Store(object var)
 416        {
 417            if (var is ArgBuilder)
 418            {
 419                Starg((ArgBuilder)var);
 420            }
 421            else if (var is LocalBuilder)
 422            {
 423                Stloc((LocalBuilder)var);
 424            }
 425            else
 426            {
 427                throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenCanOnlyStoreIntoArgOrLocGot0(var.GetType().FullName)));
 428            }
 429        }
 430
 431        internal void LoadAddress(object obj)
 432        {
 433            if (obj is ArgBuilder)
 434            {
 435                LdargAddress((ArgBuilder)obj);
 436            }
 437            else if (obj is LocalBuilder)
 438            {
 439                LdlocAddress((LocalBuilder)obj);
 440            }
 441            else
 442            {
 443                Load(obj);
 444            }
 445        }
 446
 447        internal void ConvertAddress(Type source, Type target)
 448        {
 449            InternalConvert(source, target, true);
 450        }
 451
 452        internal void ConvertValue(Type source, Type target)
 453        {
 454            InternalConvert(source, target, false);
 455        }
 456
 457        internal void Castclass(Type target)
 458        {
 459            if (codeGenTrace != CodeGenTrace.None)
 460            {
 461                EmitSourceInstruction("Castclass " + target);
 462            }
 463
 464            ilGen.Emit(OpCodes.Castclass, target);
 465        }
 466
 467        internal void Box(Type type)
 468        {
 469            if (codeGenTrace != CodeGenTrace.None)
 470            {
 471                EmitSourceInstruction("Box " + type);
 472            }
 473
 474            ilGen.Emit(OpCodes.Box, type);
 475        }
 476
 477        internal void Unbox(Type type)
 478        {
 479            if (codeGenTrace != CodeGenTrace.None)
 480            {
 481                EmitSourceInstruction("Unbox " + type);
 482            }
 483
 484            ilGen.Emit(OpCodes.Unbox, type);
 485        }
 486
 487        internal void Ldobj(Type type)
 488        {
 489            OpCode opCode = GetLdindOpCode(Type.GetTypeCode(type));
 490            if (!opCode.Equals(OpCodes.Nop))
 491            {
 492                if (codeGenTrace != CodeGenTrace.None)
 493                {
 494                    EmitSourceInstruction(opCode.ToString());
 495                }
 496
 497                ilGen.Emit(opCode);
 498            }
 499            else
 500            {
 501                if (codeGenTrace != CodeGenTrace.None)
 502                {
 503                    EmitSourceInstruction("Ldobj " + type);
 504                }
 505
 506                ilGen.Emit(OpCodes.Ldobj, type);
 507            }
 508        }
 509
 510        internal void Stobj(Type type)
 511        {
 512            if (codeGenTrace != CodeGenTrace.None)
 513            {
 514                EmitSourceInstruction("Stobj " + type);
 515            }
 516
 517            ilGen.Emit(OpCodes.Stobj, type);
 518        }
 519
 520        internal void Ldtoken(Type t)
 521        {
 522            if (codeGenTrace != CodeGenTrace.None)
 523            {
 524                EmitSourceInstruction("Ldtoken " + t);
 525            }
 526
 527            ilGen.Emit(OpCodes.Ldtoken, t);
 528        }
 529
 530        internal void Ldc(object o)
 531        {
 532            Type valueType = o.GetType();
 533            if (o is Type)
 534            {
 535                Ldtoken((Type)o);
 536                Call(GetTypeFromHandle);
 537            }
 538            else if (valueType.IsEnum)
 539            {
 540                if (codeGenTrace != CodeGenTrace.None)
 541                {
 542                    EmitSourceComment("Ldc " + o.GetType() + "." + o);
 543                }
 544
 545                Ldc(((IConvertible)o).ToType(Enum.GetUnderlyingType(valueType), null));
 546            }
 547            else
 548            {
 549                switch (Type.GetTypeCode(valueType))
 550                {
 551                    case TypeCode.Boolean:
 552                        Ldc((bool)o);
 553                        break;
 554                    case TypeCode.Char:
 555                        Ldc((int)(char)o);
 556                        break;
 557                    case TypeCode.SByte:
 558                    case TypeCode.Byte:
 559                    case TypeCode.Int16:
 560                    case TypeCode.UInt16:
 561                        Ldc(((IConvertible)o).ToInt32(CultureInfo.InvariantCulture));
 562                        break;
 563                    case TypeCode.Int32:
 564                        Ldc((int)o);
 565                        break;
 566                    case TypeCode.UInt32:
 567                        Ldc((int)(uint)o);
 568                        break;
 569                    case TypeCode.String:
 570                        Ldstr((string)o);
 571                        break;
 572                    case TypeCode.UInt64:
 573                    case TypeCode.Int64:
 574                    case TypeCode.Single:
 575                    case TypeCode.Double:
 576                    case TypeCode.Object:
 577                    case TypeCode.Decimal:
 578                    case TypeCode.DateTime:
 579                    case TypeCode.Empty:
 580                    case TypeCode.DBNull:
 581                    default:
 582                        throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenUnknownConstantType(valueType.FullName)));
 583                }
 584            }
 585        }
 586
 587        internal void Ldc(bool boolVar)
 588        {
 589            if (boolVar)
 590            {
 591                if (codeGenTrace != CodeGenTrace.None)
 592                {
 593                    EmitSourceInstruction("Ldc.i4 1");
 594                }
 595
 596                ilGen.Emit(OpCodes.Ldc_I4_1);
 597            }
 598            else
 599            {
 600                if (codeGenTrace != CodeGenTrace.None)
 601                {
 602                    EmitSourceInstruction("Ldc.i4 0");
 603                }
 604
 605                ilGen.Emit(OpCodes.Ldc_I4_0);
 606            }
 607        }
 608
 609        internal void Ldc(int intVar)
 610        {
 611            if (codeGenTrace != CodeGenTrace.None)
 612            {
 613                EmitSourceInstruction("Ldc.i4 " + intVar);
 614            }
 615
 616            switch (intVar)
 617            {
 618                case -1:
 619                    ilGen.Emit(OpCodes.Ldc_I4_M1);
 620                    break;
 621                case 0:
 622                    ilGen.Emit(OpCodes.Ldc_I4_0);
 623                    break;
 624                case 1:
 625                    ilGen.Emit(OpCodes.Ldc_I4_1);
 626                    break;
 627                case 2:
 628                    ilGen.Emit(OpCodes.Ldc_I4_2);
 629                    break;
 630                case 3:
 631                    ilGen.Emit(OpCodes.Ldc_I4_3);
 632                    break;
 633                case 4:
 634                    ilGen.Emit(OpCodes.Ldc_I4_4);
 635                    break;
 636                case 5:
 637                    ilGen.Emit(OpCodes.Ldc_I4_5);
 638                    break;
 639                case 6:
 640                    ilGen.Emit(OpCodes.Ldc_I4_6);
 641                    break;
 642                case 7:
 643                    ilGen.Emit(OpCodes.Ldc_I4_7);
 644                    break;
 645                case 8:
 646                    ilGen.Emit(OpCodes.Ldc_I4_8);
 647                    break;
 648                default:
 649                    ilGen.Emit(OpCodes.Ldc_I4, intVar);
 650                    break;
 651            }
 652        }
 653
 654        internal void Ldstr(string strVar)
 655        {
 656            if (codeGenTrace != CodeGenTrace.None)
 657            {
 658                EmitSourceInstruction("Ldstr " + strVar);
 659            }
 660
 661            ilGen.Emit(OpCodes.Ldstr, strVar);
 662        }
 663
 664        internal void LdlocAddress(LocalBuilder localBuilder)
 665        {
 666            if (localBuilder.LocalType.IsValueType)
 667            {
 668                Ldloca(localBuilder);
 669            }
 670            else
 671            {
 672                Ldloc(localBuilder);
 673            }
 674        }
 675
 676        internal void Ldloc(LocalBuilder localBuilder)
 677        {
 678            if (codeGenTrace != CodeGenTrace.None)
 679            {
 680                EmitSourceInstruction("Ldloc " + LocalNames[localBuilder]);
 681            }
 682
 683            ilGen.Emit(OpCodes.Ldloc, localBuilder);
 684            EmitStackTop(localBuilder.LocalType);
 685        }
 686
 687        internal void Stloc(LocalBuilder local)
 688        {
 689            if (codeGenTrace != CodeGenTrace.None)
 690            {
 691                EmitSourceInstruction("Stloc " + LocalNames[local]);
 692            }
 693
 694            EmitStackTop(local.LocalType);
 695            ilGen.Emit(OpCodes.Stloc, local);
 696        }
 697
 698        internal void Ldloc(int slot)
 699        {
 700            if (codeGenTrace != CodeGenTrace.None)
 701            {
 702                EmitSourceInstruction("Ldloc " + slot);
 703            }
 704
 705            switch (slot)
 706            {
 707                case 0:
 708                    ilGen.Emit(OpCodes.Ldloc_0);
 709                    break;
 710                case 1:
 711                    ilGen.Emit(OpCodes.Ldloc_1);
 712                    break;
 713                case 2:
 714                    ilGen.Emit(OpCodes.Ldloc_2);
 715                    break;
 716                case 3:
 717                    ilGen.Emit(OpCodes.Ldloc_3);
 718                    break;
 719                default:
 720                    if (slot <= 255)
 721                    {
 722                        ilGen.Emit(OpCodes.Ldloc_S, slot);
 723                    }
 724                    else
 725                    {
 726                        ilGen.Emit(OpCodes.Ldloc, slot);
 727                    }
 728
 729                    break;
 730            }
 731        }
 732
 733        internal void Stloc(int slot)
 734        {
 735            if (codeGenTrace != CodeGenTrace.None)
 736            {
 737                EmitSourceInstruction("Stloc " + slot);
 738            }
 739
 740            switch (slot)
 741            {
 742                case 0:
 743                    ilGen.Emit(OpCodes.Stloc_0);
 744                    break;
 745                case 1:
 746                    ilGen.Emit(OpCodes.Stloc_1);
 747                    break;
 748                case 2:
 749                    ilGen.Emit(OpCodes.Stloc_2);
 750                    break;
 751                case 3:
 752                    ilGen.Emit(OpCodes.Stloc_3);
 753                    break;
 754                default:
 755                    if (slot <= 255)
 756                    {
 757                        ilGen.Emit(OpCodes.Stloc_S, slot);
 758                    }
 759                    else
 760                    {
 761                        ilGen.Emit(OpCodes.Stloc, slot);
 762                    }
 763
 764                    break;
 765            }
 766        }
 767
 768        internal void Ldloca(LocalBuilder localBuilder)
 769        {
 770            if (codeGenTrace != CodeGenTrace.None)
 771            {
 772                EmitSourceInstruction("Ldloca " + LocalNames[localBuilder]);
 773            }
 774
 775            ilGen.Emit(OpCodes.Ldloca, localBuilder);
 776            EmitStackTop(localBuilder.LocalType);
 777        }
 778
 779        internal void Ldloca(int slot)
 780        {
 781            if (codeGenTrace != CodeGenTrace.None)
 782            {
 783                EmitSourceInstruction("Ldloca " + slot);
 784            }
 785
 786            if (slot <= 255)
 787            {
 788                ilGen.Emit(OpCodes.Ldloca_S, slot);
 789            }
 790            else
 791            {
 792                ilGen.Emit(OpCodes.Ldloca, slot);
 793            }
 794        }
 795
 796        internal void LdargAddress(ArgBuilder argBuilder)
 797        {
 798            if (argBuilder.ArgType.IsValueType)
 799            {
 800                Ldarga(argBuilder);
 801            }
 802            else
 803            {
 804                Ldarg(argBuilder);
 805            }
 806        }
 807
 808        internal void Ldarg(ArgBuilder arg)
 809        {
 810            Ldarg(arg.Index);
 811        }
 812
 813        internal void Starg(ArgBuilder arg)
 814        {
 815            Starg(arg.Index);
 816        }
 817
 818        internal void Ldarg(int slot)
 819        {
 820            if (codeGenTrace != CodeGenTrace.None)
 821            {
 822                EmitSourceInstruction("Ldarg " + slot);
 823            }
 824
 825            switch (slot)
 826            {
 827                case 0:
 828                    ilGen.Emit(OpCodes.Ldarg_0);
 829                    break;
 830                case 1:
 831                    ilGen.Emit(OpCodes.Ldarg_1);
 832                    break;
 833                case 2:
 834                    ilGen.Emit(OpCodes.Ldarg_2);
 835                    break;
 836                case 3:
 837                    ilGen.Emit(OpCodes.Ldarg_3);
 838                    break;
 839                default:
 840                    if (slot <= 255)
 841                    {
 842                        ilGen.Emit(OpCodes.Ldarg_S, slot);
 843                    }
 844                    else
 845                    {
 846                        ilGen.Emit(OpCodes.Ldarg, slot);
 847                    }
 848
 849                    break;
 850            }
 851        }
 852
 853        internal void Starg(int slot)
 854        {
 855            if (codeGenTrace != CodeGenTrace.None)
 856            {
 857                EmitSourceInstruction("Starg " + slot);
 858            }
 859
 860            if (slot <= 255)
 861            {
 862                ilGen.Emit(OpCodes.Starg_S, slot);
 863            }
 864            else
 865            {
 866                ilGen.Emit(OpCodes.Starg, slot);
 867            }
 868        }
 869
 870        internal void Ldarga(ArgBuilder argBuilder)
 871        {
 872            Ldarga(argBuilder.Index);
 873        }
 874
 875        internal void Ldarga(int slot)
 876        {
 877            if (codeGenTrace != CodeGenTrace.None)
 878            {
 879                EmitSourceInstruction("Ldarga " + slot);
 880            }
 881
 882            if (slot <= 255)
 883            {
 884                ilGen.Emit(OpCodes.Ldarga_S, slot);
 885            }
 886            else
 887            {
 888                ilGen.Emit(OpCodes.Ldarga, slot);
 889            }
 890        }
 891
 892        internal void Ldelem(Type arrayElementType)
 893        {
 894            if (arrayElementType.IsEnum)
 895            {
 896                Ldelem(Enum.GetUnderlyingType(arrayElementType));
 897            }
 898            else
 899            {
 900                OpCode opCode = GetLdelemOpCode(Type.GetTypeCode(arrayElementType));
 901                if (opCode.Equals(OpCodes.Nop))
 902                {
 903                    throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenArrayTypeIsNotSupported(arrayElementType.FullName)));
 904                }
 905
 906                if (codeGenTrace != CodeGenTrace.None)
 907                {
 908                    EmitSourceInstruction(opCode.ToString());
 909                }
 910
 911                ilGen.Emit(opCode);
 912                EmitStackTop(arrayElementType);
 913            }
 914        }
 915
 916        internal void Ldelema(Type arrayElementType)
 917        {
 918            OpCode opCode = OpCodes.Ldelema;
 919            if (codeGenTrace != CodeGenTrace.None)
 920            {
 921                EmitSourceInstruction(opCode.ToString());
 922            }
 923
 924            ilGen.Emit(opCode, arrayElementType);
 925
 926            EmitStackTop(arrayElementType);
 927        }
 928
 929        internal void Stelem(Type arrayElementType)
 930        {
 931            if (arrayElementType.IsEnum)
 932            {
 933                Stelem(Enum.GetUnderlyingType(arrayElementType));
 934            }
 935            else
 936            {
 937                OpCode opCode = this.GetStelemOpCode(Type.GetTypeCode(arrayElementType));
 938                if (opCode.Equals(OpCodes.Nop))
 939                {
 940                    throw Fx.Exception.AsError(
 941                        new InvalidOperationException(SR2.SFxCodeGenArrayTypeIsNotSupported(arrayElementType.FullName)));
 942                }
 943                if (this.codeGenTrace != CodeGenTrace.None)
 944                {
 945                    EmitSourceInstruction(opCode.ToString());
 946                }
 947                EmitStackTop(arrayElementType);
 948                ilGen.Emit(opCode);
 949            }
 950        }
 951
 952        internal Label DefineLabel()
 953        {
 954            return ilGen.DefineLabel();
 955        }
 956
 957        internal void MarkLabel(Label label)
 958        {
 959            ilGen.MarkLabel(label);
 960            if (codeGenTrace != CodeGenTrace.None)
 961            {
 962                EmitSourceLabel(label.GetHashCode() + ":");
 963            }
 964        }
 965
 966        internal void Ret()
 967        {
 968            if (codeGenTrace != CodeGenTrace.None)
 969            {
 970                EmitSourceInstruction("Ret");
 971            }
 972
 973            ilGen.Emit(OpCodes.Ret);
 974        }
 975
 976        internal void Br(Label label)
 977        {
 978            if (codeGenTrace != CodeGenTrace.None)
 979            {
 980                EmitSourceInstruction("Br " + label.GetHashCode());
 981            }
 982
 983            ilGen.Emit(OpCodes.Br, label);
 984        }
 985
 986        internal void Brfalse(Label label)
 987        {
 988            if (codeGenTrace != CodeGenTrace.None)
 989            {
 990                EmitSourceInstruction("Brfalse " + label.GetHashCode());
 991            }
 992
 993            ilGen.Emit(OpCodes.Brfalse, label);
 994        }
 995
 996        internal void Brtrue(Label label)
 997        {
 998            if (codeGenTrace != CodeGenTrace.None)
 999            {
1000                EmitSourceInstruction("Brtrue " + label.GetHashCode());
1001            }
1002
1003            ilGen.Emit(OpCodes.Brtrue, label);
1004        }
1005
1006        internal void Pop()
1007        {
1008            if (codeGenTrace != CodeGenTrace.None)
1009            {
1010                EmitSourceInstruction("Pop");
1011            }
1012
1013            ilGen.Emit(OpCodes.Pop);
1014        }
1015
1016        internal void Dup()
1017        {
1018            if (codeGenTrace != CodeGenTrace.None)
1019            {
1020                EmitSourceInstruction("Dup");
1021            }
1022
1023            ilGen.Emit(OpCodes.Dup);
1024        }
1025
1026        void InternalIf(bool negate)
1027        {
1028            IfState ifState = new IfState();
1029            ifState.EndIf = DefineLabel();
1030            ifState.ElseBegin = DefineLabel();
1031            if (negate)
1032            {
1033                Brtrue(ifState.ElseBegin);
1034            }
1035            else
1036            {
1037                Brfalse(ifState.ElseBegin);
1038            }
1039
1040            blockStack.Push(ifState);
1041        }
1042
1043        void InternalConvert(Type source, Type target, bool isAddress)
1044        {
1045            if (target == source)
1046            {
1047                return;
1048            }
1049
1050            if (target.IsValueType)
1051            {
1052                if (source.IsValueType)
1053                {
1054                    OpCode opCode = GetConvOpCode(Type.GetTypeCode(target));
1055                    if (opCode.Equals(OpCodes.Nop))
1056                    {
1057                        throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenNoConversionPossibleTo(target.FullName)));
1058                    }
1059                    else
1060                    {
1061                        if (codeGenTrace != CodeGenTrace.None)
1062                        {
1063                            EmitSourceInstruction(opCode.ToString());
1064                        }
1065
1066                        ilGen.Emit(opCode);
1067                    }
1068                }
1069                else if (source.IsAssignableFrom(target))
1070                {
1071                    Unbox(target);
1072                    if (!isAddress)
1073                    {
1074                        Ldobj(target);
1075                    }
1076                }
1077                else
1078                {
1079                    throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenIsNotAssignableFrom(target.FullName, source.FullName)));
1080                }
1081            }
1082            else if (target.IsPointer)
1083            {
1084                Call(UnboxPointer);
1085            }
1086            else if (source.IsPointer)
1087            {
1088                Load(source);
1089                Call(BoxPointer);
1090            }
1091            else if (target.IsAssignableFrom(source))
1092            {
1093                if (source.IsValueType)
1094                {
1095                    if (isAddress)
1096                    {
1097                        Ldobj(source);
1098                    }
1099
1100                    Box(source);
1101                }
1102            }
1103            else if (source.IsAssignableFrom(target))
1104            {
1105                //assert(source.IsValueType == false);
1106                Castclass(target);
1107            }
1108            else if (target.IsInterface || source.IsInterface)
1109            {
1110                Castclass(target);
1111            }
1112            else
1113            {
1114                throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenIsNotAssignableFrom(target.FullName, source.FullName)));
1115            }
1116        }
1117
1118        IfState PopIfState()
1119        {
1120            object stackTop = blockStack.Pop();
1121            IfState ifState = stackTop as IfState;
1122            if (ifState == null)
1123            {
1124                ThrowMismatchException(stackTop);
1125            }
1126
1127            return ifState;
1128        }
1129
1130#if USE_REFEMIT
1131        void InitAssemblyBuilder(string methodName)
1132        {
1133            //if (assemblyBuilder == null) {
1134            AssemblyName name = new AssemblyName();
1135            name.Name = "Microsoft.GeneratedCode."+methodName;
1136            bool saveAssembly = false;
1137
1138            if (codeGenTrace != CodeGenTrace.None)
1139                saveAssembly = true;
1140
1141            if (saveAssembly)
1142            {
1143                assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndSave);
1144                moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, name.Name + ".dll", false);
1145            }
1146            else
1147            {
1148                assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
1149                moduleBuilder = assemblyBuilder.DefineDynamicModule(name.Name, false);
1150            }
1151            //}
1152        }
1153#endif
1154
1155        void ThrowMismatchException(object expected)
1156        {
1157            throw Fx.Exception.AsError(new InvalidOperationException(SR2.SFxCodeGenExpectingEnd(expected.ToString())));
1158        }
1159
1160        Hashtable LocalNames
1161        {
1162            get
1163            {
1164                if (localNames == null)
1165                {
1166                    localNames = new Hashtable();
1167                }
1168
1169                return localNames;
1170            }
1171        }
1172
1173        OpCode GetConvOpCode(TypeCode typeCode)
1174        {
1175            switch (typeCode)
1176            {
1177                case TypeCode.Boolean:
1178                    return OpCodes.Conv_I1; // TypeCode.Boolean:
1179                case TypeCode.Char:
1180                    return OpCodes.Conv_I2; // TypeCode.Char:
1181                case TypeCode.SByte:
1182                    return OpCodes.Conv_I1; // TypeCode.SByte:
1183                case TypeCode.Byte:
1184                    return OpCodes.Conv_U1; // TypeCode.Byte:
1185                case TypeCode.Int16:
1186                    return OpCodes.Conv_I2; // TypeCode.Int16:
1187                case TypeCode.UInt16:
1188                    return OpCodes.Conv_U2; // TypeCode.UInt16:
1189                case TypeCode.Int32:
1190                    return OpCodes.Conv_I4; // TypeCode.Int32:
1191                case TypeCode.UInt32:
1192                    return OpCodes.Conv_U4; // TypeCode.UInt32:
1193                case TypeCode.Int64:
1194                    return OpCodes.Conv_I8; // TypeCode.Int64:
1195                case TypeCode.UInt64:
1196                    return OpCodes.Conv_I8; // TypeCode.UInt64:
1197                case TypeCode.Single:
1198                    return OpCodes.Conv_R4; // TypeCode.Single:
1199                case TypeCode.Double:
1200                    return OpCodes.Conv_R8; // TypeCode.Double:
1201                default:
1202                    return OpCodes.Nop;
1203            }
1204        }
1205
1206        OpCode GetLdindOpCode(TypeCode typeCode)
1207        {
1208            switch (typeCode)
1209            {
1210                case TypeCode.Boolean:
1211                    return OpCodes.Ldind_I1; // TypeCode.Boolean:
1212                case TypeCode.Char:
1213                    return OpCodes.Ldind_I2; // TypeCode.Char:
1214                case TypeCode.SByte:
1215                    return OpCodes.Ldind_I1; // TypeCode.SByte:
1216                case TypeCode.Byte:
1217                    return OpCodes.Ldind_U1; // TypeCode.Byte:
1218                case TypeCode.Int16:
1219                    return OpCodes.Ldind_I2; // TypeCode.Int16:
1220                case TypeCode.UInt16:
1221                    return OpCodes.Ldind_U2; // TypeCode.UInt16:
1222                case TypeCode.Int32:
1223                    return OpCodes.Ldind_I4; // TypeCode.Int32:
1224                case TypeCode.UInt32:
1225                    return OpCodes.Ldind_U4; // TypeCode.UInt32:
1226                case TypeCode.Int64:
1227                    return OpCodes.Ldind_I8; // TypeCode.Int64:
1228                case TypeCode.UInt64:
1229                    return OpCodes.Ldind_I8; // TypeCode.UInt64:
1230                case TypeCode.Single:
1231                    return OpCodes.Ldind_R4; // TypeCode.Single:
1232                case TypeCode.Double:
1233                    return OpCodes.Ldind_R8; // TypeCode.Double:
1234                case TypeCode.String:
1235                    return OpCodes.Ldind_Ref; // TypeCode.String:
1236                default:
1237                    return OpCodes.Nop;
1238            }
1239
1240            // REVIEW, stefanph: What's the type code for Ldind_I (natural int)?
1241        }
1242
1243        OpCode GetLdelemOpCode(TypeCode typeCode)
1244        {
1245            switch (typeCode)
1246            {
1247                case TypeCode.Object:
1248                    return OpCodes.Ldelem_Ref; // TypeCode.Object:
1249                case TypeCode.Boolean:
1250                    return OpCodes.Ldelem_I1; // TypeCode.Boolean:
1251                case TypeCode.Char:
1252                    return OpCodes.Ldelem_I2; // TypeCode.Char:
1253                case TypeCode.SByte:
1254                    return OpCodes.Ldelem_I1; // TypeCode.SByte:
1255                case TypeCode.Byte:
1256                    return OpCodes.Ldelem_U1; // TypeCode.Byte:
1257                case TypeCode.Int16:
1258                    return OpCodes.Ldelem_I2; // TypeCode.Int16:
1259                case TypeCode.UInt16:
1260                    return OpCodes.Ldelem_U2; // TypeCode.UInt16:
1261                case TypeCode.Int32:
1262                    return OpCodes.Ldelem_I4; // TypeCode.Int32:
1263                case TypeCode.UInt32:
1264                    return OpCodes.Ldelem_U4; // TypeCode.UInt32:
1265                case TypeCode.Int64:
1266                    return OpCodes.Ldelem_I8; // TypeCode.Int64:
1267                case TypeCode.UInt64:
1268                    return OpCodes.Ldelem_I8; // TypeCode.UInt64:
1269                case TypeCode.Single:
1270                    return OpCodes.Ldelem_R4; // TypeCode.Single:
1271                case TypeCode.Double:
1272                    return OpCodes.Ldelem_R8; // TypeCode.Double:
1273                case TypeCode.String:
1274                    return OpCodes.Ldelem_Ref; // TypeCode.String:
1275                default:
1276                    return OpCodes.Nop;
1277            }
1278        }
1279
1280        OpCode GetStelemOpCode(TypeCode typeCode)
1281        {
1282            switch (typeCode)
1283            {
1284                case TypeCode.Object:
1285                    return OpCodes.Stelem_Ref; // TypeCode.Object:
1286                case TypeCode.Boolean:
1287                    return OpCodes.Stelem_I1; // TypeCode.Boolean:
1288                case TypeCode.Char:
1289                    return OpCodes.Stelem_I2; // TypeCode.Char:
1290                case TypeCode.SByte:
1291                    return OpCodes.Stelem_I1; // TypeCode.SByte:
1292                case TypeCode.Byte:
1293                    return OpCodes.Stelem_I1; // TypeCode.Byte:
1294                case TypeCode.Int16:
1295                    return OpCodes.Stelem_I2; // TypeCode.Int16:
1296                case TypeCode.UInt16:
1297                    return OpCodes.Stelem_I2; // TypeCode.UInt16:
1298                case TypeCode.Int32:
1299                    return OpCodes.Stelem_I4; // TypeCode.Int32:
1300                case TypeCode.UInt32:
1301                    return OpCodes.Stelem_I4; // TypeCode.UInt32:
1302                case TypeCode.Int64:
1303                    return OpCodes.Stelem_I8; // TypeCode.Int64:
1304                case TypeCode.UInt64:
1305                    return OpCodes.Stelem_I8; // TypeCode.UInt64:
1306                case TypeCode.Single:
1307                    return OpCodes.Stelem_R4; // TypeCode.Single:
1308                case TypeCode.Double:
1309                    return OpCodes.Stelem_R8; // TypeCode.Double:
1310                case TypeCode.String:
1311                    return OpCodes.Stelem_Ref; // TypeCode.String:
1312                default:
1313                    return OpCodes.Nop;
1314            }
1315        }
1316
1317        internal void EmitSourceInstruction(string line)
1318        {
1319            EmitSourceLine("    " + line);
1320        }
1321
1322        internal void EmitSourceLabel(string line)
1323        {
1324            EmitSourceLine(line);
1325        }
1326
1327        internal void EmitSourceComment(string comment)
1328        {
1329            EmitSourceInstruction("// " + comment);
1330        }
1331
1332        internal void EmitSourceLine(string line)
1333        {
1334            if (codeGenTrace != CodeGenTrace.None)
1335            {
1336                OperationInvokerTrace.WriteInstruction(lineNo++, line);
1337            }
1338
1339            if (ilGen != null && codeGenTrace == CodeGenTrace.Tron)
1340            {
1341                ilGen.Emit(OpCodes.Ldstr, string.Format(CultureInfo.InvariantCulture, "{0:00000}: {1}", lineNo - 1, line));
1342                ilGen.Emit(OpCodes.Call, OperationInvokerTrace.TraceInstructionMethod);
1343            }
1344        }
1345
1346        internal void EmitStackTop(Type stackTopType)
1347        {
1348            if (codeGenTrace != CodeGenTrace.Tron)
1349            {
1350                return;
1351            }
1352
1353            codeGenTrace = CodeGenTrace.None;
1354            Dup();
1355            ToString(stackTopType);
1356            LocalBuilder topValue = DeclareLocal(typeof(string), "topValue");
1357            Store(topValue);
1358            Load("//value = ");
1359            Load(topValue);
1360            Concat2();
1361            Call(OperationInvokerTrace.TraceInstructionMethod);
1362            codeGenTrace = CodeGenTrace.Tron;
1363        }
1364
1365        internal void ToString(Type type)
1366        {
1367            if (type.IsValueType)
1368            {
1369                Box(type);
1370                Call(ObjectToString);
1371            }
1372            else
1373            {
1374                Dup();
1375                IfNot();
1376                Pop();
1377                Load("<null>");
1378                Else();
1379                Call(ObjectToString);
1380                EndIf();
1381            }
1382        }
1383
1384        internal void Concat2()
1385        {
1386            Call(StringConcat2);
1387        }
1388
1389        internal void LoadZeroValueIntoLocal(Type type, LocalBuilder local)
1390        {
1391            if (type.IsValueType)
1392            {
1393                switch (Type.GetTypeCode(type))
1394                {
1395                    case TypeCode.Boolean:
1396                    case TypeCode.Char:
1397                    case TypeCode.SByte:
1398                    case TypeCode.Byte:
1399                    case TypeCode.Int16:
1400                    case TypeCode.UInt16:
1401                    case TypeCode.Int32:
1402                    case TypeCode.UInt32:
1403                        ilGen.Emit(OpCodes.Ldc_I4_0);
1404                        Store(local);
1405                        break;
1406                    case TypeCode.Int64:
1407                    case TypeCode.UInt64:
1408                        ilGen.Emit(OpCodes.Ldc_I4_0);
1409                        ilGen.Emit(OpCodes.Conv_I8);
1410                        Store(local);
1411                        break;
1412                    case TypeCode.Single:
1413                        ilGen.Emit(OpCodes.Ldc_R4, 0.0F);
1414                        Store(local);
1415                        break;
1416                    case TypeCode.Double:
1417                        ilGen.Emit(OpCodes.Ldc_R8, 0.0);
1418                        Store(local);
1419                        break;
1420                    case TypeCode.Decimal:
1421                    case TypeCode.DateTime:
1422                    default:
1423                        LoadAddress(local);
1424                        InitObj(type);
1425                        break;
1426                }
1427            }
1428            else
1429            {
1430                Load(null);
1431                Store(local);
1432            }
1433        }
1434    }
1435
1436    internal class ArgBuilder
1437    {
1438        internal int Index;
1439
1440        internal Type ArgType;
1441        internal ArgBuilder(int index, Type argType)
1442        {
1443            this.Index = index;
1444            this.ArgType = argType;
1445        }
1446    }
1447
1448    internal class IfState
1449    {
1450        Label elseBegin;
1451        Label endIf;
1452
1453        internal Label EndIf
1454        {
1455            get
1456            {
1457                return this.endIf;
1458            }
1459
1460            set
1461            {
1462                this.endIf = value;
1463            }
1464        }
1465
1466        internal Label ElseBegin
1467        {
1468            get
1469            {
1470                return this.elseBegin;
1471            }
1472
1473            set
1474            {
1475                this.elseBegin = value;
1476            }
1477        }
1478    }
1479}
1480
1481