ilgenerator.cs

来自「没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没的 没」· CS 代码 · 共 1,729 行 · 第 1/3 页

CS
1,729
字号
/* * ILGenerator.cs - Implementation of "System.Reflection.Emit.ILGenerator"  * * Copyright (C) 2002  Southern Storm Software, Pty Ltd. *  * Contributions from Gopal.V <gopalv82@symonds.net>  *                    Rhys Weatherley <rweather@southern-storm.com.au> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#if CONFIG_REFLECTION_EMITnamespace System.Reflection.Emit{using System;using System.IO;using System.Diagnostics.SymbolStore;using System.Runtime.InteropServices;public class ILGenerator : IDetachItem{	// Internal state.	private ModuleBuilder module;	private byte[] code;	private int offset;	private int height;	private int maxHeight;	private LabelInfo[] labels;	private int numLabels;	private SignatureHelper locals;	private int numLocals;	private ExceptionTry exceptionStack;	private ExceptionTry exceptionList;	private ExceptionTry exceptionListEnd;	private TokenFixup tokenFixups;	// Information about a label in the current method.	private struct LabelInfo	{		public int       offset;		public int       height;		public LabelRef  refs;	}; // struct LabelInfo	// Reference information for back-patching a label.	private class LabelRef	{		public LabelRef	next;		public int		address;		public int		switchEnd;	}; // class LabelRef	// Information about a token fixup.	private class TokenFixup	{		public TokenFixup	next;		public int			offset;		public IntPtr		clrHandle;	}; // class TokenFixup	// Information about an exception try block.	private class ExceptionTry	{		public ExceptionTry		next;		public int				beginTry;		public int				endTry;		public int				endCatch;		public ExceptionClause	clauses;		public Label			endLabel;	}; // class ExceptionTry	// Clause types.	private const int Except_Catch   = 0;	private const int Except_Filter  = 1;	private const int Except_Finally = 2;	private const int Except_Fault   = 4;	// Information about an exception clause.	private class ExceptionClause	{		public ExceptionClause	prev;		public int				clauseType;		public int				beginClause;		public int				endClause;		public Type				classInfo;	}; // class ExceptionClause	// Constructor.	internal ILGenerator(ModuleBuilder module, int size)			{				this.module = module;				if(size < 16)				{					size = 16;				}				code = new byte [size];				offset = 0;				height = 0;				maxHeight = 0;				labels = null;				numLabels = 0;				locals = null;				exceptionStack = null;				exceptionList = null;				exceptionListEnd = null;				tokenFixups = null;				module.assembly.AddDetach(this);			}	private ILGenerator(ModuleBuilder module, byte[] explicitBody)			: this(module, explicitBody.Length)			{				Array.Copy(explicitBody, 0, code, 0, explicitBody.Length);				maxHeight = 8;			}	// Terminate the previous exception clause.	private void TerminateClause()			{				if(exceptionStack == null)				{					throw new NotSupportedException						(_("Emit_NeedExceptionBlock"));				}				if(exceptionStack.clauses == null)				{					// No clauses yet, so terminate the "try" part.					Emit(OpCodes.Leave, exceptionStack.endLabel);					exceptionStack.endTry = offset;					exceptionStack.endCatch = offset;				}				else				{					exceptionStack.clauses.endClause = offset;					switch(exceptionStack.clauses.clauseType)					{						case Except_Catch:						{							Emit(OpCodes.Leave, exceptionStack.endLabel);							exceptionStack.endCatch = offset;						}						break;						case Except_Filter:						{							Emit(OpCodes.Endfilter);						}						break;						case Except_Finally:						case Except_Fault:						{							Emit(OpCodes.Endfinally);						}						break;					}				}				height = 0;			}	// Begin a catch block on the current exception.	public virtual void BeginCatchBlock(Type exceptionType)			{				// Terminate the current clause.				TerminateClause();				// The operation is invalid if current is finally or fault.				if(exceptionStack.clauses != null)				{					if(exceptionStack.clauses.clauseType == Except_Finally ||					   exceptionStack.clauses.clauseType == Except_Fault)					{						throw new InvalidOperationException							(_("Emit_CatchAfterFinally"));					}				}				// Create a new clause information block.				ExceptionClause clause = new ExceptionClause();				clause.prev = exceptionStack.clauses;				clause.clauseType = Except_Catch;				clause.beginClause = offset;				clause.endClause = -1;				clause.classInfo = exceptionType;				exceptionStack.clauses = clause;			}	// Begin a filter block on the current exception.	public virtual void BeginExceptFilterBlock()			{				// Terminate the current clause.				TerminateClause();				// Create a new clause information block.				ExceptionClause clause = new ExceptionClause();				clause.prev = exceptionStack.clauses;				clause.clauseType = Except_Filter;				clause.beginClause = offset;				clause.endClause = -1;				clause.classInfo = null;				exceptionStack.clauses = clause;			}	// Begin the output of an exception block within the current method.	public virtual Label BeginExceptionBlock()			{				ExceptionTry tryBlock = new ExceptionTry();				tryBlock.next = exceptionStack;				tryBlock.beginTry = offset;				tryBlock.endTry = -1;				tryBlock.endCatch = -1;				tryBlock.clauses = null;				tryBlock.endLabel = DefineLabel();				exceptionStack = tryBlock;				return tryBlock.endLabel;			}	// Begin a fault block on the current exception.	public virtual void BeginFaultBlock()			{				// Terminate the current clause.				TerminateClause();				// The operation is invalid if current is finally or fault.				if(exceptionStack.clauses != null)				{					if(exceptionStack.clauses.clauseType == Except_Finally ||					   exceptionStack.clauses.clauseType == Except_Fault)					{						throw new InvalidOperationException							(_("Emit_CatchAfterFinally"));					}				}				// Create a new clause information block.				ExceptionClause clause = new ExceptionClause();				clause.prev = exceptionStack.clauses;				clause.clauseType = Except_Fault;				clause.beginClause = offset;				clause.endClause = -1;				clause.classInfo = null;				exceptionStack.clauses = clause;				height = 1;		// Top of stack is the exception object.				if(height > maxHeight)				{					maxHeight = height;				}			}	// Begin a finally block on the current exception.	public virtual void BeginFinallyBlock()			{				// Terminate the current clause.				TerminateClause();				// The operation is invalid if current is finally or fault.				if(exceptionStack.clauses != null)				{					if(exceptionStack.clauses.clauseType == Except_Finally ||					   exceptionStack.clauses.clauseType == Except_Fault)					{						throw new InvalidOperationException							(_("Emit_CatchAfterFinally"));					}				}				// Create a new clause information block.				ExceptionClause clause = new ExceptionClause();				clause.prev = exceptionStack.clauses;				clause.clauseType = Except_Finally;				clause.beginClause = offset;				clause.endClause = -1;				clause.classInfo = null;				exceptionStack.clauses = clause;				height = 1;		// Top of stack is the exception object.				if(height > maxHeight)				{					maxHeight = height;				}			}	// End the output of an exception block.	public virtual void EndExceptionBlock()			{				// Make sure that the request is legal.				ExceptionTry tryBlock = exceptionStack;				if(tryBlock == null)				{					throw new NotSupportedException						(_("Emit_NeedExceptionBlock"));				}				if(tryBlock.clauses == null)				{					throw new InvalidOperationException						(_("Emit_NoExceptionClauses"));				}				// Terminate the last clause in the list.				TerminateClause();				// Mark the label for the end of the exception block.				MarkLabel(tryBlock.endLabel);				// Add the exception to the end of the real block list.				exceptionStack = tryBlock.next;				tryBlock.next = null;				if(exceptionListEnd != null)				{					exceptionListEnd.next = tryBlock;				}				else				{					exceptionList = tryBlock;				}				exceptionListEnd = tryBlock;			}	// Enter a lexical naming scope for debug information.	public virtual void BeginScope()			{				// Scopes are not currently used in this implementation.			}	// Declare a local variable within the current method.	public LocalBuilder DeclareLocal(Type localType)			{				if(localType == null)				{					throw new ArgumentNullException("localType");				}				if(locals == null)				{					locals = SignatureHelper.GetLocalVarSigHelper(module);				}				locals.AddArgument(localType);				LocalBuilder builder = new LocalBuilder						(module, localType, numLocals);				++numLocals;				return builder;			}	// Declare a label within the current method.	public virtual Label DefineLabel()			{				if(labels == null)				{					labels = new LabelInfo [8];				}				else if(numLabels >= labels.Length)				{					LabelInfo[] newLabels = new LabelInfo [numLabels * 2];					Array.Copy(labels, 0, newLabels, 0, numLabels);					labels = newLabels;				}				return new Label(numLabels++);			}	// Emit a single byte to the current method's code.	private void EmitByte(int value)			{				if(offset >= code.Length)				{					byte[] newCode = new byte [code.Length * 2];					Array.Copy(code, 0, newCode, 0, code.Length);					code = newCode;				}				code[offset++] = (byte)value;			}	// Emit a token value to the current method's code.	private void EmitToken(int token)			{				EmitByte(token);				EmitByte(token >> 8);				EmitByte(token >> 16);				EmitByte(token >> 24);			}	// Emit a token value to the current method's code and register it	// to have a token fixup at the end of the assembly output process.	private void EmitTokenWithFixup(int token)			{				TokenFixup fixup = new TokenFixup();				fixup.next = tokenFixups;				fixup.offset = offset;				fixup.clrHandle = AssemblyBuilder.ClrGetItemFromToken						(module.assembly.privateData, token);				tokenFixups = fixup;				EmitByte(token);				EmitByte(token >> 8);				EmitByte(token >> 16);				EmitByte(token >> 24);			}	// Emit a raw opcode with no stack adjustments.	private void EmitRawOpcode(int value)			{				value &= 0xFFFF;				if(value < 0x0100)				{					EmitByte(value);				}				else				{					EmitByte(value >> 8);					EmitByte(value);				}			}	// Emit an opcode value to the current method's code and then	// adjust the stack height information accordingly.  We use a	// "ref" parameter to avoid unnecessary data copies in the	// methods that call this one.	private void EmitOpcode(ref OpCode opcode)			{				// Output the opcode to the instruction stream.				int value = (opcode.value & 0xFFFF);				if(value < 0x0100)				{					EmitByte(value);				}				else				{					EmitByte(value >> 8);					EmitByte(value);				}				// Adjust the stack requirements.				switch((StackBehaviour)(opcode.stackPop))				{					case StackBehaviour.Pop0:					case StackBehaviour.Varpop:						break;					case StackBehaviour.Pop1:					case StackBehaviour.Popi:					case StackBehaviour.Popref:						--height;						break;					case StackBehaviour.Pop1_pop1:					case StackBehaviour.Popi_pop1:					case StackBehaviour.Popi_popi:					case StackBehaviour.Popi_popi8:					case StackBehaviour.Popi_popr4:					case StackBehaviour.Popi_popr8:					case StackBehaviour.Popref_pop1:					case StackBehaviour.Popref_popi:						height -= 2;						break;					case StackBehaviour.Popi_popi_popi:					case StackBehaviour.Popref_popi_popi:					case StackBehaviour.Popref_popi_popi8:					case StackBehaviour.Popref_popi_popr4:					case StackBehaviour.Popref_popi_popr8:					case StackBehaviour.Popref_popi_popref:						height -= 3;						break;					default: break;				}				switch((StackBehaviour)(opcode.stackPush))				{					case StackBehaviour.Push0:						break;					case StackBehaviour.Push1:					case StackBehaviour.Pushi:					case StackBehaviour.Pushi8:					case StackBehaviour.Pushr4:					case StackBehaviour.Pushr8:					case StackBehaviour.Pushref:					case StackBehaviour.Varpush:						++height;						break;					case StackBehaviour.Push1_push1:						height += 2;						break;					default: break;				}				// Update the maximum stack height appropriately.				if(height > maxHeight)				{					maxHeight = height;				}				else if(height < 0)				{					height = 0;				}			}	// Emit simple opcodes.	public virtual void Emit(OpCode opcode)			{				EmitOpcode(ref opcode);			}	public virtual void Emit(OpCode opcode, byte val)			{				EmitOpcode(ref opcode);				EmitByte(val);			}	public virtual void Emit(OpCode opcode, short val)			{				EmitOpcode(ref opcode);				EmitByte(val);				EmitByte(val >> 8);			}	public virtual void Emit(OpCode opcode, int val)			{				EmitOpcode(ref opcode);				EmitByte(val);				EmitByte(val >> 8);				EmitByte(val >> 16);				EmitByte(val >> 24);			}	public virtual void Emit(OpCode opcode, long val)			{				EmitOpcode(ref opcode);				EmitByte((int)val);				EmitByte((int)(val >> 8));				EmitByte((int)(val >> 16));				EmitByte((int)(val >> 24));				EmitByte((int)(val >> 32));				EmitByte((int)(val >> 40));				EmitByte((int)(val >> 48));				EmitByte((int)(val >> 56));			}	[CLSCompliant(false)]	public void Emit(OpCode opcode, sbyte val)			{				EmitOpcode(ref opcode);				EmitByte(val);			}	public virtual void Emit(OpCode opcode, float val)			{				byte[] bytes;				EmitOpcode(ref opcode);				bytes = BitConverter.GetLittleEndianBytes(val);				EmitByte(bytes[0]);				EmitByte(bytes[1]);				EmitByte(bytes[2]);				EmitByte(bytes[3]);			}	public virtual void Emit(OpCode opcode, double val)			{				byte[] bytes;				EmitOpcode(ref opcode);				bytes = BitConverter.GetLittleEndianBytes(val);				EmitByte(bytes[0]);				EmitByte(bytes[1]);				EmitByte(bytes[2]);				EmitByte(bytes[3]);				EmitByte(bytes[4]);				EmitByte(bytes[5]);				EmitByte(bytes[6]);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?