private void TryOptimizeArgument(CilInstruction instruction) { var parameter = instruction.Operand as ParameterSignature; if (Method == null || Method.Signature == null || parameter == null) { return; } int index = Method.Signature.Parameters.IndexOf(parameter); if (index < 0 || index > byte.MaxValue) { return; } switch (instruction.OpCode.Code) { case CilCode.Ldarg: if (index <= 3) { instruction.OpCode = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldarg_0.Op2 + index]; instruction.Operand = null; } else { instruction.OpCode = CilOpCodes.Ldarg_S; } break; case CilCode.Ldarga: instruction.OpCode = CilOpCodes.Ldarga_S; break; } }
public static CilInstruction Create(CilOpCode code, CilInstruction instruction) { if (code.OperandType != CilOperandType.ShortInlineBrTarget && code.OperandType != CilOperandType.InlineBrTarget) { throw new ArgumentException("Opcode does not accept an instruction operand.", "code"); } return(new CilInstruction(0, code, instruction)); }
public string FormatInstruction(CilInstruction instruction) { string minimal = FormatLabel(instruction.Offset) + ": " + FormatOpCode(instruction.OpCode); return(instruction.Operand == null ? minimal : minimal + " " + FormatOperand(instruction.OpCode.OperandType, instruction.Operand)); }
private void TryOptimizeLdc(CilInstruction instruction) { int value = (int)instruction.Operand; if (value >= -1 && value <= 8) { instruction.OpCode = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldc_I4_0.Op2 + value]; instruction.Operand = null; } else if (value >= sbyte.MinValue && value <= sbyte.MaxValue) { instruction.OpCode = CilOpCodes.Ldc_I4_S; instruction.Operand = Convert.ToSByte(value); } }
private void TryOptimizeVariable(CilInstruction instruction) { var variable = instruction.Operand as VariableSignature; var localVarSig = Signature != null ? Signature.Signature as LocalVariableSignature : null; if (localVarSig == null || variable == null) { return; } int index = localVarSig.Variables.IndexOf(variable); if (index < 0 || index > byte.MaxValue) { return; } switch (instruction.OpCode.Code) { case CilCode.Ldloc: if (index <= 3) { instruction.OpCode = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldloc_0.Op2 + index]; instruction.Operand = null; } else { instruction.OpCode = CilOpCodes.Ldloc_S; } break; case CilCode.Ldloca: instruction.OpCode = CilOpCodes.Ldloca_S; break; case CilCode.Stloc: if (index <= 3) { instruction.OpCode = CilOpCodes.SingleByteOpCodes[CilOpCodes.Stloc_0.Op2 + index]; instruction.Operand = null; } else { instruction.OpCode = CilOpCodes.Stloc_S; } break; } }
private void OptimizeMacro(CilInstruction instruction) { switch (instruction.OpCode.OperandType) { case CilOperandType.InlineBrTarget: TryOptimizeBranch(instruction); break; case CilOperandType.InlineVar: TryOptimizeVariable(instruction); break; case CilOperandType.InlineArgument: TryOptimizeArgument(instruction); break; } if (instruction.OpCode.Code == CilCode.Ldc_I4) { TryOptimizeLdc(instruction); } }
private void TryOptimizeBranch(CilInstruction instruction) { CilInstruction operand = instruction.Operand as CilInstruction; int relativeOperand = operand.Offset - (instruction.Offset + 2); if (operand == null || relativeOperand < sbyte.MinValue || relativeOperand > sbyte.MaxValue) { return; } switch (instruction.OpCode.Code) { case CilCode.Br: instruction.OpCode = CilOpCodes.Br_S; break; case CilCode.Leave: instruction.OpCode = CilOpCodes.Leave_S; break; case CilCode.Brfalse: instruction.OpCode = CilOpCodes.Brfalse_S; break; case CilCode.Brtrue: instruction.OpCode = CilOpCodes.Brtrue_S; break; case CilCode.Beq: instruction.OpCode = CilOpCodes.Beq_S; break; case CilCode.Bge: instruction.OpCode = CilOpCodes.Bge_S; break; case CilCode.Bge_Un: instruction.OpCode = CilOpCodes.Bge_Un_S; break; case CilCode.Bgt: instruction.OpCode = CilOpCodes.Bgt_S; break; case CilCode.Bgt_Un: instruction.OpCode = CilOpCodes.Bgt_Un_S; break; case CilCode.Ble: instruction.OpCode = CilOpCodes.Ble_S; break; case CilCode.Ble_Un: instruction.OpCode = CilOpCodes.Ble_Un_S; break; case CilCode.Blt: instruction.OpCode = CilOpCodes.Blt_S; break; case CilCode.Blt_Un: instruction.OpCode = CilOpCodes.Blt_Un_S; break; case CilCode.Bne_Un: instruction.OpCode = CilOpCodes.Bne_Un_S; break; } }
private void ExpandMacro(CilInstruction instruction) { switch (instruction.OpCode.Code) { case CilCode.Br_S: instruction.OpCode = CilOpCodes.Br; break; case CilCode.Leave_S: instruction.OpCode = CilOpCodes.Leave; break; case CilCode.Brfalse_S: instruction.OpCode = CilOpCodes.Brfalse; break; case CilCode.Brtrue_S: instruction.OpCode = CilOpCodes.Brtrue; break; case CilCode.Beq_S: instruction.OpCode = CilOpCodes.Beq; break; case CilCode.Bge_S: instruction.OpCode = CilOpCodes.Bge; break; case CilCode.Bge_Un_S: instruction.OpCode = CilOpCodes.Bge_Un; break; case CilCode.Bgt_S: instruction.OpCode = CilOpCodes.Bgt; break; case CilCode.Bgt_Un_S: instruction.OpCode = CilOpCodes.Bgt_Un; break; case CilCode.Ble_S: instruction.OpCode = CilOpCodes.Ble; break; case CilCode.Ble_Un_S: instruction.OpCode = CilOpCodes.Ble_Un; break; case CilCode.Blt_S: instruction.OpCode = CilOpCodes.Blt; break; case CilCode.Blt_Un_S: instruction.OpCode = CilOpCodes.Blt_Un; break; case CilCode.Bne_Un_S: instruction.OpCode = CilOpCodes.Bne_Un; break; case CilCode.Ldloc_S: instruction.OpCode = CilOpCodes.Ldloc; break; case CilCode.Ldloca_S: instruction.OpCode = CilOpCodes.Ldloca; break; case CilCode.Ldloc_0: case CilCode.Ldloc_1: case CilCode.Ldloc_2: case CilCode.Ldloc_3: instruction.Operand = ((IOperandResolver)this).ResolveVariable(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48); instruction.OpCode = CilOpCodes.Ldloc; break; case CilCode.Stloc_S: instruction.OpCode = CilOpCodes.Stloc; break; case CilCode.Stloc_0: case CilCode.Stloc_1: case CilCode.Stloc_2: case CilCode.Stloc_3: instruction.Operand = ((IOperandResolver)this).ResolveVariable(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48); instruction.OpCode = CilOpCodes.Stloc; break; case CilCode.Ldarg_S: instruction.OpCode = CilOpCodes.Ldarg; break; case CilCode.Ldarga_S: instruction.OpCode = CilOpCodes.Ldarga; break; case CilCode.Ldarg_0: case CilCode.Ldarg_1: case CilCode.Ldarg_2: case CilCode.Ldarg_3: instruction.Operand = ((IOperandResolver)this).ResolveParameter(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48); instruction.OpCode = CilOpCodes.Ldarg; break; case CilCode.Starg_S: instruction.OpCode = CilOpCodes.Starg; break; case CilCode.Ldc_I4_0: case CilCode.Ldc_I4_1: case CilCode.Ldc_I4_2: case CilCode.Ldc_I4_3: case CilCode.Ldc_I4_4: case CilCode.Ldc_I4_5: case CilCode.Ldc_I4_6: case CilCode.Ldc_I4_7: case CilCode.Ldc_I4_8: instruction.Operand = instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48; instruction.OpCode = CilOpCodes.Ldc_I4; break; case CilCode.Ldc_I4_S: instruction.OpCode = CilOpCodes.Ldc_I4; break; case CilCode.Ldc_I4_M1: instruction.OpCode = CilOpCodes.Ldc_I4; instruction.Operand = -1; break; } }
private void ResolveOperand(IList <CilInstruction> instructions, CilInstruction current) { var nextOffset = current.Offset + current.Size; switch (current.OpCode.OperandType) { case CilOperandType.InlineArgument: case CilOperandType.ShortInlineArgument: var parameter = _resolver.ResolveParameter(Convert.ToInt32(current.Operand)); if (parameter != null) { current.Operand = parameter; } break; case CilOperandType.InlineVar: case CilOperandType.ShortInlineVar: var variable = _resolver.ResolveVariable(Convert.ToInt32(current.Operand)); if (variable != null) { current.Operand = variable; } break; case CilOperandType.ShortInlineBrTarget: case CilOperandType.InlineBrTarget: var targetInstruction = instructions.FirstOrDefault( x => x.Offset == nextOffset + Convert.ToInt32(current.Operand)); if (targetInstruction != null) { current.Operand = targetInstruction; } break; case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: var member = _resolver.ResolveMember((MetadataToken)current.Operand); if (member != null) { current.Operand = member; } break; case CilOperandType.InlineString: var stringValue = _resolver.ResolveString(((MetadataToken)current.Operand).ToUInt32()); if (stringValue != null) { current.Operand = stringValue; } break; case CilOperandType.InlineSwitch: var targetOffsets = (IList <int>)current.Operand; var targets = new List <CilInstruction>(targetOffsets.Count); for (int i = 0; i < targetOffsets.Count; i++) { targets.Add(instructions.FirstOrDefault( x => x.Offset == nextOffset + targetOffsets[i])); } current.Operand = targets; break; } }
/// <summary> /// Writes the operand of the instruction to the output stream. /// </summary> /// <param name="instruction"></param> /// <exception cref="InvalidOperationException"></exception> private void WriteOperand(CilInstruction instruction) { switch (instruction.OpCode.OperandType) { case CilOperandType.InlineArgument: _writer.WriteUInt16((ushort)_builder.GetParameterIndex(instruction.Operand as ParameterSignature)); break; case CilOperandType.ShortInlineArgument: _writer.WriteByte((byte)_builder.GetParameterIndex(instruction.Operand as ParameterSignature)); break; case CilOperandType.InlineVar: _writer.WriteUInt16((ushort)_builder.GetVariableIndex(instruction.Operand as VariableSignature)); break; case CilOperandType.ShortInlineVar: _writer.WriteByte((byte)_builder.GetVariableIndex(instruction.Operand as VariableSignature)); break; case CilOperandType.ShortInlineI: _writer.WriteSByte((sbyte)instruction.Operand); break; case CilOperandType.InlineI: _writer.WriteInt32((int)instruction.Operand); break; case CilOperandType.InlineI8: _writer.WriteInt64((long)instruction.Operand); break; case CilOperandType.ShortInlineR: _writer.WriteSingle((float)instruction.Operand); break; case CilOperandType.InlineR: _writer.WriteDouble((double)instruction.Operand); break; case CilOperandType.InlineBrTarget: _writer.WriteInt32(((CilInstruction)instruction.Operand).Offset - (instruction.Offset + instruction.Size)); break; case CilOperandType.ShortInlineBrTarget: _writer.WriteSByte((sbyte)(((CilInstruction)instruction.Operand).Offset - (instruction.Offset + instruction.Size))); break; case CilOperandType.InlineField: case CilOperandType.InlineMethod: case CilOperandType.InlineSig: case CilOperandType.InlineTok: case CilOperandType.InlineType: var token = _builder.GetMetadataToken((IMetadataMember)instruction.Operand); if (token.Rid == 0) { throw new InvalidOperationException($"Member {instruction.Operand} has an invalid metadata token."); } _writer.WriteUInt32(token.ToUInt32()); break; case CilOperandType.InlineString: _writer.WriteUInt32(_builder.GetStringOffset((string)instruction.Operand)); break; case CilOperandType.InlineSwitch: var targets = (IList <CilInstruction>)instruction.Operand; _writer.WriteInt32(targets.Count); foreach (var target in targets) { _writer.WriteInt32(target.Offset - (instruction.Offset + instruction.Size)); } break; case CilOperandType.InlineNone: break; } }
/// <summary> /// Writes a single instruction to the output stream. /// </summary> /// <param name="instruction">The instruction to write.</param> public void Write(CilInstruction instruction) { WriteOpCode(instruction.OpCode); WriteOperand(instruction); }
private bool Equals(CilInstruction other) { return(Offset == other.Offset && OpCode.Equals(other.OpCode) && Equals(Operand, other.Operand)); }