private static LinqDictionary <int, Local> GetInScopeAt(LinqList <Local> allLocals, int ix) { return (allLocals .Where( l => l.DeclaredAtIndex <= ix && (l.ReleasedAtIndex == null || l.ReleasedAtIndex > ix) ).ToDictionary(d => (int)d.Index, d => d)); }
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"); }
private ReturnTracerResult TraceFrom(int startAt, LinqList <Label> path, LinqHashSet <Label> pathLookup) { ReturnTracerResult cached; if (Cache.TryGetValue(startAt, out cached)) { return(cached); } var nextBranches = Branches.Where(b => b.Item3 >= startAt).GroupBy(g => g.Item3).OrderBy(x => x.Key).FirstOrDefault(); var orReturn = Returns.Where(ix => ix >= startAt && (nextBranches != null ? ix < nextBranches.Key : true)).Count(); var orThrow = Throws.Where(ix => ix >= startAt && (nextBranches != null ? ix < nextBranches.Key : true)).Count(); if (orReturn != 0) { Cache[startAt] = cached = ReturnTracerResult.Success(); return(cached); } if (orThrow != 0) { Cache[startAt] = cached = ReturnTracerResult.Success(); return(cached); } if (nextBranches == null) { Cache[startAt] = cached = ReturnTracerResult.Failure(path); return(cached); } var ret = new LinqList <ReturnTracerResult>(); foreach (var nextBranch in nextBranches) { if (pathLookup.Contains(nextBranch.Item2)) { Cache[startAt] = cached = ReturnTracerResult.Success(); ret.Add(cached); continue; } var branchOp = nextBranch.Item1; var branchTo = Marks[nextBranch.Item2]; var removeFromPathAt = path.Count; path.Add(nextBranch.Item2); pathLookup.Add(nextBranch.Item2); var fromFollowingBranch = TraceFrom(branchTo, path, pathLookup); path.RemoveAt(removeFromPathAt); pathLookup.Remove(nextBranch.Item2); if (IsUnconditionalBranch(branchOp)) { Cache[startAt] = cached = fromFollowingBranch; //return cached; ret.Add(cached); continue; } var fromFallingThrough = TraceFrom(startAt + 1, path, pathLookup); Cache[startAt] = cached = ReturnTracerResult.Combo(fromFallingThrough, fromFollowingBranch); ret.Add(cached); } Cache[startAt] = cached = ReturnTracerResult.Combo(ret.ToArray()); return(cached); }
// 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--; } } } }