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