mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-07-29 20:47:11 +02:00
[ARMeilleure] Address dotnet-format issues (#5357)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address or silence dotnet format CA2208 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Silence CA1806 and CA1834 issues * Address dotnet format CA1401 warnings * Fix new dotnet-format issues after rebase * Address review comments * Address dotnet format CA2208 warnings properly * Fix formatting for switch expressions * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for OpCodeTable.cs * Enable formatting for a few cases again * Format if-blocks correctly * Enable formatting for a few more cases again * Fix inline comment alignment * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Remove a few unused parameters * Adjust namespaces * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Remove unnecessary formatting exclusion * Add unsafe dotnet format changes * Change visibility of JitSupportDarwin to internal
This commit is contained in:
parent
2de78a2d55
commit
ff53dcf560
300 changed files with 3515 additions and 3120 deletions
|
@ -55,7 +55,7 @@ namespace ARMeilleure.Translation
|
|||
public Aarch32Mode Mode { get; }
|
||||
|
||||
private int _ifThenBlockStateIndex = 0;
|
||||
private Condition[] _ifThenBlockState = { };
|
||||
private Condition[] _ifThenBlockState = Array.Empty<Condition>();
|
||||
public bool IsInIfThenBlock => _ifThenBlockStateIndex < _ifThenBlockState.Length;
|
||||
public Condition CurrentIfThenBlockCond => _ifThenBlockState[_ifThenBlockStateIndex];
|
||||
|
||||
|
@ -96,7 +96,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
OperandType returnType = GetOperandType(info.ReturnType);
|
||||
|
||||
Symbol symbol = new Symbol(SymbolType.DelegateTable, (ulong)index);
|
||||
Symbol symbol = new(SymbolType.DelegateTable, (ulong)index);
|
||||
|
||||
Symbols.Add((ulong)funcPtr.ToInt64(), info.Name);
|
||||
|
||||
|
@ -219,6 +219,7 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
switch (condition)
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
case Condition.Eq: return ICompareEqual (n, m);
|
||||
case Condition.Ne: return ICompareNotEqual (n, m);
|
||||
case Condition.GeUn: return ICompareGreaterOrEqualUI(n, m);
|
||||
|
@ -229,6 +230,7 @@ namespace ARMeilleure.Translation
|
|||
case Condition.Lt: return ICompareLess (n, m);
|
||||
case Condition.Gt: return ICompareGreater (n, m);
|
||||
case Condition.Le: return ICompareLessOrEqual (n, m);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
}
|
||||
else if (cmpName == InstName.Adds && _optOpLastCompare is IOpCodeAluImm op)
|
||||
|
@ -253,12 +255,14 @@ namespace ARMeilleure.Translation
|
|||
|
||||
switch (condition)
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
case Condition.Eq: return ICompareEqual (n, m);
|
||||
case Condition.Ne: return ICompareNotEqual (n, m);
|
||||
case Condition.Ge: return ICompareGreaterOrEqual(n, m);
|
||||
case Condition.Lt: return ICompareLess (n, m);
|
||||
case Condition.Gt: return ICompareGreater (n, m);
|
||||
case Condition.Le: return ICompareLessOrEqual (n, m);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -279,4 +283,4 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,14 +7,14 @@ namespace ARMeilleure.Translation.Cache
|
|||
readonly struct CacheEntry : IComparable<CacheEntry>
|
||||
{
|
||||
public int Offset { get; }
|
||||
public int Size { get; }
|
||||
public int Size { get; }
|
||||
|
||||
public UnwindInfo UnwindInfo { get; }
|
||||
|
||||
public CacheEntry(int offset, int size, UnwindInfo unwindInfo)
|
||||
{
|
||||
Offset = offset;
|
||||
Size = size;
|
||||
Offset = offset;
|
||||
Size = size;
|
||||
UnwindInfo = unwindInfo;
|
||||
}
|
||||
|
||||
|
@ -23,4 +23,4 @@ namespace ARMeilleure.Translation.Cache
|
|||
return Offset.CompareTo(other.Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
}
|
||||
|
||||
private readonly List<MemoryBlock> _blocks = new List<MemoryBlock>();
|
||||
private readonly List<MemoryBlock> _blocks = new();
|
||||
|
||||
public CacheMemoryAllocator(int capacity)
|
||||
{
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
static partial class JitCache
|
||||
{
|
||||
private static readonly int PageSize = (int)MemoryBlock.GetPageSize();
|
||||
private static readonly int PageMask = PageSize - 1;
|
||||
private static readonly int _pageSize = (int)MemoryBlock.GetPageSize();
|
||||
private static readonly int _pageMask = _pageSize - 1;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
private const int CacheSize = 2047 * 1024 * 1024;
|
||||
|
@ -24,7 +24,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
private static CacheMemoryAllocator _cacheAllocator;
|
||||
|
||||
private static readonly List<CacheEntry> _cacheEntries = new List<CacheEntry>();
|
||||
private static readonly List<CacheEntry> _cacheEntries = new();
|
||||
|
||||
private static readonly object _lock = new();
|
||||
private static bool _initialized;
|
||||
|
@ -35,11 +35,17 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
public static void Initialize(IJitMemoryAllocator allocator)
|
||||
{
|
||||
if (_initialized) return;
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_initialized) return;
|
||||
if (_initialized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_jitRegion = new ReservedRegion(allocator, CacheSize);
|
||||
|
||||
|
@ -52,7 +58,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
if (OperatingSystem.IsWindows())
|
||||
{
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(PageSize));
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize, _jitRegion.Pointer + Allocate(_pageSize));
|
||||
}
|
||||
|
||||
_initialized = true;
|
||||
|
@ -75,7 +81,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
unsafe
|
||||
{
|
||||
fixed (byte *codePtr = code)
|
||||
fixed (byte* codePtr = code)
|
||||
{
|
||||
JitSupportDarwin.Copy(funcPtr, (IntPtr)codePtr, (ulong)code.Length);
|
||||
}
|
||||
|
@ -124,8 +130,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
int endOffs = offset + size;
|
||||
|
||||
int regionStart = offset & ~PageMask;
|
||||
int regionEnd = (endOffs + PageMask) & ~PageMask;
|
||||
int regionStart = offset & ~_pageMask;
|
||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||
|
||||
_jitRegion.Block.MapAsRwx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
@ -134,8 +140,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
int endOffs = offset + size;
|
||||
|
||||
int regionStart = offset & ~PageMask;
|
||||
int regionEnd = (endOffs + PageMask) & ~PageMask;
|
||||
int regionStart = offset & ~_pageMask;
|
||||
int regionEnd = (endOffs + _pageMask) & ~_pageMask;
|
||||
|
||||
_jitRegion.Block.MapAsRx((ulong)regionStart, (ulong)(regionEnd - regionStart));
|
||||
}
|
||||
|
@ -163,7 +169,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
private static void Add(int offset, int size, UnwindInfo unwindInfo)
|
||||
{
|
||||
CacheEntry entry = new CacheEntry(offset, size, unwindInfo);
|
||||
CacheEntry entry = new(offset, size, unwindInfo);
|
||||
|
||||
int index = _cacheEntries.BinarySearch(entry);
|
||||
|
||||
|
@ -212,4 +218,4 @@ namespace ARMeilleure.Translation.Cache
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace ARMeilleure.Translation.Cache
|
|||
{
|
||||
class JitCacheInvalidation
|
||||
{
|
||||
private static int[] _invalidationCode = new int[]
|
||||
private static readonly int[] _invalidationCode = new int[]
|
||||
{
|
||||
unchecked((int)0xd53b0022), // mrs x2, ctr_el0
|
||||
unchecked((int)0xd3504c44), // ubfx x4, x2, #16, #4
|
||||
|
@ -40,8 +40,8 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
private delegate void InvalidateCache(ulong start, ulong end);
|
||||
|
||||
private InvalidateCache _invalidateCache;
|
||||
private ReservedRegion _invalidateCacheCodeRegion;
|
||||
private readonly InvalidateCache _invalidateCache;
|
||||
private readonly ReservedRegion _invalidateCacheCodeRegion;
|
||||
|
||||
private readonly bool _needsInvalidation;
|
||||
|
||||
|
@ -76,4 +76,4 @@ namespace ARMeilleure.Translation.Cache
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,15 +29,15 @@ namespace ARMeilleure.Translation.Cache
|
|||
|
||||
private enum UnwindOp
|
||||
{
|
||||
PushNonvol = 0,
|
||||
AllocLarge = 1,
|
||||
AllocSmall = 2,
|
||||
SetFpreg = 3,
|
||||
SaveNonvol = 4,
|
||||
PushNonvol = 0,
|
||||
AllocLarge = 1,
|
||||
AllocSmall = 2,
|
||||
SetFpreg = 3,
|
||||
SaveNonvol = 4,
|
||||
SaveNonvolFar = 5,
|
||||
SaveXmm128 = 8,
|
||||
SaveXmm128 = 8,
|
||||
SaveXmm128Far = 9,
|
||||
PushMachframe = 10
|
||||
PushMachframe = 10,
|
||||
}
|
||||
|
||||
private unsafe delegate RuntimeFunction* GetRuntimeFunctionCallback(ulong controlPc, IntPtr context);
|
||||
|
@ -111,72 +111,73 @@ namespace ARMeilleure.Translation.Cache
|
|||
switch (entry.PseudoOp)
|
||||
{
|
||||
case UnwindPseudoOp.SaveXmm128:
|
||||
{
|
||||
int stackOffset = entry.StackOffsetOrAllocSize;
|
||||
|
||||
Debug.Assert(stackOffset % 16 == 0);
|
||||
|
||||
if (stackOffset <= 0xFFFF0)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128, entry.PrologOffset, entry.RegIndex);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
|
||||
}
|
||||
int stackOffset = entry.StackOffsetOrAllocSize;
|
||||
|
||||
break;
|
||||
}
|
||||
Debug.Assert(stackOffset % 16 == 0);
|
||||
|
||||
if (stackOffset <= 0xFFFF0)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128, entry.PrologOffset, entry.RegIndex);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset / 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.SaveXmm128Far, entry.PrologOffset, entry.RegIndex);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(stackOffset >> 16);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UnwindPseudoOp.AllocStack:
|
||||
{
|
||||
int allocSize = entry.StackOffsetOrAllocSize;
|
||||
|
||||
Debug.Assert(allocSize % 8 == 0);
|
||||
|
||||
if (allocSize <= 128)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
|
||||
}
|
||||
else if (allocSize <= 0x7FFF8)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
|
||||
}
|
||||
int allocSize = entry.StackOffsetOrAllocSize;
|
||||
|
||||
break;
|
||||
}
|
||||
Debug.Assert(allocSize % 8 == 0);
|
||||
|
||||
if (allocSize <= 128)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocSmall, entry.PrologOffset, (allocSize / 8) - 1);
|
||||
}
|
||||
else if (allocSize <= 0x7FFF8)
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize / 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.AllocLarge, entry.PrologOffset, 1);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 0);
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = (ushort)(allocSize >> 16);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case UnwindPseudoOp.PushReg:
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.PushNonvol, entry.PrologOffset, entry.RegIndex);
|
||||
{
|
||||
_unwindInfo->UnwindCodes[codeIndex++] = PackUnwindOp(UnwindOp.PushNonvol, entry.PrologOffset, entry.RegIndex);
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: throw new NotImplementedException($"({nameof(entry.PseudoOp)} = {entry.PseudoOp})");
|
||||
default:
|
||||
throw new NotImplementedException($"({nameof(entry.PseudoOp)} = {entry.PseudoOp})");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Assert(codeIndex <= MaxUnwindCodesArraySize);
|
||||
|
||||
_unwindInfo->VersionAndFlags = 1; // Flags: The function has no handler.
|
||||
_unwindInfo->SizeOfProlog = (byte)unwindInfo.PrologSize;
|
||||
_unwindInfo->VersionAndFlags = 1; // Flags: The function has no handler.
|
||||
_unwindInfo->SizeOfProlog = (byte)unwindInfo.PrologSize;
|
||||
_unwindInfo->CountOfUnwindCodes = (byte)codeIndex;
|
||||
_unwindInfo->FrameRegister = 0;
|
||||
_unwindInfo->FrameRegister = 0;
|
||||
|
||||
_runtimeFunction->BeginAddress = (uint)funcEntry.Offset;
|
||||
_runtimeFunction->EndAddress = (uint)(funcEntry.Offset + funcEntry.Size);
|
||||
_runtimeFunction->UnwindData = (uint)_sizeOfRuntimeFunction;
|
||||
_runtimeFunction->EndAddress = (uint)(funcEntry.Offset + funcEntry.Size);
|
||||
_runtimeFunction->UnwindData = (uint)_sizeOfRuntimeFunction;
|
||||
|
||||
return _runtimeFunction;
|
||||
}
|
||||
|
@ -186,4 +187,4 @@ namespace ARMeilleure.Translation.Cache
|
|||
return (ushort)(prologOffset | ((int)op << 8) | (opInfo << 12));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
public static CompiledFunction Compile(
|
||||
ControlFlowGraph cfg,
|
||||
OperandType[] argTypes,
|
||||
OperandType retType,
|
||||
CompilerOptions options,
|
||||
Architecture target)
|
||||
OperandType[] argTypes,
|
||||
OperandType retType,
|
||||
CompilerOptions options,
|
||||
Architecture target)
|
||||
{
|
||||
CompilerContext cctx = new(cfg, argTypes, retType, options);
|
||||
|
||||
|
@ -65,4 +65,4 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,21 +6,21 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
public ControlFlowGraph Cfg { get; }
|
||||
|
||||
public OperandType[] FuncArgTypes { get; }
|
||||
public OperandType FuncReturnType { get; }
|
||||
public OperandType[] FuncArgTypes { get; }
|
||||
public OperandType FuncReturnType { get; }
|
||||
|
||||
public CompilerOptions Options { get; }
|
||||
|
||||
public CompilerContext(
|
||||
ControlFlowGraph cfg,
|
||||
OperandType[] funcArgTypes,
|
||||
OperandType funcReturnType,
|
||||
CompilerOptions options)
|
||||
OperandType[] funcArgTypes,
|
||||
OperandType funcReturnType,
|
||||
CompilerOptions options)
|
||||
{
|
||||
Cfg = cfg;
|
||||
FuncArgTypes = funcArgTypes;
|
||||
Cfg = cfg;
|
||||
FuncArgTypes = funcArgTypes;
|
||||
FuncReturnType = funcReturnType;
|
||||
Options = options;
|
||||
Options = options;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,13 +5,13 @@ 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
|
||||
HighCq = SsaForm | Optimize | Lsra,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -130,7 +130,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public BasicBlock SplitEdge(BasicBlock predecessor, BasicBlock successor)
|
||||
{
|
||||
BasicBlock splitBlock = new BasicBlock(Blocks.Count);
|
||||
BasicBlock splitBlock = new(Blocks.Count);
|
||||
|
||||
for (int i = 0; i < predecessor.SuccessorsCount; i++)
|
||||
{
|
||||
|
@ -152,4 +152,4 @@ namespace ARMeilleure.Translation
|
|||
return splitBlock;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,9 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
class DelegateInfo
|
||||
{
|
||||
#pragma warning disable IDE0052 // Remove unread private member
|
||||
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected.
|
||||
#pragma warning restore IDE0052
|
||||
|
||||
public IntPtr FuncPtr { get; }
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
cfg.Entry.ImmediateDominator = cfg.Entry;
|
||||
|
||||
Debug.Assert(cfg.Entry == cfg.PostOrderBlocks[cfg.PostOrderBlocks.Length - 1]);
|
||||
Debug.Assert(cfg.Entry == cfg.PostOrderBlocks[^1]);
|
||||
|
||||
bool modified;
|
||||
|
||||
|
@ -92,4 +92,4 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,9 +108,9 @@ namespace ARMeilleure.Translation
|
|||
|
||||
protected static OperandType GetOperandType(Type type)
|
||||
{
|
||||
if (type == typeof(bool) || type == typeof(byte) ||
|
||||
type == typeof(char) || type == typeof(short) ||
|
||||
type == typeof(int) || type == typeof(sbyte) ||
|
||||
if (type == typeof(bool) || type == typeof(byte) ||
|
||||
type == typeof(char) || type == typeof(short) ||
|
||||
type == typeof(int) || type == typeof(sbyte) ||
|
||||
type == typeof(ushort) || type == typeof(uint))
|
||||
{
|
||||
return OperandType.I32;
|
||||
|
@ -635,7 +635,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private void NewNextBlock()
|
||||
{
|
||||
BasicBlock block = new BasicBlock(_irBlocks.Count);
|
||||
BasicBlock block = new(_irBlocks.Count);
|
||||
|
||||
_irBlocks.AddLast(block);
|
||||
|
||||
|
|
|
@ -3,4 +3,4 @@ using System;
|
|||
namespace ARMeilleure.Translation
|
||||
{
|
||||
delegate ulong GuestFunction(IntPtr nativeContextPtr);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,15 +6,15 @@ namespace ARMeilleure.Translation
|
|||
/// <summary>
|
||||
/// An Augmented Interval Tree based off of the "TreeDictionary"'s Red-Black Tree. Allows fast overlap checking of ranges.
|
||||
/// </summary>
|
||||
/// <typeparam name="K">Key</typeparam>
|
||||
/// <typeparam name="V">Value</typeparam>
|
||||
class IntervalTree<K, V> where K : IComparable<K>
|
||||
/// <typeparam name="TK">Key</typeparam>
|
||||
/// <typeparam name="TV">Value</typeparam>
|
||||
class IntervalTree<TK, TV> where TK : IComparable<TK>
|
||||
{
|
||||
private const int ArrayGrowthSize = 32;
|
||||
|
||||
private const bool Black = true;
|
||||
private const bool Red = false;
|
||||
private IntervalTreeNode<K, V> _root = null;
|
||||
private IntervalTreeNode<TK, TV> _root = null;
|
||||
private int _count = 0;
|
||||
|
||||
public int Count => _count;
|
||||
|
@ -27,9 +27,9 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="key">Key of the node value to get</param>
|
||||
/// <param name="value">Value with the given <paramref name="key"/></param>
|
||||
/// <returns>True if the key is on the dictionary, false otherwise</returns>
|
||||
public bool TryGet(K key, out V value)
|
||||
public bool TryGet(TK key, out TV value)
|
||||
{
|
||||
IntervalTreeNode<K, V> node = GetNode(key);
|
||||
IntervalTreeNode<TK, TV> node = GetNode(key);
|
||||
|
||||
if (node == null)
|
||||
{
|
||||
|
@ -49,7 +49,7 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="overlaps">Overlaps array to place results in</param>
|
||||
/// <param name="overlapCount">Index to start writing results into the array. Defaults to 0</param>
|
||||
/// <returns>Number of intervals found</returns>
|
||||
public int Get(K start, K end, ref K[] overlaps, int overlapCount = 0)
|
||||
public int Get(TK start, TK end, ref TK[] overlaps, int overlapCount = 0)
|
||||
{
|
||||
GetKeys(_root, start, end, ref overlaps, ref overlapCount);
|
||||
|
||||
|
@ -65,11 +65,11 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="updateFactoryCallback">Optional factory used to create a new value if <paramref name="start"/> is already on the tree</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="value"/> is null</exception>
|
||||
/// <returns>True if the value was added, false if the start key was already in the dictionary</returns>
|
||||
public bool AddOrUpdate(K start, K end, V value, Func<K, V, V> updateFactoryCallback)
|
||||
public bool AddOrUpdate(TK start, TK end, TV value, Func<TK, TV, TV> updateFactoryCallback)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
return BSTInsert(start, end, value, updateFactoryCallback, out IntervalTreeNode<K, V> node);
|
||||
return BSTInsert(start, end, value, updateFactoryCallback, out _);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -80,11 +80,11 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="value">Value to add</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="value"/> is null</exception>
|
||||
/// <returns><paramref name="value"/> if <paramref name="start"/> is not yet on the tree, or the existing value otherwise</returns>
|
||||
public V GetOrAdd(K start, K end, V value)
|
||||
public TV GetOrAdd(TK start, TK end, TV value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
BSTInsert(start, end, value, null, out IntervalTreeNode<K, V> node);
|
||||
BSTInsert(start, end, value, null, out IntervalTreeNode<TK, TV> node);
|
||||
return node.Value;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="key">Key of the node to remove</param>
|
||||
/// <returns>Number of deleted values</returns>
|
||||
public int Remove(K key)
|
||||
public int Remove(TK key)
|
||||
{
|
||||
int removed = Delete(key);
|
||||
|
||||
|
@ -106,9 +106,9 @@ namespace ARMeilleure.Translation
|
|||
/// Adds all the nodes in the dictionary into <paramref name="list"/>.
|
||||
/// </summary>
|
||||
/// <returns>A list of all values sorted by Key Order</returns>
|
||||
public List<V> AsList()
|
||||
public List<TV> AsList()
|
||||
{
|
||||
List<V> list = new List<V>();
|
||||
List<TV> list = new();
|
||||
|
||||
AddToList(_root, list);
|
||||
|
||||
|
@ -124,7 +124,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">The node to search for values within</param>
|
||||
/// <param name="list">The list to add values to</param>
|
||||
private void AddToList(IntervalTreeNode<K, V> node, List<V> list)
|
||||
private void AddToList(IntervalTreeNode<TK, TV> node, List<TV> list)
|
||||
{
|
||||
if (node == null)
|
||||
{
|
||||
|
@ -144,11 +144,11 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="key">Key of the node to get</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="key"/> is null</exception>
|
||||
/// <returns>Node reference in the tree</returns>
|
||||
private IntervalTreeNode<K, V> GetNode(K key)
|
||||
private IntervalTreeNode<TK, TV> GetNode(TK key)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(key);
|
||||
|
||||
IntervalTreeNode<K, V> node = _root;
|
||||
IntervalTreeNode<TK, TV> node = _root;
|
||||
while (node != null)
|
||||
{
|
||||
int cmp = key.CompareTo(node.Start);
|
||||
|
@ -175,7 +175,7 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="end">End of the range</param>
|
||||
/// <param name="overlaps">Overlaps array to place results in</param>
|
||||
/// <param name="overlapCount">Overlaps count to update</param>
|
||||
private void GetKeys(IntervalTreeNode<K, V> node, K start, K end, ref K[] overlaps, ref int overlapCount)
|
||||
private void GetKeys(IntervalTreeNode<TK, TV> node, TK start, TK end, ref TK[] overlaps, ref int overlapCount)
|
||||
{
|
||||
if (node == null || start.CompareTo(node.Max) >= 0)
|
||||
{
|
||||
|
@ -206,10 +206,10 @@ namespace ARMeilleure.Translation
|
|||
/// This should only be called if the max increases - not for rebalancing or removals.
|
||||
/// </summary>
|
||||
/// <param name="node">The node to start propagating from</param>
|
||||
private void PropagateIncrease(IntervalTreeNode<K, V> node)
|
||||
private static void PropagateIncrease(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
K max = node.Max;
|
||||
IntervalTreeNode<K, V> ptr = node;
|
||||
TK max = node.Max;
|
||||
IntervalTreeNode<TK, TV> ptr = node;
|
||||
|
||||
while ((ptr = ptr.Parent) != null)
|
||||
{
|
||||
|
@ -229,13 +229,13 @@ namespace ARMeilleure.Translation
|
|||
/// This fully recalculates the max value from all children when there is potential for it to decrease.
|
||||
/// </summary>
|
||||
/// <param name="node">The node to start propagating from</param>
|
||||
private void PropagateFull(IntervalTreeNode<K, V> node)
|
||||
private static void PropagateFull(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
IntervalTreeNode<K, V> ptr = node;
|
||||
IntervalTreeNode<TK, TV> ptr = node;
|
||||
|
||||
do
|
||||
{
|
||||
K max = ptr.End;
|
||||
TK max = ptr.End;
|
||||
|
||||
if (ptr.Left != null && ptr.Left.Max.CompareTo(max) > 0)
|
||||
{
|
||||
|
@ -263,10 +263,10 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="updateFactoryCallback">Optional factory used to create a new value if <paramref name="start"/> is already on the tree</param>
|
||||
/// <param name="outNode">Node that was inserted or modified</param>
|
||||
/// <returns>True if <paramref name="start"/> was not yet on the tree, false otherwise</returns>
|
||||
private bool BSTInsert(K start, K end, V value, Func<K, V, V> updateFactoryCallback, out IntervalTreeNode<K, V> outNode)
|
||||
private bool BSTInsert(TK start, TK end, TV value, Func<TK, TV, TV> updateFactoryCallback, out IntervalTreeNode<TK, TV> outNode)
|
||||
{
|
||||
IntervalTreeNode<K, V> parent = null;
|
||||
IntervalTreeNode<K, V> node = _root;
|
||||
IntervalTreeNode<TK, TV> parent = null;
|
||||
IntervalTreeNode<TK, TV> node = _root;
|
||||
|
||||
while (node != null)
|
||||
{
|
||||
|
@ -311,7 +311,7 @@ namespace ARMeilleure.Translation
|
|||
return false;
|
||||
}
|
||||
}
|
||||
IntervalTreeNode<K, V> newNode = new IntervalTreeNode<K, V>(start, end, value, parent);
|
||||
IntervalTreeNode<TK, TV> newNode = new(start, end, value, parent);
|
||||
if (newNode.Parent == null)
|
||||
{
|
||||
_root = newNode;
|
||||
|
@ -337,16 +337,16 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="key">Key to search for</param>
|
||||
/// <returns>Number of deleted values</returns>
|
||||
private int Delete(K key)
|
||||
private int Delete(TK key)
|
||||
{
|
||||
IntervalTreeNode<K, V> nodeToDelete = GetNode(key);
|
||||
IntervalTreeNode<TK, TV> nodeToDelete = GetNode(key);
|
||||
|
||||
if (nodeToDelete == null)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
IntervalTreeNode<K, V> replacementNode;
|
||||
IntervalTreeNode<TK, TV> replacementNode;
|
||||
|
||||
if (LeftOf(nodeToDelete) == null || RightOf(nodeToDelete) == null)
|
||||
{
|
||||
|
@ -357,7 +357,7 @@ namespace ARMeilleure.Translation
|
|||
replacementNode = PredecessorOf(nodeToDelete);
|
||||
}
|
||||
|
||||
IntervalTreeNode<K, V> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
IntervalTreeNode<TK, TV> tmp = LeftOf(replacementNode) ?? RightOf(replacementNode);
|
||||
|
||||
if (tmp != null)
|
||||
{
|
||||
|
@ -400,9 +400,9 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Root Node</param>
|
||||
/// <returns>Node with the maximum key in the tree of <paramref name="node"/></returns>
|
||||
private static IntervalTreeNode<K, V> Maximum(IntervalTreeNode<K, V> node)
|
||||
private static IntervalTreeNode<TK, TV> Maximum(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
IntervalTreeNode<K, V> tmp = node;
|
||||
IntervalTreeNode<TK, TV> tmp = node;
|
||||
while (tmp.Right != null)
|
||||
{
|
||||
tmp = tmp.Right;
|
||||
|
@ -416,13 +416,13 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node to find the predecessor of</param>
|
||||
/// <returns>Predecessor of <paramref name="node"/></returns>
|
||||
private static IntervalTreeNode<K, V> PredecessorOf(IntervalTreeNode<K, V> node)
|
||||
private static IntervalTreeNode<TK, TV> PredecessorOf(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
if (node.Left != null)
|
||||
{
|
||||
return Maximum(node.Left);
|
||||
}
|
||||
IntervalTreeNode<K, V> parent = node.Parent;
|
||||
IntervalTreeNode<TK, TV> parent = node.Parent;
|
||||
while (parent != null && node == parent.Left)
|
||||
{
|
||||
node = parent;
|
||||
|
@ -435,15 +435,15 @@ namespace ARMeilleure.Translation
|
|||
|
||||
#region Private Methods (RBL)
|
||||
|
||||
private void RestoreBalanceAfterRemoval(IntervalTreeNode<K, V> balanceNode)
|
||||
private void RestoreBalanceAfterRemoval(IntervalTreeNode<TK, TV> balanceNode)
|
||||
{
|
||||
IntervalTreeNode<K, V> ptr = balanceNode;
|
||||
IntervalTreeNode<TK, TV> ptr = balanceNode;
|
||||
|
||||
while (ptr != _root && ColorOf(ptr) == Black)
|
||||
{
|
||||
if (ptr == LeftOf(ParentOf(ptr)))
|
||||
{
|
||||
IntervalTreeNode<K, V> sibling = RightOf(ParentOf(ptr));
|
||||
IntervalTreeNode<TK, TV> sibling = RightOf(ParentOf(ptr));
|
||||
|
||||
if (ColorOf(sibling) == Red)
|
||||
{
|
||||
|
@ -475,7 +475,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
else
|
||||
{
|
||||
IntervalTreeNode<K, V> sibling = LeftOf(ParentOf(ptr));
|
||||
IntervalTreeNode<TK, TV> sibling = LeftOf(ParentOf(ptr));
|
||||
|
||||
if (ColorOf(sibling) == Red)
|
||||
{
|
||||
|
@ -509,14 +509,14 @@ namespace ARMeilleure.Translation
|
|||
SetColor(ptr, Black);
|
||||
}
|
||||
|
||||
private void RestoreBalanceAfterInsertion(IntervalTreeNode<K, V> balanceNode)
|
||||
private void RestoreBalanceAfterInsertion(IntervalTreeNode<TK, TV> balanceNode)
|
||||
{
|
||||
SetColor(balanceNode, Red);
|
||||
while (balanceNode != null && balanceNode != _root && ColorOf(ParentOf(balanceNode)) == Red)
|
||||
{
|
||||
if (ParentOf(balanceNode) == LeftOf(ParentOf(ParentOf(balanceNode))))
|
||||
{
|
||||
IntervalTreeNode<K, V> sibling = RightOf(ParentOf(ParentOf(balanceNode)));
|
||||
IntervalTreeNode<TK, TV> sibling = RightOf(ParentOf(ParentOf(balanceNode)));
|
||||
|
||||
if (ColorOf(sibling) == Red)
|
||||
{
|
||||
|
@ -539,7 +539,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
else
|
||||
{
|
||||
IntervalTreeNode<K, V> sibling = LeftOf(ParentOf(ParentOf(balanceNode)));
|
||||
IntervalTreeNode<TK, TV> sibling = LeftOf(ParentOf(ParentOf(balanceNode)));
|
||||
|
||||
if (ColorOf(sibling) == Red)
|
||||
{
|
||||
|
@ -564,17 +564,17 @@ namespace ARMeilleure.Translation
|
|||
SetColor(_root, Black);
|
||||
}
|
||||
|
||||
private void RotateLeft(IntervalTreeNode<K, V> node)
|
||||
private void RotateLeft(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
IntervalTreeNode<K, V> right = RightOf(node);
|
||||
IntervalTreeNode<TK, TV> right = RightOf(node);
|
||||
node.Right = LeftOf(right);
|
||||
if (node.Right != null)
|
||||
{
|
||||
node.Right.Parent = node;
|
||||
}
|
||||
IntervalTreeNode<K, V> nodeParent = ParentOf(node);
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
right.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
{
|
||||
|
@ -595,17 +595,17 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
private void RotateRight(IntervalTreeNode<K, V> node)
|
||||
private void RotateRight(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
IntervalTreeNode<K, V> left = LeftOf(node);
|
||||
IntervalTreeNode<TK, TV> left = LeftOf(node);
|
||||
node.Left = RightOf(left);
|
||||
if (node.Left != null)
|
||||
{
|
||||
node.Left.Parent = node;
|
||||
}
|
||||
IntervalTreeNode<K, V> nodeParent = ParentOf(node);
|
||||
IntervalTreeNode<TK, TV> nodeParent = ParentOf(node);
|
||||
left.Parent = nodeParent;
|
||||
if (nodeParent == null)
|
||||
{
|
||||
|
@ -637,7 +637,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node</param>
|
||||
/// <returns>The boolean color of <paramref name="node"/>, or black if null</returns>
|
||||
private static bool ColorOf(IntervalTreeNode<K, V> node)
|
||||
private static bool ColorOf(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
return node == null || node.Color;
|
||||
}
|
||||
|
@ -649,7 +649,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node to set the color of</param>
|
||||
/// <param name="color">Color (Boolean)</param>
|
||||
private static void SetColor(IntervalTreeNode<K, V> node, bool color)
|
||||
private static void SetColor(IntervalTreeNode<TK, TV> node, bool color)
|
||||
{
|
||||
if (node != null)
|
||||
{
|
||||
|
@ -662,7 +662,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node to retrieve the left child from</param>
|
||||
/// <returns>Left child of <paramref name="node"/></returns>
|
||||
private static IntervalTreeNode<K, V> LeftOf(IntervalTreeNode<K, V> node)
|
||||
private static IntervalTreeNode<TK, TV> LeftOf(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
return node?.Left;
|
||||
}
|
||||
|
@ -672,7 +672,7 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node to retrieve the right child from</param>
|
||||
/// <returns>Right child of <paramref name="node"/></returns>
|
||||
private static IntervalTreeNode<K, V> RightOf(IntervalTreeNode<K, V> node)
|
||||
private static IntervalTreeNode<TK, TV> RightOf(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
return node?.Right;
|
||||
}
|
||||
|
@ -682,14 +682,14 @@ namespace ARMeilleure.Translation
|
|||
/// </summary>
|
||||
/// <param name="node">Node to retrieve the parent from</param>
|
||||
/// <returns>Parent of <paramref name="node"/></returns>
|
||||
private static IntervalTreeNode<K, V> ParentOf(IntervalTreeNode<K, V> node)
|
||||
private static IntervalTreeNode<TK, TV> ParentOf(IntervalTreeNode<TK, TV> node)
|
||||
{
|
||||
return node?.Parent;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public bool ContainsKey(K key)
|
||||
public bool ContainsKey(TK key)
|
||||
{
|
||||
return GetNode(key) != null;
|
||||
}
|
||||
|
@ -704,36 +704,36 @@ namespace ARMeilleure.Translation
|
|||
/// <summary>
|
||||
/// Represents a node in the IntervalTree which contains start and end keys of type K, and a value of generic type V.
|
||||
/// </summary>
|
||||
/// <typeparam name="K">Key type of the node</typeparam>
|
||||
/// <typeparam name="V">Value type of the node</typeparam>
|
||||
class IntervalTreeNode<K, V>
|
||||
/// <typeparam name="TK">Key type of the node</typeparam>
|
||||
/// <typeparam name="TV">Value type of the node</typeparam>
|
||||
class IntervalTreeNode<TK, TV>
|
||||
{
|
||||
public bool Color = true;
|
||||
public IntervalTreeNode<K, V> Left = null;
|
||||
public IntervalTreeNode<K, V> Right = null;
|
||||
public IntervalTreeNode<K, V> Parent = null;
|
||||
public IntervalTreeNode<TK, TV> Left = null;
|
||||
public IntervalTreeNode<TK, TV> Right = null;
|
||||
public IntervalTreeNode<TK, TV> Parent = null;
|
||||
|
||||
/// <summary>
|
||||
/// The start of the range.
|
||||
/// </summary>
|
||||
public K Start;
|
||||
public TK Start;
|
||||
|
||||
/// <summary>
|
||||
/// The end of the range.
|
||||
/// </summary>
|
||||
public K End;
|
||||
public TK End;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum end value of this node and all its children.
|
||||
/// </summary>
|
||||
public K Max;
|
||||
public TK Max;
|
||||
|
||||
/// <summary>
|
||||
/// Value stored on this node.
|
||||
/// </summary>
|
||||
public V Value;
|
||||
public TV Value;
|
||||
|
||||
public IntervalTreeNode(K start, K end, V value, IntervalTreeNode<K, V> parent)
|
||||
public IntervalTreeNode(TK start, TK end, TV value, IntervalTreeNode<TK, TV> parent)
|
||||
{
|
||||
Start = start;
|
||||
End = end;
|
||||
|
|
|
@ -6,4 +6,4 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
public static readonly Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,4 +7,4 @@ namespace ARMeilleure.Translation.PTC
|
|||
event Action<PtcLoadingState, int, int> PtcStateChanged;
|
||||
void Continue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,13 +17,12 @@ using System.Runtime;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||
|
||||
namespace ARMeilleure.Translation.PTC
|
||||
{
|
||||
using Arm64HardwareCapabilities = ARMeilleure.CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = ARMeilleure.CodeGen.X86.HardwareCapabilities;
|
||||
using Arm64HardwareCapabilities = CodeGen.Arm64.HardwareCapabilities;
|
||||
using X86HardwareCapabilities = CodeGen.X86.HardwareCapabilities;
|
||||
|
||||
class Ptc : IPtcLoadState
|
||||
{
|
||||
|
@ -187,8 +186,8 @@ namespace ARMeilleure.Translation.PTC
|
|||
string fileNameActual = $"{CachePathActual}.cache";
|
||||
string fileNameBackup = $"{CachePathBackup}.cache";
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
|
||||
FileInfo fileInfoActual = new(fileNameActual);
|
||||
FileInfo fileInfoBackup = new(fileNameBackup);
|
||||
|
||||
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
|
||||
{
|
||||
|
@ -275,104 +274,102 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));
|
||||
|
||||
using (UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite))
|
||||
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
deflateStream.CopyTo(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream);
|
||||
|
||||
if (!innerHeader.IsHeaderValid())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (innerHeader.Magic != _innerHeaderMagic)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
|
||||
stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 infosHash = XXHash128.ComputeHash(infosBytes);
|
||||
|
||||
if (innerHeader.InfosHash != infosHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty;
|
||||
stream.Seek(innerHeader.CodesLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 codesHash = XXHash128.ComputeHash(codesBytes);
|
||||
|
||||
if (innerHeader.CodesHash != codesHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
|
||||
stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes);
|
||||
|
||||
if (innerHeader.RelocsHash != relocsHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
|
||||
stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);
|
||||
|
||||
if (innerHeader.UnwindInfosHash != unwindInfosHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
|
||||
|
||||
_infosStream.Write(infosBytes);
|
||||
stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);
|
||||
|
||||
_codesList.ReadFrom(stream);
|
||||
|
||||
_relocsStream.Write(relocsBytes);
|
||||
stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);
|
||||
|
||||
_unwindInfosStream.Write(unwindInfosBytes);
|
||||
stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
deflateStream.CopyTo(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
InnerHeader innerHeader = DeserializeStructure<InnerHeader>(stream);
|
||||
|
||||
if (!innerHeader.IsHeaderValid())
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (innerHeader.Magic != _innerHeaderMagic)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
|
||||
stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 infosHash = XXHash128.ComputeHash(infosBytes);
|
||||
|
||||
if (innerHeader.InfosHash != infosHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty;
|
||||
stream.Seek(innerHeader.CodesLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 codesHash = XXHash128.ComputeHash(codesBytes);
|
||||
|
||||
if (innerHeader.CodesHash != codesHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
|
||||
stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 relocsHash = XXHash128.ComputeHash(relocsBytes);
|
||||
|
||||
if (innerHeader.RelocsHash != relocsHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
|
||||
stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);
|
||||
|
||||
Hash128 unwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);
|
||||
|
||||
if (innerHeader.UnwindInfosHash != unwindInfosHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
|
||||
|
||||
_infosStream.Write(infosBytes);
|
||||
stream.Seek(innerHeader.InfosLength, SeekOrigin.Current);
|
||||
|
||||
_codesList.ReadFrom(stream);
|
||||
|
||||
_relocsStream.Write(relocsBytes);
|
||||
stream.Seek(innerHeader.RelocsLength, SeekOrigin.Current);
|
||||
|
||||
_unwindInfosStream.Write(unwindInfosBytes);
|
||||
stream.Seek(innerHeader.UnwindInfosLength, SeekOrigin.Current);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -390,7 +387,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
return true;
|
||||
}
|
||||
|
||||
private void InvalidateCompressedStream(FileStream compressedStream)
|
||||
private static void InvalidateCompressedStream(FileStream compressedStream)
|
||||
{
|
||||
compressedStream.SetLength(0L);
|
||||
}
|
||||
|
@ -404,7 +401,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
string fileNameActual = $"{CachePathActual}.cache";
|
||||
string fileNameBackup = $"{CachePathBackup}.cache";
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
FileInfo fileInfoActual = new(fileNameActual);
|
||||
|
||||
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
|
||||
{
|
||||
|
@ -427,32 +424,34 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
int translatedFuncsCount;
|
||||
|
||||
InnerHeader innerHeader = new InnerHeader();
|
||||
InnerHeader innerHeader = new()
|
||||
{
|
||||
Magic = _innerHeaderMagic,
|
||||
|
||||
innerHeader.Magic = _innerHeaderMagic;
|
||||
InfosLength = (int)_infosStream.Length,
|
||||
CodesLength = _codesList.Length(),
|
||||
RelocsLength = (int)_relocsStream.Length,
|
||||
UnwindInfosLength = (int)_unwindInfosStream.Length,
|
||||
};
|
||||
|
||||
innerHeader.InfosLength = (int)_infosStream.Length;
|
||||
innerHeader.CodesLength = _codesList.Length();
|
||||
innerHeader.RelocsLength = (int)_relocsStream.Length;
|
||||
innerHeader.UnwindInfosLength = (int)_unwindInfosStream.Length;
|
||||
OuterHeader outerHeader = new()
|
||||
{
|
||||
Magic = _outerHeaderMagic,
|
||||
|
||||
OuterHeader outerHeader = new OuterHeader();
|
||||
CacheFileVersion = InternalVersion,
|
||||
Endianness = GetEndianness(),
|
||||
FeatureInfo = GetFeatureInfo(),
|
||||
MemoryManagerMode = GetMemoryManagerMode(),
|
||||
OSPlatform = GetOSPlatform(),
|
||||
Architecture = (uint)RuntimeInformation.ProcessArchitecture,
|
||||
|
||||
outerHeader.Magic = _outerHeaderMagic;
|
||||
|
||||
outerHeader.CacheFileVersion = InternalVersion;
|
||||
outerHeader.Endianness = GetEndianness();
|
||||
outerHeader.FeatureInfo = GetFeatureInfo();
|
||||
outerHeader.MemoryManagerMode = GetMemoryManagerMode();
|
||||
outerHeader.OSPlatform = GetOSPlatform();
|
||||
outerHeader.Architecture = (uint)RuntimeInformation.ProcessArchitecture;
|
||||
|
||||
outerHeader.UncompressedStreamSize =
|
||||
UncompressedStreamSize =
|
||||
(long)Unsafe.SizeOf<InnerHeader>() +
|
||||
innerHeader.InfosLength +
|
||||
innerHeader.CodesLength +
|
||||
innerHeader.RelocsLength +
|
||||
innerHeader.UnwindInfosLength;
|
||||
innerHeader.UnwindInfosLength,
|
||||
};
|
||||
|
||||
outerHeader.SetHeaderHash();
|
||||
|
||||
|
@ -462,58 +461,54 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
intPtr = Marshal.AllocHGlobal(new IntPtr(outerHeader.UncompressedStreamSize));
|
||||
|
||||
using (UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite))
|
||||
using UnmanagedMemoryStream stream = new((byte*)intPtr.ToPointer(), outerHeader.UncompressedStreamSize, outerHeader.UncompressedStreamSize, FileAccess.ReadWrite);
|
||||
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
|
||||
|
||||
ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
|
||||
_infosStream.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty;
|
||||
_codesList.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
|
||||
_relocsStream.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
|
||||
_unwindInfosStream.WriteTo(stream);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
innerHeader.InfosHash = XXHash128.ComputeHash(infosBytes);
|
||||
innerHeader.CodesHash = XXHash128.ComputeHash(codesBytes);
|
||||
innerHeader.RelocsHash = XXHash128.ComputeHash(relocsBytes);
|
||||
innerHeader.UnwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);
|
||||
|
||||
innerHeader.SetHeaderHash();
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
SerializeStructure(stream, innerHeader);
|
||||
|
||||
translatedFuncsCount = GetEntriesCount();
|
||||
|
||||
ResetCarriersIfNeeded();
|
||||
|
||||
using FileStream compressedStream = new(fileName, FileMode.OpenOrCreate);
|
||||
using DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true);
|
||||
try
|
||||
{
|
||||
stream.Seek((long)Unsafe.SizeOf<InnerHeader>(), SeekOrigin.Begin);
|
||||
|
||||
ReadOnlySpan<byte> infosBytes = new(stream.PositionPointer, innerHeader.InfosLength);
|
||||
_infosStream.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> codesBytes = (int)innerHeader.CodesLength > 0 ? new(stream.PositionPointer, (int)innerHeader.CodesLength) : ReadOnlySpan<byte>.Empty;
|
||||
_codesList.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> relocsBytes = new(stream.PositionPointer, innerHeader.RelocsLength);
|
||||
_relocsStream.WriteTo(stream);
|
||||
|
||||
ReadOnlySpan<byte> unwindInfosBytes = new(stream.PositionPointer, innerHeader.UnwindInfosLength);
|
||||
_unwindInfosStream.WriteTo(stream);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
innerHeader.InfosHash = XXHash128.ComputeHash(infosBytes);
|
||||
innerHeader.CodesHash = XXHash128.ComputeHash(codesBytes);
|
||||
innerHeader.RelocsHash = XXHash128.ComputeHash(relocsBytes);
|
||||
innerHeader.UnwindInfosHash = XXHash128.ComputeHash(unwindInfosBytes);
|
||||
|
||||
innerHeader.SetHeaderHash();
|
||||
SerializeStructure(compressedStream, outerHeader);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
SerializeStructure(stream, innerHeader);
|
||||
stream.CopyTo(deflateStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
compressedStream.Position = 0L;
|
||||
}
|
||||
|
||||
translatedFuncsCount = GetEntriesCount();
|
||||
|
||||
ResetCarriersIfNeeded();
|
||||
|
||||
using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
|
||||
using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
|
||||
{
|
||||
try
|
||||
{
|
||||
SerializeStructure(compressedStream, outerHeader);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
stream.CopyTo(deflateStream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
compressedStream.Position = 0L;
|
||||
}
|
||||
|
||||
if (compressedStream.Position < compressedStream.Length)
|
||||
{
|
||||
compressedStream.SetLength(compressedStream.Position);
|
||||
}
|
||||
}
|
||||
if (compressedStream.Position < compressedStream.Length)
|
||||
{
|
||||
compressedStream.SetLength(compressedStream.Position);
|
||||
}
|
||||
}
|
||||
finally
|
||||
|
@ -647,7 +642,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
return _codesList[index];
|
||||
}
|
||||
|
||||
private RelocEntry[] GetRelocEntries(BinaryReader relocsReader, int relocEntriesCount)
|
||||
private static RelocEntry[] GetRelocEntries(BinaryReader relocsReader, int relocEntriesCount)
|
||||
{
|
||||
RelocEntry[] relocEntries = new RelocEntry[relocEntriesCount];
|
||||
|
||||
|
@ -663,7 +658,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
return relocEntries;
|
||||
}
|
||||
|
||||
private void PatchCode(Translator translator, Span<byte> code, RelocEntry[] relocEntries, out Counter<uint> callCounter)
|
||||
private static void PatchCode(Translator translator, Span<byte> code, RelocEntry[] relocEntries, out Counter<uint> callCounter)
|
||||
{
|
||||
callCounter = null;
|
||||
|
||||
|
@ -678,7 +673,10 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
if (translator.FunctionTable.IsValid(guestAddress))
|
||||
{
|
||||
unsafe { imm = (IntPtr)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress)); }
|
||||
unsafe
|
||||
{
|
||||
imm = (IntPtr)Unsafe.AsPointer(ref translator.FunctionTable.GetValue(guestAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (symbol.Type == SymbolType.DelegateTable)
|
||||
|
@ -696,12 +694,12 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
else if (symbol == CountTableSymbol)
|
||||
{
|
||||
if (callCounter == null)
|
||||
{
|
||||
callCounter = new Counter<uint>(translator.CountTable);
|
||||
}
|
||||
callCounter ??= new Counter<uint>(translator.CountTable);
|
||||
|
||||
unsafe { imm = (IntPtr)Unsafe.AsPointer(ref callCounter.Value); }
|
||||
unsafe
|
||||
{
|
||||
imm = (IntPtr)Unsafe.AsPointer(ref callCounter.Value);
|
||||
}
|
||||
}
|
||||
else if (symbol == DispatchStubSymbol)
|
||||
{
|
||||
|
@ -717,7 +715,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
|
||||
private UnwindInfo ReadUnwindInfo(BinaryReader unwindInfosReader)
|
||||
private static UnwindInfo ReadUnwindInfo(BinaryReader unwindInfosReader)
|
||||
{
|
||||
int pushEntriesLength = unwindInfosReader.ReadInt32();
|
||||
|
||||
|
@ -738,7 +736,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
return new UnwindInfo(pushEntries, prologueSize);
|
||||
}
|
||||
|
||||
private TranslatedFunction FastTranslate(
|
||||
private static TranslatedFunction FastTranslate(
|
||||
byte[] code,
|
||||
Counter<uint> callCounter,
|
||||
ulong guestSize,
|
||||
|
@ -809,13 +807,13 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
PtcStateChanged?.Invoke(PtcLoadingState.Start, _translateCount, _translateTotalCount);
|
||||
|
||||
using AutoResetEvent progressReportEvent = new AutoResetEvent(false);
|
||||
using AutoResetEvent progressReportEvent = new(false);
|
||||
|
||||
Thread progressReportThread = new Thread(ReportProgress)
|
||||
Thread progressReportThread = new(ReportProgress)
|
||||
{
|
||||
Name = "Ptc.ProgressReporter",
|
||||
Priority = ThreadPriority.Lowest,
|
||||
IsBackground = true
|
||||
IsBackground = true,
|
||||
};
|
||||
|
||||
progressReportThread.Start(progressReportEvent);
|
||||
|
@ -845,12 +843,14 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
|
||||
List<Thread> threads = new List<Thread>();
|
||||
List<Thread> threads = new();
|
||||
|
||||
for (int i = 0; i < degreeOfParallelism; i++)
|
||||
{
|
||||
Thread thread = new Thread(TranslateFuncs);
|
||||
thread.IsBackground = true;
|
||||
Thread thread = new(TranslateFuncs)
|
||||
{
|
||||
IsBackground = true,
|
||||
};
|
||||
|
||||
threads.Add(thread);
|
||||
}
|
||||
|
@ -871,8 +871,10 @@ namespace ARMeilleure.Translation.PTC
|
|||
|
||||
Logger.Info?.Print(LogClass.Ptc, $"{_translateCount} of {_translateTotalCount} functions translated | Thread count: {degreeOfParallelism} in {sw.Elapsed.TotalSeconds} s");
|
||||
|
||||
Thread preSaveThread = new Thread(PreSave);
|
||||
preSaveThread.IsBackground = true;
|
||||
Thread preSaveThread = new(PreSave)
|
||||
{
|
||||
IsBackground = true,
|
||||
};
|
||||
preSaveThread.Start();
|
||||
}
|
||||
|
||||
|
@ -910,15 +912,16 @@ namespace ARMeilleure.Translation.PTC
|
|||
RelocInfo relocInfo = compiledFunc.RelocInfo;
|
||||
UnwindInfo unwindInfo = compiledFunc.UnwindInfo;
|
||||
|
||||
InfoEntry infoEntry = new InfoEntry();
|
||||
|
||||
infoEntry.Address = address;
|
||||
infoEntry.GuestSize = guestSize;
|
||||
infoEntry.Hash = hash;
|
||||
infoEntry.HighCq = highCq;
|
||||
infoEntry.Stubbed = false;
|
||||
infoEntry.CodeLength = code.Length;
|
||||
infoEntry.RelocEntriesCount = relocInfo.Entries.Length;
|
||||
InfoEntry infoEntry = new()
|
||||
{
|
||||
Address = address,
|
||||
GuestSize = guestSize,
|
||||
Hash = hash,
|
||||
HighCq = highCq,
|
||||
Stubbed = false,
|
||||
CodeLength = code.Length,
|
||||
RelocEntriesCount = relocInfo.Entries.Length,
|
||||
};
|
||||
|
||||
SerializeStructure(_infosStream, infoEntry);
|
||||
|
||||
|
@ -996,10 +999,12 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
uint osPlatform = 0u;
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
osPlatform |= (OperatingSystem.IsFreeBSD() ? 1u : 0u) << 0;
|
||||
osPlatform |= (OperatingSystem.IsLinux() ? 1u : 0u) << 1;
|
||||
osPlatform |= (OperatingSystem.IsMacOS() ? 1u : 0u) << 2;
|
||||
osPlatform |= (OperatingSystem.IsWindows() ? 1u : 0u) << 3;
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
return osPlatform;
|
||||
}
|
||||
|
@ -1025,14 +1030,14 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>()));
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())]);
|
||||
}
|
||||
|
||||
public bool IsHeaderValid()
|
||||
{
|
||||
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash;
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())]) == HeaderHash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1060,14 +1065,14 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
Span<InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>()));
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>())]);
|
||||
}
|
||||
|
||||
public bool IsHeaderValid()
|
||||
{
|
||||
Span<InnerHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash;
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<InnerHeader>() - Unsafe.SizeOf<Hash128>())]) == HeaderHash;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T DeserializeStructure<T>(Stream stream) where T : struct
|
||||
{
|
||||
T structure = default(T);
|
||||
T structure = default;
|
||||
|
||||
Span<T> spanT = MemoryMarshal.CreateSpan(ref structure, 1);
|
||||
int bytesCount = stream.Read(MemoryMarshal.AsBytes(spanT));
|
||||
|
@ -176,4 +176,4 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
Start,
|
||||
Loading,
|
||||
Loaded
|
||||
Loaded,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ using System.IO.Compression;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using static ARMeilleure.Translation.PTC.PtcFormatter;
|
||||
|
||||
namespace ARMeilleure.Translation.PTC
|
||||
|
@ -46,7 +45,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
public bool Enabled { get; private set; }
|
||||
|
||||
public ulong StaticCodeStart { get; set; }
|
||||
public ulong StaticCodeSize { get; set; }
|
||||
public ulong StaticCodeSize { get; set; }
|
||||
|
||||
public PtcProfiler(Ptc ptc)
|
||||
{
|
||||
|
@ -129,8 +128,8 @@ namespace ARMeilleure.Translation.PTC
|
|||
string fileNameActual = $"{_ptc.CachePathActual}.info";
|
||||
string fileNameBackup = $"{_ptc.CachePathBackup}.info";
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
FileInfo fileInfoBackup = new FileInfo(fileNameBackup);
|
||||
FileInfo fileInfoActual = new(fileNameActual);
|
||||
FileInfo fileInfoBackup = new(fileNameBackup);
|
||||
|
||||
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
|
||||
{
|
||||
|
@ -183,42 +182,40 @@ namespace ARMeilleure.Translation.PTC
|
|||
return false;
|
||||
}
|
||||
|
||||
using (MemoryStream stream = MemoryStreamManager.Shared.GetStream())
|
||||
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
||||
Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);
|
||||
|
||||
try
|
||||
{
|
||||
Debug.Assert(stream.Seek(0L, SeekOrigin.Begin) == 0L && stream.Length == 0L);
|
||||
|
||||
try
|
||||
{
|
||||
deflateStream.CopyTo(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
Hash128 expectedHash = DeserializeStructure<Hash128>(stream);
|
||||
|
||||
Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream));
|
||||
|
||||
if (actualHash != expectedHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ProfiledFuncs = Deserialize(stream);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
_lastHash = actualHash;
|
||||
deflateStream.CopyTo(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
stream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
Hash128 expectedHash = DeserializeStructure<Hash128>(stream);
|
||||
|
||||
Hash128 actualHash = XXHash128.ComputeHash(GetReadOnlySpan(stream));
|
||||
|
||||
if (actualHash != expectedHash)
|
||||
{
|
||||
InvalidateCompressedStream(compressedStream);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ProfiledFuncs = Deserialize(stream);
|
||||
|
||||
Debug.Assert(stream.Position == stream.Length);
|
||||
|
||||
_lastHash = actualHash;
|
||||
}
|
||||
|
||||
long fileSize = new FileInfo(fileName).Length;
|
||||
|
@ -233,12 +230,12 @@ namespace ARMeilleure.Translation.PTC
|
|||
return DeserializeDictionary<ulong, FuncProfile>(stream, (stream) => DeserializeStructure<FuncProfile>(stream));
|
||||
}
|
||||
|
||||
private ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
||||
private static ReadOnlySpan<byte> GetReadOnlySpan(MemoryStream memoryStream)
|
||||
{
|
||||
return new(memoryStream.GetBuffer(), (int)memoryStream.Position, (int)memoryStream.Length - (int)memoryStream.Position);
|
||||
}
|
||||
|
||||
private void InvalidateCompressedStream(FileStream compressedStream)
|
||||
private static void InvalidateCompressedStream(FileStream compressedStream)
|
||||
{
|
||||
compressedStream.SetLength(0L);
|
||||
}
|
||||
|
@ -250,7 +247,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
string fileNameActual = $"{_ptc.CachePathActual}.info";
|
||||
string fileNameBackup = $"{_ptc.CachePathBackup}.info";
|
||||
|
||||
FileInfo fileInfoActual = new FileInfo(fileNameActual);
|
||||
FileInfo fileInfoActual = new(fileNameActual);
|
||||
|
||||
if (fileInfoActual.Exists && fileInfoActual.Length != 0L)
|
||||
{
|
||||
|
@ -266,12 +263,13 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
int profiledFuncsCount;
|
||||
|
||||
OuterHeader outerHeader = new OuterHeader();
|
||||
OuterHeader outerHeader = new()
|
||||
{
|
||||
Magic = _outerHeaderMagic,
|
||||
|
||||
outerHeader.Magic = _outerHeaderMagic;
|
||||
|
||||
outerHeader.InfoFileVersion = InternalVersion;
|
||||
outerHeader.Endianness = Ptc.GetEndianness();
|
||||
InfoFileVersion = InternalVersion,
|
||||
Endianness = Ptc.GetEndianness(),
|
||||
};
|
||||
|
||||
outerHeader.SetHeaderHash();
|
||||
|
||||
|
@ -301,28 +299,26 @@ namespace ARMeilleure.Translation.PTC
|
|||
return;
|
||||
}
|
||||
|
||||
using (FileStream compressedStream = new(fileName, FileMode.OpenOrCreate))
|
||||
using (DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true))
|
||||
using FileStream compressedStream = new(fileName, FileMode.OpenOrCreate);
|
||||
using DeflateStream deflateStream = new(compressedStream, SaveCompressionLevel, true);
|
||||
try
|
||||
{
|
||||
try
|
||||
{
|
||||
SerializeStructure(compressedStream, outerHeader);
|
||||
SerializeStructure(compressedStream, outerHeader);
|
||||
|
||||
stream.WriteTo(deflateStream);
|
||||
stream.WriteTo(deflateStream);
|
||||
|
||||
_lastHash = hash;
|
||||
}
|
||||
catch
|
||||
{
|
||||
compressedStream.Position = 0L;
|
||||
_lastHash = hash;
|
||||
}
|
||||
catch
|
||||
{
|
||||
compressedStream.Position = 0L;
|
||||
|
||||
_lastHash = default;
|
||||
}
|
||||
_lastHash = default;
|
||||
}
|
||||
|
||||
if (compressedStream.Position < compressedStream.Length)
|
||||
{
|
||||
compressedStream.SetLength(compressedStream.Position);
|
||||
}
|
||||
if (compressedStream.Position < compressedStream.Length)
|
||||
{
|
||||
compressedStream.SetLength(compressedStream.Position);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -334,7 +330,7 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
|
||||
private void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
|
||||
private static void Serialize(Stream stream, Dictionary<ulong, FuncProfile> profiledFuncs)
|
||||
{
|
||||
SerializeDictionary(stream, profiledFuncs, (stream, structure) => SerializeStructure(stream, structure));
|
||||
}
|
||||
|
@ -354,14 +350,14 @@ namespace ARMeilleure.Translation.PTC
|
|||
{
|
||||
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>()));
|
||||
HeaderHash = XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())]);
|
||||
}
|
||||
|
||||
public bool IsHeaderValid()
|
||||
{
|
||||
Span<OuterHeader> spanHeader = MemoryMarshal.CreateSpan(ref this, 1);
|
||||
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader).Slice(0, Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())) == HeaderHash;
|
||||
return XXHash128.ComputeHash(MemoryMarshal.AsBytes(spanHeader)[..(Unsafe.SizeOf<OuterHeader>() - Unsafe.SizeOf<Hash128>())]) == HeaderHash;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -418,4 +414,4 @@ namespace ARMeilleure.Translation.PTC
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Translation.PTC
|
|||
Enabled,
|
||||
Continuing,
|
||||
Closing,
|
||||
Disabled
|
||||
Disabled,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
public static void Rename(ControlFlowGraph cfg)
|
||||
{
|
||||
Dictionary<Register, Operand> registerToLocalMap = new Dictionary<Register, Operand>();
|
||||
Dictionary<Register, Operand> registerToLocalMap = new();
|
||||
|
||||
Operand GetLocal(Operand op)
|
||||
{
|
||||
|
@ -49,4 +49,4 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ARMeilleure.Translation
|
|||
static class RegisterUsage
|
||||
{
|
||||
private const int RegsCount = 32;
|
||||
private const int RegsMask = RegsCount - 1;
|
||||
private const int RegsMask = RegsCount - 1;
|
||||
|
||||
private readonly struct RegisterMask : IEquatable<RegisterMask>
|
||||
{
|
||||
|
@ -90,7 +90,7 @@ namespace ARMeilleure.Translation
|
|||
public static void RunPass(ControlFlowGraph cfg, ExecutionMode mode)
|
||||
{
|
||||
// Compute local register inputs and outputs used inside blocks.
|
||||
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
|
||||
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
|
||||
RegisterMask[] localOutputs = new RegisterMask[cfg.Blocks.Count];
|
||||
|
||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
|
@ -119,7 +119,7 @@ namespace ARMeilleure.Translation
|
|||
// Compute global register inputs and outputs used across blocks.
|
||||
RegisterMask[] globalCmnOutputs = new RegisterMask[cfg.Blocks.Count];
|
||||
|
||||
RegisterMask[] globalInputs = new RegisterMask[cfg.Blocks.Count];
|
||||
RegisterMask[] globalInputs = new RegisterMask[cfg.Blocks.Count];
|
||||
RegisterMask[] globalOutputs = new RegisterMask[cfg.Blocks.Count];
|
||||
|
||||
bool modified;
|
||||
|
@ -286,10 +286,12 @@ namespace ARMeilleure.Translation
|
|||
|
||||
switch (register.Type)
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
case RegisterType.Flag: intMask = (1L << RegsCount) << register.Index; break;
|
||||
case RegisterType.Integer: intMask = 1L << register.Index; break;
|
||||
case RegisterType.FpFlag: vecMask = (1L << RegsCount) << register.Index; break;
|
||||
case RegisterType.Vector: vecMask = 1L << register.Index; break;
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
return new RegisterMask(intMask, vecMask);
|
||||
|
@ -373,15 +375,14 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private static OperandType GetOperandType(RegisterType type, ExecutionMode mode)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case RegisterType.Flag: return OperandType.I32;
|
||||
case RegisterType.FpFlag: return OperandType.I32;
|
||||
case RegisterType.Integer: return (mode == ExecutionMode.Aarch64) ? OperandType.I64 : OperandType.I32;
|
||||
case RegisterType.Vector: return OperandType.V128;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid register type \"{type}\".");
|
||||
RegisterType.Flag => OperandType.I32,
|
||||
RegisterType.FpFlag => OperandType.I32,
|
||||
RegisterType.Integer => (mode == ExecutionMode.Aarch64) ? OperandType.I64 : OperandType.I32,
|
||||
RegisterType.Vector => OperandType.V128,
|
||||
_ => throw new ArgumentException($"Invalid register type \"{type}\"."),
|
||||
};
|
||||
}
|
||||
|
||||
private static bool EndsWithReturn(BasicBlock block)
|
||||
|
@ -391,4 +392,4 @@ namespace ARMeilleure.Translation
|
|||
return last != default && last.Instruction == Instruction.Return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
|
||||
previous = current;
|
||||
current = current.ImmediateDominator;
|
||||
current = current.ImmediateDominator;
|
||||
}
|
||||
while (previous != current);
|
||||
|
||||
|
@ -286,4 +286,4 @@ namespace ARMeilleure.Translation
|
|||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,4 +45,4 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,4 +31,4 @@ namespace ARMeilleure.Translation
|
|||
return dispatcher(context.NativeContextPtr, (ulong)FuncPointer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,24 +22,24 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
public class Translator
|
||||
{
|
||||
private static readonly AddressTable<ulong>.Level[] Levels64Bit =
|
||||
private static readonly AddressTable<ulong>.Level[] _levels64Bit =
|
||||
new AddressTable<ulong>.Level[]
|
||||
{
|
||||
new(31, 17),
|
||||
new(23, 8),
|
||||
new(15, 8),
|
||||
new( 7, 8),
|
||||
new( 2, 5)
|
||||
new( 2, 5),
|
||||
};
|
||||
|
||||
private static readonly AddressTable<ulong>.Level[] Levels32Bit =
|
||||
private static readonly AddressTable<ulong>.Level[] _levels32Bit =
|
||||
new AddressTable<ulong>.Level[]
|
||||
{
|
||||
new(31, 17),
|
||||
new(23, 8),
|
||||
new(15, 8),
|
||||
new( 7, 8),
|
||||
new( 1, 6)
|
||||
new( 1, 6),
|
||||
};
|
||||
|
||||
private readonly IJitMemoryAllocator _allocator;
|
||||
|
@ -75,7 +75,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
CountTable = new EntryTable<uint>();
|
||||
Functions = new TranslatorCache<TranslatedFunction>();
|
||||
FunctionTable = new AddressTable<ulong>(for64Bits ? Levels64Bit : Levels32Bit);
|
||||
FunctionTable = new AddressTable<ulong>(for64Bits ? _levels64Bit : _levels32Bit);
|
||||
Stubs = new TranslatorStubs(this);
|
||||
|
||||
FunctionTable.Fill = (ulong)Stubs.SlowDispatchStub;
|
||||
|
@ -126,7 +126,7 @@ namespace ARMeilleure.Translation
|
|||
// TODO: Use physical cores rather than logical. This only really makes sense for processors with
|
||||
// hyperthreading. Requires OS specific code.
|
||||
int unboundedThreadCount = Math.Max(1, (Environment.ProcessorCount - 6) / 3);
|
||||
int threadCount = Math.Min(4, unboundedThreadCount);
|
||||
int threadCount = Math.Min(4, unboundedThreadCount);
|
||||
|
||||
Thread[] backgroundTranslationThreads = new Thread[threadCount];
|
||||
|
||||
|
@ -134,10 +134,10 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
bool last = i != 0 && i == unboundedThreadCount - 1;
|
||||
|
||||
backgroundTranslationThreads[i] = new Thread(BackgroundTranslate)
|
||||
backgroundTranslationThreads[i] = new(BackgroundTranslate)
|
||||
{
|
||||
Name = "CPU.BackgroundTranslatorThread." + i,
|
||||
Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal
|
||||
Priority = last ? ThreadPriority.Lowest : ThreadPriority.Normal,
|
||||
};
|
||||
|
||||
backgroundTranslationThreads[i].Start();
|
||||
|
|
|
@ -224,7 +224,7 @@ namespace ARMeilleure.Translation
|
|||
/// <param name="context">Emitter context for the method</param>
|
||||
/// <param name="nativeContext">Pointer to the native context</param>
|
||||
/// <param name="enter">True if entering guest code, false otherwise</param>
|
||||
private void EmitSyncFpContext(EmitterContext context, Operand nativeContext, bool enter)
|
||||
private static void EmitSyncFpContext(EmitterContext context, Operand nativeContext, bool enter)
|
||||
{
|
||||
if (enter)
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.CodeGen.X86;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -62,7 +61,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public static FpFlagsPInvokeTest GenerateFpFlagsPInvokeTest()
|
||||
{
|
||||
EmitterContext context = new EmitterContext();
|
||||
EmitterContext context = new();
|
||||
|
||||
Operand methodAddress = context.Copy(context.LoadArgument(OperandType.I64, 0));
|
||||
|
||||
|
@ -110,7 +109,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
context.MarkLabel(correct2Label);
|
||||
|
||||
// Call a managed method. This method should not change Fz state.
|
||||
// Call a managed method. This method should not change Fz state.
|
||||
|
||||
context.Call(methodAddress, OperandType.None);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue