diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMAttributeRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMAttributeRef.cs index 08154b3c..37424e07 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMAttributeRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMAttributeRef.cs @@ -8,9 +8,65 @@ public unsafe partial struct LLVMAttributeRef(IntPtr handle) : IEquatable LLVM.GetEnumAttributeKind(this); + /// + /// This returns true for all attributes except string attributes. + /// + public readonly bool HasKindAsEnum => (Handle != IntPtr.Zero) && (LLVM.IsStringAttribute(this) == 0); - public readonly ulong Value => LLVM.GetEnumAttributeValue(this); + /// + /// This returns true for enum attributes and int attributes. + /// + public readonly bool IsEnumAttribute => (Handle != IntPtr.Zero) && LLVM.IsEnumAttribute(this) != 0; + + public readonly bool IsStringAttribute => (Handle != IntPtr.Zero) && LLVM.IsStringAttribute(this) != 0; + + public readonly bool IsTypeAttribute => (Handle != IntPtr.Zero) && LLVM.IsTypeAttribute(this) != 0; + + public readonly uint KindAsEnum => HasKindAsEnum ? LLVM.GetEnumAttributeKind(this) : default; + + public readonly string KindAsString + { + get + { + if (!IsStringAttribute) + { + return string.Empty; + } + + uint length = 0; + var kindPtr = LLVM.GetStringAttributeKind(this, &length); + if (kindPtr == null) + { + return string.Empty; + } + + return new ReadOnlySpan(kindPtr, (int)length).AsString(); + } + } + + public readonly ulong ValueAsInt => IsEnumAttribute ? LLVM.GetEnumAttributeValue(this) : default; + + public readonly string ValueAsString + { + get + { + if (!IsStringAttribute) + { + return string.Empty; + } + + uint length = 0; + var valuePtr = LLVM.GetStringAttributeValue(this, &length); + if (valuePtr == null) + { + return string.Empty; + } + + return new ReadOnlySpan(valuePtr, (int)length).AsString(); + } + } + + public readonly LLVMTypeRef ValueAsType => IsTypeAttribute ? LLVM.GetTypeAttributeValue(this) : default; public static implicit operator LLVMAttributeRef(LLVMOpaqueAttributeRef* value) => new LLVMAttributeRef((IntPtr)value); diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockInstructionsEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockInstructionsEnumerable.cs new file mode 100644 index 00000000..eb908c3c --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockInstructionsEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMBasicBlockInstructionsEnumerable(LLVMBasicBlockRef basicBlock) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(basicBlock); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMBasicBlockRef basicBlock) : IEnumerator + { + public LLVMValueRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = basicBlock.FirstInstruction; + } + else + { + Current = Current.NextInstruction; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockRef.cs index d6bd9a9a..9502151a 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMBasicBlockRef.cs @@ -10,6 +10,8 @@ public unsafe partial struct LLVMBasicBlockRef(IntPtr handle) : IEquatable (Handle != IntPtr.Zero) ? LLVM.GetFirstInstruction(this) : default; + public readonly LLVMBasicBlockInstructionsEnumerable Instructions => new LLVMBasicBlockInstructionsEnumerable(this); + public readonly LLVMValueRef LastInstruction => (Handle != IntPtr.Zero) ? LLVM.GetLastInstruction(this) : default; public readonly LLVMBasicBlockRef Next => (Handle != IntPtr.Zero) ? LLVM.GetNextBasicBlock(this) : default; diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMMetadataRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMMetadataRef.cs index 7d49e735..09c5f9ea 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMMetadataRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMMetadataRef.cs @@ -8,6 +8,104 @@ public unsafe partial struct LLVMMetadataRef(IntPtr handle) : IEquatable IsType ? LLVM.DITypeGetAlignInBits(this) : default; + + public readonly uint Column => Kind switch { + LLVMMetadataKind.LLVMDILocationMetadataKind => LLVM.DILocationGetColumn(this), + _ => default, + }; + + public readonly LLVMMetadataRef Expression => Kind switch { + LLVMMetadataKind.LLVMDIGlobalVariableExpressionMetadataKind => LLVM.DIGlobalVariableExpressionGetExpression(this), + _ => default, + }; + + public readonly LLVMMetadataRef File => Kind switch { + LLVMMetadataKind.LLVMDIFileMetadataKind => this, + LLVMMetadataKind.LLVMDISubprogramMetadataKind => LLVM.DIScopeGetFile(this), + _ when IsVariable => LLVM.DIVariableGetFile(this), + _ => default, + }; + + public readonly LLVMDIFlags Flags => IsType ? LLVM.DITypeGetFlags(this) : default; + + public readonly LLVMMetadataRef InlinedAt => Kind switch { + LLVMMetadataKind.LLVMDILocationMetadataKind => LLVM.DILocationGetInlinedAt(this), + _ => default, + }; + + public readonly bool IsDINode => Kind is >= LLVMMetadataKind.LLVMDILocationMetadataKind and <= LLVMMetadataKind.LLVMDIAssignIDMetadataKind; + + public readonly bool IsTemplateParameter => Kind switch { + LLVMMetadataKind.LLVMDITemplateTypeParameterMetadataKind => true, + LLVMMetadataKind.LLVMDITemplateValueParameterMetadataKind => true, + _ => false, + }; + + public readonly bool IsType => Kind switch { + LLVMMetadataKind.LLVMDICompositeTypeMetadataKind => true, + LLVMMetadataKind.LLVMDIDerivedTypeMetadataKind => true, + LLVMMetadataKind.LLVMDIStringTypeMetadataKind => true, + LLVMMetadataKind.LLVMDIBasicTypeMetadataKind => true, + LLVMMetadataKind.LLVMDISubroutineTypeMetadataKind => true, + _ => false, + }; + + public readonly bool IsVariable => Kind switch { + LLVMMetadataKind.LLVMDILocalVariableMetadataKind => true, + LLVMMetadataKind.LLVMDIGlobalVariableMetadataKind => true, + _ => false, + }; + + public readonly LLVMMetadataKind Kind => Handle == default + ? (LLVMMetadataKind)(-1) // 0 is a valid kind, so we use -1 to indicate a null metadata reference + : (LLVMMetadataKind)LLVM.GetMetadataKind(this); + + public readonly uint Line => Kind switch { + LLVMMetadataKind.LLVMDISubprogramMetadataKind => LLVM.DISubprogramGetLine(this), + LLVMMetadataKind.LLVMDILocationMetadataKind => LLVM.DILocationGetLine(this), + _ when IsType => LLVM.DITypeGetLine(this), + _ when IsVariable => LLVM.DIVariableGetLine(this), + _ => default, + }; + + public readonly string Name + { + get + { + if (!IsType) + { + return ""; + } + + nuint nameLength = 0; + sbyte* namePtr = LLVM.DITypeGetName(this, &nameLength); + if (namePtr == null) + { + return ""; + } + + return new ReadOnlySpan(namePtr, (int)nameLength).AsString(); + } + } + + public readonly ulong OffsetInBits => IsType ? LLVM.DITypeGetOffsetInBits(this) : default; + + public readonly LLVMMetadataRef Scope => Kind switch { + LLVMMetadataKind.LLVMDILocationMetadataKind => LLVM.DILocationGetScope(this), + _ when IsVariable => LLVM.DIVariableGetScope(this), + _ => default, + }; + + public readonly ulong SizeInBits => IsType ? LLVM.DITypeGetSizeInBits(this) : default; + + public readonly ushort Tag => IsDINode ? LLVM.GetDINodeTag(this) : default; + + public readonly LLVMMetadataRef Variable => Kind switch { + LLVMMetadataKind.LLVMDIGlobalVariableExpressionMetadataKind => LLVM.DIGlobalVariableExpressionGetVariable(this), + _ => default, + }; + public static implicit operator LLVMMetadataRef(LLVMOpaqueMetadata* value) => new LLVMMetadataRef((IntPtr)value); public static implicit operator LLVMOpaqueMetadata*(LLVMMetadataRef value) => (LLVMOpaqueMetadata*)value.Handle; @@ -16,11 +114,19 @@ public unsafe partial struct LLVMMetadataRef(IntPtr handle) : IEquatable !(left == right); + public readonly LLVMValueRef AsValue(LLVMContextRef context) => context.MetadataAsValue(this); + public override readonly bool Equals(object? obj) => (obj is LLVMMetadataRef other) && Equals(other); public readonly bool Equals(LLVMMetadataRef other) => this == other; public override readonly int GetHashCode() => Handle.GetHashCode(); + public readonly string GetMDString(LLVMContextRef context, out uint length) + { + var value = context.MetadataAsValue(this); + return value.GetMDString(out length); + } + public override readonly string ToString() => $"{nameof(LLVMMetadataRef)}: {Handle:X}"; } diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleFunctionsEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleFunctionsEnumerable.cs new file mode 100644 index 00000000..954c303d --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleFunctionsEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMModuleFunctionsEnumerable(LLVMModuleRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMModuleRef module) : IEnumerator + { + public LLVMValueRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstFunction; + } + else + { + Current = Current.NextFunction; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalAliasesEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalAliasesEnumerable.cs new file mode 100644 index 00000000..a741b8fa --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalAliasesEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMModuleGlobalAliasesEnumerable(LLVMModuleRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMModuleRef module) : IEnumerator + { + public LLVMValueRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstGlobalAlias; + } + else + { + Current = Current.NextGlobalAlias; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalIFuncsEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalIFuncsEnumerable.cs new file mode 100644 index 00000000..d2ea05a8 --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalIFuncsEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMModuleGlobalIFuncsEnumerable(LLVMModuleRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMModuleRef module) : IEnumerator + { + public LLVMValueRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstGlobalIFunc; + } + else + { + Current = Current.NextGlobalIFunc; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalsEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalsEnumerable.cs new file mode 100644 index 00000000..f47772c9 --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleGlobalsEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMModuleGlobalsEnumerable(LLVMModuleRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMModuleRef module) : IEnumerator + { + public LLVMValueRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstGlobal; + } + else + { + Current = Current.NextGlobal; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleNamedMetadataEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleNamedMetadataEnumerable.cs new file mode 100644 index 00000000..dda91a80 --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleNamedMetadataEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMModuleNamedMetadataEnumerable(LLVMModuleRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMModuleRef module) : IEnumerator + { + public LLVMNamedMDNodeRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstNamedMetadata; + } + else + { + Current = Current.NextNamedMetadata; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMModuleRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMModuleRef.cs index 9f5b60fa..200873de 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMModuleRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMModuleRef.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. using System; +using System.Collections.Generic; using System.Runtime.InteropServices; namespace LLVMSharp.Interop; @@ -37,14 +38,51 @@ public readonly string DataLayout } } + public readonly uint DebugMetadataVersion => (Handle != IntPtr.Zero) ? LLVM.GetModuleDebugMetadataVersion(this) : default; + public readonly LLVMValueRef FirstFunction => (Handle != IntPtr.Zero) ? LLVM.GetFirstFunction(this) : default; public readonly LLVMValueRef FirstGlobal => (Handle != IntPtr.Zero) ? LLVM.GetFirstGlobal(this) : default; + public readonly LLVMValueRef FirstGlobalAlias => (Handle != IntPtr.Zero) ? LLVM.GetFirstGlobalAlias(this) : default; + + public readonly LLVMValueRef FirstGlobalIFunc => (Handle != IntPtr.Zero) ? LLVM.GetFirstGlobalIFunc(this) : default; + + public readonly LLVMNamedMDNodeRef FirstNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetFirstNamedMetadata(this) : default; + + public readonly LLVMModuleFunctionsEnumerable Functions => new LLVMModuleFunctionsEnumerable(this); + + public readonly LLVMModuleGlobalsEnumerable Globals => new LLVMModuleGlobalsEnumerable(this); + + public readonly LLVMModuleGlobalAliasesEnumerable GlobalAliases => new LLVMModuleGlobalAliasesEnumerable(this); + + public readonly LLVMModuleGlobalIFuncsEnumerable GlobalIFuncs => new LLVMModuleGlobalIFuncsEnumerable(this); + + public readonly int IsNewDbgInfoFormat + { + get + { + return (Handle != IntPtr.Zero) ? LLVM.IsNewDbgInfoFormat(this) : 0; + } + + set + { + LLVM.SetIsNewDbgInfoFormat(this, value); + } + } + public readonly LLVMValueRef LastFunction => (Handle != IntPtr.Zero) ? LLVM.GetLastFunction(this) : default; public readonly LLVMValueRef LastGlobal => (Handle != IntPtr.Zero) ? LLVM.GetLastGlobal(this) : default; + public readonly LLVMValueRef LastGlobalAlias => (Handle != IntPtr.Zero) ? LLVM.GetLastGlobalAlias(this) : default; + + public readonly LLVMValueRef LastGlobalIFunc => (Handle != IntPtr.Zero) ? LLVM.GetLastGlobalIFunc(this) : default; + + public readonly LLVMNamedMDNodeRef LastNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetLastNamedMetadata(this) : default; + + public readonly LLVMModuleNamedMetadataEnumerable NamedMetadata => new LLVMModuleNamedMetadataEnumerable(this); + public readonly string Target { get diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMNamedMDNodeRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMNamedMDNodeRef.cs index 8ecdc155..031fbb60 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMNamedMDNodeRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMNamedMDNodeRef.cs @@ -8,6 +8,30 @@ public unsafe partial struct LLVMNamedMDNodeRef(IntPtr handle) : IEquatable(namePtr, (int)nameLength).AsString(); + } + } + + public readonly LLVMNamedMDNodeRef NextNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetNextNamedMetadata(this) : default; + + public readonly LLVMNamedMDNodeRef PreviousNamedMetadata => (Handle != IntPtr.Zero) ? LLVM.GetPreviousNamedMetadata(this) : default; + public static implicit operator LLVMNamedMDNodeRef(LLVMOpaqueNamedMDNode* value) => new LLVMNamedMDNodeRef((IntPtr)value); public static implicit operator LLVMOpaqueNamedMDNode*(LLVMNamedMDNodeRef value) => (LLVMOpaqueNamedMDNode*)value.Handle; diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMUseRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMUseRef.cs index cd81413d..17168c83 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMUseRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMUseRef.cs @@ -8,6 +8,10 @@ public unsafe partial struct LLVMUseRef(IntPtr handle) : IEquatable { public IntPtr Handle = handle; + public readonly LLVMUseRef NextUse => (Handle != IntPtr.Zero) ? LLVM.GetNextUse(this) : default; + + public readonly LLVMValueRef User => (Handle != IntPtr.Zero) ? LLVM.GetUser(this) : default; + public static implicit operator LLVMUseRef(LLVMOpaqueUse* Use) => new LLVMUseRef((IntPtr)Use); public static implicit operator LLVMOpaqueUse*(LLVMUseRef Use) => (LLVMOpaqueUse*)Use.Handle; diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs b/sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs index 41edce31..c7ace722 100644 --- a/sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs +++ b/sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. using System; +using System.Collections.Generic; +using System.Linq; using static LLVMSharp.Interop.LLVMTailCallKind; namespace LLVMSharp.Interop; @@ -56,6 +58,10 @@ public readonly LLVMValueRef Condition public readonly LLVMOpcode ConstOpcode => (IsAConstantExpr != null) ? LLVM.GetConstOpcode(this) : default; + public readonly double ConstRealDouble => (IsAConstantFP != null) ? GetConstRealDouble(out _) : default; + + public readonly LLVMContextRef Context => (Handle != IntPtr.Zero) ? LLVM.GetValueContext(this) : default; + public readonly LLVMDLLStorageClass DLLStorageClass { get @@ -491,10 +497,16 @@ public readonly string Name public readonly LLVMValueRef NextGlobal => (IsAGlobalVariable != null) ? LLVM.GetNextGlobal(this) : default; + public readonly LLVMValueRef NextGlobalAlias => (IsAGlobalAlias != null) ? LLVM.GetNextGlobalAlias(this) : default; + + public readonly LLVMValueRef NextGlobalIFunc => (IsAGlobalIFunc != null) ? LLVM.GetNextGlobalIFunc(this) : default; + public readonly LLVMValueRef NextInstruction => (IsAInstruction != null) ? LLVM.GetNextInstruction(this) : default; public readonly LLVMValueRef NextParam => (IsAArgument != null) ? LLVM.GetNextParam(this) : default; + public readonly LLVMOpcode Opcode => Kind is LLVMValueKind.LLVMInstructionValueKind ? InstructionOpcode : ConstOpcode; + public readonly int OperandCount => ((Kind == LLVMValueKind.LLVMMetadataAsValueValueKind) || (IsAUser != null)) ? LLVM.GetNumOperands(this) : default; public readonly uint ParamsCount => (IsAFunction != null) ? LLVM.CountParams(this) : default; @@ -516,6 +528,10 @@ public readonly LLVMValueRef PersonalityFn public readonly LLVMValueRef PreviousGlobal => (IsAGlobalVariable != null) ? LLVM.GetPreviousGlobal(this) : default; + public readonly LLVMValueRef PreviousGlobalAlias => (IsAGlobalAlias != null) ? LLVM.GetPreviousGlobalAlias(this) : default; + + public readonly LLVMValueRef PreviousGlobalIFunc => (IsAGlobalIFunc != null) ? LLVM.GetPreviousGlobalIFunc(this) : default; + public readonly LLVMValueRef PreviousInstruction => (IsAInstruction != null) ? LLVM.GetPreviousInstruction(this) : default; public readonly LLVMValueRef PreviousParam => (IsAArgument != null) ? LLVM.GetPreviousParam(this) : default; @@ -548,6 +564,8 @@ public readonly string Section } } + public readonly LLVMMetadataRef Subprogram => (IsAFunction != null) ? LLVM.GetSubprogram(this) : default; + public readonly uint SuccessorsCount => (IsAInstruction != null) ? LLVM.GetNumSuccessors(this) : default; public readonly LLVMBasicBlockRef SwitchDefaultDest => (IsASwitchInst != null) ? LLVM.GetSwitchDefaultDest(this) : default; @@ -580,6 +598,8 @@ public readonly LLVMThreadLocalMode ThreadLocalMode public readonly LLVMTypeRef TypeOf => (Handle != IntPtr.Zero) ? LLVM.TypeOf(this) : default; + public readonly LLVMValueUsesEnumerable Uses => new LLVMValueUsesEnumerable(this); + public readonly LLVMVisibility Visibility { get @@ -840,6 +860,8 @@ public readonly LLVMBasicBlockRef AppendBasicBlock(ReadOnlySpan Name) public readonly LLVMBasicBlockRef AsBasicBlock() => LLVM.ValueAsBasicBlock(this); + public readonly LLVMMetadataRef AsMetadata() => LLVM.ValueAsMetadata(this); + public readonly void DeleteFunction() => LLVM.DeleteFunction(this); public readonly void DeleteGlobal() => LLVM.DeleteGlobal(this); @@ -850,6 +872,35 @@ public readonly LLVMBasicBlockRef AppendBasicBlock(ReadOnlySpan Name) public readonly bool Equals(LLVMValueRef other) => this == other; + public readonly LLVMMetadataRef[] GetAllMetadataOtherThanDebugLoc() + { + if (IsAInstruction == null) + { + return []; + } + + nuint metadataCount = 0; + var ptr = LLVM.InstructionGetAllMetadataOtherThanDebugLoc(this, &metadataCount); + + LLVMMetadataRef[] metadataArray; + if (metadataCount == 0) + { + metadataArray = []; + } + else + { + metadataArray = new LLVMMetadataRef[metadataCount]; + for (uint i = 0; i < metadataCount; i++) + { + metadataArray[i] = LLVM.ValueMetadataEntriesGetMetadata(ptr, i); + } + LLVM.DisposeValueMetadataEntries(ptr); + } + + LLVM.DisposeValueMetadataEntries(ptr); + return metadataArray; + } + public readonly string GetAsString(out UIntPtr Length) { fixed (UIntPtr* pLength = &Length) @@ -893,6 +944,26 @@ public readonly void GetBasicBlocks(Span destination) } } + public readonly IEnumerable GetInstructions() + { + if (IsAFunction != default) + { + return GetBasicBlocks().SelectMany(b => b.Instructions); + } + else if (IsABasicBlock != default) + { + return AsBasicBlock().Instructions; + } + else if (IsAInstruction != default) + { + return [this]; + } + else + { + return []; + } + } + public readonly LLVMValueRef[] GetMDNodeOperands() { if (Kind != LLVMValueKind.LLVMMetadataAsValueValueKind) @@ -1022,6 +1093,22 @@ public readonly string GetMDString(out uint Len) public readonly LLVMValueRef GetOperand(uint Index) => LLVM.GetOperand(this, Index); + public readonly LLVMValueRef[] GetOperands() + { + int numOperands = OperandCount; + if (numOperands == 0) + { + return []; + } + + LLVMValueRef[] operands = new LLVMValueRef[numOperands]; + for (int i = 0; i < numOperands; i++) + { + operands[i] = GetOperand((uint)i); + } + return operands; + } + public readonly LLVMUseRef GetOperandUse(uint Index) => LLVM.GetOperandUse(this, Index); public readonly LLVMValueRef GetParam(uint Index) => LLVM.GetParam(this, Index); diff --git a/sources/LLVMSharp.Interop/Extensions/LLVMValueUsesEnumerable.cs b/sources/LLVMSharp.Interop/Extensions/LLVMValueUsesEnumerable.cs new file mode 100644 index 00000000..540223bb --- /dev/null +++ b/sources/LLVMSharp.Interop/Extensions/LLVMValueUsesEnumerable.cs @@ -0,0 +1,42 @@ +// Copyright (c) .NET Foundation and Contributors. All Rights Reserved. Licensed under the MIT License (MIT). See License.md in the repository root for more information. + +using System; +using System.Collections; +using System.Collections.Generic; + +namespace LLVMSharp.Interop; + +public readonly struct LLVMValueUsesEnumerable(LLVMValueRef module) : IEnumerable +{ + public Enumerator GetEnumerator() => new Enumerator(module); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); + + public struct Enumerator(LLVMValueRef module) : IEnumerator + { + public LLVMUseRef Current { get; private set; } + + readonly object IEnumerator.Current => Current; + + readonly void IDisposable.Dispose() + { + } + + public bool MoveNext() + { + if (Current.Handle == 0) + { + Current = module.FirstUse; + } + else + { + Current = Current.NextUse; + } + return Current.Handle != 0; + } + + public void Reset() => Current = default; + } +} diff --git a/tests/LLVMSharp.UnitTests/Functions.cs b/tests/LLVMSharp.UnitTests/Functions.cs index 05c9314b..4235b819 100644 --- a/tests/LLVMSharp.UnitTests/Functions.cs +++ b/tests/LLVMSharp.UnitTests/Functions.cs @@ -26,6 +26,6 @@ public void AddsAttributeAtIndex() functionValue.AddAttributeAtIndex((LLVMAttributeIndex)1, attr); var attrs = functionValue.GetAttributesAtIndex((LLVMAttributeIndex)1); - Assert.That((AttributeKind)attrs[0].Kind, Is.EqualTo(AttributeKind.ByVal)); + Assert.That((AttributeKind)attrs[0].KindAsEnum, Is.EqualTo(AttributeKind.ByVal)); } }