示例#1
0
        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 GenerateForArray(ContainerDefinition containerDefinition)
        {
            Type           type             = containerDefinition.Type;
            Type           elementType      = type.GetElementType();
            bool           flag             = this.CheckIfPrimitiveOrPrimiteHolderStruct(elementType);
            TypeDefinition structDefinition = this._definitionContext.GetStructDefinition(elementType);

            if (!(elementType != typeof(object)))
            {
                return;
            }
            MethodCode methodCode = new MethodCode();

            methodCode.IsStatic        = true;
            methodCode.AccessModifier  = MethodCodeAccessModifier.Private;
            methodCode.Name            = "AutoGeneratedStaticCollectObjectsForArray" + (object)this._containerNumber;
            methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)";
            if (flag)
            {
                methodCode.AddLine("//Got no child, type: " + type.FullName);
            }
            else if (structDefinition != null)
            {
                string str1 = elementType.FullName.Replace('+', '.');
                string str2 = type.FullName.Replace('+', '.');
                methodCode.AddLine("var target = (global::" + str2 + ")o;");
                methodCode.AddLine("");
                methodCode.AddLine("for (int i = 0; i < target.Length; i++)");
                methodCode.AddLine("{");
                methodCode.AddLine("var element = target[i];");
                methodCode.AddLine("");
                methodCode.AddLine("global::" + str1 + ".AutoGeneratedStaticCollectObjects" + elementType.Name + "(element, collectedObjects);");
                methodCode.AddLine("}");
            }
            else
            {
                methodCode.AddLine("var target = (global::System.Array)o;");
                methodCode.AddLine("");
                methodCode.AddLine("for (int i = 0; i < target.Length; i++)");
                methodCode.AddLine("{");
                methodCode.AddLine("var element = target.GetValue(i);");
                methodCode.AddLine("collectedObjects.Add(element);");
                methodCode.AddLine("}");
            }
            SaveId       saveId        = containerDefinition.SaveId;
            StringWriter stringWriter1 = new StringWriter();
            StringWriter stringWriter2 = stringWriter1;

            saveId.WriteTo((IWriter)stringWriter2);
            string str = flag ? "true" : "false";

            this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));");
            this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " =  (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");");
            this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";");
            this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", " + str + ");");
            this._managerMethod.AddLine("");
            ++this._delegateCount;
            this._managerClass.AddMethod(methodCode);
            ++this._containerNumber;
        }
        private void GenerateForQueue(ContainerDefinition containerDefinition)
        {
            Type type = containerDefinition.Type;

            if (!this.CheckIfPrimitiveOrPrimiteHolderStruct(type.GetGenericArguments()[0]))
            {
                return;
            }
            MethodCode methodCode = new MethodCode();

            methodCode.IsStatic        = true;
            methodCode.AccessModifier  = MethodCodeAccessModifier.Private;
            methodCode.Name            = "AutoGeneratedStaticCollectObjectsForQueue" + (object)this._containerNumber;
            methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)";
            methodCode.AddLine("//Got no child, type: " + type.FullName);
            SaveId       saveId        = containerDefinition.SaveId;
            StringWriter stringWriter1 = new StringWriter();
            StringWriter stringWriter2 = stringWriter1;

            saveId.WriteTo((IWriter)stringWriter2);
            this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));");
            this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " =  (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");");
            this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";");
            this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", true);");
            this._managerMethod.AddLine("");
            ++this._delegateCount;
            this._managerClass.AddMethod(methodCode);
            ++this._containerNumber;
        }
