FCodeEmit translates FCode fcode to IL bytecode.
Exemple #1
0
        /// <summary>
        /// Emit a mixin router from a class to the mixin body methods.
        /// </summary>
        public void emitMixinRouter(Method m)
        {
            string parent = FanUtil.toDotnetTypeName(m.parent());
            string name   = FanUtil.toDotnetMethodName(m.name());
            string ret    = FanUtil.toDotnetTypeName(m.inheritedReturns());

            string[] parTypes   = new string[] { parent };
            List     pars       = m.@params();
            int      paramCount = pars.sz();

            // find first param with default value
            int firstDefault = paramCount;

            for (int i = 0; i < paramCount; i++)
            {
                if (((Param)pars.get(i)).hasDefault())
                {
                    firstDefault = i; break;
                }
            }

            // generate routers
            for (int i = firstDefault; i <= paramCount; i++)
            {
                string[] myParams     = new string[i];
                string[] myParamNames = new string[i];
                string[] implParams   = new string[i + 1];
                implParams[0] = parent;

                for (int j = 0; j < i; j++)
                {
                    Param  param = (Param)m.@params().get(j);
                    Type   pt    = param.type();
                    string s     = FanUtil.toDotnetTypeName(pt);
                    myParams[j]       = s;
                    myParamNames[j]   = param.name();
                    implParams[j + 1] = s;
                }

                // CLR requires public virtual
                PERWAPI.MethAttr attr = PERWAPI.MethAttr.Public | PERWAPI.MethAttr.Virtual;

                PERWAPI.CILInstructions code = emitter.emitMethod(name, ret, myParamNames, myParams,
                                                                  attr, new string[0], new string[0]);
                code.Inst(PERWAPI.Op.ldarg_0); // push this
                for (int p = 0; p < i; p++)
                {
                    // push args
                    Param param = (Param)m.@params().get(p);
                    FCodeEmit.loadVar(code, FanUtil.toDotnetStackType(param.type()), p + 1);
                }
                PERWAPI.Method meth = emitter.findMethod(parent + "_", name, implParams, ret);
                code.MethInst(PERWAPI.MethodOp.call, meth);
                code.Inst(PERWAPI.Op.ret);
            }
        }
Exemple #2
0
        //////////////////////////////////////////////////////////////////////////
        // Code Utils
        //////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Push the specified number of arguments onto the stack.
        /// </summary>
        private void pushArgs(PERWAPI.CILInstructions code, bool self, int count)
        {
            if (self)
            {
                code.Inst(PERWAPI.Op.ldarg_0);
            }
            for (int i = 0; i < count; i++)
            {
                FTypeRef var = emit.pod.typeRef(method.m_vars[i].type);
                FCodeEmit.loadVar(code, var.stackType, self ? i + 1 : i);
            }
        }
Exemple #3
0
        /// <summary>
        /// Emit wrapper.
        /// </summary>
        private void emitWrapper(PERWAPI.MethodDef main, int paramLen)
        {
            // use explicit param count, and clear code
              this.paramLen = paramLen;
              this.code     = null;
              int numArgs   = isStatic && !self ? paramLen : paramLen+1;

              // TODO - this code probably isn't quite right, since it looks
              // like we generate local variables even when they might not be
              // used.  Doesn't hurt anything, but is probably more efficient
              // if we could determine that from the fcode.

              // define our locals
              int numLocals = method.m_paramCount - paramLen;
              string[] localNames = new string[numLocals];
              string[] localTypes = new string[numLocals];
              for (int i=paramLen; i<method.m_paramCount; i++)
              {
            localNames[i-paramLen] = method.m_vars[i].name;
            localTypes[i-paramLen] = emit.nname(method.m_vars[i].type);
              }

              // emit code
              PERWAPI.CILInstructions code = doEmit(localNames, localTypes);

              // push arguments passed thru
              pushArgs(code, !(isStatic && !self), paramLen);

              // emit default arguments
              FCodeEmit.Reg[] regs = FCodeEmit.initRegs(emit.pod, isStatic, method.m_vars);
              int maxLocals = method.maxLocals();
              int maxStack  = 16; // TODO - add additional default expr stack height
              for (int i=paramLen; i<method.m_paramCount; i++)
              {
            FCodeEmit ce = new FCodeEmit(emit, method.m_vars[i].def, code, regs, emit.pod.typeRef(method.m_ret));
            ce.paramCount = numArgs;
            ce.vars = method.m_vars;
            ce.isStatic = isStatic;
            // TODO - is this correct?
            ce.emit(false);  // don't emit debug s cope for wrappers
            maxStack = System.Math.Max(maxStack, 2+i+8);
              }
              // TODO
              //code.maxLocals = maxLocals;
              //code.maxStack  = maxStack;

              // call master implementation
              if (isStatic)
            code.MethInst(PERWAPI.MethodOp.call, main);
              else
            code.MethInst(PERWAPI.MethodOp.callvirt, main);

              // return
              code.Inst(PERWAPI.Op.ret);
        }
Exemple #4
0
        /// <summary>
        /// Emit wrapper.
        /// </summary>
        private void emitWrapper(PERWAPI.MethodDef main, int paramLen)
        {
            // use explicit param count, and clear code
            this.paramLen = paramLen;
            this.code     = null;
            int numArgs = isStatic && !self ? paramLen : paramLen + 1;

            // TODO - this code probably isn't quite right, since it looks
            // like we generate local variables even when they might not be
            // used.  Doesn't hurt anything, but is probably more efficient
            // if we could determine that from the fcode.

            // define our locals
            int numLocals = method.m_paramCount - paramLen;

            string[] localNames = new string[numLocals];
            string[] localTypes = new string[numLocals];
            for (int i = paramLen; i < method.m_paramCount; i++)
            {
                localNames[i - paramLen] = method.m_vars[i].name;
                localTypes[i - paramLen] = emit.nname(method.m_vars[i].type);
            }

            // emit code
            PERWAPI.CILInstructions code = doEmit(localNames, localTypes);

            // push arguments passed thru
            pushArgs(code, !(isStatic && !self), paramLen);

            // emit default arguments
            FCodeEmit.Reg[] regs      = FCodeEmit.initRegs(emit.pod, isStatic, method.m_vars);
            int             maxLocals = method.maxLocals();
            int             maxStack  = 16; // TODO - add additional default expr stack height

            for (int i = paramLen; i < method.m_paramCount; i++)
            {
                FCodeEmit ce = new FCodeEmit(emit, method.m_vars[i].def, code, regs, emit.pod.typeRef(method.m_ret));
                ce.paramCount = numArgs;
                ce.vars       = method.m_vars;
                ce.isStatic   = isStatic;
// TODO - is this correct?
                ce.emit(false); // don't emit debug s cope for wrappers
                maxStack = System.Math.Max(maxStack, 2 + i + 8);
            }
            // TODO
            //code.maxLocals = maxLocals;
            //code.maxStack  = maxStack;

            // call master implementation
            if (isStatic)
            {
                code.MethInst(PERWAPI.MethodOp.call, main);
            }
            else
            {
                code.MethInst(PERWAPI.MethodOp.callvirt, main);
            }

            // return
            code.Inst(PERWAPI.Op.ret);
        }