The Labs \ Source Viewer \ SSCLI \ System.Reflection.Emit \ __ExceptionInfo

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. namespace System.Reflection.Emit
  16. {
  17.     using System;
  18.     using TextWriter = System.IO.TextWriter;
  19.     using System.Diagnostics.SymbolStore;
  20.     using System.Runtime.InteropServices;
  21.     using System.Reflection;
  22.     using System.Security.Permissions;
  23.     using System.Globalization;
  24.    
  25.     [ClassInterface(ClassInterfaceType.None)]
  26.     [ComDefaultInterface(typeof(_ILGenerator))]
  27.     [System.Runtime.InteropServices.ComVisible(true)]
  28.     public class ILGenerator : _ILGenerator
  29.     {
  30.         #region Const Members
  31.         internal const byte PrefixInstruction = (byte)255;
  32.         internal const int defaultSize = 16;
  33.         internal const int DefaultFixupArraySize = 64;
  34.         internal const int DefaultLabelArraySize = 16;
  35.         internal const int DefaultExceptionArraySize = 8;
  36.         #endregion
  37.        
  38.         #region Internal Statics
  39.         static internal int[] EnlargeArray(int[] incoming)
  40.         {
  41.             int[] temp = new int[incoming.Length * 2];
  42.             Array.Copy(incoming, temp, incoming.Length);
  43.             return temp;
  44.         }
  45.        
  46.         static internal byte[] EnlargeArray(byte[] incoming)
  47.         {
  48.             byte[] temp = new byte[incoming.Length * 2];
  49.             Array.Copy(incoming, temp, incoming.Length);
  50.             return temp;
  51.         }
  52.        
  53.         static internal byte[] EnlargeArray(byte[] incoming, int requiredSize)
  54.         {
  55.             byte[] temp = new byte[requiredSize];
  56.             Array.Copy(incoming, temp, incoming.Length);
  57.             return temp;
  58.         }
  59.        
  60.         static internal __FixupData[] EnlargeArray(__FixupData[] incoming)
  61.         {
  62.             __FixupData[] temp = new __FixupData[incoming.Length * 2];
  63.             //Does arraycopy work for value classes?
  64.             Array.Copy(incoming, temp, incoming.Length);
  65.             return temp;
  66.         }
  67.        
  68.         static internal Type[] EnlargeArray(Type[] incoming)
  69.         {
  70.             Type[] temp = new Type[incoming.Length * 2];
  71.             Array.Copy(incoming, temp, incoming.Length);
  72.             return temp;
  73.         }
  74.        
  75.         static internal __ExceptionInfo[] EnlargeArray(__ExceptionInfo[] incoming)
  76.         {
  77.             __ExceptionInfo[] temp = new __ExceptionInfo[incoming.Length * 2];
  78.             Array.Copy(incoming, temp, incoming.Length);
  79.             return temp;
  80.         }
  81.        
  82.         static internal int CalculateNumberOfExceptions(__ExceptionInfo[] excp)
  83.         {
  84.             int num = 0;
  85.             if (excp == null)
  86.                 return 0;
  87.             for (int i = 0; i < excp.Length; i++)
  88.                 num += excp[i].GetNumberOfCatches();
  89.             return num;
  90.         }
  91.        
  92.         #endregion
  93.        
  94.         #region Internal Data Members
  95.         internal int m_length;
  96.         internal byte[] m_ILStream;
  97.        
  98.         internal int[] m_labelList;
  99.         internal int m_labelCount;
  100.        
  101.         internal __FixupData[] m_fixupData;
  102.         //internal Label[] m_fixupLabel;
  103.         //internal int[] m_fixupPos;
  104.        
  105.        
  106.        
  107.        
  108.         internal int m_fixupCount;
  109.        
  110.         internal int[] m_RVAFixupList;
  111.         internal int m_RVAFixupCount;
  112.        
  113.         internal int[] m_RelocFixupList;
  114.         internal int m_RelocFixupCount;
  115.        
  116.         internal int m_exceptionCount;
  117.         internal int m_currExcStackCount;
  118.         internal __ExceptionInfo[] m_exceptions;
  119.         //This is the list of all of the exceptions in this ILStream.
  120.         internal __ExceptionInfo[] m_currExcStack;
  121.         //This is the stack of exceptions which we're currently in.
  122.         internal ScopeTree m_ScopeTree;
  123.         // this variable tracks all debugging scope information
  124.         internal LineNumberInfo m_LineNumberInfo;
  125.         // this variable tracks all line number information
  126.         internal MethodInfo m_methodBuilder;
  127.         internal int m_localCount;
  128.         internal SignatureHelper m_localSignature;
  129.        
  130.         internal int m_maxStackSize = 0;
  131.         // Maximum stack size not counting the exceptions.
  132.         internal int m_maxMidStack = 0;
  133.         // Maximum stack size for a given basic block.
  134.         internal int m_maxMidStackCur = 0;
  135.         // Running count of the maximum stack size for the current basic block.
  136.         #endregion
  137.         #region Constructor
  138.         // package private constructor. This code path is used when client create
  139.         // ILGenerator through MethodBuilder.
  140.         internal ILGenerator(MethodInfo methodBuilder) : this(methodBuilder, 64)
  141.         {
  142.         }
  143.        
  144.         internal ILGenerator(MethodInfo methodBuilder, int size)
  145.         {
  146.             if (size < defaultSize) {
  147.                 m_ILStream = new byte[defaultSize];
  148.             }
  149.             else {
  150.                 m_ILStream = new byte[size];
  151.             }
  152.            
  153.             m_length = 0;
  154.            
  155.             m_labelCount = 0;
  156.             m_fixupCount = 0;
  157.             m_labelList = null;
  158.            
  159.             m_fixupData = null;
  160.            
  161.             m_exceptions = null;
  162.             m_exceptionCount = 0;
  163.             m_currExcStack = null;
  164.             m_currExcStackCount = 0;
  165.            
  166.             m_RelocFixupList = new int[DefaultFixupArraySize];
  167.             m_RelocFixupCount = 0;
  168.             m_RVAFixupList = new int[DefaultFixupArraySize];
  169.             m_RVAFixupCount = 0;
  170.            
  171.             // initialize the scope tree
  172.             m_ScopeTree = new ScopeTree();
  173.             m_LineNumberInfo = new LineNumberInfo();
  174.             m_methodBuilder = methodBuilder;
  175.            
  176.             // initialize local signature
  177.             m_localCount = 0;
  178.             MethodBuilder mb = m_methodBuilder as MethodBuilder;
  179.             if (mb == null)
  180.                 m_localSignature = SignatureHelper.GetLocalVarSigHelper(null);
  181.             else
  182.                 m_localSignature = SignatureHelper.GetLocalVarSigHelper(mb.GetTypeBuilder().Module);
  183.         }
  184.        
  185.         internal ILGenerator(int size)
  186.         {
  187.             if (size < defaultSize)
  188.                 m_ILStream = new byte[defaultSize];
  189.             else
  190.                 m_ILStream = new byte[size];
  191.             m_length = 0;
  192.            
  193.             m_labelCount = 0;
  194.             m_fixupCount = 0;
  195.             m_labelList = null;
  196.            
  197.             m_fixupData = null;
  198.            
  199.             m_exceptions = null;
  200.             m_exceptionCount = 0;
  201.             m_currExcStack = null;
  202.             m_currExcStackCount = 0;
  203.            
  204.             m_RelocFixupList = new int[DefaultFixupArraySize];
  205.             m_RelocFixupCount = 0;
  206.             m_RVAFixupList = new int[DefaultFixupArraySize];
  207.             m_RVAFixupCount = 0;
  208.            
  209.             // initialize the scope tree
  210.             m_ScopeTree = new ScopeTree();
  211.             m_LineNumberInfo = new LineNumberInfo();
  212.             m_methodBuilder = null;
  213.            
  214.             // initialize local signature
  215.             m_localCount = 0;
  216.             m_localSignature = SignatureHelper.GetLocalVarSigHelper(null);
  217.         }
  218.        
  219.         #endregion
  220.        
  221.         #region Private Members
  222.         private void RecordTokenFixup()
  223.         {
  224.             if (m_RelocFixupCount >= m_RelocFixupList.Length)
  225.                 m_RelocFixupList = EnlargeArray(m_RelocFixupList);
  226.            
  227.             m_RelocFixupList[m_RelocFixupCount++] = m_length;
  228.         }
  229.        
  230.         #endregion
  231.        
  232.         #region Internal Members
  233.         internal void InternalEmit(OpCode opcode)
  234.         {
  235.             if (opcode.m_size == 1) {
  236.                 m_ILStream[m_length++] = opcode.m_s2;
  237.             }
  238.             else {
  239.                 m_ILStream[m_length++] = opcode.m_s1;
  240.                 m_ILStream[m_length++] = opcode.m_s2;
  241.             }
  242.            
  243.             UpdateStackSize(opcode, opcode.StackChange());
  244.            
  245.         }
  246.        
  247.         internal void UpdateStackSize(OpCode opcode, int stackchange)
  248.         {
  249.             // Updates internal variables for keeping track of the stack size
  250.             // requirements for the function. stackchange specifies the amount
  251.             // by which the stacksize needs to be updated.
  252.            
  253.             // Special case for the Return. Returns pops 1 if there is a
  254.             // non-void return value.
  255.            
  256.            
  257.            
  258.            
  259.            
  260.            
  261.            
  262.            
  263.            
  264.             // Update the running stacksize. m_maxMidStack specifies the maximum
  265.             // amount of stack required for the current basic block irrespective of
  266.             // where you enter the block.
  267.             m_maxMidStackCur += stackchange;
  268.             if (m_maxMidStackCur > m_maxMidStack)
  269.                 m_maxMidStack = m_maxMidStackCur;
  270.             else if (m_maxMidStackCur < 0)
  271.                 m_maxMidStackCur = 0;
  272.            
  273.             // If the current instruction signifies end of a basic, which basically
  274.             // means an unconditional branch, add m_maxMidStack to m_maxStackSize.
  275.             // m_maxStackSize will eventually be the sum of the stack requirements for
  276.             // each basic block.
  277.             if (opcode.EndsUncondJmpBlk()) {
  278.                 m_maxStackSize += m_maxMidStack;
  279.                 m_maxMidStack = 0;
  280.                 m_maxMidStackCur = 0;
  281.             }
  282.         }
  283.        
  284.         internal virtual int GetMethodToken(MethodBase method, Type[] optionalParameterTypes)
  285.         {
  286.             int tk = 0;
  287.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  288.            
  289.             if (method.IsGenericMethod) {
  290.                 // Given M<Bar> unbind to M<S>
  291.                 MethodInfo methodInfoUnbound = method as MethodInfo;
  292.                
  293.                 if (!method.IsGenericMethodDefinition && method is MethodInfo)
  294.                     methodInfoUnbound = ((MethodInfo)method).GetGenericMethodDefinition();
  295.                
  296.                 if (methodInfoUnbound.Module != m_methodBuilder.Module || (methodInfoUnbound.DeclaringType != null && methodInfoUnbound.DeclaringType.IsGenericType))
  297.                     tk = GetMemberRefToken(methodInfoUnbound, null);
  298.                 else
  299.                     tk = modBuilder.GetMethodToken(methodInfoUnbound).Token;
  300.                
  301.                 // Create signature of method instantiation M<Bar>
  302.                 int sigLength;
  303.                 byte[] sigBytes = SignatureHelper.GetMethodSpecSigHelper(modBuilder, method.GetGenericArguments()).InternalGetSignature(out sigLength);
  304.                
  305.                 // Create MethodSepc M<Bar> with parent G?.M<S>
  306.                 tk = TypeBuilder.InternalDefineMethodSpec(tk, sigBytes, sigLength, modBuilder);
  307.             }
  308.             else {
  309.                 if (((method.CallingConvention & CallingConventions.VarArgs) == 0) && (method.DeclaringType == null || !method.DeclaringType.IsGenericType)) {
  310.                     if (method is MethodInfo)
  311.                         tk = modBuilder.GetMethodToken(method as MethodInfo).Token;
  312.                     else
  313.                         tk = modBuilder.GetConstructorToken(method as ConstructorInfo).Token;
  314.                 }
  315.                 else {
  316.                     tk = GetMemberRefToken(method, optionalParameterTypes);
  317.                 }
  318.             }
  319.            
  320.             return tk;
  321.         }
  322.        
  323.         internal virtual int GetMemberRefToken(MethodBase method, Type[] optionalParameterTypes)
  324.         {
  325.             Type[] parameterTypes;
  326.             Type returnType;
  327.             int tkParent;
  328.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  329.             int cGenericParameters = 0;
  330.            
  331.             if (method.IsGenericMethod) {
  332.                 if (!method.IsGenericMethodDefinition)
  333.                     throw new InvalidOperationException();
  334.                
  335.                 cGenericParameters = method.GetGenericArguments().Length;
  336.             }
  337.            
  338.             if (optionalParameterTypes != null) {
  339.                 if ((method.CallingConvention & CallingConventions.VarArgs) == 0) {
  340.                     // Client should not supply optional parameter in default calling convention
  341.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
  342.                 }
  343.             }
  344.            
  345.             if (method.DeclaringType.IsGenericType) {
  346.                 MethodBase methDef = null;
  347.                 // methodInfo = G<Foo>.M<Bar> ==> methDef = G<T>.M<S>
  348.                 if (method is MethodOnTypeBuilderInstantiation) {
  349.                     methDef = (method as MethodOnTypeBuilderInstantiation).m_method;
  350.                 }
  351.                 else if (method is ConstructorOnTypeBuilderInstantiation) {
  352.                     methDef = (method as ConstructorOnTypeBuilderInstantiation).m_ctor;
  353.                 }
  354.                 else if (method is MethodBuilder || method is ConstructorBuilder) {
  355.                     // methodInfo must be GenericMethodDefinition; trying to emit G<?>.M<S>
  356.                     methDef = method;
  357.                 }
  358.                 else if (method.IsGenericMethod) {
  359.                     methDef = ((MethodInfo)method).GetGenericMethodDefinition();
  360.                     methDef = methDef.Module.ResolveMethod(methDef.MetadataTokenInternal, methDef.GetGenericArguments(), methDef.DeclaringType != null ? methDef.DeclaringType.GetGenericArguments() : null) as MethodBase;
  361.                 }
  362.                 else {
  363.                     methDef = method;
  364.                     methDef = method.Module.ResolveMethod(method.MetadataTokenInternal, null, methDef.DeclaringType != null ? methDef.DeclaringType.GetGenericArguments() : null) as MethodBase;
  365.                 }
  366.                
  367.                 parameterTypes = methDef.GetParameterTypes();
  368.                 returnType = methDef.GetReturnType();
  369.             }
  370.             else {
  371.                 parameterTypes = method.GetParameterTypes();
  372.                 returnType = method.GetReturnType();
  373.             }
  374.            
  375.             if (method.DeclaringType.IsGenericType) {
  376.                 int length;
  377.                 byte[] sig = SignatureHelper.GetTypeSigToken(modBuilder, method.DeclaringType).InternalGetSignature(out length);
  378.                 tkParent = modBuilder.InternalGetTypeSpecTokenWithBytes(sig, length);
  379.             }
  380.             else if (method.Module != modBuilder) {
  381.                 // Use typeRef as parent because the method's declaringType lives in a different assembly
  382.                 tkParent = modBuilder.GetTypeToken(method.DeclaringType).Token;
  383.             }
  384.             else {
  385.                 // Use methodDef as parent because the method lives in this assembly and its declaringType has no generic arguments
  386.                 if (method is MethodInfo)
  387.                     tkParent = modBuilder.GetMethodToken(method as MethodInfo).Token;
  388.                 else
  389.                     tkParent = modBuilder.GetConstructorToken(method as ConstructorInfo).Token;
  390.             }
  391.            
  392.             int sigLength;
  393.             byte[] sigBytes = GetMemberRefSignature(method.CallingConvention, returnType, parameterTypes, optionalParameterTypes, cGenericParameters).InternalGetSignature(out sigLength);
  394.            
  395.             return modBuilder.InternalGetMemberRefFromSignature(tkParent, method.Name, sigBytes, sigLength);
  396.         }
  397.        
  398.         internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
  399.         {
  400.             return GetMemberRefSignature(call, returnType, parameterTypes, optionalParameterTypes, 0);
  401.         }
  402.        
  403.         internal virtual SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes, int cGenericParameters)
  404.         {
  405.             int cParams;
  406.             int i;
  407.             SignatureHelper sig;
  408.            
  409.             if (parameterTypes == null) {
  410.                 cParams = 0;
  411.             }
  412.             else {
  413.                 cParams = parameterTypes.Length;
  414.             }
  415.            
  416.             sig = SignatureHelper.GetMethodSigHelper(m_methodBuilder.Module, call, returnType, cGenericParameters);
  417.            
  418.             for (i = 0; i < cParams; i++)
  419.                 sig.AddArgument(parameterTypes[i]);
  420.            
  421.             if (optionalParameterTypes != null && optionalParameterTypes.Length != 0) {
  422.                 // add the sentinel
  423.                 sig.AddSentinel();
  424.                
  425.                 for (i = 0; i < optionalParameterTypes.Length; i++)
  426.                     sig.AddArgument(optionalParameterTypes[i]);
  427.             }
  428.            
  429.             return sig;
  430.         }
  431.        
  432.         internal virtual byte[] BakeByteArray()
  433.         {
  434.             // BakeByteArray is a package private function designed to be called by MethodDefinition to do
  435.             // all of the fixups and return a new byte array representing the byte stream with labels resolved, etc.
  436.             //
  437.            
  438.            
  439.             int newSize;
  440.             int updateAddr;
  441.             byte[] newBytes;
  442.            
  443.             if (m_currExcStackCount != 0) {
  444.                 throw new ArgumentException(Environment.GetResourceString("Argument_UnclosedExceptionBlock"));
  445.             }
  446.             if (m_length == 0)
  447.                 return null;
  448.            
  449.             //Calculate the size of the new array.
  450.             newSize = m_length;
  451.            
  452.             //Allocate space for the new array.
  453.             newBytes = new byte[newSize];
  454.            
  455.             //Copy the data from the old array
  456.             Array.Copy(m_ILStream, newBytes, newSize);
  457.            
  458.             //Do the fixups.
  459.             //This involves iterating over all of the labels and
  460.             //replacing them with their proper values.
  461.             for (int i = 0; i < m_fixupCount; i++) {
  462.                 updateAddr = GetLabelPos(m_fixupData[i].m_fixupLabel) - (m_fixupData[i].m_fixupPos + m_fixupData[i].m_fixupInstSize);
  463.                
  464.                 //Handle single byte instructions
  465.                 //Throw an exception if they're trying to store a jump in a single byte instruction that doesn't fit.
  466.                 if (m_fixupData[i].m_fixupInstSize == 1) {
  467.                    
  468.                     //Verify that our one-byte arg will fit into a Signed Byte.
  469.                     if (updateAddr < SByte.MinValue || updateAddr > SByte.MaxValue) {
  470.                        
  471.                         throw new NotSupportedException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("NotSupported_IllegalOneByteBranch"), m_fixupData[i].m_fixupPos, updateAddr));
  472.                     }
  473.                    
  474.                     //Place the one-byte arg
  475.                     if (updateAddr < 0) {
  476.                        
  477.                         newBytes[m_fixupData[i].m_fixupPos] = (byte)(256 + updateAddr);
  478.                     }
  479.                     else {
  480.                         newBytes[m_fixupData[i].m_fixupPos] = (byte)updateAddr;
  481.                     }
  482.                 }
  483.                 else {
  484.                     //Place the four-byte arg
  485.                     PutInteger4(updateAddr, m_fixupData[i].m_fixupPos, newBytes);
  486.                 }
  487.             }
  488.             return newBytes;
  489.         }
  490.        
  491.         internal virtual __ExceptionInfo[] GetExceptions()
  492.         {
  493.             __ExceptionInfo[] temp;
  494.             if (m_currExcStackCount != 0) {
  495.                 throw new NotSupportedException(Environment.GetResourceString(ResId.Argument_UnclosedExceptionBlock));
  496.             }
  497.            
  498.             if (m_exceptionCount == 0) {
  499.                 return null;
  500.             }
  501.            
  502.             temp = new __ExceptionInfo[m_exceptionCount];
  503.             Array.Copy(m_exceptions, temp, m_exceptionCount);
  504.             SortExceptions(temp);
  505.             return temp;
  506.         }
  507.        
  508.         internal virtual void EnsureCapacity(int size)
  509.         {
  510.             // Guarantees an array capable of holding at least size elements.
  511.             if (m_length + size >= m_ILStream.Length) {
  512.                 if (m_length + size >= 2 * m_ILStream.Length) {
  513.                     m_ILStream = EnlargeArray(m_ILStream, m_length + size);
  514.                 }
  515.                 else {
  516.                     m_ILStream = EnlargeArray(m_ILStream);
  517.                 }
  518.             }
  519.         }
  520.        
  521.         internal virtual int PutInteger4(int value, int startPos, byte[] array)
  522.         {
  523.             // Puts an Int32 onto the stream. This is an internal routine, so it does not do any error checking.
  524.            
  525.             array[startPos++] = (byte)value;
  526.             array[startPos++] = (byte)(value >> 8);
  527.             array[startPos++] = (byte)(value >> 16);
  528.             array[startPos++] = (byte)(value >> 24);
  529.             return startPos;
  530.         }
  531.        
  532.         internal virtual int GetLabelPos(Label lbl)
  533.         {
  534.             // Gets the position in the stream of a particular label.
  535.             // Verifies that the label exists and that it has been given a value.
  536.            
  537.             int index = lbl.GetLabelValue();
  538.            
  539.             if (index < 0 || index >= m_labelCount)
  540.                 throw new ArgumentException(Environment.GetResourceString("Argument_BadLabel"));
  541.            
  542.             if (m_labelList[index] < 0)
  543.                 throw new ArgumentException(Environment.GetResourceString("Argument_BadLabelContent"));
  544.            
  545.             return m_labelList[index];
  546.         }
  547.        
  548.         internal virtual void AddFixup(Label lbl, int pos, int instSize)
  549.         {
  550.             // Notes the label, position, and instruction size of a new fixup. Expands
  551.             // all of the fixup arrays as appropriate.
  552.            
  553.             if (m_fixupData == null) {
  554.                 m_fixupData = new __FixupData[DefaultFixupArraySize];
  555.             }
  556.            
  557.             if (m_fixupCount >= m_fixupData.Length) {
  558.                 m_fixupData = EnlargeArray(m_fixupData);
  559.             }
  560.            
  561.             m_fixupData[m_fixupCount].m_fixupPos = pos;
  562.             m_fixupData[m_fixupCount].m_fixupLabel = lbl;
  563.             m_fixupData[m_fixupCount].m_fixupInstSize = instSize;
  564.             m_fixupCount++;
  565.         }
  566.        
  567.         internal virtual int GetMaxStackSize()
  568.         {
  569.             MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
  570.             if (methodBuilder == null)
  571.                 throw new NotSupportedException();
  572.             return m_maxStackSize + methodBuilder.GetNumberOfExceptions();
  573.         }
  574.        
  575.         internal virtual void SortExceptions(__ExceptionInfo[] exceptions)
  576.         {
  577.            
  578.             int least;
  579.             __ExceptionInfo temp;
  580.             int length = exceptions.Length;
  581.             for (int i = 0; i < length; i++) {
  582.                 least = i;
  583.                 for (int j = i + 1; j < length; j++) {
  584.                     if (exceptions[least].IsInner(exceptions[j])) {
  585.                         least = j;
  586.                     }
  587.                 }
  588.                 temp = exceptions[i];
  589.                 exceptions[i] = exceptions[least];
  590.                 exceptions[least] = temp;
  591.             }
  592.         }
  593.        
  594.         internal virtual int[] GetTokenFixups()
  595.         {
  596.            
  597.             int[] narrowTokens = new int[m_RelocFixupCount];
  598.             Array.Copy(m_RelocFixupList, narrowTokens, m_RelocFixupCount);
  599.             return narrowTokens;
  600.         }
  601.        
  602.         internal virtual int[] GetRVAFixups()
  603.         {
  604.            
  605.             int[] narrowRVAs = new int[m_RVAFixupCount];
  606.             Array.Copy(m_RVAFixupList, narrowRVAs, m_RVAFixupCount);
  607.             return narrowRVAs;
  608.         }
  609.         #endregion
  610.        
  611.         #region Public Members
  612.        
  613.         #region Emit
  614.         public virtual void Emit(OpCode opcode)
  615.         {
  616.             EnsureCapacity(3);
  617.             InternalEmit(opcode);
  618.            
  619.         }
  620.        
  621.         public virtual void Emit(OpCode opcode, byte arg)
  622.         {
  623.             EnsureCapacity(4);
  624.             InternalEmit(opcode);
  625.             m_ILStream[m_length++] = arg;
  626.         }
  627.        
  628.         [CLSCompliant(false)]
  629.         public void Emit(OpCode opcode, sbyte arg)
  630.         {
  631.             // Puts opcode onto the stream of instructions followed by arg
  632.            
  633.             EnsureCapacity(4);
  634.             InternalEmit(opcode);
  635.             if (arg < 0) {
  636.                 m_ILStream[m_length++] = (byte)(256 + arg);
  637.             }
  638.             else {
  639.                 m_ILStream[m_length++] = (byte)arg;
  640.             }
  641.         }
  642.        
  643.         public virtual void Emit(OpCode opcode, short arg)
  644.         {
  645.             // Puts opcode onto the stream of instructions followed by arg
  646.             EnsureCapacity(5);
  647.             InternalEmit(opcode);
  648.             m_ILStream[m_length++] = (byte)arg;
  649.             m_ILStream[m_length++] = (byte)(arg >> 8);
  650.         }
  651.        
  652.         public virtual void Emit(OpCode opcode, int arg)
  653.         {
  654.             // Puts opcode onto the stream of instructions followed by arg
  655.             EnsureCapacity(7);
  656.             InternalEmit(opcode);
  657.             m_length = PutInteger4(arg, m_length, m_ILStream);
  658.         }
  659.        
  660.         public virtual void Emit(OpCode opcode, MethodInfo meth)
  661.         {
  662.             if (opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj)) {
  663.                 EmitCall(opcode, meth, null);
  664.             }
  665.             else {
  666.                 int stackchange = 0;
  667.                
  668.                 if (meth == null)
  669.                     throw new ArgumentNullException("meth");
  670.                
  671.                 int tk = GetMethodToken(meth, null);
  672.                
  673.                 EnsureCapacity(7);
  674.                 InternalEmit(opcode);
  675.                
  676.                 UpdateStackSize(opcode, stackchange);
  677.                 RecordTokenFixup();
  678.                 m_length = PutInteger4(tk, m_length, m_ILStream);
  679.             }
  680.         }
  681.        
  682.        
  683.         public virtual void EmitCalli(OpCode opcode, CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] optionalParameterTypes)
  684.         {
  685.             int stackchange = 0;
  686.             SignatureHelper sig;
  687.             if (optionalParameterTypes != null) {
  688.                 if ((callingConvention & CallingConventions.VarArgs) == 0) {
  689.                     // Client should not supply optional parameter in default calling convention
  690.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_NotAVarArgCallingConvention"));
  691.                 }
  692.             }
  693.            
  694.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  695.             sig = GetMemberRefSignature(callingConvention, returnType, parameterTypes, optionalParameterTypes);
  696.            
  697.             EnsureCapacity(7);
  698.             Emit(OpCodes.Calli);
  699.            
  700.             // The opcode passed in must be the calli instruction.
  701.             BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode passed to EmitCalli.");
  702.             // If there is a non-void return type, push one.
  703.             if (returnType != typeof(void))
  704.                 stackchange++;
  705.             // Pop off arguments if any.
  706.             if (parameterTypes != null)
  707.                 stackchange -= parameterTypes.Length;
  708.             // Pop off vararg arguments.
  709.             if (optionalParameterTypes != null)
  710.                 stackchange -= optionalParameterTypes.Length;
  711.             // Pop the this parameter if the method has a this parameter.
  712.             if ((callingConvention & CallingConventions.HasThis) == CallingConventions.HasThis)
  713.                 stackchange--;
  714.             // Pop the native function pointer.
  715.             stackchange--;
  716.             UpdateStackSize(opcode, stackchange);
  717.            
  718.             RecordTokenFixup();
  719.             m_length = PutInteger4(modBuilder.GetSignatureToken(sig).Token, m_length, m_ILStream);
  720.         }
  721.        
  722.         public virtual void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv, Type returnType, Type[] parameterTypes)
  723.         {
  724.             int stackchange = 0;
  725.             int cParams = 0;
  726.             int i;
  727.             SignatureHelper sig;
  728.            
  729.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  730.            
  731.             // The opcode passed in must be the calli instruction.
  732.             BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode passed to EmitCalli.");
  733.             if (parameterTypes != null) {
  734.                 cParams = parameterTypes.Length;
  735.             }
  736.            
  737.             sig = SignatureHelper.GetMethodSigHelper(modBuilder, unmanagedCallConv, returnType);
  738.            
  739.             if (parameterTypes != null) {
  740.                 for (i = 0; i < cParams; i++) {
  741.                     sig.AddArgument(parameterTypes[i]);
  742.                 }
  743.             }
  744.            
  745.             // If there is a non-void return type, push one.
  746.             if (returnType != typeof(void))
  747.                 stackchange++;
  748.            
  749.             // Pop off arguments if any.
  750.             if (parameterTypes != null)
  751.                 stackchange -= cParams;
  752.            
  753.             // Pop the native function pointer.
  754.             stackchange--;
  755.             UpdateStackSize(opcode, stackchange);
  756.            
  757.             EnsureCapacity(7);
  758.             Emit(OpCodes.Calli);
  759.             RecordTokenFixup();
  760.             m_length = PutInteger4(modBuilder.GetSignatureToken(sig).Token, m_length, m_ILStream);
  761.         }
  762.        
  763.         public virtual void EmitCall(OpCode opcode, MethodInfo methodInfo, Type[] optionalParameterTypes)
  764.         {
  765.             int stackchange = 0;
  766.            
  767.             if (methodInfo == null)
  768.                 throw new ArgumentNullException("methodInfo");
  769.            
  770.             int tk = GetMethodToken(methodInfo, optionalParameterTypes);
  771.            
  772.             EnsureCapacity(7);
  773.             InternalEmit(opcode);
  774.            
  775.             // The opcode must be one of call, callvirt, or newobj.
  776.             BCLDebug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj), "Unexpected opcode passed to EmitCall.");
  777.             // Push the return value if there is one.
  778.             if (methodInfo.GetReturnType() != typeof(void))
  779.                 stackchange++;
  780.             // Pop the parameters.
  781.             if (methodInfo.GetParameterTypes() != null)
  782.                 stackchange -= methodInfo.GetParameterTypes().Length;
  783.            
  784.             // Pop the this parameter if the method is non-static and the
  785.             // instruction is not newobj.
  786.             if (!(methodInfo is SymbolMethod) && methodInfo.IsStatic == false && !(opcode.Equals(OpCodes.Newobj)))
  787.                 stackchange--;
  788.             // Pop the optional parameters off the stack.
  789.             if (optionalParameterTypes != null)
  790.                 stackchange -= optionalParameterTypes.Length;
  791.             UpdateStackSize(opcode, stackchange);
  792.            
  793.             RecordTokenFixup();
  794.             m_length = PutInteger4(tk, m_length, m_ILStream);
  795.         }
  796.        
  797.         public virtual void Emit(OpCode opcode, SignatureHelper signature)
  798.         {
  799.             int stackchange = 0;
  800.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  801.             if (signature == null)
  802.                 throw new ArgumentNullException("signature");
  803.            
  804.             SignatureToken sig = modBuilder.GetSignatureToken(signature);
  805.            
  806.             int tempVal = sig.Token;
  807.            
  808.             EnsureCapacity(7);
  809.             InternalEmit(opcode);
  810.            
  811.             // The only IL instruction that has VarPop behaviour, that takes a
  812.             // Signature token as a parameter is calli. Pop the parameters and
  813.             // the native function pointer. To be conservative, do not pop the
  814.             // this pointer since this information is not easily derived from
  815.             // SignatureHelper.
  816.             if (opcode.m_pop == StackBehaviour.Varpop) {
  817.                 BCLDebug.Assert(opcode.Equals(OpCodes.Calli), "Unexpected opcode encountered for StackBehaviour VarPop.");
  818.                 // Pop the arguments..
  819.                 stackchange -= signature.ArgumentCount;
  820.                 // Pop native function pointer off the stack.
  821.                 stackchange--;
  822.                 UpdateStackSize(opcode, stackchange);
  823.             }
  824.            
  825.             RecordTokenFixup();
  826.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  827.         }
  828.        
  829.         [System.Runtime.InteropServices.ComVisible(true)]
  830.         public virtual void Emit(OpCode opcode, ConstructorInfo con)
  831.         {
  832.             int stackchange = 0;
  833.            
  834.             int tk = GetMethodToken(con, null);
  835.            
  836.             EnsureCapacity(7);
  837.             InternalEmit(opcode);
  838.            
  839.             // Make a conservative estimate by assuming a return type and no
  840.             // this parameter.
  841.             if (opcode.m_push == StackBehaviour.Varpush) {
  842.                 // Instruction must be one of call or callvirt.
  843.                 BCLDebug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt), "Unexpected opcode encountered for StackBehaviour of VarPush.");
  844.                 stackchange++;
  845.             }
  846.             if (opcode.m_pop == StackBehaviour.Varpop) {
  847.                 // Instruction must be one of call, callvirt or newobj.
  848.                 BCLDebug.Assert(opcode.Equals(OpCodes.Call) || opcode.Equals(OpCodes.Callvirt) || opcode.Equals(OpCodes.Newobj), "Unexpected opcode encountered for StackBehaviour of VarPop.");
  849.                
  850.                 if (con.GetParameterTypes() != null)
  851.                     stackchange -= con.GetParameterTypes().Length;
  852.             }
  853.             UpdateStackSize(opcode, stackchange);
  854.            
  855.             RecordTokenFixup();
  856.             m_length = PutInteger4(tk, m_length, m_ILStream);
  857.         }
  858.        
  859.         public virtual void Emit(OpCode opcode, Type cls)
  860.         {
  861.             // Puts opcode onto the stream and then the metadata token represented
  862.             // by cls. The location of cls is recorded so that the token can be
  863.             // patched if necessary when persisting the module to a PE.
  864.            
  865.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  866.             int tempVal = modBuilder.GetTypeToken(cls).Token;
  867.            
  868.             EnsureCapacity(7);
  869.             InternalEmit(opcode);
  870.             RecordTokenFixup();
  871.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  872.         }
  873.        
  874.         public virtual void Emit(OpCode opcode, long arg)
  875.         {
  876.             EnsureCapacity(11);
  877.             InternalEmit(opcode);
  878.             m_ILStream[m_length++] = (byte)arg;
  879.             m_ILStream[m_length++] = (byte)(arg >> 8);
  880.             m_ILStream[m_length++] = (byte)(arg >> 16);
  881.             m_ILStream[m_length++] = (byte)(arg >> 24);
  882.             m_ILStream[m_length++] = (byte)(arg >> 32);
  883.             m_ILStream[m_length++] = (byte)(arg >> 40);
  884.             m_ILStream[m_length++] = (byte)(arg >> 48);
  885.             m_ILStream[m_length++] = (byte)(arg >> 56);
  886.         }
  887.        
  888.         unsafe public virtual void Emit(OpCode opcode, float arg)
  889.         {
  890.             EnsureCapacity(7);
  891.             InternalEmit(opcode);
  892.             uint tempVal = *(uint*)&arg;
  893.             m_ILStream[m_length++] = (byte)tempVal;
  894.             m_ILStream[m_length++] = (byte)(tempVal >> 8);
  895.             m_ILStream[m_length++] = (byte)(tempVal >> 16);
  896.             m_ILStream[m_length++] = (byte)(tempVal >> 24);
  897.         }
  898.        
  899.         unsafe public virtual void Emit(OpCode opcode, double arg)
  900.         {
  901.             EnsureCapacity(11);
  902.             InternalEmit(opcode);
  903.             ulong tempVal = *(ulong*)&arg;
  904.             m_ILStream[m_length++] = (byte)tempVal;
  905.             m_ILStream[m_length++] = (byte)(tempVal >> 8);
  906.             m_ILStream[m_length++] = (byte)(tempVal >> 16);
  907.             m_ILStream[m_length++] = (byte)(tempVal >> 24);
  908.             m_ILStream[m_length++] = (byte)(tempVal >> 32);
  909.             m_ILStream[m_length++] = (byte)(tempVal >> 40);
  910.             m_ILStream[m_length++] = (byte)(tempVal >> 48);
  911.             m_ILStream[m_length++] = (byte)(tempVal >> 56);
  912.         }
  913.        
  914.         public virtual void Emit(OpCode opcode, Label label)
  915.         {
  916.             // Puts opcode onto the stream and leaves space to include label
  917.             // when fixups are done. Labels are created using ILGenerator.DefineLabel and
  918.             // their location within the stream is fixed by using ILGenerator.MarkLabel.
  919.             // If a single-byte instruction (designated by the _S suffix in OpCodes.cs) is used,
  920.             // the label can represent a jump of at most 127 bytes along the stream.
  921.             //
  922.             // opcode must represent a branch instruction (although we don't explicitly
  923.             // verify this). Since branches are relative instructions, label will be replaced with the
  924.             // correct offset to branch during the fixup process.
  925.            
  926.             int tempVal = label.GetLabelValue();
  927.             EnsureCapacity(7);
  928.            
  929.            
  930.             InternalEmit(opcode);
  931.             if (OpCodes.TakesSingleByteArgument(opcode)) {
  932.                 AddFixup(label, m_length, 1);
  933.                 m_length++;
  934.             }
  935.             else {
  936.                 AddFixup(label, m_length, 4);
  937.                 m_length += 4;
  938.             }
  939.         }
  940.        
  941.         public virtual void Emit(OpCode opcode, Label[] labels)
  942.         {
  943.             // Emitting a switch table
  944.            
  945.             int i;
  946.             int remaining;
  947.             // number of bytes remaining for this switch instruction to be substracted
  948.             // for computing the offset
  949.             int count = labels.Length;
  950.            
  951.             EnsureCapacity(count * 4 + 7);
  952.             InternalEmit(opcode);
  953.             m_length = PutInteger4(count, m_length, m_ILStream);
  954.             for (remaining = count * 4,i = 0; remaining > 0; remaining -= 4,i++) {
  955.                 AddFixup(labels[i], m_length, remaining);
  956.                 m_length += 4;
  957.             }
  958.         }
  959.        
  960.         public virtual void Emit(OpCode opcode, FieldInfo field)
  961.         {
  962.            
  963.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  964.             int tempVal = modBuilder.GetFieldToken(field).Token;
  965.             EnsureCapacity(7);
  966.             InternalEmit(opcode);
  967.             RecordTokenFixup();
  968.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  969.         }
  970.        
  971.         public virtual void Emit(OpCode opcode, string str)
  972.         {
  973.             // Puts the opcode onto the IL stream followed by the metadata token
  974.             // represented by str. The location of str is recorded for future
  975.             // fixups if the module is persisted to a PE.
  976.            
  977.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  978.             int tempVal = modBuilder.GetStringConstant(str).Token;
  979.             EnsureCapacity(7);
  980.             InternalEmit(opcode);
  981.             m_length = PutInteger4(tempVal, m_length, m_ILStream);
  982.         }
  983.        
  984.         public virtual void Emit(OpCode opcode, LocalBuilder local)
  985.         {
  986.             // Puts the opcode onto the IL stream followed by the information for local variable local.
  987.            
  988.             if (local == null) {
  989.                 throw new ArgumentNullException("local");
  990.             }
  991.             int tempVal = local.GetLocalIndex();
  992.             if (local.GetMethodBuilder() != m_methodBuilder) {
  993.                 throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchedMethodForLocal"), "local");
  994.             }
  995.             // If the instruction is a ldloc, ldloca a stloc, morph it to the optimal form.
  996.             if (opcode.Equals(OpCodes.Ldloc)) {
  997.                 switch (tempVal) {
  998.                     case 0:
  999.                         opcode = OpCodes.Ldloc_0;
  1000.                         break;
  1001.                     case 1:
  1002.                         opcode = OpCodes.Ldloc_1;
  1003.                         break;
  1004.                     case 2:
  1005.                         opcode = OpCodes.Ldloc_2;
  1006.                         break;
  1007.                     case 3:
  1008.                         opcode = OpCodes.Ldloc_3;
  1009.                         break;
  1010.                     default:
  1011.                         if (tempVal <= 255)
  1012.                             opcode = OpCodes.Ldloc_S;
  1013.                         break;
  1014.                 }
  1015.             }
  1016.             else if (opcode.Equals(OpCodes.Stloc)) {
  1017.                 switch (tempVal) {
  1018.                     case 0:
  1019.                         opcode = OpCodes.Stloc_0;
  1020.                         break;
  1021.                     case 1:
  1022.                         opcode = OpCodes.Stloc_1;
  1023.                         break;
  1024.                     case 2:
  1025.                         opcode = OpCodes.Stloc_2;
  1026.                         break;
  1027.                     case 3:
  1028.                         opcode = OpCodes.Stloc_3;
  1029.                         break;
  1030.                     default:
  1031.                         if (tempVal <= 255)
  1032.                             opcode = OpCodes.Stloc_S;
  1033.                         break;
  1034.                 }
  1035.             }
  1036.             else if (opcode.Equals(OpCodes.Ldloca)) {
  1037.                 if (tempVal <= 255)
  1038.                     opcode = OpCodes.Ldloca_S;
  1039.             }
  1040.            
  1041.             EnsureCapacity(7);
  1042.             InternalEmit(opcode);
  1043.            
  1044.             if (opcode.OperandType == OperandType.InlineNone)
  1045.                 return;
  1046.             else if (!OpCodes.TakesSingleByteArgument(opcode)) {
  1047.                 m_ILStream[m_length++] = (byte)tempVal;
  1048.                 m_ILStream[m_length++] = (byte)(tempVal >> 8);
  1049.             }
  1050.             else {
  1051.                 //Handle stloc_1, ldloc_1
  1052.                 if (tempVal > Byte.MaxValue) {
  1053.                     throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_BadInstructionOrIndexOutOfBound"));
  1054.                 }
  1055.                 m_ILStream[m_length++] = (byte)tempVal;
  1056.             }
  1057.         }
  1058.         #endregion
  1059.        
  1060.         #region Exceptions
  1061.         public virtual Label BeginExceptionBlock()
  1062.         {
  1063.             // Begin an Exception block. Creating an Exception block records some information,
  1064.             // but does not actually emit any IL onto the stream. Exceptions should be created and
  1065.             // marked in the following form:
  1066.             //
  1067.             // Emit Some IL
  1068.             // BeginExceptionBlock
  1069.             // Emit the IL which should appear within the "try" block
  1070.             // BeginCatchBlock
  1071.             // Emit the IL which should appear within the "catch" block
  1072.             // Optional: BeginCatchBlock (this can be repeated an arbitrary number of times
  1073.             // EndExceptionBlock
  1074.            
  1075.             // Delay init
  1076.             if (m_exceptions == null) {
  1077.                 m_exceptions = new __ExceptionInfo[DefaultExceptionArraySize];
  1078.             }
  1079.            
  1080.             if (m_currExcStack == null) {
  1081.                 m_currExcStack = new __ExceptionInfo[DefaultExceptionArraySize];
  1082.             }
  1083.            
  1084.             if (m_exceptionCount >= m_exceptions.Length) {
  1085.                 m_exceptions = EnlargeArray(m_exceptions);
  1086.             }
  1087.            
  1088.             if (m_currExcStackCount >= m_currExcStack.Length) {
  1089.                 m_currExcStack = EnlargeArray(m_currExcStack);
  1090.             }
  1091.            
  1092.             Label endLabel = DefineLabel();
  1093.             __ExceptionInfo exceptionInfo = new __ExceptionInfo(m_length, endLabel);
  1094.            
  1095.             // add the exception to the tracking list
  1096.             m_exceptions[m_exceptionCount++] = exceptionInfo;
  1097.            
  1098.             // Make this exception the current active exception
  1099.             m_currExcStack[m_currExcStackCount++] = exceptionInfo;
  1100.             return endLabel;
  1101.         }
  1102.        
  1103.         public virtual void EndExceptionBlock()
  1104.         {
  1105.             if (m_currExcStackCount == 0) {
  1106.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  1107.             }
  1108.            
  1109.             // Pop the current exception block
  1110.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  1111.             m_currExcStack[m_currExcStackCount - 1] = null;
  1112.             m_currExcStackCount--;
  1113.            
  1114.             Label endLabel = current.GetEndLabel();
  1115.             int state = current.GetCurrentState();
  1116.            
  1117.             if (state == __ExceptionInfo.State_Filter || state == __ExceptionInfo.State_Try) {
  1118.                
  1119.                
  1120.                 throw new InvalidOperationException(Environment.GetResourceString("Argument_BadExceptionCodeGen"));
  1121.             }
  1122.            
  1123.             if (state == __ExceptionInfo.State_Catch) {
  1124.                 this.Emit(OpCodes.Leave, endLabel);
  1125.             }
  1126.             else if (state == __ExceptionInfo.State_Finally || state == __ExceptionInfo.State_Fault) {
  1127.                 this.Emit(OpCodes.Endfinally);
  1128.             }
  1129.            
  1130.             //Check if we've alredy set this label.
  1131.             //The only reason why we might have set this is if we have a finally block.
  1132.             if (m_labelList[endLabel.GetLabelValue()] == -1) {
  1133.                 MarkLabel(endLabel);
  1134.             }
  1135.             else {
  1136.                 MarkLabel(current.GetFinallyEndLabel());
  1137.             }
  1138.            
  1139.             current.Done(m_length);
  1140.         }
  1141.        
  1142.         public virtual void BeginExceptFilterBlock()
  1143.         {
  1144.             // Begins a eception filter block. Emits a branch instruction to the end of the current exception block.
  1145.            
  1146.             if (m_currExcStackCount == 0)
  1147.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  1148.            
  1149.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  1150.            
  1151.             Label endLabel = current.GetEndLabel();
  1152.             this.Emit(OpCodes.Leave, endLabel);
  1153.            
  1154.             current.MarkFilterAddr(m_length);
  1155.         }
  1156.        
  1157.         public virtual void BeginCatchBlock(Type exceptionType)
  1158.         {
  1159.             // Begins a catch block. Emits a branch instruction to the end of the current exception block.
  1160.            
  1161.             if (m_currExcStackCount == 0) {
  1162.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  1163.             }
  1164.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  1165.            
  1166.             if (current.GetCurrentState() == __ExceptionInfo.State_Filter) {
  1167.                 if (exceptionType != null) {
  1168.                     throw new ArgumentException(Environment.GetResourceString("Argument_ShouldNotSpecifyExceptionType"));
  1169.                 }
  1170.                
  1171.                 this.Emit(OpCodes.Endfilter);
  1172.             }
  1173.             else {
  1174.                 // execute this branch if previous clause is Catch or Fault
  1175.                 if (exceptionType == null) {
  1176.                     throw new ArgumentNullException("exceptionType");
  1177.                 }
  1178.                
  1179.                 Label endLabel = current.GetEndLabel();
  1180.                 this.Emit(OpCodes.Leave, endLabel);
  1181.                
  1182.             }
  1183.            
  1184.             current.MarkCatchAddr(m_length, exceptionType);
  1185.         }
  1186.        
  1187.         public virtual void BeginFaultBlock()
  1188.         {
  1189.             if (m_currExcStackCount == 0) {
  1190.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  1191.             }
  1192.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  1193.            
  1194.             // emit the leave for the clause before this one.
  1195.             Label endLabel = current.GetEndLabel();
  1196.             this.Emit(OpCodes.Leave, endLabel);
  1197.            
  1198.             current.MarkFaultAddr(m_length);
  1199.         }
  1200.        
  1201.         public virtual void BeginFinallyBlock()
  1202.         {
  1203.             if (m_currExcStackCount == 0) {
  1204.                 throw new NotSupportedException(Environment.GetResourceString("Argument_NotInExceptionBlock"));
  1205.             }
  1206.             __ExceptionInfo current = m_currExcStack[m_currExcStackCount - 1];
  1207.             int state = current.GetCurrentState();
  1208.             Label endLabel = current.GetEndLabel();
  1209.             int catchEndAddr = 0;
  1210.             if (state != __ExceptionInfo.State_Try) {
  1211.                 // generate leave for any preceeding catch clause
  1212.                 this.Emit(OpCodes.Leave, endLabel);
  1213.                 catchEndAddr = m_length;
  1214.             }
  1215.            
  1216.             MarkLabel(endLabel);
  1217.            
  1218.            
  1219.             Label finallyEndLabel = this.DefineLabel();
  1220.             current.SetFinallyEndLabel(finallyEndLabel);
  1221.            
  1222.             // generate leave for try clause
  1223.             this.Emit(OpCodes.Leave, finallyEndLabel);
  1224.             if (catchEndAddr == 0)
  1225.                 catchEndAddr = m_length;
  1226.             current.MarkFinallyAddr(m_length, catchEndAddr);
  1227.         }
  1228.        
  1229.         #endregion
  1230.        
  1231.         #region Labels
  1232.         public virtual Label DefineLabel()
  1233.         {
  1234.             // Declares a new Label. This is just a token and does not yet represent any particular location
  1235.             // within the stream. In order to set the position of the label within the stream, you must call
  1236.             // Mark Label.
  1237.            
  1238.             // Delay init the lable array in case we dont use it
  1239.             if (m_labelList == null) {
  1240.                 m_labelList = new int[DefaultLabelArraySize];
  1241.             }
  1242.            
  1243.             if (m_labelCount >= m_labelList.Length) {
  1244.                 m_labelList = EnlargeArray(m_labelList);
  1245.             }
  1246.             m_labelList[m_labelCount] = -1;
  1247.             return new Label(m_labelCount++);
  1248.         }
  1249.        
  1250.         public virtual void MarkLabel(Label loc)
  1251.         {
  1252.             // Defines a label by setting the position where that label is found within the stream.
  1253.             // Does not allow a label to be defined more than once.
  1254.            
  1255.             int labelIndex = loc.GetLabelValue();
  1256.            
  1257.             //This should never happen.
  1258.             if (labelIndex < 0 || labelIndex >= m_labelList.Length) {
  1259.                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidLabel"));
  1260.             }
  1261.            
  1262.             if (m_labelList[labelIndex] != -1) {
  1263.                 throw new ArgumentException(Environment.GetResourceString("Argument_RedefinedLabel"));
  1264.             }
  1265.            
  1266.             m_labelList[labelIndex] = m_length;
  1267.         }
  1268.        
  1269.         #endregion
  1270.        
  1271.         #region IL Macros
  1272.         public virtual void ThrowException(Type excType)
  1273.         {
  1274.             // Emits the il to throw an exception
  1275.            
  1276.             if (excType == null) {
  1277.                 throw new ArgumentNullException("excType");
  1278.             }
  1279.            
  1280.             ModuleBuilder modBuilder = (ModuleBuilder)m_methodBuilder.Module;
  1281.            
  1282.             if (!excType.IsSubclassOf(typeof(Exception)) && excType != typeof(Exception)) {
  1283.                 throw new ArgumentException(Environment.GetResourceString("Argument_NotExceptionType"));
  1284.             }
  1285.             ConstructorInfo con = excType.GetConstructor(Type.EmptyTypes);
  1286.             if (con == null) {
  1287.                 throw new ArgumentException(Environment.GetResourceString("Argument_MissingDefaultConstructor"));
  1288.             }
  1289.             this.Emit(OpCodes.Newobj, con);
  1290.             this.Emit(OpCodes.Throw);
  1291.         }
  1292.        
  1293.         public virtual void EmitWriteLine(string value)
  1294.         {
  1295.             // Emits the IL to call Console.WriteLine with a string.
  1296.            
  1297.             Emit(OpCodes.Ldstr, value);
  1298.             Type[] parameterTypes = new Type[1];
  1299.             parameterTypes[0] = typeof(string);
  1300.             MethodInfo mi = typeof(Console).GetMethod("WriteLine", parameterTypes);
  1301.             Emit(OpCodes.Call, mi);
  1302.         }
  1303.        
  1304.         public virtual void EmitWriteLine(LocalBuilder localBuilder)
  1305.         {
  1306.             // Emits the IL necessary to call WriteLine with lcl. It is
  1307.             // an error to call EmitWriteLine with a lcl which is not of
  1308.             // one of the types for which Console.WriteLine implements overloads. (e.g.
  1309.             // we do *not* call ToString on the locals.
  1310.            
  1311.             object cls;
  1312.             if (m_methodBuilder == null) {
  1313.                 throw new ArgumentException(Environment.GetResourceString("InvalidOperation_BadILGeneratorUsage"));
  1314.             }
  1315.            
  1316.             MethodInfo prop = typeof(Console).GetMethod("get_Out");
  1317.             Emit(OpCodes.Call, prop);
  1318.             Emit(OpCodes.Ldloc, localBuilder);
  1319.             Type[] parameterTypes = new Type[1];
  1320.             cls = localBuilder.LocalType;
  1321.             if (cls is TypeBuilder || cls is EnumBuilder) {
  1322.                 throw new ArgumentException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder"));
  1323.             }
  1324.             parameterTypes[0] = (Type)cls;
  1325.             MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes);
  1326.             if (mi == null) {
  1327.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "localBuilder");
  1328.             }
  1329.            
  1330.             Emit(OpCodes.Callvirt, mi);
  1331.         }
  1332.        
  1333.         public virtual void EmitWriteLine(FieldInfo fld)
  1334.         {
  1335.             // Emits the IL necessary to call WriteLine with fld. It is
  1336.             // an error to call EmitWriteLine with a fld which is not of
  1337.             // one of the types for which Console.WriteLine implements overloads. (e.g.
  1338.             // we do *not* call ToString on the fields.
  1339.            
  1340.             object cls;
  1341.            
  1342.             if (fld == null) {
  1343.                 throw new ArgumentNullException("fld");
  1344.             }
  1345.            
  1346.             MethodInfo prop = typeof(Console).GetMethod("get_Out");
  1347.             Emit(OpCodes.Call, prop);
  1348.            
  1349.             if ((fld.Attributes & FieldAttributes.Static) != 0) {
  1350.                 Emit(OpCodes.Ldsfld, fld);
  1351.             }
  1352.             else {
  1353.                 Emit(OpCodes.Ldarg, (short)0);
  1354.                 //Load the this ref.
  1355.                 Emit(OpCodes.Ldfld, fld);
  1356.             }
  1357.             Type[] parameterTypes = new Type[1];
  1358.             cls = fld.FieldType;
  1359.             if (cls is TypeBuilder || cls is EnumBuilder) {
  1360.                 throw new NotSupportedException(Environment.GetResourceString("NotSupported_OutputStreamUsingTypeBuilder"));
  1361.             }
  1362.             parameterTypes[0] = (Type)cls;
  1363.             MethodInfo mi = typeof(TextWriter).GetMethod("WriteLine", parameterTypes);
  1364.             if (mi == null) {
  1365.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmitWriteLineType"), "fld");
  1366.             }
  1367.             Emit(OpCodes.Callvirt, mi);
  1368.         }
  1369.        
  1370.         #endregion
  1371.        
  1372.         #region Debug API
  1373.         public virtual LocalBuilder DeclareLocal(Type localType)
  1374.         {
  1375.             return DeclareLocal(localType, false);
  1376.         }
  1377.        
  1378.         public virtual LocalBuilder DeclareLocal(Type localType, bool pinned)
  1379.         {
  1380.             // Declare a local of type "local". The current active lexical scope
  1381.             // will be the scope that local will live.
  1382.            
  1383.             LocalBuilder localBuilder;
  1384.            
  1385.             MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
  1386.             if (methodBuilder == null)
  1387.                 throw new NotSupportedException();
  1388.            
  1389.             if (methodBuilder.IsTypeCreated()) {
  1390.                 // cannot change method after its containing type has been created
  1391.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_TypeHasBeenCreated"));
  1392.             }
  1393.            
  1394.             if (localType == null) {
  1395.                 throw new ArgumentNullException("localType");
  1396.             }
  1397.            
  1398.             if (methodBuilder.m_bIsBaked) {
  1399.                 throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_MethodBaked"));
  1400.             }
  1401.            
  1402.             // add the localType to local signature
  1403.             m_localSignature.AddArgument(localType, pinned);
  1404.            
  1405.             localBuilder = new LocalBuilder(m_localCount, localType, methodBuilder, pinned);
  1406.             m_localCount++;
  1407.             return localBuilder;
  1408.         }
  1409.        
  1410.         public virtual void UsingNamespace(string usingNamespace)
  1411.         {
  1412.             // Specifying the namespace to be used in evaluating locals and watches
  1413.             // for the current active lexical scope.
  1414.             int index;
  1415.            
  1416.             if (usingNamespace == null)
  1417.                 throw new ArgumentNullException("usingNamespace");
  1418.            
  1419.             if (usingNamespace.Length == 0)
  1420.                 throw new ArgumentException(Environment.GetResourceString("Argument_EmptyName"), "usingNamespace");
  1421.            
  1422.             MethodBuilder methodBuilder = m_methodBuilder as MethodBuilder;
  1423.             if (methodBuilder == null)
  1424.                 throw new NotSupportedException();
  1425.            
  1426.             index = methodBuilder.GetILGenerator().m_ScopeTree.GetCurrentActiveScopeIndex();
  1427.             if (index == -1) {
  1428.                 methodBuilder.m_localSymInfo.AddUsingNamespace(usingNamespace);
  1429.             }
  1430.             else {
  1431.                 m_ScopeTree.AddUsingNamespaceToCurrentScope(usingNamespace);
  1432.             }
  1433.         }
  1434.        
  1435.             // line number is 1 based
  1436.             // column is 0 based
  1437.             // line number is 1 based
  1438.         // column is 0 based
  1439.         public virtual void MarkSequencePoint(ISymbolDocumentWriter document, int startLine, int startColumn, int endLine, int endColumn)
  1440.         {
  1441.             if (startLine == 0 || startLine < 0 || endLine == 0 || endLine < 0) {
  1442.                 throw new ArgumentOutOfRangeException("startLine");
  1443.             }
  1444.             m_LineNumberInfo.AddLineNumberInfo(document, m_length, startLine, startColumn, endLine, endColumn);
  1445.         }
  1446.        
  1447.         public virtual void BeginScope()
  1448.         {
  1449.             m_ScopeTree.AddScopeInfo(ScopeAction.Open, m_length);
  1450.         }
  1451.        
  1452.         public virtual void EndScope()
  1453.         {
  1454.             m_ScopeTree.AddScopeInfo(ScopeAction.Close, m_length);
  1455.         }
  1456.        
  1457.         #endregion
  1458.        
  1459.         #endregion
  1460.        
  1461.         void _ILGenerator.GetTypeInfoCount(out uint pcTInfo)
  1462.         {
  1463.             throw new NotImplementedException();
  1464.         }
  1465.        
  1466.         void _ILGenerator.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo)
  1467.         {
  1468.             throw new NotImplementedException();
  1469.         }
  1470.        
  1471.         void _ILGenerator.GetIDsOfNames(        [In()]
  1472. ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
  1473.         {
  1474.             throw new NotImplementedException();
  1475.         }
  1476.        
  1477.         void _ILGenerator.Invoke(uint dispIdMember,         [In()]
  1478. ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
  1479.         {
  1480.             throw new NotImplementedException();
  1481.         }
  1482.     }
  1483.    
  1484.     internal struct __FixupData
  1485.     {
  1486.         internal Label m_fixupLabel;
  1487.         internal int m_fixupPos;
  1488.        
  1489.        
  1490.         internal int m_fixupInstSize;
  1491.        
  1492.     }
  1493.    
  1494.     internal class __ExceptionInfo
  1495.     {
  1496.        
  1497.         internal const int None = 0;
  1498.         //COR_ILEXCEPTION_CLAUSE_NONE
  1499.         internal const int Filter = 1;
  1500.         //COR_ILEXCEPTION_CLAUSE_FILTER
  1501.         internal const int Finally = 2;
  1502.         //COR_ILEXCEPTION_CLAUSE_FINALLY
  1503.         internal const int Fault = 4;
  1504.         //COR_ILEXCEPTION_CLAUSE_FAULT
  1505.         internal const int PreserveStack = 4;
  1506.         //COR_ILEXCEPTION_CLAUSE_PRESERVESTACK
  1507.         internal const int State_Try = 0;
  1508.         internal const int State_Filter = 1;
  1509.         internal const int State_Catch = 2;
  1510.         internal const int State_Finally = 3;
  1511.         internal const int State_Fault = 4;
  1512.         internal const int State_Done = 5;
  1513.        
  1514.         internal int m_startAddr;
  1515.         internal int[] m_filterAddr;
  1516.         internal int[] m_catchAddr;
  1517.         internal int[] m_catchEndAddr;
  1518.         internal int[] m_type;
  1519.         internal Type[] m_catchClass;
  1520.         internal Label m_endLabel;
  1521.         internal Label m_finallyEndLabel;
  1522.         internal int m_endAddr;
  1523.         internal int m_endFinally;
  1524.         internal int m_currentCatch;
  1525.        
  1526.         int m_currentState;
  1527.        
  1528.        
  1529.         //This will never get called. The values exist merely to keep the
  1530.         //compiler happy.
  1531.         private __ExceptionInfo()
  1532.         {
  1533.             m_startAddr = 0;
  1534.             m_filterAddr = null;
  1535.             m_catchAddr = null;
  1536.             m_catchEndAddr = null;
  1537.             m_endAddr = 0;
  1538.             m_currentCatch = 0;
  1539.             m_type = null;
  1540.             m_endFinally = -1;
  1541.             m_currentState = State_Try;
  1542.         }
  1543.        
  1544.         internal __ExceptionInfo(int startAddr, Label endLabel)
  1545.         {
  1546.             m_startAddr = startAddr;
  1547.             m_endAddr = -1;
  1548.             m_filterAddr = new int[4];
  1549.             m_catchAddr = new int[4];
  1550.             m_catchEndAddr = new int[4];
  1551.             m_catchClass = new Type[4];
  1552.             m_currentCatch = 0;
  1553.             m_endLabel = endLabel;
  1554.             m_type = new int[4];
  1555.             m_endFinally = -1;
  1556.             m_currentState = State_Try;
  1557.         }
  1558.        
  1559.             // the starting address of a clause
  1560.             // the end address of a previous catch clause. Only use when finally is following a catch
  1561.             // catch exception type
  1562.         // kind of clause
  1563.         private void MarkHelper(int catchorfilterAddr, int catchEndAddr, Type catchClass, int type)
  1564.         {
  1565.             if (m_currentCatch >= m_catchAddr.Length) {
  1566.                 m_filterAddr = ILGenerator.EnlargeArray(m_filterAddr);
  1567.                 m_catchAddr = ILGenerator.EnlargeArray(m_catchAddr);
  1568.                 m_catchEndAddr = ILGenerator.EnlargeArray(m_catchEndAddr);
  1569.                 m_catchClass = ILGenerator.EnlargeArray(m_catchClass);
  1570.                 m_type = ILGenerator.EnlargeArray(m_type);
  1571.             }
  1572.             if (type == Filter) {
  1573.                 m_type[m_currentCatch] = type;
  1574.                 m_filterAddr[m_currentCatch] = catchorfilterAddr;
  1575.                 m_catchAddr[m_currentCatch] = -1;
  1576.                 if (m_currentCatch > 0) {
  1577.                     BCLDebug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1");
  1578.                     m_catchEndAddr[m_currentCatch - 1] = catchorfilterAddr;
  1579.                 }
  1580.             }
  1581.             else {
  1582.                 // catch or Fault clause
  1583.                 m_catchClass[m_currentCatch] = catchClass;
  1584.                 if (m_type[m_currentCatch] != Filter) {
  1585.                     m_type[m_currentCatch] = type;
  1586.                 }
  1587.                 m_catchAddr[m_currentCatch] = catchorfilterAddr;
  1588.                 if (m_currentCatch > 0) {
  1589.                     if (m_type[m_currentCatch] != Filter) {
  1590.                         BCLDebug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1");
  1591.                         m_catchEndAddr[m_currentCatch - 1] = catchEndAddr;
  1592.                     }
  1593.                 }
  1594.                 m_catchEndAddr[m_currentCatch] = -1;
  1595.                 m_currentCatch++;
  1596.             }
  1597.            
  1598.             if (m_endAddr == -1) {
  1599.                 m_endAddr = catchorfilterAddr;
  1600.             }
  1601.         }
  1602.        
  1603.         internal virtual void MarkFilterAddr(int filterAddr)
  1604.         {
  1605.             m_currentState = State_Filter;
  1606.             MarkHelper(filterAddr, filterAddr, null, Filter);
  1607.         }
  1608.        
  1609.         internal virtual void MarkFaultAddr(int faultAddr)
  1610.         {
  1611.             m_currentState = State_Fault;
  1612.             MarkHelper(faultAddr, faultAddr, null, Fault);
  1613.         }
  1614.        
  1615.         internal virtual void MarkCatchAddr(int catchAddr, Type catchException)
  1616.         {
  1617.             m_currentState = State_Catch;
  1618.             MarkHelper(catchAddr, catchAddr, catchException, None);
  1619.         }
  1620.        
  1621.         internal virtual void MarkFinallyAddr(int finallyAddr, int endCatchAddr)
  1622.         {
  1623.             if (m_endFinally != -1) {
  1624.                 throw new ArgumentException(Environment.GetResourceString("Argument_TooManyFinallyClause"));
  1625.             }
  1626.             else {
  1627.                 m_currentState = State_Finally;
  1628.                 m_endFinally = finallyAddr;
  1629.             }
  1630.             MarkHelper(finallyAddr, endCatchAddr, null, Finally);
  1631.         }
  1632.        
  1633.         internal virtual void Done(int endAddr)
  1634.         {
  1635.             BCLDebug.Assert(m_currentCatch > 0, "m_currentCatch > 0");
  1636.             BCLDebug.Assert(m_catchAddr[m_currentCatch - 1] > 0, "m_catchAddr[m_currentCatch-1] > 0");
  1637.             BCLDebug.Assert(m_catchEndAddr[m_currentCatch - 1] == -1, "m_catchEndAddr[m_currentCatch-1] == -1");
  1638.             m_catchEndAddr[m_currentCatch - 1] = endAddr;
  1639.             m_currentState = State_Done;
  1640.         }
  1641.        
  1642.         internal virtual int GetStartAddress()
  1643.         {
  1644.             return m_startAddr;
  1645.         }
  1646.        
  1647.         internal virtual int GetEndAddress()
  1648.         {
  1649.             return m_endAddr;
  1650.         }
  1651.        
  1652.         internal virtual int GetFinallyEndAddress()
  1653.         {
  1654.             return m_endFinally;
  1655.         }
  1656.        
  1657.         internal virtual Label GetEndLabel()
  1658.         {
  1659.             return m_endLabel;
  1660.         }
  1661.        
  1662.         internal virtual int[] GetFilterAddresses()
  1663.         {
  1664.             return m_filterAddr;
  1665.         }
  1666.        
  1667.         internal virtual int[] GetCatchAddresses()
  1668.         {
  1669.             return m_catchAddr;
  1670.         }
  1671.        
  1672.         internal virtual int[] GetCatchEndAddresses()
  1673.         {
  1674.             return m_catchEndAddr;
  1675.         }
  1676.        
  1677.         internal virtual Type[] GetCatchClass()
  1678.         {
  1679.             return m_catchClass;
  1680.         }
  1681.        
  1682.         internal virtual int GetNumberOfCatches()
  1683.         {
  1684.             return m_currentCatch;
  1685.         }
  1686.        
  1687.         internal virtual int[] GetExceptionTypes()
  1688.         {
  1689.             return m_type;
  1690.         }
  1691.        
  1692.         internal virtual void SetFinallyEndLabel(Label lbl)
  1693.         {
  1694.             m_finallyEndLabel = lbl;
  1695.         }
  1696.        
  1697.         internal virtual Label GetFinallyEndLabel()
  1698.         {
  1699.             return m_finallyEndLabel;
  1700.         }
  1701.        
  1702.         // Specifies whether exc is an inner exception for "this". The way
  1703.         // its determined is by comparing the end address for the last catch
  1704.         // clause for both exceptions. If they're the same, the start address
  1705.         // for the exception is compared.
  1706.         // WARNING: This is not a generic function to determine the innerness
  1707.         // of an exception. This is somewhat of a mis-nomer. This gives a
  1708.         // random result for cases where the two exceptions being compared do
  1709.         // not having a nesting relation.
  1710.         internal bool IsInner(__ExceptionInfo exc)
  1711.         {
  1712.             BCLDebug.Assert(m_currentCatch > 0, "m_currentCatch > 0");
  1713.             BCLDebug.Assert(exc.m_currentCatch > 0, "exc.m_currentCatch > 0");
  1714.            
  1715.             int exclast = exc.m_currentCatch - 1;
  1716.             int last = m_currentCatch - 1;
  1717.            
  1718.             if (exc.m_catchEndAddr[exclast] < m_catchEndAddr[last])
  1719.                 return true;
  1720.             else if (exc.m_catchEndAddr[exclast] == m_catchEndAddr[last]) {
  1721.                 BCLDebug.Assert(exc.GetEndAddress() != GetEndAddress(), "exc.GetEndAddress() != GetEndAddress()");
  1722.                 if (exc.GetEndAddress() > GetEndAddress())
  1723.                     return true;
  1724.             }
  1725.             return false;
  1726.         }
  1727.        
  1728.         // 0 indicates in a try block
  1729.         // 1 indicates in a filter block
  1730.         // 2 indicates in a catch block
  1731.         // 3 indicates in a finally block
  1732.         // 4 indicates Done
  1733.         internal virtual int GetCurrentState()
  1734.         {
  1735.             return m_currentState;
  1736.         }
  1737.     }
  1738.    
  1739.    
  1740. /***************************
  1741.     *
  1742.     * Scope Tree is a class that track the scope structure within a method body
  1743.     * It keeps track two parallel array. m_ScopeAction keeps track the action. It can be
  1744.     * OpenScope or CloseScope. m_iOffset records the offset where the action
  1745.     * takes place.
  1746.     *
  1747.     ***************************/   
  1748.     [Serializable()]
  1749.     enum ScopeAction
  1750.     {
  1751.         Open = 0,
  1752.         Close = 1
  1753.     }
  1754.    
  1755.     internal class ScopeTree
  1756.     {
  1757.         internal ScopeTree()
  1758.         {
  1759.             // initialize data variables
  1760.             m_iOpenScopeCount = 0;
  1761.             m_iCount = 0;
  1762.         }
  1763.        
  1764. /***************************
  1765.         *
  1766.         * Find the current active lexcial scope. For example, if we have
  1767.         * "Open Open Open Close",
  1768.         * we will return 1 as the second BeginScope is currently active.
  1769.         *
  1770.         ***************************/       
  1771.         internal int GetCurrentActiveScopeIndex()
  1772.         {
  1773.             int cClose = 0;
  1774.             int i = m_iCount - 1;
  1775.            
  1776.             if (m_iCount == 0) {
  1777.                 return -1;
  1778.             }
  1779.             for (; cClose > 0 || m_ScopeActions[i] == ScopeAction.Close; i--) {
  1780.                 if (m_ScopeActions[i] == ScopeAction.Open) {
  1781.                     cClose--;
  1782.                 }
  1783.                 else
  1784.                     cClose++;
  1785.             }
  1786.            
  1787.             return i;
  1788.         }
  1789.        
  1790.         internal void AddLocalSymInfoToCurrentScope(string strName, byte[] signature, int slot, int startOffset, int endOffset)
  1791.         {
  1792.             int i = GetCurrentActiveScopeIndex();
  1793.             if (m_localSymInfos[i] == null) {
  1794.                 m_localSymInfos[i] = new LocalSymInfo();
  1795.             }
  1796.             m_localSymInfos[i].AddLocalSymInfo(strName, signature, slot, startOffset, endOffset);
  1797.         }
  1798.        
  1799.         internal void AddUsingNamespaceToCurrentScope(string strNamespace)
  1800.         {
  1801.             int i = GetCurrentActiveScopeIndex();
  1802.             if (m_localSymInfos[i] == null) {
  1803.                 m_localSymInfos[i] = new LocalSymInfo();
  1804.             }
  1805.             m_localSymInfos[i].AddUsingNamespace(strNamespace);
  1806.         }
  1807.        
  1808.         internal void AddScopeInfo(ScopeAction sa, int iOffset)
  1809.         {
  1810.             if (sa == ScopeAction.Close && m_iOpenScopeCount <= 0) {
  1811.                 throw new ArgumentException(Environment.GetResourceString("Argument_UnmatchingSymScope"));
  1812.             }
  1813.            
  1814.             // make sure that arrays are large enough to hold addition info
  1815.             EnsureCapacity();
  1816.            
  1817.            
  1818.            
  1819.            
  1820.             m_ScopeActions[m_iCount] = sa;
  1821.             m_iOffsets[m_iCount] = iOffset;
  1822.             m_localSymInfos[m_iCount] = null;
  1823.             m_iCount++;
  1824.             if (sa == ScopeAction.Open) {
  1825.                 m_iOpenScopeCount++;
  1826.             }
  1827.             else
  1828.                 m_iOpenScopeCount--;
  1829.            
  1830.         }
  1831.        
  1832. /**************************
  1833.         *
  1834.         * Helper to ensure arrays are large enough
  1835.         *
  1836.         **************************/       
  1837.         internal void EnsureCapacity()
  1838.         {
  1839.             if (m_iCount == 0) {
  1840.                 // First time. Allocate the arrays.
  1841.                 m_iOffsets = new int[InitialSize];
  1842.                 m_ScopeActions = new ScopeAction[InitialSize];
  1843.                 m_localSymInfos = new LocalSymInfo[InitialSize];
  1844.             }
  1845.             else if (m_iCount == m_iOffsets.Length) {
  1846.                
  1847.                 // the arrays are full. Enlarge the arrays
  1848.                 int[] temp = new int[m_iCount * 2];
  1849.                 Array.Copy(m_iOffsets, temp, m_iCount);
  1850.                 m_iOffsets = temp;
  1851.                
  1852.                 ScopeAction[] tempSA = new ScopeAction[m_iCount * 2];
  1853.                 Array.Copy(m_ScopeActions, tempSA, m_iCount);
  1854.                 m_ScopeActions = tempSA;
  1855.                
  1856.                 LocalSymInfo[] tempLSI = new LocalSymInfo[m_iCount * 2];
  1857.                 Array.Copy(m_localSymInfos, tempLSI, m_iCount);
  1858.                 m_localSymInfos = tempLSI;
  1859.                
  1860.             }
  1861.         }
  1862.        
  1863.         internal void EmitScopeTree(ISymbolWriter symWriter)
  1864.         {
  1865.             int i;
  1866.             for (i = 0; i < m_iCount; i++) {
  1867.                 if (m_ScopeActions[i] == ScopeAction.Open) {
  1868.                     symWriter.OpenScope(m_iOffsets[i]);
  1869.                 }
  1870.                 else {
  1871.                     symWriter.CloseScope(m_iOffsets[i]);
  1872.                 }
  1873.                 if (m_localSymInfos[i] != null) {
  1874.                     m_localSymInfos[i].EmitLocalSymInfo(symWriter);
  1875.                 }
  1876.             }
  1877.         }
  1878.        
  1879.         internal int[] m_iOffsets;
  1880.         // array of offsets
  1881.         internal ScopeAction[] m_ScopeActions;
  1882.         // array of scope actions
  1883.         internal int m_iCount;
  1884.         // how many entries in the arrays are occupied
  1885.         internal int m_iOpenScopeCount;
  1886.         // keep track how many scopes are open
  1887.         internal const int InitialSize = 16;
  1888.         internal LocalSymInfo[] m_localSymInfos;
  1889.         // keep track debugging local information
  1890.     }
  1891.    
  1892.    
  1893. /***************************
  1894.     *
  1895.     * This class tracks the line number info
  1896.     *
  1897.     ***************************/   
  1898.     internal class LineNumberInfo
  1899.     {
  1900.         internal LineNumberInfo()
  1901.         {
  1902.             // initialize data variables
  1903.             m_DocumentCount = 0;
  1904.             m_iLastFound = 0;
  1905.         }
  1906.        
  1907.         internal void AddLineNumberInfo(ISymbolDocumentWriter document, int iOffset, int iStartLine, int iStartColumn, int iEndLine, int iEndColumn)
  1908.         {
  1909.             int i;
  1910.            
  1911.             // make sure that arrays are large enough to hold addition info
  1912.             i = FindDocument(document);
  1913.            
  1914.             BCLDebug.Assert(i < m_DocumentCount, "Bad document look up!");
  1915.             m_Documents[i].AddLineNumberInfo(document, iOffset, iStartLine, iStartColumn, iEndLine, iEndColumn);
  1916.         }
  1917.        
  1918.         // Find a REDocument representing document. If we cannot find one, we will add a new entry into
  1919.         // the REDocument array.
  1920.         //
  1921.         internal int FindDocument(ISymbolDocumentWriter document)
  1922.         {
  1923.             int i;
  1924.            
  1925.             // This is an optimization. The chance that the previous line is coming from the same
  1926.             // document is very high.
  1927.             //
  1928.             if (m_iLastFound < m_DocumentCount && m_Documents[m_iLastFound] == document)
  1929.                 return m_iLastFound;
  1930.            
  1931.             for (i = 0; i < m_DocumentCount; i++) {
  1932.                 if (m_Documents[i].m_document == document) {
  1933.                     m_iLastFound = i;
  1934.                     return m_iLastFound;
  1935.                 }
  1936.             }
  1937.            
  1938.             // cannot find an existing document so add one to the array
  1939.             EnsureCapacity();
  1940.             m_iLastFound = m_DocumentCount;
  1941.             m_Documents[m_DocumentCount++] = new REDocument(document);
  1942.             return m_iLastFound;
  1943.         }
  1944.        
  1945. /**************************
  1946.         *
  1947.         * Helper to ensure arrays are large enough
  1948.         *
  1949.         **************************/       
  1950.         internal void EnsureCapacity()
  1951.         {
  1952.             if (m_DocumentCount == 0) {
  1953.                 // First time. Allocate the arrays.
  1954.                 m_Documents = new REDocument[InitialSize];
  1955.             }
  1956.             else if (m_DocumentCount == m_Documents.Length) {
  1957.                 // the arrays are full. Enlarge the arrays
  1958.                 REDocument[] temp = new REDocument[m_DocumentCount * 2];
  1959.                 Array.Copy(m_Documents, temp, m_DocumentCount);
  1960.                 m_Documents = temp;
  1961.             }
  1962.         }
  1963.        
  1964.         internal void EmitLineNumberInfo(ISymbolWriter symWriter)
  1965.         {
  1966.             for (int i = 0; i < m_DocumentCount; i++)
  1967.                 m_Documents[i].EmitLineNumberInfo(symWriter);
  1968.         }
  1969.        
  1970.         internal int m_DocumentCount;
  1971.         // how many documents that we have right now
  1972.         internal REDocument[] m_Documents;
  1973.         // array of documents
  1974.         internal const int InitialSize = 16;
  1975.         private int m_iLastFound;
  1976.     }
  1977.    
  1978.    
  1979. /***************************
  1980.     *
  1981.     * This class tracks the line number info
  1982.     *
  1983.     ***************************/   
  1984.     internal class REDocument
  1985.     {
  1986.         internal REDocument(ISymbolDocumentWriter document)
  1987.         {
  1988.             // initialize data variables
  1989.             m_iLineNumberCount = 0;
  1990.             m_document = document;
  1991.         }
  1992.        
  1993.         internal void AddLineNumberInfo(ISymbolDocumentWriter document, int iOffset, int iStartLine, int iStartColumn, int iEndLine, int iEndColumn)
  1994.         {
  1995.             BCLDebug.Assert(document == m_document, "Bad document look up!");
  1996.            
  1997.             // make sure that arrays are large enough to hold addition info
  1998.             EnsureCapacity();
  1999.            
  2000.             m_iOffsets[m_iLineNumberCount] = iOffset;
  2001.             m_iLines[m_iLineNumberCount] = iStartLine;
  2002.             m_iColumns[m_iLineNumberCount] = iStartColumn;
  2003.             m_iEndLines[m_iLineNumberCount] = iEndLine;
  2004.             m_iEndColumns[m_iLineNumberCount] = iEndColumn;
  2005.             m_iLineNumberCount++;
  2006.         }
  2007.        
  2008. /**************************
  2009.         *
  2010.         * Helper to ensure arrays are large enough
  2011.         *
  2012.         **************************/       
  2013.         internal void EnsureCapacity()
  2014.         {
  2015.             if (m_iLineNumberCount == 0) {
  2016.                 // First time. Allocate the arrays.
  2017.                 m_iOffsets = new int[InitialSize];
  2018.                 m_iLines = new int[InitialSize];
  2019.                 m_iColumns = new int[InitialSize];
  2020.                 m_iEndLines = new int[InitialSize];
  2021.                 m_iEndColumns = new int[InitialSize];
  2022.             }
  2023.             else if (m_iLineNumberCount == m_iOffsets.Length) {
  2024.                
  2025.                
  2026.                
  2027.                 // the arrays are full. Enlarge the arrays
  2028.                 int[] temp = new int[m_iLineNumberCount * 2];
  2029.                 Array.Copy(m_iOffsets, temp, m_iLineNumberCount);
  2030.                 m_iOffsets = temp;
  2031.                
  2032.                 temp = new int[m_iLineNumberCount * 2];
  2033.                 Array.Copy(m_iLines, temp, m_iLineNumberCount);
  2034.                 m_iLines = temp;
  2035.                
  2036.                 temp = new int[m_iLineNumberCount * 2];
  2037.                 Array.Copy(m_iColumns, temp, m_iLineNumberCount);
  2038.                 m_iColumns = temp;
  2039.                
  2040.                 temp = new int[m_iLineNumberCount * 2];
  2041.                 Array.Copy(m_iEndLines, temp, m_iLineNumberCount);
  2042.                 m_iEndLines = temp;
  2043.                
  2044.                 temp = new int[m_iLineNumberCount * 2];
  2045.                 Array.Copy(m_iEndColumns, temp, m_iLineNumberCount);
  2046.                 m_iEndColumns = temp;
  2047.             }
  2048.         }
  2049.        
  2050.         internal void EmitLineNumberInfo(ISymbolWriter symWriter)
  2051.         {
  2052.             int[] iOffsetsTemp;
  2053.             int[] iLinesTemp;
  2054.             int[] iColumnsTemp;
  2055.             int[] iEndLinesTemp;
  2056.             int[] iEndColumnsTemp;
  2057.            
  2058.             if (m_iLineNumberCount == 0)
  2059.                 return;
  2060.             // reduce the array size to be exact
  2061.             iOffsetsTemp = new int[m_iLineNumberCount];
  2062.             Array.Copy(m_iOffsets, iOffsetsTemp, m_iLineNumberCount);
  2063.            
  2064.             iLinesTemp = new int[m_iLineNumberCount];
  2065.             Array.Copy(m_iLines, iLinesTemp, m_iLineNumberCount);
  2066.            
  2067.             iColumnsTemp = new int[m_iLineNumberCount];
  2068.             Array.Copy(m_iColumns, iColumnsTemp, m_iLineNumberCount);
  2069.            
  2070.             iEndLinesTemp = new int[m_iLineNumberCount];
  2071.             Array.Copy(m_iEndLines, iEndLinesTemp, m_iLineNumberCount);
  2072.            
  2073.             iEndColumnsTemp = new int[m_iLineNumberCount];
  2074.             Array.Copy(m_iEndColumns, iEndColumnsTemp, m_iLineNumberCount);
  2075.            
  2076.             symWriter.DefineSequencePoints(m_document, iOffsetsTemp, iLinesTemp, iColumnsTemp, iEndLinesTemp, iEndColumnsTemp);
  2077.         }
  2078.        
  2079.         internal int[] m_iOffsets;
  2080.         // array of offsets
  2081.         internal int[] m_iLines;
  2082.         // array of offsets
  2083.         internal int[] m_iColumns;
  2084.         // array of offsets
  2085.         internal int[] m_iEndLines;
  2086.         // array of offsets
  2087.         internal int[] m_iEndColumns;
  2088.         // array of offsets
  2089.         internal ISymbolDocumentWriter m_document;
  2090.         // The ISymbolDocumentWriter that this REDocument is tracking.
  2091.         internal int m_iLineNumberCount;
  2092.         // how many entries in the arrays are occupied
  2093.         internal const int InitialSize = 16;
  2094.     }
  2095.     // end of REDocument
  2096. }
  2097. /*
  2098. methDef = methodInfo.GetGenericMethodDefinition();
  2099. int tk = methDef.MetadataTokenInternal;
  2100. foreach (MethodInfo m in methDef.DeclaringType.GetGenericTypeDefinition().GetMethods())
  2101. {
  2102.     if (m.MetadataTokenInternal == tk)
  2103.     {
  2104.         methDef = m;
  2105.         break;
  2106.     }
  2107. }
  2108. */

Developer Fusion