예제 #1
0
        void EmitSwapThunk(TypeBuilder tb)
        {
            MethodBuilder mb  = tb.DefineMethod("swapThunk", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(int), typeof(ILookupThunk) });
            CljILGen      ilg = new CljILGen(mb.GetILGenerator());

            Label endLabel = ilg.DefineLabel();

            Label[] labels = new Label[KeywordCallsites.count()];
            for (int i = 0; i < KeywordCallsites.count(); i++)
            {
                labels[i] = ilg.DefineLabel();
            }

            ilg.EmitLoadArg(1);
            ilg.Emit(OpCodes.Switch, labels);
            ilg.Emit(OpCodes.Br, endLabel);

            for (int i = 0; i < KeywordCallsites.count(); i++)
            {
                ilg.MarkLabel(labels[i]);
                ilg.EmitLoadArg(2);
                ilg.EmitFieldSet(_thunkFields[i]);
                ilg.Emit(OpCodes.Br, endLabel);
            }

            ilg.MarkLabel(endLabel);
            ilg.Emit(OpCodes.Ret);
        }
예제 #2
0
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            Label nullLabel  = ilg.DefineLabel();
            Label falseLabel = ilg.DefineLabel();
            Label endLabel   = ilg.DefineLabel();
            Label trueLabel  = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            if (_testExpr is StaticMethodExpr sme && sme.CanEmitIntrinsicPredicate())
            {
                sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel);
            }
예제 #3
0
        private void DoEmit(ObjExpr fn, TypeBuilder tb)
        {
            MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;
            MethodBuilder    mb      = tb.DefineMethod(MethodName, attribs, ReturnType, ArgTypes);

            SetCustomAttributes(mb);

            CljILGen baseIlg = new CljILGen(mb.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                Body.Emit(RHC.Return, fn, baseIlg);
                if (Body.HasNormalExit())
                {
                    baseIlg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
            {
                tb.DefineMethodOverride(mb, ExplicitMethodInfo);
            }
        }
예제 #4
0
        public override void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, ReturnType, ArgTypes);

            SetCustomAttributes(mb);

            CljILGen ilg       = new CljILGen(mb.GetILGenerator());
            Label    loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));
                ilg.MarkLabel(loopLabel);
                EmitBody(Objx, ilg, _retType, Body);
                if (Body.HasNormalExit())
                {
                    ilg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
            {
                tb.DefineMethodOverride(mb, ExplicitMethodInfo);
            }
        }
예제 #5
0
        private void DoEmitPrimOrStatic(ObjExpr fn, TypeBuilder tb, bool isStatic)
        {
            MethodAttributes attribs = isStatic
                ? MethodAttributes.Static | MethodAttributes.Public
                : MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;

            string methodName = isStatic ? "invokeStatic" : "invokePrim";

            MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, GetReturnType(), _argTypes);

            if (!isStatic)
            {
                SetCustomAttributes(baseMB);
            }

            CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                EmitBody(Objx, baseIlg, _retType, _body);
                if (_body.HasNormalExit())
                {
                    baseIlg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }
            // Generate the regular invoke, calling the static or prim method

            MethodBuilder regularMB = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), GetArgTypes());

            SetCustomAttributes(regularMB);

            CljILGen regIlg = new CljILGen(regularMB.GetILGenerator());

            if (!isStatic)
            {
                regIlg.Emit(OpCodes.Ldarg_0);
            }
            for (int i = 0; i < _argTypes.Length; i++)
            {
                regIlg.EmitLoadArg(i + 1);
                HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]);
            }
            regIlg.Emit(OpCodes.Call, baseMB);
            if (GetReturnType().IsValueType)
            {
                regIlg.Emit(OpCodes.Box, GetReturnType());
            }
            regIlg.Emit(OpCodes.Ret);
        }
예제 #6
0
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            List <LocalBuilder> locals = new List <LocalBuilder>();

            for (int i = 0; i < _bindingInits.count(); i++)
            {
                BindingInit bi       = (BindingInit)_bindingInits.nth(i);
                Type        primType = Compiler.MaybePrimitiveType(bi.Init);
                if (primType != null)
                {
                    LocalBuilder local = ilg.DeclareLocal(primType);
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
                else
                {
                    LocalBuilder local = ilg.DeclareLocal(typeof(Object));
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    bi.Init.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
            }

            Label loopLabel = ilg.DefineLabel();

            ilg.MarkLabel(loopLabel);

            try
            {
                if (_isLoop)
                {
                    Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel));
                }

                if (emitUnboxed)
                {
                    ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg);
                }
                else
                {
                    _body.Emit(rhc, objx, ilg);
                }
            }
            finally
            {
                if (_isLoop)
                {
                    Var.popThreadBindings();
                }
            }
        }
예제 #7
0
        protected static void EmitHasArityMethod(TypeBuilder tb, IList <int> arities, bool isVariadic, int reqArity)
        {
            // TODO: Convert to a Switch instruction
            MethodBuilder mb = tb.DefineMethod(
                "HasArity",
                MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(bool),
                new Type[] { typeof(int) });

            CljILGen gen = new CljILGen(mb.GetILGenerator());

            Label falseLabel = gen.DefineLabel();
            Label trueLabel  = gen.DefineLabel();

            if (isVariadic)
            {
                gen.EmitLoadArg(1);
                gen.EmitInt(reqArity);
                gen.Emit(OpCodes.Bge, trueLabel);
            }

            if (arities != null)
            {
                foreach (int i in arities)
                {
                    gen.EmitLoadArg(1);
                    gen.EmitInt(i);
                    gen.Emit(OpCodes.Beq, trueLabel);
                }
            }

            gen.MarkLabel(falseLabel);
            gen.EmitBoolean(false);
            gen.Emit(OpCodes.Ret);

            gen.MarkLabel(trueLabel);
            gen.EmitBoolean(true);
            gen.Emit(OpCodes.Ret);
        }
예제 #8
0
        public virtual void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.Public, ReturnType, ArgTypes);

            CljILGen ilg       = new CljILGen(mb.GetILGenerator());
            Label    loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));
                ilg.MarkLabel(loopLabel);
                Body.Emit(RHC.Return, fn, ilg);
                ilg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }
예제 #9
0
        internal void LightEmit(ObjExpr fn, Type fnType)
        {
            if (DynMethod != null)
            {
                return;
            }

            if (Prim != null || fn.IsStatic)
            {
                throw new InvalidOperationException("No light compile allowed for static methods or methods with primitive interfaces");
            }

            Type[] argTypes = ClrExtensions.ArrayInsert(fnType, GetArgTypes());

            DynamicMethod meth = new DynamicMethod(GetMethodName(), GetReturnType(), argTypes, true);

            CljILGen baseIlg = new CljILGen(meth.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                //GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                _body.Emit(RHC.Return, fn, baseIlg);
                if (_body.HasNormalExit())
                {
                    baseIlg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            DynMethod = meth;
        }
예제 #10
0
        public override void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, GetReturnType(), GetArgTypes());

            SetCustomAttributes(mb);

            //Console.Write("Compiling method {0} ", GetMethodName());
            //foreach (Type t in GetArgTypes())
            //    Console.Write("{0}, ", t.Name);
            //Console.WriteLine("returning {0}", GetReturnType().Name);

            CljILGen ilg       = new CljILGen(mb.GetILGenerator());
            Label    loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));
                ilg.MarkLabel(loopLabel);
                EmitBody(Objx, ilg, _retType, _body);
                if (_body.HasNormalExit())
                {
                    ilg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
            {
                tb.DefineMethodOverride(mb, _explicitMethodInfo);
            }
        }
