aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/CodeGen
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/CodeGen
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/CodeGen')
-rw-r--r--ARMeilleure/CodeGen/CompiledFunction.cs43
-rw-r--r--ARMeilleure/CodeGen/Linking/RelocEntry.cs38
-rw-r--r--ARMeilleure/CodeGen/Linking/RelocInfo.cs32
-rw-r--r--ARMeilleure/CodeGen/Linking/Symbol.cs100
-rw-r--r--ARMeilleure/CodeGen/Linking/SymbolType.cs28
-rw-r--r--ARMeilleure/CodeGen/X86/Assembler.cs33
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenContext.cs63
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenerator.cs66
8 files changed, 312 insertions, 91 deletions
diff --git a/ARMeilleure/CodeGen/CompiledFunction.cs b/ARMeilleure/CodeGen/CompiledFunction.cs
index 61e89c24..ab5e88eb 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
+ /// <summary>
+ /// Represents a compiled function.
+ /// </summary>
+ readonly struct CompiledFunction
{
+ /// <summary>
+ /// Gets the machine code of the <see cref="CompiledFunction"/>.
+ /// </summary>
public byte[] Code { get; }
+ /// <summary>
+ /// Gets the <see cref="Unwinding.UnwindInfo"/> of the <see cref="CompiledFunction"/>.
+ /// </summary>
public UnwindInfo UnwindInfo { get; }
- public CompiledFunction(byte[] code, UnwindInfo unwindInfo)
+ /// <summary>
+ /// Gets the <see cref="Linking.RelocInfo"/> of the <see cref="CompiledFunction"/>.
+ /// </summary>
+ public RelocInfo RelocInfo { get; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="CompiledFunction"/> struct with the specified machine code,
+ /// unwind info and relocation info.
+ /// </summary>
+ /// <param name="code">Machine code</param>
+ /// <param name="unwindInfo">Unwind info</param>
+ /// <param name="relocInfo">Relocation info</param>
+ internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo)
{
Code = code;
UnwindInfo = unwindInfo;
+ RelocInfo = relocInfo;
+ }
+
+ /// <summary>
+ /// Maps the <see cref="CompiledFunction"/> onto the <see cref="JitCache"/> and returns a delegate of type
+ /// <typeparamref name="T"/> pointing to the mapped function.
+ /// </summary>
+ /// <typeparam name="T">Type of delegate</typeparam>
+ /// <returns>A delegate of type <typeparamref name="T"/> pointing to the mapped function</returns>
+ public T Map<T>()
+ {
+ IntPtr codePtr = JitCache.Map(this);
+
+ return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
}
}
} \ 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 00000000..a27bfded
--- /dev/null
+++ b/ARMeilleure/CodeGen/Linking/RelocEntry.cs
@@ -0,0 +1,38 @@
+namespace ARMeilleure.CodeGen.Linking
+{
+ /// <summary>
+ /// Represents a relocation.
+ /// </summary>
+ readonly struct RelocEntry
+ {
+ public const int Stride = 13; // Bytes.
+
+ /// <summary>
+ /// Gets the position of the relocation.
+ /// </summary>
+ public int Position { get; }
+
+ /// <summary>
+ /// Gets the <see cref="Symbol"/> of the relocation.
+ /// </summary>
+ public Symbol Symbol { get; }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RelocEntry"/> struct with the specified position and
+ /// <see cref="Symbol"/>.
+ /// </summary>
+ /// <param name="position">Position of relocation</param>
+ /// <param name="symbol">Symbol of relocation</param>
+ public RelocEntry(int position, Symbol symbol)
+ {
+ Position = position;
+ Symbol = symbol;
+ }
+
+ /// <inheritdoc/>
+ public override string ToString()
+ {
+ return $"({nameof(Position)} = {Position}, {nameof(Symbol)} = {Symbol})";
+ }
+ }
+} \ 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 00000000..922b8bfe
--- /dev/null
+++ b/ARMeilleure/CodeGen/Linking/RelocInfo.cs
@@ -0,0 +1,32 @@
+using System;
+
+namespace ARMeilleure.CodeGen.Linking
+{
+ /// <summary>
+ /// Represents relocation information about a <see cref="CompiledFunction"/>.
+ /// </summary>
+ readonly struct RelocInfo
+ {
+ /// <summary>
+ /// Gets an empty <see cref="RelocInfo"/>.
+ /// </summary>
+ public static RelocInfo Empty { get; } = new RelocInfo(null);
+
+ private readonly RelocEntry[] _entries;
+
+ /// <summary>
+ /// Gets the set of <see cref="RelocEntry"/>.
+ /// </summary>
+ public ReadOnlySpan<RelocEntry> Entries => _entries ?? Array.Empty<RelocEntry>();
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="RelocInfo"/> struct with the specified set of
+ /// <see cref="RelocEntry"/>.
+ /// </summary>
+ /// <param name="entries">Set of <see cref="RelocInfo"/> to use</param>
+ public RelocInfo(RelocEntry[] entries)
+ {
+ _entries = entries ?? Array.Empty<RelocEntry>();
+ }
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/Linking/Symbol.cs b/ARMeilleure/CodeGen/Linking/Symbol.cs
new file mode 100644
index 00000000..fa47ee23
--- /dev/null
+++ b/ARMeilleure/CodeGen/Linking/Symbol.cs
@@ -0,0 +1,100 @@
+using System;
+
+namespace ARMeilleure.CodeGen.Linking
+{
+ /// <summary>
+ /// Represents a symbol.
+ /// </summary>
+ readonly 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/CodeGen/Linking/SymbolType.cs b/ARMeilleure/CodeGen/Linking/SymbolType.cs
new file mode 100644
index 00000000..b05b6969
--- /dev/null
+++ b/ARMeilleure/CodeGen/Linking/SymbolType.cs
@@ -0,0 +1,28 @@
+namespace ARMeilleure.CodeGen.Linking
+{
+ /// <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="Translation.Delegates"/>.
+ /// </summary>
+ DelegateTable,
+
+ /// <summary>
+ /// Refers to an entry in <see cref="Translation.Translator.FunctionTable"/>.
+ /// </summary>
+ FunctionTable,
+
+ /// <summary>
+ /// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
+ /// </summary>
+ Special
+ }
+}
diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs
index 044f6047..95608756 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<RelocEntry> 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<RelocEntry>() : 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 fa726f2f..7e96dd85 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<Jump> _jumps;
+ private readonly List<Jump> _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;
+ _relocatable = relocatable;
+ _blockOffsets = new long[blocksCount];
+ _jumps = new List<Jump>();
AllocResult = allocResult;
-
- Assembler = new Assembler(stream, ptcInfo);
-
+ Assembler = new Assembler(stream, relocatable);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
XmmSaveRegionSize = xmmSaveRegionSize;
-
- _blockOffsets = new long[blocksCount];
-
- _jumps = new List<Jump>();
-
- _ptcInfo = ptcInfo;
- _ptcDisabled = ptcInfo == null;
}
- 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<byte> 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 5818eb2e..924c113c 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())
- {
- CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count, ptcInfo);
+ 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);
+ UnwindInfo unwindInfo = WritePrologue(context);
- ptcInfo?.WriteUnwindInfo(unwindInfo);
+ for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
+ {
+ context.EnterBlock(block);
- 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);
+ GenerateOperation(context, node);
+ }
- for (Operation node = block.Operations.First; node != default; node = node.ListNext)
- {
- GenerateOperation(context, node);
- }
+ if (block.SuccessorsCount == 0)
+ {
+ // The only blocks which can have 0 successors are exit blocks.
+ Operation last = block.Operations.Last;
- 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);
- Debug.Assert(last.Instruction == Instruction.Tailcall ||
- last.Instruction == Instruction.Return);
- }
- else
+ if (succ != block.ListNext)
{
- BasicBlock succ = block.GetSuccessor(0);
-
- if (succ != block.ListNext)
- {
- context.JumpTo(succ);
- }
+ context.JumpTo(succ);
}
}
+ }
- byte[] code = context.GetCode();
+ (byte[] code, RelocInfo relocInfo) = context.GetCode();
- if (ptcInfo != null)
- {
- ptcInfo.Code = code;
- }
+ Logger.EndPass(PassName.CodeGeneration);
- Logger.EndPass(PassName.CodeGeneration);
-
- return new CompiledFunction(code, unwindInfo);
- }
+ return new CompiledFunction(code, unwindInfo, relocInfo);
}
private static void GenerateOperation(CodeGenContext context, Operation operation)