1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Runtime.InteropServices; 10 using Antmicro.Renode.Exceptions; 11 12 namespace Antmicro.Renode.Peripherals.CPU.Assembler 13 { 14 public class LLVMAssembler : IAssembler 15 { LLVMAssembler(ICPU cpu)16 public LLVMAssembler(ICPU cpu) 17 { 18 if(!LLVMArchitectureMapping.IsSupported(cpu)) 19 { 20 throw new ArgumentOutOfRangeException(nameof(cpu)); 21 } 22 this.cpu = cpu; 23 } 24 AssembleBlock(ulong pc, string code, uint flags)25 public byte[] AssembleBlock(ulong pc, string code, uint flags) 26 { 27 LLVMArchitectureMapping.GetTripleAndModelKey(cpu, flags, out var triple, out var model); 28 // We need to initialize the architecture to be used before trying to assemble. 29 // It's OK and cheap to initialize it multiple times, as this only sets a few pointers. 30 init_llvm_architecture(triple); 31 bool ok; 32 IntPtr output; 33 IntPtr outLen; 34 try 35 { 36 ok = llvm_asm(triple, model, flags, code, pc, out output, out outLen); 37 } 38 catch(EntryPointNotFoundException e) 39 { 40 throw new RecoverableException("Old version of libllvm-disas is in use, assembly is not available: ", e); 41 } 42 if(!ok) 43 { 44 var error = Marshal.PtrToStringAnsi(output); 45 llvm_free_asm_result(output); 46 throw new RecoverableException(string.Format("Failed to assemble. Reason: {0}", error)); 47 } 48 49 var result = new byte[(int)outLen]; 50 Marshal.Copy(output, result, 0, (int)outLen); 51 llvm_free_asm_result(output); 52 return result; 53 } 54 55 private readonly ICPU cpu; 56 57 [DllImport("libllvm-disas")] init_llvm_architecture(string triple)58 private static extern IntPtr init_llvm_architecture(string triple); 59 60 [DllImport("libllvm-disas")] llvm_asm(string arch, string cpu, uint flags, string instructions, ulong addr, out IntPtr output, out IntPtr outLen)61 private static extern bool llvm_asm(string arch, string cpu, uint flags, string instructions, ulong addr, out IntPtr output, out IntPtr outLen); 62 63 [DllImport("libllvm-disas")] llvm_free_asm_result(IntPtr result)64 private static extern void llvm_free_asm_result(IntPtr result); 65 } 66 } 67