예제 #11
0
        static void EmitMain(GenContext context, TypeBuilder proxyTB, string mainName, FieldBuilder mainFB)
        {
            MethodBuilder cb = proxyTB.DefineMethod("Main",MethodAttributes.Public| MethodAttributes.Static,CallingConventions.Standard,typeof(void),new Type[] { typeof(String[]) });
            CljILGen gen = new CljILGen(cb.GetILGenerator()); ;

            Label noMainLabel = gen.DefineLabel();
            Label endLabel = gen.DefineLabel();

            EmitGetVar(gen, mainFB);
            gen.Emit(OpCodes.Dup);
            gen.Emit(OpCodes.Brfalse_S, noMainLabel);
            gen.Emit(OpCodes.Castclass, typeof(IFn));
            gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
            gen.EmitCall(Method_RT_seq);                        // gen.Emit(OpCodes.Call, Method_RT_seq);
            gen.EmitCall(Method_IFn_applyTo_Object_ISeq);       // gen.Emit(OpCodes.Call, Method_IFn_applyTo_Object_ISeq);
            gen.Emit(OpCodes.Pop);
            gen.Emit(OpCodes.Br_S, endLabel);

            // no main found
            gen.MarkLabel(noMainLabel);
            EmitUnsupported(gen, mainName);

            gen.MarkLabel(endLabel);
            gen.Emit(OpCodes.Ret);

            //context.AssyBldr.SetEntryPoint(cb);
            context.AssemblyBuilder.SetEntryPoint(cb);
        }
예제 #12
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            if (objx.FnMode == FnMode.Light)
            {
                // This will emit a plain Keyword reference, rather than a callsite.
                InvokeExpr ie = new InvokeExpr(_source, _spanMap, (Symbol)_tag, _kw, RT.vector(_target));
                ie.Emit(rhc, objx, ilg);
            }
            else
            {
                Label endLabel = ilg.DefineLabel();
                Label faultLabel = ilg.DefineLabel();

                GenContext.EmitDebugInfo(ilg, _spanMap);

                LocalBuilder thunkLoc = ilg.DeclareLocal(typeof(ILookupThunk));
                LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
                LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(thunkLoc, "thunk");
                GenContext.SetLocalName(targetLoc, "target");
                GenContext.SetLocalName(resultLoc, "result");

                // TODO: Debug info

                // pseudo-code:
                //  ILookupThunk thunk = objclass.ThunkField(i)
                //  object target = ...code...
                //  object val = thunk.get(target)
                //  if ( val != thunk )
                //     return val
                //  else
                //     KeywordLookupSite site = objclass.SiteField(i)
                //     thunk = site.fault(target)
                //     objclass.ThunkField(i) = thunk
                //     val = thunk.get(target)
                //     return val

                ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                     // thunk
                ilg.Emit(OpCodes.Stloc, thunkLoc);                                  //  (thunkLoc <= thunk)

                _target.Emit(RHC.Expression, objx, ilg);                         // target
                ilg.Emit(OpCodes.Stloc, targetLoc);                                  //   (targetLoc <= target)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, targetLoc);
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
                ilg.Emit(OpCodes.Stloc, resultLoc);                                 //    (resultLoc <= result)

                ilg.Emit(OpCodes.Ldloc, thunkLoc);
                ilg.Emit(OpCodes.Ldloc, resultLoc);
                ilg.Emit(OpCodes.Beq, faultLabel);

                ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
                ilg.Emit(OpCodes.Br, endLabel);

                ilg.MarkLabel(faultLabel);
                ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));           // site
                ilg.Emit(OpCodes.Ldloc, targetLoc);                                  // site, target
                ilg.EmitCall(Compiler.Method_ILookupSite_fault);                    // new-thunk
                ilg.Emit(OpCodes.Dup);                                              // new-thunk, new-thunk
                ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                      // new-thunk

                ilg.Emit(OpCodes.Ldloc, targetLoc);                                 // new-thunk, target
                ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

                ilg.MarkLabel(endLabel);                                           // result
                if (rhc == RHC.Statement)
                    ilg.Emit(OpCodes.Pop);
            }
        }
예제 #13
0
        // TODO: Eliminate common code between EmitProtoLight and EmitProtoFull

        void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);

            e.Emit(RHC.Expression, objx, ilg);               // target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));

            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc, targetTemp);             //   (targetTemp <= target)

            ilg.EmitString(String.Format("In Light Proto for {0}", v.Symbol.ToString()));
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Ldloc, targetTemp);              // target
            //    ilg.Emit(OpCodes.Isinst, _protocolOn);            // (target or null)
            //    ilg.Emit(OpCodes.Ldnull);                         // (target or null), null
            //    ilg.Emit(OpCodes.Cgt_Un);                         // (0 or 1)
            //    ilg.Emit(OpCodes.Brtrue, onLabel);
            //}

            objx.EmitVar(ilg, v);                                   // var
            ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn


            ilg.Emit(OpCodes.Dup);
            ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType"));
            ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString"));
            ilg.EmitString("Expected AFunction, got ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) }));
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));


            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.EmitString("Castclass worked ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));


            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1, rhc, objx, ilg);

            ilg.EmitString("gen'd args and called");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Br, endLabel);

            //ilg.MarkLabel(onLabel);
            //ilg.Emit(OpCodes.Ldloc, targetTemp);                  // target
            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Castclass, _protocolOn);
            //    MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count()));
            //    //if (rhc == RHC.Return)
            //    //{
            //    //    ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref();
            //    //    method.EmitClearLocals(context);
            //    //}
            //    ilg.Emit(OpCodes.Callvirt,_onMethod);
            //    HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType);
            //}
            ilg.MarkLabel(endLabel);
        }
예제 #14
0
        void EmitSwapThunk(TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod("swapThunk", MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.Virtual, typeof(void), new Type[] { typeof(int), typeof(ILookupThunk) });
            CljILGen ilg = new CljILGen(mb.GetILGenerator());

            Label endLabel = ilg.DefineLabel();
            Label[] labels = new Label[KeywordCallsites.count()];
            for (int i = 0; i < KeywordCallsites.count(); i++)
                labels[i] = ilg.DefineLabel();

            ilg.EmitLoadArg(1);
            ilg.Emit(OpCodes.Switch, labels);
            ilg.Emit(OpCodes.Br, endLabel);

            for (int i = 0; i < KeywordCallsites.count(); i++)
            {
                ilg.MarkLabel(labels[i]);
                ilg.EmitLoadArg(2);
                ilg.EmitFieldSet(_thunkFields[i]);
                ilg.Emit(OpCodes.Br, endLabel);
            }

            ilg.MarkLabel(endLabel);
            ilg.Emit(OpCodes.Ret);
        }
