예제 #1
0
        /// <summary>
        /// Having identified the return variable -- if any -- rewrite all
        /// return statements to return that variable.
        /// </summary>
        /// <param name="ssa"></param>
        public void RewriteReturns(SsaState ssa)
        {
            // For each basic block reaching the exit block, get all reaching
            // definitions and then either replace the return expression or
            // inject out variable assignments as Stores.

            var reachingBlocks = ssa.PredecessorPhiIdentifiers(ssa.Procedure.ExitBlock);
            var sig            = ssa.Procedure.Signature;

            foreach (var reachingBlock in reachingBlocks)
            {
                var block = reachingBlock.Key;
                var idRet = sig.ReturnValue;
                if (idRet != null && !(idRet.DataType is VoidType))
                {
                    var idStg = reachingBlock.Value
                                .Where(cb => cb.Storage.Covers(idRet.Storage))
                                .FirstOrDefault();
                    SetReturnExpression(ssa, block, idRet, idStg);
                }
                int insertPos = block.Statements.FindIndex(s => s.Instruction is ReturnInstruction);
                Debug.Assert(insertPos >= 0);
                foreach (var p in sig.Parameters.Where(p => p.Storage is OutArgumentStorage))
                {
                    var outStg = (OutArgumentStorage)p.Storage;
                    var idStg  = reachingBlock.Value
                                 .Where(cb => cb.Storage == outStg.OriginalIdentifier.Storage)
                                 .FirstOrDefault();
                    InsertOutArgumentAssignment(
                        ssa,
                        p,
                        idStg?.Expression ?? Constant.Invalid,
                        block,
                        insertPos);
                    ++insertPos;
                }
            }
        }