/// <inheritdoc/>
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            // If the return type is a delegate, convert it back into its generic representation
            var definition = workUnit.Definition;
            var returnType = definition.ReturnType;

            if (!returnType.IsDelegate())
            {
                return;
            }

            // Convert IntPtr to delegate. (null for IntPtr.Zero)
            var retMarshalLabel = il.DefineLabel();

            il.DeclareLocal(typeof(IntPtr)); // loc_0

            il.Emit(OpCodes.Stloc_0);
            il.Emit(OpCodes.Ldloc_0);

            il.Emit(OpCodes.Brtrue_S, retMarshalLabel);

            // IntPtr.Zero -> return null
            il.Emit(OpCodes.Ldnull);

            il.Emit(OpCodes.Ret);

            // IntPtr != Zero -> marshal delegate
            il.MarkLabel(retMarshalLabel);
            il.Emit(OpCodes.Ldloc_0);

            var marshalPointerToDel = _marshalPointerToDel.MakeGenericMethod(workUnit.Definition.ReturnType);

            il.Emit(OpCodes.Call, marshalPointerToDel);
        }
Ejemplo n.º 2
0
 public PipelineParseResult(string expr, PipelineParseResults pipelineParseResults, PipelineWorkUnit workUnit)
 {
     ParseResult          = new ParseResult(ParseResultType.Empty, null);
     PipelineParseResults = pipelineParseResults;
     WorkUnit             = workUnit;
     Expr = expr;
 }
Ejemplo n.º 3
0
        /// <inheritdoc />
        public sealed override IEnumerable <PipelineWorkUnit <IntrospectiveMethodInfo> > GenerateImplementation
        (
            PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
        )
        {
            var definition = workUnit.Definition;

            if (!(definition.GetWrappedMember() is MethodBuilder builder))
            {
                throw new ArgumentNullException(nameof(workUnit), "Could not unwrap introspective method to method builder.");
            }

            EmitAdditionalTypes(TargetModule, workUnit);
            var passthroughMethod = GeneratePassthroughDefinition(workUnit);

            var il = builder.GetILGenerator();

            EmitPrologue(il, workUnit);
            il.EmitCallDirect(passthroughMethod.GetWrappedMember());
            EmitEpilogue(il, workUnit);
            il.EmitReturn();

            // Pass through the method
            yield return(new PipelineWorkUnit <IntrospectiveMethodInfo>(passthroughMethod, workUnit));
        }
Ejemplo n.º 4
0
        /// <inheritdoc/>
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var parameterTypes = definition.ParameterTypes;

            il.EmitLoadArgument(0);

            for (short i = 1; i <= parameterTypes.Count; ++i)
            {
                var paramType = parameterTypes[i - 1];

                if (IsSpanType(paramType))
                {
                    var pinnedLocal = il.DeclareLocal(paramType.GenericTypeArguments[0].MakeByRefType(), true);

                    var getPinnableReferenceMethod = paramType.GetMethod(nameof(Span <byte> .GetPinnableReference), BindingFlags.Public | BindingFlags.Instance);

                    il.EmitLoadArgumentAddress(i);
                    il.EmitCallDirect(getPinnableReferenceMethod);
                    il.EmitDuplicate();
                    il.EmitSetLocalVariable(pinnedLocal);
                    il.EmitConvertToNativeInt();
                }
                else
                {
                    il.EmitLoadArgument(i);
                }
            }
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Emits any additional types that a work unit requires. By default, this does nothing.
 /// </summary>
 /// <param name="module">The module to emit the types in.</param>
 /// <param name="workUnit">The unit to generate the types from.</param>
 public virtual void EmitAdditionalTypes
 (
     [NotNull] ModuleBuilder module,
     [NotNull] PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
 )
 {
 }
