internal void DoGetLocal(int num) { int index = cfi.fi.fieldInverseMapping[num]; CCStack nstack = Stack.Push(Locals.Get(index)); PropagateNext(nstack); }
internal override void Walk() { Stack.CheckMultipleSubTypeOf(tParams); CCStack nstack = Stack.Pop(tParams.Length).Push(ctsRets); next.MergeStack(nstack); }
internal void DoGetLocalIndexed(int off, int len) { Stack.Peek(0).CheckInt(); int index = cfi.fi.fieldInverseMapping[off]; CCStack nstack = Stack.Pop().Push(Locals.Get(index)); PropagateNext(nstack); }
internal override CCNode Enter(CCStack stack, CCNodeEntry parent, CCNode next) { CCNode node = new CCNodeNative(this, tParams, ctsRets, next); node.MergeStack(stack); return(node); }
internal CCNodeOpcode Propagate(int addr2, CCNodeOpcode node, CCStack nstack, CCLocals nlocals) { if (node == null) { node = GetNode(addr2); } node.MergeStack(nstack); node.MergeLocals(nlocals); return(node); }
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); }
static GStackElt MakeTOS(CCStack src) { if (src == null) { return(null); } GStackElt tos = null; GStackElt r = null; int num = 0; IEnumerator <CCTypeSet> iter = src.EnumerateFromTop(); for (;;) { if (!iter.MoveNext()) { break; } XTypeSet ss = new XTypeSet(); foreach (CCType ct in iter.Current) { ss.Add(ct.xType); } if (ss.Count == 0) { throw new Exception(string.Format("internal error: no element in CCStack at depth {0}", num)); } GStackElt r2 = new GStackElt(null, ss); if (r == null) { tos = r2; } else { r.upper = r2; } r = r2; num++; } /* * We assembled the GStack in reverse order, so all * ranks are wrong and we must fix them. */ for (r = tos; r != null; r = r.upper) { r.rank = --num; } return(tos); }
internal void MergeStack(CCStack stack2) { if (Stack == null) { Stack = stack2; MarkUpdate(); } else { CCStack nstack = CCStack.Merge(Stack, stack2); if (nstack != Stack) { Stack = nstack; MarkUpdate(); } } }
internal static CCNodeEntry EnterFunction(FunctionInterpreted fi, CCStack stack, CCNodeEntry parent, CCNode next) { if (Compiler.PrintFunctions != null) { fi.Print(Compiler.PrintFunctions, 1); } CCLocals locals = new CCLocals(fi.numLocalFieldsCoalesced); CCFunctionInterpreted cfi = new CCFunctionInterpreted(fi, next); CCNodeEntry node = new CCNodeEntry(parent, cfi); cfi.SetNode(0, node); node.MergeStack(stack); node.MergeLocals(locals); /* * All instances allocated locally by this function must * have instantiable types. */ foreach (XType xt in fi.localEmbedTypes) { xt.Close(); } /* * Infinite recursion detection: if the same function is * already present several times in the ancestry, * complains. (TODO: make the threshold configurable) */ int rc = 0; for (CCNodeEntry e = parent; e != null; e = e.parent) { if (e.cfi.fi == fi) { if (++rc >= 5) { throw new Exception(string.Format("possible infinite recursion on function {0}", fi.DebugName)); } } } return(node); }
internal static CCNode BuildTree(Function f, params CCTypeSet[] args) { CCStack stack = new CCStack(); foreach (CCTypeSet cts in args) { stack = stack.Push(cts); } CCNode start = f.Enter(stack, null, new CCNodeExit()); for (;;) { int n = TO_EXPLORE.Count; if (n == 0) { break; } CCNode node = TO_EXPLORE[n - 1]; TO_EXPLORE.RemoveAt(n - 1); node.update = false; node.Walk(); } return(start); }
internal override CCNode Enter(CCStack stack, CCNodeEntry parent, CCNode next) { return(CCNodeEntry.EnterFunction(this, stack, parent, next)); }
internal void PropagateBranch(int disp, CCStack nstack) { PropagateBranch(disp, nstack, Locals); }
internal void PropagateNext(CCStack nstack, CCLocals nlocals) { next = Propagate(addr + 1, next, nstack, nlocals); }
internal void PropagateNext(CCStack nstack) { PropagateNext(nstack, Locals); }
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 virtual CCNode Enter(CCStack stack, CCNodeEntry parent, CCNode next) { throw new Exception(string.Format("native function {0} cannot be compiled", DebugName)); }
internal void PropagateBranch(int disp, CCStack nstack, CCLocals nlocals) { branch = Propagate(addr + 1 + disp, branch, nstack, nlocals); }
internal void DoCall(string name) { /* * Make sure the next node exists. We also set its locals * to the current locals (the called function cannot * change our locals). Note that the stack is not set; * this will be done only when (if) one of the called * functions returns. */ if (next == null) { next = GetNode(addr + 1); } next.MergeLocals(Locals); /* * Find all functions registered with the specified name. * If none is found, then we want a specific error message * (this is probably a typographic error in the function * name). */ List <FunctionRegistration> r1 = Function.LookupAll(name); if (r1.Count == 0) { throw new Exception(string.Format("no such function: {0}", name)); } /* * Find all functions that may match the types on the * stack. */ List <FunctionRegistration> r2 = new List <FunctionRegistration>(); int maxNum = 0; foreach (FunctionRegistration fr in r1) { if (Stack.MayMatch(fr.types)) { r2.Add(fr); maxNum = Math.Max(maxNum, fr.types.Length); } } /* * For all combinations of types that may occur on the * stack, try to resolve the call; if any fails, then * report it as an error. * While doing so, we accumulate, for each reachable * function, the types that may appear on entry of * that function. */ CCType[] combo = new CCType[maxNum]; CCTypeSet.ComboEnumerator ce = new CCTypeSet.ComboEnumerator( Stack.GetTopElements(maxNum)); XType[] xts = new XType[maxNum]; SortedDictionary <Function, CCStack> targets = new SortedDictionary <Function, CCStack>(); CCStack root = Stack.Pop(maxNum); GStack gtail = GStack.Make(root); calls = new List <DCall>(); for (;;) { if (!ce.Next(combo)) { break; } for (int i = 0; i < maxNum; i++) { xts[i] = combo[i].xType; } Function f = Function.Resolve(name, r2, xts); CCStack nstack = root.Push(combo); CCStack ostack; if (targets.TryGetValue(f, out ostack)) { targets[f] = CCStack.Merge(ostack, nstack); } else { targets[f] = nstack; } calls.Add(new DCall(GStack.Make(xts, gtail), f)); } /* * We now have a complete list of reachable functions, * each with a corresponding entry stack; we know that * the call will always resolve to a single function. If * we are updating, we reuse the previous functions from * the dispatch variable if available. Note that an update * can only add new functions, not remove existing ones. */ if (dispatch == null) { dispatch = new SortedDictionary <Function, CCNode>(); } foreach (Function f in targets.Keys) { CCStack stack = targets[f]; CCNode onode; if (dispatch.TryGetValue(f, out onode)) { onode.MergeStack(stack); } else { dispatch[f] = f.Enter(stack, cfi.Entry, next); } } }
internal static GStack Make(CCStack src) { return(new GStack(MakeTOS(src))); }