Refactor PtcInfo
(#2625)
* Refactor `PtcInfo` This change reduces the coupling of `PtcInfo` by moving relocation tracking to the backend. `RelocEntry`s remains as `RelocEntry`s through out the pipeline until it actually needs to be written to the PTC streams. Keeping this representation makes inspecting and manipulating relocations after compilations less painful. This is something I needed to do to patch relocations to 0 to diff dumps. Contributes to #1125. * Turn `Symbol` & `RelocInfo` into readonly structs * Add documentation to `CompiledFunction` * Remove `Compiler.Compile<T>` Remove `Compiler.Compile<T>` and replace it by `Map<T>` of the `CompiledFunction` returned.
This commit is contained in:
parent
ac4ec1a015
commit
a9343c9364
@ -1,17 +1,56 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
|
using ARMeilleure.Translation.Cache;
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen
|
namespace ARMeilleure.CodeGen
|
||||||
{
|
{
|
||||||
struct CompiledFunction
|
/// <summary>
|
||||||
|
/// Represents a compiled function.
|
||||||
|
/// </summary>
|
||||||
|
readonly struct CompiledFunction
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the machine code of the <see cref="CompiledFunction"/>.
|
||||||
|
/// </summary>
|
||||||
public byte[] Code { get; }
|
public byte[] Code { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Unwinding.UnwindInfo"/> of the <see cref="CompiledFunction"/>.
|
||||||
|
/// </summary>
|
||||||
public UnwindInfo UnwindInfo { get; }
|
public UnwindInfo UnwindInfo { get; }
|
||||||
|
|
||||||
public CompiledFunction(byte[] code, UnwindInfo unwindInfo)
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Linking.RelocInfo"/> of the <see cref="CompiledFunction"/>.
|
||||||
|
/// </summary>
|
||||||
|
public RelocInfo RelocInfo { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="CompiledFunction"/> struct with the specified machine code,
|
||||||
|
/// unwind info and relocation info.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="code">Machine code</param>
|
||||||
|
/// <param name="unwindInfo">Unwind info</param>
|
||||||
|
/// <param name="relocInfo">Relocation info</param>
|
||||||
|
internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo)
|
||||||
{
|
{
|
||||||
Code = code;
|
Code = code;
|
||||||
UnwindInfo = unwindInfo;
|
UnwindInfo = unwindInfo;
|
||||||
|
RelocInfo = relocInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the <see cref="CompiledFunction"/> onto the <see cref="JitCache"/> and returns a delegate of type
|
||||||
|
/// <typeparamref name="T"/> pointing to the mapped function.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of delegate</typeparam>
|
||||||
|
/// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
|
||||||
|
public T Map<T>()
|
||||||
|
{
|
||||||
|
IntPtr codePtr = JitCache.Map(this);
|
||||||
|
|
||||||
|
return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
38
ARMeilleure/CodeGen/Linking/RelocEntry.cs
Normal file
38
ARMeilleure/CodeGen/Linking/RelocEntry.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a relocation.
|
||||||
|
/// </summary>
|
||||||
|
readonly struct RelocEntry
|
||||||
|
{
|
||||||
|
public const int Stride = 13; // Bytes.
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the position of the relocation.
|
||||||
|
/// </summary>
|
||||||
|
public int Position { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Symbol"/> of the relocation.
|
||||||
|
/// </summary>
|
||||||
|
public Symbol Symbol { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RelocEntry"/> struct with the specified position and
|
||||||
|
/// <see cref="Symbol"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of relocation</param>
|
||||||
|
/// <param name="symbol">Symbol of relocation</param>
|
||||||
|
public RelocEntry(int position, Symbol symbol)
|
||||||
|
{
|
||||||
|
Position = position;
|
||||||
|
Symbol = symbol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"({nameof(Position)} = {Position}, {nameof(Symbol)} = {Symbol})";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
32
ARMeilleure/CodeGen/Linking/RelocInfo.cs
Normal file
32
ARMeilleure/CodeGen/Linking/RelocInfo.cs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents relocation information about a <see cref="CompiledFunction"/>.
|
||||||
|
/// </summary>
|
||||||
|
readonly struct RelocInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an empty <see cref="RelocInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static RelocInfo Empty { get; } = new RelocInfo(null);
|
||||||
|
|
||||||
|
private readonly RelocEntry[] _entries;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the set of <see cref="RelocEntry"/>.
|
||||||
|
/// </summary>
|
||||||
|
public ReadOnlySpan<RelocEntry> Entries => _entries ?? Array.Empty<RelocEntry>();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RelocInfo"/> struct with the specified set of
|
||||||
|
/// <see cref="RelocEntry"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="entries">Set of <see cref="RelocInfo"/> to use</param>
|
||||||
|
public RelocInfo(RelocEntry[] entries)
|
||||||
|
{
|
||||||
|
_entries = entries ?? Array.Empty<RelocEntry>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Translation.PTC
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Represents a symbol.
|
/// Represents a symbol.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct Symbol
|
readonly struct Symbol
|
||||||
{
|
{
|
||||||
private readonly ulong _value;
|
private readonly ulong _value;
|
||||||
|
|
@ -1,4 +1,4 @@
|
|||||||
namespace ARMeilleure.Translation.PTC
|
namespace ARMeilleure.CodeGen.Linking
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Types of <see cref="Symbol"/>.
|
/// Types of <see cref="Symbol"/>.
|
||||||
@ -11,17 +11,17 @@
|
|||||||
None,
|
None,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refers to an entry in <see cref="Delegates"/>.
|
/// Refers to an entry in <see cref="Translation.Delegates"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DelegateTable,
|
DelegateTable,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refers to an entry in <see cref="Translator.FunctionTable"/>.
|
/// Refers to an entry in <see cref="Translation.Translator.FunctionTable"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FunctionTable,
|
FunctionTable,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Refers to a special symbol which is handled by <see cref="Ptc.PatchCode"/>.
|
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Special
|
Special
|
||||||
}
|
}
|
@ -1,6 +1,7 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation.PTC;
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
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;
|
public List<RelocEntry> Relocs { get; }
|
||||||
private bool _ptcDisabled;
|
public bool HasRelocs => Relocs != null;
|
||||||
|
|
||||||
static Assembler()
|
static Assembler()
|
||||||
{
|
{
|
||||||
@ -294,12 +295,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
_instTable[(int)inst] = info;
|
_instTable[(int)inst] = info;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Assembler(Stream stream, PtcInfo ptcInfo = null)
|
public Assembler(Stream stream, bool relocatable)
|
||||||
{
|
{
|
||||||
_stream = stream;
|
_stream = stream;
|
||||||
|
Relocs = relocatable ? new List<RelocEntry>() : null;
|
||||||
_ptcInfo = ptcInfo;
|
|
||||||
_ptcDisabled = ptcInfo == null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Add(Operand dest, Operand source, OperandType type)
|
public void Add(Operand dest, Operand source, OperandType type)
|
||||||
@ -498,7 +497,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public void Jcc(X86Condition condition, long offset)
|
public void Jcc(X86Condition condition, long offset)
|
||||||
{
|
{
|
||||||
if (_ptcDisabled && ConstFitsOnS8(offset))
|
if (!HasRelocs && ConstFitsOnS8(offset))
|
||||||
{
|
{
|
||||||
WriteByte((byte)(0x70 | (int)condition));
|
WriteByte((byte)(0x70 | (int)condition));
|
||||||
|
|
||||||
@ -519,7 +518,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public void Jmp(long offset)
|
public void Jmp(long offset)
|
||||||
{
|
{
|
||||||
if (_ptcDisabled && ConstFitsOnS8(offset))
|
if (!HasRelocs && ConstFitsOnS8(offset))
|
||||||
{
|
{
|
||||||
WriteByte(0xeb);
|
WriteByte(0xeb);
|
||||||
|
|
||||||
@ -980,9 +979,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
|
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);
|
WriteUInt64(imm);
|
||||||
@ -1396,9 +1395,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
return ConstFitsOnS32(value);
|
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;
|
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;
|
return 2;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation.PTC;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -13,10 +13,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
private const int ReservedBytesForJump = 1;
|
private const int ReservedBytesForJump = 1;
|
||||||
|
|
||||||
private Stream _stream;
|
private readonly Stream _stream;
|
||||||
|
private readonly bool _relocatable;
|
||||||
private PtcInfo _ptcInfo;
|
|
||||||
private bool _ptcDisabled;
|
|
||||||
|
|
||||||
public int StreamOffset => (int)_stream.Length;
|
public int StreamOffset => (int)_stream.Length;
|
||||||
|
|
||||||
@ -27,22 +25,17 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
public BasicBlock CurrBlock { get; private set; }
|
public BasicBlock CurrBlock { get; private set; }
|
||||||
|
|
||||||
public int CallArgsRegionSize { get; }
|
public int CallArgsRegionSize { get; }
|
||||||
public int XmmSaveRegionSize { get; }
|
public int XmmSaveRegionSize { get; }
|
||||||
|
|
||||||
private long[] _blockOffsets;
|
private readonly long[] _blockOffsets;
|
||||||
|
|
||||||
private struct Jump
|
private struct Jump
|
||||||
{
|
{
|
||||||
public bool IsConditional { get; }
|
public bool IsConditional { get; }
|
||||||
|
|
||||||
public X86Condition Condition { get; }
|
public X86Condition Condition { get; }
|
||||||
|
|
||||||
public BasicBlock Target { get; }
|
public BasicBlock Target { get; }
|
||||||
|
|
||||||
public long JumpPosition { get; }
|
public long JumpPosition { get; }
|
||||||
|
|
||||||
public long RelativeOffset { get; set; }
|
public long RelativeOffset { get; set; }
|
||||||
|
|
||||||
public int InstSize { get; set; }
|
public int InstSize { get; set; }
|
||||||
|
|
||||||
public Jump(BasicBlock target, long jumpPosition, int instSize = 0)
|
public Jump(BasicBlock target, long jumpPosition, int instSize = 0)
|
||||||
@ -70,33 +63,26 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Jump> _jumps;
|
private readonly List<Jump> _jumps;
|
||||||
|
|
||||||
private X86Condition _jNearCondition;
|
private X86Condition _jNearCondition;
|
||||||
|
|
||||||
private long _jNearPosition;
|
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;
|
_stream = stream;
|
||||||
|
_relocatable = relocatable;
|
||||||
AllocResult = allocResult;
|
|
||||||
|
|
||||||
Assembler = new Assembler(stream, ptcInfo);
|
|
||||||
|
|
||||||
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
|
|
||||||
XmmSaveRegionSize = xmmSaveRegionSize;
|
|
||||||
|
|
||||||
_blockOffsets = new long[blocksCount];
|
_blockOffsets = new long[blocksCount];
|
||||||
|
|
||||||
_jumps = new List<Jump>();
|
_jumps = new List<Jump>();
|
||||||
|
|
||||||
_ptcInfo = ptcInfo;
|
AllocResult = allocResult;
|
||||||
_ptcDisabled = ptcInfo == null;
|
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
|
// We need to add 8 bytes to the total size, as the call to this
|
||||||
// function already pushed 8 bytes (the return address).
|
// function already pushed 8 bytes (the return address).
|
||||||
@ -144,7 +130,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public void JumpTo(BasicBlock target)
|
public void JumpTo(BasicBlock target)
|
||||||
{
|
{
|
||||||
if (_ptcDisabled)
|
if (!_relocatable)
|
||||||
{
|
{
|
||||||
_jumps.Add(new Jump(target, _stream.Position));
|
_jumps.Add(new Jump(target, _stream.Position));
|
||||||
|
|
||||||
@ -160,7 +146,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
public void JumpTo(X86Condition condition, BasicBlock target)
|
public void JumpTo(X86Condition condition, BasicBlock target)
|
||||||
{
|
{
|
||||||
if (_ptcDisabled)
|
if (!_relocatable)
|
||||||
{
|
{
|
||||||
_jumps.Add(new Jump(condition, target, _stream.Position));
|
_jumps.Add(new Jump(condition, target, _stream.Position));
|
||||||
|
|
||||||
@ -178,7 +164,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
{
|
{
|
||||||
_jNearCondition = condition;
|
_jNearCondition = condition;
|
||||||
_jNearPosition = _stream.Position;
|
_jNearPosition = _stream.Position;
|
||||||
_jNearLength = Assembler.GetJccLength(0, _ptcDisabled);
|
_jNearLength = Assembler.GetJccLength(0, _relocatable);
|
||||||
|
|
||||||
_stream.Seek(_jNearLength, SeekOrigin.Current);
|
_stream.Seek(_jNearLength, SeekOrigin.Current);
|
||||||
}
|
}
|
||||||
@ -191,7 +177,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
long offset = currentPosition - (_jNearPosition + _jNearLength);
|
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);
|
Assembler.Jcc(_jNearCondition, offset);
|
||||||
|
|
||||||
@ -206,7 +192,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] GetCode()
|
public (byte[], RelocInfo) GetCode()
|
||||||
{
|
{
|
||||||
// Write jump relative offsets.
|
// Write jump relative offsets.
|
||||||
bool modified;
|
bool modified;
|
||||||
@ -223,7 +209,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
long offset = jumpTarget - jump.JumpPosition;
|
long offset = jumpTarget - jump.JumpPosition;
|
||||||
|
|
||||||
if (_ptcDisabled)
|
if (!_relocatable)
|
||||||
{
|
{
|
||||||
if (offset < 0)
|
if (offset < 0)
|
||||||
{
|
{
|
||||||
@ -300,7 +286,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
using (MemoryStream codeStream = new MemoryStream())
|
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++)
|
for (int index = 0; index < _jumps.Count; index++)
|
||||||
{
|
{
|
||||||
@ -309,7 +295,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
Span<byte> buffer = new byte[jump.JumpPosition - _stream.Position];
|
||||||
|
|
||||||
_stream.Read(buffer);
|
_stream.Read(buffer);
|
||||||
_stream.Seek(_ptcDisabled ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current);
|
_stream.Seek(!_relocatable ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current);
|
||||||
|
|
||||||
codeStream.Write(buffer);
|
codeStream.Write(buffer);
|
||||||
|
|
||||||
@ -325,7 +311,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
_stream.CopyTo(codeStream);
|
_stream.CopyTo(codeStream);
|
||||||
|
|
||||||
return codeStream.ToArray();
|
var code = codeStream.ToArray();
|
||||||
|
var relocInfo = Assembler.HasRelocs
|
||||||
|
? new RelocInfo(Assembler.Relocs.ToArray())
|
||||||
|
: RelocInfo.Empty;
|
||||||
|
|
||||||
|
return (code, relocInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.Optimizations;
|
using ARMeilleure.CodeGen.Optimizations;
|
||||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
@ -5,7 +6,6 @@ using ARMeilleure.Common;
|
|||||||
using ARMeilleure.Diagnostics;
|
using ARMeilleure.Diagnostics;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using ARMeilleure.Translation.PTC;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
@ -91,7 +91,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
_instTable[(int)inst] = func;
|
_instTable[(int)inst] = func;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static CompiledFunction Generate(CompilerContext cctx, PtcInfo ptcInfo = null)
|
public static CompiledFunction Generate(CompilerContext cctx)
|
||||||
{
|
{
|
||||||
ControlFlowGraph cfg = cctx.Cfg;
|
ControlFlowGraph cfg = cctx.Cfg;
|
||||||
|
|
||||||
@ -149,53 +149,47 @@ namespace ARMeilleure.CodeGen.X86
|
|||||||
|
|
||||||
Logger.StartPass(PassName.CodeGeneration);
|
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);
|
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||||
|
|
||||||
ptcInfo?.WriteUnwindInfo(unwindInfo);
|
|
||||||
|
|
||||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
|
||||||
{
|
{
|
||||||
context.EnterBlock(block);
|
GenerateOperation(context, node);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] code = context.GetCode();
|
if (block.SuccessorsCount == 0)
|
||||||
|
|
||||||
if (ptcInfo != null)
|
|
||||||
{
|
{
|
||||||
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);
|
if (succ != block.ListNext)
|
||||||
|
{
|
||||||
return new CompiledFunction(code, unwindInfo);
|
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)
|
private static void GenerateOperation(CodeGenContext context, Operation operation)
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
using ARMeilleure.State;
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using ARMeilleure.Translation.Cache;
|
|
||||||
using ARMeilleure.Translation.PTC;
|
using ARMeilleure.Translation.PTC;
|
||||||
|
|
||||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Translation.PTC;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
@ -261,7 +261,7 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
|
OperandType[] argTypes = new OperandType[] { OperandType.I32, OperandType.I64, OperandType.I64 };
|
||||||
|
|
||||||
return Compiler.Compile<UnixExceptionHandler>(cfg, argTypes, OperandType.None, CompilerOptions.HighCq);
|
return Compiler.Compile(cfg, argTypes, OperandType.None, CompilerOptions.HighCq).Map<UnixExceptionHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
|
private static VectoredExceptionHandler GenerateWindowsSignalHandler(IntPtr signalStructPtr)
|
||||||
@ -315,7 +315,7 @@ namespace ARMeilleure.Signal
|
|||||||
|
|
||||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||||
|
|
||||||
return Compiler.Compile<VectoredExceptionHandler>(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq);
|
return Compiler.Compile(cfg, argTypes, OperandType.I32, CompilerOptions.HighCq).Map<VectoredExceptionHandler>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.Diagnostics;
|
using ARMeilleure.Diagnostics;
|
||||||
|
@ -2,35 +2,16 @@ using ARMeilleure.CodeGen;
|
|||||||
using ARMeilleure.CodeGen.X86;
|
using ARMeilleure.CodeGen.X86;
|
||||||
using ARMeilleure.Diagnostics;
|
using ARMeilleure.Diagnostics;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Translation.Cache;
|
|
||||||
using ARMeilleure.Translation.PTC;
|
|
||||||
using System;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Translation
|
namespace ARMeilleure.Translation
|
||||||
{
|
{
|
||||||
static class Compiler
|
static class Compiler
|
||||||
{
|
{
|
||||||
public static T Compile<T>(
|
|
||||||
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<T>(codePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static CompiledFunction Compile(
|
public static CompiledFunction Compile(
|
||||||
ControlFlowGraph cfg,
|
ControlFlowGraph cfg,
|
||||||
OperandType[] argTypes,
|
OperandType[] argTypes,
|
||||||
OperandType retType,
|
OperandType retType,
|
||||||
CompilerOptions options,
|
CompilerOptions options)
|
||||||
PtcInfo ptcInfo = null)
|
|
||||||
{
|
{
|
||||||
Logger.StartPass(PassName.Dominance);
|
Logger.StartPass(PassName.Dominance);
|
||||||
|
|
||||||
@ -57,7 +38,7 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
CompilerContext cctx = new(cfg, argTypes, retType, options);
|
CompilerContext cctx = new(cfg, argTypes, retType, options);
|
||||||
|
|
||||||
return CodeGenerator.Generate(cctx, ptcInfo);
|
return CodeGenerator.Generate(cctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,10 +5,11 @@ namespace ARMeilleure.Translation
|
|||||||
[Flags]
|
[Flags]
|
||||||
enum CompilerOptions
|
enum CompilerOptions
|
||||||
{
|
{
|
||||||
None = 0,
|
None = 0,
|
||||||
SsaForm = 1 << 0,
|
SsaForm = 1 << 0,
|
||||||
Optimize = 1 << 1,
|
Optimize = 1 << 1,
|
||||||
Lsra = 1 << 2,
|
Lsra = 1 << 2,
|
||||||
|
Relocatable = 1 << 3,
|
||||||
|
|
||||||
MediumCq = SsaForm | Optimize,
|
MediumCq = SsaForm | Optimize,
|
||||||
HighCq = SsaForm | Optimize | Lsra
|
HighCq = SsaForm | Optimize | Lsra
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using ARMeilleure.CodeGen;
|
using ARMeilleure.CodeGen;
|
||||||
|
using ARMeilleure.CodeGen.Linking;
|
||||||
using ARMeilleure.CodeGen.Unwinding;
|
using ARMeilleure.CodeGen.Unwinding;
|
||||||
using ARMeilleure.CodeGen.X86;
|
using ARMeilleure.CodeGen.X86;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.Translation.Cache;
|
|
||||||
using Ryujinx.Common;
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Common.Configuration;
|
using Ryujinx.Common.Configuration;
|
||||||
using Ryujinx.Common.Logging;
|
using Ryujinx.Common.Logging;
|
||||||
@ -727,15 +727,10 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
UnwindInfo unwindInfo,
|
UnwindInfo unwindInfo,
|
||||||
bool highCq)
|
bool highCq)
|
||||||
{
|
{
|
||||||
CompiledFunction cFunc = new CompiledFunction(code, unwindInfo);
|
var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
|
||||||
|
var gFunc = cFunc.Map<GuestFunction>();
|
||||||
|
|
||||||
IntPtr codePtr = JitCache.Map(cFunc);
|
return new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
|
||||||
|
|
||||||
GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer<GuestFunction>(codePtr);
|
|
||||||
|
|
||||||
TranslatedFunction tFunc = new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
|
|
||||||
|
|
||||||
return tFunc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UpdateInfo(InfoEntry infoEntry)
|
private static void UpdateInfo(InfoEntry infoEntry)
|
||||||
@ -889,10 +884,14 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
return XXHash128.ComputeHash(memory.GetSpan(address, checked((int)(guestSize))));
|
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)
|
lock (_lock)
|
||||||
{
|
{
|
||||||
|
byte[] code = compiledFunc.Code;
|
||||||
|
RelocInfo relocInfo = compiledFunc.RelocInfo;
|
||||||
|
UnwindInfo unwindInfo = compiledFunc.UnwindInfo;
|
||||||
|
|
||||||
InfoEntry infoEntry = new InfoEntry();
|
InfoEntry infoEntry = new InfoEntry();
|
||||||
|
|
||||||
infoEntry.Address = address;
|
infoEntry.Address = address;
|
||||||
@ -900,18 +899,37 @@ namespace ARMeilleure.Translation.PTC
|
|||||||
infoEntry.Hash = hash;
|
infoEntry.Hash = hash;
|
||||||
infoEntry.HighCq = highCq;
|
infoEntry.HighCq = highCq;
|
||||||
infoEntry.Stubbed = false;
|
infoEntry.Stubbed = false;
|
||||||
infoEntry.CodeLength = ptcInfo.Code.Length;
|
infoEntry.CodeLength = code.Length;
|
||||||
infoEntry.RelocEntriesCount = ptcInfo.RelocEntriesCount;
|
infoEntry.RelocEntriesCount = relocInfo.Entries.Length;
|
||||||
|
|
||||||
SerializeStructure(_infosStream, infoEntry);
|
SerializeStructure(_infosStream, infoEntry);
|
||||||
|
|
||||||
WriteCode(ptcInfo.Code.AsSpan());
|
WriteCode(code.AsSpan());
|
||||||
|
|
||||||
// WriteReloc.
|
// 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.
|
// 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -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})";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +1,4 @@
|
|||||||
|
using ARMeilleure.CodeGen;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.Decoders;
|
using ARMeilleure.Decoders;
|
||||||
using ARMeilleure.Diagnostics;
|
using ARMeilleure.Diagnostics;
|
||||||
@ -279,32 +280,30 @@ namespace ARMeilleure.Translation
|
|||||||
|
|
||||||
Logger.EndPass(PassName.RegisterUsage);
|
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<GuestFunction>(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<GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo);
|
|
||||||
|
|
||||||
Hash128 hash = Ptc.ComputeHash(Memory, address, funcSize);
|
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<GuestFunction>();
|
||||||
|
|
||||||
Allocators.ResetAll();
|
Allocators.ResetAll();
|
||||||
|
|
||||||
return result;
|
return new TranslatedFunction(func, counter, funcSize, highCq);
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct Range
|
private struct Range
|
||||||
|
@ -178,7 +178,7 @@ namespace ARMeilleure.Translation
|
|||||||
var retType = OperandType.I64;
|
var retType = OperandType.I64;
|
||||||
var argTypes = new[] { OperandType.I64 };
|
var argTypes = new[] { OperandType.I64 };
|
||||||
|
|
||||||
var func = Compiler.Compile<GuestFunction>(cfg, argTypes, retType, CompilerOptions.HighCq);
|
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
|
||||||
|
|
||||||
return Marshal.GetFunctionPointerForDelegate(func);
|
return Marshal.GetFunctionPointerForDelegate(func);
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ namespace ARMeilleure.Translation
|
|||||||
var retType = OperandType.I64;
|
var retType = OperandType.I64;
|
||||||
var argTypes = new[] { OperandType.I64 };
|
var argTypes = new[] { OperandType.I64 };
|
||||||
|
|
||||||
var func = Compiler.Compile<GuestFunction>(cfg, argTypes, retType, CompilerOptions.HighCq);
|
var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
|
||||||
|
|
||||||
return Marshal.GetFunctionPointerForDelegate(func);
|
return Marshal.GetFunctionPointerForDelegate(func);
|
||||||
}
|
}
|
||||||
@ -242,7 +242,7 @@ namespace ARMeilleure.Translation
|
|||||||
var retType = OperandType.None;
|
var retType = OperandType.None;
|
||||||
var argTypes = new[] { OperandType.I64, OperandType.I64 };
|
var argTypes = new[] { OperandType.I64, OperandType.I64 };
|
||||||
|
|
||||||
return Compiler.Compile<DispatcherFunction>(cfg, argTypes, retType, CompilerOptions.HighCq);
|
return Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<DispatcherFunction>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user