Ejemplo n.º 6
0
        /// <inheritdoc/>
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition
        (
            PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
        )
        {
            var definition = workUnit.Definition;

            var newReturnType     = GetParameterPassthroughType(definition.ReturnType);
            var newParameterTypes = definition.ParameterTypes.Select(GetParameterPassthroughType).ToArray();

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                newParameterTypes
                                    );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, newParameterTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       newParameterTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
        /// <inheritdoc />
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var locals = new Dictionary <int, LocalBuilder>();

            _workUnitLocals.Add(workUnit, locals);

            // Load the "this" reference
            il.EmitLoadArgument(0);

            for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
            {
                il.EmitLoadArgument(i);

                var parameterType = definition.ParameterTypes[i - 1];
                if (parameterType != typeof(string))
                {
                    continue;
                }

                var unmanagedStringType = GetParameterUnmanagedType(definition.ParameterCustomAttributes[i - 1]);
                il.EmitCallDirect(SelectManagedToUnmanagedTransformationMethod(unmanagedStringType));

                if (definition.ParameterHasCustomAttribute <CallerFreeAttribute>(i - 1))
                {
                    var parameterLocal = il.DeclareLocal(typeof(IntPtr));
                    il.EmitSetLocalVariable(parameterLocal);
                    il.EmitLoadLocalVariable(parameterLocal);

                    locals.Add(i - 1, parameterLocal);
                }
            }
        }
        /// <inheritdoc />
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            ConstructorInfo ctor = workUnit.Definition.ReturnType.GetConstructor(new[] { typeof(void *), typeof(int) });

            il.Emit(OpCodes.Ldc_I4, GetNativeCollectionLengthMetadata(workUnit.Definition).Length);
            il.Emit(OpCodes.Newobj, ctor);
        }
Ejemplo n.º 9
0
 public PipelineParseResult(string expr, PipelineParseResults pipelineParseResults, PipelineWorkUnit workUnit, ParseResult parseResult)
 {
     ParseResult          = parseResult;
     PipelineParseResults = pipelineParseResults;
     WorkUnit             = workUnit;
     Expr = expr;
 }
Ejemplo n.º 10
0
        /// <inheritdoc/>
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            // Load the "this" reference
            il.EmitLoadArgument(0);

            for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
            {
                il.EmitLoadArgument(i);

                var parameterType = definition.ParameterTypes[i - 1];
                if (!parameterType.IsGenericDelegate())
                {
                    continue;
                }

                // Convert the input generic delegate to an explicit delegate
                var explicitDelegateType = GetCreatedExplicitDelegateType(parameterType);

                if (explicitDelegateType is null)
                {
                    throw new InvalidOperationException("No delegate type has been created for the given type.");
                }

                var explicitDelegateConstructor = explicitDelegateType.GetConstructors().First();
                var invokeMethod = parameterType.GetMethod("Invoke");

                il.EmitLoadFunctionPointer(invokeMethod);
                il.EmitNewObject(explicitDelegateConstructor);
            }
        }
Ejemplo n.º 11
0
        /// <inheritdoc/>
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            // If the return type is a delegate, convert it back into its generic representation
            var definition = workUnit.Definition;
            var returnType = definition.ReturnType;

            if (!returnType.IsGenericDelegate())
            {
                return;
            }

            // Convert the output explicit delegate to a generic delegate
            var explicitDelegateType = GetCreatedExplicitDelegateType(returnType);

            if (explicitDelegateType is null)
            {
                throw new InvalidOperationException("No delegate type has been created for the given type.");
            }

            var genericDelegateConstructor = returnType.GetConstructors().First();
            var invokeMethod = explicitDelegateType.GetMethod("Invoke");

            il.EmitLoadFunctionPointer(invokeMethod);
            il.EmitNewObject(genericDelegateConstructor);
        }
Ejemplo n.º 12
0
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var newParameterTypes = definition.ParameterTypes.Select(t => t.IsNonRefNullable() ? typeof(IntPtr) : t).ToArray();
            var newReturnType     = definition.ReturnType.IsNonRefNullable() ? typeof(IntPtr) : definition.ReturnType;

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                newReturnType,
                newParameterTypes
                                    );

            // Copy over all the attributes, except MarshalAsAttributes to IntPtr parameters
            passthroughMethod.ApplyCustomAttributesFrom
            (
                definition,
                newReturnType,
                newParameterTypes
            );

            return(new IntrospectiveMethodInfo(passthroughMethod, newReturnType, newParameterTypes, definition));
        }
