Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions sources/LLVMSharp.Interop/Extensions/LLVMValueRef.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,19 @@ public unsafe partial struct LLVMValueRef(IntPtr handle) : IEquatable<LLVMValueR
{
public IntPtr Handle = handle;

public readonly LLVMValueRef Aliasee
{
get
{
return (IsAGlobalAlias != null) ? LLVM.AliasGetAliasee(this) : default;
}

set
{
LLVM.AliasSetAliasee(this, value);
}
}

public readonly uint Alignment
{
get
Expand Down Expand Up @@ -41,6 +54,10 @@ public readonly LLVMAtomicRMWBinOp AtomicRMWBinOp

public readonly uint BasicBlocksCount => (IsAFunction != null) ? LLVM.CountBasicBlocks(this) : default;

public readonly LLVMBasicBlockRef BlockAddressBasicBlock => (IsABlockAddress != null) ? LLVM.GetBlockAddressBasicBlock(this) : default;

public readonly LLVMValueRef BlockAddressFunction => (IsABlockAddress != null) ? LLVM.GetBlockAddressFunction(this) : default;

public readonly LLVMValueRef Condition
{
get
Expand Down Expand Up @@ -150,6 +167,19 @@ public readonly string GC
}
}

public readonly LLVMValueRef GlobalIFuncResolver
{
get
{
return (IsAGlobalIFunc != null) ? LLVM.GetGlobalIFuncResolver(this) : default;
}

set
{
LLVM.SetGlobalIFuncResolver(this, value);
}
}

public readonly LLVMModuleRef GlobalParent => (IsAGlobalValue != null) ? LLVM.GetGlobalParent(this) : default;

public readonly LLVMTypeRef GlobalValueType => (IsAGlobalValue != null) ? LLVM.GlobalGetValueType(this) : default;
Expand Down Expand Up @@ -636,6 +666,19 @@ public readonly LLVMThreadLocalMode ThreadLocalMode

public readonly LLVMTypeRef TypeOf => (Handle != IntPtr.Zero) ? LLVM.TypeOf(this) : default;

public readonly LLVMUnnamedAddr UnnamedAddress
{
get
{
return (IsAGlobalValue != null) ? LLVM.GetUnnamedAddress(this) : default;
}

set
{
LLVM.SetUnnamedAddress(this, value);
}
}

public readonly LLVMValueUsesEnumerable Uses => new LLVMValueUsesEnumerable(this);

public readonly LLVMVisibility Visibility
Expand Down
39 changes: 37 additions & 2 deletions sources/LLVMSharp/LLVMContext.cs
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
// 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.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using LLVMSharp.Interop;

namespace LLVMSharp;

public sealed class LLVMContext : IEquatable<LLVMContext>
{
private static readonly ConcurrentDictionary<LLVMContextRef, WeakReference<LLVMContext>> s_createdContexts = new ConcurrentDictionary<LLVMContextRef, WeakReference<LLVMContext>>();

private static readonly Lock s_createContextLock = new Lock();

private readonly Dictionary<LLVMValueRef, WeakReference<Value>> _createdValues = [];
private readonly Dictionary<LLVMTypeRef, WeakReference<Type>> _createdTypes = [];

public LLVMContext()
public LLVMContext() : this(LLVMContextRef.Create())
{
}

private LLVMContext(LLVMContextRef handle)
{
Handle = LLVMContextRef.Create();
Handle = handle;
s_createdContexts.GetOrAdd(handle, static (_) => new WeakReference<LLVMContext>(null!)).SetTarget(this);
}

public LLVMContextRef Handle { get; }
Expand All @@ -39,6 +50,30 @@ public LLVMContext()

public override string ToString() => Handle.ToString();

internal static LLVMContext GetOrCreate(LLVMContextRef handle)
{
if (handle == null)
{
Debug.Assert(handle != null);
return null!;
}

var contextRef = s_createdContexts.GetOrAdd(handle, static (_) => new WeakReference<LLVMContext>(null!));

if (!contextRef.TryGetTarget(out var context))
{
lock (s_createContextLock)
{
if (!contextRef.TryGetTarget(out context))
{
context = new LLVMContext(handle);
contextRef.SetTarget(context);
}
}
}
return context;
}

internal BasicBlock GetOrCreate(LLVMBasicBlockRef handle) => GetOrCreate<BasicBlock>(handle.AsValue());

internal TType GetOrCreate<TType>(LLVMTypeRef handle)
Expand Down
2 changes: 2 additions & 0 deletions sources/LLVMSharp/Types/ArrayType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public sealed class ArrayType : SequentialType
internal ArrayType(LLVMTypeRef handle) : base(handle, LLVMTypeKind.LLVMArrayTypeKind)
{
}

public ulong NumElements => Handle.ArrayLength2;
}
27 changes: 27 additions & 0 deletions sources/LLVMSharp/Types/FunctionType.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// 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 LLVMSharp.Interop;

namespace LLVMSharp;
Expand All @@ -9,4 +10,30 @@ public sealed class FunctionType : Type
internal FunctionType(LLVMTypeRef handle) : base(handle, LLVMTypeKind.LLVMFunctionTypeKind)
{
}

public bool IsVarArg => Handle.IsFunctionVarArg;

public uint NumParams => Handle.ParamTypesCount;

public Type ReturnType => Context.GetOrCreate(Handle.ReturnType);

public Type[] GetParams()
{
var handles = Handle.GetParamTypes();

if (handles.Length == 0)
{
return [];
}

var context = Context;
var result = new Type[handles.Length];

for (var i = 0; i < result.Length; i++)
{
result[i] = context.GetOrCreate(handles[i]);
}

return result;
}
}
2 changes: 2 additions & 0 deletions sources/LLVMSharp/Types/IntegerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public sealed class IntegerType : Type
internal IntegerType(LLVMTypeRef handle) : base(handle, LLVMTypeKind.LLVMIntegerTypeKind)
{
}

