Skip to content

Commit 0505c2a

Browse files
authored
Updates for latest native interop. (#260)
* Updates for latest native interop. * Added support for retrieving Version from native interop as a string. * Removed value cache support as it isn't needed anymore. * Doc comment corrections and typos * Removed unused `using` * Updated version expectations to 20.1.7 as minimum * Updated to 20.1.8-alpha of native libs --------- Co-authored-by: smaillet <25911635+smaillet@users.noreply.github.com>
1 parent f3a4bc8 commit 0505c2a

21 files changed

Lines changed: 78 additions & 93 deletions

File tree

Directory.Packages.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
Global references are included in ALL projects in this repository
55
-->
66
<ItemGroup>
7-
<GlobalPackageReference Include="Ubiquity.NET.Versioning.Build.Tasks" Version="5.0.0-rc" />
7+
<GlobalPackageReference Include="Ubiquity.NET.Versioning.Build.Tasks" Version="5.0.6" />
88
<GlobalPackageReference Include="IDisposableAnalyzers" Version="4.0.8" Condition="'$(NoCommonAnalyzers)' !=' true'" />
99
<GlobalPackageReference Include="MustUseRetVal" Version="0.0.2" />
1010
<!--
@@ -28,6 +28,6 @@
2828
<PackageVersion Include="MSTest.TestAdapter" Version="3.9.1" />
2929
<PackageVersion Include="MSTest.TestFramework" Version="3.9.1" />
3030
<PackageVersion Include="Tmds.ExecFunction" Version="0.8.0" />
31-
<PackageVersion Include="Ubiquity.NET.Versioning" Version="5.0.0-rc" />
31+
<PackageVersion Include="Ubiquity.NET.Versioning" Version="6.0.1" />
3232
</ItemGroup>
33-
</Project>
33+
</Project>

IgnoredWords.dic

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
ABI
22
Accessor
33
Addr
4+
addref
45
alloca
56
anonymize
67
antlr
@@ -49,12 +50,14 @@ dllimport
4950
docfx
5051
docfxconsole
5152
dotnet
53+
endian
5254
endianess
5355
enum
5456
Enums
5557
env
5658
exe
5759
facepalm
60+
finalizer
5861
finalizers
5962
foo
6063
fullsrc

src/Interop/InteropTests/ABI/libllvm-c/TargetRegistrationBindingsTests.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,17 @@ public void LibLLVMGetRuntimeTargetsTest( )
6363
[TestMethod]
6464
public void LibLLVMGetVersionTest( )
6565
{
66-
UInt64 ver = LibLLVMGetVersion();
67-
Assert.IsTrue( ver > 0 );
68-
var csemVer = CSemVer.From(ver);
69-
Assert.AreEqual( 20, csemVer.Major );
70-
Assert.AreEqual( 1, csemVer.Minor );
66+
var ver = SemVer.Parse(LibLLVMGetVersion()?.ToString() ?? string.Empty, SemVerFormatProvider.CaseInsensitive);
67+
Assert.IsTrue( ver is SemVer or CSemVer);
68+
Assert.AreEqual( 20, ver.Major );
69+
Assert.AreEqual( 1, ver.Minor );
7170

7271
// Testing for an exact match of the patch level (or anything finer grained than that)
7372
// in an automated test is dubious as it would require updating the tests on effectively
7473
// EVERY build of the native library... So, this tests for a minimum value that was valid
7574
// at the time of creation. The above major/minor values should be updated on changes to
7675
// those assumptions as any number of things may have changed.
77-
Assert.IsTrue( csemVer.Patch >= 4 );
76+
Assert.IsTrue( ver.Patch >= 7);
7877
}
7978
}
8079
}

src/Interop/Ubiquity.NET.Llvm.Interop/ABI/libllvm-c/TargetRegistrationBindings.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,17 @@ private static unsafe partial LLVMErrorRef LibLLVMGetRuntimeTargets(
7575
LibLLVMCodeGenTarget[] targets, Int32 lengthOfArray
7676
);
7777