示例#4
0
 public FSMTransformerTemplate(DesignContext ctx, CodeDescriptor code, object instance, object[] arguments)
 {
     _context    = ctx;
     _code       = code;
     _instance   = instance;
     _arguments  = arguments;
     _methodCode = MethodCode.Create(_code.Method);
 }
 /// <summary>
 /// Constructs a new instance based on a control-flow graph and an assumption on IsCompleted properties.
 /// </summary>
 /// <param name="cfg">a control-flow graph</param>
 /// <param name="assumption">whether the IsCompleted property is assumed to return always true or always false</param>
 public AsyncMethodCustomInstructionInfo(MethodCode cfg, EAssumption assumption):
     base(cfg.Method)
 {
     _cfg = cfg;
     _assumption = assumption;
     _branchOverrides = new Dictionary<int, int>();
     MarkIsCompletedBranches();
 }
        public void Generate()
        {
            NamespaceCode orCreateNamespace = this._codeGenerationContext.FindOrCreateNamespace(this.DefaultNamespace);
            ClassCode     classCode         = new ClassCode();

            classCode.AccessModifier = ClassCodeAccessModifier.Internal;
            classCode.Name           = "AutoGeneratedSaveManager";
            classCode.AddInterface("global::TaleWorlds.SaveSystem.Definition.IAutoGeneratedSaveManager");
            MethodCode methodCode = new MethodCode();

            methodCode.IsStatic        = false;
            methodCode.AccessModifier  = MethodCodeAccessModifier.Public;
            methodCode.Name            = "Initialize";
            methodCode.MethodSignature = "(global::TaleWorlds.SaveSystem.Definition.DefinitionContext definitionContext)";
            classCode.AddMethod(methodCode);
            this._managerMethod = methodCode;
            this._managerClass  = classCode;
            ClassCode clasCode = classCode;

            orCreateNamespace.AddClass(clasCode);
            foreach (TypeDefinition definition in this._definitions)
            {
                this.GenerateForClassOrStruct(definition);
            }
            foreach (TypeDefinition structDefinition in this._structDefinitions)
            {
                this.GenerateForClassOrStruct(structDefinition);
            }
            foreach (ContainerDefinition containerDefinition in this._containerDefinitions)
            {
                ContainerType containerType;
                if (containerDefinition.Type.IsContainer(out containerType))
                {
                    switch (containerType)
                    {
                    case ContainerType.List:
                        this.GenerateForList(containerDefinition);
                        continue;

                    case ContainerType.Dictionary:
                        this.GenerateForDictionary(containerDefinition);
                        continue;

                    case ContainerType.Array:
                        this.GenerateForArray(containerDefinition);
                        continue;

                    case ContainerType.Queue:
                        this.GenerateForQueue(containerDefinition);
                        continue;

                    default:
                        continue;
                    }
                }
            }
        }
示例#7
0
        public MethodCode CreateMethod(string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentNullException(nameof(name));
            }

            var mthdCode = new MethodCode(this, name);

            _methodCodes.Add(mthdCode);

            return(mthdCode);
        }
示例#8
0
 private void fixLocalVars(Hashtable hash, MethodCode methodCode)
 {
     if (methodCode.locVarBaseTypes != null)
     {
         for (int i = 0; i < methodCode.locVarBaseTypes.Length; i++)
         {
             methodCode.locVarBaseTypes[i] =
                 formType(
                     hash,
                     methodCode.locVarBaseTypes[i],
                     methodCode.locVarDeclarators[i]
                     );
         }
     }
 }
示例#9
0
        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;
        }
