예제 #1
0
        internal static void VerifyAttributeUsage(this AttributeKind kind, FunctionAttributeIndex index)
        {
            kind.ValidateDefined(nameof(kind));

            FunctionIndexKinds allowedIndexes = kind.GetAllowedIndexes( );

            switch (index)
            {
            case FunctionAttributeIndex.Function:
                if (!allowedIndexes.HasFlag(FunctionIndexKinds.Function))
                {
                    throw new ArgumentException(Resources.Attribute_not_allowed_on_functions, nameof(index));
                }

                break;

            case FunctionAttributeIndex.ReturnType:
                if (!allowedIndexes.HasFlag(FunctionIndexKinds.Return))
                {
                    throw new ArgumentException(Resources.Attribute_not_allowed_on_function_Return, nameof(index));
                }

                break;

            // case FunctionAttributeIndex.Parameter0:
            default:
                if (!allowedIndexes.HasFlag(FunctionIndexKinds.Parameter))
                {
                    throw new ArgumentException(Resources.Attribute_not_allowed_on_function_parameter, nameof(index));
                }

                break;
            }
        }
예제 #2
0
        /// <summary>Determines if a collection of <see cref="AttributeValue"/> contains a given <see cref="AttributeKind"/></summary>
        /// <param name="self">Collection to test</param>
        /// <param name="kind"><see cref="AttributeKind"/> to search for</param>
        /// <returns><see langword="true"/> if found</returns>
        public static bool Contains([ValidatedNotNull] this ICollection <AttributeValue> self, AttributeKind kind)
        {
            self.ValidateNotNull(nameof(self));
            kind.ValidateDefined(nameof(kind));

            return(self.Any(a => a.Kind == kind));
        }
예제 #3
0
        /// <summary>Adds an attribute to an <see cref="Argument"/></summary>
        /// <param name="kind"><see cref="AttributeKind"/> to add</param>
        /// <returns>
        /// This Argument for Fluent access
        /// </returns>
        public Argument AddAttribute(AttributeKind kind)
        {
            kind.ValidateDefined(nameof(kind));

            Attributes.Add(Context.CreateAttribute(kind));

            return(this);
        }
예제 #4
0
        /// <summary>Adds an attribute to an <see cref="Argument"/></summary>
        /// <param name="self">The <see cref="Argument"/> to add attributes to</param>
        /// <param name="kind"><see cref="AttributeKind"/> to add</param>
        /// <returns>
        /// <paramref name="self"/> for Fluent access
        /// </returns>
        public static Argument AddAttribute([ValidatedNotNull] this Argument self, AttributeKind kind)
        {
            self.ValidateNotNull(nameof(self));
            kind.ValidateDefined(nameof(self));

            self.Attributes.Add(self.Context.CreateAttribute(kind));

            return(self);
        }
예제 #5
0
        /// <summary>Removes an <see cref="AttributeKind"/> from an <see cref="Argument"/></summary>
        /// <param name="self">The <see cref="Argument"/> to add attributes to</param>
        /// <param name="kind"><see cref="AttributeKind"/> to remove</param>
        /// <returns>
        /// <paramref name="self"/> for Fluent access
        /// </returns>
        public static Argument RemoveAttribute([ValidatedNotNull] this Argument self, AttributeKind kind)
        {
            kind.ValidateDefined(nameof(kind));
            if (kind == AttributeKind.None)
            {
                return(self);
            }

            return(RemoveAttribute(self, kind.GetAttributeName( )));
        }
예제 #6
0
        /// <summary>Removes an <see cref="AttributeKind"/> from an <see cref="Argument"/></summary>
        /// <param name="kind"><see cref="AttributeKind"/> to remove</param>
        /// <returns>This Argument for fluent usage</returns>
        public Argument RemoveAttribute(AttributeKind kind)
        {
            kind.ValidateDefined(nameof(kind));
            if (kind == AttributeKind.None)
            {
                return(this);
            }

            return(RemoveAttribute(kind.GetAttributeName( )));
        }