예제 #15
0
        void EmitProto(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label onLabel   = ilg.DefineLabel();
            Label callLabel = ilg.DefineLabel();
            Label endLabel  = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);

            e.Emit(RHC.Expression, objx, ilg);               // target
            ilg.Emit(OpCodes.Dup);                           // target, target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));

            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc, targetTemp);                  // target

            ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class
            ilg.EmitLoadArg(0);                                   // class, this
            ilg.EmitFieldGet(objx.CachedTypeField(_siteIndex));   // class, cached-class
            ilg.Emit(OpCodes.Beq, callLabel);                     //
            if (_protocolOn != null)
            {
                ilg.Emit(OpCodes.Ldloc, targetTemp);             // target
                ilg.Emit(OpCodes.Isinst, _protocolOn);           // null or target
                ilg.Emit(OpCodes.Ldnull);                        // (null or target), null
                ilg.Emit(OpCodes.Cgt_Un);                        // (0 or 1)
                ilg.Emit(OpCodes.Brtrue, onLabel);
            }
            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // target
            ilg.Emit(OpCodes.Call, Compiler.Method_Util_classOf); // class

            LocalBuilder typeTemp = ilg.DeclareLocal(typeof(Type));

            GenContext.SetLocalName(typeTemp, "type");
            ilg.Emit(OpCodes.Stloc, typeTemp);                   //    (typeType <= class)

            ilg.EmitLoadArg(0);                                  // this

            ilg.Emit(OpCodes.Ldloc, typeTemp);                   // this, class
            ilg.EmitFieldSet(objx.CachedTypeField(_siteIndex));  //

            ilg.MarkLabel(callLabel);

            objx.EmitVar(ilg, v);                                   // var
            ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot); // proto-fn
            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1, rhc, objx, ilg);
            ilg.Emit(OpCodes.Br, endLabel);

            ilg.MarkLabel(onLabel);
            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // target
            if (_protocolOn != null)
            {
                ilg.Emit(OpCodes.Castclass, _protocolOn);
                MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count()));
                //if (rhc == RHC.Return)
                //{
                //    ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref();
                //    method.EmitClearLocals(context);
                //}
                ilg.Emit(OpCodes.Callvirt, _onMethod);
                HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType);
            }
            ilg.MarkLabel(endLabel);
        }
예제 #16
0
        private static void GenerateProxyMethod(
            TypeBuilder proxyTB,
            FieldBuilder mapField,
            MethodInfo m,
            HashSet<MethodBuilder> specialMethods)
        {
            MethodAttributes attribs = m.Attributes;

            bool callBaseMethod;

            if ( (attribs & MethodAttributes.Abstract) == MethodAttributes.Abstract )
            {
                attribs &= ~MethodAttributes.Abstract;
                callBaseMethod = false;
            }
            else
            {
                callBaseMethod = true;

            }

            attribs &= ~MethodAttributes.NewSlot;
            attribs |= MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Public;

            //Console.Write("Generating proxy method {0}(", m.Name);
            //foreach (ParameterInfo p in m.GetParameters())
            //    Console.Write("{0}, ", p.ParameterType.FullName);
            //Console.Write(") ");
            //Console.WriteLine(attribs.ToString());

            MethodBuilder proxym = proxyTB.DefineMethod(
                m.Name,
                attribs,
                m.CallingConvention,
                m.ReturnType,
                m.GetParameters().Select<ParameterInfo, Type>(p => p.ParameterType).ToArray<Type>());

            if (m.IsSpecialName)
                specialMethods.Add(proxym);

            CljILGen gen = new CljILGen(proxym.GetILGenerator());

            Label elseLabel = gen.DefineLabel();
            Label endLabel = gen.DefineLabel();

            //// Print a little message, for debugging purposes
            //gen.Emit(OpCodes.Ldstr, String.Format("Calling {0} / {1}", proxyTB.FullName, m.ToString()));
            //gen.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine",
            //    new Type[] { typeof(string) }));
            //gen.Emit(OpCodes.Call, typeof(Console).GetMethod("get_Out"));
            //gen.Emit(OpCodes.Call, typeof(System.IO.TextWriter).GetMethod("Flush"));

            // Lookup method name in map
            gen.EmitLoadArg(0);                             // gen.Emit(OpCodes.Ldarg_0);
            gen.EmitFieldGet(mapField);                     // gen.Emit(OpCodes.Ldfld, mapField);
            gen.EmitString(m.Name);                         // gen.Emit(OpCodes.Ldstr, m.Name);
            gen.EmitCall(Method_RT_get);                    // gen.Emit(OpCodes.Call, Method_RT_get);
            gen.Emit(OpCodes.Dup);
            gen.EmitNull();                                 // gen.Emit(OpCodes.Ldnull);
            gen.Emit(OpCodes.Beq_S, elseLabel);

            // map entry found
            ParameterInfo[] pinfos = m.GetParameters();
            gen.Emit(OpCodes.Castclass, typeof(IFn));
            gen.EmitLoadArg(0);                             // gen.Emit(OpCodes.Ldarg_0);  // push implicit 'this' arg.
            for (int i = 0; i < pinfos.Length; i++)
            {
                gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
                if (m.GetParameters()[i].ParameterType.IsValueType)
                    gen.Emit(OpCodes.Box,pinfos[i].ParameterType);
            }

            int parmCount = pinfos.Length;
            gen.EmitCall(GetIFnInvokeMethodInfo(parmCount+1));        // gen.Emit(OpCodes.Call, GetIFnInvokeMethodInfo(parmCount + 1));
            if (m.ReturnType == typeof(void))
                gen.Emit(OpCodes.Pop);
            else
                gen.Emit(OpCodes.Unbox_Any, m.ReturnType);

            gen.Emit(OpCodes.Br_S,endLabel);

            // map entry not found
            gen.MarkLabel(elseLabel);
            gen.Emit(OpCodes.Pop); // get rid of null leftover from the 'get'

            if ( callBaseMethod )
            {
                gen.EmitLoadArg(0);                                     // gen.Emit(OpCodes.Ldarg_0);
                for (int i = 0; i < parmCount; i++)
                    gen.EmitLoadArg(i + 1);                             // gen.Emit(OpCodes.Ldarg, i + 1);
                gen.Emit(OpCodes.Call, m);                              // gen.EmitCall(m) improperly emits a callvirt in some cases
            }
            else
            {
                gen.EmitString(m.Name);                                 // gen.Emit(OpCodes.Ldstr, m.Name);
                gen.EmitNew(CtorInfo_NotImplementedException_1);        // gen.Emit(OpCodes.Newobj, CtorInfo_NotImplementedException_1);
                gen.Emit(OpCodes.Throw);
            }

            gen.MarkLabel(endLabel);
            gen.Emit(OpCodes.Ret);
        }
예제 #17
0
        private void DoEmitPrim(ObjExpr fn, TypeBuilder tb)
        {
            MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;

            string methodName = "invokePrim";

            Type returnType;

            if (_retType == typeof(double) || _retType == typeof(long))
            {
                returnType = ReturnType;
            }
            else
            {
                returnType = typeof(object);
            }

            MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes);

            SetCustomAttributes(baseMB);

            CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                EmitBody(Objx, baseIlg, _retType, Body);
                if (Body.HasNormalExit())
                {
                    baseIlg.Emit(OpCodes.Ret);
                }
            }
            finally
            {
                Var.popThreadBindings();
            }

            // Generate the regular invoke, calling the prim method

            MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes);

            SetCustomAttributes(regularMB);

            CljILGen regIlg = new CljILGen(regularMB.GetILGenerator());

            regIlg.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < _argTypes.Length; i++)
            {
                regIlg.EmitLoadArg(i + 1);
                HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]);
            }
            regIlg.Emit(OpCodes.Call, baseMB);
            if (ReturnType.IsValueType)
            {
                regIlg.Emit(OpCodes.Box, ReturnType);
            }
            regIlg.Emit(OpCodes.Ret);
        }
