/// <summary> /// Reads a single CIL instruction from a given data stream. /// </summary> /// <param name="stream">The source data stream.</param> /// <param name="instruction">The instruction that was read, undefined if the method returns zero.</param> /// <returns>A value indicating if an instruction was read, <c>false</c> if the end of the stream was reached.</returns> public static bool ReadInstruction(Stream stream, out RawInstruction instruction) { Contract.Requires(stream != null && stream.CanRead); int firstOpcodeByte = stream.ReadByte(); if (unchecked ((byte)firstOpcodeByte) != firstOpcodeByte) { instruction = default(RawInstruction); return(false); } OpcodeValue opcodeValue; if (OpcodeValueEnum.IsFirstOfTwoBytes((byte)firstOpcodeByte)) { opcodeValue = (OpcodeValue)((firstOpcodeByte << 8) | stream.ReadUInt8()); } else { opcodeValue = (OpcodeValue)firstOpcodeByte; } var opcode = Opcode.FromValue(opcodeValue); if (opcode == Opcode.Switch) { // Read jump table int[] jumpTable = new int[stream.ReadUInt32()]; for (int i = 0; i < jumpTable.Length; ++i) { jumpTable[i] = stream.ReadInt32(); } instruction = RawInstruction.CreateSwitch(jumpTable); } else { NumericalOperand operand; switch ((int)opcode.OperandKind.GetSizeInBytes()) { case 0: operand = default(NumericalOperand); break; case 1: operand = stream.ReadInt8(); break; case 2: operand = stream.ReadInt16(); break; case 4: operand = stream.ReadInt32(); break; case 8: operand = stream.ReadInt64(); break; default: throw new NotSupportedException("Unexpected opcode operand size"); } instruction = new RawInstruction(opcode, operand); } return(true); }
private static void compile(TextWriter output, RawInstruction[] instructions, string[] _) { foreach (var _i in instructions) { var i = _i; if (i.Command.Length == 1) { i = new RawInstruction(CommandByShort[i.Command[0]], i.Arguments); } output.WriteLine(i); } }
public void arguments() { Assert.AreEqual(0, new RawInstruction("a").Arguments.Length); var args1 = new RawInstruction("a.abc").Arguments; Assert.AreEqual(1, args1.Length); Assert.AreEqual("abc", args1[0]); var args2 = new RawInstruction("a.\"def\\\"\\\\\\n\".abc").Arguments; Assert.AreEqual(2, args2.Length); Assert.AreEqual("def\"\\\n", args2[0]); Assert.AreEqual("abc", args2[1]); }
public override void Instruction(RawInstruction instruction) { if (instruction.IsSwitch) { throw RequiresSymbolicOverload(Opcode.Switch); } var param = new VisitorParam(this, instruction.NumericalOperand); instruction.Opcode.Accept(Visitor.Instance, param); if (sink != null) { sink.Instruction(instruction); } }
private static void decompile(TextWriter output, RawInstruction[] instructions, string[] _) { int prefixLength = 4; int prefixTabs = 0; foreach (var _i in instructions) { var i = _i; if (i.Command.Length == 1) { i = new RawInstruction(CommandByShort[i.Command[0]], i.Arguments); } if (SectionEndCommands.Contains(i.Command)) { prefixTabs = Math.Max(0, prefixTabs - 1); } output.Write(string.Join("", Enumerable.Repeat(" ", prefixTabs * prefixLength))); output.WriteLine(i); if (SectionStartCommands.Contains(i.Command)) { prefixTabs++; } } }
public override void Instruction(RawInstruction instruction) { var opcode = instruction.Opcode; OpCode emitOpCode; opcode.GetReflectionEmitOpCode(out emitOpCode); switch (emitOpCode.OperandType) { case OperandType.InlineNone: generator.Emit(emitOpCode); break; case OperandType.InlineI8: generator.Emit(emitOpCode, instruction.Int64Operand); break; case OperandType.InlineR: generator.Emit(emitOpCode, instruction.Float64Operand); break; case OperandType.InlineVar: generator.Emit(emitOpCode, (ushort)instruction.UIntOperand); break; case OperandType.ShortInlineR: generator.Emit(emitOpCode, instruction.Float32Operand); break; case OperandType.ShortInlineVar: generator.Emit(emitOpCode, (byte)instruction.UIntOperand); break; case OperandType.ShortInlineBrTarget: case OperandType.ShortInlineI: generator.Emit(emitOpCode, (sbyte)instruction.IntOperand); break; case OperandType.InlineBrTarget: case OperandType.InlineI: generator.Emit(emitOpCode, instruction.IntOperand); break; default: throw new NotSupportedException(); // Phi, tokens, jump tables } }
// TODO: Replace ScriptExecution ctor with actual compiler private static RawInstruction Compile(RawInstruction raw) => LongToShortCommand.TryGetValue(raw.Command, out var shortCommand) ? new RawInstruction(shortCommand, raw.Arguments) : raw;
public override void Instruction(RawInstruction instruction) { var opcode = instruction.Opcode; stringBuilder.Append(opcode.Name); if (opcode.OperandKind == OperandKind.None) { stringBuilder.AppendLine(); return; } stringBuilder.Append(' '); switch (opcode.OperandKind) { case OperandKind.VariableIndex8: case OperandKind.VariableIndex16: { // TODO: Use index if variable has no name int variableIndex = instruction.IntOperand; bool isLocal = ((VariableReferenceOpcode)opcode).VariableKind == VariableKind.Local; stringBuilder.Append(isLocal ? locals[variableIndex].Name : argumentNames[variableIndex]); break; } case OperandKind.Int8: case OperandKind.Int32: case OperandKind.BranchTarget8: case OperandKind.BranchTarget32: stringBuilder.Append(instruction.IntOperand); break; case OperandKind.Int64: stringBuilder.Append(instruction.Int64Operand); break; case OperandKind.Float64: stringBuilder.Append(instruction.Float64Operand); break; case OperandKind.Float32: stringBuilder.Append(instruction.Float32Operand); break; case OperandKind.JumpTable: { var jumpTable = instruction.JumpTable; stringBuilder.Append("("); for (int i = 0; i < jumpTable.Length; ++i) { if (i > 0) { stringBuilder.Append(", "); } stringBuilder.Append(jumpTable[i].ToString(CultureInfo.InvariantCulture)); } stringBuilder.AppendLine(")"); break; } default: throw new NotSupportedException(); } stringBuilder.AppendLine(); }
/// <summary> /// Writes a <c>switch</c> CIL instruction to this sink. /// </summary> /// <param name="jumpTable">The switch's jump table.</param> public void Switch(int[] jumpTable) { Instruction(RawInstruction.CreateSwitch(jumpTable)); }
/// <summary> /// Writes a given CIL instruction to this sink. /// </summary> /// <param name="instruction">The instruction to be written.</param> public abstract void Instruction(RawInstruction instruction);