コード例 #1
0
        private ConstructorBuilder EmitFieldOnlyConstructor(TypeBuilder fnTB, Type baseType)
        {
            Type[] ctorTypes    = CtorTypes();
            Type[] altCtorTypes = new Type[ctorTypes.Length - _altCtorDrops];
            for (int i = 0; i < altCtorTypes.Length; i++)
            {
                altCtorTypes[i] = ctorTypes[i];
            }

            ConstructorBuilder cb  = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
            CljILGen           gen = new CljILGen(cb.GetILGenerator());

            //Call full constructor
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < altCtorTypes.Length; i++)
            {
                gen.EmitLoadArg(i + 1);
            }

            for (int i = 0; i < _altCtorDrops; i++)
            {
                gen.EmitNull();
            }

            gen.Emit(OpCodes.Call, _ctorInfo);

            gen.Emit(OpCodes.Ret);
            return(cb);
        }
コード例 #2
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
        private void EmitMetaFunctions(TypeBuilder fnTB)
        {
            // IPersistentMap meta()
            MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes);
            CljILGen gen = new CljILGen(metaMB.GetILGenerator());
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitFieldGet(MetaField);
            }
            else
                gen.EmitNull();
            gen.Emit(OpCodes.Ret);

            // IObj withMeta(IPersistentMap)
            MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) });
            gen = new CljILGen(withMB.GetILGenerator());

            if (SupportsMeta)
            {
                gen.EmitLoadArg(1);   // meta arg
                foreach (FieldBuilder fb in ClosedOverFields)
                {
                    gen.EmitLoadArg(0);
                    gen.MaybeEmitVolatileOp(fb);
                    gen.EmitFieldGet(fb);
                }

                gen.EmitNew(CtorInfo);
            }
            else
                gen.EmitLoadArg(0);  //this
            gen.Emit(OpCodes.Ret);
        }
コード例 #3
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                ilg.Emit(OpCodes.Ldarg_0); // this
                FieldBuilder fb = ClosedOverFieldsMap[lb];
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Ldfld, fb);
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
                // TODO: ONCEONLY?
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
            }
        }
コード例 #4
0
ファイル: ObjExpr.cs プロジェクト: redchew-fork/clojure-clr
        private ConstructorBuilder EmitConstructorForDefType(TypeBuilder fnTB, Type baseType)
        {
            ConstructorBuilder cb  = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
            CljILGen           gen = new CljILGen(cb.GetILGenerator());

            GenContext.EmitDebugInfo(gen, SpanMap);

            // Pass closed-overs to base class ctor

            gen.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
            int a = 0;

            for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
            {
                //LocalBinding lb = (LocalBinding)s.first();
                //FieldBuilder fb = _closedOverFields[a];
                //bool isVolatile = IsVolatile(_closedOverFieldsToBindingsMap[fb]);

                gen.EmitLoadArg(a + 1);         // gen.Emit(OpCodes.Ldarg, a + 1);
            }
            gen.Emit(OpCodes.Call, BaseClassClosedOverCtor);

            gen.Emit(OpCodes.Ret);

            return(cb);
        }
コード例 #5
0
ファイル: ObjExpr.cs プロジェクト: redchew-fork/clojure-clr
        private void EmitFieldOnlyConstructorWithoutHash(TypeBuilder fnTB)
        {
            Type[] ctorTypes    = CtorTypes();
            Type[] altCtorTypes = new Type[ctorTypes.Length - 2];
            for (int i = 0; i < altCtorTypes.Length; i++)
            {
                altCtorTypes[i] = ctorTypes[i];
            }

            ConstructorBuilder cb  = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
            CljILGen           gen = new CljILGen(cb.GetILGenerator());

            //Call full constructor
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < altCtorTypes.Length; i++)
            {
                gen.EmitLoadArg(i + 1);
            }

            gen.Emit(OpCodes.Ldc_I4_0);        // __hash
            gen.Emit(OpCodes.Ldc_I4_0);        // __hasheq

            gen.Emit(OpCodes.Call, CtorInfo);

            gen.Emit(OpCodes.Ret);
        }
コード例 #6
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);
        }
コード例 #7
0
        private void DefineBaseClassClosedOverConstructors(Type super, TypeBuilder tb)
        {
            // ctor that takes closed-overs and does nothing
            if (CtorTypes().Length > 0)
            {
                ConstructorBuilder cb  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
                CljILGen           ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));

                // store closed-overs in their fields
                int a = 0;

                for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
                {
                    FieldBuilder fb         = ClosedOverFields[a];
                    bool         isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]);

                    ilg.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
                    ilg.EmitLoadArg(a + 1);         // gen.Emit(OpCodes.Ldarg, a + 1);
                    ilg.MaybeEmitVolatileOp(isVolatile);
                    ilg.Emit(OpCodes.Stfld, fb);
                }
                ilg.Emit(OpCodes.Ret);

                if (AltCtorDrops > 0)
                {
                    Type[] ctorTypes = CtorTypes();
                    int    newLen    = ctorTypes.Length - AltCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                        {
                            altCtorTypes[i] = ctorTypes[i];
                        }
                        ConstructorBuilder cb2  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen           ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                        {
                            ilg2.EmitLoadArg(i + 1);
                        }
                        for (int i = 0; i < AltCtorDrops; i++)
                        {
                            ilg2.EmitNull();
                        }
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }
        }