예제 #18
0
        public override void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, GetReturnType(), GetArgTypes());
            SetCustomAttributes(mb);

            //Console.Write("Compiling method {0} ", GetMethodName());
            //foreach (Type t in GetArgTypes())
            //    Console.Write("{0}, ", t.Name);
            //Console.WriteLine("returning {0}", GetReturnType().Name);

            CljILGen ilg = new CljILGen(mb.GetILGenerator());
            Label loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this));
                ilg.MarkLabel(loopLabel);
                EmitBody(Objx,ilg,_retType,_body);
                if ( _body.HasNormalExit() )
                    ilg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
                tb.DefineMethodOverride(mb, _explicitMethodInfo);
        }
예제 #19
0
        // TODO: Eliminate common code between EmitProtoLight and EmitProtoFull
        void EmitProtoLight(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);
            e.Emit(RHC.Expression, objx, ilg);               // target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));
            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc, targetTemp);             //   (targetTemp <= target)

            ilg.EmitString(String.Format("In Light Proto for {0}",v.Symbol.ToString()));
            ilg.Emit(OpCodes.Call,typeof(Console).GetMethod("WriteLine",new Type[] { typeof(string) }));

            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Ldloc, targetTemp);              // target
            //    ilg.Emit(OpCodes.Isinst, _protocolOn);            // (target or null)
            //    ilg.Emit(OpCodes.Ldnull);                         // (target or null), null
            //    ilg.Emit(OpCodes.Cgt_Un);                         // (0 or 1)
            //    ilg.Emit(OpCodes.Brtrue, onLabel);
            //}

            objx.EmitVar(ilg, v);                                 // var
            ilg.Emit(OpCodes.Call, Compiler.Method_Var_getRawRoot);         // proto-fn

                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Call, typeof(Object).GetMethod("GetType"));
                ilg.Emit(OpCodes.Callvirt, typeof(Object).GetMethod("ToString"));
                ilg.EmitString("Expected AFunction, got ");
                ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("Write", new Type[] { typeof(String) }));
                ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.EmitString("Castclass worked ");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Ldloc, targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1, rhc, objx, ilg);

            ilg.EmitString("gen'd args and called");
            ilg.Emit(OpCodes.Call, typeof(Console).GetMethod("WriteLine", new Type[] { typeof(String) }));

            ilg.Emit(OpCodes.Br, endLabel);

            //ilg.MarkLabel(onLabel);
            //ilg.Emit(OpCodes.Ldloc, targetTemp);                  // target
            //if (_protocolOn != null)
            //{
            //    ilg.Emit(OpCodes.Castclass, _protocolOn);
            //    MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count()));
            //    //if (rhc == RHC.Return)
            //    //{
            //    //    ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref();
            //    //    method.EmitClearLocals(context);
            //    //}
            //    ilg.Emit(OpCodes.Callvirt,_onMethod);
            //    HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType);
            //}
            ilg.MarkLabel(endLabel);
        }
예제 #20
0
파일: IfExpr.cs 프로젝트: JvJ/clojure-clr
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            Label nullLabel = ilg.DefineLabel();
            Label falseLabel = ilg.DefineLabel();
            Label endLabel = ilg.DefineLabel();
            Label trueLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            StaticMethodExpr sme = _testExpr as StaticMethodExpr;
            if (sme != null && sme.CanEmitIntrinsicPredicate())
                sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel);
            else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool))
            {
                ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Brfalse, falseLabel);
            }
            else
            {
                LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(tempLoc, "test");

                _testExpr.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Stloc, tempLoc);

                ilg.Emit(OpCodes.Brfalse, nullLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Isinst, typeof(bool));
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Cgt_Un);
                ilg.Emit(OpCodes.Brfalse, trueLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Unbox_Any, typeof(bool));
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
                ilg.Emit(OpCodes.Brtrue, falseLabel);
            }

            ilg.MarkLabel(trueLabel);

            if (emitUnboxed)
                ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg);
            else
                _thenExpr.Emit(rhc, objx, ilg);

            if ( _thenExpr.HasNormalExit() )
                ilg.Emit(OpCodes.Br, endLabel);

            ilg.MarkLabel(nullLabel);
            ilg.MarkLabel(falseLabel);

            if (emitUnboxed)
                ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg);
            else
                _elseExpr.Emit(rhc, objx, ilg);
            ilg.MarkLabel(endLabel);
        }
예제 #21
0
파일: FnMethod.cs 프로젝트: JvJ/clojure-clr
        private void DoEmitPrimOrStatic(ObjExpr fn, TypeBuilder tb, bool isStatic)
        {
            MethodAttributes attribs = isStatic
                ? MethodAttributes.Static | MethodAttributes.Public
                : MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;

            string methodName = isStatic ? "invokeStatic" : "invokePrim";

            MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, GetReturnType(), _argTypes);

            if ( ! isStatic )
                SetCustomAttributes(baseMB);

            CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                EmitBody(Objx, baseIlg, _retType, _body);
                if ( _body.HasNormalExit() )
                    baseIlg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }
            // Generate the regular invoke, calling the static or prim method

            MethodBuilder regularMB = tb.DefineMethod(GetMethodName(), MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), GetArgTypes());
            SetCustomAttributes(regularMB);

            CljILGen regIlg = new CljILGen(regularMB.GetILGenerator());

            if ( ! isStatic )
                regIlg.Emit(OpCodes.Ldarg_0);
            for(int i = 0; i < _argTypes.Length; i++)
            {
                regIlg.EmitLoadArg(i+1);
                HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]);
            }
            regIlg.Emit(OpCodes.Call,baseMB);
            if ( GetReturnType().IsValueType)
                regIlg.Emit(OpCodes.Box,GetReturnType());
            regIlg.Emit(OpCodes.Ret);
        }
