MaybeEmitVolatileOp() 공개 메소드

public MaybeEmitVolatileOp ( FieldInfo fi ) : void
fi System.Reflection.FieldInfo
리턴 void
예제 #1
0
        internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals)
        {
            if (TypeBuilder != null)
            {
                // Full compile
                ilg.Emit(OpCodes.Castclass, TypeBuilder);

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    if (letFnLocals.contains(lb))
                    {
                        ClosedOverFieldsMap.TryGetValue(lb, out FieldBuilder fb);

                        Type primt = lb.PrimitiveType;
                        ilg.Emit(OpCodes.Dup);  // this
                        if (primt != null)
                        {
                            objx.EmitUnboxedLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                        else
                        {
                            objx.EmitLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                    }
                }
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #2
0
        internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val)
        {
            if (!IsMutable(lb))
                throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name);

            FieldBuilder fb = null;
            bool hasField = ClosedOverFieldsMap.TryGetValue(lb, out fb);

            ilg.Emit(OpCodes.Ldarg_0);  // this

            Type primt = lb.PrimitiveType;
            if (primt != null)
            {
                MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr;
                if (!(mbe != null && mbe.CanEmitPrimitive))
                    throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name);
                mbe.EmitUnboxed(RHC.Expression, this, ilg);

            }
            else
            {
                val.Emit(RHC.Expression, this, ilg);
            }

            if (hasField)
            {
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Stfld, fb);
            }
            else
                ilg.Emit(OpCodes.Stloc, lb.LocalVar);
        }
예제 #3
0
        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
        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);
        }
예제 #5
0
 protected override void EmitSet(CljILGen ilg)
 {
     if (_tinfo.IsInitOnly)
     {
         throw new InvalidOperationException(String.Format("Attempt to set readonly field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType));
     }
     ilg.MaybeEmitVolatileOp(_tinfo);
     ilg.EmitFieldSet(_tinfo);
 }
예제 #6
0
 internal void EmitConstant(CljILGen ilg, int id, object val)
 {
     FieldBuilder fb = null;
     if ( ConstantFields != null && ConstantFields.TryGetValue(id, out fb))
     {
         ilg.MaybeEmitVolatileOp(fb);
         ilg.Emit(OpCodes.Ldsfld, fb);
     }
     else
         EmitValue(val, ilg);
 }
예제 #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
        public override void EmitUnboxed(RHC rhc, ObjExpr objx, CljILGen ilg)
        {
            GenContext.EmitDebugInfo(ilg, _spanMap);
            if (_tinfo.IsLiteral)
            {
                // literal fields need to be inlined directly in here... We use GetRawConstant
                // which will work even in partial trust if the constant is protected.
                object value = _tinfo.GetRawConstantValue();
                switch (Type.GetTypeCode(_tinfo.FieldType))
                {
                case TypeCode.Boolean:
                    if ((bool)value)
                    {
                        ilg.Emit(OpCodes.Ldc_I4_1);
                    }
                    else
                    {
                        ilg.Emit(OpCodes.Ldc_I4_0);
                    }
                    break;

                case TypeCode.Byte: ilg.EmitInt((int)(byte)value); break;

                case TypeCode.Char: ilg.EmitInt((int)(char)value); break;

                case TypeCode.Double: ilg.EmitDouble((double)value); break;

                case TypeCode.Int16: ilg.EmitInt((int)(short)value); break;

                case TypeCode.Int32: ilg.EmitInt((int)value); break;

                case TypeCode.Int64: ilg.EmitLong((long)value); break;

                case TypeCode.SByte: ilg.EmitInt((int)(sbyte)value); break;

                case TypeCode.Single: ilg.EmitSingle((float)value); break;

                case TypeCode.String: ilg.EmitString((string)value); break;

                case TypeCode.UInt16: ilg.EmitInt((int)(ushort)value); break;

                case TypeCode.UInt32: ilg.Emit(OpCodes.Ldc_I4, (uint)value); break;

                case TypeCode.UInt64: ilg.Emit(OpCodes.Ldc_I8, (ulong)value); break;
                }
            }
            else
            {
                ilg.MaybeEmitVolatileOp(_tinfo);
                ilg.EmitFieldGet(_tinfo);
            }
        }
예제 #9
0
        public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val)
        {
            GenContext.EmitDebugInfo(ilg, _spanMap);

            val.Emit(RHC.Expression, objx, ilg);
            ilg.Emit(OpCodes.Dup);
            HostExpr.EmitUnboxArg(objx, ilg, FieldType);
            ilg.MaybeEmitVolatileOp(_tinfo);
            ilg.EmitFieldSet(_tinfo);
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #10
0
        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
        public override void EmitAssign(RHC rhc, ObjExpr objx, CljILGen ilg, Expr val)
        {
            if (_tinfo.IsInitOnly)
            {
                throw new InvalidOperationException(String.Format("Attempt to set readonly static field {0} in class {1}", _tinfo.Name, _tinfo.DeclaringType));
            }

            GenContext.EmitDebugInfo(ilg, _spanMap);

            val.Emit(RHC.Expression, objx, ilg);
            ilg.Emit(OpCodes.Dup);
            HostExpr.EmitUnboxArg(objx, ilg, FieldType);
            ilg.MaybeEmitVolatileOp(_tinfo);
            ilg.EmitFieldSet(_tinfo);
            if (rhc == RHC.Statement)
            {
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #12
0
 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);
 }
예제 #13
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
                    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);
            }
        }
