ilgenerator.cs

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

CS
1,729
字号
				EmitByte(bytes[7]);			}	public virtual void Emit(OpCode opcode, String val)			{				StringToken token = module.GetStringConstant(val);				EmitOpcode(ref opcode);				EmitToken(token.Token);			}	// Emit a call on a constructor.	public virtual void Emit(OpCode opcode, ConstructorInfo constructor)			{				// Bail out if "constructor" is null.				if(constructor == null)				{					throw new ArgumentNullException("constructor");				}				// Adjust the stack to account for the changes.				switch((StackBehaviour)(opcode.stackPop))				{					case StackBehaviour.Pop0:						break;					case StackBehaviour.Varpop:					{						if(constructor is ConstructorBuilder)						{							height -= ((ConstructorBuilder)constructor).numParams;						}						else						{							ParameterInfo[] paramList = constructor.GetParameters();							if(paramList != null)							{								height -= paramList.Length;							}						}					}					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;				}				if(height > maxHeight)				{					maxHeight = height;				}				else if(height < 0)				{					height = 0;				}				// Output the instruction.				MethodToken token = module.GetConstructorToken(constructor);				EmitRawOpcode(opcode.value);				EmitTokenWithFixup(token.Token);			}	// Emit a reference to a field	public virtual void Emit(OpCode opcode, FieldInfo field)			{				FieldToken token = module.GetFieldToken(field);				EmitOpcode(ref opcode);				EmitTokenWithFixup(token.Token);			}	// Emit code for a branch instruction.  Note: unlike other implementations,	// we always output the branch in such a way that an out of range error	// can never occur.  This makes it easier to process forward references	// in a single pass through the code.	public virtual void Emit(OpCode opcode, Label label)			{				int index = label.index;				int shortForm, longForm;				if(index < 0 || index >= numLabels)				{					return;				}				if((OperandType)(opcode.operandType) ==						OperandType.ShortInlineBrTarget)				{					// Convert a short opcode into its long form.					shortForm = opcode.value;					if(shortForm >= 0x2B && shortForm <= 0x37)					{						longForm = shortForm - 0x2B + 0x38;					}					else					{						longForm = 0xDD;					}				}				else if((OperandType)(opcode.operandType) ==							OperandType.InlineBrTarget)				{					// Convert a long opcode into its short form.					longForm = opcode.value;					if(longForm >= 0x38 && longForm <= 0x44)					{						shortForm = longForm + 0x2B - 0x38;					}					else					{						shortForm = 0xDE;					}				}				else				{					// Ignore non-branch opcodes.					return;				}				if(labels[index].offset != 0)				{					// The label is already defined.  Determine if the					// branch is long or short.					int dest = (labels[index].offset - 1) - (offset + 2);					if(dest >= -128 && dest <= 127)					{						EmitByte(shortForm);						EmitByte(dest);					}					else					{						dest = (labels[index].offset - 1) - (offset + 5);						EmitByte(longForm);						EmitByte(dest);						EmitByte(dest >> 8);						EmitByte(dest >> 16);						EmitByte(dest >> 24);					}				}				else				{					// Output the long form and add a reference to the label.					EmitByte(longForm);					EmitByte(0);					EmitByte(0);					EmitByte(0);					EmitByte(0);					LabelRef newRef = new LabelRef();					newRef.next = labels[index].refs;					newRef.address = offset - 4;					newRef.switchEnd = -1;					labels[index].refs = newRef;				}				switch((StackBehaviour)(opcode.stackPop))				{					case StackBehaviour.Popi:						--height;						break;					case StackBehaviour.Pop1_pop1:						height -= 2;						break;					default: break;				}			}	// Emit a switch statement.	public virtual void Emit(OpCode opcode, Label[] labels)			{				// Determine where the switch statement ends.				int switchEnd = offset + opcode.size + labels.Length * 4;				// Emit the opcode and the table length.				EmitOpcode(ref opcode);				EmitToken(labels.Length);				// Output the table of switch labels.				int posn;				Label label;				LabelInfo info;				LabelRef newRef;				for(posn = 0; posn < labels.Length; ++posn)				{					// Skip the label if it is invalid (shouldn't happen).					label = labels[posn];					if(label.index < 0 || label.index >= numLabels)					{						continue;					}					// Fetch the label information block.					info = this.labels[label.index];					// If it is already defined, output the offset now.					// Otherwise add a reference and output a placeholder.					if(info.offset != 0)					{						EmitToken(info.offset - switchEnd);					}					else					{						newRef = new LabelRef();						newRef.next = this.labels[label.index].refs;						newRef.address = offset;						newRef.switchEnd = switchEnd;						this.labels[label.index].refs = newRef;						EmitToken(0);					}				}			}	// Emit a reference to a local variable.	public virtual void Emit(OpCode opcode, LocalBuilder lbuilder)			{				// Validate the parameters.				if(lbuilder == null)				{					throw new ArgumentNullException("lbuilder");				}				// Determine if we can squash the instruction a bit more.				int index = lbuilder.index;				if(opcode.value == unchecked((short)0xFE0C)) // "ldloc"				{					if(index == 0)					{						opcode = OpCodes.Ldloc_0;					}					else if(index == 1)					{						opcode = OpCodes.Ldloc_1;					}					else if(index == 2)					{						opcode = OpCodes.Ldloc_2;					}					else if(index == 3)					{						opcode = OpCodes.Ldloc_3;					}					else if(index < 0x0100)					{						opcode = OpCodes.Ldloc_S;					}				}				else if(opcode.value == unchecked((short)0xFE0D)) // "ldloca"				{					if(index < 0x0100)					{						opcode = OpCodes.Ldloca_S;					}				}				else if(opcode.value == unchecked((short)0xFE0E)) // "stloc"				{					if(index == 0)					{						opcode = OpCodes.Stloc_0;					}					else if(index == 1)					{						opcode = OpCodes.Stloc_1;					}					else if(index == 2)					{						opcode = OpCodes.Stloc_2;					}					else if(index == 3)					{						opcode = OpCodes.Stloc_3;					}					else if(index < 0x0100)					{						opcode = OpCodes.Stloc_S;					}				}				// Output the instruction and its argument.				EmitOpcode(ref opcode);				if(opcode.operandType == (int)(OperandType.ShortInlineVar))				{					EmitByte(index);				}				else if(opcode.operandType == (int)(OperandType.InlineVar))				{					EmitByte(index);					EmitByte(index >> 8);				}			}	// Emit an instruction that refers to a method.	public virtual void Emit(OpCode opcode, MethodInfo method)			{				// Bail out if "method" is null.				if(method == null)				{					throw new ArgumentNullException("method");				}				// Adjust the stack to account for the changes.				switch((StackBehaviour)(opcode.stackPop))				{					case StackBehaviour.Pop0:						break;					case StackBehaviour.Varpop:					{						if(method is MethodBuilder)						{							height -= ((MethodBuilder)method).numParams;						}						else						{							ParameterInfo[] paramList = method.GetParameters();							if(paramList != null)							{								height -= paramList.Length;							}						}						if(!method.IsStatic && opcode.value != 0x73) // "newobj"						{							--height;						}					}					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:						++height;						break;					case StackBehaviour.Varpush:					{						if(method.ReturnType != typeof(void))						{							++height;						}					}					break;					case StackBehaviour.Push1_push1:						height += 2;						break;					default: break;				}				if(height > maxHeight)				{					maxHeight = height;				}				else if(height < 0)				{					height = 0;				}				// Output the instruction.				MethodToken token = module.GetMethodToken(method);				EmitRawOpcode(opcode.value);				EmitTokenWithFixup(token.Token);			}	// Emit an instruction that takes a signature token as an argument.	public virtual void Emit(OpCode opcode, SignatureHelper shelper)			{				// Emit the instruction.				SignatureToken token = module.GetSignatureToken(shelper);				EmitOpcode(ref opcode);				EmitToken(token.Token);				// Adjust the stack height for the "calli" instruction.				if(opcode.stackPop == (int)(StackBehaviour.Varpop))				{					height -= shelper.numArgs + 1;					if(height < 0)					{						height = 0;					}				}			}	// Emit an instruction that refers to a type.	public virtual void Emit(OpCode opcode, Type type)			{				TypeToken token = module.GetTypeToken(type);				EmitOpcode(ref opcode);				EmitTokenWithFixup(token.Token);			}	// Emit an instruction to call a method with vararg parameters.	public void EmitCall(OpCode opcode, MethodInfo methodInfo,						 Type[] optionalParamTypes)			{				// Call the method call directly if no optional parameters.				if(optionalParamTypes == null ||				   optionalParamTypes.Length == 0)				{					Emit(opcode, methodInfo);					return;				}				// Get the method's token, which takes care of importing.				MethodToken token = module.GetMethodToken(methodInfo);				// Make a copy of the method's signature and adjust it.				SignatureHelper helper =					SignatureHelper.GetMethodSigHelper(module, token);				helper.AddSentinel();				foreach(Type type in optionalParamTypes)				{					helper.AddArgument(type);				}				// Create a new token for the vararg member reference.				int refToken = MethodBuilder.ClrMethodCreateVarArgRef						(module.privateData, token.Token, helper.sig);				// Emit the raw instruction.				EmitRawOpcode(opcode.value);				EmitTokenWithFixup(refToken);				// Adjust the stack to account for the changes.				if(opcode.stackPush == (int)(StackBehaviour.Varpush))				{					if(methodInfo.ReturnType != typeof(void))					{						++height;					}				}				if(opcode.stackPop == (int)(StackBehaviour.Varpop))				{					height -= optionalParamTypes.Length;					if(methodInfo is MethodBuilder)					{						height -= ((MethodBuilder)methodInfo).numParams;					}					else					{						ParameterInfo[] paramList = methodInfo.GetParameters();						if(paramList != null)						{							height -= paramList.Length;						}					}					if(!methodInfo.IsStatic && opcode.value != 0x73) // "newobj"					{						--height;					}				}				if(height > maxHeight)				{					maxHeight = height;				}				else if(height < 0)				{					height = 0;				}			}	// Emit an indirect call instruction.	public void EmitCalli(OpCode opcode, CallingConventions callConv,						  Type returnType, Type[] paramTypes,						  Type[] optionalParamTypes)			{				// Check the calling convention.				if(optionalParamTypes != null)				{					if((callConv & CallingConventions.VarArgs) == 0)					{						throw new InvalidOperationException							(_("Emit_VarArgsWithNonVarArgMethod"));					}				}				// Build the full signature.				SignatureHelper helper =					SignatureHelper.GetMethodSigHelper						(module, callConv, (CallingConvention)0,						 returnType, paramTypes);				if(optionalParamTypes != null)				{					helper.AddSentinel();					foreach(Type type in optionalParamTypes)					{						helper.AddArgument(type);					}				}				// Emit the instruction using the constructed signature.				Emit(opcode, helper);			}	public void EmitCalli(OpCode opcode, CallingConvention unmanagedCallConv,						  Type returnType, Type[] paramTypes)			{				// Build the full signature.				SignatureHelper helper =					SignatureHelper.GetMethodSigHelper						(module, CallingConventions.Standard,						 unmanagedCallConv, returnType, paramTypes);

⌨️ 快捷键说明

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