/// <summary> /// Writes an instruction's opcode /// </summary> /// <param name="writer">The instruction writer</param> /// <param name="instr">The instruction</param> protected void WriteOpCode(ref ArrayWriter writer, Instruction instr) { var code = instr.OpCode.Code; if ((ushort)code <= 0xFF) { writer.WriteByte((byte)code); } else if (((ushort)code >> 8) == 0xFE) { writer.WriteByte((byte)((ushort)code >> 8)); writer.WriteByte((byte)code); } else if (code == Code.UNKNOWN1) { writer.WriteByte((byte)Code.Nop); } else if (code == Code.UNKNOWN2) { writer.WriteUInt16((ushort)(((ushort)Code.Nop << 8) | Code.Nop)); } else { Error("Unknown instruction"); writer.WriteByte((byte)Code.Nop); } }
/// <summary> /// Writes a <see cref="OperandType.ShortInlineI"/> operand /// </summary> /// <param name="writer">Instruction writer</param> /// <param name="instr">Instruction</param> protected virtual void WriteShortInlineI(ref ArrayWriter writer, Instruction instr) { if (instr.Operand is sbyte) { writer.WriteSByte((sbyte)instr.Operand); } else if (instr.Operand is byte) { writer.WriteByte((byte)instr.Operand); } else { Error("Operand is not a Byte or a SByte"); writer.WriteByte(0); } }
/// <summary> /// Writes a <see cref="OperandType.ShortInlineVar"/> operand /// </summary> /// <param name="writer">Instruction writer</param> /// <param name="instr">Instruction</param> protected virtual void WriteShortInlineVar(ref ArrayWriter writer, Instruction instr) { var variable = instr.Operand as IVariable; if (variable == null) { Error("Operand is not a local/arg"); writer.WriteByte(0); } else { int index = variable.Index; if (byte.MinValue <= index && index <= byte.MaxValue) { writer.WriteByte((byte)index); } else { Error("Local/arg index doesn't fit in a Byte. Use the longer ldloc/ldarg/stloc/starg instruction."); writer.WriteByte(0); } } }
/// <summary> /// Writes a <see cref="OperandType.ShortInlineBrTarget"/> operand /// </summary> /// <param name="writer">Instruction writer</param> /// <param name="instr">Instruction</param> protected virtual void WriteShortInlineBrTarget(ref ArrayWriter writer, Instruction instr) { int displ = (int)(GetOffset(instr.Operand as Instruction) - (ToInstructionOffset(ref writer) + 1)); if (sbyte.MinValue <= displ && displ <= sbyte.MaxValue) { writer.WriteSByte((sbyte)displ); } else { Error("Target instruction is too far away for a short branch. Use the long branch or call CilBody.SimplifyBranches() and CilBody.OptimizeBranches()"); writer.WriteByte(0); } }