예제 #7
0
        /// <summary>Creates an attribute with an integer value parameter</summary>
        /// <param name="kind">The kind of attribute</param>
        /// <param name="value">Value for the attribute</param>
        /// <remarks>
        /// <para>Not all attributes support a value and those that do don't all support
        /// a full 64bit value. The following table provides the kinds of attributes
        /// accepting a value and the allowed size of the values.</para>
        /// <list type="table">
        /// <listheader><term><see cref="AttributeKind"/></term><term>Bit Length</term></listheader>
        /// <item><term><see cref="AttributeKind.Alignment"/></term><term>32</term></item>
        /// <item><term><see cref="AttributeKind.StackAlignment"/></term><term>32</term></item>
        /// <item><term><see cref="AttributeKind.Dereferenceable"/></term><term>64</term></item>
        /// <item><term><see cref="AttributeKind.DereferenceableOrNull"/></term><term>64</term></item>
        /// </list>
        /// </remarks>
        /// <returns><see cref="AttributeValue"/> with the specified kind and value</returns>
        public AttributeValue CreateAttribute(AttributeKind kind, UInt64 value)
        {
            kind.ValidateDefined(nameof(kind));
            if (!kind.RequiresIntValue( ))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Attribute_0_does_not_support_a_value, kind), nameof(kind));
            }

            var handle = LLVMCreateEnumAttribute(ContextHandle
                                                 , kind.GetEnumAttributeId( )
                                                 , value
                                                 );

            return(AttributeValue.FromHandle(this, handle));
        }
예제 #8
0
        /// <summary>Creates an attribute with an integer value parameter</summary>
        /// <param name="kind">The kind of attribute</param>
        /// <param name="value">Value for the attribute</param>
        /// <remarks>
        /// <para>Not all attributes support a value and those that do don't all support
        /// a full 64bit value. The following table provides the kinds of attributes
        /// accepting a value and the allowed size of the values.</para>
        /// <list type="table">
        /// <listheader><term><see cref="AttributeKind"/></term><term>Bit Length</term></listheader>
        /// <item><term><see cref="AttributeKind.Alignment"/></term><term>32</term></item>
        /// <item><term><see cref="AttributeKind.StackAlignment"/></term><term>32</term></item>
        /// <item><term><see cref="AttributeKind.Dereferenceable"/></term><term>64</term></item>
        /// <item><term><see cref="AttributeKind.DereferenceableOrNull"/></term><term>64</term></item>
        /// </list>
        /// </remarks>
        /// <returns><see cref="AttributeValue"/> with the specified kind and value</returns>
        public AttributeValue CreateAttribute(AttributeKind kind, UInt64 value)
        {
            kind.ValidateDefined(nameof(kind));
            if (!kind.RequiresIntValue( ))
            {
                throw new ArgumentException($"Attribute {kind} does not support a value", nameof(kind));
            }

            var handle = LLVMCreateEnumAttribute(ContextHandle
                                                 , kind.GetEnumAttributeId( )
                                                 , value
                                                 );

            return(AttributeValue.FromHandle(this, handle));
        }
예제 #9
0
        /// <summary>Gets a value indicating whether the attribute requires an integer parameter value</summary>
        /// <param name="kind"><see cref="AttributeKind"/> to check</param>
        /// <returns><see langword="true"/> if the attribute requires an integer value</returns>
        public static bool RequiresIntValue(this AttributeKind kind)
        {
            kind.ValidateDefined(nameof(kind));

            switch (kind)
            {
            case AttributeKind.Alignment:
            case AttributeKind.StackAlignment:
            case AttributeKind.Dereferenceable:
            case AttributeKind.DereferenceableOrNull:
                return(true);

            default:
                return(false);
            }
        }
예제 #10
0
        internal static void RangeCheckValue(this AttributeKind kind, ulong value)
        {
            kind.ValidateDefined(nameof(kind));

            // To prevent native asserts or crashes - validate parameters before passing down to native code
            switch (kind)
            {
            case AttributeKind.Alignment:
                if (value > UInt32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), Resources.Expected_a_32_bit_value_for_alignment);
                }

                break;

            case AttributeKind.StackAlignment:
                if (value > UInt32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), Resources.Expected_a_32_bit_value_for_stack_alignment);
                }

                if (value != 0 && !IsPowerOfTwo(value))
                {
                    throw new ArgumentException(Resources.Stack_alignment_value_must_be_a_power_of_2, nameof(value));
                }

                break;

            case AttributeKind.Dereferenceable:
            case AttributeKind.DereferenceableOrNull:
                break;

            default:
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.Attribute_0_does_not_support_an_argument, kind), nameof(kind));
            }
        }
예제 #11
0
        internal static void RangeCheckValue(this AttributeKind kind, ulong value)
        {
            kind.ValidateDefined(nameof(kind));

            // To prevent native asserts or crashes - validate parameters before passing down to native code
            switch (kind)
            {
            case AttributeKind.Alignment:
                if (value > UInt32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "Expected a 32 bit value for alignment");
                }

                break;

            case AttributeKind.StackAlignment:
                if (value > UInt32.MaxValue)
                {
                    throw new ArgumentOutOfRangeException(nameof(value), "Expected a 32 bit value for stack alignment");
                }

                if (value != 0 && !IsPowerOfTwo(value))
                {
                    throw new ArgumentException("Stack alignment value must be a power of 2", nameof(value));
                }

                break;

            case AttributeKind.Dereferenceable:
            case AttributeKind.DereferenceableOrNull:
                break;

            default:
                throw new ArgumentException($"Attribute '{kind}' does not support an argument", nameof(kind));
            }
        }