コード例 #8
0
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                if (_fnMode == FnMode.Full)
                {
                    ilg.Emit(OpCodes.Ldarg_0); // this
                    ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]);
                    if (primType != null)
                    {
                        HostExpr.EmitBoxReturn(this, ilg, primType);
                    }
                    // TODO: ONCEONLY?
                }
                else // FnMode.Light
                {
                    ilg.Emit(OpCodes.Ldarg_0); // this
                    ilg.Emit(OpCodes.Castclass, typeof(IFnClosure));
                    ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure);
                    ilg.EmitFieldGet(Compiler.Field_Closure_Locals);
                    ilg.EmitInt(lb.Index);
                    ilg.EmitLoadElement(typeof(Object));
                }
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                {
                    HostExpr.EmitBoxReturn(this, ilg, primType);
                }
            }
        }
コード例 #9
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);
        }
コード例 #10
0
ファイル: ObjExpr.cs プロジェクト: redchew-fork/clojure-clr
        private ConstructorBuilder EmitConstructorForNonDefType(TypeBuilder fnTB, Type baseType)
        {
            ConstructorBuilder cb  = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
            CljILGen           gen = new CljILGen(cb.GetILGenerator());

            GenContext.EmitDebugInfo(gen, SpanMap);

            //Call base constructor
            ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, null, Type.EmptyTypes, null);

            if (baseCtorInfo == null)
            {
                throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName);
            }

            gen.EmitLoadArg(0);
            gen.Emit(OpCodes.Call, baseCtorInfo);

            // Store Meta
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitLoadArg(1);
                gen.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                gen.EmitFieldSet(MetaField);
            }

            // store closed-overs in their fields
            int a      = 0;
            int offset = !SupportsMeta ? 1 : 2;

            for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
            {
                //LocalBinding lb = (LocalBinding)s.first();
                FieldBuilder fb         = ClosedOverFields[a];
                bool         isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]);

                gen.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
                gen.EmitLoadArg(a + offset);    // gen.Emit(OpCodes.Ldarg, a + 1);
                gen.MaybeEmitVolatileOp(isVolatile);
                gen.Emit(OpCodes.Stfld, fb);
            }
            gen.Emit(OpCodes.Ret);
            return(cb);
        }
コード例 #11
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
        private ConstructorBuilder EmitNonMetaConstructor(TypeBuilder fnTB, Type baseType)
        {
            Type[] ctorTypes = CtorTypes();
            Type[] noMetaCtorTypes = new Type[ctorTypes.Length - 1];
            for (int i = 1; i < ctorTypes.Length; i++)
                noMetaCtorTypes[i - 1] = ctorTypes[i];

            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, noMetaCtorTypes);
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            gen.EmitLoadArg(0);
            gen.EmitNull();     // null meta
            for (int i = 0; i < noMetaCtorTypes.Length; i++)
                gen.EmitLoadArg(i + 1);
            gen.Emit(OpCodes.Call, CtorInfo);
            gen.Emit(OpCodes.Ret);

            return cb;
        }
コード例 #12
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);
        }
コード例 #13
0
ファイル: ObjExpr.cs プロジェクト: makufiru/clojure-clr
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         ilg.Emit(OpCodes.Ldarg_0); // this
         FieldBuilder fb = ClosedOverFieldsMap[lb];
         ilg.MaybeEmitVolatileOp(IsVolatile(lb));
         ilg.Emit(OpCodes.Ldfld, fb);
     }
     else if (lb.IsArg)
     {
         //int argOffset = IsStatic ? 0 : 1;
         //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset);
         ilg.EmitLoadArg(lb.Index);
     }
     else if (lb.IsThis)
     {
         ilg.EmitLoadArg(0);
     }
     else
         ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
 }
コード例 #14
0
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         if (_fnMode == FnMode.Full)
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             ilg.Emit(OpCodes.Ldfld, _closedOverFieldsMap[lb]);
         }
         else
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             ilg.Emit(OpCodes.Castclass, typeof(IFnClosure));
             ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure);
             ilg.EmitFieldGet(Compiler.Field_Closure_Locals);
             ilg.EmitInt(lb.Index);
             ilg.EmitLoadElement(typeof(Object));
             if (lb.PrimitiveType != null)
             {
                 ilg.Emit(OpCodes.Unbox, lb.PrimitiveType);
             }
         }
     }
     else if (lb.IsArg)
     {
         //int argOffset = IsStatic ? 0 : 1;
         //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset);
         ilg.EmitLoadArg(lb.Index);
     }
     else if (lb.IsThis)
     {
         ilg.EmitLoadArg(0);
     }
     else
     {
         ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
     }
 }
コード例 #15
0
ファイル: ObjExpr.cs プロジェクト: aaronc/clojure-clr
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         if (_fnMode == FnMode.Full)
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             FieldBuilder fb = _closedOverFieldsMap[lb];
             ilg.MaybeEmitVolatileOp(IsVolatile(lb));
             ilg.Emit(OpCodes.Ldfld, fb);
         }
         else
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             ilg.Emit(OpCodes.Castclass, typeof(IFnClosure));
             ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure);
             ilg.EmitFieldGet(Compiler.Field_Closure_Locals);
             ilg.EmitInt(lb.Index);
             ilg.EmitLoadElement(typeof(Object));
             if (lb.PrimitiveType != null)
                 ilg.Emit(OpCodes.Unbox, lb.PrimitiveType);
         }
     }
     else if (lb.IsArg)
     {
         //int argOffset = IsStatic ? 0 : 1;
         //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset);
         ilg.EmitLoadArg(lb.Index);
     }
     else if (lb.IsThis)
     {
         ilg.EmitLoadArg(0);
     }
     else
         ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
 }
