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); }
/* * Build the function if possible; this is for an automatic * builder. If the function is empty, or there are outstanding * control-flow structures, then this method returns null. * * When a non-null function is returned, this builder is * automatically cleared and made ready to accumulate new * instructions. */ internal Function BuildAuto() { if (cfPtr != -1 || code.Count == 0) { return(null); } if (jumpToLast || code[code.Count - 1].MayFallThrough) { Ret(); } Function f = new FunctionInterpreted(debugName, 0, null, 0, IZERO, code.ToArray()); code.Clear(); numLocalFields = 0; fieldMapping.Clear(); jumpToLast = true; return(f); }
internal CCFunctionInterpreted(FunctionInterpreted fi, CCNode next) { this.fi = fi; nodes = new CCNodeOpcode[fi.CodeLength]; this.next = next; }
GFunctionInterpreted(CCFunctionInterpreted cfi) : base(cfi.fi) { this.fi = cfi.fi; /* * Specialize opcodes. In this step: * * - For each source opcode, we create an appropriate GOp * instance. Type specialization for local fields * happens here. * * - Unreachable opcodes (whose entry stack is null) yield * a GOpZero. */ List <GOp> specOps = new List <GOp>(); int srcLen = cfi.nodes.Length; for (int i = 0; i < srcLen; i++) { GOp g = cfi.ToGOp(i); if (g == null) { throw new Exception("NYI (GOp)"); } specOps.Add(g); } spec = specOps.ToArray(); AdjustJumps(); /* * Compute local frame elements: * * - For local fields, only putlocal and putlocalindexed * matter; we check that each local has a single storage * type. * * - For local instances, we use reflocal and * reflocalindexed. */ frame = new GOpFrame(this); for (int i = 0; i < spec.Length; i++) { var pl = spec[i] as GOpPutLocal; if (pl != null) { frame.AddLocalVariable(pl.off, pl.ltype); } var pli = spec[i] as GOpPutLocalIndexed; if (pli != null) { frame.AddLocalVariableArray( pli.off, pli.len, pli.ltype); } var rl = spec[i] as GOpRefLocal; if (rl != null) { frame.AddLocalInstance(rl.off, rl.ltype); } var rli = spec[i] as GOpRefLocalIndexed; if (rli != null) { frame.AddLocalInstanceArray( rli.off, rli.len, rli.ltype); } } }