diff options
| author | FICTURE7 <FICTURE7@gmail.com> | 2021-09-14 03:23:37 +0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-09-14 01:23:37 +0200 |
| commit | a9343c9364246d3288b4e7f20919ca1ad2e1fd3e (patch) | |
| tree | ba8ada2c2f5d2b4b0c92fbc5258bc43ad4809913 /ARMeilleure/CodeGen/X86 | |
| parent | ac4ec1a0151fd958d7ec58146169763b446836fe (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/X86')
| -rw-r--r-- | ARMeilleure/CodeGen/X86/Assembler.cs | 33 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/X86/CodeGenContext.cs | 63 | ||||
| -rw-r--r-- | ARMeilleure/CodeGen/X86/CodeGenerator.cs | 66 |
3 files changed, 73 insertions, 89 deletions
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) |
