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; } }
/// <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)); }
/// <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); }
/// <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); }
/// <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( ))); }
/// <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( ))); }
/// <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)); }
/// <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)); }
/// <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); } }
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)); } }
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)); } }
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); } }
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); }