/// <summary> /// Executes instructions in finally blocks that protect the region the specified leave instruction exits. /// </summary> /// <param name="leaveIL">The IL instruction that exits a protected region of code. </param> void ExecuteFinallyBlocks(BranchInstruction leaveIL) { SortedList <int, ExceptionHandlingClause> finallyblocks = new SortedList <int, ExceptionHandlingClause>(); // finds nested finally blocks, candidates should meet two conditions: // 1. the leave instruction is in the protected region of the finally block // 2. the branch target is out of the the protected region of the finally block foreach (ExceptionHandlingClause clause in methodBody.ExceptionHandlingClauses) { if (clause.Flags == ExceptionHandlingClauseOptions.Finally) { if (leaveIL.Offset >= clause.TryOffset && leaveIL.Offset <= clause.TryOffset + clause.TryLength && leaveIL.Target >= clause.HandlerOffset + clause.HandlerLength) { ILInstruction instruction = instructions[clause.HandlerOffset]; if (!instruction.Visited) { finallyblocks.Add(clause.TryOffset, clause); } } } } // executes the most deeply nested blocks before the blocks that enclose them foreach (ExceptionHandlingClause clause in finallyblocks.Values.Reverse()) { ILInstruction instruction = instructions[clause.HandlerOffset]; if (!instruction.Visited) { //System.Diagnostics.Debug.WriteLine("*** enter finally *** " + PrintInstruction(instruction)); Analysis(instruction, delegate(ILInstruction next) { return(next.OpCode.Name != "endfinally"); }); //System.Diagnostics.Debug.WriteLine("*** end finally *** "); } } }
private Operator(OpCode opCode, bool invertOpResult, BranchInstruction branchOp, string methodName, IMemberInfo[] standardCandidates, SpecificOperatorProvider[] standardTemplates) { this.opCode = this.opCodeUn = this.opCodeChk = this.opCodeChkUn = opCode; this.invertOpResult = invertOpResult; this.branchOp = branchOp; this.methodName = methodName; this.standardCandidates = standardCandidates; this.standardTemplates = standardTemplates; }
private Operator(OpCode opCode, bool invertOpResult, BranchInstruction branchOp, string methodName, IMemberInfo[] standardCandidates, SpecificOperatorProvider[] standardTemplates) { OpCode = OpCodeUn = OpCodeChk = OpCodeChkUn = opCode; InvertOpResult = invertOpResult; BranchOp = branchOp; MethodName = methodName; _standardCandidates = standardCandidates ?? new IMemberInfo[0]; _standardTemplates = standardTemplates; }
public void GetBytes_BranchInstruction(BranchKind branchKind) { var instruction = new BranchInstruction(branchKind, 42); var expectedBytes = InstructionByteBuilder.Create() .Opcode(Opcode.Branch, branchKind, 42) .AsSpan(); Assert.True(expectedBytes.SequenceEqual(instruction.GetBytes())); }
public OpCode Get(BranchInstruction ins, bool unsigned) { switch (ins) { case BranchInstruction.True: return brTrue; case BranchInstruction.False: return brFalse; case BranchInstruction.Eq: return brEq; case BranchInstruction.Ne: return brNe; case BranchInstruction.Lt: return unsigned ? brLtUn : brLt; case BranchInstruction.Gt: return unsigned ? brGtUn : brGt; case BranchInstruction.Le: return unsigned ? brLeUn : brLe; case BranchInstruction.Ge: return unsigned ? brGeUn : brGe; default: throw new NotSupportedException(); } }
public void PatchEcu(ICode ecuCode) { if (ecuCode == null) { throw new ArgumentNullException("ecuCode"); } if (!valueRead) { ReadValue(); } int calculatedAddress = (Constants.INJECT_CODE_ADDRESS + branchOffsetInCode) - indexInEcu; BranchInstruction branchInstruction = new BranchInstruction(); branchInstruction.value = (UInt32)calculatedAddress; byteConverter.CopyBytesGeneric(branchInstruction, ecuCode.CodeBytes, indexInEcu); }
int GetFirstConditionalBranchTarget(ILInstruction instruction) { int returnValue; // register the branch target for re-run after normal control flow completes. if (instruction is SwitchInstruction) { SwitchInstruction switchIL = instruction as SwitchInstruction; // run the first "case" target and register other targets(including "default") for re-run if (switchIL.Cases.Length > 1) { returnValue = switchIL.Next + switchIL.Cases[0]; branchTargetsToVisit[switchIL.Next] = new Stack <Vertex>(evaluationStack); for (int i = 1; i < switchIL.Cases.Length; i++) { branchTargetsToVisit[switchIL.Next + switchIL.Cases[i]] = new Stack <Vertex>(evaluationStack); } } else { returnValue = switchIL.Next; } } else { BranchInstruction branchIL = instruction as BranchInstruction; if (branchIL.Offset > branchIL.Target) { returnValue = branchIL.Target; branchTargetsToVisit[branchIL.Next] = new Stack <Vertex>(evaluationStack); } else { returnValue = branchIL.Next; branchTargetsToVisit[branchIL.Target] = new Stack <Vertex>(evaluationStack); } } return(returnValue); }
static AssemblerController() { Assemblers["ADD"] = new AddInstruction(); Assemblers["AND"] = new AndInstruction(); Assemblers["BR"] = new BranchInstruction("BR", true, true, true); // Alias of BRNZP Assemblers["BRN"] = new BranchInstruction("BRN", true, false, false); Assemblers["BRZ"] = new BranchInstruction("BRZ", false, true, false); Assemblers["BRP"] = new BranchInstruction("BRP", false, false, true); Assemblers["BRZP"] = new BranchInstruction("BRZP", false, true, true); Assemblers["BRNP"] = new BranchInstruction("BRNP", true, false, true); Assemblers["BRNZ"] = new BranchInstruction("BRNZ", true, true, false); Assemblers["BRNZP"] = new BranchInstruction("BRNZP", true, true, true); Assemblers["JMP"] = new RegisterBasedPCAccessInstruction("JMP", 0b1100); Assemblers["JSR"] = new JSRInstruction(); Assemblers["JSRR"] = new RegisterBasedPCAccessInstruction("JSRR", 0b0100); Assemblers["LD"] = new LabelBasedMemoryAccessInstruction("LD", 0b0010); Assemblers["LDI"] = new LabelBasedMemoryAccessInstruction("LDI", 0b1010); Assemblers["LDR"] = new OffsetBasedMemoryAccessInstruction("LDR", 0b0110); Assemblers["LEA"] = new LabelBasedMemoryAccessInstruction("LEA", 0b1110); Assemblers["NOT"] = new NotInstruction(); Assemblers["RET"] = new ZeroArgumentsInstruction("RET", 0xC1C0); // 1100 000 111 000000, i.e. JMP R7 Assemblers["RTI"] = new ZeroArgumentsInstruction("RTI", 0x8000); // 1000 000000000000 Assemblers["ST"] = new LabelBasedMemoryAccessInstruction("ST", 0b0011); Assemblers["STI"] = new LabelBasedMemoryAccessInstruction("STI", 0b1011); Assemblers["STR"] = new OffsetBasedMemoryAccessInstruction("STR", 0b0111); Assemblers["TRAP"] = new TrapInstruction(); Assemblers["GETC"] = new ZeroArgumentsInstruction("GETC", 0xF020); // TRAP x20 Assemblers["OUT"] = new ZeroArgumentsInstruction("OUT", 0xF021); // TRAP x21 Assemblers["PUTS"] = new ZeroArgumentsInstruction("PUTS", 0xF022); // TRAP x22 Assemblers["IN"] = new ZeroArgumentsInstruction("IN", 0xF023); // TRAP x23 Assemblers["PUTSP"] = new ZeroArgumentsInstruction("PUTSP", 0xF024); // TRAP x24 Assemblers["HALT"] = new ZeroArgumentsInstruction("HALT", 0xF025); // TRAP x25 }
public OpCode Get(BranchInstruction ins, bool unsigned) { switch (ins) { case BranchInstruction.True: return(brTrue); case BranchInstruction.False: return(brFalse); case BranchInstruction.Eq: return(brEq); case BranchInstruction.Ne: return(brNe); case BranchInstruction.Lt: return(unsigned ? brLtUn : brLt); case BranchInstruction.Gt: return(unsigned ? brGtUn : brGt); case BranchInstruction.Le: return(unsigned ? brLeUn : brLe); case BranchInstruction.Ge: return(unsigned ? brGeUn : brGe); default: throw new NotSupportedException(); } }
public override CILInstructionBranchTarget BuildNode(ParseTreeNode node) { var instructionBranchTargetParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.INSTR_BRTARGET); CILInstructionBranchTarget result = null; var beqsParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_beqs); if (beqsParseTreeNode != null) { result = new BranchOnEqualShortInstruction(); } var bgesParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_bges); if (bgesParseTreeNode != null) { result = new BranchOnGreaterOrEqualShortInstruction(); } var blesParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_bles); if (blesParseTreeNode != null) { result = new BranchOnLessOrEqualShortInstruction(); } var bltsParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_blts); if (bltsParseTreeNode != null) { result = new BranchOnLessShortInstruction(); } var bneunsParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_bneuns); if (bneunsParseTreeNode != null) { result = new BranchOnNotEqualOrUnorderedShortInstruction(); } var brParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_br); if (brParseTreeNode != null) { result = new BranchInstruction(); } var brfalsesParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_brfalses); if (brfalsesParseTreeNode != null) { result = new BranchOnFalseShortInstruction(); } var brsParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_brs); if (brsParseTreeNode != null) { result = new BranchShortInstruction(); } var brtruesParseTreeNode = instructionBranchTargetParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_brtrues); if (brtruesParseTreeNode != null) { result = new BranchOnTrueShortInstruction(); } if (result != null) { var idParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.id); result.Label = IdParseTreeNodeHelper.GetValue(idParseTreeNode); return(result); } throw new ArgumentException("Cannot recognize CIL instruction branch target."); }
public void Visit(BranchInstruction instruction) { var instructionName = instruction.Operator.GetAssemblySymbol(); lines.Add($"{label}\t{instructionName} {instruction.One.GetAssemblySymbol()},{instruction.Another.GetAssemblySymbol()},{instruction.Target.GetAssemblySymbol()}"); }
public void ToString_BranchInstruction(BranchKind branchKind, string expectedString) { var branchInstruction = new BranchInstruction(branchKind, 42); Assert.Equal(expectedString, branchInstruction.ToString()); }
internal Instruction ReadInstruction() { OpCodes opcode = (OpCodes)this.ReadByte(); Instruction result = Instruction.FixedOpCodes[(int)opcode]; if (null != result) { return(result); } switch (opcode) { case OpCodes.Block: return(BlockInstruction.Create(this)); case OpCodes.Loop: return(LoopInstruction.Create(this)); case OpCodes.If: // block_type return(IfInstruction.Create(this)); case OpCodes.Br: case OpCodes.BrIf: // varuint32 return(BranchInstruction.Create(this, opcode)); case OpCodes.BrTable: // custom return(BranchTableInstruction.Create(this)); case OpCodes.Call: case OpCodes.CallIndirect: // varuint32 + varuint1 return(CallInstruction.Create(this, opcode)); case OpCodes.GetLocal: case OpCodes.SetLocal: case OpCodes.TeeLocal: // local_index return(LocalAccessorInstruction.Create(this, opcode)); case OpCodes.GetGlobal: case OpCodes.SetGlobal: // global_index return(GlobalAccessorInstruction.Create(this, (OpCodes.GetGlobal == opcode))); case OpCodes.I32Load: case OpCodes.I64Load: case OpCodes.F32Load: case OpCodes.F64Load: case OpCodes.I32Load8_s: case OpCodes.I32Load8_u: case OpCodes.I32Load16_s: case OpCodes.I32Load16_u: case OpCodes.I64Load8_s: case OpCodes.I64Load8_u: case OpCodes.I64Load16_s: case OpCodes.I64Load16_u: case OpCodes.I64Load32_s: case OpCodes.I64Load32_u: case OpCodes.I32Store: case OpCodes.I64Store: case OpCodes.F32Store: case OpCodes.F64Store: case OpCodes.I32Store8: case OpCodes.I32Store16: case OpCodes.I64Store8: case OpCodes.I64Store16: case OpCodes.I64Store32: // memory_immediate return(MemoryAccessInstruction.Create(this, opcode)); case OpCodes.CurrentMemory: case OpCodes.GrowMemory: // varuint1 return(MemoryControlInstruction.Create(this, opcode)); case OpCodes.I32Const: // varint32 return(ConstantValueInstruction <int> .Create(this, OpCodes.I32Const, this.ReadVarInt32())); case OpCodes.I64Const: // varint64 return(ConstantValueInstruction <long> .Create(this, OpCodes.I64Const, this.ReadVarInt64())); case OpCodes.F32Const: // uint32 return(ConstantValueInstruction <float> .Create(this, OpCodes.F32Const, this.ReadVarFloat32())); case OpCodes.F64Const: // uint64 return(ConstantValueInstruction <double> .Create(this, OpCodes.F64Const, this.ReadVarFloat64())); case OpCodes.F32eq: case OpCodes.F32ge: case OpCodes.F32gt: case OpCodes.F32le: case OpCodes.F32lt: case OpCodes.F32ne: case OpCodes.F64eq: case OpCodes.F64ge: case OpCodes.F64gt: case OpCodes.F64le: case OpCodes.F64lt: case OpCodes.F64ne: case OpCodes.I32eq: case OpCodes.I32ge_s: case OpCodes.I32ge_u: case OpCodes.I32gt_s: case OpCodes.I32gt_u: case OpCodes.I32le_s: case OpCodes.I32le_u: case OpCodes.I32lt_s: case OpCodes.I32lt_u: case OpCodes.I32ne: case OpCodes.I64eq: case OpCodes.I64ge_s: case OpCodes.I64ge_u: case OpCodes.I64gt_s: case OpCodes.I64gt_u: case OpCodes.I64le_s: case OpCodes.I64le_u: case OpCodes.I64lt_s: case OpCodes.I64lt_u: case OpCodes.I64ne: return(RelationalInstruction.GetInstruction(opcode)); case OpCodes.F32Convert_sI32: case OpCodes.F32Convert_uI32: case OpCodes.F32Convert_sI64: case OpCodes.F32Convert_uI64: case OpCodes.F32demoteF64: case OpCodes.F64Convert_sI32: case OpCodes.F64Convert_uI32: case OpCodes.F64Convert_sI64: case OpCodes.F64Convert_uI64: case OpCodes.F64PromoteF32: case OpCodes.I32Trunc_sF32: case OpCodes.I32Trunc_uF32: case OpCodes.I32Trunc_sF64: case OpCodes.I32Trunc_uF64: case OpCodes.I32wrapI64: case OpCodes.I64Extend_sI32: case OpCodes.I64Extend_uI32: case OpCodes.I64Trunc_sF32: case OpCodes.I64Trunc_uF32: case OpCodes.I64Trunc_sF64: case OpCodes.I64Trunc_uF64: return(ConversionInstruction.GetInstruction(opcode)); default: throw new NotSupportedException(); } }
protected abstract void VisitBranchInstruction(BranchInstruction instruction);
public void VisitBranch(BranchInstruction instruction) => IncrementCallCount(nameof(VisitBranch));
public virtual void Visit(BranchInstruction instruction) { }
ExecuteComparisonInstructionBackward(CompareInstruction compareInstruction, Operand varOperand, Path path) { Expression result = null; Operator comparisonOperator = null; switch (compareInstruction.ConditionCode) { case ConditionCode.GT: comparisonOperator = OperatorStore.GreaterThanOp; break; case ConditionCode.UGT: comparisonOperator = OperatorStore.UGreaterThanOp; break; case ConditionCode.FGT: comparisonOperator = OperatorStore.FGreaterThanOp; break; case ConditionCode.GE: comparisonOperator = OperatorStore.GreaterThanEqualOp; break; case ConditionCode.UGE: comparisonOperator = OperatorStore.UGreaterThanEqualOp; break; case ConditionCode.FGE: comparisonOperator = OperatorStore.FGreaterThanEqualOp; break; case ConditionCode.LT: comparisonOperator = OperatorStore.LessThanOp; break; case ConditionCode.ULT: comparisonOperator = OperatorStore.ULessThanOp; break; case ConditionCode.FLT: comparisonOperator = OperatorStore.FLessThanOp; break; case ConditionCode.LE: comparisonOperator = OperatorStore.LessThanEqualOp; break; case ConditionCode.ULE: comparisonOperator = OperatorStore.ULessThanEqualOp; break; case ConditionCode.FLE: comparisonOperator = OperatorStore.FLessThanEqualOp; break; case ConditionCode.EQ: comparisonOperator = OperatorStore.EqualOp; break; case ConditionCode.NE: comparisonOperator = OperatorStore.NotEqualOp; break; default: throw new NotImplementedException("PHOENIX: Compare instruction Opcode " + "not implemented in symbolic tracer: " + compareInstruction.ToString()); } Operand srcOp1 = compareInstruction.SourceOperand1; Operand srcOp2 = compareInstruction.SourceOperand2; Expression srcExpr1 = TraceOperandBackward(srcOp1, varOperand, path); Expression srcExpr2 = TraceOperandBackward(srcOp2, varOperand, path); result = new Expression(comparisonOperator, srcExpr1, srcExpr2, path.Config.WORD_BITSIZE); result.Type = compareInstruction.DestinationOperand.Type; BranchInstruction branchInstruction = compareInstruction.Next.AsBranchInstruction; if (branchInstruction != null) { if (path.Blocks[path.Blocks.IndexOf(compareInstruction.BasicBlock) + 1] == branchInstruction.FalseLabelInstruction.BasicBlock) { result = new Expression(OperatorStore.NotOp, result, result.BitSize); result.Type = compareInstruction.DestinationOperand.Type; } } return(result); }
public IList <IInstruction> ParseAssembly(Stream assembly, int baseAddress) { var result = new List <IInstruction>(); var startPosition = assembly.Position; while (assembly.Position < assembly.Length) { var instructionPosition = (int)(baseAddress + assembly.Position - startPosition); var instruction = ReadUInt32(assembly); var condition = (byte)(instruction >> 28); switch (GetInstructionType(instruction)) { case InstructionType.DataProcessing: result.Add(DataProcessingInstructionFactory.Create(instructionPosition, condition, instruction)); break; case InstructionType.Multiply: // TODO: Implement multiply _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'Multiply'."); break; case InstructionType.MultiplyLong: // TODO: Implement Multiply long _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'MultiplyLong'."); break; case InstructionType.SingleDataSwap: // TODO: Implement Data swap _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'SingleDataSwap'."); break; case InstructionType.BranchExchange: result.Add(BranchAndExchangeInstruction.Parse(instructionPosition, condition, instruction)); break; case InstructionType.HalfwordDataTransferReg: // TODO: Implement halfword data transfer reg _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'HalfwordDataTransferReg'."); break; case InstructionType.HalfwordDataTransferImm: // TODO: Implement halfword data transer imm _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'HalfwordDataTransferImm'."); break; case InstructionType.SingleDataTransfer: result.Add(SingleDataTransferInstruction.Parse(instructionPosition, condition, instruction)); break; case InstructionType.BlockDataTransfer: result.Add(BlockDataTransferInstruction.Parse(instructionPosition, condition, instruction)); break; case InstructionType.Branch: result.Add(BranchInstruction.Parse(instructionPosition, condition, instruction)); break; case InstructionType.CoprocessorDataTransfer: _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'CoprocessorDataTransfer'."); break; case InstructionType.CoprocessorDataOperation: _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'CoprocessorDataOperation'."); break; case InstructionType.CoprocessorRegTransfer: _logger?.Log(LogLevel.Fatal, "Unimplemented Instructiontype 'CoprocessorRegTransfer'."); break; case InstructionType.SoftwareInterrupt: result.Add(SvcInstruction.Parse(instructionPosition, condition, instruction)); break; case InstructionType.Undefined: default: throw new UndefinedInstructionException(instruction, instructionPosition); } } return(result); }
public virtual void Visit(BranchInstruction instruction) { } // { Default(instruction); }
public void Read(ref BlobReader reader) { this.ReadStart(); while (reader.RemainingBytes > 0) { int offset = reader.Offset; ILOpCode opCode = reader.DecodeILOpCode(); switch (opCode) { case ILOpCode.Nop: this.Read(NopInstruction.Nop(), offset); break; case ILOpCode.Ldarg_0: this.Read(LoadArgumentInstruction.FromIndex(0), offset); break; case ILOpCode.Ldarg_1: this.Read(LoadArgumentInstruction.FromIndex(1), offset); break; case ILOpCode.Ldloc_0: this.Read(LoadLocalInstruction.FromIndex(0), offset); break; case ILOpCode.Ldloc_1: this.Read(LoadLocalInstruction.FromIndex(1), offset); break; case ILOpCode.Ldloca_s: this.Read(LoadLocalAddressInstruction.FromIndex(reader.ReadSByte()), offset); break; case ILOpCode.Stloc_0: this.Read(StoreLocalInstruction.ToIndex(0), offset); break; case ILOpCode.Stloc_1: this.Read(StoreLocalInstruction.ToIndex(1), offset); break; case ILOpCode.Ldc_i4_0: this.Read(PushInt32Instruction.Constant(0), offset); break; case ILOpCode.Ldc_i4_1: this.Read(PushInt32Instruction.Constant(1), offset); break; case ILOpCode.Ldc_i4_2: this.Read(PushInt32Instruction.Constant(2), offset); break; case ILOpCode.Ldc_i4_3: this.Read(PushInt32Instruction.Constant(3), offset); break; case ILOpCode.Ldc_i4_s: this.Read(PushInt32Instruction.Constant(reader.ReadSByte()), offset); break; case ILOpCode.Ldc_i4: this.Read(PushInt32Instruction.Constant(reader.ReadInt32()), offset); break; case ILOpCode.Ldc_i8: this.Read(PushInt64Instruction.Constant(reader.ReadInt64()), offset); break; case ILOpCode.Br_s: this.Read(BranchInstruction.ILIndex(reader.ReadSByte() + reader.Offset), offset); break; case ILOpCode.Bgt_s: this.Read(BranchGreaterInstruction.ILIndex(reader.ReadSByte() + reader.Offset), offset); break; case ILOpCode.Brfalse_s: this.Read(BranchFalseInstruction.ILIndex(reader.ReadSByte() + reader.Offset), offset); break; case ILOpCode.Call: this.Read(CallInstruction.Handle(reader.ReadInt32()), offset); break; case ILOpCode.Pop: this.Read(PopInstruction.Pop(), offset); break; case ILOpCode.Ret: this.Read(ReturnInstruction.Return(), offset); break; case ILOpCode.Add: this.Read(AddInstruction.Add(), offset); break; case ILOpCode.Sub: this.Read(SubtractInstruction.Subtract(), offset); break; case ILOpCode.Initobj: this.Read(InitObjectInstruction.Handle(reader.ReadInt32()), offset); break; case ILOpCode.Ldfld: this.Read(LoadFieldValueInstruction.Handle(reader.ReadInt32()), offset); break; case ILOpCode.Stfld: this.Read(SaveFieldValueInstruction.Handle(reader.ReadInt32()), offset); break; default: throw new NotSupportedException("Opcode: " + opCode); } } this.ReadEnd(); }
protected override void VisitBranchInstruction(BranchInstruction instruction) { ControlState.Move(instruction.Offset, instruction.Label); }