Ejemplo n.º 13
0
        /// <inheritdoc />
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var throwMethod = typeof(NativeLibraryBase).GetMethod("ThrowIfDisposed", NonPublic | Instance);

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, throwMethod);

            // Emit the parameters as usual
            base.EmitPrologue(il, workUnit);
        }
Ejemplo n.º 14
0
        /// <inheritdoc />
        public virtual void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            // Load the "this" reference
            il.EmitLoadArgument(0);

            for (short i = 1; i <= workUnit.Definition.ParameterTypes.Count; ++i)
            {
                il.EmitLoadArgument(i);
            }
        }
Ejemplo n.º 15
0
        /// <inheritdoc />
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var returnType = workUnit.Definition.ReturnType;

            if (IsSpanType(returnType))
            {
                il.EmitConstantInt(GetNativeCollectionLengthMetadata(workUnit.Definition).Length);
                il.EmitNewObject(returnType.GetConstructor(new[] { typeof(void *), typeof(int) }));
            }
        }
        /// <inheritdoc />
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var locals = _workUnitLocals[workUnit];

            if (locals.Any())
            {
                // We have cleanup to do (freeing unmanaged string memory)
                foreach (var localCombo in locals)
                {
                    var parameterIndex = localCombo.Key;
                    var local          = localCombo.Value;

                    var unmanagedStringType = GetParameterUnmanagedType(definition.ParameterCustomAttributes[parameterIndex]);
                    il.EmitLoadLocalVariable(local);
                    il.EmitCallDirect(SelectUnmanagedFreeMethod(unmanagedStringType));
                }

                _workUnitLocals.Remove(workUnit);
            }

            if (definition.ReturnType != typeof(string))
            {
                return;
            }

            var unmanagedReturnStringType = GetParameterUnmanagedType(definition.ReturnParameterCustomAttributes);

            if (definition.ReturnParameterHasCustomAttribute <CallerFreeAttribute>())
            {
                var ptrLocal    = il.DeclareLocal(typeof(IntPtr));
                var returnLocal = il.DeclareLocal(typeof(string));

                // Store the pointer returned from native code
                il.EmitSetLocalVariable(ptrLocal);

                // Marshal the string from the pointer, and store it
                il.EmitLoadLocalVariable(ptrLocal);
                il.EmitCallDirect(SelectUnmanagedToManagedTransformationMethod(unmanagedReturnStringType));
                il.EmitSetLocalVariable(returnLocal);

                // Free the pointer
                il.EmitLoadLocalVariable(ptrLocal);
                il.EmitCallDirect(SelectUnmanagedFreeMethod(unmanagedReturnStringType));

                // Load the string
                il.EmitLoadLocalVariable(returnLocal);
            }
            else
            {
                il.EmitCallDirect(SelectUnmanagedToManagedTransformationMethod(unmanagedReturnStringType));
            }
        }
Ejemplo n.º 17
0
        /// <inheritdoc />
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            if (definition.ReturnType != typeof(bool))
            {
                return;
            }

            var unmanagedType = GetParameterUnmanagedType(definition.ReturnParameterCustomAttributes);

            EmitUnmanagedIntegerToBooleanConversion(il, unmanagedType);
        }
