aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/CodeGen')
-rw-r--r--ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs8
-rw-r--r--ARMeilleure/CodeGen/Unwinding/UnwindPseudoOp.cs11
-rw-r--r--ARMeilleure/CodeGen/Unwinding/UnwindPseudoOperation.cs11
-rw-r--r--ARMeilleure/CodeGen/X86/Assembler.cs28
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenContext.cs132
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenerator.cs7
6 files changed, 125 insertions, 72 deletions
diff --git a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
index 84eedee0..eff53217 100644
--- a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
+++ b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs
@@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Optimizations
return;
}
- if (!AreAllSourcesConstant(operation))
+ if (!AreAllSourcesConstantAndCFEnabled(operation))
{
return;
}
@@ -212,11 +212,13 @@ namespace ARMeilleure.CodeGen.Optimizations
}
}
- private static bool AreAllSourcesConstant(Operation operation)
+ private static bool AreAllSourcesConstantAndCFEnabled(Operation operation)
{
for (int index = 0; index < operation.SourcesCount; index++)
{
- if (operation.GetSource(index).Kind != OperandKind.Constant)
+ Operand srcOp = operation.GetSource(index);
+
+ if (srcOp.Kind != OperandKind.Constant || srcOp.DisableCF)
{
return false;
}
diff --git a/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOp.cs b/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOp.cs
new file mode 100644
index 00000000..4a8288a2
--- /dev/null
+++ b/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOp.cs
@@ -0,0 +1,11 @@
+namespace ARMeilleure.CodeGen.Unwinding
+{
+ enum UnwindPseudoOp
+ {
+ PushReg = 0,
+ SetFrame = 1,
+ AllocStack = 2,
+ SaveReg = 3,
+ SaveXmm128 = 4
+ }
+} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOperation.cs b/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOperation.cs
deleted file mode 100644
index 44ed23f5..00000000
--- a/ARMeilleure/CodeGen/Unwinding/UnwindPseudoOperation.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-namespace ARMeilleure.CodeGen.Unwinding
-{
- enum UnwindPseudoOp
- {
- PushReg,
- SetFrame,
- AllocStack,
- SaveReg,
- SaveXmm128
- }
-} \ No newline at end of file
diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs
index 5ad54289..99df3cb5 100644
--- a/ARMeilleure/CodeGen/X86/Assembler.cs
+++ b/ARMeilleure/CodeGen/X86/Assembler.cs
@@ -1,4 +1,5 @@
using ARMeilleure.IntermediateRepresentation;
+using ARMeilleure.Translation.PTC;
using System;
using System.Diagnostics;
using System.IO;
@@ -64,6 +65,9 @@ namespace ARMeilleure.CodeGen.X86
private Stream _stream;
+ private PtcInfo _ptcInfo;
+ private bool _ptcDisabled;
+
static Assembler()
{
_instTable = new InstructionInfo[(int)X86Instruction.Count];
@@ -273,9 +277,12 @@ namespace ARMeilleure.CodeGen.X86
_instTable[(int)inst] = info;
}
- public Assembler(Stream stream)
+ public Assembler(Stream stream, PtcInfo ptcInfo = null)
{
_stream = stream;
+
+ _ptcInfo = ptcInfo;
+ _ptcDisabled = ptcInfo == null;
}
public void Add(Operand dest, Operand source, OperandType type)
@@ -456,7 +463,7 @@ namespace ARMeilleure.CodeGen.X86
public void Jcc(X86Condition condition, long offset)
{
- if (ConstFitsOnS8(offset))
+ if (_ptcDisabled && ConstFitsOnS8(offset))
{
WriteByte((byte)(0x70 | (int)condition));
@@ -477,7 +484,7 @@ namespace ARMeilleure.CodeGen.X86
public void Jmp(long offset)
{
- if (ConstFitsOnS8(offset))
+ if (_ptcDisabled && ConstFitsOnS8(offset))
{
WriteByte(0xeb);
@@ -915,6 +922,8 @@ namespace ARMeilleure.CodeGen.X86
}
else if (dest != null && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
{
+ int? index = source.PtcIndex;
+
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
if (rexPrefix != 0)
@@ -924,6 +933,11 @@ namespace ARMeilleure.CodeGen.X86
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
+ if (_ptcInfo != null && index != null)
+ {
+ _ptcInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, (int)index));
+ }
+
WriteUInt64(imm);
}
else
@@ -1316,9 +1330,9 @@ namespace ARMeilleure.CodeGen.X86
return ConstFitsOnS32(value);
}
- public static int GetJccLength(long offset)
+ public static int GetJccLength(long offset, bool ptcDisabled = true)
{
- if (ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
+ if (ptcDisabled && ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
{
return 2;
}
@@ -1332,9 +1346,9 @@ namespace ARMeilleure.CodeGen.X86
}
}
- public static int GetJmpLength(long offset)
+ public static int GetJmpLength(long offset, bool ptcDisabled = true)
{
- if (ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
+ if (ptcDisabled && ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
{
return 2;
}
diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs
index d719b516..da147cca 100644
--- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs
+++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs
@@ -1,6 +1,7 @@
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
+using ARMeilleure.Translation.PTC;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
@@ -13,6 +14,9 @@ namespace ARMeilleure.CodeGen.X86
private Stream _stream;
+ private PtcInfo _ptcInfo;
+ private bool _ptcDisabled;
+
public int StreamOffset => (int)_stream.Length;
public AllocationResult AllocResult { get; }
@@ -40,7 +44,7 @@ namespace ARMeilleure.CodeGen.X86
public int InstSize { get; set; }
- public Jump(BasicBlock target, long jumpPosition)
+ public Jump(BasicBlock target, long jumpPosition, int instSize = 0)
{
IsConditional = false;
Condition = 0;
@@ -49,10 +53,10 @@ namespace ARMeilleure.CodeGen.X86
RelativeOffset = 0;
- InstSize = 0;
+ InstSize = instSize;
}
- public Jump(X86Condition condition, BasicBlock target, long jumpPosition)
+ public Jump(X86Condition condition, BasicBlock target, long jumpPosition, int instSize = 0)
{
IsConditional = true;
Condition = condition;
@@ -61,7 +65,7 @@ namespace ARMeilleure.CodeGen.X86
RelativeOffset = 0;
- InstSize = 0;
+ InstSize = instSize;
}
}
@@ -72,13 +76,13 @@ namespace ARMeilleure.CodeGen.X86
private long _jNearPosition;
private int _jNearLength;
- public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount)
+ public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount, PtcInfo ptcInfo = null)
{
_stream = stream;
AllocResult = allocResult;
- Assembler = new Assembler(stream);
+ Assembler = new Assembler(stream, ptcInfo);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
XmmSaveRegionSize = xmmSaveRegionSize;
@@ -86,6 +90,9 @@ namespace ARMeilleure.CodeGen.X86
_blockOffsets = new long[blocksCount];
_jumps = new List<Jump>();
+
+ _ptcInfo = ptcInfo;
+ _ptcDisabled = ptcInfo == null;
}
private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize)
@@ -136,23 +143,41 @@ namespace ARMeilleure.CodeGen.X86
public void JumpTo(BasicBlock target)
{
- _jumps.Add(new Jump(target, _stream.Position));
+ if (_ptcDisabled)
+ {
+ _jumps.Add(new Jump(target, _stream.Position));
- WritePadding(ReservedBytesForJump);
+ WritePadding(ReservedBytesForJump);
+ }
+ else
+ {
+ _jumps.Add(new Jump(target, _stream.Position, 5));
+
+ WritePadding(5);
+ }
}
public void JumpTo(X86Condition condition, BasicBlock target)
{
- _jumps.Add(new Jump(condition, target, _stream.Position));
+ if (_ptcDisabled)
+ {
+ _jumps.Add(new Jump(condition, target, _stream.Position));
+
+ WritePadding(ReservedBytesForJump);
+ }
+ else
+ {
+ _jumps.Add(new Jump(condition, target, _stream.Position, 6));
- WritePadding(ReservedBytesForJump);
+ WritePadding(6);
+ }
}
public void JumpToNear(X86Condition condition)
{
_jNearCondition = condition;
_jNearPosition = _stream.Position;
- _jNearLength = Assembler.GetJccLength(0);
+ _jNearLength = Assembler.GetJccLength(0, _ptcDisabled);
_stream.Seek(_jNearLength, SeekOrigin.Current);
}
@@ -165,7 +190,7 @@ namespace ARMeilleure.CodeGen.X86
long offset = currentPosition - (_jNearPosition + _jNearLength);
- Debug.Assert(_jNearLength == Assembler.GetJccLength(offset), "Relative offset doesn't fit on near jump.");
+ Debug.Assert(_jNearLength == Assembler.GetJccLength(offset, _ptcDisabled), "Relative offset doesn't fit on near jump.");
Assembler.Jcc(_jNearCondition, offset);
@@ -197,56 +222,63 @@ namespace ARMeilleure.CodeGen.X86
long offset = jumpTarget - jump.JumpPosition;
- if (offset < 0)
+ if (_ptcDisabled)
{
- for (int index2 = index - 1; index2 >= 0; index2--)
+ if (offset < 0)
{
- Jump jump2 = _jumps[index2];
-
- if (jump2.JumpPosition < jumpTarget)
+ for (int index2 = index - 1; index2 >= 0; index2--)
{
- break;
- }
+ Jump jump2 = _jumps[index2];
- offset -= jump2.InstSize - ReservedBytesForJump;
+ if (jump2.JumpPosition < jumpTarget)
+ {
+ break;
+ }
+
+ offset -= jump2.InstSize - ReservedBytesForJump;
+ }
}
- }
- else
- {
- for (int index2 = index + 1; index2 < _jumps.Count; index2++)
+ else
{
- Jump jump2 = _jumps[index2];
-
- if (jump2.JumpPosition >= jumpTarget)
+ for (int index2 = index + 1; index2 < _jumps.Count; index2++)
{
- break;
+ Jump jump2 = _jumps[index2];
+
+ if (jump2.JumpPosition >= jumpTarget)
+ {
+ break;
+ }
+
+ offset += jump2.InstSize - ReservedBytesForJump;
}
- offset += jump2.InstSize - ReservedBytesForJump;
+ offset -= ReservedBytesForJump;
}
- offset -= ReservedBytesForJump;
- }
+ if (jump.IsConditional)
+ {
+ jump.InstSize = Assembler.GetJccLength(offset);
+ }
+ else
+ {
+ jump.InstSize = Assembler.GetJmpLength(offset);
+ }
- if (jump.IsConditional)
- {
- jump.InstSize = Assembler.GetJccLength(offset);
+ // The jump is relative to the next instruction, not the current one.
+ // Since we didn't know the next instruction address when calculating
+ // the offset (as the size of the current jump instruction was not known),
+ // we now need to compensate the offset with the jump instruction size.
+ // It's also worth noting that:
+ // - This is only needed for backward jumps.
+ // - The GetJmpLength and GetJccLength also compensates the offset
+ // internally when computing the jump instruction size.
+ if (offset < 0)
+ {
+ offset -= jump.InstSize;
+ }
}
else
{
- jump.InstSize = Assembler.GetJmpLength(offset);
- }
-
- // The jump is relative to the next instruction, not the current one.
- // Since we didn't know the next instruction address when calculating
- // the offset (as the size of the current jump instruction was not know),
- // we now need to compensate the offset with the jump instruction size.
- // It's also worth to note that:
- // - This is only needed for backward jumps.
- // - The GetJmpLength and GetJccLength also compensates the offset
- // internally when computing the jump instruction size.
- if (offset < 0)
- {
offset -= jump.InstSize;
}
@@ -267,7 +299,7 @@ namespace ARMeilleure.CodeGen.X86
using (MemoryStream codeStream = new MemoryStream())
{
- Assembler assembler = new Assembler(codeStream);
+ Assembler assembler = new Assembler(codeStream, _ptcInfo);
byte[] buffer;
@@ -278,7 +310,7 @@ namespace ARMeilleure.CodeGen.X86
buffer = new byte[jump.JumpPosition - _stream.Position];
_stream.Read(buffer, 0, buffer.Length);
- _stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
+ _stream.Seek(_ptcDisabled ? ReservedBytesForJump : jump.InstSize, SeekOrigin.Current);
codeStream.Write(buffer);
@@ -298,6 +330,8 @@ namespace ARMeilleure.CodeGen.X86
codeStream.Write(buffer);
+ _ptcInfo?.WriteCode(codeStream);
+
return codeStream.ToArray();
}
}
diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
index 0faba6dd..e7e7553e 100644
--- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs
+++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
@@ -5,6 +5,7 @@ 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;
@@ -100,7 +101,7 @@ namespace ARMeilleure.CodeGen.X86
_instTable[(int)inst] = func;
}
- public static CompiledFunction Generate(CompilerContext cctx)
+ public static CompiledFunction Generate(CompilerContext cctx, PtcInfo ptcInfo = null)
{
ControlFlowGraph cfg = cctx.Cfg;
@@ -158,10 +159,12 @@ namespace ARMeilleure.CodeGen.X86
using (MemoryStream stream = new MemoryStream())
{
- CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count);
+ CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count, ptcInfo);
UnwindInfo unwindInfo = WritePrologue(context);
+ ptcInfo?.WriteUnwindInfo(unwindInfo);
+
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{
context.EnterBlock(block);