コード例 #16
0
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */

        // TODO: Preparse method heads to pick up signatures, implement those methods as abstract or as NotImpelmented so that Reflection can pick up calls during compilation and avoide a callsite.
        static Type CompileStub(GenContext context, Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName + RT.nextID(), TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding    lb     = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                if (!ret.IsMutable(lb))
                {
                    access |= FieldAttributes.InitOnly;
                }

                Type fieldType = lb.PrimitiveType ?? typeof(Object);

                if (ret.IsVolatile(lb))
                {
                    tb.DefineField(lb.Name, fieldType, new Type[] { typeof(IsVolatile) }, Type.EmptyTypes, access);
                }
                else
                {
                    tb.DefineField(lb.Name, fieldType, access);
                }
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                CljILGen           ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);


                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int    newLen    = ctorTypes.Length - ret._altCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                        {
                            altCtorTypes[i] = ctorTypes[i];
                        }
                        ConstructorBuilder cb2  = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen           ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                        {
                            ilg2.EmitLoadArg(i + 1);
                        }
                        for (int i = 0; i < ret._altCtorDrops; i++)
                        {
                            ilg2.EmitNull();
                        }
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();

            //Compiler.RegisterDuplicateType(t);
            return(t);
        }
コード例 #17
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
 internal void EmitUnboxedLocal(CljILGen ilg, LocalBinding lb)
 {
     if (Closes.containsKey(lb))
     {
         ilg.Emit(OpCodes.Ldarg_0); // this
         FieldBuilder fb = _closedOverFieldsMap[lb];
         ilg.MaybeEmitVolatileOp(IsVolatile(lb));
         ilg.Emit(OpCodes.Ldfld, fb);
     }
     else if (lb.IsArg)
     {
         //int argOffset = IsStatic ? 0 : 1;
         //ilg.Emit(OpCodes.Ldarg, lb.Index + argOffset);
         ilg.EmitLoadArg(lb.Index);
     }
     else if (lb.IsThis)
     {
         ilg.EmitLoadArg(0);
     }
     else
         ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
 }
コード例 #18
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        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);
        }
コード例 #19
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private void EmitMetaFunctions(TypeBuilder fnTB)
        {
            // IPersistentMap meta()
            MethodBuilder metaMB = fnTB.DefineMethod("meta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IPersistentMap), Type.EmptyTypes);
            CljILGen gen = new CljILGen(metaMB.GetILGenerator());
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitFieldGet(_metaField);
            }
            else
                gen.EmitNull();
            gen.Emit(OpCodes.Ret);

            // IObj withMeta(IPersistentMap)
            MethodBuilder withMB = fnTB.DefineMethod("withMeta", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.ReuseSlot, typeof(IObj), new Type[] { typeof(IPersistentMap) });
            gen = new CljILGen(withMB.GetILGenerator());

            if (SupportsMeta)
            {
                gen.EmitLoadArg(1);   // meta arg
                foreach (FieldBuilder fb in _closedOverFields)
                {
                    gen.EmitLoadArg(0);
                    gen.MaybeEmitVolatileOp(fb);
                    gen.EmitFieldGet(fb);
                }

                gen.EmitNew(_ctorInfo);
            }
            else
                gen.EmitLoadArg(0);  //this
            gen.Emit(OpCodes.Ret);
        }
コード例 #20
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private ConstructorBuilder EmitConstructor(TypeBuilder fnTB, Type baseType)
        {
            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            GenContext.EmitDebugInfo(gen, SpanMap);

            //Call base constructor
            ConstructorInfo baseCtorInfo = baseType.GetConstructor(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public,null,Type.EmptyTypes,null);
            if (baseCtorInfo == null)
                throw new InvalidOperationException("Unable to find default constructor for " + baseType.FullName);

            gen.EmitLoadArg(0);
            gen.Emit(OpCodes.Call, baseCtorInfo);

            // Store Meta
            if (SupportsMeta)
            {
                gen.EmitLoadArg(0);
                gen.EmitLoadArg(1);
                gen.Emit(OpCodes.Castclass, typeof(IPersistentMap));
                gen.EmitFieldSet(_metaField);
            }

            // store closed-overs in their fields
            int a = 0;
            int offset = !SupportsMeta ? 1 : 2;

            for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
            {
                //LocalBinding lb = (LocalBinding)s.first();
                FieldBuilder fb = _closedOverFields[a];
                bool isVolatile = IsVolatile(_closedOverFieldsToBindingsMap[fb]);

                gen.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
                gen.EmitLoadArg(a + offset);         // gen.Emit(OpCodes.Ldarg, a + 1);
                gen.MaybeEmitVolatileOp(isVolatile);
                gen.Emit(OpCodes.Stfld, fb);
            }
            gen.Emit(OpCodes.Ret);
            return cb;
        }