예제 #22
0
파일: FnMethod.cs 프로젝트: JvJ/clojure-clr
        private void DoEmit(ObjExpr fn, TypeBuilder tb)
        {
            MethodAttributes attribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;

            MethodBuilder mb = tb.DefineMethod(GetMethodName(), attribs, GetReturnType(), GetArgTypes());

            SetCustomAttributes(mb);

            CljILGen baseIlg = new CljILGen(mb.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                _body.Emit(RHC.Return, fn, baseIlg);
                if ( _body.HasNormalExit() )
                    baseIlg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
                tb.DefineMethodOverride(mb, _explicitMethodInfo);
        }
예제 #23
0
파일: FnMethod.cs 프로젝트: JvJ/clojure-clr
        internal void LightEmit(ObjExpr fn, Type fnType)
        {
            if (DynMethod != null)
                return;

            if (Prim != null || fn.IsStatic)
                throw new InvalidOperationException("No light compile allowed for static methods or methods with primitive interfaces");

            Type[] argTypes = ClrExtensions.ArrayInsert(fnType,GetArgTypes());

            DynamicMethod meth = new DynamicMethod(GetMethodName(), GetReturnType(), argTypes, true);

            CljILGen baseIlg = new CljILGen(meth.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                //GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                _body.Emit(RHC.Return, fn, baseIlg);
                if (_body.HasNormalExit())
                    baseIlg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }

            DynMethod = meth;
        }
예제 #24
0
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            List<LocalBuilder> locals = new List<LocalBuilder>();

            for (int i = 0; i < _bindingInits.count(); i++)
            {
                BindingInit bi = (BindingInit)_bindingInits.nth(i);
                Type primType = Compiler.MaybePrimitiveType(bi.Init);
                if (primType != null)
                {
                    LocalBuilder local = ilg.DeclareLocal(primType);
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    ((MaybePrimitiveExpr)bi.Init).EmitUnboxed(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
                else
                {
                    LocalBuilder local = ilg.DeclareLocal(typeof(Object));
                    locals.Add(local);
                    GenContext.SetLocalName(local, bi.Binding.Name);
                    bi.Binding.LocalVar = local;

                    bi.Init.Emit(RHC.Expression, objx, ilg);
                    ilg.Emit(OpCodes.Stloc, local);
                }
             }

            Label loopLabel = ilg.DefineLabel();
            ilg.MarkLabel(loopLabel);

            try
            {
                if (_isLoop)
                    Var.pushThreadBindings(PersistentHashMap.create(Compiler.LoopLabelVar, loopLabel));

                if (emitUnboxed)
                    ((MaybePrimitiveExpr)_body).EmitUnboxed(rhc, objx, ilg);
                else
                    _body.Emit(rhc, objx, ilg);
            }
            finally
            {
                if (_isLoop)
                    Var.popThreadBindings();
            }
        }
예제 #25
0
        public void Emit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label endLabel   = ilg.DefineLabel();
            Label faultLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _spanMap);

            LocalBuilder thunkLoc  = ilg.DeclareLocal(typeof(ILookupThunk));
            LocalBuilder targetLoc = ilg.DeclareLocal(typeof(Object));
            LocalBuilder resultLoc = ilg.DeclareLocal(typeof(Object));

            GenContext.SetLocalName(thunkLoc, "thunk");
            GenContext.SetLocalName(targetLoc, "target");
            GenContext.SetLocalName(resultLoc, "result");

            // TODO: Debug info

            // pseudo-code:
            //  ILookupThunk thunk = objclass.ThunkField(i)
            //  object target = ...code...
            //  object val = thunk.get(target)
            //  if ( val != thunk )
            //     return val
            //  else
            //     KeywordLookupSite site = objclass.SiteField(i)
            //     thunk = site.fault(target)
            //     objclass.ThunkField(i) = thunk
            //     val = thunk.get(target)
            //     return val

            ilg.EmitFieldGet(objx.ThunkField(_siteIndex));                   // thunk
            ilg.Emit(OpCodes.Stloc, thunkLoc);                               //  (thunkLoc <= thunk)

            _target.Emit(RHC.Expression, objx, ilg);                         // target
            ilg.Emit(OpCodes.Stloc, targetLoc);                              //   (targetLoc <= target)

            ilg.Emit(OpCodes.Ldloc, thunkLoc);
            ilg.Emit(OpCodes.Ldloc, targetLoc);
            ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result
            ilg.Emit(OpCodes.Stloc, resultLoc);                                //    (resultLoc <= result)

            ilg.Emit(OpCodes.Ldloc, thunkLoc);
            ilg.Emit(OpCodes.Ldloc, resultLoc);
            ilg.Emit(OpCodes.Beq, faultLabel);

            ilg.Emit(OpCodes.Ldloc, resultLoc);                                  // result
            ilg.Emit(OpCodes.Br, endLabel);

            ilg.MarkLabel(faultLabel);
            ilg.EmitFieldGet(objx.KeywordLookupSiteField(_siteIndex));         // site
            ilg.Emit(OpCodes.Ldloc, targetLoc);                                // site, target
            ilg.EmitCall(Compiler.Method_ILookupSite_fault);                   // new-thunk
            ilg.Emit(OpCodes.Dup);                                             // new-thunk, new-thunk
            ilg.EmitFieldSet(objx.ThunkField(_siteIndex));                     // new-thunk

            ilg.Emit(OpCodes.Ldloc, targetLoc);                                // new-thunk, target
            ilg.EmitCall(Compiler.Method_ILookupThunk_get);                    // result

            ilg.MarkLabel(endLabel);                                           // result
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #26
0
        public void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            Label defaultLabel = ilg.DefineLabel();
            Label endLabel = ilg.DefineLabel();

            SortedDictionary<int, Label> labels = new SortedDictionary<int, Label>();
            foreach (int i in _tests.Keys)
                labels[i] = ilg.DefineLabel();

            // TODO: debug info

            Type primExprType = Compiler.MaybePrimitiveType(_expr);

            if (_testType == _intKey)
                EmitExprForInts(objx, ilg, primExprType, defaultLabel);
            else
                EmitExprForHashes(objx, ilg);

            if (_switchType == _sparseKey)
            {
                Label[] la = labels.Values.ToArray<Label>();
                ilg.Emit(OpCodes.Switch, la);
                ilg.Emit(OpCodes.Br, defaultLabel);
            }
            else
            {
                Label[] la = new Label[(_high - _low) + 1];
                for (int i = _low; i <= _high; i++)
                    la[i - _low] = labels.ContainsKey(i) ? labels[i] : defaultLabel;
                ilg.EmitInt(_low);
                ilg.Emit(OpCodes.Sub);
                ilg.Emit(OpCodes.Switch, la);
                ilg.Emit(OpCodes.Br, defaultLabel);
             }

            foreach (int i in labels.Keys)
            {
                ilg.MarkLabel(labels[i]);
                if (_testType == _intKey)
                    EmitThenForInts(objx, ilg, primExprType, _tests[i], _thens[i], defaultLabel, emitUnboxed);
                else if ((bool)RT.contains(_skipCheck, i))
                    EmitExpr(objx, ilg, _thens[i], emitUnboxed);
                else
                    EmitThenForHashes(objx, ilg, _tests[i], _thens[i], defaultLabel, emitUnboxed);
                if (  _thens[i].HasNormalExit() )
                    ilg.Emit(OpCodes.Br, endLabel);
            }
            ilg.MarkLabel(defaultLabel);
            EmitExpr(objx, ilg, _defaultExpr, emitUnboxed);
            ilg.MarkLabel(endLabel);
            if (rhc == RHC.Statement)
                ilg.Emit(OpCodes.Pop);
        }
예제 #27
0
        public override void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, ReturnType, ArgTypes);
            SetCustomAttributes(mb);

            CljILGen ilg = new CljILGen(mb.GetILGenerator());
            Label loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this));
                ilg.MarkLabel(loopLabel);
                EmitBody(Objx,ilg,_retType,Body);
                if ( Body.HasNormalExit() )
                    ilg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }

            if (IsExplicit)
                tb.DefineMethodOverride(mb, ExplicitMethodInfo);
        }
