Exemple #1
0
        private static void MergePath(CodePath targetPath, CodePath newPath)
        {
            HLInstruction hlInstruction = newPath.StartInstruction;

            if (targetPath.EndInstruction == null)
            {
                targetPath.StartInstruction       = hlInstruction;
                hlInstruction.PreviousInstruction = null;
            }
            else
            {
                targetPath.EndInstruction.NextInstruction = hlInstruction;
                hlInstruction.PreviousInstruction         = targetPath.EndInstruction;
            }

            while (true)
            {
                newPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = targetPath;
                targetPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null)
                {
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            targetPath.EndInstruction = hlInstruction;
            targetPath.EndOffset      = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            newPath.ParentFunction.CodePaths.Remove(newPath);
        }
Exemple #2
0
        private void AnalyzeConditionalBranch(HLInstruction branchInstruction)
        {
            int branchOffset = branchInstruction.Instruction.Offset +
                               branchInstruction.Instruction.InstructionLength;

            CodePath parentPath = branchInstruction.ParentCodePath;

            CodePath branchCodePath = CreateCodePath("if", branchOffset, parentPath);

            branchCodePath.ParentExitInstruction = branchInstruction;

            bool condition = branchInstruction.Instruction.OpCode == OpCode.JumpFalse ? true : false;

            branchInstruction.BranchCodesPaths.Add(condition, branchCodePath);

            branchInstruction.DefaultConditional = condition;

            AnalyzeCodePath(branchCodePath);

            if (branchInstruction.NextInstruction != null &&
                branchCodePath.ParentEntryTargetInstruction != branchInstruction.NextInstruction)
            {
                // Well, shit.. we got an else block.

                CodePath branchElseCodePath = ExtractPath("if_else", branchInstruction.ParentCodePath, branchInstruction,
                                                          branchInstruction.NextInstruction,
                                                          branchCodePath.ParentEntryInstruction);

                branchInstruction.BranchCodesPaths.Add(!condition, branchElseCodePath);
            }
        }
Exemple #3
0
        private static CodePath CreateCodePath(string identifier, int startOffset, CodePath parentPath)
        {
            CodePath path = parentPath.ParentFunction.CreateCodePath(string.Format("{0}_{1:x}", identifier, startOffset));

            path.ParentCodePath = parentPath;
            path.StartOffset    = startOffset;
            return(path);
        }
Exemple #4
0
 public CodePath CreateCodePath(string name)
 {
     var path = new CodePath();
     path.Name = name;
     path.ParentFunction = this;
     CodePaths.Add(path);
     return path;
 }
Exemple #5
0
        public CodePath CreateCodePath(string name)
        {
            var path = new CodePath();

            path.Name           = name;
            path.ParentFunction = this;
            CodePaths.Add(path);
            return(path);
        }
Exemple #6
0
        private void AnalyzeSwitchBranch(HLInstruction branchInstruction)
        {
            var sw = branchInstruction.Instruction as InstructionSwitch;

            CodePath parentPath = branchInstruction.ParentCodePath;

            var  swMap          = new Dictionary <int, CodePath>();
            bool allWereReturns = true;

            HLInstruction switchExitInstruction = branchInstruction.NextInstruction.NextInstruction;

            foreach (var item in sw.SwitchTable)
            {
                if (swMap.ContainsKey(item.Value))
                {
                    // Deal with multiple values leading to the same code path
                    branchInstruction.BranchCodesPaths.Add(item.Key, swMap[item.Value]);
                }
                else
                {
                    CodePath branchCodePath = CreateCodePath("sw_case_" + item.Key, item.Value, parentPath);
                    branchCodePath.ParentExitInstruction = branchInstruction;

                    branchInstruction.BranchCodesPaths.Add(item.Key, branchCodePath);
                    swMap.Add(item.Value, branchCodePath);

                    AnalyzeCodePath(branchCodePath);

                    if (branchCodePath.ParentEntryInstruction != null)
                    {
                        allWereReturns        = false;
                        switchExitInstruction = branchCodePath.ParentEntryInstruction;
                    }
                }
            }

            if (allWereReturns)
            {
                switchExitInstruction = null;
            }

            if (switchExitInstruction != branchInstruction.NextInstruction.NextInstruction)
            {
                // Crappy... got a default case statement that we need to extract

                CodePath branchDefaultCodePath = ExtractPath("sw_case_default", parentPath, branchInstruction, branchInstruction.NextInstruction, switchExitInstruction);

                branchInstruction.BranchCodesPaths.Add(new object(), branchDefaultCodePath);
            }
        }
Exemple #7
0
        /// <summary>
        /// Dumps a codepath to debug
        /// </summary>
        /// <param name="path"></param>
        private static void DumpCodePath(CodePath path)
        {
            HLInstruction instruction = path.StartInstruction;

            while (instruction != null)
            {
                Debug.WriteLine(instruction.Instruction.ToString());
                if (instruction.BranchCodesPaths != null && instruction.BranchCodesPaths.Count > 0)
                {
                    foreach (var item in instruction.BranchCodesPaths)
                    {
                        Debug.WriteLine("    " + item.Key + " --> " + item.Value.Name);
                    }
                }
                instruction = instruction.NextInstruction;
            }
        }
Exemple #8
0
        private static CodePath FindCommonPathAncestor(CodePath path1, CodePath path2)
        {
            var paths = new Dictionary <CodePath, object>();

            while (path1 != null)
            {
                paths.Add(path1, null);
                path1 = path1.ParentCodePath;
            }

            while (path2 != null)
            {
                if (paths.ContainsKey(path2))
                {
                    return(path2);
                }
                path2 = path2.ParentCodePath;
            }

            return(null);
        }
        private static CodePath FindCommonPathAncestor(CodePath path1, CodePath path2)
        {
            var paths = new Dictionary<CodePath, object>();

            while(path1 != null)
            {
                paths.Add(path1, null);
                path1 = path1.ParentCodePath;
            }

            while(path2 != null)
            {
                if (paths.ContainsKey(path2))
                {
                    return path2;
                }
                path2 = path2.ParentCodePath;
            }

            return null;
        }
Exemple #10
0
        /// <summary>
        /// Extracts a sequence of instructions into a new sub codepath
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="parentPath"></param>
        /// <param name="parentExitInstruction"></param>
        /// <param name="startInstruction">inclusive</param>
        /// <param name="endInstruction">exclusive (this is where our codepath returns to)</param>
        /// <returns></returns>
        private static CodePath ExtractPath(string identifier, CodePath parentPath, HLInstruction parentExitInstruction, HLInstruction startInstruction,
                                            HLInstruction endInstruction)
        {
            CodePath toPath = CreateCodePath(identifier, startInstruction.Instruction.Offset, parentPath);

            toPath.ParentCodePath        = parentPath;
            toPath.ParentExitInstruction = parentExitInstruction;

            HLInstruction hlInstruction = startInstruction;

            while (true)
            {
                parentPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = toPath;
                toPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null || hlInstruction.NextInstruction == endInstruction)
                {
                    hlInstruction.NextInstruction = null;
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            if (startInstruction.PreviousInstruction != null)
            {
                startInstruction.PreviousInstruction.NextInstruction = endInstruction;
            }
            else
            {
                parentPath.StartInstruction = endInstruction;
                if (endInstruction != null)
                {
                    parentPath.StartOffset = endInstruction.Instruction.Offset;
                }
            }

            if (endInstruction != null)
            {
                endInstruction.PreviousInstruction = startInstruction.PreviousInstruction;
            }
            if (endInstruction == null)
            {
                parentPath.EndInstruction = startInstruction.PreviousInstruction;
                if (parentPath.EndInstruction != null)
                {
                    parentPath.EndOffset = parentPath.EndInstruction.Instruction.Offset +
                                           parentPath.EndInstruction.Instruction.InstructionLength;
                }
                else
                {
                    parentPath.EndOffset = parentPath.StartOffset;
                }
            }

            startInstruction.PreviousInstruction = null;

            toPath.StartInstruction = startInstruction;
            toPath.EndInstruction   = hlInstruction;

            toPath.EndOffset = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            if (endInstruction != null && parentPath == endInstruction.ParentCodePath)
            {
                toPath.ParentEntryInstruction = endInstruction;
            }
            else
            {
                toPath.ParentEntryInstruction = null;
            }

            return(toPath);
        }
        /// <summary>
        /// Extracts a sequence of instructions into a new sub codepath
        /// </summary>
        /// <param name="identifier"></param>
        /// <param name="parentPath"></param>
        /// <param name="parentExitInstruction"></param>
        /// <param name="startInstruction">inclusive</param>
        /// <param name="endInstruction">exclusive (this is where our codepath returns to)</param>
        /// <returns></returns>
        private static CodePath ExtractPath(string identifier, CodePath parentPath, HLInstruction parentExitInstruction, HLInstruction startInstruction,
                                     HLInstruction endInstruction)
        {
            CodePath toPath = CreateCodePath(identifier, startInstruction.Instruction.Offset, parentPath);
            toPath.ParentCodePath = parentPath;
            toPath.ParentExitInstruction = parentExitInstruction;

            HLInstruction hlInstruction = startInstruction;

            while (true)
            {
                parentPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = toPath;
                toPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null || hlInstruction.NextInstruction == endInstruction)
                {
                    hlInstruction.NextInstruction = null;
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            if (startInstruction.PreviousInstruction != null)
            {
                startInstruction.PreviousInstruction.NextInstruction = endInstruction;
            }
            else
            {
                parentPath.StartInstruction = endInstruction;
                if (endInstruction != null)
                {
                    parentPath.StartOffset = endInstruction.Instruction.Offset;
                }
            }

            if (endInstruction != null)
            {
                endInstruction.PreviousInstruction = startInstruction.PreviousInstruction;
            }
            if (endInstruction == null)
            {
                parentPath.EndInstruction = startInstruction.PreviousInstruction;
                if (parentPath.EndInstruction != null)
                {
                    parentPath.EndOffset = parentPath.EndInstruction.Instruction.Offset +
                                           parentPath.EndInstruction.Instruction.InstructionLength;
                }
                else
                {
                    parentPath.EndOffset = parentPath.StartOffset;
                }
            }

            startInstruction.PreviousInstruction = null;

            toPath.StartInstruction = startInstruction;
            toPath.EndInstruction = hlInstruction;

            toPath.EndOffset = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            if (endInstruction != null && parentPath == endInstruction.ParentCodePath)
            {
                toPath.ParentEntryInstruction = endInstruction;
            }
            else
            {
                toPath.ParentEntryInstruction = null;
            }

            return toPath;
        }
        private bool IsCodePathAnIfPath(CodePath path)
        {
            HLInstruction instruction = path.GetFirstInstruction();
            bool foundOneIf = false;
            while (instruction != null)
            {
                if (instruction.IsConditionalBranch && instruction.ProcessedStackValue != null)
                {
                    foundOneIf = true;
                }
                else
                {
                    if (instruction.ProcessedStackValue != null)
                    {
                        return false;
                    }
                }

                instruction = instruction.GetNextInstruction();
            }

            return foundOneIf;
        }
Exemple #13
0
        private void AnalyzeCodePath(Stack <StackValue> stack, CodePath path, ref int tempVarIndex)
        {
            HLInstruction instruction = path.GetFirstInstruction();

            while (instruction != null)
            {
                try
                {
                    if (instruction.BranchFunction != null)
                    {
                        if (!instruction.Instruction.HasStackUsageInfo)
                        {
                            instruction.Instruction.StackIn           = instruction.BranchFunction.ParameterCount;
                            instruction.Instruction.StackOut          = instruction.BranchFunction.ReturnCount;
                            instruction.Instruction.StackLeftOver     = 0;
                            instruction.Instruction.HasStackUsageInfo = true;
                        }
                    }

                    if (instruction.UnconditionalBranch)
                    {
                        // One should not even occur
                        //Debug.Assert(false);
                    }
                    else if (instruction.ExitFunction)
                    {
                        var value = new StackValueOperation(StackValueOperationType.Return);

                        if (path.ParentFunction.ReturnCount > 0)
                        {
                            for (int i = 0; i < path.ParentFunction.ReturnCount; i++)
                            {
                                value.Operands.Add(stack.Pop());
                            }
                        }

                        instruction.ProcessedStackValue = value;
                    }
                    else if (instruction.IsConditionalBranch || instruction.IsSwitchBranch)
                    {
                        instruction.ProcessedStackValue = stack.Pop();
                    }
                    else
                    {
                        bool processDefault = false;

                        StackValueOperation   operationValue = null;
                        StackValue            tempAnyValue;
                        StackValueOperation   tempOpValue;
                        StackValueLiteral     tempLiteralValue;
                        StackValuePointerBase tempPointerValue;

                        OpCode opCode = instruction.Instruction.OpCode;
                        switch (opCode)
                        {
                        case OpCode.AddVec:
                            VectorOperation(StackValueOperationType.Add, stack);
                            break;

                        case OpCode.SubVec:
                            VectorOperation(StackValueOperationType.Sub, stack);
                            break;

                        case OpCode.MulVec:
                            VectorOperation(StackValueOperationType.Mul, stack);
                            break;

                        case OpCode.DivVec:
                            VectorOperation(StackValueOperationType.Div, stack);
                            break;

                        case OpCode.NegVec:
                            VectorOperation(StackValueOperationType.Neg, stack);
                            break;

                        case OpCode.VecFromF:
                            VectorOperation(StackValueOperationType.FromF, stack);
                            break;

                        case OpCode.PushS:
                            stack.Push(new StackValueLiteral((short)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.Push:
                            stack.Push(new StackValueLiteral((int)(uint)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.PushF:
                            stack.Push(new StackValueLiteral((float)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.PushString:
                            stack.Push(new StackValueLiteral((string)instruction.Instruction.Operands[0]));
                            break;

                        case OpCode.Dup:
                            stack.Push(stack.Peek());
                            break;

                        case OpCode.Pop:
                            tempOpValue = stack.Peek() as StackValueOperation;
                            if (tempOpValue != null && tempOpValue.OperationType == StackValueOperationType.Call)
                            {
                                operationValue = new StackValueOperation(StackValueOperationType.Pop);
                                processDefault = true;
                            }
                            break;

                        case OpCode.CallNative:
                            operationValue = new StackValueOperation(instruction.Instruction.Operands[2].ToString());
                            processDefault = true;
                            break;

                        case OpCode.Call:
                            operationValue = new StackValueOperation(instruction.BranchFunction.Name);
                            processDefault = true;
                            break;

                        case OpCode.RefGet:
                            stack.Push(new StackValueDeref(stack.Pop()));
                            break;

                        case OpCode.RefSet:
                            instruction.ProcessedStackValue = new StackValueAssign(PopPointer(stack), stack.Pop());
                            break;

                        case OpCode.RefPeekSet:
                            tempAnyValue = stack.Pop();     // value!
                            instruction.ProcessedStackValue = new StackValueAssign(PeekPointer(stack), tempAnyValue);
                            break;

                        case OpCode.ArrayExplode:
                            // This is used to either pass a structure to a native/function call
                            // or to explode the variables onto the stack to do a "shallow-copy"

                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var explodeCount = (int)tempLiteralValue.Value;
                            for (int i = 0; i < explodeCount; i++)
                            {
                                stack.Push(new StackValueDeref(new StackValuePointerIndex(tempPointerValue, i)));
                            }

                            break;

                        case OpCode.ArrayImplode:
                            // The only case this is ever used is for a shallow copy!

                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var tempStack    = new Stack <StackValue>();
                            var implodeCount = (int)tempLiteralValue.Value;
                            for (int i = implodeCount - 1; i >= 0; i--)
                            {
                                tempStack.Push(
                                    new StackValueAssign(new StackValuePointerIndex(tempPointerValue, i),
                                                         stack.Pop()));
                            }

                            var stackValueGroup = new ProcessedStackValueGroup();

                            stackValueGroup.Values.AddRange(tempStack.ToArray());
                            instruction.ProcessedStackValue = stackValueGroup;

                            break;

                        case OpCode.Var0:
                        case OpCode.Var1:
                        case OpCode.Var2:
                        case OpCode.Var3:
                        case OpCode.Var4:
                        case OpCode.Var5:
                        case OpCode.Var6:
                        case OpCode.Var7:
                            stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                (opCode - OpCode.Var0)));
                            break;

                        case OpCode.Var:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.LocalVar:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Local,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.GlobalVar:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerVar(StackValuePointerType.Global,
                                                                (int)tempLiteralValue.Value));
                            break;

                        case OpCode.ArrayRef:
                            tempPointerValue = PopPointer(stack);
                            tempLiteralValue = stack.Pop() as StackValueLiteral;
                            tempAnyValue     = stack.Pop();
                            Debug.Assert(tempPointerValue != null);
                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            stack.Push(new StackValuePointerArray(tempPointerValue, tempAnyValue,
                                                                  (int)tempLiteralValue.Value));
                            break;

                        case OpCode.NullObj:
                            stack.Push(new StackValuePointerVar(StackValuePointerType.Null));
                            break;

                        case OpCode.Add:
                            // Special case for pointer add
                            tempAnyValue     = stack.Pop();
                            tempPointerValue = stack.Peek() as StackValuePointerBase;

                            if (tempPointerValue != null)
                            {
                                stack.Pop();     // tempPointerValue

                                tempLiteralValue = tempAnyValue as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null && (int)tempLiteralValue.Value % 4 == 0);

                                stack.Push(new StackValuePointerIndex(tempPointerValue,
                                                                      (int)tempLiteralValue.Value / 4));
                            }
                            else
                            {
                                stack.Push(tempAnyValue);
                                operationValue = new StackValueOperation(opCode);
                                processDefault = true;
                            }
                            break;

                        case OpCode.StrCat:
                        case OpCode.StrCatI:
                        case OpCode.StrCpy:
                        case OpCode.IntToStr:
                            operationValue = new StackValueStringOperation(opCode, (byte)instruction.Instruction.Operands[0]);
                            processDefault = true;
                            break;

                        case OpCode.StrVarCpy:
                            tempPointerValue = PopPointer(stack);

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var targetSize = (uint)(int)tempLiteralValue.Value;

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var sourceSize = (uint)(int)tempLiteralValue.Value;

                            var popSize = sourceSize;

                            tempAnyValue = PopPointer(stack);

                            // Pop till the last one
                            for (var i = 1; i < popSize; i++)
                            {
                                tempAnyValue = PopPointer(stack);
                            }

                            operationValue = new StackValueStringOperation(opCode, targetSize, sourceSize);
                            operationValue.Operands.Add(new StackValueRef(tempAnyValue)); // 0 = source
                            operationValue.Operands.Add(tempPointerValue);                // 1 = target

                            instruction.ProcessedStackValue = operationValue;

                            break;

                        case OpCode.RefProtect:
                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var protectMode = (int)tempLiteralValue.Value;

                            Debug.Assert(protectMode == 1 || protectMode == 2 || protectMode == 5 || protectMode == 6);

                            tempLiteralValue = stack.Pop() as StackValueLiteral;

                            Debug.Assert(tempLiteralValue != null &&
                                         tempLiteralValue.ValueType == StackValueType.Integer);

                            var protectCount = (int)tempLiteralValue.Value;

                            //Debug.Assert(protectCount == 1);

                            tempPointerValue = PopPointer(stack);

                            operationValue = new StackValueOperation(StackValueOperationType.RefProtect);
                            operationValue.Operands.Add(tempPointerValue);
                            operationValue.Operands.Add(tempLiteralValue);

                            if ((protectMode & 1) != 0)
                            {
                                stack.Push(operationValue);
                            }

                            break;

                        default:
                            if (instruction.Instruction is InstructionPush)
                            {
                                // PushD special case
                                stack.Push(new StackValueLiteral((int)instruction.Instruction.Operands[0]));
                            }
                            else
                            {
                                operationValue = new StackValueOperation(opCode);
                                processDefault = true;
                            }
                            break;
                        }

                        if (processDefault)
                        {
                            Debug.Assert(instruction.Instruction.HasStackUsageInfo);

                            var stackValues = new Stack <StackValue>();
                            for (int i = 0; i < instruction.Instruction.StackIn; i++)
                            {
                                StackValue stackItem = stack.Pop();
                                stackValues.Push(stackItem);
                            }

                            operationValue.Operands.AddRange(stackValues);

                            if (instruction.Instruction.StackLeftOver > 0)
                            {
                                for (int i = 0; i < instruction.Instruction.StackLeftOver; i++)
                                {
                                    stackValues.Push(stackValues.Pop());
                                }
                            }

                            if (instruction.Instruction.StackOut > 0)
                            {
                                if (instruction.Instruction.StackOut > 1)
                                {
                                    var multiAssign = new StackValueAssignMulti(operationValue);
                                    for (int i = 0; i < instruction.Instruction.StackOut; i++)
                                    {
                                        tempPointerValue = new StackValuePointerVar(StackValuePointerType.Temporary,
                                                                                    tempVarIndex + i);
                                        multiAssign.AssignPointers.Add(tempPointerValue);
                                        stack.Push(new StackValueDeref(tempPointerValue));
                                    }
                                    tempVarIndex += instruction.Instruction.StackOut;
                                    instruction.ProcessedStackValue = multiAssign;
                                }
                                else
                                {
                                    stack.Push(operationValue);
                                }
                            }
                            else
                            {
                                instruction.ProcessedStackValue = operationValue;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(
                              "Error while decompiling instruction : " + instruction.Instruction + "\n", e);
                }

                instruction = instruction.GetNextInstruction();
            }
        }
        private void AnalyzeCodePath(CodePath path)
        {
            HLInstruction previousInstruction = null;
            var branchInstructions = new List<HLInstruction>();

            int offset = path.StartOffset;

            while (true)
            {
                if (path.ParentCodePath != null) // non main
                {
                    CodePath parentPath = path.ParentFunction.DetermineCodePathFromOffset(offset);
                    if (parentPath != null)
                    {
                        if (!path.IsInstructionOffsetInPathTree(offset))
                        {
                            // Hmm.. so the target offset is not the current tree... which is bad
                            // This can only mean a bad jump assumption before. We must somehow extract
                            // The instructions from this existing path and merge it with our parent

                            HLInstruction startInstruction = parentPath.InstructionMap[offset];
                            CodePath newPath = ExtractPath(path.ParentCodePath.Name + "_temp", parentPath,
                                                           startInstruction.PreviousInstruction, startInstruction, null);

                            // Now we can merge it with this path's parent

                            CodePath targetCodePath = FindCommonPathAncestor(path, parentPath);
                            MergePath(targetCodePath, newPath);

                            if (parentPath.ParentCodePath == targetCodePath)
                            {
                                parentPath.ParentEntryInstruction = startInstruction;
                            }
                            else
                            {
                                parentPath.ParentEntryInstruction = null;
                            }

                            // Set some variables so we know how to break out of here.

                            parentPath = targetCodePath;
                        }

                        // Okay, break out of there buddy!

                        if (parentPath == path.ParentCodePath)
                        {
                            path.ParentEntryInstruction = path.ParentCodePath.GetInstruction(offset);
                        }
                        else
                        {
                            // null = we reached the end of the code path for the parent as well!
                            path.ParentEntryInstruction = null;
                        }
                        break;
                    }

                }

                Instruction instruction = Decoder.Decode(offset);
                offset += instruction.InstructionLength;

                var hlInstruction = new HLInstruction(instruction);

                if (instruction is InstructionFnEnd)
                {
                    if (path.ParentCodePath == null)
                    {
                        // This means this is in the function root

                        path.ParentFunction.EndOffset = instruction.Offset + instruction.InstructionLength;
                        path.ParentFunction.ReturnCount = (instruction as InstructionFnEnd).ReturnCount;

                        hlInstruction.ExitFunction = true;
                    }
                    else
                    {
                        if (instruction.Offset == path.ParentFunction.EndOffset)
                        {
                            // Non root code path reached end of function
                            path.ParentEntryInstruction = null;

                            hlInstruction.ExitFunction = true;
                        }
                        else
                        {
                            // Hmm, this must be a exit function invocation
                            // We'll add it, and exit out of the loop later in the code

                            hlInstruction.ExitFunction = true;
                        }
                    }
                }
                else if (instruction is InstructionBranch)
                {
                    if (instruction.OpCode == OpCode.Call)
                    {
                        hlInstruction.BranchFunction = FunctionTargets[instruction.BranchOffset];
                    }
                    else if (instruction.OpCode == OpCode.Jump)
                    {
                        if (path.ParentCodePath != null && instruction.BranchOffset < instruction.Offset &&
                            path.ParentCodePath.GetInstruction(instruction.BranchOffset) != null)
                        {
                            // Loop!
                            hlInstruction.BranchLoopInstruction =
                                path.ParentCodePath.GetInstruction(instruction.BranchOffset);
                            hlInstruction.BranchLoopInstruction.LoopCodePath = path;

                            // The next instruction should break us out of this codepath...

                            hlInstruction.UnconditionalBranch = true;
                        }
                        else
                        {
                            // Okay, we'll just be naive for now and follow the jump
                            // It is *possible* that this jump might be for an "else" or "case default" block, in which case, we are screwed.
                            // But we will deal with this while we deal with branches
                            hlInstruction.UnconditionalBranch = true;
                            offset = instruction.BranchOffset;
                        }
                    }
                    else
                    {
                        // We got a conditional branch instruction
                        hlInstruction.IsConditionalBranch = true;
                        branchInstructions.Add(hlInstruction);
                        offset = instruction.BranchOffset;
                    }
                }
                else if (instruction is InstructionSwitch)
                {
                    hlInstruction.IsSwitchBranch = true;
                    branchInstructions.Add(hlInstruction);
                }

                hlInstruction.PreviousInstruction = previousInstruction;
                if (previousInstruction == null)
                {
                    path.StartInstruction = hlInstruction;
                }
                else
                {
                    previousInstruction.NextInstruction = hlInstruction;
                }
                previousInstruction = hlInstruction;

                hlInstruction.ParentCodePath = path;
                path.InstructionMap.Add(instruction.Offset, hlInstruction);

                if (hlInstruction.ExitFunction)
                {
                    break; // out of while loop
                }
            }

            path.EndInstruction = previousInstruction;
            path.EndOffset = offset;

            AnalyzeBranchInstructions(branchInstructions);
        }
 /// <summary>
 /// Dumps a codepath to debug
 /// </summary>
 /// <param name="path"></param>
 private static void DumpCodePath(CodePath path)
 {
     HLInstruction instruction = path.StartInstruction;
     while (instruction != null)
     {
         Debug.WriteLine(instruction.Instruction.ToString());
         if (instruction.BranchCodesPaths != null && instruction.BranchCodesPaths.Count > 0)
         {
             foreach (var item in instruction.BranchCodesPaths)
             {
                 Debug.WriteLine("    " + item.Key + " --> " + item.Value.Name);
             }
         }
         instruction = instruction.NextInstruction;
     }
 }
        private static void MergePath(CodePath targetPath, CodePath newPath)
        {
            HLInstruction hlInstruction = newPath.StartInstruction;

            if (targetPath.EndInstruction == null)
            {
                targetPath.StartInstruction = hlInstruction;
                hlInstruction.PreviousInstruction = null;
            }
            else
            {
                targetPath.EndInstruction.NextInstruction = hlInstruction;
                hlInstruction.PreviousInstruction = targetPath.EndInstruction;
            }

            while (true)
            {
                newPath.InstructionMap.Remove(hlInstruction.Instruction.Offset);
                hlInstruction.ParentCodePath = targetPath;
                targetPath.InstructionMap.Add(hlInstruction.Instruction.Offset, hlInstruction);

                if (hlInstruction.NextInstruction == null)
                {
                    break;
                }

                hlInstruction = hlInstruction.NextInstruction;
            }

            targetPath.EndInstruction = hlInstruction;
            targetPath.EndOffset = hlInstruction.Instruction.Offset + hlInstruction.Instruction.InstructionLength;

            newPath.ParentFunction.CodePaths.Remove(newPath);
        }
Exemple #17
0
        private void AnalyzeCodePath(CodePath path)
        {
            HLInstruction previousInstruction = null;
            var           branchInstructions  = new List <HLInstruction>();

            int offset = path.StartOffset;

            while (true)
            {
                if (path.ParentCodePath != null) // non main
                {
                    CodePath parentPath = path.ParentFunction.DetermineCodePathFromOffset(offset);
                    if (parentPath != null)
                    {
                        if (!path.IsInstructionOffsetInPathTree(offset))
                        {
                            // Hmm.. so the target offset is not the current tree... which is bad
                            // This can only mean a bad jump assumption before. We must somehow extract
                            // The instructions from this existing path and merge it with our parent

                            HLInstruction startInstruction = parentPath.InstructionMap[offset];
                            CodePath      newPath          = ExtractPath(path.ParentCodePath.Name + "_temp", parentPath,
                                                                         startInstruction.PreviousInstruction, startInstruction, null);

                            // Now we can merge it with this path's parent

                            CodePath targetCodePath = FindCommonPathAncestor(path, parentPath);
                            MergePath(targetCodePath, newPath);

                            if (parentPath.ParentCodePath == targetCodePath)
                            {
                                parentPath.ParentEntryInstruction = startInstruction;
                            }
                            else
                            {
                                parentPath.ParentEntryInstruction = null;
                            }

                            // Set some variables so we know how to break out of here.

                            parentPath = targetCodePath;
                        }

                        // Okay, break out of there buddy!

                        if (parentPath == path.ParentCodePath)
                        {
                            path.ParentEntryInstruction = path.ParentCodePath.GetInstruction(offset);
                        }
                        else
                        {
                            // null = we reached the end of the code path for the parent as well!
                            path.ParentEntryInstruction = null;
                        }
                        break;
                    }
                }

                Instruction instruction = Decoder.Decode(offset);
                offset += instruction.InstructionLength;

                var hlInstruction = new HLInstruction(instruction);

                if (instruction is InstructionFnEnd)
                {
                    if (path.ParentCodePath == null)
                    {
                        // This means this is in the function root

                        path.ParentFunction.EndOffset   = instruction.Offset + instruction.InstructionLength;
                        path.ParentFunction.ReturnCount = (instruction as InstructionFnEnd).ReturnCount;

                        hlInstruction.ExitFunction = true;
                    }
                    else
                    {
                        if (instruction.Offset == path.ParentFunction.EndOffset)
                        {
                            // Non root code path reached end of function
                            path.ParentEntryInstruction = null;

                            hlInstruction.ExitFunction = true;
                        }
                        else
                        {
                            // Hmm, this must be a exit function invocation
                            // We'll add it, and exit out of the loop later in the code

                            hlInstruction.ExitFunction = true;
                        }
                    }
                }
                else if (instruction is InstructionBranch)
                {
                    if (instruction.OpCode == OpCode.Call)
                    {
                        hlInstruction.BranchFunction = FunctionTargets[instruction.BranchOffset];
                    }
                    else if (instruction.OpCode == OpCode.Jump)
                    {
                        if (path.ParentCodePath != null && instruction.BranchOffset < instruction.Offset &&
                            path.ParentCodePath.GetInstruction(instruction.BranchOffset) != null)
                        {
                            // Loop!
                            hlInstruction.BranchLoopInstruction =
                                path.ParentCodePath.GetInstruction(instruction.BranchOffset);
                            hlInstruction.BranchLoopInstruction.LoopCodePath = path;

                            // The next instruction should break us out of this codepath...

                            hlInstruction.UnconditionalBranch = true;
                        }
                        else
                        {
                            // Okay, we'll just be naive for now and follow the jump
                            // It is *possible* that this jump might be for an "else" or "case default" block, in which case, we are screwed.
                            // But we will deal with this while we deal with branches
                            hlInstruction.UnconditionalBranch = true;
                            offset = instruction.BranchOffset;
                        }
                    }
                    else
                    {
                        // We got a conditional branch instruction
                        hlInstruction.IsConditionalBranch = true;
                        branchInstructions.Add(hlInstruction);
                        offset = instruction.BranchOffset;
                    }
                }
                else if (instruction is InstructionSwitch)
                {
                    hlInstruction.IsSwitchBranch = true;
                    branchInstructions.Add(hlInstruction);
                }

                hlInstruction.PreviousInstruction = previousInstruction;
                if (previousInstruction == null)
                {
                    path.StartInstruction = hlInstruction;
                }
                else
                {
                    previousInstruction.NextInstruction = hlInstruction;
                }
                previousInstruction = hlInstruction;

                hlInstruction.ParentCodePath = path;
                path.InstructionMap.Add(instruction.Offset, hlInstruction);

                if (hlInstruction.ExitFunction)
                {
                    break; // out of while loop
                }
            }

            path.EndInstruction = previousInstruction;
            path.EndOffset      = offset;

            AnalyzeBranchInstructions(branchInstructions);
        }
        private void ProcessCodePath(TextWriter writer, CodePath path, string indent)
        {
            HLInstruction instruction = path.GetFirstInstruction();

            while (instruction != null)
            {
                if (instruction.IsConditionalBranch)
                {
                    writer.WriteLine(string.Format("{0}if ({1})", indent,
                                                   instruction.DefaultConditional ? "true" : "false"));
                    writer.WriteLine(indent + "{");
                    ProcessCodePath(writer, instruction.BranchCodesPaths[instruction.DefaultConditional],
                                    indent + "    ");
                    writer.WriteLine(indent + "}");

                    if (instruction.BranchCodesPaths.ContainsKey(!instruction.DefaultConditional))
                    {
                        CodePath elsePath = instruction.BranchCodesPaths[!instruction.DefaultConditional];

                        if (elsePath.StartInstruction != null)
                        {
                            writer.WriteLine(indent + "else");
                            writer.WriteLine(indent + "{");
                            ProcessCodePath(writer, elsePath,
                                            indent + "    ");
                            writer.WriteLine(indent + "}");
                        }
                    }
                }
                else if (instruction.IsSwitchBranch)
                {
                    // Do switch cases ever fall through?? I'm assuming they don't here!

                    writer.WriteLine(indent + "switch");
                    writer.WriteLine(indent + "{");

                    // Keep track of code paths are have already outputted to keep
                    // track of offsets that lead to the same codepath
                    var swDonePaths = new List<CodePath>();

                    foreach (var item in instruction.BranchCodesPaths)
                    {
                        if (swDonePaths.Contains(item.Value))
                        {
                            continue;
                        }

                        foreach (var item2 in instruction.BranchCodesPaths)
                        {
                            // O(n^2) loop here, there's probably a better way to optimize it

                            if (item2.Value == item.Value)
                            {
                                if (item2.Key.GetType() == typeof (int))
                                {
                                    writer.WriteLine(string.Format("{0}    case {1}:", indent, item2.Key));
                                }
                                else
                                {
                                    writer.WriteLine(string.Format("{0}    default:", indent, item2.Key));
                                }
                            }
                        }

                        writer.WriteLine(indent + "    {");
                        ProcessCodePath(writer, item.Value, indent + "        ");
                        if (item.Value.EndInstruction == null || !item.Value.EndInstruction.ExitFunction)
                        {
                            writer.WriteLine(indent + "        break");
                        }
                        writer.WriteLine(indent + "    }");

                        swDonePaths.Add(item.Value);
                    }

                    writer.WriteLine(indent + "}");
                }
                else if (instruction.LoopCodePath != null)
                {
                    // First of a loop instruction (hopefully, someday, this will be extracted out by the ProgramAnalyzer)
                    // Can we ever break out of a loop? I assume we can't here!

                    writer.WriteLine(indent + "while");
                    writer.WriteLine(indent + "(");
                    instruction = WriteLoopConditional(writer, instruction, indent + "    ");
                    writer.WriteLine(indent + ")");
                    writer.WriteLine(indent + "{");
                    ProcessCodePath(writer, instruction.BranchCodesPaths[true], indent + "    ");
                    writer.WriteLine(indent + "}");
                }
                else
                {
                    WriteInstruction(writer, instruction, indent);
                }

                instruction = instruction.GetNextInstruction();
            }
        }
        private void AnalyzeCodePath(Stack<StackValue> stack, CodePath path, ref int tempVarIndex)
        {
            HLInstruction instruction = path.GetFirstInstruction();
            while (instruction != null)
            {
                try
                {
                    if (instruction.BranchFunction != null)
                    {
                        if (!instruction.Instruction.HasStackUsageInfo)
                        {
                            instruction.Instruction.StackIn = instruction.BranchFunction.ParameterCount;
                            instruction.Instruction.StackOut = instruction.BranchFunction.ReturnCount;
                            instruction.Instruction.StackLeftOver = 0;
                            instruction.Instruction.HasStackUsageInfo = true;
                        }
                    }

                    if (instruction.UnconditionalBranch)
                    {
                        // One should not even occur
                        //Debug.Assert(false);
                    }
                    else if (instruction.ExitFunction)
                    {
                        var value = new StackValueOperation(StackValueOperationType.Return);

                        if (path.ParentFunction.ReturnCount > 0)
                        {
                            for (int i = 0; i < path.ParentFunction.ReturnCount; i++)
                            {
                                value.Operands.Add(stack.Pop());
                            }
                        }

                        instruction.ProcessedStackValue = value;
                    }
                    else if (instruction.IsConditionalBranch || instruction.IsSwitchBranch)
                    {
                        instruction.ProcessedStackValue = stack.Pop();
                    }
                    else
                    {
                        bool processDefault = false;

                        StackValueOperation operationValue = null;
                        StackValue tempAnyValue;
                        StackValueOperation tempOpValue;
                        StackValueLiteral tempLiteralValue;
                        StackValuePointerBase tempPointerValue;

                        OpCode opCode = instruction.Instruction.OpCode;
                        switch (opCode)
                        {
                            case OpCode.AddVec:
                                VectorOperation(StackValueOperationType.Add, stack);
                                break;
                            case OpCode.SubVec:
                                VectorOperation(StackValueOperationType.Sub, stack);
                                break;
                            case OpCode.MulVec:
                                VectorOperation(StackValueOperationType.Mul, stack);
                                break;
                            case OpCode.DivVec:
                                VectorOperation(StackValueOperationType.Div, stack);
                                break;
                            case OpCode.NegVec:
                                VectorOperation(StackValueOperationType.Neg, stack);
                                break;
                            case OpCode.VecFromF:
                                VectorOperation(StackValueOperationType.FromF, stack);
                                break;
                            case OpCode.PushS:
                                stack.Push(new StackValueLiteral((short) instruction.Instruction.Operands[0]));
                                break;
                            case OpCode.Push:
                                stack.Push(new StackValueLiteral((int) (uint) instruction.Instruction.Operands[0]));
                                break;
                            case OpCode.PushF:
                                stack.Push(new StackValueLiteral((float) instruction.Instruction.Operands[0]));
                                break;
                            case OpCode.PushString:
                                stack.Push(new StackValueLiteral((string) instruction.Instruction.Operands[0]));
                                break;
                            case OpCode.Dup:
                                stack.Push(stack.Peek());
                                break;
                            case OpCode.Pop:
                                tempOpValue = stack.Peek() as StackValueOperation;
                                if (tempOpValue != null && tempOpValue.OperationType == StackValueOperationType.Call)
                                {
                                    operationValue = new StackValueOperation(StackValueOperationType.Pop);
                                    processDefault = true;
                                }
                                break;
                            case OpCode.CallNative:
                                operationValue = new StackValueOperation(instruction.Instruction.Operands[2].ToString());
                                processDefault = true;
                                break;
                            case OpCode.Call:
                                operationValue = new StackValueOperation(instruction.BranchFunction.Name);
                                processDefault = true;
                                break;
                            case OpCode.RefGet:
                                stack.Push(new StackValueDeref(stack.Pop()));
                                break;
                            case OpCode.RefSet:
                                instruction.ProcessedStackValue = new StackValueAssign(PopPointer(stack), stack.Pop());
                                break;
                            case OpCode.RefPeekSet:
                                tempAnyValue = stack.Pop(); // value!
                                instruction.ProcessedStackValue = new StackValueAssign(PeekPointer(stack), tempAnyValue);
                                break;
                            case OpCode.ArrayExplode:
                                // This is used to either pass a structure to a native/function call
                                // or to explode the variables onto the stack to do a "shallow-copy"

                                tempPointerValue = PopPointer(stack);
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                var explodeCount = (int) tempLiteralValue.Value;
                                for (int i = 0; i < explodeCount; i++)
                                {
                                    stack.Push(new StackValueDeref(new StackValuePointerIndex(tempPointerValue, i)));
                                }

                                break;
                            case OpCode.ArrayImplode:
                                // The only case this is ever used is for a shallow copy!

                                tempPointerValue = PopPointer(stack);
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                var tempStack = new Stack<StackValue>();
                                var implodeCount = (int) tempLiteralValue.Value;
                                for (int i = implodeCount - 1; i >= 0; i--)
                                {
                                    tempStack.Push(
                                        new StackValueAssign(new StackValuePointerIndex(tempPointerValue, i),
                                                             stack.Pop()));
                                }

                                var stackValueGroup = new ProcessedStackValueGroup();

                                stackValueGroup.Values.AddRange(tempStack.ToArray());
                                instruction.ProcessedStackValue = stackValueGroup;

                                break;
                            case OpCode.Var0:
                            case OpCode.Var1:
                            case OpCode.Var2:
                            case OpCode.Var3:
                            case OpCode.Var4:
                            case OpCode.Var5:
                            case OpCode.Var6:
                            case OpCode.Var7:
                                stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                    (opCode - OpCode.Var0)));
                                break;
                            case OpCode.Var:
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                stack.Push(new StackValuePointerVar(StackValuePointerType.Stack,
                                                                    (int) tempLiteralValue.Value));
                                break;
                            case OpCode.LocalVar:
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                stack.Push(new StackValuePointerVar(StackValuePointerType.Local,
                                                                    (int) tempLiteralValue.Value));
                                break;
                            case OpCode.GlobalVar:
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                stack.Push(new StackValuePointerVar(StackValuePointerType.Global,
                                                                    (int) tempLiteralValue.Value));
                                break;
                            case OpCode.ArrayRef:
                                tempPointerValue = PopPointer(stack);
                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                tempAnyValue = stack.Pop();
                                Debug.Assert(tempPointerValue != null);
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                stack.Push(new StackValuePointerArray(tempPointerValue, tempAnyValue,
                                                                      (int) tempLiteralValue.Value));
                                break;
                            case OpCode.NullObj:
                                stack.Push(new StackValuePointerVar(StackValuePointerType.Null));
                                break;
                            case OpCode.Add:
                                // Special case for pointer add
                                tempAnyValue = stack.Pop();
                                tempPointerValue = stack.Peek() as StackValuePointerBase;

                                if (tempPointerValue != null)
                                {
                                    stack.Pop(); // tempPointerValue

                                    tempLiteralValue = tempAnyValue as StackValueLiteral;
                                    Debug.Assert(tempLiteralValue != null && (int) tempLiteralValue.Value%4 == 0);

                                    stack.Push(new StackValuePointerIndex(tempPointerValue,
                                                                          (int) tempLiteralValue.Value/4));
                                }
                                else
                                {
                                    stack.Push(tempAnyValue);
                                    operationValue = new StackValueOperation(opCode);
                                    processDefault = true;
                                }
                                break;
                            case OpCode.StrCat:
                            case OpCode.StrCatI:
                            case OpCode.StrCpy:
                            case OpCode.IntToStr:
                                operationValue = new StackValueStringOperation(opCode, (byte)instruction.Instruction.Operands[0]);
                                processDefault = true;
                                break;
                            case OpCode.StrVarCpy:
                                tempPointerValue = PopPointer(stack);

                                tempLiteralValue = stack.Pop() as StackValueLiteral;
                                
                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                var targetSize = (uint)(int)tempLiteralValue.Value;

                                tempLiteralValue = stack.Pop() as StackValueLiteral;

                                Debug.Assert(tempLiteralValue != null &&
                                             tempLiteralValue.ValueType == StackValueType.Integer);

                                var sourceSize = (uint)(int)tempLiteralValue.Value;

                                var popSize = sourceSize;

                                tempAnyValue = PopPointer(stack);

                                // Pop till the last one
                                for (var i = 1; i < popSize; i++)
                                {
                                    tempAnyValue = PopPointer(stack);
                                }

                                operationValue = new StackValueStringOperation(opCode, targetSize, sourceSize);
                                operationValue.Operands.Add(new StackValueRef(tempAnyValue)); // 0 = source
                                operationValue.Operands.Add(tempPointerValue); // 1 = target
                                
                                instruction.ProcessedStackValue = operationValue;

                                break;
                            case OpCode.RefProtect:
                                tempLiteralValue = stack.Pop() as StackValueLiteral;

                                Debug.Assert(tempLiteralValue != null &&
                                     tempLiteralValue.ValueType == StackValueType.Integer);

                                var protectMode = (int)tempLiteralValue.Value;

                                Debug.Assert(protectMode == 1 || protectMode == 2 || protectMode == 5 || protectMode == 6);

                                tempLiteralValue = stack.Pop() as StackValueLiteral;

                                Debug.Assert(tempLiteralValue != null &&
                                     tempLiteralValue.ValueType == StackValueType.Integer);

                                var protectCount = (int)tempLiteralValue.Value;

                                //Debug.Assert(protectCount == 1);

                                tempPointerValue = PopPointer(stack);

                                operationValue = new StackValueOperation(StackValueOperationType.RefProtect);
                                operationValue.Operands.Add(tempPointerValue);
                                operationValue.Operands.Add(tempLiteralValue);

                                if ((protectMode & 1) != 0)
                                {
                                    stack.Push(operationValue);
                                }
                                
                                break;
                            default:
                                if (instruction.Instruction is InstructionPush)
                                {
                                    // PushD special case
                                    stack.Push(new StackValueLiteral((int) instruction.Instruction.Operands[0]));
                                }
                                else
                                {
                                    operationValue = new StackValueOperation(opCode);
                                    processDefault = true;
                                }
                                break;
                        }

                        if (processDefault)
                        {
                            Debug.Assert(instruction.Instruction.HasStackUsageInfo);

                            var stackValues = new Stack<StackValue>();
                            for (int i = 0; i < instruction.Instruction.StackIn; i++)
                            {
                                StackValue stackItem = stack.Pop();
                                stackValues.Push(stackItem);
                            }

                            operationValue.Operands.AddRange(stackValues);

                            if (instruction.Instruction.StackLeftOver > 0)
                            {
                                for (int i = 0; i < instruction.Instruction.StackLeftOver; i++)
                                {
                                    stackValues.Push(stackValues.Pop());
                                }
                            }

                            if (instruction.Instruction.StackOut > 0)
                            {
                                if (instruction.Instruction.StackOut > 1)
                                {
                                    var multiAssign = new StackValueAssignMulti(operationValue);
                                    for (int i = 0; i < instruction.Instruction.StackOut; i++)
                                    {
                                        tempPointerValue = new StackValuePointerVar(StackValuePointerType.Temporary,
                                                                                    tempVarIndex + i);
                                        multiAssign.AssignPointers.Add(tempPointerValue);
                                        stack.Push(new StackValueDeref(tempPointerValue));
                                    }
                                    tempVarIndex += instruction.Instruction.StackOut;
                                    instruction.ProcessedStackValue = multiAssign;
                                }
                                else
                                {
                                    stack.Push(operationValue);
                                }
                            }
                            else
                            {
                                instruction.ProcessedStackValue = operationValue;
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    throw new Exception(
                        "Error while decompiling instruction : " + instruction.Instruction + "\n", e);
                }

                instruction = instruction.GetNextInstruction();
            }
        }
 private static CodePath CreateCodePath(string identifier, int startOffset, CodePath parentPath)
 {
     CodePath path = parentPath.ParentFunction.CreateCodePath(string.Format("{0}_{1:x}", identifier, startOffset));
     path.ParentCodePath = parentPath;
     path.StartOffset = startOffset;
     return path;
 }