Ejemplo n.º 18
0
        public virtual IntrospectiveMethodInfo GeneratePassthroughDefinition([NotNull] PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var passthroughMethod = TargetType.DefineMethod
                                    (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapper",
                Private | Virtual | HideBySig,
                CallingConventions.Standard,
                definition.ReturnType,
                definition.ParameterTypes.ToArray()
                                    );

            passthroughMethod.ApplyCustomAttributesFrom(workUnit.Definition);

            return(new IntrospectiveMethodInfo(passthroughMethod, definition.ReturnType, definition.ParameterTypes, definition));
        }
        private TypeBuilder GenerateDelegateType
        (
            [NotNull] PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
        )
        {
            var definition = workUnit.Definition;

            // Declare a delegate type
            var delegateBuilder = TargetModule.DefineDelegate
                                  (
                $"{workUnit.GetUniqueBaseMemberName()}_delegate",
                definition,
                Options.HasFlagFast(SuppressSecurity)
                                  );

            return(delegateBuilder);
        }
        /// <inheritdoc/>
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            il.EmitLoadArgument(0);
            for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
            {
                var parameterType = definition.ParameterTypes[i - 1];

                if (!parameterType.IsDelegate())
                {
                    il.EmitLoadArgument(i);
                    continue;
                }

                var lifetime = GetParameterDelegateLifetime(definition.ParameterCustomAttributes[i - 1]);

                if (lifetime == DelegateLifetime.Persistent)
                {
                    // Keep delegate alive.

                    // Load this
                    il.EmitLoadArgument(0);
                    il.EmitLoadArgument(i);
                    il.Emit(OpCodes.Call, _allocMethod);
                }

                // Convert delegate to IntPtr. (IntPtr.Zero for null)
                var marshalToPtrLabel = il.DefineLabel();
                var endLabel          = il.DefineLabel();

                il.EmitLoadArgument(i);
                il.Emit(OpCodes.Brtrue_S, marshalToPtrLabel);

                // Delegate is null -> load IntPtr.Zero and branch to end...
                il.Emit(OpCodes.Ldsfld, _intPtrZero);
                il.Emit(OpCodes.Br_S, endLabel);

                // Delegate is non null -> call Marshal.GetFunctionPointerForDelegate and load it's resulting IntPtr...
                il.MarkLabel(marshalToPtrLabel);
                il.EmitLoadArgument(i);
                il.Emit(OpCodes.Call, _marshalDelToPointer);

                il.MarkLabel(endLabel);
            }
        }
Ejemplo n.º 21
0
        /// <inheritdoc/>
        public override void EmitAdditionalTypes
        (
            ModuleBuilder module,
            PipelineWorkUnit <IntrospectiveMethodInfo> workUnit
        )
        {
            var definition = workUnit.Definition;

            foreach (var parameterType in definition.ParameterTypes.Concat(new[] { definition.ReturnType }))
            {
                if (!parameterType.IsGenericDelegate())
                {
                    continue;
                }

                EmitExplicitDelegateDefinition(module, parameterType);
            }
        }
Ejemplo n.º 22
0
        /// <inheritdoc />
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            // Load the "this" reference
            il.EmitLoadArgument(0);

            for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
            {
                il.EmitLoadArgument(i);

                var parameterType = definition.ParameterTypes[i - 1];
                if (parameterType != typeof(bool))
                {
                    continue;
                }

                // Convert the input boolean to an unmanaged integer
                var unmanagedType = GetParameterUnmanagedType(definition.ParameterCustomAttributes[i - 1]);
                EmitBooleanToUnmanagedIntegerConversion(il, unmanagedType);
            }
        }
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            if (!workUnit.Definition.ReturnType.GenericTypeArguments[0].IsValueType)
            {
                // Span<byte> is used because unbound generics are not allowed inside a nameof, and it still results as just 'Span'
                throw new NotSupportedException($"Method is not a {nameof(ValueType)} and cannot be marshaled as a {nameof(Span<byte>)}. Marshalling {nameof(Span<byte>)}" +
                                                $"requires the marshaled type T in {nameof(Span<byte>)}<T> to be a {nameof(ValueType)}");
            }

            var definition = workUnit.Definition;

            Type newReturnType = definition.ReturnType.GenericTypeArguments[0].MakePointerType();

            /* TODO? Add marshaling for Span<> params */

            Type[] parametersTypes = definition.ParameterTypes.ToArray();

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
Ejemplo n.º 24
0
        /// <inheritdoc />
        public override IEnumerable <PipelineWorkUnit <IntrospectiveMethodInfo> > GenerateImplementation(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var backingFieldType = typeof(IntPtr);

            var backingField = Options.HasFlagFast(UseLazyBinding)
            ? TargetType.DefineField
                               (
                $"{workUnit.GetUniqueBaseMemberName()}_ptr_lazy",
                typeof(Lazy <>).MakeGenericType(backingFieldType),
                FieldAttributes.Private | FieldAttributes.InitOnly
                               )
            : TargetType.DefineField
                               (
                $"{workUnit.GetUniqueBaseMemberName()}_ptr",
                backingFieldType,
                FieldAttributes.Private | FieldAttributes.InitOnly
                               );

            AugmentHostingTypeConstructorWithNativeInitialization(workUnit.SymbolName, backingFieldType, backingField);
            GenerateNativeInvokerBody(definition, definition.GetNativeCallingConvention(), backingField);

            yield break;
        }
