diff --git a/sources/LLVMSharp/Interop.Extensions/LLVMTargetMachineRef.cs b/sources/LLVMSharp/Interop.Extensions/LLVMTargetMachineRef.cs index cd37b48c..ed86e7dd 100644 --- a/sources/LLVMSharp/Interop.Extensions/LLVMTargetMachineRef.cs +++ b/sources/LLVMSharp/Interop.Extensions/LLVMTargetMachineRef.cs @@ -22,18 +22,7 @@ public LLVMTargetMachineRef(IntPtr handle) public static bool operator !=(LLVMTargetMachineRef left, LLVMTargetMachineRef right) => !(left == right); - public string CreateTargetDataLayout() - { - var pDataLayout = LLVM.CreateTargetDataLayout(this); - - if (pDataLayout is null) - { - return string.Empty; - } - - var span = new ReadOnlySpan(pDataLayout, int.MaxValue); - return span.Slice(0, span.IndexOf((byte)'\0')).AsString(); - } + public LLVMTargetDataRef CreateTargetDataLayout() => LLVM.CreateTargetDataLayout(this); public void EmitToFile(LLVMModuleRef module, string fileName, LLVMCodeGenFileType codegen) => EmitToFile(module, fileName.AsSpan(), codegen); diff --git a/sources/LLVMSharp/Interop.Extensions/LLVMTargetRef.cs b/sources/LLVMSharp/Interop.Extensions/LLVMTargetRef.cs index 0b1ab452..b1d84600 100644 --- a/sources/LLVMSharp/Interop.Extensions/LLVMTargetRef.cs +++ b/sources/LLVMSharp/Interop.Extensions/LLVMTargetRef.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; namespace LLVMSharp.Interop { @@ -30,6 +31,41 @@ public static string DefaultTriple } } + public static bool TryGetTargetFromTriple(ReadOnlySpan triple, out LLVMTargetRef outTarget, out string outError) + { + using var marshaledTriple = new MarshaledString(triple); + + fixed (LLVMTargetRef* pOutTarget = &outTarget) + { + sbyte* pError; + var result = LLVM.GetTargetFromTriple(marshaledTriple, (LLVMTarget**)pOutTarget, &pError); + + if (pError is null) + { + outError = string.Empty; + } + else + { + var span = new ReadOnlySpan(pError, int.MaxValue); + outError = span.Slice(0, span.IndexOf((byte)'\0')).AsString(); + } + + return result == 0; + } + } + + public static LLVMTargetRef GetTargetFromTriple(string triple) => GetTargetFromTriple(triple.AsSpan()); + + public static LLVMTargetRef GetTargetFromTriple(ReadOnlySpan triple) + { + if (!TryGetTargetFromTriple(triple, out LLVMTargetRef target, out string message)) + { + throw new ExternalException(message); + } + + return target; + } + public static LLVMTargetRef First => LLVM.GetFirstTarget(); public static IEnumerable Targets diff --git a/tests/LLVMSharp.UnitTests/TargetData.cs b/tests/LLVMSharp.UnitTests/TargetData.cs index cd271023..d2ed9d38 100644 --- a/tests/LLVMSharp.UnitTests/TargetData.cs +++ b/tests/LLVMSharp.UnitTests/TargetData.cs @@ -67,5 +67,29 @@ public void AlignmentTest() LLVMValueRef global = m.AddGlobal(LLVMTypeRef.CreatePointer(LLVMTypeRef.Int8, 0), "someGlobal"); Assert.AreEqual(4, target.PreferredAlignmentOfGlobal(global)); } + + private LLVMTargetDataRef TargetDataFromTriple(string triple) + { + LLVMTargetRef target = LLVMTargetRef.GetTargetFromTriple(triple); + LLVMTargetMachineRef targetMachine = target.CreateTargetMachine(triple, "", "", + LLVMCodeGenOptLevel.LLVMCodeGenLevelDefault, LLVMRelocMode.LLVMRelocDefault, + LLVMCodeModel.LLVMCodeModelDefault); + return targetMachine.CreateTargetDataLayout(); + } + + [Test] + public void MachineTest() + { + LLVM.InitializeX86TargetInfo(); + LLVM.InitializeX86Target(); + LLVM.InitializeX86TargetMC(); + + LLVMTypeRef pointerType = LLVMTypeRef.CreatePointer(LLVMTypeRef.Int32, 0); + LLVMTargetDataRef x86 = TargetDataFromTriple("i386-unknown-unknown"); + LLVMTargetDataRef x86_64 = TargetDataFromTriple("amd64-unknown-unknown"); + + Assert.AreEqual(4, x86.ABISizeOfType(pointerType)); + Assert.AreEqual(8, x86_64.ABISizeOfType(pointerType)); + } } }