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)); }
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)); }