/// <summary>
        /// Lays out all parameters of the method.
        /// </summary>
        private void LayoutParameters()
        {
            var parameters = new List <Operand>();

            int offset = 0;

            if (MethodCompiler.Method.HasThis || MethodCompiler.Method.HasExplicitThis)
            {
                ++offset;
            }

            for (int i = 0; i < MethodCompiler.Method.Signature.Parameters.Count + offset; ++i)
            {
                var parameter = MethodCompiler.GetParameterOperand(i);

                parameters.Add(parameter);
            }

            int returnSize = 0;

            if (TypeLayout.IsCompoundType(MethodCompiler.Method.Signature.ReturnType))
            {
                returnSize = TypeLayout.GetTypeSize(MethodCompiler.Method.Signature.ReturnType);
            }

            int size = LayoutVariables(parameters, CallingConvention, CallingConvention.OffsetOfFirstParameter + returnSize, false);

            MethodCompiler.StackLayout.StackParameterSize = size;
            MethodCompiler.TypeLayout.SetMethodParameterStackSize(MethodCompiler.Method, size);
        }
Beispiel #2
0
        /// <summary>
        /// Adds PHI functions for all ref/out parameters of the method being compiled.
        /// </summary>
        private void AddPhiFunctionsForOutParameters()
        {
            Dictionary <StackOperand, StackOperand> liveIn = null;

            // Retrieve the well known epilogue block
            BasicBlock epilogue = FindBlock(Int32.MaxValue);

            Debug.Assert(epilogue != null, "Method doesn't have epilogue block?");

            Context ctxEpilogue = new Context(InstructionSet, epilogue);

            ctxEpilogue.GotoLast();

            // Iterate all parameter definitions
            foreach (RuntimeParameter rp in MethodCompiler.Method.Parameters)
            {
                // Retrieve the stack operand for the parameter
                StackOperand paramOp = (StackOperand)MethodCompiler.GetParameterOperand(rp.Position - 1);

                // Only add a PHI if the runtime parameter is out or ref...
                if (rp.IsOut || (paramOp.Type is RefSigType || paramOp.Type is PtrSigType))
                {
                    ctxEpilogue.AppendInstruction(IR.Instruction.PhiInstruction, paramOp);

                    if (liveIn == null)
                    {
                        liveIn = new Dictionary <StackOperand, StackOperand> ();
                    }

                    liveIn.Add(paramOp, paramOp);
                }
            }

            // Save the in versions to force a merge later
            if (liveIn != null)
            {
                _liveness[epilogue.Sequence] = liveIn;
            }
        }
Beispiel #3
0
        /// <summary>
        /// Performs stage specific processing on the compiler context.
        /// </summary>
        public void Run()
        {
            _dominanceProvider = (IDominanceProvider)MethodCompiler.GetPreviousStage(typeof(IDominanceProvider));
            Debug.Assert(_dominanceProvider != null, "SSA Conversion requires a dominance provider.");
            if (_dominanceProvider == null)
            {
                throw new InvalidOperationException("SSA Conversion requires a dominance provider.");
            }

            // Allocate space for live outs
            _liveness = new IDictionary <StackOperand, StackOperand> [BasicBlocks.Count];
            // Retrieve the dominance frontier Blocks
            _dominanceFrontierBlocks = _dominanceProvider.GetDominanceFrontier();

            // Add ref/out parameters to the epilogue block to have uses there...
            AddPhiFunctionsForOutParameters();

            // Transformation worklist
            Queue <WorkItem> workList = new Queue <WorkItem> ();

            /* Move parameter operands into the dictionary as version 0,
             * because they are live at entry and maybe referenced. Anyways, an
             * assignment to a parameter is also SSA related.
             */
            IDictionary <StackOperand, StackOperand> liveIn = new Dictionary <StackOperand, StackOperand> (s_comparer);
            int i = 0;

            if (MethodCompiler.Method.Signature.HasThis)
            {
                StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(0);
                liveIn.Add(param, param);
                i++;
            }
            for (int j = 0; j < MethodCompiler.Method.Parameters.Count; j++)
            {
                StackOperand param = (StackOperand)MethodCompiler.GetParameterOperand(i + j);
                liveIn.Add(param, param);
            }

            // Start with the very first block
            workList.Enqueue(new WorkItem(BasicBlocks[0], null, liveIn));

            // Iterate until the worklist is empty
            while (workList.Count != 0)
            {
                // Remove the block From the queue
                WorkItem workItem = workList.Dequeue();

                // Transform the block
                BasicBlock block    = workItem.block;
                bool       schedule = TransformToSsaForm(new Context(InstructionSet, block), workItem.caller, workItem.liveIn, out liveIn);
                _liveness[block.Sequence] = liveIn;

                if (schedule)
                {
                    // Add all branch targets to the work list
                    foreach (BasicBlock next in block.NextBlocks)
                    {
                        // Only follow backward branches, if we've redefined a variable
                        // this may force us to reinsert a PHI function in a block we
                        // already have completed processing on.
                        workList.Enqueue(new WorkItem(next, block, liveIn));
                    }
                }
            }
        }