Пример #1
0
    /*
     * Turn a function call into the corresponding GFunctionInterpreted.
     * This applies recursively on all the the call sub-tree.
     */
    internal static GFunctionInterpreted Add(CCFunctionInterpreted cfi)
    {
        GFunctionInterpreted ngf = new GFunctionInterpreted(cfi);

        /*
         * Find the GFunction already existing for this function.
         */
        SortedSet <GFunctionInterpreted> ss;

        if (!ALL.TryGetValue(cfi.fi, out ss))
        {
            ss = new SortedSet <GFunctionInterpreted>();
            ss.Add(ngf);
            ALL[cfi.fi] = ss;
            return(ngf);
        }

        /*
         * If the new function can be merged into any of the
         * existing GFunction, do it; otherwise, add it as a
         * new GFunction.
         */
        foreach (GFunctionInterpreted gf in ss)
        {
            if (gf.Merge(ngf))
            {
                return(gf);
            }
        }
        ss.Add(ngf);
        return(ngf);
    }
Пример #2
0
    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);
    }
Пример #3
0
 internal CCNodeEntry(CCNodeEntry parent, CCFunctionInterpreted cfi)
     : base(cfi, 0)
 {
     this.parent = parent;
 }
Пример #4
0
 internal CCNodeOpcode(CCFunctionInterpreted cfi, int addr)
     : base()
 {
     this.cfi  = cfi;
     this.addr = addr;
 }
Пример #5
0
    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);
            }
        }
    }