internal override void Walk() { CCTypeSet cts = Stack.Peek(0); Stack.Peek(1).CheckInt(); CCTypeSet mv = null; foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCTypeSet sv = new CCTypeSet(tos.GetEmbedded(eltType)); if (mv == null) { mv = sv; } else { mv = CCTypeSet.Merge(mv, sv); } } if (mv != null) { next.MergeStack(Stack.Pop(2).Push(mv)); } }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); Stack.Peek(1).CheckInt(); CCTypeSet mv = null; foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCType tos2 = tos.GetEmbedded( owner.GetArrayElementType()); CCTypeSet vt = new CCTypeSet(tos2); if (vt != null) { if (mv == null) { mv = vt; } else { mv = CCTypeSet.Merge(mv, vt); } } } if (mv != null) { next.MergeStack(Stack.Pop(2).Push(mv)); } }
public override bool Equals(object other) { if (object.ReferenceEquals(this, other)) { return(true); } CCTypeSet ss = other as CCTypeSet; if (ss == null) { return(false); } if (GetHashCode() != ss.GetHashCode()) { return(false); } int n = types.Count; if (n != ss.types.Count) { return(false); } SortedSet <CCType> .Enumerator e = ss.types.GetEnumerator(); foreach (CCType t in types) { if (!e.MoveNext() || !t.Equals(e.Current)) { return(false); } } return(true); }
internal override void Walk() { CCTypeSet cts1 = Stack.Peek(1); CCTypeSet cts2 = Stack.Peek(0); next.MergeStack(Stack.Pop(2).Push(cts2).Push(cts1)); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); Stack.Peek(1).CheckInt(); CCTypeSet mv = null; foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCType tos2 = tos.GetEmbedded(owner); CCStruct cs = CCStruct.Lookup(tos2); CCTypeSet vt = cs.Get(owner.fieldInverseMapping[off]); if (vt != null) { if (mv == null) { mv = vt; } else { mv = CCTypeSet.Merge(mv, vt); } } } if (mv != null) { next.MergeStack(Stack.Pop(2).Push(mv)); } }
internal CCTypeSet Get(int index) { CCTypeSet cts = locals[index]; if (cts.MayBeNull) { throw new Exception("potentially reading uninitialized local variable"); } return(cts); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); } next.MergeStack(Stack.Pop().Push(CCTypeSet.BOOL)); }
/* * Merge two type sets into an aggregate set. If one of the sets * is a subset of the other, then that other subset is returned; * if the two sets are equal, then the ss1 instance is returned. * * This method traps on any attempt at merging incompatible type * sets (ones with basic types). */ internal static CCTypeSet Merge(CCTypeSet ss1, CCTypeSet ss2) { string err; CCTypeSet cts = MergeNF(ss1, ss2, out err); if (cts == null) { throw new Exception(err); } return(cts); }
internal void DoPutLocal(int num, XType ltype) { int index = cfi.fi.fieldInverseMapping[num]; CCTypeSet cts = Stack.Peek(0); if (ltype != null) { cts.CheckSubTypeOf(ltype); } PropagateNext(Stack.Pop(), Locals.Set(index, cts)); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); Stack.Peek(1).CheckInt(); Stack.Peek(2).CheckInt(); foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); } next.MergeStack(Stack.Pop(3)); }
internal CCTypeSet[] GetTopElements(int depth) { CCTypeSet[] ctss = new CCTypeSet[depth]; StackElt e = tos; for (int j = 0; j < depth; j++) { ctss[depth - 1 - j] = e.cts; e = e.upper; } return(ctss); }
internal void DoPutLocalIndexed(int off, int len, XType ltype) { int index = cfi.fi.fieldInverseMapping[off]; Stack.Peek(0).CheckInt(); CCTypeSet cts = Stack.Peek(1); if (ltype != null) { cts.CheckSubTypeOf(ltype); } PropagateNext(Stack.Pop().Pop(), Locals.Set(index, cts)); }
internal StackElt(StackElt upper, CCTypeSet cts) { this.upper = upper; this.cts = cts; if (upper == null) { rank = 0; } else { rank = upper.rank + 1; } }
internal FunctionNative(string debugName, XType[] tParams, XType[] tRets) : base(debugName) { this.tParams = tParams; int n = tRets.Length; ctsRets = new CCTypeSet[n]; for (int i = 0; i < n; i++) { ctsRets[i] = new CCTypeSet(new CCType(tRets[i])); } }
/* * Merge two type sets into an aggregate set. If one of the sets * is a subset of the other, then that other subset is returned; * if the two sets are equal, then the ss1 instance is returned. * * If merging is not possible (incompatible basic types), then * null is returned, and err is set to an appropriate error * message. Otherwise, the merged type is returned, and err is * set to null. */ internal static CCTypeSet MergeNF(CCTypeSet ss1, CCTypeSet ss2, out string err) { err = null; if (ss2.IsSubsetOf(ss1)) { return(ss1); } if (ss1.IsSubsetOf(ss2)) { return(ss2); } /* * Handling of restricted types relies on the following * features: * * - A CCTypeSet that contains a restricted type can * only contain that restricted type, none other. * * - Restricted types cannot have allocation nodes, * variants, or be std::type. * * - The tests with IsSubsetOf() above have already * ruled out the case of two identical restricted types. */ if (ss1.types.Count == 1 && ss2.types.Count == 1) { CCType ct1 = ss1.types.Min; CCType ct2 = ss2.types.Min; if (ct1.xType.IsRestricted || ct2.xType.IsRestricted) { err = string.Format("forbidden type merging between {0} and {1}", ct1, ct2); return(null); } } CCTypeSet ss3 = new CCTypeSet(); foreach (CCType t in ss1.types) { ss3.types.Add(t); ss3.xTypes.Add(t.xType); } foreach (CCType t in ss2.types) { ss3.types.Add(t); ss3.xTypes.Add(t.xType); } return(ss3); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); CCTypeSet sv = Stack.Peek(1); foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCType tos2 = tos.GetEmbedded(owner); CCStruct cs = CCStruct.Lookup(tos2); cs.Merge(owner.fieldInverseMapping[off], sv); } next.MergeStack(Stack.Pop(2)); }
internal void DoJumpIf(int disp) { /* * Check that the top stack element is std::bool. * Remove it for the successor opcodes. */ CCTypeSet cts = Stack.Peek(0); cts.CheckBool(); CCStack nstack = Stack.Pop(); PropagateNext(nstack); PropagateBranch(disp, nstack); }
internal CCLocals Set(int index, CCTypeSet cts) { CCTypeSet octs = locals[index]; if (!cts.IsSubsetOf(octs)) { CCLocals r = new CCLocals(locals.Length); Array.Copy(locals, 0, r.locals, 0, locals.Length); r.locals[index] = cts; return(r); } else { return(this); } }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); Stack.Peek(1).CheckInt(); CCTypeSet sv = Stack.Peek(2); foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCType tos2 = tos.GetEmbedded(owner); CCStruct cs = CCStruct.Lookup(tos2); cs.Merge(0, sv); } next.MergeStack(Stack.Pop(3)); }
CCStruct(CCType owner) { owner.xType.Close(); this.owner = owner; XType[] fti = owner.xType.GetFieldInitTypes(); int size = fti.Length; fields = new CCTypeSet[size]; regNodes = new SortedSet <CCNode> [size]; for (int i = 0; i < fti.Length; i++) { if (fti[i] == null) { continue; } fields[i] = new CCTypeSet(new CCType(fti[i])); } }
internal void Merge(int index, CCTypeSet cts) { /* * Escape analysis: we must not write in a field of * a structure a value that pertains to a descendent * allocator node. */ CCNodeEntry oa = owner.allocationNode; if (oa != null) { foreach (CCType ct in cts) { if (oa.IsDescendentOf(ct.allocationNode)) { continue; } throw new Exception(string.Format("reference to local instance of type {0} may escape through writing in field of type {1}", ct, owner)); } } CCTypeSet octs = fields[index]; CCTypeSet ncts; if (octs == null) { ncts = cts; } else { ncts = CCTypeSet.Merge(octs, cts); } if (!object.ReferenceEquals(octs, ncts)) { SortedSet <CCNode> rn = regNodes[index]; if (rn != null) { foreach (CCNode node in rn) { node.MarkUpdate(); } } } }
internal bool IsSubsetOf(CCTypeSet ss) { if (object.ReferenceEquals(this, ss)) { return(true); } if (types.Count > ss.types.Count) { return(false); } foreach (CCType t in types) { if (!ss.types.Contains(t)) { return(false); } } return(true); }
internal override void Walk() { /* * For all possible types of the TOS: * * 1. Verify that the accessor is usable on that type. * * 2. Obtain the right CCStruct, and get the types * that may be thus obtained. The "right CCStruct" * is the one for the CCType that matches the * element type, and the allocation node and variant * of the type found on the stack. * * 3. Merge all resulting types. */ CCTypeSet cts = Stack.Peek(0); CCTypeSet mv = null; foreach (CCType tos in cts) { tos.xType.CheckExtends(owner); CCType tos2 = tos.GetEmbedded(owner); CCStruct cs = CCStruct.Lookup(tos2); CCTypeSet vt = cs.Get(owner.fieldInverseMapping[off]); if (vt != null) { if (mv == null) { mv = vt; } else { mv = CCTypeSet.Merge(mv, vt); } } } if (mv != null) { next.MergeStack(Stack.Pop().Push(mv)); } }
/* * Check that all values in this set are for std::type with * a specific type target (i.e. "types of types"). */ internal CCTypeSet ToNewInstance() { CCTypeSet r = new CCTypeSet(); foreach (CCType ct in types) { if (ct.xType != XType.XTYPE) { throw new Exception(string.Format("instance allocation expects a std::type instance, got {0} instead", ct.xType.Name)); } if (ct.ofType == null) { throw new Exception("instance allocation needs a specific type target, but got a generic std::type"); } if (ct.ofType == XType.XTYPE) { throw new Exception("cannot dynamically allocate new std::type instances"); } r.types.Add(new CCType(ct.ofType, null, 0, false)); r.xTypes.Add(ct.ofType); } return(r); }
internal static CCStack Merge(CCStack s1, CCStack s2) { if (object.ReferenceEquals(s1, s2)) { return(s1); } int n1 = s1.Depth; int n2 = s2.Depth; if (n1 != n2) { throw new Exception(string.Format("stack merge depth mismatch ({0} / {1})", n1, n2)); } /* * Find the common root (it may be null). We retain in * 'root' the topmost element at which the two stacks have * equal contents. */ StackElt e1 = s1.tos, e2 = s2.tos; StackElt root = null; for (;;) { /* * When we have reached the same StackElt instance, * no further divergence may occur. */ if (object.ReferenceEquals(e1, e2)) { if (root == null) { root = e1; } break; } if (e1.cts.Equals(e2.cts)) { if (root == null) { root = e1; } } else { root = null; } e1 = e1.upper; e2 = e2.upper; } int rootRank = (root == null) ? -1 : root.rank; /* * If the root has maximal rank, then the two stacks are * identical. */ if (rootRank == n1 - 1) { return(s1); } /* * Everything above the root must be instantiated anew. We * create the instances in a top-down fashion, fixing links * on the way. */ StackElt tos = null; StackElt e3 = null; e1 = s1.tos; e2 = s2.tos; for (int i = n1 - 1; i > rootRank; i--) { StackElt e4 = new StackElt(null, CCTypeSet.Merge(e1.cts, e2.cts)); e4.rank = i; if (e3 == null) { tos = e4; } else { e3.upper = e4; } e3 = e4; e1 = e1.upper; e2 = e2.upper; } e3.upper = root; return(new CCStack(tos)); }
internal CCStack Push(CCTypeSet cts) { return(new CCStack(new StackElt(tos, cts))); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(0); next.MergeStack(Stack.Pop().Push(cts.ToNewInstance())); }
internal override void Walk() { CCTypeSet cts = Stack.Peek(1); next.MergeStack(Stack.Push(cts)); }
internal static CCLocals MergeNF( CCLocals l1, CCLocals l2, out string err) { err = null; if (object.ReferenceEquals(l1, l2)) { return(l1); } int n = l1.locals.Length; if (n != l2.locals.Length) { err = string.Format("internal error: mismatch on number of locals ({0} / {1})", n, l2.locals.Length); return(null); } /* * Merge entries one by one. The destination is lazily * updated to avoid allocation when not needed. */ bool r1ok = true, r2ok = true; CCTypeSet[] nlocals = null; for (int i = 0; i < n; i++) { CCTypeSet cts1 = l1.locals[i]; CCTypeSet cts2 = l2.locals[i]; if (cts1.Equals(cts2)) { if (nlocals != null) { nlocals[i] = cts1; } } else if (cts1.IsSubsetOf(cts2)) { r1ok = false; if (r2ok) { continue; } if (nlocals != null) { nlocals[i] = cts2; } } else if (cts2.IsSubsetOf(cts1)) { r2ok = false; if (r1ok) { continue; } if (nlocals != null) { nlocals[i] = cts1; } } else { if (nlocals == null) { r1ok = false; r2ok = false; nlocals = new CCTypeSet[n]; Array.Copy(l1.locals, 0, nlocals, 0, i); } CCTypeSet cts = CCTypeSet.MergeNF( cts1, cts2, out err); if (cts == null) { return(null); } nlocals[i] = cts; } } if (r1ok) { return(l1); } if (r2ok) { return(l2); } return(new CCLocals(nlocals)); }