private void EmitLoadInteriorAddress(ILCodeStream codeStream, int offset) { // This helper field is needed to generate proper GC tracking. There is no direct way // to create interior pointer. if (_helperFieldToken == 0) _helperFieldToken = NewToken(_method.Context.GetWellKnownType(WellKnownType.Object).GetField("m_pEEType")); codeStream.EmitLdArg(0); // this codeStream.Emit(ILOpcode.ldflda, _helperFieldToken); codeStream.EmitLdc(offset); codeStream.Emit(ILOpcode.add); }
private ArrayMethodILEmitter(ArrayMethod method) { _method = method; ArrayType arrayType = (ArrayType)method.OwningType; _rank = arrayType.Rank; _elementType = arrayType.ElementType; _emitter = new ILEmitter(); // This helper field is needed to generate proper GC tracking. There is no direct way // to create interior pointer. _helperFieldToken = _emitter.NewToken(_method.Context.GetWellKnownType(WellKnownType.Object).GetField("m_pEEType")); }
private ArrayMethodILEmitter(ArrayMethod method) { _method = method; ArrayType arrayType = (ArrayType)method.OwningType; _rank = arrayType.Rank; _elementType = arrayType.ElementType; _emitter = new ILEmitter(); // This helper field is needed to generate proper GC tracking. There is no direct way // to create interior pointer. _helperFieldToken = _emitter.NewToken(_method.Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType")); }
private ArrayMethodILEmitter(ArrayMethod method) { Debug.Assert(method.Kind != ArrayMethodKind.Address, "Should be " + nameof(ArrayMethodKind.AddressWithHiddenArg)); _method = method; ArrayType arrayType = (ArrayType)method.OwningType; _rank = arrayType.Rank; _elementType = arrayType.ElementType; _emitter = new ILEmitter(); // This helper field is needed to generate proper GC tracking. There is no direct way // to create interior pointer. _helperFieldToken = _emitter.NewToken(_method.Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType")); }
private static MethodIL EmitCopy(MethodDesc method) { Debug.Assert(method.Signature.IsStatic && method.Signature.Length == 2); TypeSystemContext context = method.Context; ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); ILToken token = emit.NewToken(context.GetSignatureVariable(0, method: true)); codeStream.EmitLdArg(0); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.ldobj, token); codeStream.Emit(ILOpcode.stobj, token); codeStream.Emit(ILOpcode.ret); return(emit.Link(method)); }
public static MethodIL EmitIL(MethodDesc method) { Debug.Assert(((MetadataType)method.OwningType).Name == "Stream"); bool isRead = method.Name == "HasOverriddenBeginEndRead"; if (!isRead && method.Name != "HasOverriddenBeginEndWrite") { return(null); } TypeDesc streamClass = method.OwningType; MethodDesc beginMethod = streamClass.GetMethod(isRead ? "BeginRead" : "BeginWrite", null); MethodDesc endMethod = streamClass.GetMethod(isRead ? "EndRead" : "EndWrite", null); ILEmitter emitter = new ILEmitter(); ILCodeStream codestream = emitter.NewCodeStream(); ILCodeLabel lOverriden = emitter.NewCodeLabel(); ILToken beginMethodToken = emitter.NewToken(beginMethod); codestream.EmitLdArg(0); codestream.Emit(ILOpcode.ldvirtftn, beginMethodToken); codestream.Emit(ILOpcode.ldftn, beginMethodToken); codestream.Emit(ILOpcode.bne_un, lOverriden); ILToken endMethodToken = emitter.NewToken(endMethod); codestream.EmitLdArg(0); codestream.Emit(ILOpcode.ldvirtftn, endMethodToken); codestream.Emit(ILOpcode.ldftn, endMethodToken); codestream.Emit(ILOpcode.bne_un, lOverriden); codestream.EmitLdc(0); codestream.Emit(ILOpcode.ret); codestream.EmitLabel(lOverriden); codestream.EmitLdc(1); codestream.Emit(ILOpcode.ret); return(emitter.Link(method)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); MetadataType appContextType = Context.SystemModule.GetKnownType("System", "AppContext"); MethodDesc setDataMethod = appContextType.GetKnownMethod("SetData", null); ILToken setDataToken = emitter.NewToken(setDataMethod); foreach (KeyValuePair <string, string> keyValue in _switches) { codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(keyValue.Key)); codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(keyValue.Value)); codeStream.Emit(ILOpcode.call, setDataToken); } codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); MetadataType appContextType = Context.SystemModule.GetKnownType("System", "AppContext"); MethodDesc setSwitchMethod = appContextType.GetKnownMethod("SetSwitch", null); ILToken setSwitchToken = emitter.NewToken(setSwitchMethod); foreach (string switchName in _switches) { codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(switchName)); codeStream.EmitLdc(1); codeStream.Emit(ILOpcode.call, setSwitchToken); } codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { // We will generate the following code: // // object ret; // object[] args = new object[parameterCount]; // args[0] = param0; // args[1] = param1; // ... // try { // ret = ((Func<object[], object>)dlg.m_helperObject)(args); // } finally { // param0 = (T0)args[0]; // only generated for each byref argument // } // return (TRet)ret; ILEmitter emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); TypeDesc objectType = Context.GetWellKnownType(WellKnownType.Object); TypeDesc objectArrayType = objectType.MakeArrayType(); ILLocalVariable argsLocal = emitter.NewLocal(objectArrayType); bool hasReturnValue = !Signature.ReturnType.IsVoid; bool hasRefArgs = false; if (Signature.Length > 0) { codeStream.EmitLdc(Signature.Length); codeStream.Emit(ILOpcode.newarr, emitter.NewToken(objectType)); codeStream.EmitStLoc(argsLocal); for (int i = 0; i < Signature.Length; i++) { TypeDesc paramType = Signature[i]; bool paramIsByRef = false; if (paramType.IsByRef) { hasRefArgs |= paramType.IsByRef; paramIsByRef = true; paramType = ((ByRefType)paramType).ParameterType; } hasRefArgs |= paramType.IsByRef; codeStream.EmitLdLoc(argsLocal); codeStream.EmitLdc(i); codeStream.EmitLdArg(i + 1); TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType); ILToken boxableParamToken = emitter.NewToken(boxableParamType); if (paramIsByRef) { codeStream.Emit(ILOpcode.ldobj, boxableParamToken); } codeStream.Emit(ILOpcode.box, boxableParamToken); codeStream.Emit(ILOpcode.stelem_ref); } } else { MethodDesc emptyObjectArrayMethod = Context.GetHelperEntryPoint("DelegateHelpers", "GetEmptyObjectArray"); codeStream.Emit(ILOpcode.call, emitter.NewToken(emptyObjectArrayMethod)); codeStream.EmitStLoc(argsLocal); } if (hasRefArgs) { // we emit a try/finally to update the args array even if an exception is thrown // ilgen.BeginTryBody(); } codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(HelperObjectField)); MetadataType funcType = Context.SystemModule.GetKnownType("System", "Func`2"); TypeDesc instantiatedFunc = funcType.MakeInstantiatedType(objectArrayType, objectType); codeStream.Emit(ILOpcode.castclass, emitter.NewToken(instantiatedFunc)); codeStream.EmitLdLoc(argsLocal); MethodDesc invokeMethod = instantiatedFunc.GetKnownMethod("Invoke", null); codeStream.Emit(ILOpcode.callvirt, emitter.NewToken(invokeMethod)); ILLocalVariable retLocal = (ILLocalVariable)(-1); if (hasReturnValue) { retLocal = emitter.NewLocal(objectType); codeStream.EmitStLoc(retLocal); } else { codeStream.Emit(ILOpcode.pop); } if (hasRefArgs) { // ILGeneratorLabel returnLabel = new ILGeneratorLabel(); // ilgen.Emit(OperationCode.Leave, returnLabel); // copy back ref/out args //ilgen.BeginFinallyBlock(); for (int i = 0; i < Signature.Length; i++) { TypeDesc paramType = Signature[i]; if (paramType.IsByRef) { paramType = ((ByRefType)paramType).ParameterType; TypeDesc boxableParamType = DelegateDynamicInvokeThunk.ConvertToBoxableType(paramType); ILToken boxableParamToken = emitter.NewToken(boxableParamType); // Update parameter codeStream.EmitLdArg(i + 1); codeStream.EmitLdLoc(argsLocal); codeStream.EmitLdc(i); codeStream.Emit(ILOpcode.ldelem_ref); codeStream.Emit(ILOpcode.unbox_any, boxableParamToken); codeStream.Emit(ILOpcode.stobj, boxableParamToken); } } // ilgen.Emit(OperationCode.Endfinally); // ilgen.EndTryBody(); // ilgen.MarkLabel(returnLabel); } if (hasReturnValue) { TypeDesc boxableReturnType = DelegateDynamicInvokeThunk.ConvertToBoxableType(Signature.ReturnType); codeStream.EmitLdLoc(retLocal); codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(boxableReturnType)); } codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public void Emit(ILOpcode opcode, ILToken token) { Emit(opcode); EmitUInt32((int)token); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret ILCodeLabel lStaticCall = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); DynamicInvokeMethodParameterKind paramKind = _targetSignature[paramIndex]; if (paramKind == DynamicInvokeMethodParameterKind.Pointer) { for (int i = 0; i < _targetSignature.GetNumberOfParameterPointerIndirections(paramIndex); i++) { paramType = paramType.MakePointerType(); } } ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (paramKind == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); staticCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall DynamicInvokeMethodParameterKind returnKind = _targetSignature.ReturnType; TypeDesc returnType = returnKind != DynamicInvokeMethodParameterKind.None ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); if (returnKind == DynamicInvokeMethodParameterKind.Pointer) { for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++) { returnType = returnType.MakePointerType(); } } MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); if (returnKind == DynamicInvokeMethodParameterKind.None) { thisCallSiteSetupStream.Emit(ILOpcode.ldnull); staticCallSiteSetupStream.Emit(ILOpcode.ldnull); } else if (returnKind == DynamicInvokeMethodParameterKind.Pointer) { thisCallSiteSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnType)); staticCallSiteSetupStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnType)); MethodDesc getTypeFromHandleMethod = Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null); thisCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); staticCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); MethodDesc pointerBoxMethod = Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null); thisCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); staticCallSiteSetupStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); } else { Debug.Assert(returnKind == DynamicInvokeMethodParameterKind.Value); ILToken tokReturnType = emitter.NewToken(returnType); thisCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); staticCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); } thisCallSiteSetupStream.Emit(ILOpcode.ret); staticCallSiteSetupStream.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); } // 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() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream returnCodeStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldarg.2 // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(ref ArgSetupState, RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldarg.2 // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(ref ArgSetupState, RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // br Process_return // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // *** Return code stream starts here *** // Process_return: // !if (ReturnType is Byref) // dup // brfalse ByRefNull // ldobj ReturnType // !if ((ReturnType == void) // ldnull // !elif (ReturnType is pointer) // System.Reflection.Pointer.Box(ReturnType) // !else // box ReturnType // ret // // !if (ReturnType is ByRef) // ByRefNull: // throw NullReferenceException ILCodeLabel lStaticCall = emitter.NewCodeLabel(); ILCodeLabel lProcessReturn = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); DynamicInvokeMethodParameterKind paramKind = _targetSignature[paramIndex]; for (int i = 0; i < _targetSignature.GetNumberOfParameterPointerIndirections(paramIndex); i++) { paramType = paramType.MakePointerType(); } ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (paramKind == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.EmitLdInd(paramType); staticCallSiteSetupStream.EmitLdInd(paramType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall DynamicInvokeMethodParameterKind returnKind = _targetSignature.ReturnType; TypeDesc returnType = returnKind != DynamicInvokeMethodParameterKind.None ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); for (int i = 0; i < _targetSignature.GetNumerOfReturnTypePointerIndirections(); i++) { returnType = returnType.MakePointerType(); } if (returnKind == DynamicInvokeMethodParameterKind.Reference) { returnType = returnType.MakeByRefType(); } MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); thisCallSiteSetupStream.Emit(ILOpcode.br, lProcessReturn); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); returnCodeStream.EmitLabel(lProcessReturn); ILCodeLabel lByRefReturnNull = null; if (returnKind == DynamicInvokeMethodParameterKind.None) { returnCodeStream.Emit(ILOpcode.ldnull); } else { TypeDesc returnTypeForBoxing = returnType; if (returnType.IsByRef) { // If this is a byref return, we need to dereference first returnTypeForBoxing = ((ByRefType)returnType).ParameterType; lByRefReturnNull = emitter.NewCodeLabel(); returnCodeStream.Emit(ILOpcode.dup); returnCodeStream.Emit(ILOpcode.brfalse, lByRefReturnNull); returnCodeStream.EmitLdInd(returnTypeForBoxing); } if (returnTypeForBoxing.IsPointer) { // Pointers box differently returnCodeStream.Emit(ILOpcode.ldtoken, emitter.NewToken(returnTypeForBoxing)); MethodDesc getTypeFromHandleMethod = Context.SystemModule.GetKnownType("System", "Type").GetKnownMethod("GetTypeFromHandle", null); returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(getTypeFromHandleMethod)); MethodDesc pointerBoxMethod = Context.SystemModule.GetKnownType("System.Reflection", "Pointer").GetKnownMethod("Box", null); returnCodeStream.Emit(ILOpcode.call, emitter.NewToken(pointerBoxMethod)); } else { ILToken tokReturnType = emitter.NewToken(returnTypeForBoxing); returnCodeStream.Emit(ILOpcode.box, tokReturnType); } } returnCodeStream.Emit(ILOpcode.ret); if (lByRefReturnNull != null) { returnCodeStream.EmitLabel(lByRefReturnNull); MethodDesc nullReferencedExceptionHelper = Context.GetHelperEntryPoint("ThrowHelpers", "ThrowInvokeNullRefReturned"); returnCodeStream.EmitCallThrowHelper(emitter, nullReferencedExceptionHelper); } 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)); }
public override MethodIL EmitIL() { ILEmitter emitter = new ILEmitter(); ILCodeStream argSetupStream = emitter.NewCodeStream(); ILCodeStream thisCallSiteSetupStream = emitter.NewCodeStream(); ILCodeStream staticCallSiteSetupStream = emitter.NewCodeStream(); // This function will look like // // !For each parameter to the method // !if (parameter is In Parameter) // localX is TypeOfParameterX& // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperIn(RuntimeTypeHandle) // stloc localX // !else // localX is TypeOfParameter // ldtoken TypeOfParameterX // call DynamicInvokeParamHelperRef(RuntimeTypeHandle) // stloc localX // ldarg.2 // call DynamicInvokeArgSetupComplete(ref ArgSetupState) // *** Thiscall instruction stream starts here *** // ldarg.3 // Load targetIsThisCall // brfalse Not_this_call // ldarg.0 // Load this pointer // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType thiscall(TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !else // box ReturnType // ret // *** Static call instruction stream starts here *** // Not_this_call: // !For each parameter // !if (parameter is In Parameter) // ldloc localX // ldobj TypeOfParameterX // !else // ldloc localX // ldarg.1 // calli ReturnType (TypeOfParameter1, ...) // !if ((ReturnType == void) // ldnull // !else // box ReturnType // ret ILCodeLabel lStaticCall = emitter.NewCodeLabel(); thisCallSiteSetupStream.EmitLdArg(3); // targetIsThisCall thisCallSiteSetupStream.Emit(ILOpcode.brfalse, lStaticCall); staticCallSiteSetupStream.EmitLabel(lStaticCall); thisCallSiteSetupStream.EmitLdArg(0); // thisPtr ILToken tokDynamicInvokeParamHelperRef = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperRef", null)); ILToken tokDynamicInvokeParamHelperIn = emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeParamHelperIn", null)); TypeDesc[] targetMethodSignature = new TypeDesc[_targetSignature.Length]; for (int paramIndex = 0; paramIndex < _targetSignature.Length; paramIndex++) { TypeDesc paramType = Context.GetSignatureVariable(paramIndex, true); ILToken tokParamType = emitter.NewToken(paramType); ILLocalVariable local = emitter.NewLocal(paramType.MakeByRefType()); thisCallSiteSetupStream.EmitLdLoc(local); staticCallSiteSetupStream.EmitLdLoc(local); argSetupStream.Emit(ILOpcode.ldtoken, tokParamType); if (_targetSignature[paramIndex] == DynamicInvokeMethodParameterKind.Reference) { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperRef); targetMethodSignature[paramIndex] = paramType.MakeByRefType(); } else { argSetupStream.Emit(ILOpcode.call, tokDynamicInvokeParamHelperIn); thisCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); staticCallSiteSetupStream.Emit(ILOpcode.ldobj, tokParamType); targetMethodSignature[paramIndex] = paramType; } argSetupStream.EmitStLoc(local); } argSetupStream.EmitLdArg(2); // argSetupState argSetupStream.Emit(ILOpcode.call, emitter.NewToken(InvokeUtilsType.GetKnownMethod("DynamicInvokeArgSetupComplete", null))); thisCallSiteSetupStream.EmitLdArg(1); // methodToCall staticCallSiteSetupStream.EmitLdArg(1); // methodToCall TypeDesc returnType = _targetSignature.HasReturnValue ? Context.GetSignatureVariable(_targetSignature.Length, true) : Context.GetWellKnownType(WellKnownType.Void); MethodSignature thisCallMethodSig = new MethodSignature(0, 0, returnType, targetMethodSignature); CalliIntrinsic.EmitTransformedCalli(emitter, thisCallSiteSetupStream, thisCallMethodSig); //thisCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(thisCallMethodSig)); MethodSignature staticCallMethodSig = new MethodSignature(MethodSignatureFlags.Static, 0, returnType, targetMethodSignature); CalliIntrinsic.EmitTransformedCalli(emitter, staticCallSiteSetupStream, staticCallMethodSig); //staticCallSiteSetupStream.Emit(ILOpcode.calli, emitter.NewToken(staticCallMethodSig)); if (_targetSignature.HasReturnValue) { ILToken tokReturnType = emitter.NewToken(returnType); thisCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); staticCallSiteSetupStream.Emit(ILOpcode.box, tokReturnType); } else { thisCallSiteSetupStream.Emit(ILOpcode.ldnull); staticCallSiteSetupStream.Emit(ILOpcode.ldnull); } thisCallSiteSetupStream.Emit(ILOpcode.ret); staticCallSiteSetupStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }