public ILExceptionRegionBuilder NewFinallyRegion() { var region = new ILExceptionRegionBuilder(); _finallyRegions.Add(region); return(region); }
private MethodIL EmitIL() { PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream marshallingCodestream = pInvokeILCodeStreams.MarshallingCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; ILCodeStream cleanupCodestream = pInvokeILCodeStreams.CleanupCodeStream; // Marshalling is wrapped in a finally block to guarantee cleanup ILExceptionRegionBuilder tryFinally = emitter.NewFinallyRegion(); marshallingCodestream.BeginTry(tryFinally); cleanupCodestream.BeginHandler(tryFinally); // Marshal the arguments bool isHRSwappedRetVal = !_flags.PreserveSig && !_targetMethod.Signature.ReturnType.IsVoid; for (int i = isHRSwappedRetVal ? 1 : 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } if (isHRSwappedRetVal) { _marshallers[0].EmitMarshallingIL(pInvokeILCodeStreams); } // make the call switch (_targetMethod) { case DelegateMarshallingMethodThunk delegateMethod: EmitDelegateCall(delegateMethod, pInvokeILCodeStreams); break; case CalliMarshallingMethodThunk calliMethod: EmitCalli(pInvokeILCodeStreams, calliMethod); break; default: EmitPInvokeCall(pInvokeILCodeStreams); break; } ILCodeLabel lReturn = emitter.NewCodeLabel(); unmarshallingCodestream.Emit(ILOpcode.leave, lReturn); unmarshallingCodestream.EndTry(tryFinally); cleanupCodestream.Emit(ILOpcode.endfinally); cleanupCodestream.EndHandler(tryFinally); cleanupCodestream.EmitLabel(lReturn); _marshallers[0].LoadReturnValue(cleanupCodestream); cleanupCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod), IsStubRequired())); }
private MethodIL EmitIL() { if (!_importMetadata.Flags.PreserveSig) { throw new NotSupportedException(); } if (MarshalHelpers.ShouldCheckForPendingException(_targetMethod.Context.Target, _importMetadata)) { throw new NotSupportedException(); } if (_targetMethod.IsUnmanagedCallersOnly) { throw new NotSupportedException(); } if (_targetMethod.HasCustomAttribute("System.Runtime.InteropServices", "LCIDConversionAttribute")) { throw new NotSupportedException(); } PInvokeILCodeStreams pInvokeILCodeStreams = new PInvokeILCodeStreams(); ILEmitter emitter = pInvokeILCodeStreams.Emitter; ILCodeStream marshallingCodestream = pInvokeILCodeStreams.MarshallingCodeStream; ILCodeStream unmarshallingCodestream = pInvokeILCodeStreams.UnmarshallingCodestream; ILCodeStream cleanupCodestream = pInvokeILCodeStreams.CleanupCodeStream; // Marshalling is wrapped in a finally block to guarantee cleanup ILExceptionRegionBuilder tryFinally = emitter.NewFinallyRegion(); marshallingCodestream.BeginTry(tryFinally); cleanupCodestream.BeginHandler(tryFinally); // Marshal the arguments for (int i = 0; i < _marshallers.Length; i++) { _marshallers[i].EmitMarshallingIL(pInvokeILCodeStreams); } EmitPInvokeCall(pInvokeILCodeStreams); ILCodeLabel lReturn = emitter.NewCodeLabel(); unmarshallingCodestream.Emit(ILOpcode.leave, lReturn); unmarshallingCodestream.EndTry(tryFinally); cleanupCodestream.Emit(ILOpcode.endfinally); cleanupCodestream.EndHandler(tryFinally); cleanupCodestream.EmitLabel(lReturn); _marshallers[0].LoadReturnValue(cleanupCodestream); cleanupCodestream.Emit(ILOpcode.ret); return(new PInvokeILStubMethodIL((ILStubMethodIL)emitter.Link(_targetMethod))); }
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); ILToken paramToken = emitter.NewToken(paramType); if (paramIsByRef) { codeStream.Emit(ILOpcode.ldobj, paramToken); } codeStream.Emit(ILOpcode.box, paramToken); codeStream.Emit(ILOpcode.stelem_ref); } } else { MethodDesc emptyObjectArrayMethod = Context.GetHelperEntryPoint("DelegateHelpers", "GetEmptyObjectArray"); codeStream.Emit(ILOpcode.call, emitter.NewToken(emptyObjectArrayMethod)); codeStream.EmitStLoc(argsLocal); } ILExceptionRegionBuilder tryFinallyRegion = null; if (hasRefArgs) { // we emit a try/finally to update the args array even if an exception is thrown tryFinallyRegion = emitter.NewFinallyRegion(); codeStream.BeginTry(tryFinallyRegion); } 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) { ILCodeLabel returnLabel = emitter.NewCodeLabel(); codeStream.Emit(ILOpcode.leave, returnLabel); codeStream.EndTry(tryFinallyRegion); // copy back ref/out args codeStream.BeginHandler(tryFinallyRegion); for (int i = 0; i < Signature.Length; i++) { TypeDesc paramType = Signature[i]; if (paramType.IsByRef) { paramType = ((ByRefType)paramType).ParameterType; ILToken paramToken = emitter.NewToken(paramType); // Update parameter codeStream.EmitLdArg(i + 1); codeStream.EmitLdLoc(argsLocal); codeStream.EmitLdc(i); codeStream.Emit(ILOpcode.ldelem_ref); codeStream.Emit(ILOpcode.unbox_any, paramToken); codeStream.Emit(ILOpcode.stobj, paramToken); } } codeStream.Emit(ILOpcode.endfinally); codeStream.EndHandler(tryFinallyRegion); codeStream.EmitLabel(returnLabel); } if (hasReturnValue) { codeStream.EmitLdLoc(retLocal); codeStream.Emit(ILOpcode.unbox_any, emitter.NewToken(Signature.ReturnType)); } codeStream.Emit(ILOpcode.ret); return(emitter.Link(this)); }
public MethodIL Link(MethodDesc owningMethod) { int totalLength = 0; int numSequencePoints = 0; for (int i = 0; i < _codeStreams.Count; i++) { ILCodeStream ilCodeStream = _codeStreams[i]; ilCodeStream._startOffsetForLinking = totalLength; totalLength += ilCodeStream._length; numSequencePoints += ilCodeStream._sequencePoints.Count; } byte[] ilInstructions = new byte[totalLength]; int copiedLength = 0; for (int i = 0; i < _codeStreams.Count; i++) { ILCodeStream ilCodeStream = _codeStreams[i]; ilCodeStream.PatchLabels(); Array.Copy(ilCodeStream._instructions, 0, ilInstructions, copiedLength, ilCodeStream._length); copiedLength += ilCodeStream._length; } MethodDebugInformation debugInfo = null; if (numSequencePoints > 0) { ILSequencePoint[] sequencePoints = new ILSequencePoint[numSequencePoints]; int copiedSequencePointLength = 0; for (int codeStreamIndex = 0; codeStreamIndex < _codeStreams.Count; codeStreamIndex++) { ILCodeStream ilCodeStream = _codeStreams[codeStreamIndex]; for (int sequencePointIndex = 0; sequencePointIndex < ilCodeStream._sequencePoints.Count; sequencePointIndex++) { ILSequencePoint sequencePoint = ilCodeStream._sequencePoints[sequencePointIndex]; sequencePoints[copiedSequencePointLength] = new ILSequencePoint( ilCodeStream._startOffsetForLinking + sequencePoint.Offset, sequencePoint.Document, sequencePoint.LineNumber); copiedSequencePointLength++; } } debugInfo = new EmittedMethodDebugInformation(sequencePoints); } ILExceptionRegion[] exceptionRegions = null; int numberOfExceptionRegions = _finallyRegions.Count; if (numberOfExceptionRegions > 0) { exceptionRegions = new ILExceptionRegion[numberOfExceptionRegions]; for (int i = 0; i < _finallyRegions.Count; i++) { ILExceptionRegionBuilder region = _finallyRegions[i]; Debug.Assert(region.IsDefined); exceptionRegions[i] = new ILExceptionRegion(ILExceptionRegionKind.Finally, region.TryOffset, region.TryLength, region.HandlerOffset, region.HandlerLength, classToken: 0, filterOffset: 0); } } var result = new ILStubMethodIL(owningMethod, ilInstructions, _locals.ToArray(), _tokens.ToArray(), exceptionRegions, debugInfo); result.CheckStackBalance(); return(result); }
public void EndHandler(ILExceptionRegionBuilder builder) { Debug.Assert(builder._endHandlerStream == null); builder._endHandlerStream = this; builder._endHandlerOffset = _length; }
public void BeginTry(ILExceptionRegionBuilder builder) { Debug.Assert(builder._beginTryStream == null); builder._beginTryStream = this; builder._beginTryOffset = _length; }