public uint BitWidth => Handle.IntWidth;
}
2 changes: 2 additions & 0 deletions sources/LLVMSharp/Types/PointerType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public sealed class PointerType : Type
internal PointerType(LLVMTypeRef handle) : base(handle, LLVMTypeKind.LLVMPointerTypeKind)
{
}

public uint AddressSpace => Handle.PointerAddressSpace;
}
2 changes: 2 additions & 0 deletions sources/LLVMSharp/Types/SequentialType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public class SequentialType : CompositeType
private protected SequentialType(LLVMTypeRef handle, LLVMTypeKind expectedTypeKind) : base(handle, expectedTypeKind)
{
}

public Type ElementType => Context.GetOrCreate(Handle.ElementType);
}
50 changes: 50 additions & 0 deletions sources/LLVMSharp/Types/StructType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,54 @@ public static StructType Create(LLVMContext context, ReadOnlySpan<char> name)
var handle = context.Handle.CreateNamedStruct(name);
return context.GetOrCreate<StructType>(handle);
}

public bool IsOpaque => Handle.IsOpaqueStruct;

public bool IsPacked => Handle.IsPackedStruct;

public string Name => Handle.StructName;

public uint NumElements => Handle.StructElementTypesCount;

public Type GetElementType(uint index) => Context.GetOrCreate(Handle.StructGetTypeAtIndex(index));

public Type[] GetElementTypes()
{
var handles = Handle.GetStructElementTypes();

if (handles.Length == 0)
{
return [];
}

var context = Context;
var result = new Type[handles.Length];

for (var i = 0; i < result.Length; i++)
{
result[i] = context.GetOrCreate(handles[i]);
}

return result;
}

public void SetBody(Type[] elementTypes, bool packed)
{
ArgumentNullException.ThrowIfNull(elementTypes);
SetBody(elementTypes.AsSpan(), packed);
}

public void SetBody(ReadOnlySpan<Type> elementTypes, bool packed)
{
var handles = new LLVMTypeRef[elementTypes.Length];

for (var i = 0; i < handles.Length; i++)
{
var elementType = elementTypes[i];
ArgumentNullException.ThrowIfNull(elementType);
handles[i] = elementType.Handle;
}

Handle.StructSetBody(handles, packed);
}
}
52 changes: 52 additions & 0 deletions sources/LLVMSharp/Types/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,54 @@ private protected Type(LLVMTypeRef handle, LLVMTypeKind expectedTypeKind)

public LLVMTypeRef Handle { get; }

public LLVMContext Context => LLVMContext.GetOrCreate(Handle.Context);

public bool IsAggregateType => Handle.Kind is LLVMTypeKind.LLVMStructTypeKind or LLVMTypeKind.LLVMArrayTypeKind;

public bool IsArrayTy => Handle.Kind == LLVMTypeKind.LLVMArrayTypeKind;

public bool IsBFloatTy => Handle.Kind == LLVMTypeKind.LLVMBFloatTypeKind;

public bool IsDoubleTy => Handle.Kind == LLVMTypeKind.LLVMDoubleTypeKind;

public bool IsFP128Ty => Handle.Kind == LLVMTypeKind.LLVMFP128TypeKind;

public bool IsFloatTy => Handle.Kind == LLVMTypeKind.LLVMFloatTypeKind;

public bool IsFloatingPointTy => Handle.Kind is LLVMTypeKind.LLVMHalfTypeKind or LLVMTypeKind.LLVMBFloatTypeKind or LLVMTypeKind.LLVMFloatTypeKind or LLVMTypeKind.LLVMDoubleTypeKind or LLVMTypeKind.LLVMX86_FP80TypeKind or LLVMTypeKind.LLVMFP128TypeKind or LLVMTypeKind.LLVMPPC_FP128TypeKind;

public bool IsFunctionTy => Handle.Kind == LLVMTypeKind.LLVMFunctionTypeKind;

public bool IsHalfTy => Handle.Kind == LLVMTypeKind.LLVMHalfTypeKind;

public bool IsIntegerTy => Handle.Kind == LLVMTypeKind.LLVMIntegerTypeKind;