예제 #28
0
        void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            Label nullLabel  = ilg.DefineLabel();
            Label falseLabel = ilg.DefineLabel();
            Label endLabel   = ilg.DefineLabel();
            Label trueLabel  = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            StaticMethodExpr sme = _testExpr as StaticMethodExpr;

            if (sme != null && sme.CanEmitIntrinsicPredicate())
            {
                sme.EmitIntrinsicPredicate(RHC.Expression, objx, ilg, falseLabel);
            }
            else if (Compiler.MaybePrimitiveType(_testExpr) == typeof(bool))
            {
                ((MaybePrimitiveExpr)_testExpr).EmitUnboxed(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Brfalse, falseLabel);
            }
            else
            {
                LocalBuilder tempLoc = ilg.DeclareLocal(typeof(Object));
                GenContext.SetLocalName(tempLoc, "test");

                _testExpr.Emit(RHC.Expression, objx, ilg);
                ilg.Emit(OpCodes.Dup);
                ilg.Emit(OpCodes.Stloc, tempLoc);

                ilg.Emit(OpCodes.Brfalse, nullLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Isinst, typeof(bool));
                ilg.Emit(OpCodes.Ldnull);
                ilg.Emit(OpCodes.Cgt_Un);
                ilg.Emit(OpCodes.Brfalse, trueLabel);

                ilg.Emit(OpCodes.Ldloc, tempLoc);
                ilg.Emit(OpCodes.Unbox_Any, typeof(bool));
                ilg.Emit(OpCodes.Ldc_I4_0);
                ilg.Emit(OpCodes.Ceq);
                ilg.Emit(OpCodes.Brtrue, falseLabel);
            }

            ilg.MarkLabel(trueLabel);

            if (emitUnboxed)
            {
                ((MaybePrimitiveExpr)_thenExpr).EmitUnboxed(rhc, objx, ilg);
            }
            else
            {
                _thenExpr.Emit(rhc, objx, ilg);
            }


            if (_thenExpr.HasNormalExit())
            {
                ilg.Emit(OpCodes.Br, endLabel);
            }

            ilg.MarkLabel(nullLabel);
            ilg.MarkLabel(falseLabel);

            if (emitUnboxed)
            {
                ((MaybePrimitiveExpr)_elseExpr).EmitUnboxed(rhc, objx, ilg);
            }
            else
            {
                _elseExpr.Emit(rhc, objx, ilg);
            }
            ilg.MarkLabel(endLabel);
        }
예제 #29
0
        private void DoEmitStatic(ObjExpr fn, TypeBuilder tb)
        {
            MethodAttributes attribs = MethodAttributes.Static | MethodAttributes.Public;

            string methodName = "invokeStatic";

            Type returnType = ReturnType;

            MethodBuilder baseMB = tb.DefineMethod(methodName, attribs, returnType, _argTypes);

            CljILGen baseIlg = new CljILGen(baseMB.GetILGenerator());

            try
            {
                Label loopLabel = baseIlg.DefineLabel();
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar, loopLabel, Compiler.MethodVar, this));

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                baseIlg.MarkLabel(loopLabel);
                EmitBody(Objx, baseIlg, _retType, Body);
                if (Body.HasNormalExit())
                    baseIlg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }

            // Generate the regular invoke, calling the static method
            {
                MethodBuilder regularMB = tb.DefineMethod(MethodName, MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual, typeof(Object), ArgTypes);
                SetCustomAttributes(regularMB);

                CljILGen regIlg = new CljILGen(regularMB.GetILGenerator());

                for (int i = 0; i < _argTypes.Length; i++)
                {
                    regIlg.EmitLoadArg(i + 1);
                    HostExpr.EmitUnboxArg(fn, regIlg, _argTypes[i]);
                }

                GenContext.EmitDebugInfo(baseIlg, SpanMap);

                regIlg.Emit(OpCodes.Call, baseMB);
                if (ReturnType.IsValueType)
                    regIlg.Emit(OpCodes.Box, ReturnType);
                regIlg.Emit(OpCodes.Ret);
            }

            // Generate primInvoke if prim
            if (Prim != null)
            {
                MethodAttributes primAttribs = MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual;

                string primMethodName = "invokePrim";

                Type primReturnType;
                if (_retType == typeof(double) || _retType == typeof(long))
                    primReturnType = ReturnType;
                else
                    primReturnType = typeof(object);

                MethodBuilder primMB = tb.DefineMethod(primMethodName, primAttribs, primReturnType, _argTypes);
                SetCustomAttributes(primMB);

                CljILGen primIlg = new CljILGen(primMB.GetILGenerator());
                for (int i = 0; i < _argTypes.Length; i++)
                {
                    primIlg.EmitLoadArg(i + 1);
                    //HostExpr.EmitUnboxArg(fn, primIlg, _argTypes[i]);
                }
                primIlg.Emit(OpCodes.Call, baseMB);
                if (Body.HasNormalExit())
                    primIlg.Emit(OpCodes.Ret);
            }
        }
