From e50c43087cc72c9302589d050a7dece9f3c792ab Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:03:09 +0000 Subject: [PATCH 1/5] Initial plan From 6545c29aa19a499a3dd5d2bd93915c9d69b55480 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:31:21 +0000 Subject: [PATCH 2/5] Add documentation for core LLVM IR generator classes and enums Co-authored-by: grendello <184788+grendello@users.noreply.github.com> --- .../LlvmIrAddressSignificance.cs | 9 + .../LlvmIrGenerator/LlvmIrComposer.cs | 34 +++ .../LlvmIrGenerator/LlvmIrIcmpCond.cs | 33 +++ .../LlvmIrGenerator/LlvmIrLinkage.cs | 33 +++ .../LlvmIrGenerator/LlvmIrStringEncoding.cs | 9 + .../LlvmIrGenerator/LlvmIrVariable.cs | 239 ++++++++++++++++-- .../LlvmIrGenerator/LlvmIrWritability.cs | 8 +- 7 files changed, 338 insertions(+), 27 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrAddressSignificance.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrAddressSignificance.cs index 5dc9203d385..264d5b3ee52 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrAddressSignificance.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrAddressSignificance.cs @@ -8,8 +8,17 @@ namespace Xamarin.Android.Tasks.LLVMIR [Flags] enum LlvmIrAddressSignificance { + /// + /// Default address significance. + /// Default = 1 << 0, + /// + /// Unnamed address significance - the address of the global is not significant. + /// Unnamed = 1 << 1, + /// + /// Local unnamed address significance - the address is not significant within the module. + /// LocalUnnamed = 1 << 2, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrComposer.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrComposer.cs index 589ab5e7c48..76252092354 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrComposer.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrComposer.cs @@ -7,6 +7,9 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Abstract base class for composing LLVM IR modules. Provides a framework for constructing and generating LLVM IR code. + /// abstract class LlvmIrComposer { bool constructed; @@ -14,13 +17,26 @@ abstract class LlvmIrComposer protected readonly TaskLoggingHelper Log; + /// + /// Initializes a new instance of the class. + /// + /// The task logging helper for logging messages. + /// Thrown when is null. protected LlvmIrComposer (TaskLoggingHelper log) { this.Log = log ?? throw new ArgumentNullException (nameof (log)); } + /// + /// When overridden in a derived class, constructs the LLVM IR module by adding the necessary structures, functions, and variables. + /// + /// The LLVM IR module to construct. protected abstract void Construct (LlvmIrModule module); + /// + /// Constructs the LLVM IR module by calling the derived class implementation and performing necessary finalization. + /// + /// The constructed LLVM IR module. public LlvmIrModule Construct () { var module = new LlvmIrModule (cache, Log); @@ -31,6 +47,14 @@ public LlvmIrModule Construct () return module; } + /// + /// Generates LLVM IR code for the specified target architecture and writes it to the output stream. + /// + /// The LLVM IR module to generate code from. + /// The target Android architecture. + /// The stream writer to write the generated LLVM IR code to. + /// The name of the file being generated. + /// Thrown when the module has not been constructed yet. public void Generate (LlvmIrModule module, AndroidTargetArch arch, StreamWriter output, string fileName) { if (!constructed) { @@ -44,9 +68,19 @@ public void Generate (LlvmIrModule module, AndroidTargetArch arch, StreamWriter CleanupAfterGeneration (arch); } + /// + /// Performs any necessary cleanup after code generation for the specified architecture. + /// + /// The target Android architecture that was used for generation. protected virtual void CleanupAfterGeneration (AndroidTargetArch arch) {} + /// + /// Ensures that the specified variable is a global variable and returns it as such. + /// + /// The variable to check and cast. + /// The variable cast as a global variable. + /// Thrown when the variable is not a global variable. protected LlvmIrGlobalVariable EnsureGlobalVariable (LlvmIrVariable variable) { var gv = variable as LlvmIrGlobalVariable; diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrIcmpCond.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrIcmpCond.cs index 68310783d42..63b7602c02d 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrIcmpCond.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrIcmpCond.cs @@ -1,16 +1,49 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Represents comparison conditions for the LLVM IR icmp instruction. + /// enum LlvmIrIcmpCond { + /// + /// Equal comparison (eq). + /// Equal, + /// + /// Not equal comparison (ne). + /// NotEqual, + /// + /// Unsigned greater than comparison (ugt). + /// UnsignedGreaterThan, + /// + /// Unsigned greater than or equal comparison (uge). + /// UnsignedGreaterOrEqual, + /// + /// Unsigned less than comparison (ult). + /// UnsignedLessThan, + /// + /// Unsigned less than or equal comparison (ule). + /// UnsignedLessOrEqual, + /// + /// Signed greater than comparison (sgt). + /// SignedGreaterThan, + /// + /// Signed greater than or equal comparison (sge). + /// SignedGreaterOrEqual, + /// + /// Signed less than comparison (slt). + /// SignedLessThan, + /// + /// Signed less than or equal comparison (sle). + /// SignedLessOrEqual, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrLinkage.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrLinkage.cs index da11f93761b..9e84138ae9b 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrLinkage.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrLinkage.cs @@ -8,16 +8,49 @@ namespace Xamarin.Android.Tasks.LLVMIR [Flags] enum LlvmIrLinkage { + /// + /// Default linkage (external). + /// Default = 0 << 0, + /// + /// Private linkage - symbol is not accessible from outside the module. + /// Private = 1 << 0, + /// + /// Internal linkage - symbol is accessible within the current module only. + /// Internal = 1 << 1, + /// + /// Available externally linkage - symbol is available for inspection but not emission. + /// AvailableExternally = 1 << 2, + /// + /// Link once linkage - symbol may be defined in multiple modules but only one will be chosen. + /// LinkOnce = 1 << 3, + /// + /// Weak linkage - symbol may be overridden by other definitions. + /// Weak = 1 << 4, + /// + /// Common linkage - for uninitialized global variables. + /// Common = 1 << 5, + /// + /// Appending linkage - for arrays that should be concatenated with arrays from other modules. + /// Appending = 1 << 6, + /// + /// Extern weak linkage - weak reference to external symbol. + /// ExternWeak = 1 << 7, + /// + /// Link once ODR linkage - link once with One Definition Rule enforcement. + /// LinkOnceODR = 1 << 8, + /// + /// External linkage - symbol is accessible from outside the module. + /// External = 1 << 9, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrStringEncoding.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrStringEncoding.cs index abbad82df4f..3186e63f070 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrStringEncoding.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrStringEncoding.cs @@ -1,7 +1,16 @@ namespace Xamarin.Android.Tasks.LLVMIR; +/// +/// Specifies the encoding used for string variables in LLVM IR. +/// enum LlvmIrStringEncoding { + /// + /// UTF-8 encoding using i8 LLVM IR type. + /// UTF8, + /// + /// Unicode (UTF-16) encoding using i16 LLVM IR type. + /// Unicode, } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs index 29df53cf43f..4b2165e66a3 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs @@ -6,57 +6,122 @@ namespace Xamarin.Android.Tasks.LLVMIR; +/// +/// Flags that control how variables are written in the LLVM IR output. +/// [Flags] enum LlvmIrVariableWriteOptions { + /// + /// No special write options. + /// None = 0x0000, + /// + /// Write index comments for array elements. + /// ArrayWriteIndexComments = 0x0001, + /// + /// Format arrays in rows rather than one element per line. + /// ArrayFormatInRows = 0x0002, } +/// +/// Specifies the number format to use when writing numeric variables. +/// enum LlvmIrVariableNumberFormat { + /// + /// Use the default format for the variable type. + /// Default, + /// + /// Force hexadecimal format. + /// Hexadecimal, + /// + /// Force decimal format. + /// Decimal, } +/// +/// Abstract base class for LLVM IR variable references. +/// +/// +/// Abstract base class for LLVM IR variable references. +/// abstract class LlvmIrVariableReference { - public abstract bool Global { get; } - public abstract string NamePrefix { get; } - public string? Name { get; protected set; } - - /// - /// Returns a string which constitutes a reference to a local (using the % prefix character) or a global - /// (using the @ prefix character) variable, ready for use in the generated code wherever variables are - /// referenced. - /// - public virtual string Reference { - get { - if (String.IsNullOrEmpty (Name)) { - throw new InvalidOperationException ("Variable doesn't have a name, it cannot be referenced"); - } - return $"{NamePrefix}{Name}"; - } - } - protected LlvmIrVariableReference (string? name) - { - Name = name; - } + /// + /// Gets a value indicating whether this is a global variable reference. + /// + public abstract bool Global { get; } + /// + /// Gets the prefix character used when referencing this variable in LLVM IR code. + /// + public abstract string NamePrefix { get; } + /// + /// Gets or sets the name of the variable. + /// + public string? Name { get; protected set; } + + /// + /// Returns a string which constitutes a reference to a local (using the % prefix character) or a global + /// (using the @ prefix character) variable, ready for use in the generated code wherever variables are + /// referenced. + /// + public virtual string Reference { + get { + if (String.IsNullOrEmpty (Name)) { + throw new InvalidOperationException ("Variable doesn't have a name, it cannot be referenced"); + } + return $"{NamePrefix}{Name}"; + } + } + /// + /// Initializes a new instance of the class. + /// + /// The name of the variable. + protected LlvmIrVariableReference (string? name) + { + Name = name; + } } +/// +/// Represents a reference to a global LLVM IR variable. +/// class LlvmIrGlobalVariableReference : LlvmIrVariableReference { - public override bool Global => true; - public override string NamePrefix => "@"; - public LlvmIrGlobalVariableReference (string name) - : base (name) + /// + /// Gets a value indicating that this is a global variable reference. + /// + public override bool Global => true; + /// + /// Gets the global variable prefix character '@'. + /// + public override string NamePrefix => "@"; + /// + /// Initializes a new instance of the class. + /// + /// The name of the global variable. + public LlvmIrGlobalVariableReference (string name) + : base (name) {} } +/// +/// Abstract base class for LLVM IR variables that can hold values and be referenced in LLVM IR code. +/// abstract class LlvmIrVariable : LlvmIrVariableReference, IEquatable { + /// + /// Gets or sets the .NET type of this variable. + /// public Type Type { get; protected set; } + /// + /// Gets or sets the write options that control how this variable is output in LLVM IR. + /// public LlvmIrVariableWriteOptions WriteOptions { get; set; } = LlvmIrVariableWriteOptions.ArrayWriteIndexComments; /// @@ -65,15 +130,25 @@ abstract class LlvmIrVariable : LlvmIrVariableReference, IEquatable public uint ArrayStride { get; set; } = 8; + /// + /// Gets or sets the value stored in this variable. + /// public object? Value { get; set; } + /// + /// Gets or sets a comment to be written alongside this variable in the LLVM IR output. + /// public string? Comment { get; set; } + /// + /// Gets or sets the number format to use when writing numeric values. + /// public LlvmIrVariableNumberFormat NumberFormat { get; set; } = LlvmIrVariableNumberFormat.Decimal; /// /// Both global and local variables will want their names to matter in equality checks, but function /// parameters must not take it into account, thus this property. If set to false, /// will ignore name when checking for equality. + /// protected bool NameMatters { get; set; } = true; /// @@ -116,6 +191,8 @@ abstract class LlvmIrVariable : LlvmIrVariableReference, IEquatable + /// The .NET type of the variable. + /// The optional name of the variable. protected LlvmIrVariable (Type type, string? name = null) : base (name) { @@ -123,11 +200,20 @@ protected LlvmIrVariable (Type type, string? name = null) Name = name; } + /// + /// Returns a hash code for this variable based on its type and name. + /// + /// A hash code for the current object. public override int GetHashCode () { return Type.GetHashCode () ^ (Name?.GetHashCode () ?? 0); } + /// + /// Determines whether the specified object is equal to the current variable. + /// + /// The object to compare with the current variable. + /// true if the specified object is equal to the current variable; otherwise, false. public override bool Equals (object obj) { var irVar = obj as LlvmIrVariable; @@ -138,6 +224,11 @@ public override bool Equals (object obj) return Equals (irVar); } + /// + /// Determines whether the specified LLVM IR variable is equal to the current variable. + /// + /// The LLVM IR variable to compare with the current variable. + /// true if the specified variable is equal to the current variable; otherwise, false. public virtual bool Equals (LlvmIrVariable other) { if (other == null) { @@ -152,9 +243,18 @@ public virtual bool Equals (LlvmIrVariable other) } } +/// +/// Represents a local LLVM IR variable. +/// class LlvmIrLocalVariable : LlvmIrVariable { + /// + /// Gets a value indicating that this is not a global variable. + /// public override bool Global => false; + /// + /// Gets the local variable prefix character '%'. + /// public override string NamePrefix => "%"; /// @@ -163,24 +263,48 @@ class LlvmIrLocalVariable : LlvmIrVariable /// is treated as an opaque pointer type. is optional because local variables can be unnamed, in /// which case they will be assigned a sequential number when function code is generated. /// + /// The .NET type of the variable. + /// The optional name of the variable. public LlvmIrLocalVariable (Type type, string? name = null) : base (type, name) {} + /// + /// Assigns a numeric name to this local variable. + /// + /// The number to assign as the variable name. public void AssignNumber (ulong n) { Name = n.ToString (CultureInfo.InvariantCulture); } } +/// +/// Represents the state of a streamed array data provider. +/// enum LlvmIrStreamedArrayDataProviderState { + /// + /// More sections are available after this one. + /// NextSection, + /// + /// This is the last section with data. + /// LastSection, + /// + /// More sections are available but this one has no data. + /// NextSectionNoData, + /// + /// This is the last section and it has no data. + /// LastSectionNoData, } +/// +/// Abstract base class for providing streamed array data to LLVM IR variables. +/// abstract class LlvmIrStreamedArrayDataProvider { /// @@ -189,6 +313,10 @@ abstract class LlvmIrStreamedArrayDataProvider /// public Type ArrayElementType { get; } + /// + /// Initializes a new instance of the class. + /// + /// The type of elements in the arrays returned by this provider. protected LlvmIrStreamedArrayDataProvider (Type arrayElementType) { ArrayElementType = arrayElementType; @@ -199,6 +327,8 @@ protected LlvmIrStreamedArrayDataProvider (Type arrayElementType) /// comment, if any, to be output before the actual data. Returning `String.Empty` prevents the comment /// from being added. /// + /// The target module for which to get the comment. + /// The section start comment or an empty string if no comment should be added. public virtual string GetSectionStartComment (LlvmIrModuleTarget target) => String.Empty; /// @@ -208,15 +338,25 @@ protected LlvmIrStreamedArrayDataProvider (Type arrayElementType) /// must have a value of . /// Each section may be preceded by a comment, . /// + /// The target module for which to get data. + /// A tuple containing the provider state and the data collection. public abstract (LlvmIrStreamedArrayDataProviderState status, ICollection data) GetData (LlvmIrModuleTarget target); /// /// Provide the total data size for the specified target (ABI). This needs to be used instead of /// because a variable instance is created once and shared by all targets, while per-target data sets might have different sizes. /// + /// The target module for which to get the total data size. + /// The total size of data that will be provided for the specified target. public abstract ulong GetTotalDataSize (LlvmIrModuleTarget target); } +/// +/// Represents a global LLVM IR variable. +/// +/// +/// Represents a global LLVM IR variable. +/// class LlvmIrGlobalVariable : LlvmIrVariable { /// @@ -224,7 +364,13 @@ class LlvmIrGlobalVariable : LlvmIrVariable /// public static readonly LlvmIrVariableOptions DefaultOptions = LlvmIrVariableOptions.GlobalConstant; + /// + /// Gets a value indicating that this is a global variable. + /// public override bool Global => true; + /// + /// Gets the global variable prefix character '@'. + /// public override string NamePrefix => "@"; /// @@ -272,6 +418,10 @@ class LlvmIrGlobalVariable : LlvmIrVariable /// https://llvm.org/docs/LangRef.html#t-firstclass) only if it's an integral or floating point type. In all other cases it /// is treated as an opaque pointer type. is required because global variables must be named. /// + /// The .NET type of the variable. + /// The name of the global variable. + /// Optional variable options. + /// Thrown when is null or empty. public LlvmIrGlobalVariable (Type type, string name, LlvmIrVariableOptions? options = null) : base (type, name) { @@ -284,9 +434,13 @@ public LlvmIrGlobalVariable (Type type, string name, LlvmIrVariableOptions? opti /// /// Constructs a local variable and sets the property to and - /// property to its type. For that reason, **must not** be null. is + /// property to its type. For that reason, **must not** be null. is /// required because global variables must be named. /// + /// The value to assign to the variable. Must not be null. + /// The name of the global variable. + /// Optional variable options. + /// Thrown when is null. public LlvmIrGlobalVariable (object value, string name, LlvmIrVariableOptions? options = null) : this ((value ?? throw new ArgumentNullException (nameof (value))).GetType (), name, options) { @@ -298,24 +452,48 @@ public LlvmIrGlobalVariable (object value, string name, LlvmIrVariableOptions? o /// generating output for a specific target (e.g. 32-bit vs 64-bit integer variables). If the variable requires such /// type changes, this should be done at generation time from within the method. /// + /// The new type to assign to the variable. + /// The new value to assign to the variable. public void OverrideTypeAndValue (Type newType, object? newValue) { Type = newType; Value = newValue; } + /// + /// Overrides the name of this global variable. + /// + /// The new name for the variable. public void OverrideName (string newName) { Name = newName; } } +/// +/// Represents a string variable in LLVM IR with specific encoding and formatting options. +/// class LlvmIrStringVariable : LlvmIrGlobalVariable { + /// + /// Gets the string encoding used for this variable. + /// public LlvmIrStringEncoding Encoding { get; } + /// + /// Gets the LLVM IR type string for this string variable. + /// public string IrType { get; } + /// + /// Gets a value indicating whether this string should be output as a constant string literal. + /// public bool IsConstantStringLiteral { get; } + /// + /// Initializes a new instance of the class. + /// + /// The name of the string variable. + /// The string value holder containing the string data and encoding. + /// Optional variable options, defaults to global constant string pointer. public LlvmIrStringVariable (string name, StringHolder value, LlvmIrVariableOptions? options = null) : base (typeof(string), name, options ?? LlvmIrVariableOptions.GlobalConstantStringPointer) { @@ -337,10 +515,19 @@ public LlvmIrStringVariable (string name, StringHolder value, LlvmIrVariableOpti } } + /// + /// Initializes a new instance of the class. + /// + /// The name of the string variable. + /// The string value. + /// The encoding to use for the string. + /// The string comparison method to use. + /// Optional variable options. public LlvmIrStringVariable (string name, string value, LlvmIrStringEncoding encoding, StringComparison comparison = StringComparison.Ordinal, LlvmIrVariableOptions? options = null) : this (name, new StringHolder (value, encoding, comparison), options) {} } +} /// /// This is to address my dislike to have single-line variables separated by empty lines :P. diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrWritability.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrWritability.cs index ce17b357f8b..6d1d27e8239 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrWritability.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrWritability.cs @@ -3,12 +3,18 @@ namespace Xamarin.Android.Tasks.LLVMIR { /// - /// Address significance, see https://llvm.org/docs/LangRef.html#global-variables + /// Specifies whether a variable is writable or constant, see https://llvm.org/docs/LangRef.html#global-variables /// [Flags] enum LlvmIrWritability { + /// + /// Variable is constant and cannot be modified. + /// Constant = 1 << 0, + /// + /// Variable is writable and can be modified. + /// Writable = 1 << 1, } } From e224c9b3f472be3b2052414b77d067ccaf922856 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:35:54 +0000 Subject: [PATCH 3/5] Add documentation for additional LLVM IR generator classes and enums Co-authored-by: grendello <184788+grendello@users.noreply.github.com> --- .../LlvmIrModuleMergeBehavior.cs | 26 ++++++- .../LlvmIrRuntimePreemption.cs | 9 +++ .../LlvmIrGenerator/LlvmIrVariableOptions.cs | 22 ++++++ .../LlvmIrGenerator/LlvmVisibility.cs | 9 +++ .../NativeAssemblerAttribute.cs | 28 ++++++++ .../LlvmIrGenerator/NativeClassAttribute.cs | 4 ++ .../LlvmIrGenerator/NativePointerAttribute.cs | 4 ++ .../Utilities/LlvmIrGenerator/StringHolder.cs | 71 +++++++++++++++++++ 8 files changed, 172 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrModuleMergeBehavior.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrModuleMergeBehavior.cs index 54a20680799..62254347fea 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrModuleMergeBehavior.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrModuleMergeBehavior.cs @@ -1,14 +1,38 @@ namespace Xamarin.Android.Tasks.LLVMIR { - // See: https://llvm.org/docs/LangRef.html#module-flags-metadata + /// + /// Constants defining LLVM IR module merge behaviors for module flags metadata. + /// See: https://llvm.org/docs/LangRef.html#module-flags-metadata + /// static class LlvmIrModuleMergeBehavior { + /// + /// Error merge behavior - linking fails if flag values differ. + /// public const int Error = 1; + /// + /// Warning merge behavior - warning is emitted if flag values differ. + /// public const int Warning = 2; + /// + /// Require merge behavior - linking fails if the flag is not present in the other module. + /// public const int Require = 3; + /// + /// Override merge behavior - the flag value is overridden. + /// public const int Override = 4; + /// + /// Append merge behavior - the flag values are appended. + /// public const int Append = 5; + /// + /// Append unique merge behavior - the flag values are appended only if unique. + /// public const int AppendUnique = 6; + /// + /// Max merge behavior - the maximum value is used. + /// public const int Max = 7; } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrRuntimePreemption.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrRuntimePreemption.cs index ceab704634b..1be5ca225e4 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrRuntimePreemption.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrRuntimePreemption.cs @@ -8,8 +8,17 @@ namespace Xamarin.Android.Tasks.LLVMIR [Flags] enum LlvmIrRuntimePreemption { + /// + /// Default runtime preemption (dso_preemptable). + /// Default = 0 << 0, + /// + /// DSO preemptable - symbol may be preempted by symbols from other modules. + /// DSOPreemptable = 1 << 0, + /// + /// DSO local - symbol is local to the current dynamic shared object. + /// DSOLocal = 1 << 1, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariableOptions.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariableOptions.cs index 680881ca31f..775f6eaec0a 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariableOptions.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariableOptions.cs @@ -1,5 +1,9 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Represents options for LLVM IR variables, controlling linkage, visibility, writability, and other attributes. + /// Provides predefined option sets for common variable types. + /// class LlvmIrVariableOptions { /// @@ -84,12 +88,30 @@ class LlvmIrVariableOptions AddressSignificance = LlvmIrAddressSignificance.LocalUnnamed, }; + /// + /// Gets or sets the linkage type for the variable. + /// public LlvmIrLinkage Linkage { get; set; } = LlvmIrLinkage.Default; + /// + /// Gets or sets the runtime preemption setting for the variable. + /// public LlvmIrRuntimePreemption RuntimePreemption { get; set; } = LlvmIrRuntimePreemption.DSOLocal; + /// + /// Gets or sets the visibility of the variable. + /// public LlvmIrVisibility Visibility { get; set; } = LlvmIrVisibility.Default; + /// + /// Gets or sets the address significance of the variable. + /// public LlvmIrAddressSignificance AddressSignificance { get; set; } = LlvmIrAddressSignificance.Default; + /// + /// Gets or sets whether the variable is writable or constant. + /// public LlvmIrWritability Writability { get; set; } = LlvmIrWritability.Writable; + /// + /// Gets a value indicating whether this variable has global linkage. + /// public bool IsGlobal => Linkage == LlvmIrLinkage.Default || (Linkage != LlvmIrLinkage.Private && Linkage != LlvmIrLinkage.Internal); } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmVisibility.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmVisibility.cs index 59f43110291..3ccc73cf678 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmVisibility.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmVisibility.cs @@ -8,8 +8,17 @@ namespace Xamarin.Android.Tasks.LLVMIR [Flags] enum LlvmIrVisibility { + /// + /// Default visibility - symbol is visible to other modules. + /// Default = 1 << 0, + /// + /// Hidden visibility - symbol is not visible to other modules. + /// Hidden = 1 << 1, + /// + /// Protected visibility - symbol is visible but not overrideable. + /// Protected = 1 << 2, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeAssemblerAttribute.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeAssemblerAttribute.cs index eba498721f8..cb0d6edf3d2 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeAssemblerAttribute.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeAssemblerAttribute.cs @@ -2,13 +2,29 @@ namespace Xamarin.Android.Tasks { + /// + /// Specifies the target architectures for which a native assembler member is valid. + /// enum NativeAssemblerValidTarget { + /// + /// Valid for any target architecture. + /// Any, + /// + /// Valid only for 32-bit target architectures. + /// ThirtyTwoBit, + /// + /// Valid only for 64-bit target architectures. + /// SixtyFourBit, } + /// + /// Attribute that controls how fields and properties are handled during native assembler generation. + /// Provides fine-grained control over member inclusion, formatting, and target-specific behavior. + /// [AttributeUsage (AttributeTargets.Field | AttributeTargets.Property, Inherited = true)] class NativeAssemblerAttribute : Attribute { @@ -66,11 +82,23 @@ class NativeAssemblerAttribute : Attribute public string? MemberName { get; set; } } + /// + /// Attribute that specifies a context data provider for a native assembler structure. + /// The provider allows for dynamic data generation based on structure instances. + /// [AttributeUsage (AttributeTargets.Class, Inherited = true)] class NativeAssemblerStructContextDataProviderAttribute : Attribute { + /// + /// Gets the type of the context data provider. + /// public Type Type { get; } + /// + /// Initializes a new instance of the class. + /// + /// The type of the context data provider. Must be derived from . + /// Thrown when the type is not derived from . public NativeAssemblerStructContextDataProviderAttribute (Type type) { if (!type.IsSubclassOf (typeof(NativeAssemblerStructContextDataProvider))) { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeClassAttribute.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeClassAttribute.cs index 698f4e74434..7dc19f2f2c2 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeClassAttribute.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativeClassAttribute.cs @@ -2,6 +2,10 @@ namespace Xamarin.Android.Tasks { + /// + /// Attribute that marks a class as representing a native structure for LLVM IR generation. + /// Classes decorated with this attribute will be treated as native structures during code generation. + /// [AttributeUsage (AttributeTargets.Class, Inherited = true)] class NativeClassAttribute : Attribute { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativePointerAttribute.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativePointerAttribute.cs index 7bcb3a32fdd..f46a3983a10 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativePointerAttribute.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/NativePointerAttribute.cs @@ -2,6 +2,10 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Attribute that marks a field or property as representing a native pointer in LLVM IR generation. + /// This provides control over how the pointer is handled during code generation. + /// [AttributeUsage (AttributeTargets.Field | AttributeTargets.Property, Inherited = true)] class NativePointerAttribute : Attribute { diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/StringHolder.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/StringHolder.cs index 55d8d594e09..a963ec2f4ad 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/StringHolder.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/StringHolder.cs @@ -2,13 +2,28 @@ namespace Xamarin.Android.Tasks.LLVMIR; +/// +/// Holds a string with its encoding information and comparison semantics for use in LLVM IR generation. +/// class StringHolder : IComparable, IComparable, IEquatable { + /// + /// Gets the encoding used for this string. + /// public LlvmIrStringEncoding Encoding { get; } + /// + /// Gets the string data. + /// public string? Data { get; } StringComparison comparison; + /// + /// Initializes a new instance of the class. + /// + /// The string data to hold. + /// The encoding to use for the string. + /// The string comparison method to use. public StringHolder (string? data, LlvmIrStringEncoding encoding = LlvmIrStringEncoding.UTF8, StringComparison comparison = StringComparison.Ordinal) { Data = data; @@ -16,6 +31,14 @@ public StringHolder (string? data, LlvmIrStringEncoding encoding = LlvmIrStringE this.comparison = comparison; } + /// + /// Converts an object to a StringHolder, handling both string and StringHolder inputs. + /// + /// The value to convert (string or StringHolder). + /// The encoding to use if creating a new StringHolder. + /// The comparison method to use if creating a new StringHolder. + /// A StringHolder containing the value. + /// Thrown when value is not a string or StringHolder. public static StringHolder AsHolder (object? value, LlvmIrStringEncoding encoding = LlvmIrStringEncoding.UTF8, StringComparison comparison = StringComparison.Ordinal) { if (value == null) { @@ -34,8 +57,18 @@ public static StringHolder AsHolder (object? value, LlvmIrStringEncoding encodin return holder; } + /// + /// Compares this StringHolder to an object. + /// + /// The object to compare to. + /// A signed integer that indicates the relative values of this instance and value. public int CompareTo (object obj) => CompareTo (obj as StringHolder); + /// + /// Compares this StringHolder to another StringHolder. + /// + /// The StringHolder to compare to. + /// A signed integer that indicates the relative values of this instance and other. public int CompareTo (StringHolder? other) { if (other == null) { @@ -65,6 +98,10 @@ public int CompareTo (StringHolder? other) return dataCompare != 0 ? dataCompare : encodingCompare; } + /// + /// Returns a hash code for this StringHolder. + /// + /// A hash code for the current object. public override int GetHashCode () { int hc = 0; @@ -75,8 +112,18 @@ public override int GetHashCode () return hc ^ Encoding.GetHashCode (); } + /// + /// Determines whether the specified object is equal to the current StringHolder. + /// + /// The object to compare with the current StringHolder. + /// true if the specified object is equal to the current StringHolder; otherwise, false. public override bool Equals (object obj) => Equals (obj as StringHolder); + /// + /// Determines whether the specified StringHolder is equal to the current StringHolder. + /// + /// The StringHolder to compare with the current StringHolder. + /// true if the specified StringHolder is equal to the current StringHolder; otherwise, false. public bool Equals (StringHolder? other) { if (other == null || Encoding != other.Encoding) { @@ -86,21 +133,45 @@ public bool Equals (StringHolder? other) return MonoAndroidHelper.StringEquals (Data, other.Data, comparison); } + /// + /// Determines whether one StringHolder is greater than another. + /// + /// The first StringHolder to compare. + /// The second StringHolder to compare. + /// true if a is greater than b; otherwise, false. public static bool operator > (StringHolder a, StringHolder b) { return a.CompareTo (b) > 0; } + /// + /// Determines whether one StringHolder is less than another. + /// + /// The first StringHolder to compare. + /// The second StringHolder to compare. + /// true if a is less than b; otherwise, false. public static bool operator < (StringHolder a, StringHolder b) { return a.CompareTo (b) < 0; } + /// + /// Determines whether one StringHolder is greater than or equal to another. + /// + /// The first StringHolder to compare. + /// The second StringHolder to compare. + /// true if a is greater than or equal to b; otherwise, false. public static bool operator >= (StringHolder a, StringHolder b) { return a.CompareTo (b) >= 0; } + /// + /// Determines whether one StringHolder is less than or equal to another. + /// + /// The first StringHolder to compare. + /// The second StringHolder to compare. + /// true if a is less than or equal to b; otherwise, false. public static bool operator <= (StringHolder a, StringHolder b) { return a.CompareTo (b) <= 0; From 674f0829286494d1ecdc34202f352c05c465e474 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 15:38:53 +0000 Subject: [PATCH 4/5] Add documentation for utility classes and metadata constants Co-authored-by: grendello <184788+grendello@users.noreply.github.com> --- .../LlvmIrGenerator/LlvmIrCallMarkers.cs | 15 ++++ .../LlvmIrGenerator/LlvmIrKnownMetadata.cs | 9 ++ .../LlvmIrGenerator/MemberInfoUtilities.cs | 83 +++++++++++++++++++ .../LlvmIrGenerator/TypeUtilities.cs | 47 +++++++++++ 4 files changed, 154 insertions(+) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrCallMarkers.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrCallMarkers.cs index 48acbcd5d64..a9c2fb2bb27 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrCallMarkers.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrCallMarkers.cs @@ -1,10 +1,25 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Represents call markers for LLVM IR call instructions that control tail call optimization. + /// enum LlvmIrCallMarker { + /// + /// No call marker specified. + /// None, + /// + /// Tail call marker - suggests tail call optimization. + /// Tail, + /// + /// Must tail call marker - requires tail call optimization. + /// MustTail, + /// + /// No tail call marker - prevents tail call optimization. + /// NoTail, } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrKnownMetadata.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrKnownMetadata.cs index dbd6ce0f69c..158f0b21788 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrKnownMetadata.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrKnownMetadata.cs @@ -1,7 +1,16 @@ namespace Xamarin.Android.Tasks.LLVMIR; +/// +/// Contains constants for well-known LLVM IR metadata names. +/// sealed class LlvmIrKnownMetadata { + /// + /// The "llvm.module.flags" metadata name used for module-level flags. + /// public const string LlvmModuleFlags = "llvm.module.flags"; + /// + /// The "llvm.ident" metadata name used for module identification. + /// public const string LlvmIdent = "llvm.ident"; } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/MemberInfoUtilities.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/MemberInfoUtilities.cs index aac8b8b3636..5ee1dad4d5d 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/MemberInfoUtilities.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/MemberInfoUtilities.cs @@ -3,13 +3,29 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Provides utility methods for working with member information in the context of LLVM IR generation. + /// static class MemberInfoUtilities { + /// + /// Determines whether a member is marked as a native pointer. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the member is a native pointer; otherwise, false. public static bool IsNativePointer (this MemberInfo mi, LlvmIrTypeCache cache) { return cache.GetNativePointerAttribute (mi) != null; } + /// + /// Determines whether a member is a native pointer that points to a pre-allocated buffer. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// When this method returns, contains the required buffer size if the member points to a pre-allocated buffer; otherwise, 0. + /// true if the member points to a pre-allocated buffer; otherwise, false. public static bool IsNativePointerToPreallocatedBuffer (this MemberInfo mi, LlvmIrTypeCache cache, out ulong requiredBufferSize) { var attr = cache.GetNativePointerAttribute (mi); @@ -22,6 +38,13 @@ public static bool IsNativePointerToPreallocatedBuffer (this MemberInfo mi, Llvm return attr.PointsToPreAllocatedBuffer; } + /// + /// Determines whether a member points to a symbol and gets the symbol name. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// When this method returns, contains the symbol name if the member points to a symbol; otherwise, null. + /// true if the member points to a symbol; otherwise, false. public static bool PointsToSymbol (this MemberInfo mi, LlvmIrTypeCache cache, out string? symbolName) { var attr = cache.GetNativePointerAttribute (mi); @@ -34,6 +57,12 @@ public static bool PointsToSymbol (this MemberInfo mi, LlvmIrTypeCache cache, ou return true; } + /// + /// Determines whether a string member should use Unicode (UTF-16) encoding. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the member should use Unicode encoding; otherwise, false. public static bool IsUnicodeString (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); @@ -44,6 +73,12 @@ public static bool IsUnicodeString (this MemberInfo mi, LlvmIrTypeCache cache) return attr.IsUTF16; } + /// + /// Gets the string encoding to use for a member. + /// + /// The member info to get encoding for. + /// The LLVM IR type cache. + /// The string encoding to use for the member. public static LlvmIrStringEncoding GetStringEncoding (this MemberInfo mi, LlvmIrTypeCache cache) { const LlvmIrStringEncoding DefaultStringEncoding = LlvmIrStringEncoding.UTF8; @@ -56,36 +91,72 @@ public static LlvmIrStringEncoding GetStringEncoding (this MemberInfo mi, LlvmIr return attr.IsUTF16 ? LlvmIrStringEncoding.Unicode : DefaultStringEncoding; } + /// + /// Gets the overridden name for a member if specified in attributes. + /// + /// The member info to get the overridden name for. + /// The LLVM IR type cache. + /// The overridden name if specified; otherwise, null. public static string? GetOverriddenName (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); return attr != null ? attr.MemberName : null; } + /// + /// Gets the valid target specification for a member. + /// + /// The member info to get the valid target for. + /// The LLVM IR type cache. + /// The valid target specification for the member. public static NativeAssemblerValidTarget GetValidTarget (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); return attr != null ? attr.ValidTarget : NativeAssemblerValidTarget.Any; } + /// + /// Determines whether a member should be ignored during native assembler generation. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the member should be ignored; otherwise, false. public static bool ShouldBeIgnored (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); return attr != null && attr.Ignore; } + /// + /// Determines whether a member uses a data provider for dynamic data generation. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the member uses a data provider; otherwise, false. public static bool UsesDataProvider (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); return attr != null && attr.UsesDataProvider; } + /// + /// Determines whether a member represents an inline array. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the member is an inline array; otherwise, false. public static bool IsInlineArray (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); return attr != null && attr.InlineArray; } + /// + /// Gets the size of an inline array member. + /// + /// The member info to get the array size for. + /// The LLVM IR type cache. + /// The size of the inline array, or -1 if the member is not an inline array. public static int GetInlineArraySize (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); @@ -96,6 +167,12 @@ public static int GetInlineArraySize (this MemberInfo mi, LlvmIrTypeCache cache) return attr.InlineArraySize; } + /// + /// Determines whether an inline array member needs padding. + /// + /// The member info to check. + /// The LLVM IR type cache. + /// true if the inline array needs padding; otherwise, false. public static bool InlineArrayNeedsPadding (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); @@ -106,6 +183,12 @@ public static bool InlineArrayNeedsPadding (this MemberInfo mi, LlvmIrTypeCache return attr.NeedsPadding; } + /// + /// Gets the number format to use for a member. + /// + /// The member info to get the number format for. + /// The LLVM IR type cache. + /// The number format to use for the member. public static LlvmIrVariableNumberFormat GetNumberFormat (this MemberInfo mi, LlvmIrTypeCache cache) { var attr = cache.GetNativeAssemblerAttribute (mi); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/TypeUtilities.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/TypeUtilities.cs index eec6dd7a771..e28a4d663ba 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/TypeUtilities.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/TypeUtilities.cs @@ -5,8 +5,17 @@ namespace Xamarin.Android.Tasks.LLVMIR { + /// + /// Provides utility methods for working with types in the context of LLVM IR generation. + /// static class TypeUtilities { + /// + /// Gets the short name of a type (without namespace or containing type information). + /// + /// The type to get the short name for. + /// The short name of the type. + /// Thrown when the type is unnamed or has an invalid name. public static string GetShortName (this Type type) { string? fullName = type.FullName; @@ -35,6 +44,11 @@ public static string GetShortName (this Type type) return ret; } + /// + /// Determines whether a type represents a structure (value type that is not an enum, primitive, or array). + /// + /// The type to check. + /// true if the type is a structure; otherwise, false. public static bool IsStructure (this Type type) { return type.IsValueType && @@ -46,6 +60,12 @@ public static bool IsStructure (this Type type) type != typeof (object); } + /// + /// Determines whether a structure member represents an LLVM IR structure. + /// + /// The structure member info to check. + /// The LLVM IR type cache. + /// true if the member represents an IR structure; otherwise, false. public static bool IsIRStruct (this StructureMemberInfo smi, LlvmIrTypeCache cache) { Type type = smi.MemberType; @@ -58,6 +78,11 @@ public static bool IsIRStruct (this StructureMemberInfo smi, LlvmIrTypeCache cac (type.IsStructure () || type.IsClass); } + /// + /// Gets the data provider for a type if it has a NativeAssemblerStructContextDataProviderAttribute. + /// + /// The type to get the data provider for. + /// The data provider instance, or null if the type doesn't have a data provider attribute. public static NativeAssemblerStructContextDataProvider? GetDataProvider (this Type t) { var attr = t.GetCustomAttribute (); @@ -68,12 +93,23 @@ public static bool IsIRStruct (this StructureMemberInfo smi, LlvmIrTypeCache cac return Activator.CreateInstance (attr.Type) as NativeAssemblerStructContextDataProvider; } + /// + /// Determines whether a type is marked with the NativeClassAttribute. + /// + /// The type to check. + /// true if the type has the NativeClassAttribute; otherwise, false. public static bool IsNativeClass (this Type t) { var attr = t.GetCustomAttribute (); return attr != null; } + /// + /// Determines whether a type implements a specific interface. + /// + /// The type to check. + /// The interface type to check for. + /// true if the type implements the interface; otherwise, false. public static bool ImplementsInterface (this Type type, Type requiredIfaceType) { if (type == null || requiredIfaceType == null) { @@ -104,6 +140,12 @@ public static bool ImplementsInterface (this Type type, Type requiredIfaceType) return false; } + /// + /// Determines whether a type is a StructureInstance generic type and gets the structure type. + /// + /// The type to check. + /// When this method returns, contains the structure type if the type is a StructureInstance; otherwise, null. + /// true if the type is a StructureInstance; otherwise, false. public static bool IsStructureInstance (this Type type, out Type? structureType) { structureType = null; @@ -124,6 +166,8 @@ public static bool IsStructureInstance (this Type type, out Type? structureType) /// correspond to one of the following array types: T[], ICollection<T> or IDictionary<string, string>. The latter is /// used to comfortably represent name:value arrays, which are output as single dimensional arrays in the native code. /// + /// The array type to get the element type for. + /// The element type of the array. /// /// Thrown when is not one of the array types listed above. /// @@ -158,6 +202,9 @@ public static Type GetArrayElementType (this Type type) /// a standard single-dimensional language array (i.e. T[]), implement ICollection<T> together with ICollection or, /// as a special case for name:value pair collections, implement IDictionary<string, string> /// + /// The type to check. + /// true if the type represents an array; otherwise, false. + /// Thrown when multi-dimensional arrays are encountered. public static bool IsArray (this Type t) { if (t.IsPrimitive) { From 6973b39d1e7b0df499a888678a4e8ac6a302caf6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 11 Jul 2025 16:29:53 +0000 Subject: [PATCH 5/5] Fix XML documentation issues in LlvmIrVariable.cs - Remove duplicate XML documentation comments for LlvmIrVariableReference and LlvmIrGlobalVariable - Add remarks sections documenting default values for WriteOptions and NumberFormat properties - Remove accidentally added extra closing brace Co-authored-by: grendello <184788+grendello@users.noreply.github.com> --- .../Utilities/LlvmIrGenerator/LlvmIrVariable.cs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs index 4b2165e66a3..21eb0c39d6a 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrVariable.cs @@ -45,9 +45,6 @@ enum LlvmIrVariableNumberFormat Decimal, } -/// -/// Abstract base class for LLVM IR variable references. -/// /// /// Abstract base class for LLVM IR variable references. /// @@ -122,6 +119,9 @@ abstract class LlvmIrVariable : LlvmIrVariableReference, IEquatable /// Gets or sets the write options that control how this variable is output in LLVM IR. /// + /// + /// Defaults to . + /// public LlvmIrVariableWriteOptions WriteOptions { get; set; } = LlvmIrVariableWriteOptions.ArrayWriteIndexComments; /// @@ -142,6 +142,9 @@ abstract class LlvmIrVariable : LlvmIrVariableReference, IEquatable /// Gets or sets the number format to use when writing numeric values. /// + /// + /// Defaults to . + /// public LlvmIrVariableNumberFormat NumberFormat { get; set; } = LlvmIrVariableNumberFormat.Decimal; /// @@ -351,9 +354,6 @@ protected LlvmIrStreamedArrayDataProvider (Type arrayElementType) public abstract ulong GetTotalDataSize (LlvmIrModuleTarget target); } -/// -/// Represents a global LLVM IR variable. -/// /// /// Represents a global LLVM IR variable. /// @@ -527,7 +527,6 @@ public LlvmIrStringVariable (string name, string value, LlvmIrStringEncoding enc : this (name, new StringHolder (value, encoding, comparison), options) {} } -} /// /// This is to address my dislike to have single-line variables separated by empty lines :P. pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy