private bool IsCodePathAnIfPath(CodePath path) { HLInstruction instruction = path.GetFirstInstruction(); bool foundOneIf = false; while (instruction != null) { if (instruction.IsConditionalBranch && instruction.ProcessedStackValue != null) { foundOneIf = true; } else { if (instruction.ProcessedStackValue != null) { return(false); } } instruction = instruction.GetNextInstruction(); } return(foundOneIf); }
private void ProcessCodePath(TextWriter writer, CodePath path, string indent) { HLInstruction instruction = path.GetFirstInstruction(); while (instruction != null) { Annotate(writer, indent, instruction); if (instruction.UnconditionalBranch) { // Not used } else if (instruction.IsConditionalBranch) { if (_nextIfIsAnElseIf) { writer.Write(string.Format("{0}else if", indent)); _nextIfIsAnElseIf = false; } else { writer.Write(string.Format("{0}if", indent)); } writer.WriteLine(string.Format(" ({0})", instruction.ProcessedStackValue)); writer.WriteLine(indent + "{"); ProcessCodePath(writer, instruction.BranchCodesPaths[instruction.DefaultConditional], indent + " "); writer.WriteLine(indent + "}"); if (instruction.BranchCodesPaths.ContainsKey(!instruction.DefaultConditional)) { CodePath elsePath = instruction.BranchCodesPaths[!instruction.DefaultConditional]; if (elsePath.StartInstruction != null) { if (IsCodePathAnIfPath(elsePath)) { _nextIfIsAnElseIf = true; ProcessCodePath(writer, elsePath, indent); } else { writer.WriteLine(indent + "else"); writer.WriteLine(indent + "{"); ProcessCodePath(writer, elsePath, indent + " "); writer.WriteLine(indent + "}"); } } } } else if (instruction.IsSwitchBranch) { // Do switch cases ever fall through?? I'm assuming they don't here! writer.WriteLine(indent + string.Format("switch ({0})", instruction.ProcessedStackValue)); writer.WriteLine(indent + "{"); // Keep track of code paths are have already outputted to keep // track of offsets that lead to the same codepath var swDonePaths = new List <CodePath>(); foreach (var item in instruction.BranchCodesPaths) { if (swDonePaths.Contains(item.Value)) { continue; } foreach (var item2 in instruction.BranchCodesPaths) { // O(n^2) loop here, there's probably a better way to optimize it if (item2.Value == item.Value) { if (item2.Key.GetType() == typeof(int)) { writer.WriteLine(string.Format("{0} case {1}:", indent, LiteralFormatter.FormatInteger((int)item2.Key))); } else { writer.WriteLine(string.Format("{0} default:", indent)); } } } writer.WriteLine(indent + " {"); ProcessCodePath(writer, item.Value, indent + " "); if (item.Value.EndInstruction == null || !item.Value.EndInstruction.ExitFunction) { writer.WriteLine(indent + " break;"); } writer.WriteLine(indent + " }"); swDonePaths.Add(item.Value); } writer.WriteLine(indent + "}"); } else if (instruction.LoopCodePath != null) { // First of a loop instruction (hopefully, someday, this will be extracted out by the ProgramAnalyzer) // Can we ever break out of a loop? I assume we can't here! while (!instruction.IsConditionalBranch) { instruction = instruction.NextInstruction; Annotate(writer, indent, instruction); } writer.WriteLine(indent + string.Format("while ({0})", instruction.ProcessedStackValue)); writer.WriteLine(indent + "{"); ProcessCodePath(writer, instruction.BranchCodesPaths[true], indent + " "); writer.WriteLine(indent + "}"); } else { WriteInstruction(writer, instruction, indent); } instruction = instruction.NextInstruction; } }
private void ProcessCodePath(TextWriter writer, CodePath path, string indent) { HLInstruction instruction = path.GetFirstInstruction(); while (instruction != null) { if (instruction.IsConditionalBranch) { writer.WriteLine(string.Format("{0}.if{1}", indent, instruction.DefaultConditional ? "true" : "false")); ProcessCodePath(writer, instruction.BranchCodesPaths[instruction.DefaultConditional], indent + " "); if (instruction.BranchCodesPaths.ContainsKey(!instruction.DefaultConditional)) { CodePath elsePath = instruction.BranchCodesPaths[!instruction.DefaultConditional]; if (elsePath.StartInstruction != null) { writer.WriteLine(indent + ".else"); ProcessCodePath(writer, elsePath, indent + " "); } } writer.WriteLine(indent + ".endif"); } else if (instruction.IsSwitchBranch) { // Do switch cases ever fall through?? I'm assuming they don't here! writer.WriteLine(indent + ".switch"); // Keep track of code paths are have already outputted to keep // track of offsets that lead to the same codepath var swDonePaths = new List <CodePath>(); foreach (var item in instruction.BranchCodesPaths) { if (swDonePaths.Contains(item.Value)) { continue; } foreach (var item2 in instruction.BranchCodesPaths) { // O(n^2) loop here, there's probably a better way to optimize it if (item2.Value == item.Value) { if (item2.Key.GetType() == typeof(int)) { writer.WriteLine(string.Format("{0} .case {1}", indent, item2.Key)); } else { writer.WriteLine(string.Format("{0} .default", indent, item2.Key)); } } } ProcessCodePath(writer, item.Value, indent + " "); if (item.Value.EndInstruction == null || !item.Value.EndInstruction.ExitFunction) { writer.WriteLine(indent + " .break"); } swDonePaths.Add(item.Value); } writer.WriteLine(indent + ".endswitch"); } else if (instruction.LoopCodePath != null) { // First of a loop instruction (hopefully, someday, this will be extracted out by the ProgramAnalyzer) // Can we ever break out of a loop? I assume we can't here! writer.WriteLine(indent + ".while"); instruction = WriteLoopConditional(writer, instruction, indent + " "); writer.WriteLine(indent + ".do"); ProcessCodePath(writer, instruction.BranchCodesPaths[true], indent + " "); writer.WriteLine(indent + ".endwhile"); } else { WriteInstruction(writer, instruction, indent); } instruction = instruction.GetNextInstruction(); } }