public override MethodIL EmitIL()
        {
            TypeDesc owningType = _owningType.InstantiateAsOpen();

            ILEmitter emitter = new ILEmitter();

            TypeDesc   eeTypePtrType     = Context.SystemModule.GetKnownType("System", "EETypePtr");
            MethodDesc eeTypePtrOfMethod = eeTypePtrType.GetKnownMethod("EETypePtrOf", null);
            ILToken    eeTypePtrToken    = emitter.NewToken(eeTypePtrType);

            var switchStream   = emitter.NewCodeStream();
            var getFieldStream = emitter.NewCodeStream();

            ArrayBuilder <ILCodeLabel> fieldGetters = new ArrayBuilder <ILCodeLabel>();

            foreach (FieldDesc field in owningType.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                ILCodeLabel label = emitter.NewCodeLabel();
                fieldGetters.Add(label);

                getFieldStream.EmitLabel(label);
                getFieldStream.EmitLdArg(2);

                // We need something we can instantiate EETypePtrOf over. Also, the classlib
                // code doesn't handle pointers.
                TypeDesc boxableFieldType = field.FieldType;
                if (boxableFieldType.IsPointer || boxableFieldType.IsFunctionPointer)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.IntPtr);
                }

                // The fact that the type is a reference type is sufficient for the callers.
                // Don't unnecessarily create an MethodTable for the field type.
                if (!boxableFieldType.IsSignatureVariable && !boxableFieldType.IsValueType)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.Object);
                }

                // If this is an enum, it's okay to Equals/GetHashCode the underlying type.
                // Don't unnecessarily create an MethodTable for the enum.
                boxableFieldType = boxableFieldType.UnderlyingType;

                MethodDesc ptrOfField = eeTypePtrOfMethod.MakeInstantiatedMethod(boxableFieldType);
                getFieldStream.Emit(ILOpcode.call, emitter.NewToken(ptrOfField));

                getFieldStream.Emit(ILOpcode.stobj, eeTypePtrToken);

                getFieldStream.EmitLdArg(0);
                getFieldStream.Emit(ILOpcode.ldflda, emitter.NewToken(field));

                getFieldStream.EmitLdArg(0);

                getFieldStream.Emit(ILOpcode.sub);

                getFieldStream.Emit(ILOpcode.ret);
            }

            if (fieldGetters.Count > 0)
            {
                switchStream.EmitLdArg(1);
                switchStream.EmitSwitch(fieldGetters.ToArray());
            }

            switchStream.EmitLdc(fieldGetters.Count);

            switchStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }
Example #2
0
        public override MethodIL EmitIL()
        {
            TypeDesc owningType = _owningType.InstantiateAsOpen();

            ILEmitter emitter = new ILEmitter();

            TypeDesc   eeTypePtrType     = Context.SystemModule.GetKnownType("System", "EETypePtr");
            MethodDesc eeTypePtrOfMethod = eeTypePtrType.GetKnownMethod("EETypePtrOf", null);
            ILToken    eeTypePtrToken    = emitter.NewToken(eeTypePtrType);

            var switchStream   = emitter.NewCodeStream();
            var getFieldStream = emitter.NewCodeStream();

            ArrayBuilder <ILCodeLabel> fieldGetters = new ArrayBuilder <ILCodeLabel>();

            foreach (FieldDesc field in owningType.GetFields())
            {
                if (field.IsStatic)
                {
                    continue;
                }

                ILCodeLabel label = emitter.NewCodeLabel();
                fieldGetters.Add(label);

                getFieldStream.EmitLabel(label);
                getFieldStream.EmitLdArg(2);

                // We need something we can instantiate EETypePtrOf over. Also, the classlib
                // code doesn't handle pointers.
                TypeDesc boxableFieldType = field.FieldType;
                if (boxableFieldType.IsPointer || boxableFieldType.IsFunctionPointer)
                {
                    boxableFieldType = Context.GetWellKnownType(WellKnownType.IntPtr);
                }

                MethodDesc ptrOfField = eeTypePtrOfMethod.MakeInstantiatedMethod(boxableFieldType);
                getFieldStream.Emit(ILOpcode.call, emitter.NewToken(ptrOfField));

                getFieldStream.Emit(ILOpcode.stobj, eeTypePtrToken);

                getFieldStream.EmitLdArg(0);
                getFieldStream.Emit(ILOpcode.ldflda, emitter.NewToken(field));

                getFieldStream.EmitLdArg(0);

                getFieldStream.Emit(ILOpcode.sub);

                getFieldStream.Emit(ILOpcode.ret);
            }

            if (fieldGetters.Count > 0)
            {
                switchStream.EmitLdArg(1);
                switchStream.EmitSwitch(fieldGetters.ToArray());
            }

            switchStream.EmitLdc(fieldGetters.Count);

            switchStream.Emit(ILOpcode.ret);

            return(emitter.Link(this));
        }