public void _EntryAndExitPoints() { var tree = CSharpSyntaxTree.ParseText(@" class C { void M(int x) { L1: ; // 1 if (x == 0) goto L1; //firstIf if (x == 1) goto L2; if (x == 3) goto L3; L3: ; //label3 L2: ; // 2 if(x == 4) goto L3; } } "); var Mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location); var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { Mscorlib }); var model = compilation.GetSemanticModel(tree); //Choose first and last statements var firstIf = tree.GetRoot().DescendantNodes().OfType <IfStatementSyntax>().First(); var label3 = tree.GetRoot().DescendantNodes().OfType <LabeledStatementSyntax>().Skip(1).Take(1).Single(); ControlFlowAnalysis result = model.AnalyzeControlFlow(firstIf, label3); //DebugLogger.Instance.WriteLine(result.EntryPoints); //1 - L3: ; //Label 3 is a candidate entry point within these statements //DebugLogger.Instance.WriteLine(result.ExitPoints); //2 - goto L1;,goto L2; //goto L1 and goto L2 and candidate exit points }
public void _UnreachableCode() { var tree = CSharpSyntaxTree.ParseText(@" class C { void M(int x) { return; if(x == 0) //-+ Start is unreachable System.//DebugLogger.Instance.WriteLine(""Hello""); // | L1: //-+ End is unreachable } } "); var Mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location); var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { Mscorlib }); var model = compilation.GetSemanticModel(tree); //Choose first and last statements var firstIf = tree.GetRoot().DescendantNodes().OfType <IfStatementSyntax>().Single(); var label1 = tree.GetRoot().DescendantNodes().OfType <LabeledStatementSyntax>().Single(); ControlFlowAnalysis result = model.AnalyzeControlFlow(firstIf, label1); //DebugLogger.Instance.WriteLine(result.StartPointIsReachable); //False //DebugLogger.Instance.WriteLine(result.EndPointIsReachable); //False }
public MethodBody Execute() { MethodBody bytecodeBody = new MethodBody(MethodBodyKind.Bytecode); bytecodeBody.Parameters.AddRange(_tacBody.Parameters); bytecodeBody.LocalVariables.AddRange(_tacBody.LocalVariables); //bytecodeBody.ExceptionInformation.AddRange(_tacBody.ExceptionInformation); bytecodeBody.MaxStack = 0; if (_tacBody.Instructions.Count > 0) { InstructionConverter instructionConverter = new InstructionConverter(); ControlFlowAnalysis cfanalysis = new ControlFlowAnalysis(_tacBody); // exceptions disabled for now ControlFlowGraph cfg = cfanalysis.GenerateNormalControlFlow(); //FillExceptionHandlersStart(); foreach (CFGNode node in cfg.ForwardOrder) { ProcessBasicBlock(bytecodeBody, node, instructionConverter); } bytecodeBody.Instructions.AddRange(instructionConverter.Result); } return(bytecodeBody); }
// this function applies analysis-net analyses on the method defined in our assembly (methodDefinition) // the result is a typed stackless three address code representation of the orignal method definition body // you can 'out' the control flow graph because it can be reused for another analysis public static MethodBody ThreeAddressCode(IMethodDefinition methodDefinition, MetadataReaderHost host, out ControlFlowGraph cfg) { if (methodDefinition.IsAbstract || methodDefinition.IsExternal) { cfg = null; return(null); } var disassembler = new Disassembler(host, methodDefinition, null); var methodBody = disassembler.Execute(); var cfAnalysis = new ControlFlowAnalysis(methodBody); //var cfg = cfAnalysis.GenerateNormalControlFlow(); cfg = cfAnalysis.GenerateExceptionalControlFlow(); var splitter = new WebAnalysis(cfg, methodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var typeAnalysis = new TypeInferenceAnalysis(cfg, methodDefinition.Type); typeAnalysis.Analyze(); methodBody.UpdateVariables(); return(methodBody); }
public void AnalyzeRegionControlFlow() { TestCode testCode = new TestCode(@" class C { public void F() { goto L1; // 1 /*start*/ L1: ; if (false) return; /*end*/ goto L1; // 2 } }"); StatementSyntax firstStatement, lastStatement; testCode.GetStatementsBetweenMarkers(out firstStatement, out lastStatement); ControlFlowAnalysis regionControlFlowAnalysis = testCode.SemanticModel.AnalyzeControlFlow(firstStatement, lastStatement); Assert.AreEqual(1, regionControlFlowAnalysis.EntryPoints.Count()); Assert.AreEqual(1, regionControlFlowAnalysis.ExitPoints.Count()); Assert.IsTrue(regionControlFlowAnalysis.EndPointIsReachable); BlockSyntax methodBody = testCode.SyntaxTree .GetRoot() .DescendantNodes() .OfType <MethodDeclarationSyntax>() .First() .Body; regionControlFlowAnalysis = testCode.SemanticModel.AnalyzeControlFlow(methodBody, methodBody); Assert.IsFalse(regionControlFlowAnalysis.EndPointIsReachable); }
public void _BasicControlFlow() { var tree = CSharpSyntaxTree.ParseText(@" class C { void M() { for (int i = 0; i < 10; i++) { if (i == 3) continue; if (i == 8) break; } } } "); var Mscorlib = PortableExecutableReference.CreateFromFile(typeof(object).Assembly.Location); var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { Mscorlib }); var model = compilation.GetSemanticModel(tree); var firstFor = tree.GetRoot().DescendantNodes().OfType <ForStatementSyntax>().Single(); ControlFlowAnalysis result = model.AnalyzeControlFlow(firstFor.Statement); //DebugLogger.Instance.WriteLine(result.Succeeded); //True //DebugLogger.Instance.WriteLine(result.ExitPoints.Count()); //2 - continue, and break }
public static async Task ComputeRefactoringAsync(RefactoringContext context, MethodDeclarationSyntax methodDeclaration) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeMethodReturnTypeToVoid) && methodDeclaration.ReturnType?.IsVoid() == false && methodDeclaration.Body?.Statements.Count > 0 && !methodDeclaration.IsIterator() && context.SupportsSemanticModel) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); if (!IsAsyncMethodThatReturnsTask(methodDeclaration, semanticModel, context.CancellationToken)) { ControlFlowAnalysis analysis = semanticModel.AnalyzeControlFlow(methodDeclaration.Body); if (analysis.Succeeded && analysis.ReturnStatements.All(node => IsReturnStatementWithoutExpression(node))) { context.RegisterRefactoring( "Change return type to 'void'", cancellationToken => { return(ChangeTypeRefactoring.ChangeTypeAsync( context.Document, methodDeclaration.ReturnType, CSharpFactory.VoidType(), cancellationToken)); }); } } } }
MethodBlockAnalysis(MethodDeclarationSyntax methodDeclarationSyntax, BlockSyntax methodBodySyntax, SemanticModel semanticModel, ControlFlowAnalysis controlFlow, DataFlowAnalysis dataFlow) { MethodDeclarationSyntax = methodDeclarationSyntax; SemanticModel = semanticModel; ControlFlowAnalysis = controlFlow; DataFlowAnalysis = dataFlow; BodyBlock = methodBodySyntax; }
public static TypeSyntax GetReturnType(BlockSyntax code, SemanticModel model) { if (code == null) { return(@void); } ControlFlowAnalysis cfa = model.AnalyzeControlFlow(code); if (!cfa.ReturnStatements.Any()) { return(@void); } ITypeSymbol rt = null; foreach (var rs in cfa.ReturnStatements) { ReturnStatementSyntax rss = (ReturnStatementSyntax)rs; ITypeSymbol type = model.GetSpeculativeTypeInfo(rss.Expression.SpanStart, rss.Expression, SpeculativeBindingOption.BindAsExpression).Type; if (type == null) { continue; } if (type.TypeKind == TypeKind.Error) { rt = null; break; } if (rt == null) { rt = type; } else if (rt != type) { rt = null; break; } } if (rt == null) { return(@object); } var syntaxReference = rt.DeclaringSyntaxReferences.SingleOrDefault(); return(CSharp.ParseTypeName(rt.ToString())); }
public void GenerateCFG(MethodDefinition method) { var methodInfo = programInfo.GetOrAdd(method); //GenerateIL(method); GenerateTAC(method); if (!methodInfo.Contains("CFG")) { // Control-flow var cfAnalysis = new ControlFlowAnalysis(method.Body); var cfg = cfAnalysis.GenerateNormalControlFlow(); //var cfg = cfAnalysis.GenerateExceptionalControlFlow(); var domAnalysis = new DominanceAnalysis(cfg); domAnalysis.Analyze(); domAnalysis.GenerateDominanceTree(); //// Optional //var loopAnalysis = new NaturalLoopAnalysis(cfg); //loopAnalysis.Analyze(); var domFrontierAnalysis = new DominanceFrontierAnalysis(cfg); domFrontierAnalysis.Analyze(); var pdomAnalysis = new PostDominanceAnalysis(cfg); pdomAnalysis.Analyze(); pdomAnalysis.GeneratePostDominanceTree(); var pdomFrontierAnalysis = new PostDominanceFrontierAnalysis(cfg); pdomFrontierAnalysis.Analyze(); var controlDependenceAnalysis = new ControlDependenceAnalysis(cfg); controlDependenceAnalysis.Analyze(); var text = DGMLSerializer.Serialize(cfg); methodInfo.Add("CFG", cfg); methodInfo.Add("CFG_TEXT", text); text = DGMLSerializer.SerializeDominanceTree(cfg); methodInfo.Add("DT_TEXT", text); text = DGMLSerializer.SerializePostDominanceTree(cfg); methodInfo.Add("PDT_TEXT", text); text = DGMLSerializer.SerializeControlDependenceGraph(cfg); methodInfo.Add("CDG_TEXT", text); } }
public void Execute() { var disassembler = new Backend.Transformations.Disassembler(host, methodDefinition, sourceLocationProvider); var methodBody = disassembler.Execute(); MethodBody = methodBody; var cfAnalysis = new ControlFlowAnalysis(methodBody); ControlFlowGraph = cfAnalysis.GenerateExceptionalControlFlow(); var splitter = new WebAnalysis(ControlFlowGraph, methodBody.MethodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var typeAnalysis = new TypeInferenceAnalysis(ControlFlowGraph, methodBody.MethodDefinition.Type); typeAnalysis.Analyze(); //var forwardCopyAnalysis = new ForwardCopyPropagationAnalysis(Traverser.CFG); //forwardCopyAnalysis.Analyze(); //forwardCopyAnalysis.Transform(methodBody); //var backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(Traverser.CFG); //backwardCopyAnalysis.Analyze(); //backwardCopyAnalysis.Transform(methodBody); // TinyBCT transformations var fieldInitialization = new FieldInitialization(methodBody); fieldInitialization.Transform(); if (!Settings.AddressesEnabled()) { var refAlias = new RefAlias(methodBody); refAlias.Transform(); } // execute this after RefAlias! var immutableArguments = new ImmutableArguments(methodBody); immutableArguments.Transform(); methodBody.RemoveUnusedLabels(); }
protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken) { var semanticModel = await _document.GetSemanticModelAsync(cancellationToken) .ConfigureAwait(false); if (semanticModel == null || cancellationToken.IsCancellationRequested) { return(_document); } var pxContext = new PXContext(semanticModel.Compilation); var oldRoot = await _document.GetSyntaxRootAsync(cancellationToken) .ConfigureAwait(false); if (oldRoot == null || cancellationToken.IsCancellationRequested) { return(_document); } var newRoot = oldRoot; var generator = SyntaxGenerator.GetGenerator(_document); var newReturnType = GetNewReturnType(generator, semanticModel, cancellationToken); var newParametersList = GetNewParametersList(generator, pxContext, cancellationToken); if (newReturnType == null || newParametersList == null || cancellationToken.IsCancellationRequested) { return(_document); } var newMethod = _method.WithReturnType(newReturnType) .WithParameterList(newParametersList); ControlFlowAnalysis controlFlow = semanticModel.AnalyzeControlFlow(_method.Body); if (controlFlow != null && controlFlow.Succeeded && controlFlow.ReturnStatements.IsEmpty) { newMethod = AddReturnStatement(newMethod, generator); } newRoot = newRoot.ReplaceNode(_method, newMethod); newRoot = AddCollectionsUsing(newRoot, generator, cancellationToken); if (cancellationToken.IsCancellationRequested) { return(_document); } return(_document.WithSyntaxRoot(newRoot)); }
public static async Task ComputeRefactoringAsync(RefactoringContext context, MethodDeclarationSyntax methodDeclaration) { if (context.IsRefactoringEnabled(RefactoringIdentifiers.ChangeMethodReturnTypeToVoid)) { TypeSyntax returnType = methodDeclaration.ReturnType; if (returnType?.IsVoid() == false) { BlockSyntax body = methodDeclaration.Body; if (body != null) { SyntaxList <StatementSyntax> statements = body.Statements; if (statements.Any() && !ContainsOnlyThrowStatement(statements) && !methodDeclaration.ContainsYield()) { SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false); IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken); if (methodSymbol?.IsOverride == false && !methodSymbol.ImplementsInterfaceMember() && !IsAsyncMethodThatReturnsTask(methodSymbol, semanticModel)) { ControlFlowAnalysis analysis = semanticModel.AnalyzeControlFlow(body); if (analysis.Succeeded && analysis.ReturnStatements.All(IsReturnStatementWithoutExpression)) { context.RegisterRefactoring( "Change return type to 'void'", cancellationToken => { return(ChangeTypeRefactoring.ChangeTypeAsync( context.Document, returnType, CSharpFactory.VoidType(), cancellationToken)); }); } } } } } } }
protected bool IsReacheableByControlFlow(StatementSyntax statement) { ControlFlowAnalysis controlFlow = null; try { controlFlow = SemanticModel.AnalyzeControlFlow(statement); } catch { //If there was some kind of error during analysis we should assume the worst case - that assignment is reacheable return(true); } return(controlFlow?.Succeeded != true || controlFlow.EndPointIsReachable); }
static void Main(string[] args) { string parseText = @" class MyClass { void MyMethod() { for (int i = 0; i < 10; i++) { if (i == 3) continue; if (i == 8) break; } } } "; if (args.Any()) { var path = args[0]; if (File.Exists(path)) { parseText = File.ReadAllText(path); } } var tree = CSharpSyntaxTree.ParseText(parseText); var Mscorlib = MetadataReference.CreateFromFile(Assembly.GetExecutingAssembly().Location); var compilation = CSharpCompilation.Create("MyCompilation", syntaxTrees: new[] { tree }, references: new[] { Mscorlib }); var model = compilation.GetSemanticModel(tree); // control flow analysis of for statement var firstFor = tree.GetRoot().DescendantNodes().OfType <ForStatementSyntax>().Single(); ControlFlowAnalysis result = model.AnalyzeControlFlow(firstFor.Statement); Console.WriteLine("Succeeded: " + result.Succeeded); Console.WriteLine("Exit Points:"); foreach (var exitPoint in result.ExitPoints) { Console.WriteLine("\t" + exitPoint.Kind().ToString()); } Console.ReadKey(); }
public static TypeSyntax GetReturnType(BlockSyntax code, SemanticModel model) { ControlFlowAnalysis cfa = model.AnalyzeControlFlow(code); if (!cfa.ReturnStatements.Any()) { return(@void); } ITypeSymbol rt = null; foreach (var rs in cfa.ReturnStatements) { ReturnStatementSyntax rss = (ReturnStatementSyntax)rs; ITypeSymbol type = model.GetSpeculativeTypeInfo(rss.Expression.SpanStart, rss.Expression, SpeculativeBindingOption.BindAsExpression).Type; if (type == null) { continue; } if (type.TypeKind == TypeKind.Error) { rt = null; break; } if (rt == null) { rt = type; } else if (rt != type) { rt = null; break; } } if (rt == null) { return(@dynamic); } return(CSharp.ParseTypeName(rt.Name)); }
internal string CalcTryUsingFuncInfo(DataFlowAnalysis dataFlow, ControlFlowAnalysis ctrlFlow, out List <string> inputs, out List <string> outputs, out string paramsStr) { var sbIn = new StringBuilder(); var sbOut = new StringBuilder(); inputs = new List <string>(); outputs = new List <string>(); string prestrIn = string.Empty; string prestrOut = string.Empty; if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName)) { sbIn.Append(ReturnVarName); prestrIn = ", "; sbOut.Append(ReturnVarName); prestrOut = ", "; } foreach (var v in dataFlow.DataFlowsIn) { if (v.Name == "this") { continue; } inputs.Add(v.Name); sbIn.Append(prestrIn); sbIn.Append(v.Name); prestrIn = ", "; } foreach (var v in dataFlow.DataFlowsOut) { outputs.Add(v.Name); if (!inputs.Contains(v.Name)) { sbIn.Append(prestrIn); sbIn.Append(v.Name); prestrIn = ", "; } sbOut.Append(prestrOut); sbOut.Append(v.Name); prestrOut = ", "; } paramsStr = sbIn.ToString(); return(sbOut.ToString()); }
private static void ComputeRefactoring( RefactoringContext context, IMethodSymbol methodSymbol, SemanticModel semanticModel, BlockSyntax body, TypeSyntax returnType) { if (methodSymbol?.IsOverride != false) { return; } if (methodSymbol.ImplementsInterfaceMember()) { return; } if (methodSymbol.IsAsync && methodSymbol.ReturnType.HasMetadataName(MetadataNames.System_Threading_Tasks_Task)) { return; } ControlFlowAnalysis analysis = semanticModel.AnalyzeControlFlow(body); if (!analysis.Succeeded) { return; } if (!analysis.ReturnStatements.All(f => (f as ReturnStatementSyntax)?.Expression == null)) { return; } Document document = context.Document; context.RegisterRefactoring( "Change return type to 'void'", ct => document.ReplaceNodeAsync(returnType, CSharpFactory.VoidType().WithTriviaFrom(returnType), ct), RefactoringDescriptors.ChangeMethodReturnTypeToVoid); }
public bool CatchClauseCatchesCoroutineStopped(CatchClauseSyntax catchClause, SemanticModel model, out bool rethrows) { rethrows = false; if (catchClause.Declaration != null) { INamedTypeSymbol exceptionSymbol = model.GetSymbolInfo(catchClause.Declaration.Type).Symbol as INamedTypeSymbol; if (exceptionSymbol == null) { return(false); } if (exceptionSymbol != ExceptionType && exceptionSymbol != CoroutineStoppedExceptionType) { return(false); } if (RethrowsCoroutineStoppedException(catchClause, model)) { rethrows = true; return(true); } } ControlFlowAnalysis controlFlowResult = model.AnalyzeControlFlow(catchClause.Block); // Check if this catch always rethrows if (controlFlowResult.Succeeded && !controlFlowResult.EndPointIsReachable && controlFlowResult.ExitPoints.Length == 0 && controlFlowResult.ReturnStatements.Length == 0) { rethrows = true; } return(true); }
private void AnalyzeCatchBlock(SyntaxNodeAnalysisContext context) { // As always skip generated code. if (context.IsGeneratedOrNonUserCode()) { return; } CatchClauseSyntax theCatch = (CatchClauseSyntax)context.Node; // I want to be smart about how I look at the catch blocks as the control flow could // be slow on very large blocks. Consequently, I only want to look at those blocks // that don't have any diagnostics (errors) in them. TextSpan span = theCatch.GetLocation().SourceSpan; var allDiagnostics = context.SemanticModel.Compilation.GetDiagnostics(); for (Int32 i = 0; i < allDiagnostics.Length; i++) { if (allDiagnostics[i].Location.SourceSpan.IntersectsWith(span)) { return; } } // Take a look at the control flow. ControlFlowAnalysis flowAnalysis = context.SemanticModel.AnalyzeControlFlow(theCatch.Block); if (flowAnalysis.Succeeded) { if ((flowAnalysis.ReturnStatements.Length == 0) && (flowAnalysis.EndPointIsReachable == false) && (flowAnalysis.EntryPoints.Length == 0)) { return; } // Now we know this catch block either eats the exception or has a return. var diagnostic = Diagnostic.Create(Rule, theCatch.GetLocation()); context.ReportDiagnostic(diagnostic); } }
public static void transformBody(MethodBody methodBody) { var cfAnalysis = new ControlFlowAnalysis(methodBody); //var cfg = cfAnalysis.GenerateNormalControlFlow(); Traverser.CFG = cfAnalysis.GenerateExceptionalControlFlow(); var splitter = new WebAnalysis(Traverser.CFG, methodBody.MethodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var typeAnalysis = new TypeInferenceAnalysis(Traverser.CFG, methodBody.MethodDefinition.Type); typeAnalysis.Analyze(); //var forwardCopyAnalysis = new ForwardCopyPropagationAnalysis(Traverser.CFG); //forwardCopyAnalysis.Analyze(); //forwardCopyAnalysis.Transform(methodBody); //var backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(Traverser.CFG); //backwardCopyAnalysis.Analyze(); //backwardCopyAnalysis.Transform(methodBody); // TinyBCT transformations if (!Settings.NewAddrModelling) { var refAlias = new RefAlias(methodBody); refAlias.Transform(); var immutableArguments = new ImmutableArguments(methodBody); immutableArguments.Transform(); var fieldInitialization = new FieldInitialization(methodBody); fieldInitialization.Transform(); } methodBody.RemoveUnusedLabels(); }
private IEnumerable <MutantInfo> DeleteStatement(SyntaxNode node) { var _semanticModel = _compiler.GetSemanticModel(node.SyntaxTree); // Note: Roslyn does not seem to like empty block statements. StatementSyntax nop = SyntaxFactory.ParseStatement(";"); DataFlowAnalysis dataFlow = _semanticModel.AnalyzeDataFlow(node); ControlFlowAnalysis controlFlow = _semanticModel.AnalyzeControlFlow(node); // statements with only side effects and no returns or exceptions trivially can be erased if (!controlFlow.ExitPoints.Any() && controlFlow.EndPointIsReachable) { if (!dataFlow.VariablesDeclared.Any() || node is BlockSyntax) // || !dataFlow.ReadOutside.Any()) { yield return(new MutantInfo(lineID, node, nop, "Deleted statement executed by test")); } } if (node is ForStatementSyntax && controlFlow.EndPointIsReachable) { yield return(new MutantInfo(lineID, node, nop, "Deleted entire for loop")); } }
public override SyntaxNode VisitBlock(BlockSyntax node) { SyntaxList <StatementSyntax> statements = node.Statements; // eliminate unreachable statements (cosmetic) List <int> remove = new List <int>(); for (int i = 0; i < statements.Count; i++) { try { ControlFlowAnalysis cfa = semanticModel.AnalyzeControlFlow(statements[i]); if (!cfa.StartPointIsReachable) { remove.Add(i); } } catch (ArgumentException) { // probably node not in tree (because we rewrote it) // do nothing and come back next time Debug.Assert(Changed); break; } } if (remove.Count != 0) { Changed = true; for (int i = remove.Count - 1; i >= 0; i--) { statements = statements.RemoveAt(remove[i]); } node = node.WithStatements(statements); } return(base.VisitBlock(node)); }
public void AnalysisOnForCycle() { var source = @" class C { void M() { for (int i = 0; i < 10; i++) { if (i == 3) continue; return; if (i == 8) break; } } } "; var tree = CSharpSyntaxTree.ParseText(source); var model = GetSemanticModel(tree); var firstFor = tree.GetRoot().DescendantNodes().OfType <ForStatementSyntax>().Single(); ControlFlowAnalysis result = model.AnalyzeControlFlow(firstFor.Statement); Trace.WriteLine(source); Trace.WriteLine(""); Trace.WriteLine($"Is start point reachable: {result.StartPointIsReachable}"); Trace.WriteLine($"Is end point reachable: {result.EndPointIsReachable}"); foreach (var exitPoint in result.ExitPoints) { Trace.WriteLine($"Exit points: {exitPoint}"); } foreach (var returnStatements in result.ReturnStatements) { Trace.WriteLine($"Resturnt statements: {returnStatements}"); } }
public static void TransformToTac(MethodDefinition method) { Disassembler disassembler = new Disassembler(method); MethodBody methodBody = disassembler.Execute(); method.Body = methodBody; ControlFlowAnalysis cfAnalysis = new ControlFlowAnalysis(method.Body); //var cfg = cfAnalysis.GenerateNormalControlFlow(); Backend.Model.ControlFlowGraph cfg = cfAnalysis.GenerateExceptionalControlFlow(); WebAnalysis splitter = new WebAnalysis(cfg); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); TypeInferenceAnalysis typeAnalysis = new TypeInferenceAnalysis(cfg, method.ReturnType); typeAnalysis.Analyze(); // Copy Propagation ForwardCopyPropagationAnalysis forwardCopyAnalysis = new ForwardCopyPropagationAnalysis(cfg); forwardCopyAnalysis.Analyze(); forwardCopyAnalysis.Transform(methodBody); BackwardCopyPropagationAnalysis backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(cfg); backwardCopyAnalysis.Analyze(); backwardCopyAnalysis.Transform(methodBody); methodBody.UpdateVariables(); }
public MethodCfgAndTac AnalyzeIntraProcedural(IMethodDefinition methodDefinition) { // System.Console.WriteLine("Traversing: {0}", methodDefinition.GetName()); if (Stubber.SuppressM(methodDefinition)) { return(null); } if (methodDefinition.IsExternal) { return(null); } if (methodDefinition.IsAbstract) { return(null); } ITypeDefinition containingDefn = methodDefinition.ContainingTypeDefinition; ISourceLocationProvider sourceLocationProvider = null; if (containingDefn != null) { IModule mod = TypeHelper.GetDefiningUnit(containingDefn) as IModule; if (moduleToPdbMap.ContainsKey(mod)) { sourceLocationProvider = moduleToPdbMap[mod]; } else { if (!(mod == null || mod == Dummy.Module || mod == Dummy.Assembly)) { sourceLocationProvider = GetPdbReader(mod.Location); moduleToPdbMap[mod] = sourceLocationProvider; } } } var disassembler = new Disassembler(host, methodDefinition, sourceLocationProvider); var methodBody = disassembler.Execute(); var cfAnalysis = new ControlFlowAnalysis(methodBody); // var cfg = cfAnalysis.GenerateNormalControlFlow(); var cfg = cfAnalysis.GenerateExceptionalControlFlow(); var domAnalysis = new DominanceAnalysis(cfg); domAnalysis.Analyze(); domAnalysis.GenerateDominanceTree(); var loopAnalysis = new NaturalLoopAnalysis(cfg); loopAnalysis.Analyze(); var domFrontierAnalysis = new DominanceFrontierAnalysis(cfg); domFrontierAnalysis.Analyze(); var splitter = new WebAnalysis(cfg, methodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var typeAnalysis = new TypeInferenceAnalysis(cfg, methodDefinition.Type); typeAnalysis.Analyze(); var forwardCopyAnalysis = new ForwardCopyPropagationAnalysis(cfg); forwardCopyAnalysis.Analyze(); forwardCopyAnalysis.Transform(methodBody); // backwardCopyAnalysis is buggy - it says so in the source file - see notes in src/test // var backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(cfg); // backwardCopyAnalysis.Analyze(); // backwardCopyAnalysis.Transform(methodBody); var liveVariables = new LiveVariablesAnalysis(cfg); liveVariables.Analyze(); var ssa = new StaticSingleAssignment(methodBody, cfg); ssa.Transform(); ssa.Prune(liveVariables); methodBody.UpdateVariables(); MethodCfgAndTac mct = new MethodCfgAndTac(cfg, methodBody); foreach (IExceptionHandlerBlock ehInfo in disassembler.GetExceptionHandlers()) { if (ehInfo is CatchExceptionHandler) { mct.ehInfoList.Add(ehInfo as CatchExceptionHandler); } } return(mct); }
internal string CalcTryUsingFuncOptions(DataFlowAnalysis dataFlow, ControlFlowAnalysis ctrlFlow, List <string> inputs, List <string> outputs) { string returnType = "System.Int32"; string returnTypeKind = "TypeKind.Struct"; bool returnTypeIsExtern = false; var sb = new StringBuilder(); sb.AppendFormat("needfuncinfo({0}), rettype(return, {1}, {2}, 0, true)", NeedFuncInfo ? "true" : "false", returnType, returnTypeKind); if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName)) { returnType = ClassInfo.GetFullName(SemanticInfo.ReturnType); if (string.IsNullOrEmpty(returnType)) { returnType = "null"; } returnTypeKind = "TypeKind." + SemanticInfo.ReturnType.TypeKind.ToString(); returnTypeIsExtern = !SymbolTable.Instance.IsCs2DslSymbol(SemanticInfo.ReturnType); sb.Append(", "); sb.AppendFormat("rettype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false"); } foreach (var v in dataFlow.DataFlowsOut) { sb.Append(", "); int refOrOut = 2; if (inputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("rettype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } if (ctrlFlow.ReturnStatements.Length > 0 && !string.IsNullOrEmpty(ReturnVarName)) { sb.Append(", "); sb.AppendFormat("paramtype({0}, {1}, {2}, 1, {3})", ReturnVarName, returnType, returnTypeKind, returnTypeIsExtern ? "true" : "false"); } foreach (var v in dataFlow.DataFlowsIn) { if (v.Name == "this") { continue; } sb.Append(", "); int refOrOut = 0; if (outputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } foreach (var v in dataFlow.DataFlowsOut) { sb.Append(", "); int refOrOut = 2; if (inputs.Contains(v.Name)) { refOrOut = 1; } var psym = v as IParameterSymbol; var lsym = v as ILocalSymbol; if (null != psym) { var type = ClassInfo.GetFullName(psym.Type); var typeKind = psym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(psym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } else if (null != lsym) { var type = ClassInfo.GetFullName(lsym.Type); var typeKind = lsym.Type.TypeKind.ToString(); bool isExtern = !SymbolTable.Instance.IsCs2DslSymbol(lsym.Type); if (string.IsNullOrEmpty(type)) { type = "null"; } sb.AppendFormat("paramtype({0}, {1}, {2}, {3}, {4})", v.Name, type, typeKind, refOrOut, isExtern ? "true" : "false"); } } return(sb.ToString()); }
public static ControlFlowGraph DoAnalysisPhases(this IMethodDefinition method, IMetadataHost host, ISourceLocationProvider locationProvider, IEnumerable <IMethodReference> methodsToTryToInline = null) { AnalysisStats.extraAnalysisOverHead.Start(); var disassembler = new Disassembler(host, method, locationProvider); var methodBody = disassembler.Execute(); MethodBodyProvider.Instance.AddBody(method, methodBody); if (methodsToTryToInline != null) { DoInlining(method, host, methodBody, locationProvider, methodsToTryToInline); } var cfAnalysis = new ControlFlowAnalysis(methodBody); //var cfg = cfAnalysis.GenerateExceptionalControlFlow(); var cfg = cfAnalysis.GenerateNormalControlFlow(); var domAnalysis = new DominanceAnalysis(cfg); domAnalysis.Analyze(); domAnalysis.GenerateDominanceTree(); var loopAnalysis = new NaturalLoopAnalysis(cfg); loopAnalysis.Analyze(); var domFrontierAnalysis = new DominanceFrontierAnalysis(cfg); domFrontierAnalysis.Analyze(); var splitter = new WebAnalysis(cfg, method); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var analysis = new TypeInferenceAnalysis(cfg, methodBody.MethodDefinition.Type); analysis.Analyze(); var copyProgapagtion = new ForwardCopyPropagationAnalysis(cfg); copyProgapagtion.Analyze(); copyProgapagtion.Transform(methodBody); //var backwardCopyProgapagtion = new BackwardCopyPropagationAnalysis(cfg); //backwardCopyProgapagtion.Analyze(); //backwardCopyProgapagtion.Transform(methodBody); var liveVariables = new LiveVariablesAnalysis(cfg); var resultLiveVar = liveVariables.Analyze(); var ssa = new StaticSingleAssignment(methodBody, cfg); ssa.Transform(); ssa.Prune(liveVariables); methodBody.UpdateVariables(); AnalysisStats.extraAnalysisOverHead.Stop(); return(cfg); }
//string _code = String.Empty; /// <summary> /// For a given methodDefinition, create a CFG and run basic analyses such as /// stack removal, SSA transformation, live-variables analysis, and copy-propagation. /// </summary> /// <param name="methodDefinition"></param> /// <returns></returns> private ControlFlowGraph PrepareMethod(IMethodDefinition methodDefinition) { var sw2 = new Stopwatch(); sw2.Start(); var disassembler = new Disassembler(mhost, methodDefinition, sourceLocationProvider); var methodBody = disassembler.Execute(); var cfAnalysis = new ControlFlowAnalysis(methodBody); var cfg = cfAnalysis.GenerateNormalControlFlow(); var domAnalysis = new DominanceAnalysis(cfg); domAnalysis.Analyze(); domAnalysis.GenerateDominanceTree(); var loopAnalysis = new NaturalLoopAnalysis(cfg); loopAnalysis.Analyze(); var domFrontierAnalysis = new DominanceFrontierAnalysis(cfg); domFrontierAnalysis.Analyze(); var splitter = new WebAnalysis(cfg, methodDefinition); splitter.Analyze(); splitter.Transform(); methodBody.UpdateVariables(); var analysis = new TypeInferenceAnalysis(cfg, methodBody.MethodDefinition.Type); analysis.Analyze(); var copyProgapagtion = new ForwardCopyPropagationAnalysis(cfg); copyProgapagtion.Analyze(); copyProgapagtion.Transform(methodBody); var backwardCopyProgapagtion = new BackwardCopyPropagationAnalysis(cfg); backwardCopyProgapagtion.Analyze(); backwardCopyProgapagtion.Transform(methodBody); var liveVariables = new LiveVariablesAnalysis(cfg); var resultLiveVar = liveVariables.Analyze(); var ssa = new StaticSingleAssignment(methodBody, cfg); ssa.Transform(); ssa.Prune(liveVariables); methodBody.UpdateVariables(); sw2.Stop(); this.nonAnalysisOverhead = sw2.Elapsed; return(cfg); //var cfg = ControlFlowGraph.GenerateNormalControlFlow(methodBody); //ControlFlowGraph.ComputeDominators(cfg); //ControlFlowGraph.IdentifyLoops(cfg); //ControlFlowGraph.ComputeDominatorTree(cfg); //ControlFlowGraph.ComputeDominanceFrontiers(cfg); //// Uniquely rename stack variables. //var splitter = new WebAnalysis(cfg); //splitter.Analyze(); //splitter.Transform(); //methodBody.UpdateVariables(); //// Infer types for stack variables. //var typeAnalysis = new TypeInferenceAnalysis(cfg); //typeAnalysis.Analyze(); //var backwardCopyAnalysis = new BackwardCopyPropagationAnalysis(cfg); //backwardCopyAnalysis.Analyze(); //backwardCopyAnalysis.Transform(methodBody); //var lva = new LiveVariablesAnalysis(cfg); //lva.Analyze(); //var ssa = new StaticSingleAssignmentAnalysis(methodBody, cfg); //ssa.Transform(); //ssa.Prune(lva); //methodBody.UpdateVariables(); ////_code = methodBody.ToString(); //return cfg; }
private void ComputeDependencyGraph(ControlFlowAnalysis cfg) { //var dependencyGraph = new DependencyGraph(); //foreach (var cfgNode in cfg.ForwardOrder) //{ // var ptg = result[cfgNode.Id].Output; // foreach (var instruction in cfgNode.Instructions) // { // var uses = instruction.UsedVariables; // var defs = instruction.ModifiedVariables; // var access = ""; // //if (instruction is StoreInstruction) // //{ // // var store = instruction as StoreInstruction; // // if (store.Result is InstanceFieldAccess) // // { // // var fieldAccess = store.Result as InstanceFieldAccess; // // access = fieldAccess.FieldName; // // defs.Add(store.Operand); // // LastDefSet(store.Operand, fieldAccess.Field, cfgNode.Id, ptg); // // } // //} // //else // //{ // //} // //// TODO: Complete // foreach (var def in defs) // { // var v = def.Variables.Single(); // if (ptg.Variables.Contains(v)) // { // var ptgNodes = ptg.GetTargets(v); // foreach (var ptgNode in ptgNodes) // { // var depNode = new DependencyInfo(ptgNode, access); // dependencyGraph.AddVertex(depNode); // var useAccess = ""; // if (instruction is LoadInstruction) // { // var load = instruction as LoadInstruction; // if (load.Operand is InstanceFieldAccess) // { // var fieldAccess = load.Operand as InstanceFieldAccess; // useAccess = fieldAccess.FieldName; // uses.Add(load.Result); // } // } // foreach (var use in uses) // { // var v2 = use.Variables.Single(); // if (ptg.Variables.Contains(v2)) // { // var ptgUseNodes = ptg.GetTargets(v2); // foreach (var ptgNode2 in ptgUseNodes) // { // var useNode = new DependencyInfo(ptgNode2, useAccess); // dependencyGraph.ConnectVertex(depNode, useNode); // } // } // } // } // } // } // } //} //System.Console.WriteLine(dependencyGraph); }