static void CopyBranchStackSize(Instruction instruction, ref Dictionary<Instruction, int> stack_sizes, int stack_size) { if (stack_size == 0) return; switch (instruction.opcode.OperandType) { case OperandType.ShortInlineBrTarget: case OperandType.InlineBrTarget: { if (instruction.ResolveOperand != null) { instruction.Operand = instruction.ResolveOperand(instruction); } CopyBranchStackSize(ref stack_sizes, (Instruction) instruction.operand, stack_size); break; } case OperandType.InlineSwitch: var targets = (Instruction[]) instruction.operand; for (int i = 0; i < targets.Length; i++) CopyBranchStackSize (ref stack_sizes, targets [i], stack_size); break; } }
void WriteOperand(Instruction instruction) { var opcode = instruction.opcode; var operand_type = opcode.OperandType; if (operand_type == OperandType.InlineNone) return; var operand = instruction.operand; if (instruction.ResolveOperand != null) { operand = instruction.ResolveOperand(instruction); } if (operand == null) { throw new ArgumentException(); } switch (operand_type) { case OperandType.InlineSwitch: { var targets = (Instruction []) operand; WriteInt32 (targets.Length); var diff = instruction.Offset + opcode.Size + (4 * (targets.Length + 1)); for (int i = 0; i < targets.Length; i++) WriteInt32 (GetTargetOffset (targets [i]) - diff); break; } case OperandType.ShortInlineBrTarget: { var target = (Instruction) operand; WriteSByte ((sbyte) (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 1))); break; } case OperandType.InlineBrTarget: { var target = (Instruction) operand; WriteInt32 (GetTargetOffset (target) - (instruction.Offset + opcode.Size + 4)); break; } case OperandType.ShortInlineVar: WriteByte ((byte) GetVariableIndex ((VariableDefinition) operand)); break; case OperandType.ShortInlineArg: WriteByte ((byte) GetParameterIndex ((ParameterDefinition) operand)); break; case OperandType.InlineVar: WriteInt16 ((short) GetVariableIndex ((VariableDefinition) operand)); break; case OperandType.InlineArg: WriteInt16 ((short) GetParameterIndex ((ParameterDefinition) operand)); break; case OperandType.InlineSig: WriteMetadataToken (GetStandAloneSignature ((CallSite) operand)); break; case OperandType.ShortInlineI: if (opcode == OpCodes.Ldc_I4_S) WriteSByte ((sbyte) operand); else WriteByte ((byte) operand); break; case OperandType.InlineI: WriteInt32 ((int) operand); break; case OperandType.InlineI8: WriteInt64 ((long) operand); break; case OperandType.ShortInlineR: WriteSingle ((float) operand); break; case OperandType.InlineR: WriteDouble ((double) operand); break; case OperandType.InlineString: WriteMetadataToken ( new MetadataToken ( TokenType.String, GetUserStringIndex ((string) operand))); break; case OperandType.InlineType: case OperandType.InlineField: case OperandType.InlineMethod: case OperandType.InlineTok: WriteMetadataToken (metadata.LookupToken ((IMetadataTokenProvider) operand)); break; default: throw new ArgumentException (); } }
static void ComputeStackDelta(Instruction instruction, ref int stack_size) { if (instruction.ResolveOperand != null) { instruction.Operand = instruction.ResolveOperand(instruction); if (instruction.Operand == null) { throw new ApplicationException("Couldn't resolve instruction operand."); } } switch (instruction.opcode.FlowControl) { case FlowControl.Call: { var method = (IMethodSignature) instruction.operand; // pop 'this' argument if (method.HasImplicitThis() && instruction.opcode.Code != Code.Newobj) stack_size--; // pop normal arguments if (method.HasParameters) stack_size -= method.Parameters.Count; // pop function pointer if (instruction.opcode.Code == Code.Calli) stack_size--; // push return value if (method.ReturnType.etype != ElementType.Void || instruction.opcode.Code == Code.Newobj) stack_size++; break; } default: ComputePopDelta (instruction.opcode.StackBehaviourPop, ref stack_size); ComputePushDelta (instruction.opcode.StackBehaviourPush, ref stack_size); break; } }