Ejemplo n.º 25
0
        /// <inheritdoc />
        public override IntrospectiveMethodInfo GeneratePassthroughDefinition(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var  returnType = workUnit.Definition.ReturnType;
            Type newReturnType;
            var  definition = workUnit.Definition;

            if (IsSpanType(returnType))
            {
                var genericType = returnType.GenericTypeArguments[0];

                if (!genericType.IsUnmanaged())
                {
                    throw new NotSupportedException($"Method return type must be blittable.");
                }

                newReturnType = genericType.MakePointerType();
            }
            else
            {
                newReturnType = returnType;
            }

            var parametersTypes = definition.ParameterTypes.ToArray();

            for (int i = 0; i < parametersTypes.Length; ++i)
            {
                var paramType = parametersTypes[i];
                if (IsSpanType(paramType))
                {
                    var genericParam = paramType.GenericTypeArguments[0];

                    if (genericParam.IsGenericType)
                    {
                        throw new NotSupportedException("Generic type found as Span generic argument");
                    }

                    if (!genericParam.IsUnmanaged())
                    {
                        throw new NotSupportedException("Reference or value type containing references found in Span<T> or ReadOnlySpan<T> generic parameter.");
                    }

                    parametersTypes[i] = genericParam.MakePointerType(); // genercParam.MakePointerType();
                }
            }

            MethodBuilder passthroughMethod = TargetType.DefineMethod
                                              (
                $"{workUnit.GetUniqueBaseMemberName()}_wrapped",
                MethodAttributes.Private | MethodAttributes.Virtual | MethodAttributes.HideBySig,
                CallingConventions.Standard,
                newReturnType,
                parametersTypes
                                              );

            passthroughMethod.ApplyCustomAttributesFrom(definition, newReturnType, parametersTypes);

            return(new IntrospectiveMethodInfo
                   (
                       passthroughMethod,
                       newReturnType,
                       parametersTypes,
                       definition.MetadataType,
                       definition
                   ));
        }
Ejemplo n.º 26
0
        /// <inheritdoc />
        public override void EmitPrologue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var locals = new Dictionary <int, LocalBuilder>();

            _workUnitLocals.Add(workUnit, locals);

            // Load the "this" reference
            il.EmitLoadArgument(0);

            for (short i = 1; i <= definition.ParameterTypes.Count; ++i)
            {
                var parameterType = definition.ParameterTypes[i - 1];
                if (!parameterType.IsNonRefNullable())
                {
                    il.EmitLoadArgument(i);
                    continue;
                }

                var nullableType   = parameterType.GetGenericArguments().First();
                var hasValueMethod = GetHasValueMethod(nullableType);
                var getValueMethod = GetGetValueMethod(nullableType);

                var hasValueLabel = il.DefineLabel();
                var branchEnd     = il.DefineLabel();

                var ptrLocal = il.DeclareLocal(typeof(IntPtr));

                il.EmitLoadArgumentAddress(i);
                il.EmitCallDirect(hasValueMethod);

                il.EmitBranchTrue(hasValueLabel);
                // false case - no value, pass null
                {
                    il.EmitLoadStaticField(_nullPtrField);
                    il.EmitBranch(branchEnd);
                }
                // true case - marshal the structure to a pointer, pass it
                il.MarkLabel(hasValueLabel);
                {
                    il.EmitSizeOf(nullableType);
                    il.EmitCallDirect(_allocHGlobalMethod);
                    il.EmitSetLocalVariable(ptrLocal);

                    il.EmitLoadArgumentAddress(i);
                    il.EmitCallDirect(getValueMethod);
                    il.EmitBox(nullableType);
                    il.EmitLoadLocalVariable(ptrLocal);
                    il.EmitConstantInt(0);

                    il.EmitCallDirect(_structureToPtrMethod);

                    il.EmitLoadLocalVariable(ptrLocal);
                }

                il.MarkLabel(branchEnd);

                if (definition.ParameterHasCustomAttribute <CallerFreeAttribute>(i - 1))
                {
                    il.EmitSetLocalVariable(ptrLocal);
                    il.EmitLoadLocalVariable(ptrLocal);

                    locals.Add(i - 1, ptrLocal);
                }
            }
        }