78+
public static LazyEncodedString? LibLLVMGetVersion( )
79+
{
80+
unsafe
81+
{
82+
byte* p = LibLLVMGetVersion(out nuint len);
83+
return LazyEncodedString.FromUnmanaged( p, len );
84+
}
85+
}
86+
7887
[LibraryImport( LibraryName )]
7988
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
80-
public static unsafe partial UInt64 LibLLVMGetVersion( );
89+
private static unsafe partial byte* LibLLVMGetVersion(out nuint len);
8190
}
8291
}

src/Interop/Ubiquity.NET.Llvm.Interop/ABI/libllvm-c/ValueBindings.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,6 @@
1010

1111
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c
1212
{
13-
// Misplaced using directive; It isn't misplaced - tooling is too brain dead to know the difference between an alias and a using directive
14-
#pragma warning disable IDE0065, SA1200
15-
using unsafe LibLLVMValueCacheItemDeletedCallback = delegate* unmanaged[Cdecl]< nint /*ctx*/,/*LLVMValueRef*/ nint /*@ref*/, nint /*handle*/, void /*retVal*/>;
16-
using unsafe LibLLVMValueCacheItemReplacedCallback = delegate* unmanaged[Cdecl]< nint /*ctx*/, /*LLVMValueRef*/ nint /*oldValue*/, nint /*handle*/, /*LLVMValueRef*/nint /*newValue*/, nint /*retVal*/ >;
17-
#pragma warning restore IDE0065, SA1200
18-
1913
public enum LibLLVMValueKind
2014
: Int32
2115
{
@@ -159,18 +153,6 @@ public static partial class ValueBindings
159153
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
160154
public static unsafe partial LLVMValueRef LibLLVMValueAsMetadataGetValue( LLVMMetadataRef vmd );
161155

162-
[LibraryImport( LibraryName )]
163-
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
164-
public static unsafe partial LibLLVMValueCacheRef LibLLVMCreateValueCache( nint ctx, LibLLVMValueCacheItemDeletedCallback deletedCallback, LibLLVMValueCacheItemReplacedCallback replacedCallback );
165-
166-
[LibraryImport( LibraryName )]
167-
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
168-
public static unsafe partial void LibLLVMValueCacheAdd( LibLLVMValueCacheRef cacheRef, LLVMValueRef value, nint handle );
169-
170-
[LibraryImport( LibraryName )]
171-
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
172-
public static unsafe partial nint LibLLVMValueCacheLookup( LibLLVMValueCacheRef cacheRef, LLVMValueRef valueRef );
173-
174156
[LibraryImport( LibraryName )]
175157
[UnmanagedCallConv( CallConvs = [ typeof( CallConvCdecl ) ] )]
176158
[return: MarshalAs( UnmanagedType.Bool )]

src/Interop/Ubiquity.NET.Llvm.Interop/GlobalHandleBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ protected GlobalHandleBase( nint handle, bool ownsHandle )
8080
// In a debug build capture the stack for creation of this instance
8181
// that way it is still available if there is an access violation
8282
// in the dispose. Usually such a thing indicates the source did NOT
83-
// properly apply a using. So it is VERY helpful in debugging odf finalizer
83+
// properly apply a using. So it is VERY helpful in debugging of finalizer
8484
// failures to locate the source.
8585
CaptureStack();
8686
#endif
@@ -150,7 +150,7 @@ public static T CloneWithAddRef<T>( this T self )
150150
self.DangerousAddRef( ref success );
151151
if(!success)
152152
{
153-
throw new InvalidOperationException( "Failed to addreff the SafeHandle!" );
153+
throw new InvalidOperationException( "Failed to addref the SafeHandle!" );
154154
}
155155

156156
Marshal.InitHandle( retVal, self.DangerousGetHandle() );

src/Interop/Ubiquity.NET.Llvm.Interop/GlobalHandleMarshaller.cs

Lines changed: 0 additions & 27 deletions
This file was deleted.

src/Interop/Ubiquity.NET.Llvm.Interop/GlobalSuppressions.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
[assembly: SuppressMessage( "StyleCop.CSharp.NamingRules", "SA1300:Element should begin with upper-case letter", Justification = "Interop ABI naming matches source for most structures and types" )]
1818
[assembly: SuppressMessage( "StyleCop.CSharp.DocumentationRules", "SA1649:File name should match first type name", Justification = "Filenames match that of the native ABI header file" )]
1919
[assembly: SuppressMessage( "StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "Interop ABI naming matches source for most structures and types" )]
20-
[assembly: SuppressMessage( "StyleCop.CSharp.DocumentationRules", "SA1642:Constructor summary documentation should begin with standard text", Justification = "Dumb rule - if the summary is really **supposed** to be a fixed format then tooling should just generate it..." )]
2120
[assembly: SuppressMessage( "Style", "IDE1006:Naming Styles", Justification = "Interop ABI naming matches source for most structures and types" )]
2221
[assembly: SuppressMessage( "Redundancies in Symbol Declarations", "RECS0007:The default underlying type of enums is int, so defining it explicitly is redundant.", Justification = "ABI interop; intent is to be explicit for clarity (even if redundant)" )]
2322
[assembly: SuppressMessage( "Maintainability", "CA1506:Avoid excessive class coupling", Justification = "The whole point of this library is to expose the native ABI methods and types" )]

src/Interop/Ubiquity.NET.Llvm.Interop/ILibLlvm.cs

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,31 @@ public interface ILibLlvm
2929
/// <remarks>
3030
/// This is a simple set of enumerated values for the known targets supported by the library. It
3131
/// is distinct from the registered targets. Registration of each top level enumerated target may indeed
32-
/// register support for more targets (e.g., ARM includes thumb big and little endian targets).
32+
/// register support for more targets (e.g., ARM includes thumb big and little endian targets). This reports
33+
/// only the top level architectural targets that are supported and available to register not what is currently
34+
/// registered.
3335
/// </remarks>
3436
ImmutableArray<LibLLVMCodeGenTarget> SupportedTargets { get; }
3537

3638
/// <summary>Gets version information for the library implementation</summary>
37-
/// <returns><see cref="CSemVer"/> for the native interop library</returns>
39+
/// <returns><see cref="FileVersionQuad"/> for the native interop library</returns>
3840
/// <remarks>
39-
/// Not, since it is an extension of LLVM the version is NOT guaranteed to match that of LLVM itself. Though,
40-
/// to avoid confusion it usually does and would only deviate when no option is available (Such as the extension
41-
/// APIs changed even though LLVM itself did not)
41+
/// <note type="note">Since it is dealing with an extension of LLVM, the version is NOT guaranteed to match that
42+
/// of LLVM itself. Though, to avoid confusion, the major, minor and patch usually does and would only deviate
43+
/// when no option is available (Such as the extension APIs changed even though LLVM itself did not)</note>
4244
/// </remarks>
43-
CSemVer GetVersionInfo( );
45+
SemVer ExtendedAPIVersion { get; }
46+
47+
/// <summary>Gets version information for LLVM</summary>
48+
/// <remarks>
49+
/// This is a short hand wrapper around the <see cref="ABI.llvm_c.Core.LLVMGetVersion(out uint, out uint, out uint)"/>
50+
/// for a given library instance. It converts the multiple out params to a <see cref="SemVer"/>.
51+
/// <note type="note">
52+
/// LLVM and the underlying APIs do not support any form of the pre-release information, nor do they support or provide
53+
/// the build meta (which doesn't participate in ordering anyway). Therefore, any ordering from <see cref="SemVerComparer"/>
54+
/// or <see cref="SemVerComparer.CaseSensitive"/> is valid for these versions and will produce the correct ordering.
55+
/// </note>
56+
/// </remarks>
57+
SemVer LlvmVersion { get; }
4458
}
4559
}

src/Interop/Ubiquity.NET.Llvm.Interop/Library.cs

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,17 @@ public void RegisterTarget( LibLLVMCodeGenTarget target, LibLLVMTargetRegistrati
2424
LibLLVMRegisterTarget( target, registrations ).ThrowIfFailed();
2525
}
2626

27-
public CSemVer GetVersionInfo( )
27+
/// <inheritdoc/>
28+
public SemVer ExtendedAPIVersion { get; private set; }
29+
30+
/// <inheritdoc/>
31+
public SemVer LlvmVersion
2832
{
29-
return CSemVer.From( LibLLVMGetVersion() );
33+
get
34+
{
35+
LLVMGetVersion( out UInt32 major, out UInt32 minor, out UInt32 patch );
36+
return new SemVer( major, minor, patch );
37+
}
3038
}
3139

3240
/// <inheritdoc/>
@@ -48,26 +56,27 @@ public static ILibLlvm InitializeLLVM( )
4856
}
4957

5058
// Verify the version of LibLLVM.
51-
var libLLVMVersion = CSemVer.From(LibLLVMGetVersion());
52-
if(libLLVMVersion.Major != SupportedVersion.Major
53-
|| libLLVMVersion.Minor != SupportedVersion.Minor
54-
|| libLLVMVersion.Patch != SupportedVersion.Patch
59+
var libVersion = SemVer.Parse(LibLLVMGetVersion()?.ToString() ?? string.Empty, SemVerFormatProvider.CaseInsensitive);
60+
if( libVersion.Major != SupportedVersion.Major
61+
|| libVersion.Minor != SupportedVersion.Minor
62+
|| libVersion.Patch != SupportedVersion.Patch
5563
)
5664
{
5765
string msgFmt = Resources.Mismatched_LibLLVM_version_Expected_0_Actual_1;
5866
string msg = string.Format( CultureInfo.CurrentCulture
5967
, msgFmt
6068
, SupportedVersion.ToString()
61-
, libLLVMVersion.ToString()
69+
, libVersion.ToString()
6270
);
6371
throw new InvalidOperationException( msg );
6472
}
6573

66-
return new Library();
74+
return new Library(libVersion);
6775
}
6876

69-
private Library( )
77+
private Library( SemVer libVersion )
7078
{
79+
ExtendedAPIVersion = libVersion;
7180
unsafe
7281
{
7382
LLVMInstallFatalErrorHandler( &FatalErrorHandler );
@@ -78,7 +87,7 @@ private Library( )
7887

7988
// Expected version info for verification of matched LibLLVM
8089
// Interop exports/signatures may not be valid if not a match.
81-
private static readonly CSemVer SupportedVersion = new(20, 1, 6);
90+
private static readonly CSemVer SupportedVersion = new(20, 1, 8);
8291

8392
// Singleton initializer for the supported targets array
8493
private static ImmutableArray<LibLLVMCodeGenTarget> GetSupportedTargets( )
@@ -91,20 +100,20 @@ private static ImmutableArray<LibLLVMCodeGenTarget> GetSupportedTargets( )
91100
}
92101

93102
// Native call back for fatal error handling.
103+
// NOTE: LLVM will call exit() upon return from this function and there's no way to stop it
94104
[UnmanagedCallersOnly( CallConvs = [ typeof( CallConvCdecl ) ] )]
95105
[SuppressMessage( "Design", "CA1031:Do not catch general exception types", Justification = "REQUIRED for unmanaged callback - Managed exceptions must never cross the boundary to native code" )]
96106
private static unsafe void FatalErrorHandler( byte* reason )
97107
{
98108
try
99109
{
100-
// NOTE: LLVM will call exit() upon return from this function and there's no way to stop it
101110
Trace.TraceError( "LLVM Fatal Error: '{0}'; Application will exit.", ExecutionEncodingStringMarshaller.ConvertToManaged( reason ) );
102111
}
103112
catch(Exception ex)
104113
{
105114
// No finalizers will occur after this, it's a HARD termination of the app.
106115
// LLVM will do that on return but this can at least indicate a different problem
107-
// from the original LLVM was reporting.
116+
// from the original one LLVM was reporting.
108117
Environment.FailFast( $"Unhandled exception in {nameof( FatalErrorHandler )}.", ex );
109118
}
110119
}

0 commit comments

Comments
 (0)