예제 #30
0
        static void DefineCtors(TypeBuilder proxyTB, 
            Type superClass,
            string initName,
            string postInitName,
            ISeq ctors,
            ISeq ctorTypes,
            FieldBuilder initFB,
            FieldBuilder postInitFB,
            FieldBuilder stateFB,
            string factoryName)
        {
            ISeq s1 = ctors;
            for (ISeq s = ctorTypes; s != null; s = s.next())
            {
                // TODO: Get rid of this mess by making sure the metadata on the keys of the constructors map gets copied to the constructor-types map.  Sigh.
                IPersistentMap ctorAttributes = GenInterface.ExtractAttributes(RT.meta(((IMapEntry)s1.first()).key()));
                s1 = s1.next();

                IMapEntry me = (IMapEntry)s.first();
                ISeq thisParamTypesV = (ISeq)me.key();
                ISeq baseParamTypesV = (ISeq)me.val();

                Type[] thisParamTypes = CreateTypeArray(thisParamTypesV);
                Type[] baseParamTypes = CreateTypeArray(baseParamTypesV);

                BindingFlags flags = BindingFlags.CreateInstance| BindingFlags.NonPublic| BindingFlags.Public| BindingFlags.Instance;
                ConstructorInfo superCtor = superClass.GetConstructor(flags,null,baseParamTypes,null);

                if (superCtor == null || superCtor.IsPrivate)
                    throw new InvalidOperationException("Base class constructor missing or private");

                ConstructorBuilder cb = proxyTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, thisParamTypes);
                GenInterface.SetCustomAttributes(cb, ctorAttributes);

                CljILGen gen = new CljILGen(cb.GetILGenerator());

                Label noInitLabel = gen.DefineLabel();
                Label noPostInitLabel = gen.DefineLabel();
                Label endPostInitLabel = gen.DefineLabel();
                Label endLabel = gen.DefineLabel();

                LocalBuilder locSuperArgs = gen.DeclareLocal(typeof(object));
                LocalBuilder locInitVal = gen.DeclareLocal(typeof(object));

                if (initFB != null)
                {
                    // init supplied
                    EmitGetVar(gen, initFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Box,thisParamTypes[i]);
                    }

                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length]);

                    // Expecting:  [[super-ctor-args...] state]

                    // store the init return in a local
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Stloc,locInitVal);

                    // store the first element in a local
                    gen.EmitInt(0);                             // gen.Emit(OpCodes.Ldc_I4_0);
                    gen.EmitCall(Method_RT_nth);                // gen.Emit(OpCodes.Call, Method_RT_nth);
                    gen.Emit(OpCodes.Stloc, locSuperArgs);

                    // Stack this + super-ctor-args + call base-class ctor.
                    gen.EmitLoadArg(0);                         // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < baseParamTypes.Length; i++)
                    {
                        gen.Emit(OpCodes.Ldloc, locSuperArgs);
                        gen.EmitInt(i);                         // gen.Emit(OpCodes.Ldc_I4, i);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        if (baseParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Unbox_Any, baseParamTypes[i]);
                        else
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                    }

                    gen.Emit(OpCodes.Call, superCtor);

                    if (stateFB != null)
                    {
                        gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldloc, locInitVal);
                        gen.EmitInt(1);                         // gen.Emit(OpCodes.Ldc_I4_1);
                        gen.EmitCall(Method_RT_nth);            // gen.Emit(OpCodes.Call, Method_RT_nth);
                        gen.Emit(OpCodes.Castclass, typeof(object));
                        gen.EmitFieldSet(stateFB);              // gen.Emit(OpCodes.Stfld, stateFB);
                    }

                    gen.Emit(OpCodes.Br_S, endLabel);

                    // No init found
                    gen.MarkLabel(noInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen, initName);

                    gen.MarkLabel(endLabel);
                }
                else  // no InitFB supplied.
                {
                    bool ok = thisParamTypes.Length == baseParamTypes.Length;
                    for (int i = 0; ok && i < thisParamTypes.Length; i++)
                        ok = baseParamTypes[i].IsAssignableFrom(thisParamTypes[i]);
                    if (!ok)
                        throw new InvalidOperationException(":init not specified, but ctor and super ctor args differ");
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for ( int i=0; i< thisParamTypes.Length; i++ )
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (baseParamTypes[i] != thisParamTypes[i])
                            gen.Emit(OpCodes.Castclass, baseParamTypes[i]);
                    }
                    gen.Emit(OpCodes.Call, superCtor);
                }

                if (postInitFB != null)
                {
                    // post-init supplied
                    EmitGetVar(gen, postInitFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brfalse_S, noPostInitLabel);
                    gen.Emit(OpCodes.Castclass, typeof(IFn));

                    // box init args
                    gen.EmitLoadArg(0);                                 // gen.Emit(OpCodes.Ldarg_0);
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        gen.EmitLoadArg(i + 1);                         // gen.Emit(OpCodes.Ldarg, i + 1);
                        if (thisParamTypes[i].IsValueType)
                            gen.Emit(OpCodes.Box, thisParamTypes[i]);
                        gen.Emit(OpCodes.Castclass, thisParamTypes[i]);
                    }
                    gen.EmitCall(Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);   // gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[thisParamTypes.Length + 1]);
                    gen.Emit(OpCodes.Pop);
                    gen.Emit(OpCodes.Br_S, endPostInitLabel);

                    // no post-init found

                    gen.MarkLabel(noPostInitLabel);

                    gen.Emit(OpCodes.Pop);
                    EmitUnsupported(gen,postInitName + " not defined");

                    gen.MarkLabel(endPostInitLabel);
               }

                gen.Emit(OpCodes.Ret);

                if (!String.IsNullOrEmpty(factoryName))
                {
                    MethodBuilder factoryMB = proxyTB.DefineMethod(factoryName, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, proxyTB, thisParamTypes);
                    CljILGen genf = new CljILGen(factoryMB.GetILGenerator());

                    LocalBuilder[] locals = new LocalBuilder[thisParamTypes.Length];
                    for (int i = 0; i < thisParamTypes.Length; i++)
                    {
                        locals[i] = genf.DeclareLocal(thisParamTypes[i]);
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);
                        genf.Emit(OpCodes.Stloc, locals[i]);
                    }

                    for (int i = 0; i < thisParamTypes.Length; i++)
                        genf.EmitLoadArg(i);                    // genf.Emit(OpCodes.Ldarg, i);

                    genf.EmitNew(cb);                           // genf.Emit(OpCodes.Newobj, cb);
                    genf.Emit(OpCodes.Ret);
                }
            }
        }
예제 #31
0
        public void DoEmit(RHC rhc, ObjExpr objx, CljILGen ilg, bool emitUnboxed)
        {
            GenContext.EmitDebugInfo(ilg, _sourceSpan);

            Label defaultLabel = ilg.DefineLabel();
            Label endLabel     = ilg.DefineLabel();

            SortedDictionary <int, Label> labels = new SortedDictionary <int, Label>();

            foreach (int i in _tests.Keys)
            {
                labels[i] = ilg.DefineLabel();
            }

            Type primExprType = Compiler.MaybePrimitiveType(_expr);

            if (_testType == _intKey)
            {
                EmitExprForInts(objx, ilg, primExprType, defaultLabel);
            }
            else
            {
                EmitExprForHashes(objx, ilg);
            }

            if (_switchType == _sparseKey)
            {
                Label[] la = labels.Values.ToArray <Label>();
                ilg.Emit(OpCodes.Switch, la);
                ilg.Emit(OpCodes.Br, defaultLabel);
            }
            else
            {
                Label[] la = new Label[(_high - _low) + 1];
                for (int i = _low; i <= _high; i++)
                {
                    la[i - _low] = labels.ContainsKey(i) ? labels[i] : defaultLabel;
                }
                ilg.EmitInt(_low);
                ilg.Emit(OpCodes.Sub);
                ilg.Emit(OpCodes.Switch, la);
                ilg.Emit(OpCodes.Br, defaultLabel);
            }

            foreach (int i in labels.Keys)
            {
                ilg.MarkLabel(labels[i]);
                if (_testType == _intKey)
                {
                    EmitThenForInts(objx, ilg, primExprType, _tests[i], _thens[i], defaultLabel, emitUnboxed);
                }
                else if ((bool)RT.contains(_skipCheck, i))
                {
                    EmitExpr(objx, ilg, _thens[i], emitUnboxed);
                }
                else
                {
                    EmitThenForHashes(objx, ilg, _tests[i], _thens[i], defaultLabel, emitUnboxed);
                }
                if (_thens[i].HasNormalExit())
                {
                    ilg.Emit(OpCodes.Br, endLabel);
                }
            }
            ilg.MarkLabel(defaultLabel);
            EmitExpr(objx, ilg, _defaultExpr, emitUnboxed);
            ilg.MarkLabel(endLabel);
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #32
0
        private static void EmitForwardingMethod(TypeBuilder proxyTB, 
            bool isStatic,
            FieldBuilder regularFB,
            FieldBuilder overloadFB,
            MethodSignature sig,
            ElseGenDelegate elseGen)
        {
            MethodAttributes attributes;
            CallingConventions conventions;

            if (isStatic)
            {
                attributes = MethodAttributes.Public | MethodAttributes.Static;
                conventions = CallingConventions.Standard;
            }
            else
            {
                attributes = MethodAttributes.Public | MethodAttributes.Virtual;
                conventions = CallingConventions.HasThis;
            }

            MethodBuilder mb = proxyTB.DefineMethod(sig.Name, attributes, conventions, sig.ReturnType, sig.ParamTypes);
            CljILGen gen = new CljILGen(mb.GetILGenerator());

            Label foundLabel = gen.DefineLabel();
            Label elseLabel = gen.DefineLabel();
            Label endLabel = gen.DefineLabel();

            if (sig.ParamTypes.Length > 18)
                elseGen(gen);
            else
            {

                if (overloadFB != null)
                {
                    EmitGetVar(gen, overloadFB);
                    gen.Emit(OpCodes.Dup);
                    gen.Emit(OpCodes.Brtrue_S, foundLabel);
                    gen.Emit(OpCodes.Pop);
                }
                EmitGetVar(gen, regularFB);
                gen.Emit(OpCodes.Dup);
                gen.Emit(OpCodes.Brfalse_S, elseLabel);

                if (overloadFB != null)
                    gen.MarkLabel(foundLabel);
                gen.Emit(OpCodes.Castclass, typeof(IFn));

                if (!isStatic)
                    gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);

                for (int i = 0; i < sig.ParamTypes.Length; i++)
                {
                    gen.EmitLoadArg(isStatic ? i : i + 1);                 // gen.Emit(OpCodes.Ldarg, i + 1);
                    if (sig.ParamTypes[i].IsValueType)
                        gen.Emit(OpCodes.Box, sig.ParamTypes[i]);

                }
                gen.EmitCall(Compiler.Methods_IFn_invoke[sig.ParamTypes.Length + (isStatic ? 0 : 1)]);
                //gen.Emit(OpCodes.Call, Compiler.Methods_IFn_invoke[sig.ParamTypes.Length + (isStatic ? 0 : 1)]);
                if (sig.ReturnType == typeof(void))
                    gen.Emit(OpCodes.Pop);
                else if (sig.ReturnType.IsValueType)
                    gen.Emit(OpCodes.Unbox_Any,sig.ReturnType);
                gen.Emit(OpCodes.Br_S, endLabel);

                gen.MarkLabel(elseLabel);
                gen.Emit(OpCodes.Pop);
                elseGen(gen);

                gen.MarkLabel(endLabel);
                gen.Emit(OpCodes.Ret);
            }
        }