Ejemplo n.º 27
0
        /// <inheritdoc />
        public override void EmitEpilogue(ILGenerator il, PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var locals = _workUnitLocals[workUnit];

            if (locals.Any())
            {
                // We have cleanup to do (freeing unmanaged structure memory)
                foreach (var localCombo in locals)
                {
                    var local           = localCombo.Value;
                    var hasPointerLabel = il.DefineLabel();
                    var branchEnd       = il.DefineLabel();

                    // Check if we have a pointer to clean up
                    il.EmitLoadLocalVariable(local);
                    il.EmitLoadStaticField(_nullPtrField);
                    il.EmitCallDirect(_ptrInequalityOperator);

                    il.EmitBranchTrue(hasPointerLabel);
                    // false case, null pointer
                    {
                        il.EmitBranch(branchEnd);
                    }
                    // true case, has pointer
                    il.MarkLabel(hasPointerLabel);
                    {
                        il.EmitLoadLocalVariable(local);
                        il.EmitCallDirect(_freeHGlobalMethod);
                    }
                    il.MarkLabel(branchEnd);
                }

                _workUnitLocals.Remove(workUnit);
            }

            if (!definition.ReturnType.IsNonRefNullable())
            {
                return;
            }

            var nullableType         = definition.ReturnType.GetGenericArguments().First();
            var ptrToStructureMethod = _ptrToStructureMethodBase.MakeGenericMethod(nullableType);

            var returnIsNotNullLabel = il.DefineLabel();
            var returnBranchEndLabel = il.DefineLabel();

            var closedNullableType = typeof(Nullable <>).MakeGenericType(nullableType);
            var returnLocal        = il.DeclareLocal(closedNullableType);

            var ptrLocal = il.DeclareLocal(typeof(IntPtr));

            // Store the pointer returned from native code
            il.EmitSetLocalVariable(ptrLocal);

            // Check if we have a valid value
            il.EmitLoadLocalVariable(ptrLocal);
            il.EmitLoadStaticField(_nullPtrField);
            il.EmitCallDirect(_ptrInequalityOperator);
            il.EmitBranchTrue(returnIsNotNullLabel);
            // false case, return null
            {
                il.EmitLoadLocalVariableAddress(returnLocal);
                il.EmitInitObject(closedNullableType);
                il.EmitLoadLocalVariable(returnLocal);
                il.EmitBranch(returnBranchEndLabel);
            }
            // true case, return marshalled structure
            il.MarkLabel(returnIsNotNullLabel);
            {
                // Marshal the structure from the pointer
                il.EmitLoadLocalVariable(ptrLocal);
                il.EmitCallDirect(ptrToStructureMethod);
                if (definition.ReturnParameterHasCustomAttribute <CallerFreeAttribute>())
                {
                    var marshalledReturnLocal = il.DeclareLocal(nullableType);

                    // And store it
                    il.EmitSetLocalVariable(marshalledReturnLocal);

                    // Free the pointer
                    il.EmitLoadLocalVariable(ptrLocal);
                    il.EmitCallDirect(_freeHGlobalMethod);

                    // Load the structure
                    il.EmitLoadLocalVariable(marshalledReturnLocal);
                }

                il.EmitNewObject(GetNullableConstructor(nullableType));
            }
            il.MarkLabel(returnBranchEndLabel);
        }
