forked from UbiquityDotNET/Llvm.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLibrary.cs
More file actions
126 lines (109 loc) · 5.34 KB
/
Copy pathLibrary.cs
File metadata and controls
126 lines (109 loc) · 5.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
// Copyright (c) Ubiquity.NET Contributors. All rights reserved.
// Licensed under the Apache-2.0 WITH LLVM-exception license. See the LICENSE.md file in the project root for full license information.
namespace Ubiquity.NET.Llvm.Interop
{
/// <summary>Provides support for various LLVM static state initialization and manipulation</summary>
public sealed class Library
: ILibLlvm
{
/// <inheritdoc/>
public ImmutableArray<LibLLVMCodeGenTarget> SupportedTargets => LazyTargets.Value;
/// <inheritdoc/>
public void RegisterTarget( LibLLVMCodeGenTarget target, LibLLVMTargetRegistrationKind registrations = LibLLVMTargetRegistrationKind.TargetRegistration_All )
{
// NOTE: All logic for registering the targets is in native code.
LibLLVMRegisterTarget( target, registrations ).ThrowIfFailed();
}
/// <inheritdoc/>
public SemVer ExtendedAPIVersion { get; private set; }
/// <inheritdoc/>
public SemVer LlvmVersion
{
get
{
LLVMGetVersion( out UInt32 major, out UInt32 minor, out UInt32 patch );
return new SemVer( major, minor, patch );
}
}
/// <inheritdoc/>
public void Dispose( )
{
LLVMResetFatalErrorHandler();
LLVMShutdown();
}
/// <summary>Initializes the native LLVM library support</summary>
/// <returns><see cref="ILibLlvm"/> implementation for the library</returns>
public static ILibLlvm InitializeLLVM( )
{
// If this is the first call and the library resolver is applied, then validate
// the version from the library for sanity.
if(!NativeLibraryResolver.Apply())
{
throw new InvalidOperationException( "LLVM library was previously initialized. Re-init is not supported in the native library" );
}
// Verify the version of LibLLVM.
string verString = LibLLVMGetVersion()?.ToString() ?? string.Empty;
if(string.IsNullOrWhiteSpace(verString))
{
throw new InvalidOperationException("Internal error: LLVM reported an empty string for version!");
}
var libVersion = SemVer.Parse(LibLLVMGetVersion()?.ToString() ?? string.Empty, SemVerFormatProvider.CaseInsensitive);
if( libVersion is CSemVerCI semVerCI)
{
libVersion = semVerCI.BaseBuild;
}
if( libVersion.Major != SupportedVersion.Major
|| libVersion.Minor != SupportedVersion.Minor
|| libVersion.Patch != SupportedVersion.Patch
)
{
string msgFmt = Resources.Mismatched_LibLLVM_version_Expected_0_Actual_1;
string msg = string.Format( CultureInfo.CurrentCulture
, msgFmt
, SupportedVersion.ToString()
, libVersion.ToString()
);
throw new InvalidOperationException( msg );
}
return new Library(libVersion);
}
private Library( SemVer libVersion )
{
ExtendedAPIVersion = libVersion;
unsafe
{
LLVMInstallFatalErrorHandler( &FatalErrorHandler );
}
}
private readonly Lazy<ImmutableArray<LibLLVMCodeGenTarget>> LazyTargets = new(GetSupportedTargets);
// Expected version info for verification of matched LibLLVM
// Interop exports/signatures may not be valid if not a match.
private static readonly CSemVer SupportedVersion = new(20, 1, 8);
// Singleton initializer for the supported targets array
private static ImmutableArray<LibLLVMCodeGenTarget> GetSupportedTargets( )
{
var resultArray = new LibLLVMCodeGenTarget[LibLLVMGetNumTargets()];
LibLLVMGetRuntimeTargets( resultArray ).ThrowIfFailed();
// Create a new immutable array without copy (Wraps the input array)
return ImmutableCollectionsMarshal.AsImmutableArray( resultArray );
}
// Native call back for fatal error handling.
// NOTE: LLVM will call exit() upon return from this function and there's no way to stop it
[UnmanagedCallersOnly( CallConvs = [ typeof( CallConvCdecl ) ] )]
[SuppressMessage( "Design", "CA1031:Do not catch general exception types", Justification = "REQUIRED for unmanaged callback - Managed exceptions must never cross the boundary to native code" )]
private static unsafe void FatalErrorHandler( byte* reason )
{
try
{
Trace.TraceError( "LLVM Fatal Error: '{0}'; Application will exit.", ExecutionEncodingStringMarshaller.ConvertToManaged( reason ) );
}
catch(Exception ex)
{
// No finalizers will occur after this, it's a HARD termination of the app.
// LLVM will do that on return but this can at least indicate a different problem
// from the original one LLVM was reporting.
Environment.FailFast( $"Unhandled exception in {nameof( FatalErrorHandler )}.", ex );
}
}
}
}