public virtual VerificationResult UnconditionalBranch(Label to) { // If we've recorded elsewhere that the label we're branching to *must* receive // an empty stack, then inject a transition that expects that if (MustBeEmptyWhenBranchedTo.Contains(to)) { var trans = new LinqList <StackTransition>(); trans.Add(new StackTransition(sizeMustBe: 0)); var stackIsEmpty = Transition(new InstructionAndTransitions(null, null, trans)); if (stackIsEmpty != null) { return(stackIsEmpty); } } var intoVerified = VerifyBranchInto(to); if (intoVerified != null) { return(intoVerified); } UpdateRestores(to); if (!RestoreOnMark.ContainsKey(to)) { RestoreOnMark[to] = new LinqList <VerifiableTracker>(); RestoreStacksOnMark[to] = new LinqList <LinqStack <LinqList <TypeOnStack> > >(); } 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); } RestoreOnMark[to].AddRange(CurrentlyInScope); RestoreStacksOnMark[to].AddRange(CurrentlyInScopeStacks); EmptyCurrentScope(); MarkCreatesNewVerifier = true; return(VerificationResult.Successful()); }
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); }
private static void UpdateStack(LinqStack <LinqList <TypeOnStack> > stack, InstructionAndTransitions wrapped, bool isBaseless) { var legal = wrapped.Transitions; var instr = wrapped.Instruction; var legalSize = 0; legal.Each( t => { legalSize += t.PushedToStack.Length; if (t.Before != null) { t.Before(stack, isBaseless); } } ); if (legal.Any(l => LinqAlternative.Any(l.PoppedFromStack, u => u == TypeOnStack.Get <PopAllType>()))) { if (instr.HasValue) { for (var i = 0; i < stack.Count; i++) { var ix = stack.Count - i - 1; stack.ElementAt(i).Each(y => y.Mark(wrapped, ix)); } } stack.Clear(); } else { var toPop = legal.First().PoppedCount; for (var j = 0; j < toPop && stack.Count > 0; j++) { var popped = stack.Pop(); if (instr.HasValue) { var ix = toPop - j - 1; popped.Each(y => y.Mark(wrapped, ix)); } } } var toPush = new LinqList <TypeOnStack>(legalSize); var pushed = new LinqHashSet <TypeOnStack>(); for (var i = 0; i < legal.Count; i++) { foreach (var p in legal[i].PushedToStack) { if (pushed.Contains(p)) { continue; } toPush.Add(p); pushed.Add(p); } } if (toPush.Count > 0) { stack.Push(toPush); } }