예제 #14
0
 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);
 }
예제 #15
0
 protected override void EmitGet(CljILGen ilg)
 {
     ilg.MaybeEmitVolatileOp(_tinfo);
     ilg.EmitFieldGet(_tinfo);
 }
예제 #16
0
 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);
 }
예제 #17
0
        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);
            }
        }
예제 #18
0
        internal void EmitLetFnInits(CljILGen ilg, LocalBuilder localBuilder, ObjExpr objx, IPersistentSet letFnLocals)
        {
            if (_typeBuilder != null)
            {
                // Full compile
                ilg.Emit(OpCodes.Castclass, _typeBuilder);

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    if (letFnLocals.contains(lb))
                    {
                        FieldBuilder fb;
                        _closedOverFieldsMap.TryGetValue(lb, out fb);

                        Type primt = lb.PrimitiveType;
                        ilg.Emit(OpCodes.Dup);  // this
                        if (primt != null)
                        {
                            objx.EmitUnboxedLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                        else
                        {
                            objx.EmitLocal(ilg, lb);
                            ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                            ilg.Emit(OpCodes.Stfld, fb);
                        }
                    }
                }
                ilg.Emit(OpCodes.Pop);
            }
        }
예제 #19
0
 internal void EmitConstant(CljILGen ilg, int id, object val)
 {
     FieldBuilder fb = null;
     if ( ConstantFields != null && ConstantFields.TryGetValue(id, out fb))
     {
         ilg.MaybeEmitVolatileOp(fb);
         ilg.Emit(OpCodes.Ldsfld, fb);
     }
     else
         EmitValue(val, ilg);
 }
예제 #20
0
        internal void EmitAssignLocal(CljILGen ilg, LocalBinding lb, Expr val)
        {
            if (!IsMutable(lb))
                throw new ArgumentException("Cannot assign to non-mutable: ", lb.Name);

            FieldBuilder fb = null;
            bool hasField = _closedOverFieldsMap.TryGetValue(lb, out fb);

            ilg.Emit(OpCodes.Ldarg_0);  // this

            Type primt = lb.PrimitiveType;
            if (primt != null)
            {
                MaybePrimitiveExpr mbe = val as MaybePrimitiveExpr;
                if (!(mbe != null && mbe.CanEmitPrimitive))
                    throw new ArgumentException("Must assign primitive to primitive mutable", lb.Name);
                mbe.EmitUnboxed(RHC.Expression, this, ilg);

            }
            else
            {
                val.Emit(RHC.Expression, this, ilg);
            }

            if (hasField)
            {
                ilg.MaybeEmitVolatileOp(IsVolatile(lb));
                ilg.Emit(OpCodes.Stfld, fb);
            }
            else
                ilg.Emit(OpCodes.Stloc, lb.LocalVar);
        }
예제 #21
0
        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);
        }
예제 #22
0
        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;
        }
예제 #23
0
        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);
                }
            }
        }
