public override MethodIL EmitIL() { // Generate the unboxing stub. This loosely corresponds to following C#: // return BoxedValue.InstanceMethod([rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen(); // unbox to get a pointer to the value type codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField)); // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Call an instance method on the target valuetype codeStream.Emit(ILOpcode.call, emit.NewToken(_targetMethod.InstantiateAsOpen())); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public override MethodIL EmitIL() { // Generate the unboxing stub. This loosely corresponds to following C#: // return BoxedValue.InstanceMethod(this.m_pEEType, [rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType"); FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen(); // Load ByRef to the field with the value of the boxed valuetype codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField)); // Load the EEType of the boxed valuetype (this is the hidden generic context parameter expected // by the (canonical) instance method, but normally not part of the signature in IL). codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField)); // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Call an instance method on the target valuetype that has a fake instantiation parameter // in it's signature. This will be swapped by the actual instance method after codegen is done. codeStream.Emit(ILOpcode.call, emit.NewToken(_nakedTargetMethod.InstantiateAsOpen())); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public override MethodIL EmitIL() { if (_owningType.BoxedValue == null) { // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws. return(new ILStubMethodIL(this, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty <LocalVariableDefinition>(), Array.Empty <object>())); } // Generate the unboxing stub. This loosely corresponds to following C#: // return BoxedValue.InstanceMethod([rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen(); // unbox to get a pointer to the value type codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField)); // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Call an instance method on the target valuetype codeStream.Emit(ILOpcode.call, emit.NewToken(_targetMethod.InstantiateAsOpen())); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
protected override void EmitMarshalFieldManagedToNative() { ILEmitter emitter = _ilCodeStreams.Emitter; ILCodeStream codeStream = _ilCodeStreams.MarshallingCodeStream; var nativeArrayType = NativeType as InlineArrayType; Debug.Assert(nativeArrayType != null); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField)); codeStream.Emit(ILOpcode.conv_u); EmitElementCount(codeStream, MarshalDirection.Forward); if (IsAnsi) { codeStream.Emit(PInvokeFlags.BestFitMapping ? ILOpcode.ldc_i4_1 : ILOpcode.ldc_i4_0); codeStream.Emit(PInvokeFlags.ThrowOnUnmappableChar ? ILOpcode.ldc_i4_1 : ILOpcode.ldc_i4_0); } codeStream.Emit(ILOpcode.call, emitter.NewToken(GetManagedToNativeHelper())); }
protected override void EmitElementCount(ILCodeStream codeStream, MarshalDirection direction) { ILEmitter emitter = _ilCodeStreams.Emitter; if (MarshalAsDescriptor == null || !MarshalAsDescriptor.SizeConst.HasValue) { throw new InvalidProgramException("SizeConst is required for ByValArray."); } if (direction == MarshalDirection.Forward) { // In forward direction ElementCount = Min(managed.length, SizeConst); var vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); var lSmaller = emitter.NewCodeLabel(); var lDone = emitter.NewCodeLabel(); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); var lNullCheck = emitter.NewCodeLabel(); codeStream.Emit(ILOpcode.brfalse, lNullCheck); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); codeStream.Emit(ILOpcode.ldlen); codeStream.Emit(ILOpcode.conv_i4); codeStream.EmitStLoc(vLength); codeStream.EmitLabel(lNullCheck); Debug.Assert(MarshalAsDescriptor.SizeConst.HasValue); int sizeConst = (int)MarshalAsDescriptor.SizeConst.Value; codeStream.EmitLdc(sizeConst); codeStream.EmitLdLoc(vLength); codeStream.Emit(ILOpcode.blt, lSmaller); codeStream.EmitLdLoc(vLength); codeStream.Emit(ILOpcode.br, lDone); codeStream.EmitLabel(lSmaller); codeStream.EmitLdc(sizeConst); codeStream.EmitLabel(lDone); } else { // In reverse direction ElementCount = SizeConst; Debug.Assert(MarshalAsDescriptor.SizeConst.HasValue); int sizeConst = (int)MarshalAsDescriptor.SizeConst.Value; codeStream.EmitLdc(sizeConst); } }
public override MethodIL EmitIL() { if (_owningType.BoxedValue == null) { // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws. return(new ILStubMethodIL(this, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty <LocalVariableDefinition>(), Array.Empty <object>())); } // Generate the unboxing stub. This loosely corresponds to following C#: // return BoxedValue.InstanceMethod([rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc boxedValueField = _owningType.BoxedValue.InstantiateAsOpen(); // unbox to get a pointer to the value type codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emit.NewToken(boxedValueField)); // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } TypeDesc owner = _targetMethod.OwningType; MethodDesc methodToInstantiate = _targetMethod; if (owner.HasInstantiation) { MetadataType instantiatedOwner = (MetadataType)owner.InstantiateAsOpen(); methodToInstantiate = _targetMethod.Context.GetMethodForInstantiatedType(_targetMethod, (InstantiatedType)instantiatedOwner); } if (methodToInstantiate.HasInstantiation) { TypeSystemContext context = methodToInstantiate.Context; var inst = new TypeDesc[methodToInstantiate.Instantiation.Length]; for (int i = 0; i < inst.Length; i++) { inst[i] = context.GetSignatureVariable(i, true); } methodToInstantiate = context.GetInstantiatedMethod(methodToInstantiate, new Instantiation(inst)); } codeStream.Emit(ILOpcode.call, emit.NewToken(methodToInstantiate)); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public override MethodIL EmitIL() { var emitter = new ILEmitter(); ILCodeStream codeStream = emitter.NewCodeStream(); codeStream.EmitLdArg(0); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.call, emitter.NewToken( InteropTypes.GetNativeFunctionPointerWrapper(Context).GetMethod(".ctor", Signature))); codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); if (Context.Target.IsWindows) { codeStream.MarkDebuggerStepThroughPoint(); } for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i); } if (Context.Target.IsWindows) { codeStream.MarkDebuggerStepInPoint(); } codeStream.Emit(ILOpcode.call, emit.NewToken(WrappedMethod)); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
protected override void EmitMarshalFieldNativeToManaged() { ILEmitter emitter = _ilCodeStreams.Emitter; ILCodeStream codeStream = _ilCodeStreams.UnmarshallingCodestream; codeStream.EmitLdArg(1); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField)); codeStream.Emit(ILOpcode.conv_u); EmitElementCount(codeStream, MarshalDirection.Reverse); codeStream.Emit(ILOpcode.call, emitter.NewToken(GetNativeToManagedHelper())); codeStream.Emit(ILOpcode.stfld, emitter.NewToken(_managedField)); }
public static MethodIL EmitIL(MethodDesc method) { Debug.Assert(method.OwningType.IsDelegate); Debug.Assert(method.IsRuntimeImplemented); if (method.Name == "BeginInvoke" || method.Name == "EndInvoke") { // BeginInvoke and EndInvoke are not supported on .NET Core ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); MethodDesc notSupportedExceptionHelper = method.Context.GetHelperEntryPoint("ThrowHelpers", "ThrowPlatformNotSupportedException"); codeStream.EmitCallThrowHelper(emit, notSupportedExceptionHelper); return(emit.Link()); } if (method.Name == ".ctor") { TypeSystemContext context = method.Context; ILEmitter emit = new ILEmitter(); TypeDesc delegateType = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType; MethodDesc objectCtorMethod = context.GetWellKnownType(WellKnownType.Object).GetDefaultConstructor(); FieldDesc functionPointerField = delegateType.GetKnownField("m_functionPointer"); FieldDesc firstParameterField = delegateType.GetKnownField("m_firstParameter"); ILCodeStream codeStream = emit.NewCodeStream(); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.call, emit.NewToken(objectCtorMethod)); codeStream.EmitLdArg(0); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.stfld, emit.NewToken(firstParameterField)); codeStream.EmitLdArg(0); codeStream.EmitLdArg(2); codeStream.Emit(ILOpcode.stfld, emit.NewToken(functionPointerField)); codeStream.Emit(ILOpcode.ret); return(emit.Link()); } return(null); }
public override MethodIL EmitIL() { if (_owningType.ValueTypeRepresented.IsByRefLike) { // If this is the fake unboxing thunk for ByRef-like types, just make a method that throws. return(new ILStubMethodIL(this, new byte[] { (byte)ILOpcode.ldnull, (byte)ILOpcode.throw_ }, Array.Empty <LocalVariableDefinition>(), Array.Empty <object>())); } // Generate the unboxing stub. This loosely corresponds to following C#: // return BoxedValue.InstanceMethod(this.m_pEEType, [rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType"); // Load ByRef to the field with the value of the boxed valuetype codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emit.NewToken(Context.SystemModule.GetKnownType("System.Runtime.CompilerServices", "RawData").GetField("Data"))); // Load the MethodTable of the boxed valuetype (this is the hidden generic context parameter expected // by the (canonical) instance method, but normally not part of the signature in IL). codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField)); // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Call an instance method on the target valuetype that has a fake instantiation parameter // in it's signature. This will be swapped by the actual instance method after codegen is done. codeStream.Emit(ILOpcode.call, emit.NewToken(_nakedTargetMethod.InstantiateAsOpen())); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public override MethodIL EmitIL() { // Generate the instantiating stub. This loosely corresponds to following C#: // return Interface.Method(this, GetOrdinalInterface(this.m_pEEType, Index), [rest of parameters]) ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); FieldDesc eeTypeField = Context.GetWellKnownType(WellKnownType.Object).GetKnownField("m_pEEType"); MethodDesc getOrdinalInterfaceMethod = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetOrdinalInterface"); MethodDesc getCurrentContext = Context.GetHelperEntryPoint("SharedCodeHelpers", "GetCurrentSharedThunkContext"); // Load "this" codeStream.EmitLdArg(0); // Load the instantiating argument. if (_interfaceIndex == UseContextFromRuntime) { codeStream.Emit(ILOpcode.call, emit.NewToken(getCurrentContext)); } else { codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emit.NewToken(eeTypeField)); codeStream.EmitLdc(_interfaceIndex); codeStream.Emit(ILOpcode.call, emit.NewToken(getOrdinalInterfaceMethod)); } // Load rest of the arguments for (int i = 0; i < _targetMethod.Signature.Length; i++) { codeStream.EmitLdArg(i + 1); } // Call an instance method on the target interface that has a fake instantiation parameter // in it's signature. This will be swapped by the actual instance method after codegen is done. codeStream.Emit(ILOpcode.call, emit.NewToken(_nakedTargetMethod)); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public void EmitMarshallingIL(ILEmitter emitter, ILCodeStream marshallingCodeStream, ILCodeStream callsiteSetupCodeStream, ILCodeStream unmarshallingCodeStream, ILCodeStream returnValueCodeStream) { if (!PInvokeParameterMetadata.Return) { marshallingCodeStream.EmitLdArg(PInvokeParameterMetadata.Index - 1); NativeType = MarshalArgument(ManagedType, emitter, marshallingCodeStream, unmarshallingCodeStream); IL.Stubs.ILLocalVariable vMarshalledTypeTemp = emitter.NewLocal(NativeType); marshallingCodeStream.EmitStLoc(vMarshalledTypeTemp); callsiteSetupCodeStream.EmitLdLoc(vMarshalledTypeTemp); } else { NativeType = MarshalReturn(ManagedType, emitter, marshallingCodeStream, returnValueCodeStream); } }
public override MethodIL EmitIL() { ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i); } codeStream.Emit(ILOpcode.call, emit.NewToken(_mainMethod)); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
public override MethodIL EmitIL() { ILEmitter emit = new ILEmitter(); ILCodeStream codeStream = emit.NewCodeStream(); // We only need the initial step over sequence point if there's any instructions before the call. if (Signature.Length > 0) { codeStream.MarkDebuggerStepThroughPoint(); } for (int i = 0; i < Signature.Length; i++) { codeStream.EmitLdArg(i); } codeStream.MarkDebuggerStepInPoint(); codeStream.Emit(ILOpcode.call, emit.NewToken(WrappedMethod)); codeStream.Emit(ILOpcode.ret); return(emit.Link(this)); }
protected override void EmitMarshalFieldManagedToNative() { // It generates the following code //if (ManagedArg.Field != null) //{ // // fixed (InlineArray* pUnsafe = &NativeArg.Field) // { // uint index = 0u; // while ((ulong)index < (ulong)((long)ManagedArg.Field.Length)) // { // NativeArg.s[index] = ManagedArg.Field[(int)index]; // index += 1u; // } // } //} ILEmitter emitter = _ilCodeStreams.Emitter; ILCodeStream codeStream = _ilCodeStreams.MarshallingCodeStream; var nativeArrayType = NativeType as InlineArrayType; Debug.Assert(nativeArrayType != null); Debug.Assert(ManagedType is ArrayType); var managedElementType = ((ArrayType)ManagedType).ElementType; ILCodeLabel lDone = emitter.NewCodeLabel(); ILCodeLabel lRangeCheck = emitter.NewCodeLabel(); ILCodeLabel lLoopHeader = emitter.NewCodeLabel(); ILLocalVariable vIndex = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); ILLocalVariable vNative = emitter.NewLocal(NativeType.MakeByRefType(), isPinned: true); // check if ManagedType == null, then return codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); codeStream.Emit(ILOpcode.brfalse, lDone); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField)); codeStream.EmitStLoc(vNative); EmitElementCount(codeStream, MarshalDirection.Forward); codeStream.EmitStLoc(vLength); codeStream.EmitLdc(0); codeStream.EmitStLoc(vIndex); codeStream.Emit(ILOpcode.br, lRangeCheck); codeStream.EmitLabel(lLoopHeader); codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField)); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdElem(managedElementType); // generate marshalling IL for the element GetElementMarshaller(MarshalDirection.Forward) .EmitMarshallingIL(new PInvokeILCodeStreams(_ilCodeStreams.Emitter, codeStream)); codeStream.Emit(ILOpcode.call, emitter.NewToken( nativeArrayType.GetInlineArrayMethod(InlineArrayMethodKind.Setter))); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdc(1); codeStream.Emit(ILOpcode.add); codeStream.EmitStLoc(vIndex); codeStream.EmitLabel(lRangeCheck); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdLoc(vLength); codeStream.Emit(ILOpcode.blt, lLoopHeader); codeStream.EmitLabel(lDone); }
protected override void EmitMarshalFieldNativeToManaged() { ILEmitter emitter = _ilCodeStreams.Emitter; ILCodeStream codeStream = _ilCodeStreams.UnmarshallingCodestream; // It generates the following IL: // ManagedArg.s = new ElementType[Length]; // // for (uint index = 0u; index < Length; index += 1u) // { // ManagedArg.s[index] = NativeArg.s[index]; // } // ILCodeLabel lRangeCheck = emitter.NewCodeLabel(); ILCodeLabel lLoopHeader = emitter.NewCodeLabel(); Debug.Assert(ManagedType is ArrayType); var nativeArrayType = NativeType as InlineArrayType; Debug.Assert(nativeArrayType != null); var managedElementType = ((ArrayType)ManagedType).ElementType; ILLocalVariable vLength = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); codeStream.EmitLdArg(1); // load the length EmitElementCount(codeStream, MarshalDirection.Reverse); codeStream.EmitStLoc(vLength); codeStream.EmitLdLoc(vLength); codeStream.Emit(ILOpcode.newarr, emitter.NewToken(managedElementType)); codeStream.Emit(ILOpcode.stfld, emitter.NewToken(_managedField)); var vIndex = emitter.NewLocal(Context.GetWellKnownType(WellKnownType.Int32)); // index = 0 codeStream.EmitLdc(0); codeStream.EmitStLoc(vIndex); codeStream.Emit(ILOpcode.br, lRangeCheck); codeStream.EmitLabel(lLoopHeader); // load managed type codeStream.EmitLdArg(1); codeStream.Emit(ILOpcode.ldfld, emitter.NewToken(_managedField)); codeStream.EmitLdLoc(vIndex); // load native type codeStream.EmitLdArg(0); codeStream.Emit(ILOpcode.ldflda, emitter.NewToken(_nativeField)); codeStream.EmitLdLoc(vIndex); codeStream.Emit(ILOpcode.call, emitter.NewToken( nativeArrayType.GetInlineArrayMethod(InlineArrayMethodKind.Getter))); // generate marshalling IL for the element GetElementMarshaller(MarshalDirection.Reverse) .EmitMarshallingIL(new PInvokeILCodeStreams(_ilCodeStreams.Emitter, codeStream)); codeStream.EmitStElem(managedElementType); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdc(1); codeStream.Emit(ILOpcode.add); codeStream.EmitStLoc(vIndex); codeStream.EmitLabel(lRangeCheck); codeStream.EmitLdLoc(vIndex); codeStream.EmitLdLoc(vLength); codeStream.Emit(ILOpcode.blt, lLoopHeader); }