internal static GStack Make(XType[] topCombo, GStack tail) { GStackElt tos = tail.tos; for (int i = topCombo.Length - 1; i >= 0; i--) { XTypeSet xts = new XTypeSet(); xts.Add(topCombo[i]); tos = new GStackElt(tos, xts); } return(new GStack(tos)); }
internal DCall(GStack gs, Function f) { this.gs = gs; this.f = f; }
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); } } }