コード例 #21
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        private static void CreateSuperCall(TypeBuilder proxyTB, Symbol p, MethodInfo mi)
        {
            Type[] paramTypes = CreateTypeArray(mi.GetParameters());

            MethodBuilder mb = proxyTB.DefineMethod(p.Name, MethodAttributes.Public, CallingConventions.HasThis, mi.ReturnType, paramTypes);
            CljILGen gen = new CljILGen(mb.GetILGenerator());
            gen.EmitLoadArg(0);                             // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < paramTypes.Length; i++)
                gen.EmitLoadArg(i + 1);                     // gen.Emit(OpCodes.Ldarg, i + 1);
            gen.Emit(OpCodes.Call, mi);                     // not gen.EmitCall(mi); -- we need call versus callvirt
            gen.Emit(OpCodes.Ret);
        }
コード例 #22
0
        private void DefineBaseClassClosedOverConstructors(Type super, TypeBuilder tb)
        {
            // ctor that takes closed-overs and does nothing
            if (CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis,CtorTypes());
                CljILGen ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));

                // store closed-overs in their fields
                int a = 0;

                for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
                {
                    FieldBuilder fb = ClosedOverFields[a];
                    bool isVolatile = IsVolatile(ClosedOverFieldsToBindingsMap[fb]);

                    ilg.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
                    ilg.EmitLoadArg(a + 1);         // gen.Emit(OpCodes.Ldarg, a + 1);
                    ilg.MaybeEmitVolatileOp(isVolatile);
                    ilg.Emit(OpCodes.Stfld, fb);
                }
                ilg.Emit(OpCodes.Ret);

                if (AltCtorDrops > 0)
                {
                    Type[] ctorTypes = CtorTypes();
                    int newLen = ctorTypes.Length - AltCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                            altCtorTypes[i] = ctorTypes[i];
                        ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                            ilg2.EmitLoadArg(i + 1);
                        for (int i = 0; i < AltCtorDrops; i++)
                            ilg2.EmitNull();
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }
        }
コード例 #23
0
        protected override void EmitStatics(TypeBuilder tb)
        {
            if (IsDefType)
            {
                // getBasis()
                {
                    MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes);
                    CljILGen ilg = new CljILGen(mbg.GetILGenerator());
                    EmitValue(HintedFields, ilg);
                    ilg.Emit(OpCodes.Ret);
                }

                if (Fields.count() > HintedFields.count())
                {
                    // create(IPersistentMap)
                    MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) });
                    CljILGen gen = new CljILGen(mbc.GetILGenerator());

                    LocalBuilder kwLocal = gen.DeclareLocal(typeof(Keyword));
                    List<LocalBuilder> locals = new List<LocalBuilder>();
                    for (ISeq s = RT.seq(HintedFields); s != null; s = s.next())
                    {
                        string bName = ((Symbol)s.first()).Name;
                        Type t = Compiler.TagType(Compiler.TagOf(s.first()));

                        // local_kw = Keyword.intern(bname)
                        // local_i = arg_0.valAt(kw,null)
                        gen.EmitLoadArg(0);
                        gen.EmitString(bName);
                        gen.EmitCall(Compiler.Method_Keyword_intern_string);
                        gen.Emit(OpCodes.Dup);
                        gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex);
                        gen.EmitNull();
                        gen.EmitCall(Compiler.Method_IPersistentMap_valAt2);
                        LocalBuilder lb = gen.DeclareLocal(t);
                        locals.Add(lb);
                        if (t.IsPrimitive)
                            gen.EmitUnbox(t);
                        gen.Emit(OpCodes.Stloc, lb.LocalIndex);

                        // arg_0 = arg_0.without(local_kw);
                        gen.EmitLoadArg(0);
                        gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex);
                        gen.EmitCall(Compiler.Method_IPersistentMap_without);
                        gen.EmitStoreArg(0);
                    }

                    foreach (LocalBuilder lb in locals)
                        gen.Emit(OpCodes.Ldloc, lb.LocalIndex);
                    gen.EmitNull();
                    gen.EmitLoadArg(0);
                    gen.EmitCall(Compiler.Method_RT_seqOrElse);
                    gen.EmitNew(CtorInfo);

                    gen.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #24
0
ファイル: ObjExpr.cs プロジェクト: clojure/clojure-clr
        private void EmitFieldOnlyConstructorWithoutHash(TypeBuilder fnTB)
        {
            Type[] ctorTypes = CtorTypes();
            Type[] altCtorTypes = new Type[ctorTypes.Length - 2];
            for (int i = 0; i < altCtorTypes.Length; i++)
                altCtorTypes[i] = ctorTypes[i];

            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            //Call full constructor
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < altCtorTypes.Length; i++)
                gen.EmitLoadArg(i + 1);

            gen.Emit(OpCodes.Ldc_I4_0);        // __hash
            gen.Emit(OpCodes.Ldc_I4_0);        // __hasheq

            gen.Emit(OpCodes.Call, CtorInfo);

            gen.Emit(OpCodes.Ret);
        }