예제 #24
0
 internal void EmitConstant(CljILGen ilg, int id, object val)
 {
     if (_fnMode == Ast.FnMode.Light)
     {
         if (val == null)
         {
             ilg.EmitNull();
         }
         if (val.GetType().IsPrimitive)
         {
             EmitPrimitive(ilg, val);
             ilg.Emit(OpCodes.Box,val.GetType());
         }
         else
         {
             ilg.Emit(OpCodes.Ldarg_0); // this
             ilg.Emit(OpCodes.Castclass, typeof(IFnClosure));
             ilg.EmitCall(Compiler.Method_IFnClosure_GetClosure);
             ilg.EmitFieldGet(Compiler.Field_Closure_Constants);
             ilg.EmitInt(id);
             ilg.EmitLoadElement(typeof(Object));
             ilg.Emit(OpCodes.Castclass, ConstantType(id));
         }
     }
     else
     {
         FieldBuilder fb = null;
         if (_fnMode == FnMode.Full && ConstantFields != null && ConstantFields.TryGetValue(id, out fb))
         {
             ilg.MaybeEmitVolatileOp(fb);
             ilg.Emit(OpCodes.Ldsfld, fb);
         }
         else
             EmitValue(val, ilg);
     }
 }
예제 #25
0
        void LightEmit(RHC rhc, ObjExpr objx, CljILGen ilg)
        {

            //emitting a Fn means constructing an instance, feeding closed-overs from enclosing scope, if any
            //objx arg is enclosing objx, not this

            
            // Create the function instance
            LocalBuilder fnLocal = ilg.DeclareLocal(CompiledType);
            
            if (CompiledType == typeof(RestFnImpl))
            {
                ilg.EmitInt(_variadicMethod.RequiredArity);
                ilg.EmitNew(Compiler.Ctor_RestFnImpl_1);
            }
            else
            {
                ilg.EmitNew(Compiler.Ctor_AFnImpl);
            }

            ilg.Emit(OpCodes.Stloc, fnLocal);

            //ilg.EmitString(String.Format("Creating fn {0}", Name));
            //ilg.Emit(OpCodes.Call, typeof(System.Console).GetMethod("WriteLine", new Type[] { typeof(string) }));

            // Set up the methods

            for (ISeq s = RT.seq(_methods); s != null; s = s.next())
            {
                FnMethod method = (FnMethod)s.first();
                int key = GetMethodKey(method);
 
                string fieldName = IsVariadic && method.IsVariadic
                    ? "_fnDo" + (key - 1)  // because key is arity+1 for variadic
                    : "_fn" + key;

                FieldInfo fi = CompiledType.GetField(fieldName);

                ilg.Emit(OpCodes.Ldloc, fnLocal);


                EmitGetDynMethod(key, ilg);
                ilg.EmitType(fi.FieldType);
                ilg.Emit(OpCodes.Ldloc, fnLocal);
                ilg.Emit(OpCodes.Callvirt, Method_DynamicMethod_CreateDelegate);
                ilg.Emit(OpCodes.Castclass, fi.FieldType);

                ilg.MaybeEmitVolatileOp(fi);
                ilg.EmitFieldSet(fi);
            }



            // setup the constants and locals
            ilg.Emit(OpCodes.Ldloc, fnLocal);

            if (Constants.count() > 0)
            {
                EmitGetCompiledConstants(ilg);
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            if (Closes.count() > 0)
            {

                int maxIndex = Closes.Max(c => ((LocalBinding)c.key()).Index);

                ilg.EmitInt(maxIndex + 1);
                ilg.Emit(OpCodes.Newarr, typeof(object));

                for (ISeq s = RT.keys(Closes); s != null; s = s.next())
                {
                    LocalBinding lb = (LocalBinding)s.first();
                    ilg.Emit(OpCodes.Dup);
                    ilg.EmitInt(lb.Index);
                    objx.EmitLocal(ilg, lb);
                    ilg.EmitStoreElement(typeof(object));
                }
            }
            else
            {
                ilg.EmitInt(0);
                ilg.EmitArray(typeof(Object[]));
            }

            // Create the closure
            ilg.EmitNew(Compiler.Ctor_Closure_2);

            // Assign the clojure
            ilg.EmitCall(Compiler.Method_IFnClosure_SetClosure);

            // Leave the instance on the stack.
            ilg.Emit(OpCodes.Ldloc, fnLocal);
        }
예제 #26
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);
                    }
                }
            }
        }