public static LinqRoot <IGrouping <K, T> > GroupBy <T, K>(IEnumerable <T> e, SigilFunc <T, K> p) { if (e == null) { throw new ArgumentNullException("e"); } if (p == null) { throw new ArgumentNullException("p"); } var ret = new LinqList <IGrouping <K, T> >(); var gLookup = new Dictionary <K, Grouping <K, T> >(); using (var i = e.GetEnumerator()) { while (i.MoveNext()) { var k = p(i.Current); Grouping <K, T> g; if (!gLookup.TryGetValue(k, out g)) { gLookup[k] = g = new Grouping <K, T>(k); ret.Add(g); } g.Add(i.Current); } } return(ret); }
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); }
public ReturnTracer(LinqList <SigilTuple <OpCode, Label, int> > branches, LinqDictionary <Label, int> marks, LinqList <int> returns, LinqList <int> throws) { Branches = branches; Marks = marks; Returns = returns; Throws = throws; }
public static LinqList <T> ToList <T>(IEnumerable <T> e) { if (e == null) { throw new ArgumentNullException(); } LinqList <T> ret; var col = e as ICollection <T>; if (col != null) { ret = new LinqList <T>(col.Count); } else { ret = new LinqList <T>(); } using (var i = e.GetEnumerator()) { while (i.MoveNext()) { ret.Add(i.Current); } } return(ret); }
public LinqList <TypeOnStack>[] Peek(bool baseless, int n) { var stack = this; if (stack.Count < n && !baseless) { return(null); } var ret = new LinqList <TypeOnStack> [n]; int i; for (i = 0; i < n && i < stack.Count; i++) { ret[i] = stack.ElementAt(i) as LinqList <TypeOnStack>; } while (i < n) { ret[i] = _PeekWildcard; i++; } return(ret); }
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()); }
internal string[] Instructions(LinqList <Local> locals) { var ret = new List <string>(); var invoke = typeof(DelegateType).GetMethod("Invoke"); var returnType = invoke.ReturnType; var parameterTypes = LinqAlternative.Select(invoke.GetParameters(), s => s.ParameterType).ToArray(); var dynMethod = new DynamicMethod(Guid.NewGuid().ToString(), returnType, parameterTypes); var il = dynMethod.GetILGenerator(); var instrs = new StringBuilder(); for (var i = 0; i < Buffer.Count; i++) { var x = Buffer[i]; x(il, true, instrs); var line = instrs.ToString().TrimEnd(); if (line.StartsWith(OpCodes.Ldloc_0.ToString()) || line.StartsWith(OpCodes.Stloc_0.ToString())) { line += " // " + GetInScopeAt(locals, i)[0]; } if (line.StartsWith(OpCodes.Ldloc_1.ToString()) || line.StartsWith(OpCodes.Stloc_1.ToString())) { line += " // " + GetInScopeAt(locals, i)[1]; } if (line.StartsWith(OpCodes.Ldloc_2.ToString()) || line.StartsWith(OpCodes.Stloc_2.ToString())) { line += " // " + GetInScopeAt(locals, i)[2]; } if (line.StartsWith(OpCodes.Ldloc_3.ToString()) || line.StartsWith(OpCodes.Stloc_3.ToString())) { line += " // " + GetInScopeAt(locals, i)[3]; } if (line.StartsWith(OpCodes.Ldloc_S.ToString()) || line.StartsWith(OpCodes.Stloc_S.ToString())) { line += " // " + ExtractLocal(line, locals, i); } ret.Add(line); instrs.Length = 0; } return(ret.ToArray()); }
public static ReturnTracerResult Failure(LinqList <Label> path) { return (new ReturnTracerResult { IsSuccess = false, FailingPaths = (LinqArray <LinqRoot <Label> >) new [] { path.ToList() } }); }
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 static Local ExtractLocal(string from, LinqList <Local> locals, int ix) { var match = _ExtractLocal.Match(from); var locId = match.Groups["locId"].Value; var lid = int.Parse(locId); return(GetInScopeAt(locals, ix)[lid]); }
private void AddRange(LinqList <VerifiableTracker> trackers, LinqList <LinqStack <LinqList <TypeOnStack> > > stacks) { if (trackers.Count != stacks.Count) { throw new Exception(); } for (var i = 0; i < trackers.Count; i++) { Add(trackers[i], stacks[i]); } }
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()); }
public static VerificationResult FailureTypeMismatch(Label involving, LinqList <TypeOnStack> expected, LinqList <TypeOnStack> actual) { return (new VerificationResult { Success = false, IsTypeMismatch = true, ExpectedOnStack = expected, ActuallyOnStack = actual }); }
public ReturnTracerResult Verify() { var firstLabel = Marks.OrderBy(o => o.Value).First().Key; var firstIx = Marks[firstLabel]; var path = new LinqList <Label>(); path.Add(firstLabel); var pathLookup = new LinqHashSet <Label>(path.AsEnumerable()); return(TraceFrom(firstIx, path, pathLookup)); }
public void EmitCall(OpCode op, MethodInfo method, IEnumerable <Type> parameterTypes, Type[] arglist) { InstructionSizes.Add(() => InstructionSize.Get(op)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.EmitCall(op, method, arglist); } var mtdString = method is MethodBuilder ? method.Name : method.ToString(); log.AppendLine(op + " " + mtdString + " __arglist(" + Join(", ", arglist) + ")"); } ); var parameters = new LinqList <Type>(parameterTypes); if (!method.IsStatic) { var declaring = method.DeclaringType; if (TypeHelpers.IsValueType(declaring)) { declaring = declaring.MakePointerType(); } parameters.Insert(0, declaring); } parameters.AddRange(arglist); var paras = new List <object> { method }; paras.AddRange(arglist); TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = op, MethodReturnType = method.ReturnType, MethodParameterTypes = parameters }); Operations.Add(new Operation <DelegateType> { OpCode = op, Parameters = paras.ToArray() }); }
private static LinqList <Type> GetBases(Type t) { if (t.IsValueType) { return(new LinqList <Type>()); } var ret = new LinqList <Type>(); t = t.BaseType; while (t != null) { ret.Add(t); t = t.BaseType; } return(ret); }
private static LinqList <Type> GetBases(Type t) { if (TypeHelpers.IsValueType(t)) { return(new LinqList <Type>()); } var ret = new LinqList <Type>(); t = TypeHelpers.GetBaseType(t); while (t != null) { ret.Add(t); t = TypeHelpers.GetBaseType(t); } return(ret); }
public void Emit(OpCode op, MethodInfo method, IEnumerable <Type> parameterTypes) { InstructionSizes.Add(() => InstructionSize.Get(op)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.Emit(op, method); } var mtdString = method is MethodBuilder ? method.Name : method.ToString(); log.AppendLine(op + " " + mtdString); } ); var parameters = new LinqList <Type>(parameterTypes); if (!method.IsStatic) { var declaring = method.DeclaringType; if (declaring.IsValueType) { declaring = declaring.MakePointerType(); } parameters.Insert(0, declaring); } TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = op, MethodReturnType = method.ReturnType, MethodParameterTypes = parameters }); Operations.Add(new Operation <DelegateType> { OpCode = op, Parameters = new object[] { method } }); }
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 void Emit(OpCode op, ConstructorInfo cons, IEnumerable <Type> parameterTypes) { InstructionSizes.Add(() => InstructionSize.Get(op)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.Emit(op, cons); } var mtdString = cons is ConstructorBuilder ? cons.Name : cons.ToString(); log.AppendLine(op + " " + mtdString); } ); var parameters = new LinqList <Type>(parameterTypes); var declaring = cons.DeclaringType; if (TypeHelpers.IsValueType(declaring)) { declaring = declaring.MakePointerType(); } parameters.Insert(0, declaring); TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = op, MethodReturnType = typeof(void), MethodParameterTypes = parameters }); Operations.Add(new Operation <DelegateType> { OpCode = op, Parameters = new object[] { cons } }); }
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()); }
public void EmitCalli(CallingConventions callingConvention, Type returnType, Type[] parameterTypes, Type[] arglist) { InstructionSizes.Add(() => InstructionSize.Get(OpCodes.Calli)); LengthCache.Clear(); Buffer.Add( (il, logOnly, log) => { if (!logOnly) { il.EmitCalli(OpCodes.Calli, callingConvention, returnType, parameterTypes, arglist); } log.AppendLine(OpCodes.Calli + " " + callingConvention + " " + returnType + " " + Join(" ", (IEnumerable <Type>)parameterTypes) + " __arglist(" + Join(", ", arglist) + ")"); } ); var ps = new LinqList <Type>(parameterTypes); ps.AddRange(arglist); TraversableBuffer.Add(new BufferedILInstruction { IsInstruction = OpCodes.Calli, MethodReturnType = returnType, MethodParameterTypes = ps }); var paras = new List <object>() { callingConvention, returnType }; paras.AddRange(parameterTypes); paras.AddRange(arglist); Operations.Add(new Operation <DelegateType> { OpCode = OpCodes.Calli, Parameters = paras.ToArray() }); }
public virtual VerificationResult Transition(InstructionAndTransitions legalTransitions) { var stacks = new LinqList <LinqStack <LinqList <TypeOnStack> > >(); VerificationResult last = null; foreach (var x in CurrentlyInScope.AsEnumerable()) { var inner = x.Transition(legalTransitions); if (!inner.Success) { return(inner); } last = inner; stacks.Add(CopyStack(inner.Stack)); } CurrentlyInScopeStacks = stacks; return(last); }
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); } }
private LinqList <StackTransition> GetLegalTransitions(LinqList <StackTransition> ops, LinqStack <LinqList <TypeOnStack> > runningStack) { var ret = new LinqList <StackTransition>(ops.Count); for (var i = 0; i < ops.Count; i++) { var w = ops[i]; if (LinqAlternative.All(w.PoppedFromStack, u => u == TypeOnStack.Get <PopAllType>())) { ret.Add(w); continue; } var onStack = runningStack.Peek(IsBaseless, w.PoppedCount); if (onStack == null) { continue; } if (LinqAlternative.Any(w.PushedToStack, p => p == TypeOnStack.Get <SamePointerType>())) { if (w.PushedToStack.Length > 1) { throw new Exception("SamePointerType can be only product of a transition which contains it"); } var shouldBePointer = LinqAlternative.SelectMany(onStack, p => p.Where(x => x.IsPointer || x == TypeOnStack.Get <WildcardType>()).AsEnumerable()).Distinct().ToList(); if (shouldBePointer.Count == 0) { continue; } w = new StackTransition(w.PoppedFromStack, new [] { shouldBePointer.Single() }); } if (LinqAlternative.Any(w.PushedToStack, p => p == TypeOnStack.Get <SameByRefType>())) { if (w.PushedToStack.Length > 1) { throw new Exception("SameByRefType can be only product of a transition which contains it"); } var shouldBeByRef = LinqAlternative.SelectMany(onStack, p => p.Where(x => x.IsReference || x == TypeOnStack.Get <WildcardType>()).AsEnumerable()).Distinct().ToList(); if (shouldBeByRef.Count == 0) { continue; } w = new StackTransition(w.PoppedFromStack, new[] { shouldBeByRef.Single() }); } bool outerContinue = false; for (var j = 0; j < w.PoppedCount; j++) { var shouldBe = w.PoppedFromStack[j]; var actuallyIs = onStack[j]; if (!actuallyIs.Any(a => shouldBe.IsAssignableFrom(a))) { outerContinue = true; break; } } if (outerContinue) { continue; } ret.Add(w); } return(ret); }
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); }
public InstructionAndTransitions(OpCode?instr, int?ix, LinqList <StackTransition> trans) { Instruction = instr; Transitions = trans; InstructionIndex = ix; }
private void EmptyCurrentScope() { CurrentlyInScope = new LinqList <VerifiableTracker>(); CurrentlyInScopeStacks = new LinqList <LinqStack <LinqList <TypeOnStack> > >(); }