コード例 #25
0
ファイル: ObjExpr.cs プロジェクト: telefunkenvf14/clojure-clr
        private ConstructorBuilder EmitConstructorForDefType(TypeBuilder fnTB, Type baseType)
        {
            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, CtorTypes());
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            GenContext.EmitDebugInfo(gen, SpanMap);

            // Pass closed-overs to base class ctor

            gen.EmitLoadArg(0);             // gen.Emit(OpCodes.Ldarg_0);
            int a = 0;
            for (ISeq s = RT.keys(Closes); s != null; s = s.next(), a++)
            {
                //LocalBinding lb = (LocalBinding)s.first();
                //FieldBuilder fb = _closedOverFields[a];
                //bool isVolatile = IsVolatile(_closedOverFieldsToBindingsMap[fb]);

                gen.EmitLoadArg(a + 1);         // gen.Emit(OpCodes.Ldarg, a + 1);
            }
            gen.Emit(OpCodes.Call, _baseClassClosedOverCtor);

            gen.Emit(OpCodes.Ret);

            return cb;
        }
コード例 #26
0
        protected override void EmitStatics(TypeBuilder tb)
        {
            if (IsDefType)
            {
                // getBasis()
                {
                    MethodBuilder mbg = tb.DefineMethod("getBasis", MethodAttributes.Public | MethodAttributes.Static, typeof(IPersistentVector), Type.EmptyTypes);
                    CljILGen      ilg = new CljILGen(mbg.GetILGenerator());
                    EmitValue(HintedFields, ilg);
                    ilg.Emit(OpCodes.Ret);
                }

                if (Fields.count() > HintedFields.count())
                {
                    // create(IPersistentMap)
                    MethodBuilder mbc = tb.DefineMethod("create", MethodAttributes.Public | MethodAttributes.Static, tb, new Type[] { typeof(IPersistentMap) });
                    CljILGen      gen = new CljILGen(mbc.GetILGenerator());

                    LocalBuilder        kwLocal = gen.DeclareLocal(typeof(Keyword));
                    List <LocalBuilder> locals  = new List <LocalBuilder>();
                    for (ISeq s = RT.seq(HintedFields); s != null; s = s.next())
                    {
                        string bName = ((Symbol)s.first()).Name;
                        Type   t     = Compiler.TagType(Compiler.TagOf(s.first()));

                        // local_kw = Keyword.intern(bname)
                        // local_i = arg_0.valAt(kw,null)
                        gen.EmitLoadArg(0);
                        gen.EmitString(bName);
                        gen.EmitCall(Compiler.Method_Keyword_intern_string);
                        gen.Emit(OpCodes.Dup);
                        gen.Emit(OpCodes.Stloc, kwLocal.LocalIndex);
                        gen.EmitNull();
                        gen.EmitCall(Compiler.Method_IPersistentMap_valAt2);
                        LocalBuilder lb = gen.DeclareLocal(t);
                        locals.Add(lb);
                        if (t.IsPrimitive)
                        {
                            gen.EmitUnbox(t);
                        }
                        gen.Emit(OpCodes.Stloc, lb.LocalIndex);

                        // arg_0 = arg_0.without(local_kw);
                        gen.EmitLoadArg(0);
                        gen.Emit(OpCodes.Ldloc, kwLocal.LocalIndex);
                        gen.EmitCall(Compiler.Method_IPersistentMap_without);
                        gen.EmitStoreArg(0);
                    }

                    foreach (LocalBuilder lb in locals)
                    {
                        gen.Emit(OpCodes.Ldloc, lb.LocalIndex);
                    }
                    gen.EmitNull();             // __meta
                    gen.EmitLoadArg(0);         // __extmap
                    gen.EmitCall(Compiler.Method_RT_seqOrElse);
                    gen.Emit(OpCodes.Ldc_I4_0); // __hash
                    gen.Emit(OpCodes.Ldc_I4_0); // __hasheq
                    gen.EmitNew(CtorInfo);

                    gen.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #27
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        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);
                }
            }
        }
コード例 #28
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);
        }
