private void DecompileStates() { ProcessDescriptor pd = (ProcessDescriptor)_code; _templ = new MSILDecompilerTemplate() { Instance = pd.Instance.Owner, ArgumentValues = new object[0], Decompilee = _code, Method = _code.Method, Code = MethodCode.Create(_code.Method), DisallowReturnStatements = true, NestLoopsDeeply = true, TryToEliminateLoops = true, DisallowConditionals = true }; LocalVariableState initialState = _templ.ExportLocalVariableState(); GetStateInfo(_dissectionPoints[0], initialState); while (_stateWorkQueue.Any()) { StateInfo si = _stateWorkQueue.Dequeue(); MSILDecompiler decomp = new MSILDecompiler(_code, si.CFG, _instance) { Template = _templ }; _templ.AddAttribute(this); _templ.ImportLocalVariableState(si.LVState); IDecompilationResult result = decomp.Decompile(); si.StateFun = result.Decompiled; _calledMethods.AddRange(result.CalledMethods); _referencedFields.AddRange(result.ReferencedFields); } }
private void InitCoState(TAVerb tav, CoStateInfo csi) { MethodCode csc = MethodCode.Create(tav.Op.Method); MethodDescriptor md = new MethodDescriptor(tav.Op.Method, new object[0], new EVariability[0]); MSILDecompiler decomp = new MSILDecompiler(md, csc, tav.Op.Target); decomp.Template.DisallowReturnStatements = true; decomp.Template.NestLoopsDeeply = true; decomp.Template.TryToEliminateLoops = true; decomp.Template.DisallowConditionals = true; IDecompilationResult result = decomp.Decompile(); csi.StateAction = result.Decompiled; csi.DuringAction = tav.During; }
/// <summary> /// Decompiles the method to an explicit state machine representation /// </summary> /// <returns>decopmiled method</returns> public IDecompilationResult DecompileToFSM() { InitializeCFGs(); int numILStates = _stateCFGs.Length; var design = _code.GetDesign(); var owner = _code.Owner as ComponentDescriptor; var myps = _code as ProcessDescriptor; // Decompile state handlers _stateInfos = new Dictionary<StateInfo, StateInfo>(); var decomp = new MSILDecompiler(_code, _stateCFGs[1], _fsmInstance); _curTempl = decomp.Template; _curTempl.AddAttribute(this); _curTempl.DisallowReturnStatements = true; _curTempl.DisallowConditionals = true; _curTempl.DisallowLoops = true; var lvState = _curTempl.ExportLocalVariableState(); var startSI = new StateInfo(0); foreach (var kvp in _locFields) startSI.LVState[kvp.Key] = kvp.Value.Type.GetSampleInstance(ETypeCreationOptions.ForceCreation); _stateInfos[startSI] = startSI; _curSI = startSI; var stateList = new List<StateInfo>(); stateList.Add(startSI); _stateQ = new Queue<StateInfo>(); startSI.Result = decomp.Decompile(); while (_stateQ.Any()) { var nextSI = _stateQ.Dequeue(); _curSI = nextSI.Fork(nextSI.ILState); decomp = new MSILDecompiler(_code, _stateCFGs[nextSI.ILState + 1], _fsmInstance); _curTempl = decomp.Template; _curTempl.AddAttribute(this); _curTempl.DisallowReturnStatements = true; _curTempl.DisallowConditionals = true; _curTempl.DisallowLoops = true; _curSI.Result = decomp.Decompile(); stateList.Add(_curSI); _stateInfos[_curSI] = _curSI; } // Create enumeration type for state string prefix = _code.Name; string enumName = "t_" + prefix + "_state"; var stateNames = new List<string>(); for (int i = 0; i < stateList.Count; i++) { string name; if (stateList[i].HasWaitState) { name = enumName + "_await_" + i; stateNames.Add(name); } name = enumName + "_" + i; stateNames.Add(name); } int numStates = stateNames.Count; Statement[] states; SignalDescriptor stateSignal = null; if (numStates > 1) { var enumType = design.CreateEnum(enumName, stateNames); _stateValues = enumType.CILType.GetEnumValues(); var enumDefault = _stateValues.GetValue(0); int j = 0; for (int i = 0; i < stateList.Count; i++) { if (stateList[i].HasWaitState) stateList[i].WaitStateValue = _stateValues.GetValue(j++); stateList[i].StateValue = _stateValues.GetValue(j++); } // Create signals for state string stateSignalName = prefix + "_state"; stateSignal = owner.CreateSignalInstance(stateSignalName, enumDefault); _nextStateSignal = stateSignal; // Implement state joins states = new Statement[numStates]; j = 0; for (int i = 0; i < stateList.Count; i++) { if (stateList[i].HasWaitState) { var wsb = new DefaultAlgorithmBuilder(); ImplementJoin(stateList[i].JP, wsb, stateList[i]); var join = wsb.Complete(); states[j++] = join.Body; } states[j++] = stateList[i].Result.Decompiled.Body; } // Replace ProceedWithState calls with actual states for (j = 0; j < states.Length; j++) { var orgBody = states[j]; var xform = new StateAssigner(this, orgBody); var state = xform.GetAlgorithm(); states[j] = state.Body; } } else { // Implement state joins states = new Statement[1]; // Replace ProceedWithState calls with actual states var xform = new StateAssigner(this, stateList[0].Result.Decompiled.Body, true); var state = xform.GetAlgorithm(); states[0] = state.Body; } var calledMethods = stateList .SelectMany(b => b.Result.CalledMethods) .Distinct() .ToList(); var calledSyncMethods = calledMethods .Where(mci => !mci.Method.IsAsync()) .ToList(); var referencedFields = stateList .SelectMany(b => b.Result.ReferencedFields) .Distinct() .ToList(); var referencedLocals = stateList .SelectMany(b => b.Result.Decompiled.LocalVariables) .Distinct(); _coFSMs = DecompileCoFSMs(calledMethods); // Extract clock edge var predFunc = _context.CurrentProcess.Predicate; var predInstRef = LiteralReference.CreateConstant(predFunc.Target); var arg = new StackElement(predInstRef, predFunc.Target, EVariability.ExternVariable); var edge = _curTempl.GetCallExpression(predFunc.Method, arg).Expr; // Synchronous process var alg = new DefaultAlgorithmBuilder(); foreach (var v in referencedLocals) { alg.DeclareLocal(v); } alg.If(edge); // Co state machines foreach (var cofsm in _coFSMs.Order) { foreach (var argv in cofsm.Arguments) alg.DeclareLocal(argv); alg.DeclareLocal(cofsm.DoneVar); if (cofsm.ResultVar != null) alg.DeclareLocal(cofsm.ResultVar); _curCoFSM = cofsm; var weaver = new StateWeaver(this, cofsm.HandlerBody); alg.InlineCall(weaver.GetAlgorithm().Body); } // Main state machine switch statement if (numStates > 1) { var switchStmt = alg.Switch( SignalRef.Create(stateSignal, SignalRef.EReferencedProperty.Cur)); { for (int i = 0; i < states.Length; i++) { var stateValue = _stateValues.GetValue(i); alg.Case(LiteralReference.CreateConstant(stateValue)); var weaver = new StateWeaver(this, states[i]); alg.InlineCall(weaver.GetAlgorithm().Body); alg.Break(switchStmt); alg.EndCase(); } } alg.EndSwitch(); } else { var weaver = new StateWeaver(this, states[0]); alg.InlineCall(weaver.GetAlgorithm().Body); } alg.EndIf(); var syncPS = alg.Complete(); syncPS.Name = prefix + "$sync"; myps.Kind = Process.EProcessKind.Triggered; myps.Sensitivity = new ISignalOrPortDescriptor[] { ((SignalBase)predFunc.Target).Descriptor }; return new Result(syncPS, calledSyncMethods, referencedFields); }
private CoFSM DecompileToCoFSM(string prefix) { ImplStyle = EAsyncImplStyle.FSM; InjectAttributes(prefix); InitializeCFGs(); CoFSM cofsm = new CoFSM(); var args = _code.AsyncMethod.GetParameters(); cofsm.Arguments = new Variable[args.Length]; _argFields = new Dictionary<string, Variable>(); for (int i = 0; i < args.Length; i++) { string name = prefix + "_" + args[i].Name; var argv = new Variable(TypeDescriptor.GetTypeOf(_arguments[i])) { Name = name }; _argFields[args[i].Name] = argv; cofsm.Arguments[i] = argv; } int numILStates = _stateCFGs.Length; var mym = _code as MethodDescriptor; cofsm.Method = mym; cofsm.Dependencies = new HashSet<Task>(); // Create result variable and done flag cofsm.DoneVar = new Variable(typeof(bool)) { Name = prefix + "_$done" }; if (_code.AsyncMethod.ReturnType.IsGenericType && _code.AsyncMethod.ReturnType.GetGenericTypeDefinition().Equals(typeof(Task<>))) { var resultType = _code.AsyncMethod.ReturnType.GetGenericArguments()[0]; if (!resultType.Equals(typeof(void))) { cofsm.ResultVar = new Variable(resultType) { Name = prefix + "_$result" }; var builderType = typeof(AsyncTaskMethodBuilder<>).MakeGenericType(resultType); AttributeInjector.Inject(builderType, new MapToIntrinsicType(Meta.EIntrinsicTypes.IllegalRuntimeType)); var aoc1 = builderType.GetMethod("AwaitOnCompleted"); var aoc2 = builderType.GetMethod("AwaitUnsafeOnCompleted"); var rwc = new AwaitOnCompletedRewriter(); AttributeInjector.Inject(aoc1, rwc); AttributeInjector.Inject(aoc2, rwc); var sr = builderType.GetMethod("SetResult"); var rwsr = new SetResultRewriter(); AttributeInjector.Inject(sr, rwsr); var se = builderType.GetMethod("SetException"); var serw = new SetExceptionRewriter(); AttributeInjector.Inject(se, serw); AttributeInjector.Inject(builderType, new HideDeclaration()); var awaiterType = typeof(TaskAwaiter<>).MakeGenericType(resultType); AttributeInjector.Inject(awaiterType, new MapToIntrinsicType(Meta.EIntrinsicTypes.IllegalRuntimeType)); AttributeInjector.Inject(awaiterType.GetMethod("get_IsCompleted"), new RewriteIsCompleted()); AttributeInjector.Inject(awaiterType.GetMethod("OnCompleted"), new AwaitOnCompletedRewriter()); AttributeInjector.Inject(awaiterType.GetMethod("UnsafeOnCompleted"), new AwaitOnCompletedRewriter()); AttributeInjector.Inject(awaiterType.GetMethod("GetResult"), new RewriteGetResult()); AttributeInjector.Inject(awaiterType, new HideDeclaration()); } } // Decompile state handlers _stateInfos = new Dictionary<StateInfo, StateInfo>(); var decomp = new MSILDecompiler(_code, _stateCFGs[0], _fsmInstance); _curTempl = decomp.Template; _curTempl.AddAttribute(this); _curTempl.DisallowReturnStatements = true; _curTempl.DisallowConditionals = true; _curTempl.DisallowLoops = true; var lvState = _curTempl.ExportLocalVariableState(); var startSI = new StateInfo(-1); foreach (var kvp in _locFields) startSI.LVState[kvp.Key] = kvp.Value.Type.GetSampleInstance(ETypeCreationOptions.ForceCreation); _stateInfos[startSI] = startSI; _curSI = startSI; var stateList = new List<StateInfo>(); stateList.Add(startSI); _stateQ = new Queue<StateInfo>(); _curCoFSM = cofsm; startSI.Result = decomp.Decompile(); while (_stateQ.Any()) { var nextSI = _stateQ.Dequeue(); _curSI = nextSI.Fork(nextSI.ILState); decomp = new MSILDecompiler(_code, _stateCFGs[nextSI.ILState + 1], _fsmInstance); _curTempl = decomp.Template; _curTempl.AddAttribute(this); _curTempl.DisallowReturnStatements = true; _curTempl.DisallowConditionals = true; _curTempl.DisallowLoops = true; _curSI.Result = decomp.Decompile(); stateList.Add(_curSI); _stateInfos[_curSI] = _curSI; } // Create state active variables cofsm.StateActiveVars = new List<Variable>(); int j = 0; for (int i = 0; i < stateList.Count; i++) { if (stateList[i].HasWaitState) { cofsm.StateActiveVars.Add(new Variable(typeof(bool)) { Name = prefix + "_$waitStateActive" + i }); stateList[i].WaitStateValue = j++; } cofsm.StateActiveVars.Add(new Variable(typeof(bool)) { Name = prefix + "_$stateActive" + i }); stateList[i].StateValue = j++; } int numStates = j; // Replace ProceedWithState calls with actual states var states = new Statement[numStates]; j = 0; for (int i = 0; i < stateList.Count; i++) { if (stateList[i].HasWaitState) { var wsb = new DefaultAlgorithmBuilder(); ImplementJoin(stateList[i].JP, wsb, stateList[i]); //wsb.Call(stateList[i].JoinSpec, new Expression[0]); var join = wsb.Complete(); states[j++] = join.Body; } states[j++] = stateList[i].Result.Decompiled.Body; } for (j = 0; j < states.Length; j++) { var orgBody = states[j]; var xform = new CoStateAssigner(this, cofsm.StateActiveVars, orgBody, j); var state = xform.GetAlgorithm(); states[j] = state.Body; } var calledMethods = stateList .SelectMany(b => b.Result.CalledMethods) .Distinct() .ToList(); var calledSyncMethods = calledMethods .Where(mci => !mci.Method.IsAsync()) .ToList(); cofsm.CalledMethods = calledSyncMethods; // State handlers var alg = new DefaultAlgorithmBuilder(); alg.Store(cofsm.DoneVar, LiteralReference.CreateConstant(false)); for (int i = states.Length - 1; i >= 1; i--) { var lrsa = (LiteralReference)cofsm.StateActiveVars[i]; alg.If(lrsa); alg.InlineCall(states[i]); alg.EndIf(); } var handlerAlg = alg.Complete(); cofsm.HandlerBody = handlerAlg.Body; alg = new DefaultAlgorithmBuilder(); alg.Store(cofsm.DoneVar, LiteralReference.CreateConstant(false)); alg.InlineCall(states[0]); cofsm.InitialHandler = alg.Complete().Body; return cofsm; }
public IDecompilationResult DecompileSequential() { _cfg = MethodCode.Create(_code.Method); var targets = StateTargetFinder.FindStateTargets(_cfg); var entry = targets[0]; var entryCFG = MethodCode.Create(_code.Method, entry.StartIndex); var decomp = new MSILDecompiler(_code, entryCFG, _fsmInstance); decomp.Template.AddAttribute(this); decomp.Template.DisallowReturnStatements = true; var result = decomp.Decompile(); return result; }
private void DecompileAndEnqueueCallees(CodeDescriptor cd, object instance, object[] arguments, MethodCallInfo mymci = null) { IPackageOrComponentDescriptor owner = cd.Owner as IPackageOrComponentDescriptor; var rmd = cd.Method.GetCustomOrInjectedAttribute<RewriteMethodDefinition>(); IDecompilationResult result; var md = cd as MethodDescriptor; var pd = cd as ProcessDescriptor; if (pd != null) _context.CurrentProcess = pd.Instance; else _context.CurrentProcess = md.CallingProcess.Instance; EVariability[] argVar; if (md == null) argVar = new EVariability[0]; else argVar = md.ArgVariabilities; if (rmd != null) { result = rmd.Rewrite(_context, cd, instance, arguments); } else if (cd.Method.IsMoveNext()) { var decomp = new AsyncMethodDecompiler(_context, cd, instance, arguments); result = decomp.Decompile(); cd.Implementation = result.Decompiled; cd.GenuineImplementation = result.Decompiled; } else { var decomp = new MSILDecompiler(cd, instance, arguments, argVar); if (cd is ProcessDescriptor) { decomp.Template.DisallowReturnStatements = true; } decomp.Template.DisallowConditionals = true; if (mymci != null) mymci.Inherit(decomp.Template); result = decomp.Decompile(); cd.Implementation = result.Decompiled; cd.GenuineImplementation = result.Decompiled; } foreach (var mci in result.CalledMethods) { _methodQ.Enqueue(mci); } foreach (var fri in result.ReferencedFields) { AnalyzeFieldRef(fri, cd); } _allMethods.Add(cd); }
private void DecompileAndEnqueueCallees(CodeDescriptor cd, object instance, object[] arguments, MethodCallInfo mymci = null) { IPackageOrComponentDescriptor owner = cd.Owner as IPackageOrComponentDescriptor; var rmd = cd.Method.GetCustomOrInjectedAttribute <RewriteMethodDefinition>(); IDecompilationResult result; var md = cd as MethodDescriptor; var pd = cd as ProcessDescriptor; if (pd != null) { _context.CurrentProcess = pd.Instance; } else { _context.CurrentProcess = md.CallingProcess.Instance; } EVariability[] argVar; if (md == null) { argVar = new EVariability[0]; } else { argVar = md.ArgVariabilities; } if (rmd != null) { result = rmd.Rewrite(_context, cd, instance, arguments); } else if (cd.Method.IsMoveNext()) { var decomp = new AsyncMethodDecompiler(_context, cd, instance, arguments); result = decomp.Decompile(); cd.Implementation = result.Decompiled; cd.GenuineImplementation = result.Decompiled; } else { var decomp = new MSILDecompiler(cd, instance, arguments, argVar); if (cd is ProcessDescriptor) { decomp.Template.DisallowReturnStatements = true; } decomp.Template.DisallowConditionals = true; if (mymci != null) { mymci.Inherit(decomp.Template); } result = decomp.Decompile(); cd.Implementation = result.Decompiled; cd.GenuineImplementation = result.Decompiled; } foreach (var mci in result.CalledMethods) { _methodQ.Enqueue(mci); } foreach (var fri in result.ReferencedFields) { AnalyzeFieldRef(fri, cd); } _allMethods.Add(cd); }