示例#10
0
        /// <summary>
        /// Executes the analysis.
        /// </summary>
        public virtual void Run()
        {
            Contract.Requires(!AnalysisDone);
            Contract.Ensures(AnalysisDone);

            MethodFacts myFacts = FactUniverse.Instance.GetFacts(Method);

            CFG = myFacts.CFG;

            _stackStates = new AbstractStackState <TElem> [CFG.Instructions.Count];
            AbstractStackState <TElem> initial = CreateInitialStackState();
            Queue <Tuple <AbstractStackState <TElem>, ILInstruction> > q = new Queue <Tuple <AbstractStackState <TElem>, ILInstruction> >();

            q.Enqueue(Tuple.Create(initial, CFG.Instructions[0]));
            int marshal = CFG.Instructions.Count - 1;

            while (q.Count > 0)
            {
                Tuple <AbstractStackState <TElem>, ILInstruction> cur = q.Dequeue();
                AbstractStackState <TElem> preState = cur.Item1;
                ILInstruction ili = cur.Item2;
                AbstractStackState <TElem> nextState = Propagate(ili, preState);
                ILInstruction[]            succs     = CFG.GetSuccessorsOf(ili);
                if (_stackStates[ili.Index] == null)
                {
                    _stackStates[ili.Index] = nextState;
                }
                else
                {
                    bool changed = Merge(_stackStates[ili.Index], nextState, out _stackStates[ili.Index]);
                    if (!changed)
                    {
                        continue;
                    }
                }
                foreach (ILInstruction nextILI in succs)
                {
                    if (nextILI.Index < marshal) // skip pseudo ret at the end
                    {
                        q.Enqueue(Tuple.Create(_stackStates[ili.Index], nextILI));
                    }
                }
            }

            AnalysisDone = true;
        }