コード例 #29
0
        /***
         * Current host interop uses reflection, which requires pre-existing classes
         * Work around this by:
         * Generate a stub class that has the same interfaces and fields as the class we are generating.
         * Use it as a type hint for this, and bind the simple name of the class to this stub (in resolve etc)
         * Unmunge the name (using a magic prefix) on any code gen for classes
         */
        // TODO: Preparse method heads to pick up signatures, implement those methods as abstract or as NotImpelmented so that Reflection can pick up calls during compilation and avoide a callsite.
        static Type CompileStub(GenContext context, Type super, NewInstanceExpr ret, Type[] interfaces, Object frm)
        {
            //GenContext context = Compiler.CompilerContextVar.get() as GenContext ?? GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false);
            //GenContext context = Compiler.IsCompiling ? Compiler.CompilerContextVar.get() as GenContext : GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false);
            //context = GenContext.CreateWithExternalAssembly("stub" + RT.nextID().ToString(), ".dll", false);
            TypeBuilder tb = context.ModuleBuilder.DefineType(Compiler.CompileStubPrefix + "." + ret.InternalName + RT.nextID(), TypeAttributes.Public | TypeAttributes.Abstract, super, interfaces);

            tb.DefineDefaultConstructor(MethodAttributes.Public);

            // instance fields for closed-overs
            for (ISeq s = RT.keys(ret.Closes); s != null; s = s.next())
            {
                LocalBinding lb = (LocalBinding)s.first();
                FieldAttributes access = FieldAttributes.Public;

                // TODO: FIgure out Volatile
                if (!ret.IsVolatile(lb))
                    access |= FieldAttributes.InitOnly;

                if (lb.PrimitiveType != null)
                    tb.DefineField(lb.Name, lb.PrimitiveType, access);
                else
                    tb.DefineField(lb.Name, typeof(Object), access);
            }

            // ctor that takes closed-overs and does nothing
            if (ret.CtorTypes().Length > 0)
            {
                ConstructorBuilder cb = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, ret.CtorTypes());
                CljILGen ilg = new CljILGen(cb.GetILGenerator());
                ilg.EmitLoadArg(0);
                ilg.Emit(OpCodes.Call, super.GetConstructor(Type.EmptyTypes));
                ilg.Emit(OpCodes.Ret);

                if (ret._altCtorDrops > 0)
                {
                    Type[] ctorTypes = ret.CtorTypes();
                    int newLen = ctorTypes.Length - ret._altCtorDrops;
                    if (newLen > 0)
                    {
                        Type[] altCtorTypes = new Type[newLen];
                        for (int i = 0; i < altCtorTypes.Length; i++)
                            altCtorTypes[i] = ctorTypes[i];
                        ConstructorBuilder cb2 = tb.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
                        CljILGen ilg2 = new CljILGen(cb2.GetILGenerator());
                        ilg2.EmitLoadArg(0);
                        for (int i = 0; i < newLen; i++)
                            ilg2.EmitLoadArg(i + 1);
                        for (int i = 0; i < ret._altCtorDrops; i++)
                            ilg2.EmitNull();
                        ilg2.Emit(OpCodes.Call, cb);
                        ilg2.Emit(OpCodes.Ret);
                    }
                }
            }

            Type t = tb.CreateType();
            //Compiler.RegisterDuplicateType(t);
            return t;
        }
コード例 #30
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private ConstructorBuilder EmitFieldOnlyConstructor(TypeBuilder fnTB, Type baseType)
        {
            Type[] ctorTypes = CtorTypes();
            Type[] altCtorTypes = new Type[ctorTypes.Length - _altCtorDrops];
            for (int i = 0; i < altCtorTypes.Length; i++)
                altCtorTypes[i] = ctorTypes[i];

            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, altCtorTypes);
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            //Call full constructor
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < altCtorTypes.Length; i++)
                gen.EmitLoadArg(i + 1);

            for (int i = 0; i < _altCtorDrops; i++)
                gen.EmitNull();

            gen.Emit(OpCodes.Call, _ctorInfo);

            gen.Emit(OpCodes.Ret);
            return cb;
        }
コード例 #31
0
ファイル: FnMethod.cs プロジェクト: clojure/clojure-clr
        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);
            }
        }
コード例 #32
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        private ConstructorBuilder EmitNonMetaConstructor(TypeBuilder fnTB, Type baseType)
        {
            Type[] ctorTypes = CtorTypes();
            Type[] noMetaCtorTypes = new Type[ctorTypes.Length - 1];
            for (int i = 1; i < ctorTypes.Length; i++)
                noMetaCtorTypes[i - 1] = ctorTypes[i];

            ConstructorBuilder cb = fnTB.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, noMetaCtorTypes);
            CljILGen gen = new CljILGen(cb.GetILGenerator());

            gen.EmitLoadArg(0);
            gen.EmitNull();     // null meta
            for (int i = 0; i < noMetaCtorTypes.Length; i++)
                gen.EmitLoadArg(i + 1);
            gen.Emit(OpCodes.Call, _ctorInfo);
            gen.Emit(OpCodes.Ret);

            return cb;
        }
コード例 #33
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        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);
        }
コード例 #34
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                ilg.Emit(OpCodes.Ldarg_0); // this
                FieldBuilder fb = _closedOverFieldsMap[lb];
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Ldfld, fb);
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
                // TODO: ONCEONLY?
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
            }
        }
コード例 #35
0
ファイル: FnMethod.cs プロジェクト: nasser/Clojure.Runtime
        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);
        }
コード例 #36
0
ファイル: ObjExpr.cs プロジェクト: EricThorsen/clojure-clr
        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);
        }
コード例 #37
0
ファイル: GenProxy.cs プロジェクト: stuman08/clojure-clr
        private static FieldBuilder AddIProxyMethods(TypeBuilder proxyTB)
        {
            FieldBuilder fb = proxyTB.DefineField(
                _methodMapFieldName,
                typeof(IPersistentMap),
                 FieldAttributes.Private);

            MethodBuilder initMb = proxyTB.DefineMethod(
                "__initClojureFnMappings",
                 MethodAttributes.Public|MethodAttributes.Virtual|MethodAttributes.HideBySig,
                 typeof(void),
                 new Type[] { typeof(IPersistentMap) });
            CljILGen gen = new CljILGen(initMb.GetILGenerator());
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);
            gen.EmitLoadArg(1);                     // gen.Emit(OpCodes.Ldarg_1);
            gen.EmitFieldSet(fb);                   // gen.Emit(OpCodes.Stfld, fb);
            gen.Emit(OpCodes.Ret);

            MethodBuilder updateTB = proxyTB.DefineMethod(
                "__updateClojureFnMappings",
                 MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                 typeof(void),
                 new Type[] { typeof(IPersistentMap) });
            gen = new CljILGen(updateTB.GetILGenerator());
            gen.EmitLoadArg(0);                     // gen.Emit(OpCodes.Ldarg_0);

            gen.Emit(OpCodes.Dup);
            gen.EmitFieldGet(fb);                   // gen.Emit(OpCodes.Ldfld, fb);
            gen.Emit(OpCodes.Castclass, typeof(IPersistentMap));

            gen.EmitLoadArg(1);                                     // gen.Emit(OpCodes.Ldarg_1);
            gen.EmitCall(Method_IPersistentMap_Cons);        //gen.Emit(OpCodes.Call, Method_IPersistentCollection_Cons);

            gen.EmitFieldSet(fb);                                   // gen.Emit(OpCodes.Stfld, fb);
            gen.Emit(OpCodes.Ret);

            MethodBuilder getMb = proxyTB.DefineMethod(
                "__getClojureFnMappings",
                 MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                typeof(IPersistentMap),
                Type.EmptyTypes);

            gen = new CljILGen(getMb.GetILGenerator());
            gen.EmitLoadArg(0);                                     // gen.Emit(OpCodes.Ldarg_0);
            gen.EmitFieldGet(fb);                                   // gen.Emit(OpCodes.Ldfld, fb);
            gen.Emit(OpCodes.Ret);

            return fb;
        }
