private BlockStatement DecompileObject(CodeObject obj) { var context = new DecompileContext(obj); var m = Script.Methods[obj]; m.Compact(); context.BuildCFG(m.Instructions); var pass1 = new RegMemberPass(); var entry = pass1.Process(context, new BlockStatement()); var pass2 = new ExpressionPass(); entry = pass2.Process(context, entry); var pass3 = new ControlFlowPass(); entry = pass3.Process(context, entry); var pass4 = new StatementCollectPass(); entry = pass4.Process(context, entry); m.Vars = context.Vars; return(entry); }
public void TestDecompileBlock() { var path = "..\\..\\Res\\Initialize.tjs.comp"; Module md = new Module(path); var mt = md.TopLevel.ResolveMethod(); mt.Compact(); DecompileContext context = new DecompileContext(md.TopLevel); context.ScanBlocks(mt.Instructions); context.ComputeDominators(); context.ComputeNaturalLoops(); context.FillInBlocks(mt.Instructions); var pass1 = new RegMemberPass(); var entry = pass1.Process(context, new BlockStatement()); var pass2 = new ExpressionPass(); entry = pass2.Process(context, entry); var b = context.Blocks[1]; var s1 = b.Statements.FirstOrDefault(); var pass3 = new ControlFlowPass(); entry = pass3.Process(context, entry); var c = entry.Statements.Count; foreach (var st in entry.Statements) { var s = st; } var pass4 = new StatementCollectPass(); entry = pass4.Process(context, entry); foreach (var statement in entry.Statements) { var s = statement; } var sWriter = new StringWriter(); TjsWriter writer = new TjsWriter(sWriter); writer.WriteBlock(entry); sWriter.Flush(); var result = sWriter.ToString(); }
private BoundLambda ReallyBind(NamedTypeSymbol delegateType) { var invokeMethod = DelegateInvokeMethod(delegateType); RefKind refKind; var returnType = DelegateReturnType(invokeMethod, out refKind); LambdaSymbol lambdaSymbol; Binder lambdaBodyBinder; BoundBlock block; var diagnostics = DiagnosticBag.GetInstance(); // when binding for real (not for return inference), there is still // a good chance that we could reuse a body of a lambda previously bound for // return type inference. var cacheKey = ReturnInferenceCacheKey.Create(delegateType, IsAsync); BoundLambda returnInferenceLambda; if (_returnInferenceCache.TryGetValue(cacheKey, out returnInferenceLambda) && returnInferenceLambda.InferredFromSingleType) { lambdaSymbol = returnInferenceLambda.Symbol; if ((object)LambdaSymbol.InferenceFailureReturnType != lambdaSymbol.ReturnType && lambdaSymbol.ReturnType == returnType && lambdaSymbol.RefKind == refKind) { lambdaBodyBinder = returnInferenceLambda.Binder; block = returnInferenceLambda.Body; diagnostics.AddRange(returnInferenceLambda.Diagnostics); goto haveLambdaBodyAndBinders; } } lambdaSymbol = new LambdaSymbol( binder.Compilation, binder.ContainingMemberOrLambda, _unboundLambda, cacheKey.ParameterTypes, cacheKey.ParameterRefKinds, refKind, returnType, diagnostics); lambdaBodyBinder = new ExecutableCodeBinder(_unboundLambda.Syntax, lambdaSymbol, ParameterBinder(lambdaSymbol, binder)); if (lambdaSymbol.RefKind == CodeAnalysis.RefKind.RefReadOnly) { binder.Compilation.EnsureIsReadOnlyAttributeExists(diagnostics, lambdaSymbol.DiagnosticLocation, modifyCompilationForRefReadOnly: false); } ParameterHelpers.EnsureIsReadOnlyAttributeExists(lambdaSymbol.Parameters, diagnostics, modifyCompilationForRefReadOnly: false); block = BindLambdaBody(lambdaSymbol, lambdaBodyBinder, diagnostics); ((ExecutableCodeBinder)lambdaBodyBinder).ValidateIteratorMethods(diagnostics); ValidateUnsafeParameters(diagnostics, cacheKey.ParameterTypes); haveLambdaBodyAndBinders: bool reachableEndpoint = ControlFlowPass.Analyze(binder.Compilation, lambdaSymbol, block, diagnostics); if (reachableEndpoint) { if (DelegateNeedsReturn(invokeMethod)) { // Not all code paths return a value in {0} of type '{1}' diagnostics.Add(ErrorCode.ERR_AnonymousReturnExpected, lambdaSymbol.DiagnosticLocation, this.MessageID.Localize(), delegateType); } else { block = FlowAnalysisPass.AppendImplicitReturn(block, lambdaSymbol); } } if (IsAsync && !ErrorFacts.PreventsSuccessfulDelegateConversion(diagnostics)) { if ((object)returnType != null && // Can be null if "delegateType" is not actually a delegate type. returnType.SpecialType != SpecialType.System_Void && !returnType.IsNonGenericTaskType(binder.Compilation) && !returnType.IsGenericTaskType(binder.Compilation)) { // Cannot convert async {0} to delegate type '{1}'. An async {0} may return void, Task or Task<T>, none of which are convertible to '{1}'. diagnostics.Add(ErrorCode.ERR_CantConvAsyncAnonFuncReturns, lambdaSymbol.DiagnosticLocation, lambdaSymbol.MessageID.Localize(), delegateType); } } if (IsAsync) { Debug.Assert(lambdaSymbol.IsAsync); SourceOrdinaryMethodSymbol.ReportAsyncParameterErrors(lambdaSymbol.Parameters, diagnostics, lambdaSymbol.DiagnosticLocation); } var result = new BoundLambda(_unboundLambda.Syntax, block, diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, inferReturnType: false) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; return(result); }
public void ToInstructionList() => ControlFlowPass.ToInstructionList(this);
public void ToControlFlowGraph() => ControlFlowPass.ToControlFlowGraph(this);