private void PrepareMainBlock() { RootBlock = new SimanticsBlock() { BlockType = SimanticsBlockType.BlockSequence, //IBody = Instructions.Values.ToList() }; }
private void ResetBlock(SimanticsBlock block) { block.VisitCount = 0; foreach (var sblock in block.Body) { ResetBlock(sblock); } }
private void IdentifySequences() { //O(n) scan through instructions //keep track of a "start" instruction, initially the first instruction. //and build a list of instructions following it. //whenever the new instruction has more than one input (or yields), complete the sequence (minus new) and start a new one on this instruction //whenever the new instruction has more than one output, complete the sequence (including new) and start on the following var firstSequence = new SimanticsBlock() { BlockType = SimanticsBlockType.InstructionSequence, Parent = RootBlock, StartInstructionIndex = 0, }; var toProcess = new Queue <Tuple <byte, SimanticsBlock> >(); toProcess.Enqueue(new Tuple <byte, SimanticsBlock>(0, firstSequence)); Instructions[0].VisitCount = 1; while (toProcess.Count > 0) { var process = toProcess.Dequeue(); var inst = Instructions[process.Item1]; var currentSequence = process.Item2; if (currentSequence != null && (inst.From.Count > 1 || inst.Yields)) { //something jumps back in here, likely a loop or yield. if (currentSequence.IBody.Count > 0) { RootBlock.Body.Add(currentSequence); currentSequence.LastInstructionIndex = currentSequence.IBody.Last().Index; currentSequence = null; /* * currentSequence = new SimanticsBlock() * { * BlockType = SimanticsBlockType.InstructionSequence, * Parent = RootBlock, * StartInstructionIndex = inst.Index, * }; */ } } if (currentSequence == null) { currentSequence = new SimanticsBlock() { BlockType = SimanticsBlockType.InstructionSequence, Parent = RootBlock, StartInstructionIndex = inst.Index, }; } currentSequence.IBody.Add(inst); var nextSequence = currentSequence; if (inst.To.Count > 1 || inst.ReturnType == PrimitiveReturnType.SimanticsSubroutine) { RootBlock.Body.Add(currentSequence); currentSequence.LastInstructionIndex = currentSequence.IBody.Last().Index; nextSequence = null; } var hadDest = false; foreach (var dest in inst.To) { if (dest != null && dest.VisitCount == 0) { toProcess.Enqueue(new Tuple <byte, SimanticsBlock>(dest.Index, nextSequence)); dest.VisitCount++; hadDest = true; } } if (!hadDest && nextSequence != null) { RootBlock.Body.Add(currentSequence); currentSequence.LastInstructionIndex = currentSequence.IBody.Last().Index; } } foreach (var sequence in RootBlock.Body) { var firstInst = sequence.IBody.First(); var lastInst = sequence.IBody.Last(); sequence.FromBlocks = RootBlock.Body.Where(x => firstInst.From.Contains(x.IBody.Last())).ToList(); sequence.NextBlocks = lastInst.To.Select(x => (x == null) ? null : RootBlock.Body.First(y => y.StartInstructionIndex == x.Index)).ToList(); } }