コード例 #38
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);
        }
コード例 #39
0
ファイル: GenProxy.cs プロジェクト: stuman08/clojure-clr
        private static void DefineCtor(TypeBuilder proxyTB, ConstructorInfo ctor)
        {
            ParameterInfo[] pinfos = ctor.GetParameters();
            Type[] paramTypes = new Type[pinfos.Length];
            for (int i = 0; i < pinfos.Length; i++)
                paramTypes[i] = pinfos[i].ParameterType;

            ConstructorBuilder cb = proxyTB.DefineConstructor(ctor.Attributes, CallingConventions.HasThis, paramTypes);
            // Call base class ctor on all the args
            CljILGen gen = new CljILGen(cb.GetILGenerator());
            gen.EmitLoadArg(0);                         // gen.Emit(OpCodes.Ldarg_0);
            for (int i = 0; i < pinfos.Length; i++)
                gen.EmitLoadArg(i + 1);                 // gen.Emit(OpCodes.Ldarg, i + 1);
            gen.Emit(OpCodes.Call, ctor);
            gen.Emit(OpCodes.Ret);
        }
コード例 #40
0
ファイル: ObjExpr.cs プロジェクト: aaronc/clojure-clr
        internal void EmitLocal(CljILGen ilg, LocalBinding lb)
        {
            Type primType = lb.PrimitiveType;

            if (Closes.containsKey(lb))
            {
                if (_fnMode == FnMode.Full)
                {
                    ilg.Emit(OpCodes.Ldarg_0); // this
                    FieldBuilder fb = _closedOverFieldsMap[lb];
                    ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                    ilg.Emit(OpCodes.Ldfld, fb);
                    if (primType != null)
                        HostExpr.EmitBoxReturn(this, ilg, primType);
                    // TODO: ONCEONLY?
                }
                else // FnMode.Light
                {
                    ilg.Emit(OpCodes.Ldarg_0); // this
                    ilg.Emit(OpCodes.Castclass, typeof(IFnClosure));
                    ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure);
                    ilg.EmitFieldGet(Compiler.Field_Closure_Locals);
                    ilg.EmitInt(lb.Index);
                    ilg.EmitLoadElement(typeof(Object));
                }
            }
            else
            {
                if (lb.IsArg)
                {
                    //int argOffset = IsStatic ? 1 : 0;
                    //ilg.Emit(OpCodes.Ldarg, lb.Index - argOffset);
                    ilg.EmitLoadArg(lb.Index);
                }
                else if (lb.IsThis)
                {
                    ilg.EmitLoadArg(0);
                }
                else
                {
                    ilg.Emit(OpCodes.Ldloc, lb.LocalVar);
                }
                if (primType != null)
                    HostExpr.EmitBoxReturn(this, ilg, primType);
            }
        }
コード例 #41
0
ファイル: GenProxy.cs プロジェクト: stuman08/clojure-clr
        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);
        }