예제 #12
0
        internal static FunctionIndexKinds GetAllowedIndexes(this AttributeKind kind)
        {
            kind.ValidateDefined(nameof(kind));

            switch (kind)
            {
            default:
                return(FunctionIndexKinds.None);

            case AttributeKind.ReadOnly:
            case AttributeKind.WriteOnly:
            case AttributeKind.ReadNone:
                return(FunctionIndexKinds.Function | FunctionIndexKinds.Parameter);

            case AttributeKind.ByVal:
            case AttributeKind.InAlloca:
            case AttributeKind.StructRet:
            case AttributeKind.Nest:
            case AttributeKind.NoCapture:
            case AttributeKind.Returned:
            case AttributeKind.SwiftSelf:
            case AttributeKind.SwiftError:
                return(FunctionIndexKinds.Parameter);

            case AttributeKind.ZExt:
            case AttributeKind.SExt:
            case AttributeKind.InReg:
            case AttributeKind.Alignment:
            case AttributeKind.NoAlias:
            case AttributeKind.NonNull:
            case AttributeKind.Dereferenceable:
            case AttributeKind.DereferenceableOrNull:
                return(FunctionIndexKinds.Parameter | FunctionIndexKinds.Return);

            case AttributeKind.NoReturn:
            case AttributeKind.NoUnwind:
            case AttributeKind.NoInline:
            case AttributeKind.AlwaysInline:
            case AttributeKind.OptimizeForSize:
            case AttributeKind.StackProtect:
            case AttributeKind.StackProtectReq:
            case AttributeKind.StackProtectStrong:
            case AttributeKind.SafeStack:
            case AttributeKind.NoRedZone:
            case AttributeKind.NoImplicitFloat:
            case AttributeKind.Naked:
            case AttributeKind.InlineHint:
            case AttributeKind.StackAlignment:
            case AttributeKind.UWTable:
            case AttributeKind.NonLazyBind:
            case AttributeKind.ReturnsTwice:
            case AttributeKind.SanitizeAddress:
            case AttributeKind.SanitizeThread:
            case AttributeKind.SanitizeMemory:
            case AttributeKind.MinSize:
            case AttributeKind.NoDuplicate:
            case AttributeKind.Builtin:
            case AttributeKind.NoBuiltin:
            case AttributeKind.Cold:
            case AttributeKind.OptimizeNone:
            case AttributeKind.JumpTable:
            case AttributeKind.Convergent:
            case AttributeKind.ArgMemOnly:
            case AttributeKind.NoRecurse:
            case AttributeKind.InaccessibleMemOnly:
            case AttributeKind.InaccessibleMemOrArgMemOnly:
            case AttributeKind.AllocSize:
            case AttributeKind.Speculatable:
                return(FunctionIndexKinds.Function);
            }
        }
예제 #13
0
        internal static bool CheckAttributeUsage(this AttributeKind kind, FunctionAttributeIndex index, Value value)
        {
            kind.ValidateDefined(nameof(kind));

            FunctionIndexKinds allowedindices = kind.GetAllowedIndexes( );

            switch (index)
            {
            case FunctionAttributeIndex.Function:
                if (!allowedindices.HasFlag(FunctionIndexKinds.Function))
                {
                    return(false);
                }

                break;

            case FunctionAttributeIndex.ReturnType:
                if (!allowedindices.HasFlag(FunctionIndexKinds.Return))
                {
                    return(false);
                }

                break;

            // case FunctionAttributeIndex.Parameter0:
            default:
            {
                if (value == null)
                {
                    throw new ArgumentNullException(nameof(value));
                }

                if (!allowedindices.HasFlag(FunctionIndexKinds.Parameter))
                {
                    return(false);
                }

                IrFunction function;
                switch (value)
                {
                case IrFunction f:
                    function = f;
                    break;

                case Invoke inv:
                    function = inv.TargetFunction;
                    break;

                case CallInstruction call:
                    function = call.TargetFunction;
                    break;

                case Argument arg:
                    function = arg.ContainingFunction;
                    if (index != FunctionAttributeIndex.Parameter0 + ( int )arg.Index)
                    {
                        return(false);
                    }

                    break;

                default:
                    function = null;
                    break;
                }

                int paramIndex = index - FunctionAttributeIndex.Parameter0;
                if (paramIndex >= (function?.Parameters.Count ?? 0))
                {
                    return(false);
                }
            }

            break;
            }

            return(true);
        }