示例#1
0
            public SsaIdentifier ReadVariableRecursive(SsaBlockState bs)
            {
                SsaIdentifier val;

                if (bs.Block.Pred.Any(p => !blockstates[p].Visited))
                {
                    // Incomplete CFG
                    val = NewPhi(id, bs.Block);
                    outer.incompletePhis.Add(val);
                }
                else if (bs.Block.Pred.Count == 0)
                {
                    // Undef'ined or unreachable parameter; assume it's a def.
                    val = NewDefInstruction(id, bs.Block);
                }
                else if (bs.Block.Pred.Count == 1)
                {
                    // Search for the variable in the single predecessor.
                    val = ReadVariable(blockstates[bs.Block.Pred[0]]);
                }
                else
                {
                    // Break potential cycles with operandless phi
                    val = NewPhi(id, bs.Block);
                    WriteVariable(bs, val);
                    val = AddPhiOperands(val);
                }
                if (val != null)
                {
                    WriteVariable(bs, val);
                }
                return(val);
            }
示例#2
0
            /// <summary>
            /// Reaches "backwards" to locate the SSA identifier that defines
            /// the identifier <paramref name="id"/>, starting in block <paramref name="b"/>.
            /// </summary>
            /// If no definition of <paramref name="id"/> is found, a new
            /// DefStatement is created in the entry block of the procedure.
            /// </summary>
            /// <param name="bs"></param>
            /// <returns>The SSA name of the identifier that was read.</returns>
            public virtual SsaIdentifier ReadVariable(SsaBlockState bs)
            {
                trace.Verbose("ReadVariable {0} in block {1}", this.id, bs.Block.Name);
                if (bs.Terminates)
                {
                    // Reko has determined that this block diverges. We fall back to
                    // getting a variable from the entry block, which is guaranteed to
                    // dominate every other block in the procedure.
                    bs = outer.blockstates[bs.Block.Procedure.EntryBlock];
                }
                var sid = ReadBlockLocalVariable(bs);

                if (sid != null)
                {
                    return(sid);
                }
                // Keep probin'.
                // The commented-out code below is for assistance when troubleshooting
                // stack overflows in the code. These are always caused by the
                // CFG of the Procedure being malformed due to errors in the Scanning
                // phase. Once #726 is addressed, there should be no need for this
                // code.
                //if (++this.depth > 1000)
                //    throw new StackOverflowException("");
                sid = ReadVariableRecursive(bs);
                //--this.depth;
                return(sid !);
            }
示例#3
0
            /// <summary>
            /// Reaches "backwards" to locate the SSA identifier that defines
            /// the identifier <paramref name="id"/>, starting in block <paramref name="b"/>.
            /// </summary>
            /// If no definition of <paramref name="id"/> is found, a new
            /// DefStatement is created in the entry block of the procedure.
            /// </summary>
            /// <param name="bs"></param>
            /// <returns>The SSA name of the identifier that was read.</returns>
            public virtual SsaIdentifier ReadVariable(SsaBlockState bs)
            {
                if (bs.Terminates)
                {
                    // Reko has determined that this block diverges. We fall back to
                    // getting a variable from the entry block, which is guaranteed to
                    // dominate every other block in the procedure.
                    bs = outer.blockstates[bs.Block.Procedure.EntryBlock];
                }
                var sid = ReadBlockLocalVariable(bs);

                if (sid != null)
                {
                    return(sid);
                }
                // Keep probin'.
                return(ReadVariableRecursive(bs));
            }
示例#4
0
            private void ReplaceStackDefs(
                SsaBlockState bs,
                SsaIdentifier sidOld,
                SsaIdentifier sidNew)
            {
                if (!(sidOld.Identifier.Storage is StackStorage stack))
                {
                    return;
                }
                var offsetInterval = Interval.Create(
                    stack.StackOffset,
                    stack.StackOffset + sidOld.Identifier.DataType.Size);
                var ints = bs.currentStackDef
                           .GetIntervalsOverlappingWith(offsetInterval).ToArray();

                foreach (var de in ints)
                {
                    if (de.Value.SsaId == sidOld)
                    {
                        de.Value.SsaId = sidNew;
                    }
                }
            }