예제 #33
0
        protected static void EmitHasArityMethod(TypeBuilder tb, IList<int> arities, bool isVariadic, int reqArity)
        {
            // TODO: Convert to a Switch instruction
            MethodBuilder mb = tb.DefineMethod(
                "HasArity",
                MethodAttributes.ReuseSlot | MethodAttributes.Public | MethodAttributes.Virtual,
                typeof(bool),
                new Type[] { typeof(int) });

            CljILGen gen = new CljILGen(mb.GetILGenerator());

            Label falseLabel = gen.DefineLabel();
            Label trueLabel = gen.DefineLabel();

            if (isVariadic)
            {
                gen.EmitLoadArg(1);
                gen.EmitInt(reqArity);
                gen.Emit(OpCodes.Bge, trueLabel);
            }

            if (arities != null)
            {
                foreach (int i in arities)
                {
                    gen.EmitLoadArg(1);
                    gen.EmitInt(i);
                    gen.Emit(OpCodes.Beq, trueLabel);
                }
            }

            gen.MarkLabel(falseLabel);
            gen.EmitBoolean(false);
            gen.Emit(OpCodes.Ret);

            gen.MarkLabel(trueLabel);
            gen.EmitBoolean(true);
            gen.Emit(OpCodes.Ret);
        }
예제 #34
0
        static void EmitGetVar(CljILGen gen, FieldBuilder fb)
        {
            Label falseLabel = gen.DefineLabel();
            Label endLabel = gen.DefineLabel();

            gen.EmitFieldGet(fb);                       // gen.Emit(OpCodes.Ldsfld,fb);
            gen.Emit(OpCodes.Dup);
            gen.EmitCall(Method_Var_isBound);           // gen.Emit(OpCodes.Call, Method_Var_IsBound);
            gen.Emit(OpCodes.Brfalse_S,falseLabel);
            gen.Emit(OpCodes.Call,Method_Var_get);
            gen.Emit(OpCodes.Br_S,endLabel);
            gen.MarkLabel(falseLabel);
            gen.Emit(OpCodes.Pop);
            gen.EmitNull();                             // gen.Emit(OpCodes.Ldnull);
            gen.MarkLabel(endLabel);
        }
예제 #35
0
        void EmitProto(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            Label onLabel = ilg.DefineLabel();
            Label callLabel = ilg.DefineLabel();
            Label endLabel = ilg.DefineLabel();

            Var v = ((VarExpr)_fexpr).Var;

            Expr e = (Expr)_args.nth(0);
            e.Emit(RHC.Expression, objx, ilg);               // target
            ilg.Emit(OpCodes.Dup);                               // target, target

            LocalBuilder targetTemp = ilg.DeclareLocal(typeof(Object));
            GenContext.SetLocalName(targetTemp, "target");
            ilg.Emit(OpCodes.Stloc,targetTemp);                  // target

            ilg.Emit(OpCodes.Call,Compiler.Method_Util_classOf);          // class
            ilg.EmitLoadArg(0);                                  // class, this
            ilg.EmitFieldGet(objx.CachedTypeField(_siteIndex));  // class, cached-class
            ilg.Emit(OpCodes.Beq, callLabel);                    //
            if (_protocolOn != null)
            {
                ilg.Emit(OpCodes.Ldloc,targetTemp);              // target
                ilg.Emit(OpCodes.Isinst, _protocolOn);           // null or target
                ilg.Emit(OpCodes.Ldnull);                        // (null or target), null
                ilg.Emit(OpCodes.Cgt_Un);                        // (0 or 1)
                ilg.Emit(OpCodes.Brtrue, onLabel);
            }
            ilg.Emit(OpCodes.Ldloc,targetTemp);                  // target
            ilg.Emit(OpCodes.Call,Compiler.Method_Util_classOf);          // class

            LocalBuilder typeTemp = ilg.DeclareLocal(typeof(Type));
            GenContext.SetLocalName(typeTemp, "type");
            ilg.Emit(OpCodes.Stloc,typeTemp);                    //    (typeType <= class)

            ilg.EmitLoadArg(0);                                  // this

            ilg.Emit(OpCodes.Ldloc,typeTemp);                    // this, class
            ilg.EmitFieldSet(objx.CachedTypeField(_siteIndex));  //

            ilg.MarkLabel(callLabel);

            objx.EmitVar(ilg,v);                              // var
            ilg.Emit(OpCodes.Call,Compiler.Method_Var_getRawRoot);         // proto-fn
            ilg.Emit(OpCodes.Castclass, typeof(AFunction));

            ilg.Emit(OpCodes.Ldloc,targetTemp);                  // proto-fn, target

            EmitArgsAndCall(1,rhc,objx,ilg);
            ilg.Emit(OpCodes.Br,endLabel);

            ilg.MarkLabel(onLabel);
            ilg.Emit(OpCodes.Ldloc,targetTemp);                  // target
            if ( _protocolOn != null )
            {
                ilg.Emit(OpCodes.Castclass, _protocolOn);
                MethodExpr.EmitTypedArgs(objx, ilg, _onMethod.GetParameters(), RT.subvec(_args, 1, _args.count()));
                //if (rhc == RHC.Return)
                //{
                //    ObjMethod2 method = (ObjMethod)Compiler.MethodVar.deref();
                //    method.EmitClearLocals(context);
                //}
                ilg.Emit(OpCodes.Callvirt, _onMethod);
                HostExpr.EmitBoxReturn(objx, ilg, _onMethod.ReturnType);
            }
            ilg.MarkLabel(endLabel);
        }
예제 #36
0
        public virtual void Emit(ObjExpr fn, TypeBuilder tb)
        {
            MethodBuilder mb = tb.DefineMethod(MethodName, MethodAttributes.Public, ReturnType, ArgTypes);

            CljILGen ilg = new CljILGen(mb.GetILGenerator());
            Label loopLabel = ilg.DefineLabel();

            GenContext.EmitDebugInfo(ilg, SpanMap);

            try
            {
                Var.pushThreadBindings(RT.map(Compiler.LoopLabelVar,loopLabel,Compiler.MethodVar,this));
                ilg.MarkLabel(loopLabel);
                Body.Emit(RHC.Return,fn,ilg);
                ilg.Emit(OpCodes.Ret);
            }
            finally
            {
                Var.popThreadBindings();
            }
        }