コード例 #42
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        private static void EmitExposers(TypeBuilder proxyTB, Type superClass, IPersistentMap exposesFields)
        {
            for ( ISeq s = RT.seq(exposesFields); s != null; s = s.next() )
            {
                IMapEntry me = (IMapEntry)s.first();
                Symbol protectedFieldSym = (Symbol)me.key();
                IPersistentMap accessMap = (IPersistentMap)me.val();

                string fieldName = protectedFieldSym.Name;
                Symbol getterSym = (Symbol)accessMap.valAt(_getKw, null);
                Symbol setterSym = (Symbol)accessMap.valAt(_setKW, null);

                FieldInfo fld = null;

                if ( getterSym != null || setterSym != null )
                    fld = superClass.GetField(fieldName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy | BindingFlags.Static | BindingFlags.Instance);

                if (getterSym != null)
                {
                    MethodAttributes attribs = MethodAttributes.Public;
                    if (fld.IsStatic)
                        attribs |= MethodAttributes.Static;

                    MethodBuilder mb = proxyTB.DefineMethod(getterSym.Name, attribs, fld.FieldType, Type.EmptyTypes);
                    CljILGen gen = new CljILGen(mb.GetILGenerator());
                    //if (fld.IsStatic)
                    //    gen.Emit(OpCodes.Ldsfld, fld);
                    //else
                    //{
                    //    gen.Emit(OpCodes.Ldarg_0);
                    //    gen.Emit(OpCodes.Ldfld, fld);
                    //}
                    if (!fld.IsStatic)
                        gen.EmitLoadArg(0);
                    gen.MaybeEmitVolatileOp(fld);
                    gen.EmitFieldGet(fld);

                    gen.Emit(OpCodes.Ret);
                }

                if (setterSym != null)
                {
                    MethodAttributes attribs = MethodAttributes.Public;
                    if (fld.IsStatic)
                        attribs |= MethodAttributes.Static;

                    MethodBuilder mb = proxyTB.DefineMethod(setterSym.Name, attribs, typeof(void), new Type[] { fld.FieldType });
                    CljILGen gen = new CljILGen(mb.GetILGenerator());
                    if (fld.IsStatic)
                    {
                        gen.Emit(OpCodes.Ldarg_0);
                        //gen.Emit(OpCodes.Stsfld, fld);
                    }
                    else
                    {
                        gen.Emit(OpCodes.Ldarg_0);
                        gen.Emit(OpCodes.Ldarg_1);
                        //gen.Emit(OpCodes.Stfld, fld);
                    }
                    gen.MaybeEmitVolatileOp(fld);
                    gen.EmitFieldSet(fld);
                    gen.Emit(OpCodes.Ret);
                }
            }
        }
コード例 #43
0
ファイル: InvokeExpr.cs プロジェクト: EricThorsen/clojure-clr
        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);
        }
コード例 #44
0
ファイル: GenClass.cs プロジェクト: chrisortman/clojure-clr
        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);
            }
        }
コード例 #45
0
ファイル: MethodExpr.cs プロジェクト: einert/clojure-clr
        static public void EmitDynamicCallPreamble(DynamicExpression dyn, IPersistentMap spanMap, string methodName, Type returnType, IList <ParameterExpression> paramExprs, Type[] paramTypes, CljILGen ilg, out LambdaExpression lambda, out Type delType, out MethodBuilder mbLambda)
        {
            Expression call = dyn;

            GenContext context = Compiler.CompilerContextVar.deref() as GenContext;

            DynInitHelper.SiteInfo siteInfo;
            if (context != null && context.DynInitHelper != null)
            {
                call = context.DynInitHelper.ReduceDyn(dyn, out siteInfo);
            }
            else
            {
                throw new InvalidOperationException("Don't know how to handle callsite in this case");
            }

            if (returnType == typeof(void))
            {
                call       = Expression.Block(call, Expression.Default(typeof(object)));
                returnType = typeof(object);
            }
            else if (returnType != call.Type)
            {
                call = Expression.Convert(call, returnType);
            }

            call = GenContext.AddDebugInfo(call, spanMap);


            delType  = Microsoft.Scripting.Generation.Snippets.Shared.DefineDelegate("__interop__", returnType, paramTypes);
            lambda   = Expression.Lambda(delType, call, paramExprs);
            mbLambda = null;

            if (context == null)
            {
                // light compile

                Delegate d   = lambda.Compile();
                int      key = RT.nextID();
                CacheDelegate(key, d);

                ilg.EmitInt(key);
                ilg.Emit(OpCodes.Call, Method_MethodExpr_GetDelegate);
                ilg.Emit(OpCodes.Castclass, delType);
            }
            else
            {
                mbLambda = context.TB.DefineMethod(methodName, MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, returnType, paramTypes);
                //lambda.CompileToMethod(mbLambda);
                // Now we get to do all this code create by hand.
                // the primary code is
                // (loc1 = fb).Target.Invoke(loc1,*args);
                // if return type if void, pop the value and push a null
                // if return type does not match the call site, add a conversion
                CljILGen ilg2 = new CljILGen(mbLambda.GetILGenerator());
                ilg2.EmitFieldGet(siteInfo.FieldBuilder);
                ilg2.Emit(OpCodes.Dup);
                LocalBuilder siteVar = ilg2.DeclareLocal(siteInfo.DelegateType);
                ilg2.Emit(OpCodes.Stloc, siteVar);
                ilg2.EmitFieldGet(siteInfo.SiteType.GetField("Target"));
                ilg2.Emit(OpCodes.Ldloc, siteVar);
                for (int i = 0; i < paramExprs.Count; i++)
                {
                    ilg2.EmitLoadArg(i);
                }

                ilg2.EmitCall(siteInfo.DelegateType.GetMethod("Invoke"));
                if (returnType == typeof(void))
                {
                    ilg2.Emit(OpCodes.Pop);
                    ilg2.EmitNull();
                }
                else if (returnType != call.Type)
                {
                    EmitConvertToType(ilg2, call.Type, returnType, false);
                }

                ilg2.Emit(OpCodes.Ret);


                /*
                 *             return Expression.Block(
                 * new[] { site },
                 * Expression.Call(
                 * Expression.Field(
                 *  Expression.Assign(site, access),
                 *  cs.GetType().GetField("Target")
                 * ),
                 * node.DelegateType.GetMethod("Invoke"),
                 * ClrExtensions.ArrayInsert(site, node.Arguments)
                 * )
                 */
            }
        }