Example #1
0
        private static CILBB BuildCILCFG(Instruction start)
        {
            if (start == null)
            {
                throw new ArgumentNullException("start");
            }

            List <CILBB> cilbblist = new List <CILBB>();

            Instruction instr = start;

            // Determine leading instructions starting each basic block:
            // The first instruction is a leader.
            // The target of a conditional or an unconditional goto/jump instruction is a leader.
            // The instruction that immediately follows a conditional or an unconditional goto/jump instruction is a leader.

            List <Instruction> leaders = new List <Instruction>();

            leaders.Add(instr);
            bool afterTrailer = false;

            while (instr != null)
            {
                if (afterTrailer)
                {
                    if (!leaders.Contains(instr))
                    {
                        leaders.Add(instr);
                    }
                    afterTrailer = false;
                }

                CILOpCodes opcode   = (CILOpCodes)instr.OpCode.Value;
                bool       isBranch = opcode > CILOpCodes.Ret && opcode < CILOpCodes.Switch;
                if (isBranch)
                {
                    if (!leaders.Contains(instr.Operand as Instruction))
                    {
                        leaders.Add(instr.Operand as Instruction);
                    }
                }
                afterTrailer = isBranch || opcode == CILOpCodes.Ret;

                instr = instr.Next;
            }

            // Starting from a leader, the set of all following instructions until and not including the next leader is
            // the basic block corresponding to the starting leader.

            List <Instruction> trailers = new List <Instruction>();

            foreach (Instruction leader in leaders)
            {
                CILBB cilbb = new CILBB();
                cilbb.code.Add(leader);
                Instruction cur = leader.Next;
                while (cur != null && !leaders.Contains(cur))
                {
                    cilbb.code.Add(cur);
                    cur = cur.Next;
                }
                trailers.Add(cilbb.code.Last());
                cilbblist.Add(cilbb);
            }

            // Perform linking of CIL basic blocks.

            for (int i = 0; i < cilbblist.Count; i++)
            {
                Instruction trailer      = trailers[i];
                CILOpCodes  trailerCode  = (CILOpCodes)trailer.OpCode.Value;
                bool        uncondBranch = trailerCode == CILOpCodes.Br_S || trailerCode == CILOpCodes.Br;
                bool        condBranch   = !uncondBranch && trailerCode > CILOpCodes.Ret && trailerCode < CILOpCodes.Switch;
                if (condBranch)
                {
                    cilbblist[i].target    = cilbblist.Single(cilbb => cilbb.code.First().Offset == (trailer.Operand as Instruction).Offset);
                    cilbblist[i].successor = cilbblist.Single(cilbb => cilbb.code.First().Offset == trailer.Next.Offset);
                }
                else if (trailerCode != CILOpCodes.Ret)
                {
                    cilbblist[i].successor = uncondBranch ?
                                             cilbblist.Single(cilbb => cilbb.code.First().Offset == (trailer.Operand as Instruction).Offset) :
                                             ((trailer.Next == null) ? null : cilbblist.Single(cilbb => cilbb.code.First().Offset == trailer.Next.Offset));
                }
            }

            return(cilbblist[0]);
        }
Example #2
0
        // IL basic block will have a separate IR implementation for each stack type context.

        private static CILBBImplementation BuildIRCFG(CILBB cilbb,
                                                      Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> > stack,
                                                      Dictionary <CILBB, List <CILBBImplementation> > cilbbimpls,
                                                      IList <FormalParameter> parameters,
                                                      IList <VirtualRegister> variables,
                                                      bool result,
                                                      IList <SpecialRegister> srpool,
                                                      IDictionary <MethodInfo, Subprogram> spmap,
                                                      Func <Type, StateSpaces, InstructionSelector.DynamicRegister> regalloc)
        {
            if (cilbb == null)
            {
                if (stack.Count > 0)
                {
                    throw new InvalidProgramException("Evaluation stack must be empty at return moment.");
                }
                else
                {
                    return(null);
                }
            }
            else
            {
                List <CILBBImplementation> impls;
                if (!cilbbimpls.TryGetValue(cilbb, out impls))
                {
                    impls = new List <CILBBImplementation>();
                    cilbbimpls.Add(cilbb, impls);
                }

                CILBBImplementation impl = impls.Find(im => im.TypeContextEqual(stack));

                bool handleNext = false;

                if (impl != null)
                {
                    if (!impl.Implements(stack))
                    {
                        impl.Simulate(stack);
                        handleNext = true;
                    }
                }
                else
                {
                    impl = new CILBBImplementation(cilbb.code, stack, parameters, variables, result, srpool, spmap, regalloc);
                    impls.Add(impl);
                    handleNext = true;
                }

                if (handleNext)
                {
                    impl.Successor = BuildIRCFG(cilbb.successor,
                                                new Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> >(stack.Reverse()),
                                                cilbbimpls, parameters, variables, result, srpool, spmap, regalloc);
                    if (cilbb.target != null)
                    {
                        impl.Target = BuildIRCFG(cilbb.target,
                                                 new Stack <Tuple <Tuple <GenericOperand, bool>, InstructionSelector> >(stack.Reverse()),
                                                 cilbbimpls, parameters, variables, result, srpool, spmap, regalloc);
                    }
                }

                return(impl);
            }
        }