Example #1
0
        private bool RemapParameterToLoadStack(APC pc, ref Parameter param, out bool isLoadResult, out int loadStackOffset, out bool isOld, out APC lookupPC)
        {
            if (pc.SubroutineContext == null)
            {
                isLoadResult    = false;
                loadStackOffset = 0;
                isOld           = false;
                lookupPC        = pc;
                return(false);
            }

            if (pc.Block.Subroutine.IsRequires)
            {
                isLoadResult = false;
                isOld        = false;
                lookupPC     = pc;
                for (LispList <Edge <CFGBlock, EdgeTag> > list = pc.SubroutineContext; list != null; list = list.Tail)
                {
                    EdgeTag edgeTag = list.Head.Tag;
                    if (edgeTag == EdgeTag.Entry)
                    {
                        param           = RemapParameter(param, list.Head.From, pc.Block);
                        loadStackOffset = 0;
                        return(false);
                    }
                    if (edgeTag.Is(EdgeTag.BeforeMask))
                    {
                        int stackDepth = this.parent.LocalStackDepth(pc);
                        loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex(param) + stackDepth;
                        return(true);
                    }
                }
                throw new InvalidOperationException();
            }

            if (pc.Block.Subroutine.IsEnsuresOrOldValue)
            {
                isOld = true;
                for (LispList <Edge <CFGBlock, EdgeTag> > ctx = pc.SubroutineContext; ctx != null; ctx = ctx.Tail)
                {
                    EdgeTag tag = ctx.Head.Tag;
                    if (tag == EdgeTag.Exit)
                    {
                        param           = RemapParameter(param, ctx.Head.From, pc.Block);
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        lookupPC        = pc;
                        return(false);
                    }

                    if (tag == EdgeTag.AfterCall)
                    {
                        loadStackOffset = this.parent.MetaDataProvider.ParameterStackIndex(param);
                        isLoadResult    = false;
                        lookupPC        = new APC(ctx.Head.From, 0, ctx.Tail);
                        return(true);
                    }

                    if (tag == EdgeTag.AfterNewObj)
                    {
                        if (this.parent.MetaDataProvider.ParameterIndex(param) == 0)
                        {
                            loadStackOffset = this.parent.LocalStackDepth(pc);
                            isLoadResult    = true;
                            lookupPC        = pc;
                            isOld           = false;
                            return(false);
                        }

                        loadStackOffset = this.parent.MetaDataProvider.ParameterIndex(param);
                        isLoadResult    = false;
                        lookupPC        = new APC(ctx.Head.From, 0, ctx.Tail);
                        return(true);
                    }
                    if (tag == EdgeTag.OldManifest)
                    {
                        param           = RemapParameter(param, ctx.Tail.Head.From, pc.Block);
                        isOld           = false;
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        lookupPC        = pc;
                        return(false);
                    }
                }
                throw new InvalidOperationException();
            }

            if (pc.Block.Subroutine.IsInvariant)
            {
                for (LispList <Edge <CFGBlock, EdgeTag> > list = pc.SubroutineContext; list != null; list = list.Tail)
                {
                    EdgeTag tag = list.Head.Tag;
                    if (tag == EdgeTag.Entry || tag == EdgeTag.Exit)
                    {
                        Method method;
                        if (pc.TryGetContainingMethod(out method))
                        {
                            param           = this.parent.MetaDataProvider.This(method);
                            isLoadResult    = false;
                            loadStackOffset = 0;
                            isOld           = tag == EdgeTag.Exit;
                            lookupPC        = pc;
                            return(false);
                        }
                        isLoadResult    = false;
                        loadStackOffset = 0;
                        isOld           = false;
                        lookupPC        = pc;
                        return(false);
                    }
                    if (tag == EdgeTag.AfterCall)
                    {
                        Method calledMethod;
                        bool   isNewObj;
                        bool   isVirtual;
                        list.Head.From.IsMethodCallBlock(out calledMethod, out isNewObj, out isVirtual);
                        int count = this.parent.MetaDataProvider.Parameters(calledMethod).Count;
                        loadStackOffset = count;
                        isLoadResult    = false;
                        isOld           = true;
                        lookupPC        = new APC(list.Head.From, 0, list.Tail);
                        return(true);
                    }
                    if (tag == EdgeTag.AfterNewObj)
                    {
                        isLoadResult    = true;
                        loadStackOffset = this.parent.LocalStackDepth(pc);
                        isOld           = false;
                        lookupPC        = pc;
                        return(false);
                    }
                    if (tag.Is(EdgeTag.BeforeMask))
                    {
                        throw new InvalidOperationException("this should never happen");
                    }
                }
                throw new InvalidOperationException("this should never happen");
            }

            isLoadResult    = false;
            loadStackOffset = 0;
            isOld           = false;
            lookupPC        = pc;
            return(false);
        }