/// <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); }
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); } }