public DecompileCache(ProjectFile pf)
        {
            Types = new AssetResolverTypes(pf);
            GlobalFunctionNames = new Dictionary <GMFunctionEntry, string>();
            if (pf.DataHandle.VersionInfo.IsNumberAtLeast(2, 3))
            {
                // Find all function names in global scripts
                GMChunkCODE code = pf.DataHandle.GetChunk <GMChunkCODE>();
                Parallel.ForEach(pf.DataHandle.GetChunk <GMChunkGLOB>().List, scr =>
                {
                    GMCode entry = code.List[scr];

                    // Find fragments
                    List <Fragment> fragments = Fragments.FindAndProcess(entry, false);

                    // Find blocks in the main fragment that come after another fagment
                    foreach (Block b in fragments[^ 1].Blocks.List)
                    {
                        if (b.AfterFragment && b.Instructions.Count > 2 &&
                            b.Instructions[0].Kind == GMCode.Bytecode.Instruction.Opcode.Push &&
                            b.Instructions[0].Type1 == GMCode.Bytecode.Instruction.DataType.Int32 &&
                            b.Instructions[0].Value == null)
                        {
                            string name = ASTBuilder.GetNameAfterFragment(b);
                            if (name != null)
                            {
                                GMFunctionEntry func = b.Instructions[0].Function.Target;
                                lock (GlobalFunctionNames)
                                    GlobalFunctionNames[func] = name;
                            }
                        }
                    }
                });
예제 #2
0
 ILExpression MakeLeftAssociativeShortCircuit(GMCode code, ILExpression left, ILExpression right)
 {
     // Assuming that the inputs are already left associative
     if (right.Match(code))
     {
         // Find the leftmost logical expression
         ILExpression current = right;
         while (current.Arguments[0].Match(code))
         {
             current = current.Arguments[0];
         }
         current.Arguments[0] = new ILExpression(code, null, left, current.Arguments[0])
         {
             InferredType = GM_Type.Bool
         };
         return(right);
     }
     else
     {
         return(new ILExpression(code, null, left, right)
         {
             InferredType = GM_Type.Bool
         });
     }
 }
예제 #3
0
        public static uint toUInt(this GMCode t, GM_Type type)
        {
            byte b  = (byte)t;
            byte bt = (byte)type;

            return((uint)(b << 24) | (uint)(bt << 16));
        }
예제 #4
0
 public static bool MatchLastCount <T>(this IList <T> ast, GMCode code, int count, out List <ILExpression> match) where T : ILNode
 {
     do
     {
         if (ast.Count == 0 && ast.Count < count)
         {
             break;
         }
         int i = ast.Count - 1, j = 0;
         List <ILExpression> ret = new List <ILExpression>();
         for (; i >= 0 && j < count; i--, j++)
         {
             ILExpression test;
             if (ast.ElementAtOrDefault(i).Match(code, out test))
             {
                 ret.Add(test);
             }
             else
             {
                 break;
             }
         }
         if (j != count)
         {
             break;             // bad match or not enough match
         }
         match = ret;
         return(true);
     } while (false);
     match = default(List <ILExpression>);
     return(false);
 }
예제 #5
0
        public static bool isExpression(this GMCode i)
        {
            switch (i)
            {
            case GMCode.LogicAnd:
            case GMCode.LogicOr:
            case GMCode.Neg:
            case GMCode.Not:
            case GMCode.Add:
            case GMCode.Sub:
            case GMCode.Mul:
            case GMCode.Div:
            case GMCode.Mod:
            case GMCode.And:
            case GMCode.Or:
            case GMCode.Xor:
            case GMCode.Sal:
            case GMCode.Seq:
            case GMCode.Sge:
            case GMCode.Sgt:
            case GMCode.Sle:
            case GMCode.Slt:
            case GMCode.Sne:
                return(true);

            default:
                return(false);
            }
        }
예제 #6
0
 public static bool MatchLastAt(this ILBasicBlock bb, int back, GMCode code)
 {
     if (bb.Body.ElementAtOrDefault(bb.Body.Count - back).Match(code))
     {
         return(true);
     }
     return(false);
 }
예제 #7
0
 public static bool MatchAt(this ILBasicBlock bb, int index, GMCode code)
 {
     if (bb.Body.ElementAtOrDefault(index).Match(code))
     {
         return(true);
     }
     return(false);
 }
예제 #8
0
 protected ILExpression CreateLabeledExpression(GMCode code)
 {
     int absolute = GMCodeUtil.getBranchOffset(CurrentRaw) + CurrentPC;
     ILExpression e = new ILExpression(code, GetLabel(absolute));
     e.Extra = (int)(CurrentRaw & 0xFFFF);
     e.ILRanges.Add(new ILRange(CurrentPC, CurrentPC));
     return e;
 }
예제 #9
0
        protected ILExpression CreateLabeledExpression(GMCode code)
        {
            int          absolute = GMCodeUtil.getBranchOffset(CurrentRaw) + CurrentPC;
            ILExpression e        = new ILExpression(code, GetLabel(absolute));

            e.Extra = (int)(CurrentRaw & 0xFFFF);
            e.ILRanges.Add(new ILRange(CurrentPC, CurrentPC));
            return(e);
        }
예제 #10
0
        protected ILExpression CreateExpression(GMCode code, GM_Type[] types)
        {
            ILExpression e = new ILExpression(code, null);

            e.Types = types;
            e.Extra = (int)(CurrentRaw & 0xFFFF);
            e.AddILRange(CurrentPC);
            return(e);
        }
예제 #11
0
 public static bool MatchLastAt <T>(this ILBasicBlock bb, int back, GMCode code, out T operand)
 {
     if (bb.Body.ElementAtOrDefault(bb.Body.Count - back).Match(code, out operand))
     {
         return(true);
     }
     operand = default(T);
     return(false);
 }
예제 #12
0
 public static bool MatchLastAt(this ILBasicBlock bb, int back, GMCode code, out ILExpression arg)
 {
     if (bb.Body.ElementAtOrDefault(bb.Body.Count - back).Match(code, out arg))
     {
         return(true);
     }
     arg = default(ILExpression);
     return(false);
 }
예제 #13
0
 public static bool MatchAt(this ILBasicBlock bb, int index, GMCode code, out IList <ILExpression> args)
 {
     if (bb.Body.ElementAtOrDefault(index).Match(code, out args))
     {
         return(true);
     }
     args = default(IList <ILExpression>);
     return(false);
 }
예제 #14
0
 public static bool MatchAt <T>(this ILBasicBlock bb, int index, GMCode code, out T operand)
 {
     if (bb.Body.ElementAtOrDefault(index).Match(code, out operand))
     {
         return(true);
     }
     operand = default(T);
     return(false);
 }
예제 #15
0
        public static int getOpTreeCount(this GMCode t)
        {
            int count;

            if (opMathOperationCount.TryGetValue(t, out count))
            {
                return(count);
            }
            return(0);
        }
예제 #16
0
        public static string getOpTreeString(this GMCode t)
        {
            string ret;

            if (opMathOperation.TryGetValue(t, out ret))
            {
                return(ret);
            }
            return(null);
        }
예제 #17
0
        protected ILExpression CreateExpression(GMCode code, GM_Type[] types, ILLabel operand)
        {
            Debug.Assert(operand != null);
            ILExpression e = new ILExpression(code, operand);

            e.Types = types;
            e.Extra = (int)(CurrentRaw & 0xFFFF);
            e.AddILRange(CurrentPC);
            return(e);
        }
예제 #18
0
 public static bool MatchSingle <T>(this ILBasicBlock bb, GMCode code, out T operand)
 {
     if (bb.Body.Count == 2 &&
         bb.Body[0] is ILLabel &&
         bb.Body[1].Match(code, out operand))
     {
         return(true);
     }
     operand = default(T);
     return(false);
 }
예제 #19
0
 public static bool MatchLastAndBr(this ILBasicBlock bb, GMCode code, out ILExpression arg, out ILLabel brLabel)
 {
     if (bb.Body.ElementAtOrDefault(bb.Body.Count - 2).Match(code, out arg) &&
         bb.Body.LastOrDefault().Match(GMCode.B, out brLabel))
     {
         return(true);
     }
     arg     = default(ILExpression);
     brLabel = null;
     return(false);
 }
예제 #20
0
 public static bool MatchLastAndBr <T>(this ILBasicBlock bb, GMCode code, out T operand, out ILLabel brLabel)
 {
     if (bb.Body.ElementAtOrDefault(bb.Body.Count - 2).Match(code, out operand) &&
         bb.Body.LastOrDefault().Match(GMCode.B, out brLabel))
     {
         return(true);
     }
     operand = default(T);
     brLabel = null;
     return(false);
 }
예제 #21
0
        public static bool Match <T>(this ILNode node, GMCode code, out T operand)
        {
            ILExpression expr = node as ILExpression;

            if (expr != null && expr.Code == code && expr.Arguments.Count == 0)
            {
                operand = (T)expr.Operand;
                return(true);
            }
            operand = default(T);
            return(false);
        }
예제 #22
0
        public static bool Match <T>(this ILNode node, GMCode code, out T operand, out ILExpression arg)
        {
            IList <ILExpression> args;

            if (node.Match(code, out operand, out args) && args.Count == 1)
            {
                arg = args[0];
                return(true);
            }
            arg = null;
            return(false);
        }
예제 #23
0
        public static bool Match(this ILNode node, GMCode code, out IList <ILExpression> args)
        {
            ILExpression expr = node as ILExpression;

            if (expr != null && expr.Code == code && expr.Operand == null)
            {
                args = expr.Arguments;
                return(true);
            }
            args = null;
            return(false);
        }
예제 #24
0
        public ILExpression(GMCode code, object operand, params ILExpression[] args)
        {
            if (operand is ILExpression)
            {
                throw new ArgumentException("operand");
            }

            this.Code      = code;
            this.Operand   = operand;
            this.Arguments = new List <ILExpression>(args);
            this.ILRanges  = new List <ILRange>(1);
        }
예제 #25
0
        public static int GetPopDelta(this GMCode i)
        {
            switch (i)
            {
            case GMCode.Popenv:
            case GMCode.Exit:
            case GMCode.Conv:
                break;     // we ignore conv

            case GMCode.Call:
            case GMCode.Push:
            case GMCode.Pop:
            case GMCode.Dup:
                throw new Exception("Need more info for pop");

            case GMCode.Popz:
            case GMCode.Ret:

            case GMCode.Bt:
            case GMCode.Bf:
            case GMCode.Neg:
            case GMCode.Not:
            case GMCode.Pushenv:
                return(1);

            case GMCode.Add:
            case GMCode.Sub:
            case GMCode.Mul:
            case GMCode.Div:
            case GMCode.Mod:
            case GMCode.And:
            case GMCode.Or:
            case GMCode.Xor:
            case GMCode.Sal:
            case GMCode.Seq:
            case GMCode.Sge:
            case GMCode.Sgt:
            case GMCode.Sle:
            case GMCode.Slt:
            case GMCode.Sne:
                return(2);

            case GMCode.Var:
            case GMCode.Constant:
            case GMCode.B:
                return(0);

            default:
                throw new Exception("Unkonwn opcode");
            }
            return(0);
        }
예제 #26
0
        public static bool Match <T>(this ILNode node, GMCode code, out T operand, out IList <ILExpression> args)
        {
            ILExpression expr = node as ILExpression;

            if (expr != null && expr.Code == code)
            {
                operand = (T)expr.Operand;
                args    = expr.Arguments;
                return(true);
            }
            operand = default(T);
            args    = null;
            return(false);
        }
예제 #27
0
 public static int FindLastIndexOf(this IList <ILNode> ast, GMCode code, int from)
 {
     if (ast.Count == 0 || from < 0 || from > (ast.Count - 1))
     {
         return(-1);
     }
     for (int i = from; i >= 0; i--)
     {
         if (ast[i].Match(code))
         {
             return(i);
         }
     }
     return(-1);
 }
예제 #28
0
 public static bool MatchSingleAndBr <T>(this ILBasicBlock bb, GMCode code, out T operand, out ILLabel brLabel)
 {
     {
         if (bb.Body.Count == 3 &&
             bb.Body[0] is ILLabel &&
             bb.Body[1].Match(code, out operand) &&
             bb.Body[2].Match(GMCode.B, out brLabel))
         {
             return(true);
         }
     }
     operand = default(T);
     brLabel = null;
     return(false);
 }
        static bool IsBranch(GMCode opcode)
        {
            switch (opcode)
            {
            case GMCode.B:
            case GMCode.Bf:
            case GMCode.Bt:
            case GMCode.Exit:
            case GMCode.Ret:
                return(true);

            default:
                return(false);
            }
        }
예제 #30
0
 public static bool MatchSingleAndBr <T>(this ILBasicBlock bb, GMCode code, out T operand, out IList <ILExpression> args, out ILLabel brLabel)
 {
     {
         if (bb.Body.Count == 3 &&
             bb.Body[0] is ILLabel &&
             bb.Body[1].Match(code, out operand, out args) &&
             bb.Body[2].Match(GMCode.B, out brLabel))
         {
             return(true);
         }
     }
     args    = default(List <ILExpression>);
     brLabel = default(ILLabel);
     operand = default(T);
     return(false);
 }
예제 #31
0
        public static bool IsConditionalStatment(this GMCode code)
        {
            switch (code)
            {
            case GMCode.Seq:
            case GMCode.Sne:
            case GMCode.Sge:
            case GMCode.Sle:
            case GMCode.Sgt:
            case GMCode.Slt:
                return(true);

            default:
                return(false);
            }
        }
예제 #32
0
 protected ILExpression CreatePushExpression(GMCode code, GM_Type[] types)
 {
     ILExpression e = new ILExpression(code, null);
     e.Types = types;
     e.Extra = (int)(CurrentRaw & 0xFFFF);
     Debug.Assert(e.ILRanges.Count == 0);
     e.AddILRange(CurrentPC);
     ILValue v = null;
     switch (types[0])
     {
         case GM_Type.Var:
                 e.Operand = BuildUnresolvedVar(r.ReadInt32());
             break;
         case GM_Type.Short:
             {
                 v = new ILValue((short)(CurrentRaw & 0xFFFF));
                 v.DataOffset = (int)(r.BaseStream.Position - 4);
                 e.Arguments.Add(new ILExpression(GMCode.Constant, v));
             }
             break;
         default:
             v = ReadConstant(r, types[0]);
             e.Arguments.Add(new ILExpression(GMCode.Constant, v));
             break;
     }
     if (v != null)
     {
         v.DataOffset += StartingOffset ;
         DebugILValueOffset(v);
     }
    
     return e;
 }
예제 #33
0
 protected  ILExpression CreateExpression(GMCode code,  GM_Type[] types, ILLabel operand)
 {
     Debug.Assert(operand != null);
     ILExpression e = new ILExpression(code, operand);
     e.Types = types;
     e.Extra = (int)(CurrentRaw & 0xFFFF);
     e.AddILRange(CurrentPC);
     return e;
 }
예제 #34
0
 protected ILExpression CreateExpression(GMCode code,  GM_Type[] types)
 {
     ILExpression e = new ILExpression(code, null);
     e.Types = types;
     e.Extra = (int)(CurrentRaw & 0xFFFF);
     e.AddILRange(CurrentPC);
     return e;
 }