private int FindStackFailureIndex(LinqStack <LinqList <TypeOnStack> > types, IEnumerable <StackTransition> ops, out IEnumerable <TypeOnStack> expected) { var stillLegal = new LinqList <StackTransition>(ops); for (var i = 0; i < types.Count; i++) { var actuallyIs = types.ElementAt(i); var legal = stillLegal.Where(l => actuallyIs.Any(a => l.PoppedFromStack[i].IsAssignableFrom(a))).ToList(); if (legal.Count == 0) { expected = stillLegal.Select(l => l.PoppedFromStack[i]).Distinct().ToList().AsEnumerable(); return(i); } stillLegal = new LinqList <StackTransition>(legal); } throw new Exception("Shouldn't be possible"); }
public virtual VerificationResult ConditionalBranch(params Label[] toLabels) { foreach (var to in toLabels) { var intoVerified = VerifyBranchInto(to); if (intoVerified != null) { return(intoVerified); } UpdateRestores(to); if (!RestoreOnMark.ContainsKey(to)) { if (!RestoreOnMark.ContainsKey(to)) { RestoreOnMark[to] = new LinqList <VerifiableTracker>(); RestoreStacksOnMark[to] = new LinqList <LinqStack <LinqList <TypeOnStack> > >(); } RestoreOnMark[to].AddRange(CurrentlyInScope.Select(t => t.Clone())); RestoreStacksOnMark[to].AddRange(CurrentlyInScopeStacks.Select(s => CopyStack(s))); } if (!ExpectedStacksAtLabels.ContainsKey(to)) { ExpectedStacksAtLabels[to] = new LinqList <SigilTuple <bool, LinqStack <LinqList <TypeOnStack> > > >(); } ExpectedStacksAtLabels[to].Add(GetCurrentStack()); var verify = CheckStackMatches(to); if (verify != null) { return(verify); } } return(VerificationResult.Successful()); }
// Looks at CurrentlyInScope and removes any verifiers that are not necessary going forward private void RemoveUnnecessaryVerifiers() { // if anything's rooted, we only need one of them (since the IL stream being currently valid means they must in the future) var rooted = CurrentlyInScope.Where(c => !c.IsBaseless && c.CanBePruned).ToList(); if (rooted.Count >= 2) { for (var i = 1; i < rooted.Count; i++) { var toRemove = rooted[i]; var ix = CurrentlyInScope.IndexOf(toRemove); RemoveAt(ix); } } // remove any verifiers that have duplicate terminal stack states; we know that another verifier will do just as well, no need to verify the whole instruction stream again for (var i = CurrentlyInScope.Count - 1; i >= 0; i--) { var curStack = CurrentlyInScopeStacks[i]; var otherMatch = CurrentlyInScopeStacks .Select( (cx, ix) => { if (ix == i) { return(-1); } if (curStack.Count != cx.Count) { return(-1); } if (!CurrentlyInScope[ix].CanBePruned) { return(-1); } for (var j = 0; j < curStack.Count; j++) { var curFrame = curStack.ElementAt(j); var cxFrame = cx.ElementAt(j); if (curFrame.Count != cxFrame.Count) { return(-1); } curFrame = curFrame.OrderBy(_ => _).ToList(); cxFrame = cxFrame.OrderBy(_ => _).ToList(); for (var k = 0; k < curFrame.Count; k++) { var curT = curFrame[k]; var cxT = cxFrame[k]; if (curT != cxT) { return(-1); } } } return(ix); } ).Where(x => x != -1).OrderByDescending(_ => _).ToList(); foreach (var o in otherMatch.AsEnumerable()) { RemoveAt(o); if (o < i) { i--; } } } }