Exemple #1
0
 public ILStack Clone()
 {
     ILStack clone = new ILStack();
     foreach(Slot s in this.Items) {
         clone.Items.Add(new Slot(s.PushedBy, s.Type));
     }
     return clone;
 }
Exemple #2
0
        public void StackAnalysis(List<Instruction> body, MethodDefinition methodDef)
        {
            Queue<Instruction> agenda = new Queue<Instruction>();

            // Add known states
            stackBefore[body[0]] = new ILStack();
            agenda.Enqueue(body[0]);

            if(methodDef.Body.HasExceptionHandlers) {
                foreach(ExceptionHandler ex in methodDef.Body.ExceptionHandlers) {
                    stackBefore[ex.TryStart] = new ILStack();
                    agenda.Enqueue(ex.TryStart);

                    ILStack stack = new ILStack();
                    stack.Items.Add(new ILStack.Slot(null, MyRocks.TypeException));
                    stackBefore[ex.HandlerStart] = stack;
                    agenda.Enqueue(ex.HandlerStart);
                }
            }

            // Process agenda
            while(agenda.Count > 0) {
                Instruction inst = agenda.Dequeue();

                // What is the effect of the instruction on the stack?
                ILStack newStack = stackBefore[inst].Clone();
                int popCount = inst.GetPopCount();
                if (popCount == int.MaxValue) popCount = stackBefore[inst].Items.Count; // Pop all
                List<TypeReference> typeArgs = new List<TypeReference>();
                for (int i = newStack.Items.Count - popCount; i < newStack.Items.Count; i++) {
                    typeArgs.Add(newStack.Items[i].Type);
                }
                TypeReference type;
                try {
                    type = inst.GetTypeInternal(methodDef, typeArgs);
                } catch {
                    type = MyRocks.TypeObject;
                }
                if (popCount > 0) {
                    newStack.Items.RemoveRange(newStack.Items.Count - popCount, popCount);
                }
                int pushCount = inst.GetPushCount();
                for (int i = 0; i < pushCount; i++) {
                    newStack.Items.Add(new ILStack.Slot(inst, type));
                }

                // Apply the state to any successors
                List<Instruction> branchTargets = new List<Instruction>();
                if (inst.OpCode.CanFallThough()) {
                    branchTargets.Add(inst.Next);
                }
                if (inst.OpCode.IsBranch()) {
                    if (inst.Operand is Instruction[]) {
                        branchTargets.AddRange((Instruction[])inst.Operand);
                    } else {
                        branchTargets.Add((Instruction)inst.Operand);
                    }
                }
                foreach (Instruction branchTarget in branchTargets) {
                    ILStack nextStack;
                    if (stackBefore.TryGetValue(branchTarget, out nextStack)) {
                        // TODO: Compare stacks
                    } else {
                        stackBefore[branchTarget] = newStack;
                        agenda.Enqueue(branchTarget);
                    }
                }
            }
        }