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