public static void Dump(TextWriter writer, IEnumerable <Node> cfg, IClrMethodBody body) { var method = body.Method; writer.WriteLine(separator); writer.WriteLine("//{0}: {1}", CommonLanguageInfrastructure.Debug ? "DEBUG" : "RELEASE", method); writer.WriteLine(separator); DumpLocalVariables(writer, body); writer.WriteLine(separator); if (body.HasProtectedBlocks) { foreach (var instr in body.Code) { if (instr.Dumped) { continue; } var block = instr.SehBlock; if (block != null) { WriteBlock(writer, block); //if (instruction.Index == block.EntryIndex) //{ // BeginBlock(writer, block); //} //string tab = GetBlockIndent(block); //writer.Write(tab + "\t"); } else { instr.Dumped = true; writer.WriteLine(instr.ToString()); } //if (block != null) //{ // if (instruction.Index == block.ExitIndex) // EndBlock(writer, block); //} } } else { writer.WriteLine(body.Code.ToString()); } writer.WriteLine(); writer.WriteLine("--------------------------------------------------"); writer.WriteLine("CFG"); writer.WriteLine("--------------------------------------------------"); foreach (var node in cfg) { writer.WriteLine("{0}: {1} - {2}", node, node.EntryIndex, node.ExitIndex); } writer.WriteLine(); }
private static void ReadLocals(IEnumerable <PdbScope> scopes, IClrMethodBody body) { foreach (var scope in scopes) { ReadLocals(scope, body); } }
internal JsFunction CompileMethodBody(JsClass klass, IMethod method, IClrMethodBody body) { var blocks = body.GetAllProtectedBlocks().ToArray(); var context = new MethodContext(this, klass, method, blocks); var func = new JsFunction(null, method.JsParams()); //TODO: cache info and code as separate class property var info = new JsObject(true) { { "isVoid", method.IsVoid() }, { "blocks", CompileBlocks(blocks) }, { "blockMap", CompileBlockMap(body, blocks) }, }; var args = CompilerArgs(method); var vars = new JsArray(method.Body.LocalVariables.Select(x => x.Type.InitialValue())); var code = new JsArray(body.Code.Select <Instruction, object>(i => new JsInstruction(i, CompileInstruction(context, i))), "\n"); func.Body.Add(args.Var("args")); func.Body.Add(vars.Var("vars")); func.Body.Add(info.Var("info")); foreach (var var in context.Vars) { func.Body.Add(var); } func.Body.Add(code.Var("code")); func.Body.Add(new JsText("var ctx = new $context(info, args, vars);")); func.Body.Add(new JsText("return ctx.exec(code);")); return(func); }
/// <summary> /// Builds flowgraph. Prepares list of basic blocks to translate. /// </summary> public static ControlFlowGraph Build(IClrMethodBody body) { #if DEBUG DebugHooks.LogInfo("CFG Builder started"); #endif var graph = body.ControlFlowGraph; if (graph != null) { #if DEBUG body.VisualizeGraph(graph.Entry, false); #endif return(graph); } var builder = new GraphBuilder(body, false) { IsVoidCallEnd = true }; var entry = builder.Build(); if (entry == null) { throw new ILTranslatorException("Unable to build flowgraph"); } #if DEBUG body.VisualizeGraph(entry, false); #endif //Prepares list of basic blocks in the same order as they are located in code. var blocks = new NodeList(); Node prevNode = null; foreach (var instruction in body.Code) { var bb = instruction.BasicBlock; //if (bb == null) // throw new InvalidOperationException(); if (bb == null) { continue; } if (prevNode == bb) { continue; } blocks.Add(bb); prevNode = bb; } graph = new ControlFlowGraph { Entry = entry, Blocks = blocks }; body.ControlFlowGraph = graph; return(graph); }
internal static void VisualizeGraph(this IClrMethodBody body, Node entry, bool translatedCode) { if (entry == null) { return; } var list = entry.GetGraphNodes(); body.VisualizeGraph(list, translatedCode); }
public static void Dump(IEnumerable <Node> cfg, IClrMethodBody body, string root) { string dir = body.GetTestDirectory(); Directory.CreateDirectory(dir); string path = Path.Combine(dir, "cil.txt"); using (var writer = new StreamWriter(path)) { Dump(writer, cfg, body); } }
public static void DumpLocalVariables(TextWriter writer, IClrMethodBody body) { if (body.LocalVariables != null) { int n = body.LocalVariables.Count; writer.WriteLine("LocalCount: {0}", n); int pn = body.Method.Parameters.Count + 1; for (int i = 0; i < n; ++i) { var v = body.LocalVariables[i]; writer.WriteLine("v{0}[{1}]: {2}", pn + i, i, v.Type.FullName); } } }
public bool LoadSymbols(IClrMethodBody body) { var entry = _symbolFile.GetMethodByToken(body.Method.MetadataToken); if (entry == null) { return(false); } var points = ReadSequencePoints(entry); body.SetSequencePoints(points); ReadLocals(entry, body); return(true); }
public bool LoadSymbols(IClrMethodBody body) { var token = body.Method.MetadataToken; PdbFunction function; if (!_functions.TryGetValue((uint)token, out function)) { return(false); } var points = ReadSequencePoints(function); body.SetSequencePoints(points); ReadLocals(function.scopes, body); return(true); }
public Code(IMethod method, IClrMethodBody body, ICodeProvider provider) { if (method == null) { throw new ArgumentNullException("method"); } if (body == null) { throw new ArgumentNullException("body"); } if (provider == null) { throw new ArgumentNullException("provider"); } Method = method; Body = body; Provider = provider; }
private static void ReadLocals(PdbScope scope, IClrMethodBody body) { if (scope == null) { return; } foreach (var slot in scope.slots) { int index = (int)slot.slot; if (index < 0 || index >= body.LocalVariables.Count) { continue; } var var = body.LocalVariables[index]; var.Name = slot.name; } ReadLocals(scope.scopes, body); }
internal static void VisualizeGraph(this IClrMethodBody body, NodeList list, bool translatedCode) { DebugHooks.LogInfo("Flow graph constructed"); DotService.NameService = null; bool filter = DebugHooks.EvalFilter(body.Method); var after = translatedCode; var before = !translatedCode; if (filter || (before && DebugHooks.VisualizeGraphBefore) || (after && DebugHooks.VisualizeGraphAfter)) { DotService.Write(list, DotService.MakePath(body, before ? "before" : "after"), true, translatedCode); } if (filter || DebugHooks.DumpILCode) { DumpService.Dump(list, body, CommonLanguageInfrastructure.TestCaseDirectory); DebugHooks.LogInfo("IL code dumped"); } }
private static JsArray CompileBlockMap(IClrMethodBody body, TryCatchBlock[] blocks) { return(blocks.Length > 0 ? new JsArray( body.Code.Select <Instruction, object>( i => { var b = i.SehBlock; while (b != null) { var tb = b as TryCatchBlock; if (tb != null) { return blocks.IndexOf(x => x == b); } var h = b as HandlerBlock; b = h != null ? h.Owner.Parent : b.Parent; } return -1; })) : JsArray.Empty); }
private static void ProcessLocalVars(IMethod currentMethod, IClrMethodBody body) { foreach (var var in body.LocalVariables) { //NOTE: We should reset var tag since it can be used for pointer emulation var.Data = null; if (var.GenericType != null) { var.Type = ResolveType(currentMethod, var.GenericType); continue; } var type = ResolveType(currentMethod, var.Type); if (!ReferenceEquals(type, var.Type)) { if (var.GenericType == null) { var.GenericType = var.Type; } var.Type = type; } } }
public static void Resolve(IMethod currentMethod, IClrMethodBody body) { ResolveBaseTypes(currentMethod.DeclaringType); if (!body.HasGenerics) { return; } if (body.HasGenericInstructions) { foreach (var instr in body.Code) { ProcessInstruction(currentMethod, instr); } } if (body.HasGenericVars) { ProcessLocalVars(currentMethod, body); } if (body.InstanceCount > 1) { //NOTE: We should reset parameter tag since it can be used for pointer emulation foreach (var p in currentMethod.Parameters) { p.Data = null; } } if (body.HasGenericExceptions) { ProcessExceptionTypes(currentMethod, body.ProtectedBlocks.Cast <Block>()); } }
public static void Dump(IClrMethodBody body, TranslatorResult result, string format, string filename) { if (!(DebugHooks.EvalFilter(body.Method) || DebugHooks.DumpILMap)) { return; } DebugHooks.LogInfo("DumpILMap started. Format = {0}. FileName = {1}.", format, filename); string dir = body.GetTestDirectory(); Directory.CreateDirectory(dir); using (var writer = new StreamWriter(Path.Combine(dir, filename))) { DumpService.DumpLocalVariables(writer, body); writer.WriteLine(Separator); if (result.Begin != null && result.Begin.Length > 0) { writer.WriteLine("#BEGIN CODE"); writer.WriteLine(Separator); for (int i = 0; i < result.Begin.Length; ++i) { writer.WriteLine(result.Output[i].ToString(format, null)); } writer.WriteLine(Separator); } foreach (var bb in body.ControlFlowGraph.Blocks) { writer.WriteLine("#BASIC BLOCK {0}", bb.Index); DumpStackState(writer, bb); writer.WriteLine(Separator); writer.WriteLine("#ORIGINAL CODE"); foreach (var instruction in bb.Code) { writer.WriteLine(instruction.ToString(format, null)); } writer.WriteLine(); var code = bb.TranslatedCode; writer.WriteLine("#TRANSLATED CODE"); foreach (var instruction in code) { writer.WriteLine(instruction.ToString(format, null)); } writer.WriteLine(Separator); } if (result.End != null && result.End.Length > 0) { writer.WriteLine("#END CODE"); writer.WriteLine(Separator); foreach (var instruction in result.End) { writer.WriteLine(instruction.ToString(format, null)); } } } DebugHooks.LogInfo("DumpILMap succeded"); }
public GraphBuilder(IClrMethodBody body, bool removeSingleGotos) { _code = body.Code; _removeSingleGotos = removeSingleGotos; }
public static IEnumerable <TryCatchBlock> GetAllProtectedBlocks(this IClrMethodBody body) { return((body.ProtectedBlocks ?? Enumerable.Empty <TryCatchBlock>()) .SelectMany(x => x.GetSelfAndDescendants())); }
public Context(IClrMethodBody body, ICodeProvider provider) { Body = body; Method = body.Method; Provider = provider; }
/// <summary> /// Performs flowgraph analysis. /// </summary> public static void Analyze(IClrMethodBody body, ICodeProvider provider) { Analyze(new Context(body, provider)); }