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 + -
显示快捷键?