public bool IsLabelTy => Handle.Kind == LLVMTypeKind.LLVMLabelTypeKind;

public bool IsMetadataTy => Handle.Kind == LLVMTypeKind.LLVMMetadataTypeKind;

public bool IsPPCFP128Ty => Handle.Kind == LLVMTypeKind.LLVMPPC_FP128TypeKind;

public bool IsPointerTy => Handle.Kind == LLVMTypeKind.LLVMPointerTypeKind;

public bool IsSized => Handle.IsSized;

public bool IsStructTy => Handle.Kind == LLVMTypeKind.LLVMStructTypeKind;

public bool IsTokenTy => Handle.Kind == LLVMTypeKind.LLVMTokenTypeKind;

public bool IsVectorTy => Handle.Kind is LLVMTypeKind.LLVMVectorTypeKind or LLVMTypeKind.LLVMScalableVectorTypeKind;

public bool IsVoidTy => Handle.Kind == LLVMTypeKind.LLVMVoidTypeKind;

public bool IsX86AMXTy => Handle.Kind == LLVMTypeKind.LLVMX86_AMXTypeKind;

public bool IsX86FP80Ty => Handle.Kind == LLVMTypeKind.LLVMX86_FP80TypeKind;

public LLVMTypeKind Kind => Handle.Kind;

public Type ScalarType => (Handle.Kind is LLVMTypeKind.LLVMVectorTypeKind or LLVMTypeKind.LLVMScalableVectorTypeKind) ? Context.GetOrCreate(Handle.ElementType) : this;

public static bool operator ==(Type? left, Type? right) => ReferenceEquals(left, right) || (left?.Handle == right?.Handle);

public static bool operator !=(Type? left, Type? right) => !(left == right);
Expand Down Expand Up @@ -128,6 +176,10 @@ public static Type GetX86_FP80Ty(LLVMContext c)

public override string ToString() => Handle.ToString();

public void Dump() => Handle.Dump();

public string PrintToString() => Handle.PrintToString();

internal static Type Create(LLVMTypeRef handle) => handle.Kind switch
{
LLVMTypeKind.LLVMVoidTypeKind => new Type(handle, LLVMTypeKind.LLVMVoidTypeKind),
Expand Down
2 changes: 2 additions & 0 deletions sources/LLVMSharp/Types/VectorType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ public sealed class VectorType : SequentialType
internal VectorType(LLVMTypeRef handle) : base(handle, LLVMTypeKind.LLVMVectorTypeKind)
{
}

public uint NumElements => Handle.VectorSize;
}
4 changes: 4 additions & 0 deletions sources/LLVMSharp/Values/Users/Constants/BlockAddress.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ public sealed class BlockAddress : Constant
internal BlockAddress(LLVMValueRef handle) : base(handle.IsABlockAddress, LLVMValueKind.LLVMBlockAddressValueKind)
{
}

public BasicBlock BasicBlock => Context.GetOrCreate(Handle.BlockAddressBasicBlock);

public Function Function => Context.GetOrCreate<Function>(Handle.BlockAddressFunction);
}
8 changes: 8 additions & 0 deletions sources/LLVMSharp/Values/Users/Constants/Constant.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ private protected Constant(LLVMValueRef handle, LLVMValueKind expectedValueKind)
{
}

public bool IsNullValue => Handle.IsNull;

public Constant? GetAggregateElement(uint index)
{
var handle = Handle.GetAggregateElement(index);
return (handle == null) ? null : Context.GetOrCreate<Constant>(handle);
}

internal static new Constant Create(LLVMValueRef handle) => handle switch
{
_ when handle.IsABlockAddress != null => new BlockAddress(handle),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ private protected ConstantDataSequential(LLVMValueRef handle, LLVMValueKind expe
{
}

public bool IsString => Handle.IsConstantString;

public string AsString() => Handle.GetAsString(out _);

internal static new ConstantDataSequential Create(LLVMValueRef handle) => handle switch
{
_ when handle.IsAConstantDataArray != null => new ConstantDataArray(handle),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ public sealed class ConstantFP : ConstantData
internal ConstantFP(LLVMValueRef handle) : base(handle.IsAConstantFP, LLVMValueKind.LLVMConstantFPValueKind)
{
}

public double ValueAsDouble => Handle.ConstRealDouble;

public double GetDouble(out bool losesInfo) => Handle.GetConstRealDouble(out losesInfo);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,8 @@ public sealed class ConstantInt : ConstantData
internal ConstantInt(LLVMValueRef handle) : base(handle.IsAConstantInt, LLVMValueKind.LLVMConstantIntValueKind)
{
}

public long SExtValue => Handle.ConstIntSExt;

public ulong ZExtValue => Handle.ConstIntZExt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ private protected ConstantExpr(LLVMValueRef handle) : base(handle.IsAConstantExp
{
}

public LLVMOpcode Opcode => Handle.ConstOpcode;

internal static new ConstantExpr Create(LLVMValueRef handle) => handle switch
{
_ => new ConstantExpr(handle),
Expand Down
Loading
Loading