public virtual VerificationResult Mark(Label label) { // This is, effectively, "follows an unconditional branch & hasn't been seen before" if (MarkCreatesNewVerifier && UsesStrictBranchVerification && !ExpectedStacksAtLabels.ContainsKey(label)) { MustBeEmptyWhenBranchedTo.Add(label); } if (CurrentlyInScope.Count > 0) { StacksAtLabels[label] = GetCurrentStack(); var verify = CheckStackMatches(label); if (verify != null) { return(verify); } } if (MarkCreatesNewVerifier) { var newVerifier = new VerifiableTracker(label, baseless: true); Add(newVerifier, new LinqStack <LinqList <TypeOnStack> >()); MarkCreatesNewVerifier = false; } LinqList <VerifiableTracker> restore; if (RestoreOnMark.TryGetValue(label, out restore)) { // don't copy, we want the *exact* same verifiers restore here AddRange(restore, RestoreStacksOnMark[label]); RestoreOnMark.Remove(label); RestoreStacksOnMark.Remove(label); } var based = CurrentlyInScope.FirstOrDefault(f => !f.IsBaseless); based = based ?? CurrentlyInScope.First(); var fromLabel = new VerifiableTracker(label, based.IsBaseless, based); var fromStack = CurrentlyInScopeStacks[CurrentlyInScope.IndexOf(based)]; Add(fromLabel, CopyStack(fromStack)); if (!VerifyFromLabel.ContainsKey(label)) { VerifyFromLabel[label] = new LinqList <VerifiableTracker>(); } VerifyFromLabel[label].Add(fromLabel); RemoveUnnecessaryVerifiers(); return(VerificationResult.Successful()); }
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()); }
internal VerifiableTracker Concat(VerifiableTracker other) { var branchTo = BranchesAtTransitions.ContainsKey(other.BeganAt) ? BranchesAtTransitions[other.BeganAt] : Transitions.Count; var shouldTake = branchTo != Transitions.Count; var trans = new LinqList <InstructionAndTransitions>(branchTo + other.Transitions.Count); if (shouldTake) { for (var i = 0; i < branchTo; i++) { trans.Add(Transitions[i]); } } else { trans.AddRange(Transitions); } trans.AddRange(other.Transitions); var canReuseCache = branchTo == Transitions.Count && IsBaseless && CachedVerifyStack != null; var ret = new VerifiableTracker(BeganAt, IsBaseless) { StartingStack = new LinqStack <LinqList <TypeOnStack> >(StartingStack.Reverse().AsEnumerable()), Transitions = trans, CachedVerifyStack = canReuseCache ? new LinqStack <LinqList <TypeOnStack> >(CachedVerifyStack.Reverse().AsEnumerable()) : null, CachedVerifyIndex = canReuseCache ? CachedVerifyIndex : null }; return(ret); }
private VerificationResult CheckStackMatches(Label atLabel) { if (!StacksAtLabels.ContainsKey(atLabel) || !ExpectedStacksAtLabels.ContainsKey(atLabel)) { return(null); } var actual = StacksAtLabels[atLabel]; var expectations = ExpectedStacksAtLabels[atLabel]; foreach (var exp in expectations.AsEnumerable()) { var mismatch = CompareStacks(atLabel, actual, exp); if (mismatch != null) { return(mismatch); } } return(null); }