示例#11
0
        public static DissectResult Dissect(MethodBase mb)
        {
            MethodBodyReader mbr = new MethodBodyReader(mb);
            WaitDissector    wd  = new WaitDissector(mbr.instructions);

            wd.Dissect();
            EnsureNotInitBehavior(mbr.instructions, wd.DissectionPoints[0], mb.Name);
            List <MethodCode> states = new List <MethodCode>();
            HashSet <int>     exits  = new HashSet <int>(wd.DissectionPoints);

            foreach (int ilIndex in wd.DissectionPoints)
            {
                MethodCode mc = MethodCode.Create(mb, ilIndex + 1, exits);
                states.Add(mc);
            }
            return(new DissectResult(states, wd.DissectionPoints));
        }
 private void InitializeCFGs()
 {
     _cfg = MethodCode.Create(_code.Method);
     _stateTargets = StateTargetFinder.FindStateTargets(_cfg);
     var cii = new AsyncMethodCustomInstructionInfo(
         _cfg, ImplStyle == EAsyncImplStyle.FSM ?
             AsyncMethodCustomInstructionInfo.EAssumption.NeverCompleted :
             AsyncMethodCustomInstructionInfo.EAssumption.AlwaysCompleted);
     _stateCFGs = _stateTargets.Select(t => new MethodCode(cii, t.StartIndex)).ToArray();
 }
 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;
 }
 /// <summary>
 /// Determines the set of CIL instructions which potentially compute a particular stack element.
 /// </summary>
 /// <param name="ilIndex">index of CIL instruction</param>
 /// <param name="stackLevel">index of stack element (0 is top)</param>
 /// <param name="cfg">control-flow graph</param>
 /// <returns>indices of CIL instructions which come into consideration for producing specified stack element</returns>
 public static IEnumerable<int> GetStackElementDefinitions(int ilIndex, int stackLevel, MethodCode cfg)
 {
     Queue<Tuple<int, int>> q = new Queue<Tuple<int, int>>();
     bool[] visited = new bool[cfg.Instructions.Count];
     foreach (ILInstruction pred in cfg.GetPredecessors(ilIndex))
     {
         q.Enqueue(Tuple.Create(pred.Index, stackLevel));
     }
     while (q.Count > 0)
     {
         Tuple<int, int> cur = q.Dequeue();
         int curIndex = cur.Item1;
         int curLevel = cur.Item2;
         visited[curIndex] = true;
         int npush, npop;
         GetStackBilance(cfg.Instructions[curIndex], cfg.Method, out npop, out npush);
         if (npush + curLevel >= 1)
         {
             yield return curIndex;
         }
         else
         {
             int delta = npush - npop;
             int nextLevel = curLevel + delta;
             if (nextLevel > 0)
                 throw new InvalidOperationException("Illegal stack behavior detected in method " + cfg.Method);
             foreach (ILInstruction pred in cfg.GetPredecessors(curIndex))
             {
                 if (!visited[pred.Index])
                     q.Enqueue(Tuple.Create(pred.Index, nextLevel));
             }
         }
     }
 }
        private void GenerateForDictionary(ContainerDefinition containerDefinition)
        {
            Type           type             = containerDefinition.Type;
            Type           genericArgument1 = type.GetGenericArguments()[0];
            Type           genericArgument2 = type.GetGenericArguments()[1];
            int            num               = this.CheckIfPrimitiveOrPrimiteHolderStruct(genericArgument1) ? 1 : 0;
            bool           flag1             = this.CheckIfPrimitiveOrPrimiteHolderStruct(genericArgument2);
            TypeDefinition structDefinition1 = this._definitionContext.GetStructDefinition(genericArgument1);
            TypeDefinition structDefinition2 = this._definitionContext.GetStructDefinition(genericArgument2);
            bool           flag2             = (num & (flag1 ? 1 : 0)) != 0;

            if (num == 0 && structDefinition1 == null || !flag1 && structDefinition2 == null || (!(genericArgument1 != typeof(object)) || !(genericArgument2 != typeof(object))))
            {
                return;
            }
            MethodCode methodCode = new MethodCode();

            methodCode.IsStatic        = true;
            methodCode.AccessModifier  = MethodCodeAccessModifier.Private;
            methodCode.Name            = "AutoGeneratedStaticCollectObjectsForDictionary" + (object)this._containerNumber;
            methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)";
            if (flag2)
            {
                methodCode.AddLine("//Got no child, type: " + type.FullName);
            }
            else
            {
                methodCode.AddLine("var target = (global::System.Collections.IDictionary)o;");
                methodCode.AddLine("");
                if (structDefinition1 != null)
                {
                    string str = genericArgument1.FullName.Replace('+', '.');
                    methodCode.AddLine("foreach (var key in target.Keys)");
                    methodCode.AddLine("{");
                    methodCode.AddLine("global::" + str + ".AutoGeneratedStaticCollectObjects" + genericArgument1.Name + "(key, collectedObjects);");
                    methodCode.AddLine("}");
                }
                methodCode.AddLine("");
                if (structDefinition2 != null)
                {
                    string str = genericArgument2.FullName.Replace('+', '.');
                    methodCode.AddLine("foreach (var value in target.Values)");
                    methodCode.AddLine("{");
                    methodCode.AddLine("global::" + str + ".AutoGeneratedStaticCollectObjects" + genericArgument2.Name + "(value, collectedObjects);");
                    methodCode.AddLine("}");
                }
            }
            SaveId       saveId        = containerDefinition.SaveId;
            StringWriter stringWriter1 = new StringWriter();
            StringWriter stringWriter2 = stringWriter1;

            saveId.WriteTo((IWriter)stringWriter2);
            string str1 = flag2 ? "true" : "false";

            this._managerMethod.AddLine("var saveId" + (object)this._delegateCount + " = global::TaleWorlds.SaveSystem.Definition.SaveId.ReadSaveIdFrom(new global::TaleWorlds.Library.StringReader(\"" + stringWriter1.Data + "\"));");
            this._managerMethod.AddLine("var typeDefinition" + (object)this._delegateCount + " =  (global::TaleWorlds.SaveSystem.Definition.ContainerDefinition)definitionContext.TryGetTypeDefinition(saveId" + (object)this._delegateCount + ");");
            this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)this._delegateCount + " = " + methodCode.Name + ";");
            this._managerMethod.AddLine("typeDefinition" + (object)this._delegateCount + ".InitializeForAutoGeneration(d" + (object)this._delegateCount + ", " + str1 + ");");
            this._managerMethod.AddLine("");
            ++this._delegateCount;
            this._managerClass.AddMethod(methodCode);
            ++this._containerNumber;
        }
        /// <summary>
        /// Determines the set of CIL instructions which potentially compute a particular stack element.
        /// </summary>
        /// <param name="ilIndex">index of CIL instruction</param>
        /// <param name="stackLevel">index of stack element (0 is top)</param>
        /// <param name="cfg">control-flow graph</param>
        /// <returns>indices of CIL instructions which come into consideration for producing specified stack element</returns>
        public static IEnumerable <int> GetStackElementDefinitions(int ilIndex, int stackLevel, MethodCode cfg)
        {
            Queue <Tuple <int, int> > q = new Queue <Tuple <int, int> >();

            bool[] visited = new bool[cfg.Instructions.Count];
            foreach (ILInstruction pred in cfg.GetPredecessors(ilIndex))
            {
                q.Enqueue(Tuple.Create(pred.Index, stackLevel));
            }
            while (q.Count > 0)
            {
                Tuple <int, int> cur = q.Dequeue();
                int curIndex         = cur.Item1;
                int curLevel         = cur.Item2;
                visited[curIndex] = true;
                int npush, npop;
                GetStackBilance(cfg.Instructions[curIndex], cfg.Method, out npop, out npush);
                if (npush + curLevel >= 1)
                {
                    yield return(curIndex);
                }
                else
                {
                    int delta     = npush - npop;
                    int nextLevel = curLevel + delta;
                    if (nextLevel > 0)
                    {
                        throw new InvalidOperationException("Illegal stack behavior detected in method " + cfg.Method);
                    }
                    foreach (ILInstruction pred in cfg.GetPredecessors(curIndex))
                    {
                        if (!visited[pred.Index])
                        {
                            q.Enqueue(Tuple.Create(pred.Index, nextLevel));
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Given a control-flow graph of an asynchronous method, finds all state entry points.
        /// This is done using some pattern matching and knowledge on how the compiler translates asynchronous methods.
        /// Therefore, some special cases might not be resolved correctly, and the code might break down with future compiler revisions.
        /// </summary>
        /// <param name="cfg">a control-flow graph</param>
        /// <returns>all state entry points</returns>
        public static MSILCodeBlock[] FindStateTargets(MethodCode cfg)
        {
            var entry = cfg.BasicBlocks[0];
            FieldInfo statefield = null;
            int stateLocalIndex = -1;
            int stateValue = int.MinValue;
            int stateOffset = 0;
            var mode = EStateLocMode.LocatingStateField;
            var q = new Queue<Tuple<int, MSILCodeBlock>>();
            foreach (var cili in entry.Range)
            {
                switch (mode)
                {
                    case EStateLocMode.LocatingStateField:
                        if (cili.Code == OpCodes.Ldfld)
                        {
                            // this must be the state field
                            statefield = (FieldInfo)cili.Operand;
                            mode = EStateLocMode.LocatingStateLocal;
                        }
                        break;

                    case EStateLocMode.LocatingStateLocal:
                        {
                            int index;
                            if (IsStloc(cili, out index))
                                stateLocalIndex = index;
                        }
                        break;
                }

                int value;
                if (IsLdc_I(cili, out value))
                {
                    stateValue = value;
                }

                if (cili.Code == OpCodes.Sub)
                {
                    stateOffset = stateValue;
                }
                else if (cili.Code == OpCodes.Beq ||
                    cili.Code == OpCodes.Beq_S)
                {
                    // State -3 exists only in debug builds and skips the whole FSM => irrelevant
                    if (stateValue != -3)
                    {
                        q.Enqueue(Tuple.Create(stateValue, entry.Successors[1]));
                    }
                    q.Enqueue(Tuple.Create(-1, entry.Successors[0]));
                }
                else if (cili.Code == OpCodes.Switch)
                {
                    bool have_1 = false;
                    for (int i = 1; i < entry.Successors.Length; i++)
                    {
                        int state = i - 1 + stateOffset;
                        // State -3 exists only in debug builds and skips the whole FSM => irrelevant
                        // State -2 is completion state => also irrelevant
                        if (state >= -1)
                        {
                            q.Enqueue(Tuple.Create(state, entry.Successors[i]));

                            if (state == -1)
                                have_1 = true;
                        }
                    }
                    if (!have_1)
                        q.Enqueue(Tuple.Create(-1, entry.Successors[0]));
                }
            }
            var stateDic = new SortedDictionary<int, MSILCodeBlock>();
            while (q.Any())
            {
                var tup = q.Dequeue();
                int state = tup.Item1;
                var block = tup.Item2;

                int value;
                if (IsLdloc(block.Range.First(), out value) &&
                    value == stateLocalIndex)
                {
                    if (block.Range.Count != 3)
                        throw new NotSupportedException("Decompilation of await pattern failed: expected 3 instructions in this block.");

                    if (!IsLdc_I(block.Range[1], out stateValue))
                        throw new NotSupportedException("Decompilation of await pattern failed: expected Ldc_I<x> op-code.");

                    if (block.Range[2].Code != OpCodes.Beq &&
                        block.Range[2].Code != OpCodes.Beq_S)
                        throw new NotSupportedException("Decompilation of await pattern failed: expected Beq/Beq_S op-code.");

                    q.Enqueue(Tuple.Create(stateValue, block.Successors[1]));
                    q.Enqueue(Tuple.Create(-1, block.Successors[0]));
                }
                else
                {
                    stateDic[state] = block;
                }
            }
            for (int state = -1; state < stateDic.Count - 1; state++)
            {
                if (!stateDic.ContainsKey(state))
                    throw new NotSupportedException("Decompilation of await pattern failed: expected consecutive states from -1 to " + (stateDic.Count-1));
            }
            return stateDic.Values.ToArray();
        }
        private void GenerateForClassOrStruct(TypeDefinition typeDefinition)
        {
            Type   type1         = typeDefinition.Type;
            bool   isClass       = type1.IsClass;
            bool   flag1         = !isClass;
            bool   flag2         = this.CheckIfBaseTypeDefind(type1);
            string name1         = type1.Namespace;
            string str1          = type1.FullName.Replace('+', '.');
            string fullClassName = str1.Substring(name1.Length + 1, str1.Length - name1.Length - 1).Replace('+', '.');

            string[]      nestedClasses     = this.GetNestedClasses(fullClassName);
            NamespaceCode orCreateNamespace = this._codeGenerationContext.FindOrCreateNamespace(name1);
            string        str2      = nestedClasses[nestedClasses.Length - 1];
            ClassCode     classCode = (ClassCode)null;

            for (int index = 0; index < nestedClasses.Length; ++index)
            {
                string    className = nestedClasses[index];
                ClassCode clasCode  = new ClassCode();
                clasCode.IsPartial = true;
                if (index + 1 == nestedClasses.Length)
                {
                    clasCode.IsClass = isClass;
                }
                clasCode.AccessModifier = ClassCodeAccessModifier.DoNotMention;
                int genericInformation = this.GetClassGenericInformation(className);
                if (genericInformation >= 0)
                {
                    clasCode.IsGeneric        = true;
                    clasCode.GenericTypeCount = genericInformation;
                    className = className.Substring(0, className.Length - 2);
                }
                clasCode.Name = className;
                if (classCode != null)
                {
                    classCode.AddNestedClass(clasCode);
                }
                else
                {
                    orCreateNamespace.AddClass(clasCode);
                }
                classCode = clasCode;
            }
            TypeSaveId saveId        = (TypeSaveId)typeDefinition.SaveId;
            int        delegateCount = this._delegateCount;

            ++this._delegateCount;
            this._managerMethod.AddLine("var typeDefinition" + (object)delegateCount + " =  (global::TaleWorlds.SaveSystem.Definition.TypeDefinition)definitionContext.TryGetTypeDefinition(new global::TaleWorlds.SaveSystem.Definition.TypeSaveId(" + (object)saveId.Id + "));");
            if (!type1.IsGenericTypeDefinition && !type1.IsAbstract)
            {
                MethodCode methodCode = new MethodCode();
                methodCode.IsStatic        = true;
                methodCode.AccessModifier  = flag1 ? MethodCodeAccessModifier.Public : MethodCodeAccessModifier.Internal;
                methodCode.Name            = "AutoGeneratedStaticCollectObjects" + str2;
                methodCode.MethodSignature = "(object o, global::System.Collections.Generic.List<object> collectedObjects)";
                methodCode.AddLine("var target = (global::" + str1 + ")o;");
                methodCode.AddLine("target.AutoGeneratedInstanceCollectObjects(collectedObjects);");
                classCode.AddMethod(methodCode);
                this._managerMethod.AddLine("TaleWorlds.SaveSystem.Definition.CollectObjectsDelegate d" + (object)delegateCount + " = global::" + name1 + "." + fullClassName + "." + methodCode.Name + ";");
                this._managerMethod.AddLine(nameof(typeDefinition) + (object)delegateCount + ".InitializeForAutoGeneration(d" + (object)delegateCount + ");");
            }
            this._managerMethod.AddLine("");
            MethodCode methodCode1 = new MethodCode();

            if (flag2)
            {
                methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.Override;
                methodCode1.AccessModifier   = MethodCodeAccessModifier.Protected;
            }
            else if (!type1.IsSealed)
            {
                methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.Virtual;
                methodCode1.AccessModifier   = MethodCodeAccessModifier.Protected;
            }
            else
            {
                methodCode1.PolymorphismInfo = MethodCodePolymorphismInfo.None;
                methodCode1.AccessModifier   = MethodCodeAccessModifier.Private;
            }
            methodCode1.Name            = "AutoGeneratedInstanceCollectObjects";
            methodCode1.MethodSignature = "(global::System.Collections.Generic.List<object> collectedObjects)";
            if (flag2)
            {
                methodCode1.AddLine("base.AutoGeneratedInstanceCollectObjects(collectedObjects);");
                methodCode1.AddLine("");
            }
            foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions)
            {
                if (memberDefinition is FieldDefinition)
                {
                    FieldInfo fieldInfo = (memberDefinition as FieldDefinition).FieldInfo;
                    Type      fieldType = fieldInfo.FieldType;
                    string    name2     = fieldInfo.Name;
                    if (fieldType.IsClass || fieldType.IsInterface)
                    {
                        if (fieldType != typeof(string))
                        {
                            bool flag3         = false;
                            Type declaringType = fieldInfo.DeclaringType;
                            if (declaringType != type1)
                            {
                                flag3 = this.CheckIfTypeDefined(declaringType);
                            }
                            string str3 = "";
                            if (flag3)
                            {
                                str3 += "//";
                            }
                            string line = str3 + "collectedObjects.Add(this." + name2 + ");";
                            methodCode1.AddLine(line);
                        }
                    }
                    else if (!fieldType.IsClass && this._definitionContext.GetStructDefinition(fieldType) != null)
                    {
                        string str3          = "";
                        bool   flag3         = false;
                        Type   declaringType = fieldInfo.DeclaringType;
                        if (declaringType != type1)
                        {
                            flag3 = this.CheckIfTypeDefined(declaringType);
                        }
                        if (flag3)
                        {
                            str3 += "//";
                        }
                        string str4 = fieldType.FullName.Replace('+', '.');
                        string line = str3 + "global::" + str4 + ".AutoGeneratedStaticCollectObjects" + fieldType.Name + "(this." + name2 + ", collectedObjects);";
                        methodCode1.AddLine(line);
                    }
                }
            }
            methodCode1.AddLine("");
            foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions)
            {
                if (memberDefinition is PropertyDefinition)
                {
                    PropertyDefinition propertyDefinition = memberDefinition as PropertyDefinition;
                    PropertyInfo       propertyInfo       = propertyDefinition.PropertyInfo;
                    Type   propertyType = propertyDefinition.PropertyInfo.PropertyType;
                    string name2        = propertyInfo.Name;
                    if (propertyType.IsClass || propertyType.IsInterface)
                    {
                        if (propertyType != typeof(string))
                        {
                            bool flag3         = false;
                            Type declaringType = propertyInfo.DeclaringType;
                            if (declaringType != type1)
                            {
                                flag3 = this.CheckIfTypeDefined(declaringType);
                            }
                            string str3 = "";
                            if (flag3)
                            {
                                str3 += "//";
                            }
                            string line = str3 + "collectedObjects.Add(this." + name2 + ");";
                            methodCode1.AddLine(line);
                        }
                    }
                    else if (!propertyType.IsClass && this._definitionContext.GetStructDefinition(propertyType) != null)
                    {
                        bool flag3         = false;
                        Type declaringType = propertyInfo.DeclaringType;
                        if (declaringType != type1)
                        {
                            flag3 = this.CheckIfTypeDefined(declaringType);
                        }
                        string str3 = "";
                        if (flag3)
                        {
                            str3 += "//";
                        }
                        string str4 = propertyType.FullName.Replace('+', '.');
                        string line = str3 + "global::" + str4 + ".AutoGeneratedStaticCollectObjects" + propertyType.Name + "(this." + name2 + ", collectedObjects);";
                        methodCode1.AddLine(line);
                    }
                }
            }
            classCode.AddMethod(methodCode1);
            foreach (MemberDefinition memberDefinition in typeDefinition.MemberDefinitions)
            {
                if (!type1.IsGenericTypeDefinition)
                {
                    MethodCode methodCode2 = new MethodCode();
                    string     str3        = "";
                    Type       type2       = (Type)null;
                    switch (memberDefinition)
                    {
                    case PropertyDefinition _:
                        PropertyDefinition propertyDefinition = memberDefinition as PropertyDefinition;
                        str3  = propertyDefinition.PropertyInfo.Name;
                        type2 = propertyDefinition.PropertyInfo.DeclaringType;
                        break;

                    case FieldDefinition _:
                        FieldDefinition fieldDefinition = memberDefinition as FieldDefinition;
                        str3  = fieldDefinition.FieldInfo.Name;
                        type2 = fieldDefinition.FieldInfo.DeclaringType;
                        break;
                    }
                    bool flag3 = false;
                    if (type2 != type1)
                    {
                        flag3 = this.CheckIfTypeDefined(type2);
                    }
                    if (!flag3)
                    {
                        methodCode2.Name             = "AutoGeneratedGetMemberValue" + str3;
                        methodCode2.MethodSignature  = "(object o)";
                        methodCode2.IsStatic         = true;
                        methodCode2.AccessModifier   = MethodCodeAccessModifier.Internal;
                        methodCode2.PolymorphismInfo = MethodCodePolymorphismInfo.None;
                        methodCode2.ReturnParameter  = "object";
                        methodCode2.AddLine("var target = (global::" + str1 + ")o;");
                        methodCode2.AddLine("return (object)target." + str3 + ";");
                        classCode.AddMethod(methodCode2);
                        string str4 = "GetPropertyDefinitionWithId";
                        if (memberDefinition is FieldDefinition)
                        {
                            str4 = "GetFieldDefinitionWithId";
                        }
                        this._managerMethod.AddLine("{");
                        this._managerMethod.AddLine("var memberDefinition = typeDefinition" + (object)delegateCount + "." + str4 + "(new global::TaleWorlds.SaveSystem.Definition.MemberTypeId(" + (object)memberDefinition.Id.TypeLevel + "," + (object)memberDefinition.Id.LocalSaveId + "));");
                        this._managerMethod.AddLine("memberDefinition.InitializeForAutoGeneration(" + ("global::" + name1 + "." + fullClassName + "." + methodCode2.Name) + ");");
                        this._managerMethod.AddLine("}");
                        this._managerMethod.AddLine("");
                    }
                }
            }
        }