Beispiel #1
0
            /// <summary>
            /// Inserts the statement <paramref name="ass"/> after the statement
            /// <paramref name="stmBefore"/>, skipping any AliasAssignments that
            /// statements that may have been added after
            /// <paramref name="stmBefore"/>.
            /// </summary>
            /// <param name="stmBefore"></param>
            /// <param name="ass"></param>
            /// <returns></returns>
            public SsaIdentifier InsertAfterDefinition(Statement stmBefore, AliasAssignment ass)
            {
                var b = stmBefore.Block;
                int i = b.Statements.IndexOf(stmBefore);

                // Skip alias statements
                while (i < b.Statements.Count - 1 && b.Statements[i + 1].Instruction is AliasAssignment)
                {
                    ++i;
                }
                var stm = new Statement(stmBefore.LinearAddress, ass, stmBefore.Block);

                stmBefore.Block.Statements.Insert(i + 1, stm);

                var sidTo = ssaIds.Add(ass.Dst, stm, ass.Src, false);

                ass.Dst = sidTo.Identifier;
                return(sidTo);
            }
Beispiel #2
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);
                }
            }