diff --git a/ARMeilleure/CodeGen/CompiledFunction.cs b/ARMeilleure/CodeGen/CompiledFunction.cs index 61e89c2401..ab5e88ebb2 100644 --- a/ARMeilleure/CodeGen/CompiledFunction.cs +++ b/ARMeilleure/CodeGen/CompiledFunction.cs @@ -1,17 +1,56 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Unwinding; +using ARMeilleure.Translation.Cache; +using System; +using System.Runtime.InteropServices; namespace ARMeilleure.CodeGen { - struct CompiledFunction + /// + /// Represents a compiled function. + /// + readonly struct CompiledFunction { + /// + /// Gets the machine code of the . + /// public byte[] Code { get; } + /// + /// Gets the of the . + /// public UnwindInfo UnwindInfo { get; } - public CompiledFunction(byte[] code, UnwindInfo unwindInfo) + /// + /// Gets the of the . + /// + public RelocInfo RelocInfo { get; } + + /// + /// Initializes a new instance of the struct with the specified machine code, + /// unwind info and relocation info. + /// + /// Machine code + /// Unwind info + /// Relocation info + internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo) { Code = code; UnwindInfo = unwindInfo; + RelocInfo = relocInfo; + } + + /// + /// Maps the onto the and returns a delegate of type + /// pointing to the mapped function. + /// + /// Type of delegate + /// A delegate of type pointing to the mapped function + public T Map() + { + IntPtr codePtr = JitCache.Map(this); + + return Marshal.GetDelegateForFunctionPointer(codePtr); } } } \ No newline at end of file diff --git a/ARMeilleure/CodeGen/Linking/RelocEntry.cs b/ARMeilleure/CodeGen/Linking/RelocEntry.cs new file mode 100644 index 0000000000..a27bfded2c --- /dev/null +++ b/ARMeilleure/CodeGen/Linking/RelocEntry.cs @@ -0,0 +1,38 @@ +namespace ARMeilleure.CodeGen.Linking +{ + /// + /// Represents a relocation. + /// + readonly struct RelocEntry + { + public const int Stride = 13; // Bytes. + + /// + /// Gets the position of the relocation. + /// + public int Position { get; } + + /// + /// Gets the of the relocation. + /// + public Symbol Symbol { get; } + + /// + /// Initializes a new instance of the struct with the specified position and + /// . + /// + /// Position of relocation + /// Symbol of relocation + public RelocEntry(int position, Symbol symbol) + { + Position = position; + Symbol = symbol; + } + + /// + public override string ToString() + { + return $"({nameof(Position)} = {Position}, {nameof(Symbol)} = {Symbol})"; + } + } +} \ No newline at end of file diff --git a/ARMeilleure/CodeGen/Linking/RelocInfo.cs b/ARMeilleure/CodeGen/Linking/RelocInfo.cs new file mode 100644 index 0000000000..922b8bfeb2 --- /dev/null +++ b/ARMeilleure/CodeGen/Linking/RelocInfo.cs @@ -0,0 +1,32 @@ +using System; + +namespace ARMeilleure.CodeGen.Linking +{ + /// + /// Represents relocation information about a . + /// + readonly struct RelocInfo + { + /// + /// Gets an empty . + /// + public static RelocInfo Empty { get; } = new RelocInfo(null); + + private readonly RelocEntry[] _entries; + + /// + /// Gets the set of . + /// + public ReadOnlySpan Entries => _entries ?? Array.Empty(); + + /// + /// Initializes a new instance of the struct with the specified set of + /// . + /// + /// Set of to use + public RelocInfo(RelocEntry[] entries) + { + _entries = entries ?? Array.Empty(); + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/Symbol.cs b/ARMeilleure/CodeGen/Linking/Symbol.cs similarity index 97% rename from ARMeilleure/Translation/PTC/Symbol.cs rename to ARMeilleure/CodeGen/Linking/Symbol.cs index f9d67742bc..fa47ee23b9 100644 --- a/ARMeilleure/Translation/PTC/Symbol.cs +++ b/ARMeilleure/CodeGen/Linking/Symbol.cs @@ -1,11 +1,11 @@ using System; -namespace ARMeilleure.Translation.PTC +namespace ARMeilleure.CodeGen.Linking { /// /// Represents a symbol. /// - struct Symbol + readonly struct Symbol { private readonly ulong _value; diff --git a/ARMeilleure/Translation/PTC/SymbolType.cs b/ARMeilleure/CodeGen/Linking/SymbolType.cs similarity index 67% rename from ARMeilleure/Translation/PTC/SymbolType.cs rename to ARMeilleure/CodeGen/Linking/SymbolType.cs index cd7b6c1c6a..b05b696927 100644 --- a/ARMeilleure/Translation/PTC/SymbolType.cs +++ b/ARMeilleure/CodeGen/Linking/SymbolType.cs @@ -1,4 +1,4 @@ -namespace ARMeilleure.Translation.PTC +namespace ARMeilleure.CodeGen.Linking { /// /// Types of . @@ -11,17 +11,17 @@ None, /// - /// Refers to an entry in . + /// Refers to an entry in . /// DelegateTable, /// - /// Refers to an entry in . + /// Refers to an entry in . /// FunctionTable, /// - /// Refers to a special symbol which is handled by . + /// Refers to a special symbol which is handled by . /// Special } diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs index 044f604726..9560875662 100644 --- a/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/ARMeilleure/CodeGen/X86/Assembler.cs @@ -1,6 +1,7 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.IntermediateRepresentation; -using ARMeilleure.Translation.PTC; using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; @@ -61,12 +62,12 @@ namespace ARMeilleure.CodeGen.X86 } } - private static InstructionInfo[] _instTable; + private readonly static InstructionInfo[] _instTable; - private Stream _stream; + private readonly Stream _stream; - private PtcInfo _ptcInfo; - private bool _ptcDisabled; + public List Relocs { get; } + public bool HasRelocs => Relocs != null; static Assembler() { @@ -294,12 +295,10 @@ namespace ARMeilleure.CodeGen.X86 _instTable[(int)inst] = info; } - public Assembler(Stream stream, PtcInfo ptcInfo = null) + public Assembler(Stream stream, bool relocatable) { _stream = stream; - - _ptcInfo = ptcInfo; - _ptcDisabled = ptcInfo == null; + Relocs = relocatable ? new List() : null; } public void Add(Operand dest, Operand source, OperandType type) @@ -498,7 +497,7 @@ namespace ARMeilleure.CodeGen.X86 public void Jcc(X86Condition condition, long offset) { - if (_ptcDisabled && ConstFitsOnS8(offset)) + if (!HasRelocs && ConstFitsOnS8(offset)) { WriteByte((byte)(0x70 | (int)condition)); @@ -519,7 +518,7 @@ namespace ARMeilleure.CodeGen.X86 public void Jmp(long offset) { - if (_ptcDisabled && ConstFitsOnS8(offset)) + if (!HasRelocs && ConstFitsOnS8(offset)) { WriteByte(0xeb); @@ -980,9 +979,9 @@ namespace ARMeilleure.CodeGen.X86 WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111))); - if (_ptcInfo != default && source.Relocatable) + if (HasRelocs && source.Relocatable) { - _ptcInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, source.Symbol)); + Relocs.Add(new RelocEntry((int)_stream.Position, source.Symbol)); } WriteUInt64(imm); @@ -1396,9 +1395,9 @@ namespace ARMeilleure.CodeGen.X86 return ConstFitsOnS32(value); } - public static int GetJccLength(long offset, bool ptcDisabled = true) + public static int GetJccLength(long offset, bool relocatable = false) { - if (ptcDisabled && ConstFitsOnS8(offset < 0 ? offset - 2 : offset)) + if (!relocatable && ConstFitsOnS8(offset < 0 ? offset - 2 : offset)) { return 2; } @@ -1412,9 +1411,9 @@ namespace ARMeilleure.CodeGen.X86 } } - public static int GetJmpLength(long offset, bool ptcDisabled = true) + public static int GetJmpLength(long offset, bool relocatable = false) { - if (ptcDisabled && ConstFitsOnS8(offset < 0 ? offset - 2 : offset)) + if (!relocatable && ConstFitsOnS8(offset < 0 ? offset - 2 : offset)) { return 2; } diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index fa726f2f86..7e96dd85a7 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -1,7 +1,7 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.Common; using ARMeilleure.IntermediateRepresentation; -using ARMeilleure.Translation.PTC; using System; using System.Collections.Generic; using System.Diagnostics; @@ -13,10 +13,8 @@ namespace ARMeilleure.CodeGen.X86 { private const int ReservedBytesForJump = 1; - private Stream _stream; - - private PtcInfo _ptcInfo; - private bool _ptcDisabled; + private readonly Stream _stream; + private readonly bool _relocatable; public int StreamOffset => (int)_stream.Length; @@ -27,22 +25,17 @@ namespace ARMeilleure.CodeGen.X86 public BasicBlock CurrBlock { get; private set; } public int CallArgsRegionSize { get; } - public int XmmSaveRegionSize { get; } + public int XmmSaveRegionSize { get; } - private long[] _blockOffsets; + private readonly long[] _blockOffsets; private struct Jump { public bool IsConditional { get; } - public X86Condition Condition { get; } - public BasicBlock Target { get; } - public long JumpPosition { get; } - public long RelativeOffset { get; set; } - public int InstSize { get; set; } public Jump(BasicBlock target, long jumpPosition, int instSize = 0) @@ -70,33 +63,26 @@ namespace ARMeilleure.CodeGen.X86 } } - private List _jumps; + private readonly List _jumps; private X86Condition _jNearCondition; - private long _jNearPosition; - private int _jNearLength; + private int _jNearLength; - public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount, PtcInfo ptcInfo = null) + public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable) { _stream = stream; - - AllocResult = allocResult; - - Assembler = new Assembler(stream, ptcInfo); - - CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize); - XmmSaveRegionSize = xmmSaveRegionSize; - + _relocatable = relocatable; _blockOffsets = new long[blocksCount]; - _jumps = new List(); - _ptcInfo = ptcInfo; - _ptcDisabled = ptcInfo == null; + AllocResult = allocResult; + Assembler = new Assembler(stream, relocatable); + CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize); + XmmSaveRegionSize = xmmSaveRegionSize; } - private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize) + private static int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize) { // We need to add 8 bytes to the total size, as the call to this // function already pushed 8 bytes (the return address). @@ -144,7 +130,7 @@ namespace ARMeilleure.CodeGen.X86 public void JumpTo(BasicBlock target) { - if (_ptcDisabled) + if (!_relocatable) { _jumps.Add(new Jump(target, _stream.Position)); @@ -160,7 +146,7 @@ namespace ARMeilleure.CodeGen.X86 public void JumpTo(X86Condition condition, BasicBlock target) { - if (_ptcDisabled) + if (!_relocatable) { _jumps.Add(new Jump(condition, target, _stream.Position)); @@ -178,7 +164,7 @@ namespace ARMeilleure.CodeGen.X86 { _jNearCondition = condition; _jNearPosition = _stream.Position; - _jNearLength = Assembler.GetJccLength(0, _ptcDisabled); + _jNearLength = Assembler.GetJccLength(0, _relocatable); _stream.Seek(_jNearLength, SeekOrigin.Current); } @@ -191,7 +177,7 @@ namespace ARMeilleure.CodeGen.X86 long offset = currentPosition - (_jNearPosition + _jNearLength); - Debug.Assert(_jNearLength == Assembler.GetJccLength(offset, _ptcDisabled), "Relative offset doesn't fit on near jump."); + Debug.Assert(_jNearLength == Assembler.GetJccLength(offset, _relocatable), "Relative offset doesn't fit on near jump."); Assembler.Jcc(_jNearCondition, offset); @@ -206,7 +192,7 @@ namespace ARMeilleure.CodeGen.X86 } } - public byte[] GetCode() + public (byte[], RelocInfo) GetCode() { // Write jump relative offsets. bool modified; @@ -223,7 +209,7 @@ namespace ARMeilleure.CodeGen.X86 long offset = jumpTarget - jump.JumpPosition; - if (_ptcDisabled) + if (!_relocatable) { if (offset < 0) { @@ -300,7 +286,7 @@ namespace ARMeilleure.CodeGen.X86 using (MemoryStream codeStream = new MemoryStream()) { - Assembler assembler = new Assembler(codeStream, _ptcInfo); + Assembler assembler = new Assembler(codeStream, _relocatable); for (int index = 0; index < _jumps.Count; index++) { @@ -309,7 +295,7 @@ namespace ARMeilleure.CodeGen.X86 Span buffer = new byte[jump.JumpPosition - _stream.Position]; _stream.Read(buffer); - _stream.Seek(_ptcDisabled ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current); + _stream.Seek(!_relocatable ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current); codeStream.Write(buffer); @@ -325,7 +311,12 @@ namespace ARMeilleure.CodeGen.X86 _stream.CopyTo(codeStream); - return codeStream.ToArray(); + var code = codeStream.ToArray(); + var relocInfo = Assembler.HasRelocs + ? new RelocInfo(Assembler.Relocs.ToArray()) + : RelocInfo.Empty; + + return (code, relocInfo); } } } diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 5818eb2eeb..924c113c4f 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -1,3 +1,4 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Optimizations; using ARMeilleure.CodeGen.RegisterAllocators; using ARMeilleure.CodeGen.Unwinding; @@ -5,7 +6,6 @@ using ARMeilleure.Common; using ARMeilleure.Diagnostics; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.Translation; -using ARMeilleure.Translation.PTC; using System; using System.Collections.Generic; using System.Diagnostics; @@ -91,7 +91,7 @@ namespace ARMeilleure.CodeGen.X86 _instTable[(int)inst] = func; } - public static CompiledFunction Generate(CompilerContext cctx, PtcInfo ptcInfo = null) + public static CompiledFunction Generate(CompilerContext cctx) { ControlFlowGraph cfg = cctx.Cfg; @@ -149,53 +149,47 @@ namespace ARMeilleure.CodeGen.X86 Logger.StartPass(PassName.CodeGeneration); - using (MemoryStream stream = new MemoryStream()) + bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0; + + using MemoryStream stream = new(); + + CodeGenContext context = new(stream, allocResult, maxCallArgs, cfg.Blocks.Count, relocatable); + + UnwindInfo unwindInfo = WritePrologue(context); + + for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) { - CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count, ptcInfo); + context.EnterBlock(block); - UnwindInfo unwindInfo = WritePrologue(context); - - ptcInfo?.WriteUnwindInfo(unwindInfo); - - for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) + for (Operation node = block.Operations.First; node != default; node = node.ListNext) { - context.EnterBlock(block); - - for (Operation node = block.Operations.First; node != default; node = node.ListNext) - { - GenerateOperation(context, node); - } - - if (block.SuccessorsCount == 0) - { - // The only blocks which can have 0 successors are exit blocks. - Operation last = block.Operations.Last; - - Debug.Assert(last.Instruction == Instruction.Tailcall || - last.Instruction == Instruction.Return); - } - else - { - BasicBlock succ = block.GetSuccessor(0); - - if (succ != block.ListNext) - { - context.JumpTo(succ); - } - } + GenerateOperation(context, node); } - byte[] code = context.GetCode(); - - if (ptcInfo != null) + if (block.SuccessorsCount == 0) { - ptcInfo.Code = code; + // The only blocks which can have 0 successors are exit blocks. + Operation last = block.Operations.Last; + + Debug.Assert(last.Instruction == Instruction.Tailcall || + last.Instruction == Instruction.Return); } + else + { + BasicBlock succ = block.GetSuccessor(0); - Logger.EndPass(PassName.CodeGeneration); - - return new CompiledFunction(code, unwindInfo); + if (succ != block.ListNext) + { + context.JumpTo(succ); + } + } } + + (byte[] code, RelocInfo relocInfo) = context.GetCode(); + + Logger.EndPass(PassName.CodeGeneration); + + return new CompiledFunction(code, unwindInfo, relocInfo); } private static void GenerateOperation(CodeGenContext context, Operation operation) diff --git a/ARMeilleure/Instructions/InstEmitFlowHelper.cs b/ARMeilleure/Instructions/InstEmitFlowHelper.cs index 2d73745316..8ce704b102 100644 --- a/ARMeilleure/Instructions/InstEmitFlowHelper.cs +++ b/ARMeilleure/Instructions/InstEmitFlowHelper.cs @@ -1,8 +1,8 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.Decoders; using ARMeilleure.IntermediateRepresentation; using ARMeilleure.State; using ARMeilleure.Translation; -using ARMeilleure.Translation.Cache; using ARMeilleure.Translation.PTC; using static ARMeilleure.Instructions.InstEmitHelper; diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs index 2e0b649c05..ff3354f2fd 100644 --- a/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -1,5 +1,5 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.Common; -using ARMeilleure.Translation.PTC; using System; using System.Collections.Generic; using System.Diagnostics; diff --git a/ARMeilleure/Signal/NativeSignalHandler.cs b/ARMeilleure/Signal/NativeSignalHandler.cs index 18d19b82fb..2716896994 100644 --- a/ARMeilleure/Signal/NativeSignalHandler.cs +++ b/ARMeilleure/Signal/NativeSignalHandler.cs @@ -261,7 +261,7 @@ namespace ARMeilleure.Signal OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 }; - return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq); + return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map(); } private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr) @@ -315,7 +315,7 @@ namespace ARMeilleure.Signal OperandType[] argTypes = new OperandType[] { OperandType.I64 }; - return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq); + return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map(); } } } diff --git a/ARMeilleure/Translation/ArmEmitterContext.cs b/ARMeilleure/Translation/ArmEmitterContext.cs index 563775ee98..6d02728ca4 100644 --- a/ARMeilleure/Translation/ArmEmitterContext.cs +++ b/ARMeilleure/Translation/ArmEmitterContext.cs @@ -1,3 +1,4 @@ +using ARMeilleure.CodeGen.Linking; using ARMeilleure.Common; using ARMeilleure.Decoders; using ARMeilleure.Diagnostics; diff --git a/ARMeilleure/Translation/Compiler.cs b/ARMeilleure/Translation/Compiler.cs index 812144a13c..9e4cdb243f 100644 --- a/ARMeilleure/Translation/Compiler.cs +++ b/ARMeilleure/Translation/Compiler.cs @@ -2,35 +2,16 @@ using ARMeilleure.CodeGen; using ARMeilleure.CodeGen.X86; using ARMeilleure.Diagnostics; using ARMeilleure.IntermediateRepresentation; -using ARMeilleure.Translation.Cache; -using ARMeilleure.Translation.PTC; -using System; -using System.Runtime.InteropServices; namespace ARMeilleure.Translation { static class Compiler { - public static T Compile( - ControlFlowGraph cfg, - OperandType[] argTypes, - OperandType retType, - CompilerOptions options, - PtcInfo ptcInfo = null) - { - CompiledFunction func = Compile(cfg, argTypes, retType, options, ptcInfo); - - IntPtr codePtr = JitCache.Map(func); - - return Marshal.GetDelegateForFunctionPointer(codePtr); - } - public static CompiledFunction Compile( ControlFlowGraph cfg, OperandType[] argTypes, OperandType retType, - CompilerOptions options, - PtcInfo ptcInfo = null) + CompilerOptions options) { Logger.StartPass(PassName.Dominance); @@ -57,7 +38,7 @@ namespace ARMeilleure.Translation CompilerContext cctx = new(cfg, argTypes, retType, options); - return CodeGenerator.Generate(cctx, ptcInfo); + return CodeGenerator.Generate(cctx); } } } \ No newline at end of file diff --git a/ARMeilleure/Translation/CompilerOptions.cs b/ARMeilleure/Translation/CompilerOptions.cs index 53998ec6f3..0a07ed4ab9 100644 --- a/ARMeilleure/Translation/CompilerOptions.cs +++ b/ARMeilleure/Translation/CompilerOptions.cs @@ -5,10 +5,11 @@ namespace ARMeilleure.Translation [Flags] enum CompilerOptions { - None = 0, - SsaForm = 1 << 0, - Optimize = 1 << 1, - Lsra = 1 << 2, + None = 0, + SsaForm = 1 << 0, + Optimize = 1 << 1, + Lsra = 1 << 2, + Relocatable = 1 << 3, MediumCq = SsaForm | Optimize, HighCq = SsaForm | Optimize | Lsra diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs index 8d4f971bdb..ad2871d079 100644 --- a/ARMeilleure/Translation/PTC/Ptc.cs +++ b/ARMeilleure/Translation/PTC/Ptc.cs @@ -1,9 +1,9 @@ using ARMeilleure.CodeGen; +using ARMeilleure.CodeGen.Linking; using ARMeilleure.CodeGen.Unwinding; using ARMeilleure.CodeGen.X86; using ARMeilleure.Common; using ARMeilleure.Memory; -using ARMeilleure.Translation.Cache; using Ryujinx.Common; using Ryujinx.Common.Configuration; using Ryujinx.Common.Logging; @@ -727,15 +727,10 @@ namespace ARMeilleure.Translation.PTC UnwindInfo unwindInfo, bool highCq) { - CompiledFunction cFunc = new CompiledFunction(code, unwindInfo); + var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty); + var gFunc = cFunc.Map(); - IntPtr codePtr = JitCache.Map(cFunc); - - GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer(codePtr); - - TranslatedFunction tFunc = new TranslatedFunction(gFunc, callCounter, guestSize, highCq); - - return tFunc; + return new TranslatedFunction(gFunc, callCounter, guestSize, highCq); } private static void UpdateInfo(InfoEntry infoEntry) @@ -889,10 +884,14 @@ namespace ARMeilleure.Translation.PTC return XXHash128.ComputeHash(memory.GetSpan(address, checked((int)(guestSize)))); } - internal static void WriteInfoCodeRelocUnwindInfo(ulong address, ulong guestSize, Hash128 hash, bool highCq, PtcInfo ptcInfo) + internal static void WriteCompiledFunction(ulong address, ulong guestSize, Hash128 hash, bool highCq, CompiledFunction compiledFunc) { lock (_lock) { + byte[] code = compiledFunc.Code; + RelocInfo relocInfo = compiledFunc.RelocInfo; + UnwindInfo unwindInfo = compiledFunc.UnwindInfo; + InfoEntry infoEntry = new InfoEntry(); infoEntry.Address = address; @@ -900,18 +899,37 @@ namespace ARMeilleure.Translation.PTC infoEntry.Hash = hash; infoEntry.HighCq = highCq; infoEntry.Stubbed = false; - infoEntry.CodeLength = ptcInfo.Code.Length; - infoEntry.RelocEntriesCount = ptcInfo.RelocEntriesCount; + infoEntry.CodeLength = code.Length; + infoEntry.RelocEntriesCount = relocInfo.Entries.Length; SerializeStructure(_infosStream, infoEntry); - WriteCode(ptcInfo.Code.AsSpan()); + WriteCode(code.AsSpan()); // WriteReloc. - ptcInfo.RelocStream.WriteTo(_relocsStream); + using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true); + + foreach (RelocEntry entry in relocInfo.Entries) + { + relocInfoWriter.Write(entry.Position); + relocInfoWriter.Write((byte)entry.Symbol.Type); + relocInfoWriter.Write(entry.Symbol.Value); + } // WriteUnwindInfo. - ptcInfo.UnwindInfoStream.WriteTo(_unwindInfosStream); + using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true); + + unwindInfoWriter.Write(unwindInfo.PushEntries.Length); + + foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries) + { + unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp); + unwindInfoWriter.Write(unwindPushEntry.PrologOffset); + unwindInfoWriter.Write(unwindPushEntry.RegIndex); + unwindInfoWriter.Write(unwindPushEntry.StackOffsetOrAllocSize); + } + + unwindInfoWriter.Write(unwindInfo.PrologSize); } } diff --git a/ARMeilleure/Translation/PTC/PtcInfo.cs b/ARMeilleure/Translation/PTC/PtcInfo.cs deleted file mode 100644 index b28b2dc1f5..0000000000 --- a/ARMeilleure/Translation/PTC/PtcInfo.cs +++ /dev/null @@ -1,63 +0,0 @@ -using ARMeilleure.CodeGen.Unwinding; -using System; -using System.IO; - -namespace ARMeilleure.Translation.PTC -{ - class PtcInfo : IDisposable - { - private readonly BinaryWriter _relocWriter; - private readonly BinaryWriter _unwindInfoWriter; - - public byte[] Code { get; set; } - - public MemoryStream RelocStream { get; } - public MemoryStream UnwindInfoStream { get; } - - public int RelocEntriesCount { get; private set; } - - public PtcInfo() - { - RelocStream = new MemoryStream(); - UnwindInfoStream = new MemoryStream(); - - _relocWriter = new BinaryWriter(RelocStream, EncodingCache.UTF8NoBOM, true); - _unwindInfoWriter = new BinaryWriter(UnwindInfoStream, EncodingCache.UTF8NoBOM, true); - - RelocEntriesCount = 0; - } - - public void WriteRelocEntry(RelocEntry relocEntry) - { - _relocWriter.Write((int)relocEntry.Position); - _relocWriter.Write((byte)relocEntry.Symbol.Type); - _relocWriter.Write((ulong)relocEntry.Symbol.Value); - - RelocEntriesCount++; - } - - public void WriteUnwindInfo(UnwindInfo unwindInfo) - { - _unwindInfoWriter.Write((int)unwindInfo.PushEntries.Length); - - foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries) - { - _unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp); - _unwindInfoWriter.Write((int)unwindPushEntry.PrologOffset); - _unwindInfoWriter.Write((int)unwindPushEntry.RegIndex); - _unwindInfoWriter.Write((int)unwindPushEntry.StackOffsetOrAllocSize); - } - - _unwindInfoWriter.Write((int)unwindInfo.PrologSize); - } - - public void Dispose() - { - _relocWriter.Dispose(); - _unwindInfoWriter.Dispose(); - - RelocStream.Dispose(); - UnwindInfoStream.Dispose(); - } - } -} \ No newline at end of file diff --git a/ARMeilleure/Translation/PTC/RelocEntry.cs b/ARMeilleure/Translation/PTC/RelocEntry.cs deleted file mode 100644 index 545612d019..0000000000 --- a/ARMeilleure/Translation/PTC/RelocEntry.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace ARMeilleure.Translation.PTC -{ - struct RelocEntry - { - public const int Stride = 13; // Bytes. - - public int Position; - public Symbol Symbol; - - public RelocEntry(int position, Symbol symbol) - { - Position = position; - Symbol = symbol; - } - - public override string ToString() - { - return $"({nameof(Position)} = {Position}, {nameof(Symbol)} = {Symbol})"; - } - } -} \ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 03ed4c5eb1..9974fb2d83 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -1,3 +1,4 @@ +using ARMeilleure.CodeGen; using ARMeilleure.Common; using ARMeilleure.Decoders; using ARMeilleure.Diagnostics; @@ -279,32 +280,30 @@ namespace ARMeilleure.Translation Logger.EndPass(PassName.RegisterUsage); - OperandType[] argTypes = new OperandType[] { OperandType.I64 }; + var retType = OperandType.I64; + var argTypes = new OperandType[] { OperandType.I64 }; - CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; + var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None; - GuestFunction func; - - if (!context.HasPtc) + if (context.HasPtc) { - func = Compiler.Compile(cfg, argTypes, OperandType.I64, options); + options |= CompilerOptions.Relocatable; } - else + + CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options); + + if (context.HasPtc) { - using PtcInfo ptcInfo = new PtcInfo(); - - func = Compiler.Compile(cfg, argTypes, OperandType.I64, options, ptcInfo); - Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize); - Ptc.WriteInfoCodeRelocUnwindInfo(address, funcSize, hash, highCq, ptcInfo); + Ptc.WriteCompiledFunction(address, funcSize, hash, highCq, compiledFunc); } - var result = new TranslatedFunction(func, counter, funcSize, highCq); + GuestFunction func = compiledFunc.Map(); Allocators.ResetAll(); - return result; + return new TranslatedFunction(func, counter, funcSize, highCq); } private struct Range diff --git a/ARMeilleure/Translation/TranslatorStubs.cs b/ARMeilleure/Translation/TranslatorStubs.cs index 48fa3a9478..4ad6c2f233 100644 --- a/ARMeilleure/Translation/TranslatorStubs.cs +++ b/ARMeilleure/Translation/TranslatorStubs.cs @@ -178,7 +178,7 @@ namespace ARMeilleure.Translation var retType = OperandType.I64; var argTypes = new[] { OperandType.I64 }; - var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq); + var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map(); return Marshal.GetFunctionPointerForDelegate(func); } @@ -204,7 +204,7 @@ namespace ARMeilleure.Translation var retType = OperandType.I64; var argTypes = new[] { OperandType.I64 }; - var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq); + var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map(); return Marshal.GetFunctionPointerForDelegate(func); } @@ -242,7 +242,7 @@ namespace ARMeilleure.Translation var retType = OperandType.None; var argTypes = new[] { OperandType.I64, OperandType.I64 }; - return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq); + return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map(); } } }