int AnalyzeCodeBlock(CodeBlock block, List<Instruction> insns, Dictionary<Instruction, CodeBlock> blockMapping, int index, int endAddress) { int i = index; int continueAddr = int.MaxValue; while (i < insns.Count) { if (i == endAddress) return i; Instruction insn = insns[i]; if (i == index) { if (blockMapping.ContainsKey(insn)) { Instruction lastInsn = blockMapping[insn].Instructions[blockMapping[insn].Instructions.Count - 1]; CodeBlock cur = blockMapping[insn]; while (lastInsn.Inst == Instructions.DummyCodeBlock) { cur = cur.CodeBlocks[lastInsn.Operand1]; lastInsn = cur.Instructions[cur.Instructions.Count - 1]; } foreach (Instruction j in blockMapping[insn].Instructions) block.Instructions.Add(j); foreach (CodeBlock j in blockMapping[insn].CodeBlocks) block.CodeBlocks.Add(j); return insns.IndexOf(lastInsn) + 1; } blockMapping.Add(insn, block); } if (insn.IsBranchTarget && i != index) { CodeBlock newBlock = new CodeBlock(); block.CodeBlocks.Add(newBlock); Instruction dummy = new Instruction(); dummy.Inst = Instructions.DummyCodeBlock; dummy.Operand1 = block.CodeBlocks.Count - 1; block.Instructions.Add(dummy); i = AnalyzeCodeBlock(newBlock, insns, blockMapping, i, -1); if (newBlock.Instructions.Count == 1) { if (newBlock.Instructions[0].BranchTarget.Count > 0) { } } continue; } int elseTarget = insn.BranchTarget.Count > 0 ? insn.BranchTarget[0] : int.MaxValue; block.Instructions.Add(insn); i++; if (insn.StartNewBlock) { if (insn.BranchTarget[0] > i) { if (insns[i].EndBlock) { } int tmpI = i; int tmpI2 = i; CodeBlock newBlock = new CodeBlock(); CodeBlock newBlock2 = null; Instruction dummy2 = null; block.CodeBlocks.Add(newBlock); Instruction dummy = new Instruction(); dummy.Inst = Instructions.DummyCodeBlock; dummy.Operand1 = block.CodeBlocks.Count - 1; block.Instructions.Add(dummy); i = AnalyzeCodeBlock(newBlock, insns, blockMapping, i, elseTarget); /*Instruction lastInsn = newBlock.Instructions[newBlock.Instructions.Count - 1]; if (lastInsn.Inst == Instructions.DummyCodeBlock) { lastInsn = newBlock.CodeBlocks[lastInsn.Operand1].Instructions.Last(); } if (lastInsn.BranchTarget.Count > 0) { continueAddr = lastInsn.BranchTarget[0]; }*/ continueAddr = FindContinueAddress(elseTarget, newBlock); if ((continueAddr != -1) && !insns[continueAddr - 1].EndBlock) { Instruction continueInsn = insns[continueAddr - 1]; continueInsn.EndBlock = true; continueInsn.BranchTarget.Add(continueAddr); } if (continueAddr == elseTarget) { dummy.Operand2 = 1; } bool shouldReturn = false; if (elseTarget < continueAddr) { i = elseTarget; if (i != elseTarget) { } newBlock2 = new CodeBlock(); block.CodeBlocks.Add(newBlock2); dummy2 = new Instruction(); dummy2.Inst = Instructions.DummyCodeBlock; dummy2.Operand1 = block.CodeBlocks.Count - 1; block.Instructions.Add(dummy2); i = AnalyzeCodeBlock(newBlock2, insns, blockMapping, i, continueAddr); //tmpI2 = i; if (i == continueAddr) shouldReturn = true; } else { shouldReturn = true; } /*i = tmpI; newBlock = new CodeBlock(); block.CodeBlocks.Add(newBlock); dummy = new Instruction(); dummy.Inst = Instructions.DummyCodeBlock; dummy.Operand1 = block.CodeBlocks.Count - 1; block.Instructions.Add(dummy); i = AnalyzeCodeBlock(newBlock, insns, blockMapping, i); if (newBlock2 != null) { block.CodeBlocks.Add(newBlock2); dummy2.Operand1 = block.CodeBlocks.Count - 1; block.Instructions.Add(dummy2); i = tmpI2; }*/ if ((shouldReturn && endAddress == -1) || i >= endAddress) return i; else continue; } } if ((insn.EndBlock && (((insn.BranchTarget.Count == 0) || insn.BranchTarget[0] > endAddress) || endAddress == -1) && (insn.Inst != Instructions.Ret || (i < insns.Count && insns[i].IsBranchTarget))) || (i >= endAddress && endAddress >= 0)) { if (i > 1 && (insns[i - 2].Inst == Instructions.Switch || insns[i - 2].Inst == Instructions.SwitchS)) endAddress = insns[i - 1].BranchTarget[0]; else return i; } } return i; }
public static Instruction ParseInstruction(System.IO.BinaryReader br,Assembly asm,Function func) { Instructions op = (Instructions)br.ReadInt16(); Instruction insn = new Instruction(); insn.Assembly = asm; insn.Function = func; insn.Inst = op; switch (op) { case Instructions.BneLocal: case Instructions.BgeLocal: case Instructions.BltLocal: case Instructions.BgtLocal: case Instructions.BneField: case Instructions.BeqField: case Instructions.BneFieldLocal: case Instructions.BgtField: insn.Operand1 = br.ReadInt32(); insn.Operand2 = br.ReadInt32(); insn.Operand3 = br.ReadInt32(); insn.BranchTarget.Add(insn.Operand3); insn.StartNewBlock = true; break; case Instructions.Jmp: insn.Operand1 = br.ReadInt32(); insn.BranchTarget.Add(insn.Operand1); insn.EndBlock = true; break; case Instructions.BrFalse: case Instructions.BrTrue: insn.Operand1 = br.ReadInt32(); insn.BranchTarget.Add(insn.Operand1); insn.StartNewBlock = true; break; case Instructions.Switch: case Instructions.SwitchS: insn.Operand1 = br.ReadInt32(); Switch swi = asm.SwitchTables[insn.Operand1]; foreach (int i in swi.SwitchTable.Values) insn.BranchTarget.Add(i); if (swi.DefaultCase != -1) insn.BranchTarget.Add(swi.DefaultCase); break; case Instructions.Push: case Instructions.CallMethod: case Instructions.Call: case Instructions.RefGlobal: case Instructions.RefLocal: case Instructions.PushS: case Instructions.AssertFunc: case Instructions.AssertFile: case Instructions.CallSys: case Instructions.EndOfFunc: case Instructions.StructDelLocal: case Instructions.PushField: case Instructions.IncLocal: case Instructions.DecLocal: case Instructions.ArraySizeField: case Instructions.ArraySizeGlobal: case Instructions.PushLocal2: case Instructions.PushSLocal: case Instructions.AssignSConst: case Instructions.PushSField: case Instructions.ArrayStructRef: case Instructions.PushSGlobal: case Instructions.AssignSLocal: case Instructions.StringEmptyLocal: case Instructions.StringEmptyField: case Instructions.StructRef: case Instructions.AssignSField: case Instructions.Msg: insn.Operand1 = br.ReadInt32(); break; case Instructions.PushF: insn.Operand1F = br.ReadSingle(); break; case Instructions.BrFalseField: case Instructions.BNotEmptyField: case Instructions.BneS: insn.Operand1 = br.ReadInt32(); insn.Operand2 = br.ReadInt32(); insn.BranchTarget.Add(insn.Operand2); insn.StartNewBlock = true; break; case Instructions.StructCreateLocal: case Instructions.AssignLocal: case Instructions.AssignField: case Instructions.CallHLL: case Instructions.AssignFieldLocal: case Instructions.AssignGlobalLocal: case Instructions.AssignLocalField: case Instructions.ArrayPushBackLocal: case Instructions.AssignGlobal: case Instructions.GeField: case Instructions.EqlSLocal: case Instructions.NeqSLocal: case Instructions.EqlSFieldLocal: case Instructions.AssignSFieldLocal: case Instructions.PushStructRefField: case Instructions.ArrayPushBackFieldLocal: case Instructions.AssignArrayLocalField: case Instructions.ArrayPushBackLocalString: case Instructions.ArrayPushBackGlobalLocalRef: case Instructions.ArrayPushBackFieldLocalRef: case Instructions.AssignFieldLocalITOB: case Instructions.ArrayPushBackGlobalLocal: case Instructions.MinLocal: case Instructions.NeqFieldS: case Instructions.NeqSFieldLocal: case Instructions.AssignSLocalLocal: insn.Operand1 = br.ReadInt32(); insn.Operand2 = br.ReadInt32(); break; case Instructions.LtOrGeLocal: insn.Operand1 = br.ReadInt32(); insn.Operand2 = br.ReadInt32(); insn.Operand3 = br.ReadInt32(); break; case Instructions.Ret: insn.EndBlock = true; break; case Instructions.PushSP: case Instructions.Le: default: break; } return insn; }