Ejemplo n.º 28
0
        /// <inheritdoc />
        public override IEnumerable <PipelineWorkUnit <IntrospectiveMethodInfo> > GenerateImplementation(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var permutations = new List <IntrospectiveMethodInfo>();
            var definition   = workUnit.Definition;

            // Generate permutation definitions
            var parameterPermutations = _permutationGenerator.Generate(definition);

            for (int i = 0; i < parameterPermutations.Count; ++i)
            {
                var permutation = parameterPermutations[i];
                var method      = TargetType.DefineMethod
                                  (
                    $"{workUnit.GetUniqueBaseMemberName()}_permutation_{i}",
                    Public | Final | Virtual | HideBySig | NewSlot,
                    CallingConventions.Standard,
                    definition.ReturnType,
                    permutation.ToArray()
                                  );

                var methodInfo = new IntrospectiveMethodInfo(method, definition.ReturnType, permutation, definition);
                permutations.Add(methodInfo);
            }

            GenerateTopLevelMethodImplementation(definition, permutations);

            // Pass the permutations on for further processing
            foreach (var permutation in permutations)
            {
                yield return(new PipelineWorkUnit <IntrospectiveMethodInfo>(permutation, workUnit));
            }
        }
        /// <inheritdoc />
        public override IEnumerable <PipelineWorkUnit <IntrospectiveMethodInfo> > GenerateImplementation(PipelineWorkUnit <IntrospectiveMethodInfo> workUnit)
        {
            var definition = workUnit.Definition;

            var delegateBuilder = GenerateDelegateType(workUnit);

            // Create a delegate field
            var backingFieldType = delegateBuilder.CreateTypeInfo();

            var backingField = Options.HasFlagFast(UseLazyBinding)
            ? TargetType.DefineField
                               (
                $"{workUnit.GetUniqueBaseMemberName()}_delegate_lazy",
                typeof(Lazy <>).MakeGenericType(backingFieldType),
                FieldAttributes.Private | FieldAttributes.InitOnly
                               )
            : TargetType.DefineField
                               (
                $"{workUnit.GetUniqueBaseMemberName()}_delegate",
                backingFieldType,
                FieldAttributes.Private | FieldAttributes.InitOnly
                               );

            AugmentHostingTypeConstructorWithDelegateInitialization(workUnit.SymbolName, backingFieldType, backingField);
            GenerateDelegateInvokerBody(definition, backingFieldType, backingField);

            yield break;
        }
Ejemplo n.º 30
0
        /// <inheritdoc />
        public override IEnumerable <PipelineWorkUnit <IntrospectivePropertyInfo> > GenerateImplementation(PipelineWorkUnit <IntrospectivePropertyInfo> workUnit)
        {
            var property = workUnit.Definition;

            var propertyBuilder = TargetType.DefineProperty
                                  (
                property.Name,
                PropertyAttributes.None,
                CallingConventions.HasThis,
                property.PropertyType,
                property.IndexParameterTypes.ToArray()
                                  );

            // Note, the field is going to have to be a pointer, because it is pointing to global variable
            var fieldType            = Options.HasFlagFast(UseLazyBinding) ? typeof(Lazy <IntPtr>) : typeof(IntPtr);
            var propertyFieldBuilder = TargetType.DefineField
                                       (
                $"{workUnit.GetUniqueBaseMemberName()}_backing",
                fieldType,
                FieldAttributes.Private
                                       );

            if (property.CanRead)
            {
                GeneratePropertyGetter(property, propertyFieldBuilder, propertyBuilder);
            }

            if (property.CanWrite)
            {
                GeneratePropertySetter(property, propertyFieldBuilder, propertyBuilder);
            }

            AugmentHostingTypeConstructor(workUnit.SymbolName, propertyFieldBuilder);

            yield break;
        }