static public bool Detect(CodeBlock block, out StatementStructure statementStructure) { List <OpCode> brs = new List <OpCode> { OpCodes.Br_S, OpCodes.Br }; statementStructure = null; if (!ConditionalBranch_OpCodes.Contains(block.first.OpCode)) { return(false); } var conditionStatementBlock = Detect(block.first, block.last); if (conditionStatementBlock == null) { return(false); } List <ConditionStatementBlock> blocks = new List <ConditionStatementBlock>(); blocks.Add(conditionStatementBlock); while (true) { var next = conditionStatementBlock.body.last.Next; if (!brs.Contains(next.Previous.OpCode)) { break; } var br = next.Previous as Instruction; var target = br.Operand as Instruction; if (target.OpCode == OpCodes.Ret) { break; } conditionStatementBlock = Detect(next, target.Previous); if (conditionStatementBlock == null) { conditionStatementBlock = new ConditionStatementBlock(null, new CodeBlock(next, target.Previous)); blocks.Add(conditionStatementBlock); break; } var current = blocks[blocks.Count - 1]; blocks[blocks.Count - 1] = new ConditionStatementBlock( current.condition, new CodeBlock(current.body.first, current.body.last.Previous) ); blocks.Add(conditionStatementBlock); } CodeBlock all = new CodeBlock(block.first, blocks[blocks.Count - 1].body.last); statementStructure = new ConditionStatementStructure(all, blocks); return(true); }
static public StatementStructureType Recognize(CodeBlock block, out StatementStructure statementStructure) { if (LoopStatementStructure.Detect(block, out statementStructure) || ConditionStatementStructure.Detect(block, out statementStructure)) { return(statementStructure.type); } statementStructure = null; return(StatementStructureType.Unknown); }
static public bool Detect(CodeBlock block, out StatementStructure statementStructure) { statementStructure = null; var opCode = block.first.OpCode; if (opCode != OpCodes.Br && opCode != OpCodes.Br_S) { return(false); } // maybe loop condition var target = block.first.Operand as Instruction; // find next branch instruction (Brtrue, Brtrue_S), which may be a loop tag and an end Instruction last = null; { var tmp = target; while (tmp != null && !ConditionalBranch_OpCodes.Contains(tmp.OpCode)) { tmp = tmp.Next; } if (tmp == null) { return(false); } last = tmp; } // loop body if ((last.Operand as Instruction).Previous != block.first) { return(false); } CodeBlock all = new CodeBlock(block.first, last); CodeBlock init = null; CodeBlock condition = new CodeBlock(target, last); CodeBlock step = null; CodeBlock body = new CodeBlock(block.first.Next, target.Previous); statementStructure = new LoopStatementStructure(all, init, condition, step, body); return(true); }
public static Instruction Step(this Instruction current, Instruction last, CompileContext compileContext) { if (StatementStructure.Recognize(new CodeBlock(current, last), out StatementStructure statementStructure) != StatementStructureType.Unknown) { string s = statementStructure.Generate(compileContext); compileContext.WriteLine(s); return(statementStructure.all.last.Next); } uint?localVariableIndex = compileContext.GetLocalVariableInstructionIndex(current); if (localVariableIndex != null && compileContext.IsUnnecessaryLocalVariableID(localVariableIndex.Value)) { return(current.Next.Next); } var code = current.OpCode.Code; if (!methods.TryGetValue(code, out MethodInfo method)) { throw new Exception(string.Format("Unsupported operate code: {0}", code)); } method.Invoke(null, new object[] { current, compileContext }); return(current.Next); }