aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation
diff options
context:
space:
mode:
authorFICTURE7 <FICTURE7@gmail.com>2021-09-14 03:23:37 +0400
committerGitHub <noreply@github.com>2021-09-14 01:23:37 +0200
commita9343c9364246d3288b4e7f20919ca1ad2e1fd3e (patch)
treeba8ada2c2f5d2b4b0c92fbc5258bc43ad4809913 /ARMeilleure/Translation
parentac4ec1a0151fd958d7ec58146169763b446836fe (diff)
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.
Diffstat (limited to 'ARMeilleure/Translation')
-rw-r--r--ARMeilleure/Translation/ArmEmitterContext.cs1
-rw-r--r--ARMeilleure/Translation/Compiler.cs23
-rw-r--r--ARMeilleure/Translation/CompilerOptions.cs9
-rw-r--r--ARMeilleure/Translation/PTC/Ptc.cs48
-rw-r--r--ARMeilleure/Translation/PTC/PtcInfo.cs63
-rw-r--r--ARMeilleure/Translation/PTC/RelocEntry.cs21
-rw-r--r--ARMeilleure/Translation/PTC/Symbol.cs100
-rw-r--r--ARMeilleure/Translation/PTC/SymbolType.cs28
-rw-r--r--ARMeilleure/Translation/Translator.cs25
-rw-r--r--ARMeilleure/Translation/TranslatorStubs.cs6
10 files changed, 56 insertions, 268 deletions
diff --git a/ARMeilleure/Translation/ArmEmitterContext.cs b/ARMeilleure/Translation/ArmEmitterContext.cs
index 563775ee..6d02728c 100644
--- a/ARMeilleure/Translation/ArmEmitterContext.cs
+++ b/ARMeilleure/Translation/ArmEmitterContext.cs
@@ -1,3 +1,4 @@
+using ARMeilleure.CodeGen.Linking;
using ARMeilleure.Common;
using ARMeilleure.Decoders;
using ARMeilleure.Diagnostics;
diff --git a/ARMeilleure/Translation/Compiler.cs b/ARMeilleure/Translation/Compiler.cs
index 812144a1..9e4cdb24 100644
--- a/ARMeilleure/Translation/Compiler.cs
+++ b/ARMeilleure/Translation/Compiler.cs
@@ -2,35 +2,16 @@ using ARMeilleure.CodeGen;
using ARMeilleure.CodeGen.X86;
using ARMeilleure.Diagnostics;
using ARMeilleure.IntermediateRepresentation;
-using ARMeilleure.Translation.Cache;
-using ARMeilleure.Translation.PTC;
-using System;
-using System.Runtime.InteropServices;
namespace ARMeilleure.Translation
{
static class Compiler
{
- public static T Compile<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(
ControlFlowGraph cfg,
OperandType[] argTypes,
OperandType retType,
- CompilerOptions options,
- PtcInfo ptcInfo = null)
+ CompilerOptions options)
{
Logger.StartPass(PassName.Dominance);
@@ -57,7 +38,7 @@ namespace ARMeilleure.Translation
CompilerContext cctx = new(cfg, argTypes, retType, options);
- return CodeGenerator.Generate(cctx, ptcInfo);
+ return CodeGenerator.Generate(cctx);
}
}
} \ No newline at end of file
diff --git a/ARMeilleure/Translation/CompilerOptions.cs b/ARMeilleure/Translation/CompilerOptions.cs
index 53998ec6..0a07ed4a 100644
--- a/ARMeilleure/Translation/CompilerOptions.cs
+++ b/ARMeilleure/Translation/CompilerOptions.cs
@@ -5,10 +5,11 @@ namespace ARMeilleure.Translation
[Flags]
enum CompilerOptions
{
- None = 0,
- SsaForm = 1 << 0,
- Optimize = 1 << 1,
- Lsra = 1 << 2,
+ None = 0,
+ SsaForm = 1 << 0,
+ Optimize = 1 << 1,
+ Lsra = 1 << 2,
+ Relocatable = 1 << 3,
MediumCq = SsaForm | Optimize,
HighCq = SsaForm | Optimize | Lsra
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 8d4f971b..ad2871d0 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -1,9 +1,9 @@
using ARMeilleure.CodeGen;
+using ARMeilleure.CodeGen.Linking;
using ARMeilleure.CodeGen.Unwinding;
using ARMeilleure.CodeGen.X86;
using ARMeilleure.Common;
using ARMeilleure.Memory;
-using ARMeilleure.Translation.Cache;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
@@ -727,15 +727,10 @@ namespace ARMeilleure.Translation.PTC
UnwindInfo unwindInfo,
bool highCq)
{
- CompiledFunction cFunc = new CompiledFunction(code, unwindInfo);
+ var cFunc = new CompiledFunction(code, unwindInfo, RelocInfo.Empty);
+ var gFunc = cFunc.Map<GuestFunction>();
- IntPtr codePtr = JitCache.Map(cFunc);
-
- GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer<GuestFunction>(codePtr);
-
- TranslatedFunction tFunc = new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
-
- return tFunc;
+ return new TranslatedFunction(gFunc, callCounter, guestSize, highCq);
}
private static void UpdateInfo(InfoEntry infoEntry)
@@ -889,10 +884,14 @@ namespace ARMeilleure.Translation.PTC
return XXHash128.ComputeHash(memory.GetSpan(address, checked((int)(guestSize))));
}
- internal static void WriteInfoCodeRelocUnwindInfo(ulong address, ulong guestSize, Hash128 hash, bool highCq, PtcInfo ptcInfo)
+ internal static void WriteCompiledFunction(ulong address, ulong guestSize, Hash128 hash, bool highCq, CompiledFunction compiledFunc)
{
lock (_lock)
{
+ byte[] code = compiledFunc.Code;
+ RelocInfo relocInfo = compiledFunc.RelocInfo;
+ UnwindInfo unwindInfo = compiledFunc.UnwindInfo;
+
InfoEntry infoEntry = new InfoEntry();
infoEntry.Address = address;
@@ -900,18 +899,37 @@ namespace ARMeilleure.Translation.PTC
infoEntry.Hash = hash;
infoEntry.HighCq = highCq;
infoEntry.Stubbed = false;
- infoEntry.CodeLength = ptcInfo.Code.Length;
- infoEntry.RelocEntriesCount = ptcInfo.RelocEntriesCount;
+ infoEntry.CodeLength = code.Length;
+ infoEntry.RelocEntriesCount = relocInfo.Entries.Length;
SerializeStructure(_infosStream, infoEntry);
- WriteCode(ptcInfo.Code.AsSpan());
+ WriteCode(code.AsSpan());
// WriteReloc.
- ptcInfo.RelocStream.WriteTo(_relocsStream);
+ using var relocInfoWriter = new BinaryWriter(_relocsStream, EncodingCache.UTF8NoBOM, true);
+
+ foreach (RelocEntry entry in relocInfo.Entries)
+ {
+ relocInfoWriter.Write(entry.Position);
+ relocInfoWriter.Write((byte)entry.Symbol.Type);
+ relocInfoWriter.Write(entry.Symbol.Value);
+ }
// WriteUnwindInfo.
- ptcInfo.UnwindInfoStream.WriteTo(_unwindInfosStream);
+ using var unwindInfoWriter = new BinaryWriter(_unwindInfosStream, EncodingCache.UTF8NoBOM, true);
+
+ unwindInfoWriter.Write(unwindInfo.PushEntries.Length);
+
+ foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries)
+ {
+ unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp);
+ unwindInfoWriter.Write(unwindPushEntry.PrologOffset);
+ unwindInfoWriter.Write(unwindPushEntry.RegIndex);
+ unwindInfoWriter.Write(unwindPushEntry.StackOffsetOrAllocSize);
+ }
+
+ unwindInfoWriter.Write(unwindInfo.PrologSize);
}
}
diff --git a/ARMeilleure/Translation/PTC/PtcInfo.cs b/ARMeilleure/Translation/PTC/PtcInfo.cs
deleted file mode 100644
index b28b2dc1..00000000
--- a/ARMeilleure/Translation/PTC/PtcInfo.cs
+++ /dev/null
@@ -1,63 +0,0 @@
-using ARMeilleure.CodeGen.Unwinding;
-using System;
-using System.IO;
-
-namespace ARMeilleure.Translation.PTC
-{
- class PtcInfo : IDisposable
- {
- private readonly BinaryWriter _relocWriter;
- private readonly BinaryWriter _unwindInfoWriter;
-
- public byte[] Code { get; set; }
-
- public MemoryStream RelocStream { get; }
- public MemoryStream UnwindInfoStream { get; }
-
- public int RelocEntriesCount { get; private set; }
-
- public PtcInfo()
- {
- RelocStream = new MemoryStream();
- UnwindInfoStream = new MemoryStream();
-
- _relocWriter = new BinaryWriter(RelocStream, EncodingCache.UTF8NoBOM, true);
- _unwindInfoWriter = new BinaryWriter(UnwindInfoStream, EncodingCache.UTF8NoBOM, true);
-
- RelocEntriesCount = 0;
- }
-
- public void WriteRelocEntry(RelocEntry relocEntry)
- {
- _relocWriter.Write((int)relocEntry.Position);
- _relocWriter.Write((byte)relocEntry.Symbol.Type);
- _relocWriter.Write((ulong)relocEntry.Symbol.Value);
-
- RelocEntriesCount++;
- }
-
- public void WriteUnwindInfo(UnwindInfo unwindInfo)
- {
- _unwindInfoWriter.Write((int)unwindInfo.PushEntries.Length);
-
- foreach (UnwindPushEntry unwindPushEntry in unwindInfo.PushEntries)
- {
- _unwindInfoWriter.Write((int)unwindPushEntry.PseudoOp);
- _unwindInfoWriter.Write((int)unwindPushEntry.PrologOffset);
- _unwindInfoWriter.Write((int)unwindPushEntry.RegIndex);
- _unwindInfoWriter.Write((int)unwindPushEntry.StackOffsetOrAllocSize);
- }
-
- _unwindInfoWriter.Write((int)unwindInfo.PrologSize);
- }
-
- public void Dispose()
- {
- _relocWriter.Dispose();
- _unwindInfoWriter.Dispose();
-
- RelocStream.Dispose();
- UnwindInfoStream.Dispose();
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/Translation/PTC/RelocEntry.cs b/ARMeilleure/Translation/PTC/RelocEntry.cs
deleted file mode 100644
index 545612d0..00000000
--- a/ARMeilleure/Translation/PTC/RelocEntry.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-namespace ARMeilleure.Translation.PTC
-{
- struct RelocEntry
- {
- public const int Stride = 13; // Bytes.
-
- public int Position;
- public Symbol Symbol;
-
- public RelocEntry(int position, Symbol symbol)
- {
- Position = position;
- Symbol = symbol;
- }
-
- public override string ToString()
- {
- return $"({nameof(Position)} = {Position}, {nameof(Symbol)} = {Symbol})";
- }
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/Translation/PTC/Symbol.cs b/ARMeilleure/Translation/PTC/Symbol.cs
deleted file mode 100644
index f9d67742..00000000
--- a/ARMeilleure/Translation/PTC/Symbol.cs
+++ /dev/null
@@ -1,100 +0,0 @@
-using System;
-
-namespace ARMeilleure.Translation.PTC
-{
- /// <summary>
- /// Represents a symbol.
- /// </summary>
- struct Symbol
- {
- private readonly ulong _value;
-
- /// <summary>
- /// Gets the <see cref="SymbolType"/> of the <see cref="Symbol"/>.
- /// </summary>
- public SymbolType Type { get; }
-
- /// <summary>
- /// Gets the value of the <see cref="Symbol"/>.
- /// </summary>
- /// <exception cref="InvalidOperationException"><see cref="Type"/> is <see cref="SymbolType.None"/></exception>
- public ulong Value
- {
- get
- {
- if (Type == SymbolType.None)
- {
- ThrowSymbolNone();
- }
-
- return _value;
- }
- }
-
- /// <summary>
- /// Initializes a new instance of the <see cref="Symbol"/> structure with the specified <see cref="SymbolType"/> and value.
- /// </summary>
- /// <param name="type">Type of symbol</param>
- /// <param name="value">Value of symbol</param>
- public Symbol(SymbolType type, ulong value)
- {
- (Type, _value) = (type, value);
- }
-
- /// <summary>
- /// Determines if the specified <see cref="Symbol"/> instances are equal.
- /// </summary>
- /// <param name="a">First instance</param>
- /// <param name="b">Second instance</param>
- /// <returns><see langword="true"/> if equal; otherwise <see langword="false"/></returns>
- public static bool operator ==(Symbol a, Symbol b)
- {
- return a.Equals(b);
- }
-
- /// <summary>
- /// Determines if the specified <see cref="Symbol"/> instances are not equal.
- /// </summary>
- /// <param name="a">First instance</param>
- /// <param name="b">Second instance</param>
- /// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
- /// <inheritdoc/>
- public static bool operator !=(Symbol a, Symbol b)
- {
- return !(a == b);
- }
-
- /// <summary>
- /// Determines if the specified <see cref="Symbol"/> is equal to this <see cref="Symbol"/> instance.
- /// </summary>
- /// <param name="other">Other <see cref="Symbol"/> instance</param>
- /// <returns><see langword="true"/> if equal; otherwise <see langword="false"/></returns>
- public bool Equals(Symbol other)
- {
- return other.Type == Type && other._value == _value;
- }
-
- /// <inheritdoc/>
- public override bool Equals(object obj)
- {
- return obj is Symbol sym && Equals(sym);
- }
-
- /// <inheritdoc/>
- public override int GetHashCode()
- {
- return HashCode.Combine(Type, _value);
- }
-
- /// <inheritdoc/>
- public override string ToString()
- {
- return $"{Type}:{_value}";
- }
-
- private static void ThrowSymbolNone()
- {
- throw new InvalidOperationException("Symbol refers to nothing.");
- }
- }
-}
diff --git a/ARMeilleure/Translation/PTC/SymbolType.cs b/ARMeilleure/Translation/PTC/SymbolType.cs
deleted file mode 100644
index cd7b6c1c..00000000
--- a/ARMeilleure/Translation/PTC/SymbolType.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-namespace ARMeilleure.Translation.PTC
-{
- /// <summary>
- /// Types of <see cref="Symbol"/>.
- /// </summary>
- enum SymbolType : byte
- {
- /// <summary>
- /// Refers to nothing, i.e no symbol.
- /// </summary>
- None,
-
- /// <summary>
- /// Refers to an entry in <see cref="Delegates"/>.
- /// </summary>
- DelegateTable,
-
- /// <summary>
- /// Refers to an entry in <see cref="Translator.FunctionTable"/>.
- /// </summary>
- FunctionTable,
-
- /// <summary>
- /// Refers to a special symbol which is handled by <see cref="Ptc.PatchCode"/>.
- /// </summary>
- Special
- }
-}
diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs
index 03ed4c5e..9974fb2d 100644
--- a/ARMeilleure/Translation/Translator.cs
+++ b/ARMeilleure/Translation/Translator.cs
@@ -1,3 +1,4 @@
+using ARMeilleure.CodeGen;
using ARMeilleure.Common;
using ARMeilleure.Decoders;
using ARMeilleure.Diagnostics;
@@ -279,32 +280,30 @@ namespace ARMeilleure.Translation
Logger.EndPass(PassName.RegisterUsage);
- OperandType[] argTypes = new OperandType[] { OperandType.I64 };
+ var retType = OperandType.I64;
+ var argTypes = new OperandType[] { OperandType.I64 };
- CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
+ var options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
- GuestFunction func;
-
- if (!context.HasPtc)
+ if (context.HasPtc)
{
- func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
+ options |= CompilerOptions.Relocatable;
}
- else
- {
- using PtcInfo ptcInfo = new PtcInfo();
- func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options, ptcInfo);
+ CompiledFunction compiledFunc = Compiler.Compile(cfg, argTypes, retType, options);
+ if (context.HasPtc)
+ {
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();
- return result;
+ return new TranslatedFunction(func, counter, funcSize, highCq);
}
private struct Range
diff --git a/ARMeilleure/Translation/TranslatorStubs.cs b/ARMeilleure/Translation/TranslatorStubs.cs
index 48fa3a94..4ad6c2f2 100644
--- a/ARMeilleure/Translation/TranslatorStubs.cs
+++ b/ARMeilleure/Translation/TranslatorStubs.cs
@@ -178,7 +178,7 @@ namespace ARMeilleure.Translation
var retType = OperandType.I64;
var argTypes = new[] { OperandType.I64 };
- var func = Compiler.Compile<GuestFunction>(cfg, argTypes, retType, CompilerOptions.HighCq);
+ var func = Compiler.Compile(cfg, argTypes, retType, CompilerOptions.HighCq).Map<GuestFunction>();
return Marshal.GetFunctionPointerForDelegate(func);
}
@@ -204,7 +204,7 @@ namespace ARMeilleure.Translation
var retType = 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);
}
@@ -242,7 +242,7 @@ namespace ARMeilleure.Translation
var retType = OperandType.None;
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>();
}
}
}