private void VectorOperation(StackValueOperationType type, Stack<StackValue> stack)
        {
            var vec1 = new StackValue[3];
            var vec2 = new StackValue[3];

            if (type != StackValueOperationType.FromF)
            {
                vec1[0] = stack.Pop();
                vec1[1] = stack.Pop();
                vec1[2] = stack.Pop();

                if (type != StackValueOperationType.Neg)
                {
                    vec2[0] = stack.Pop();
                    vec2[1] = stack.Pop();
                    vec2[2] = stack.Pop();

                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[2], vec2[2]}));
                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[1], vec2[1]}));
                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[0], vec2[0]}));
                }
                else
                {
                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[2]}));
                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[1]}));
                    stack.Push(new StackValueOperation(type, StackValueType.Float, new[] {vec1[0]}));
                }
            }
            else
            {
                vec1[0] = stack.Pop();

                stack.Push(vec1[0]);
                stack.Push(vec1[0]);
                stack.Push(vec1[0]);
            }
        }
 public StackValueAssignMulti(StackValue assignment)
 {
     AssignValue = assignment;
     AssignPointers = new List<StackValuePointerBase>();
 }
Beispiel #3
0
 public StackValuePointerArray(StackValuePointerBase pointer, StackValue index, int itemSize)
 {
     Pointer  = pointer;
     Index    = index;
     ItemSize = itemSize;
 }
 public StackValuePointerArray(StackValuePointerBase pointer, StackValue index, int itemSize)
 {
     Pointer = pointer;
     Index = index;
     ItemSize = itemSize;
 }
Beispiel #5
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();
            }
        }