示例#5
0
            /// <summary>
            /// Registers the fact that identifier <paramref name="id"/> is
            /// modified in the block <paramref name="b" /> and generates a
            /// fresh SSA identifier.
            /// </summary>
            /// <param name="bs">The block in which the identifier was changed</param>
            /// <param name="sid">The identifier after being SSA transformed.</param>
            /// <returns>The new SSA identifier</returns>
            public override Identifier WriteVariable(SsaBlockState bs, SsaIdentifier sid)
            {
                DebugEx.Verbose(trace, "  WriteBlockLocalVariable: ({0}, {1}, ({2})", bs.Block.Name, id, this.liveBits);
                if (!bs.currentDef.TryGetValue(id.Storage.Domain, out var aliasState))
                {
                    aliasState = new AliasState();
                    bs.currentDef.Add(id.Storage.Domain, aliasState);
                }
                var stgDef   = id.Storage;
                var defRange = stgDef.GetBitRange();

                for (int i = 0; i < aliasState.Definitions.Count; ++i)
                {
                    var(sidPrev, prevRange, offset) = aliasState.Definitions[i];
                    var stgPrev = sidPrev.Identifier.Storage;
                    if (defRange.Covers(prevRange))
                    {
                        DebugEx.Verbose(trace, "     overwriting: {0}", sidPrev.Identifier);
                        aliasState.Definitions.RemoveAt(i);
                        --i;
                    }
                }
                aliasState.Definitions.Add((sid, defRange, this.Offset));
                DebugEx.Verbose(trace, "     writing: {0}", sid.Identifier);

                var newDict = aliasState.ExactAliases
                              .Where(kv => !kv.Key.OverlapsWith(id.Storage))
                              .ToDictionary(kv => kv.Key, kv => kv.Value);

                if (id.Storage == sid.Identifier.Storage)
                {
                    newDict[id.Storage] = sid;
                }
                aliasState.ExactAliases = newDict;
                return(sid.Identifier);
            }
示例#6
0
 /// <summary>
 /// If the `id` has an SsaIdentifier available (not necessarily
 /// defined) in this block, return that SsaIdentifier.
 /// </summary>
 /// <param name="bs">SsaBlockState we look in.</param>
 /// <returns>An SsaIdentifier if it is available,
 /// otherwise null.
 /// </returns>
 public abstract SsaIdentifier ReadBlockLocalVariable(SsaBlockState bs);
示例#7
0
 public abstract Identifier WriteVariable(SsaBlockState bs, SsaIdentifier sid);
示例#8
0
            public override SsaIdentifier ReadBlockLocalVariable(SsaBlockState bs)
            {
                DebugEx.Verbose(trace, "  ReadBlockLocalVariable: ({0}, {1}, ({2})", bs.Block.Name, id, this.liveBits);
                if (!bs.currentDef.TryGetValue(id.Storage.Domain, out var alias))
                {
                    return(null);
                }

                // Identifier id is defined locally in this block.
                // Has an exact alias already been calculated?
                if (alias.ExactAliases.TryGetValue(id.Storage, out var sid))
                {
                    DebugEx.Verbose(trace, "    found alias ({0}, {1})", bs.Block.Name, sid.Identifier.Name);
                    return(sid);
                }

                // At least some of the bits of 'id' are defined locally in this
                // block. Walk across the bits of 'id', collecting all parts
                // defined into a sequence.
                int offsetLo = this.liveBits.Lsb;
                int offsetHi = this.liveBits.Msb;
                var sids     = new List <(SsaIdentifier, BitRange)>();

                while (offsetLo < offsetHi)
                {
                    var useRange = new BitRange(offsetLo, offsetHi);
                    var(sidElem, usedRange, defRange) = FindIntersectingRegister(alias.Definitions, useRange);
                    if (sidElem == null || offsetLo < usedRange.Lsb)
                    {
                        // Found a gap in the register that wasn't defined in
                        // this basic block. Seek backwards
                        var bitrangeR = sidElem == null
                            ? useRange
                            : new BitRange(offsetLo, usedRange.Lsb);
                        var idR = MakeTmpIdentifier(sidElem, bitrangeR);
                        var rx  = new RegisterTransformer(idR, stm, this.outer)
                        {
                            liveBits = bitrangeR
                        };
                        var sidR = rx.ReadVariableRecursive(bs);
                        sids.Add((sidR, bitrangeR));
                        offsetLo = bitrangeR.Msb;
                    }
                    if (sidElem != null)
                    {
                        sids.Add((sidElem, defRange));
                        offsetLo = usedRange.Msb;
                    }
                }
                if (sids.Count == 1)
                {
                    var sidSlice = MakeSlice(sids[0].Item1, sids[0].Item2, this.id);
                    alias.ExactAliases[this.id.Storage] = sidSlice;
                    return(sidSlice);
                }
                else
                {
                    sids.Reverse(); // Order sids in big-endian order
                    var elems = new List <Expression>();
                    foreach (var(sidElem, bitrange) in sids)
                    {
                        var idSlice  = MakeTmpIdentifier(sidElem, bitrange);
                        var sidSlice = MakeSlice(sidElem, bitrange, idSlice);
                        alias.ExactAliases[sidSlice.OriginalIdentifier.Storage] = sidSlice;
                        elems.Add(sidSlice.Identifier);
                    }
                    var seq    = outer.m.Seq(elems.ToArray());
                    var assSeq = new AliasAssignment(id, seq);
                    var sidTo  = InsertBeforeStatement(bs.Block, this.stm, assSeq);
                    seq.Accept(new InstructionUseAdder(sidTo.DefStatement, ssaIds));
                    alias.ExactAliases[this.id.Storage] = sidTo;
                    return(sidTo);
                }
            }