Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Bred <bredpetr@gmail.com>2017-09-20 23:23:13 +0300
committerJan Kotas <jkotas@microsoft.com>2017-09-20 23:23:13 +0300
commitbcf05f3933d1584a6618c5eb1d14f846a5f5d798 (patch)
tree7c615ecd2895ad3f434edf93d98a43bdf86db0c9 /src/ILCompiler.Compiler
parent3c882b0ed8bc355d07156632f6dd6e96de7a1c35 (diff)
Adding inspections to ARM emitter (#4578)
Signed-off-by: Petr Bred <bredpetr@gmail.com>
Diffstat (limited to 'src/ILCompiler.Compiler')
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs68
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs14
-rw-r--r--src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs20
3 files changed, 71 insertions, 31 deletions
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs
index 96cd53b78..535f13fce 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMEmitter.cs
@@ -18,31 +18,55 @@ namespace ILCompiler.DependencyAnalysis.ARM
public ObjectDataBuilder Builder;
public TargetRegisterMap TargetRegister;
+ // check the value length
+ private static bool IsBitNumOverflow(int value, byte numBits)
+ {
+ return (value >> numBits) != 0;
+ }
+
+ private static bool IsLowReg(Register reg)
+ {
+ return !IsBitNumOverflow((int)reg, 3);
+ }
+
+ private static bool IsValidReg(Register reg)
+ {
+ return !IsBitNumOverflow((int)reg, 4);
+ }
+
// mov reg, immediate
- // reg range: 0-7
- public void EmitMOV(Register reg, byte immediate)
+ // reg range: [0..7]
+ // immediage range: [0..255]
+ public void EmitMOV(Register reg, int immediate)
{
+ Debug.Assert(IsLowReg(reg) && !IsBitNumOverflow(immediate, 8));
Builder.EmitShort((short)(0x2000 + ((byte)reg << 8) + immediate));
}
// cmp reg, immediate
- // reg range: 0-7
- public void EmitCMP(Register reg, byte immediate)
+ // reg range: [0..7]
+ // immediage range: [0..255]
+ public void EmitCMP(Register reg, int immediate)
{
+ Debug.Assert(IsLowReg(reg) && !IsBitNumOverflow(immediate, 8));
Builder.EmitShort((short)(0x2800 + ((byte)reg << 8) + immediate));
}
// add reg, immediate
- // reg range: 0-7
- public void EmitADD(Register reg, byte immediate)
+ // reg range: [0..7]
+ // immediage range: [0..255]
+ public void EmitADD(Register reg, int immediate)
{
+ Debug.Assert(IsLowReg(reg) && !IsBitNumOverflow(immediate, 8));
Builder.EmitShort((short)(0x3000 + ((byte)reg << 8) + immediate));
}
// sub reg, immediate
- // reg range: 0-7
- public void EmitSUB(Register reg, byte immediate)
+ // reg range: [0..7]
+ // immediage range: [0..255]
+ public void EmitSUB(Register reg, int immediate)
{
+ Debug.Assert(IsLowReg(reg) && !IsBitNumOverflow(immediate, 8));
Builder.EmitShort((short)(0x3800 + ((byte)reg << 8) + immediate));
}
@@ -61,38 +85,48 @@ namespace ILCompiler.DependencyAnalysis.ARM
}
// push reg
+ // reg range: [0..12, LR]
public void EmitPUSH(Register reg)
{
+ Debug.Assert(reg >= Register.R0 && (reg <= Register.R12 || reg == TargetRegister.LR));
Builder.EmitByte(0x4d);
Builder.EmitByte(0xf8);
Builder.EmitShort((short)(0x0d04 + ((byte)reg << 12)));
}
// pop reg
+ // reg range: [0..12, LR, PC]
public void EmitPOP(Register reg)
{
+ Debug.Assert(IsValidReg(reg) && reg != TargetRegister.SP);
Builder.EmitByte(0x5d);
Builder.EmitByte(0xf8);
Builder.EmitShort((short)(0x0b04 + ((byte)reg << 12)));
}
// mov reg, reg
+ // reg range: [0..PC]
public void EmitMOV(Register destination, Register source)
{
+ Debug.Assert(IsValidReg(destination) && IsValidReg(source));
Builder.EmitShort((short)(0x4600 + (((byte)destination & 0x8) << 4) + (((byte)source & 0x8) << 3) + (((byte)source & 0x7) << 3) + ((byte)destination & 0x7)));
}
// ldr reg, [reg]
- // reg range: 0-7
+ // reg range: [0..7]
public void EmitLDR(Register destination, Register source)
{
+ Debug.Assert(IsLowReg(destination) && IsLowReg(source));
Builder.EmitShort((short)(0x6800 + (((byte)source & 0x7) << 3) + ((byte)destination & 0x7)));
}
// ldr.w reg, [reg, #offset]
+ // reg range: [0..PC]
// offset range: [-255..4095]
- public void EmitLDR(Register destination, Register source, short offset)
+ public void EmitLDR(Register destination, Register source, int offset)
{
+ Debug.Assert(IsValidReg(destination) && IsValidReg(source));
+ Debug.Assert(offset >= -255 && offset <= 4095);
if (offset >= 0)
{
Builder.EmitShort((short)(0xf8d0 + ((byte)(source))));
@@ -105,10 +139,12 @@ namespace ILCompiler.DependencyAnalysis.ARM
}
}
- // mov reg, [reloc] & 0x0000FFFF
+ // movw reg, [reloc] & 0x0000FFFF
// movt reg, [reloc] & 0xFFFF0000
+ // reg range: [0..12, LR]
public void EmitMOV(Register destination, ISymbolNode symbol)
{
+ Debug.Assert(destination >= Register.R0 && (destination <= Register.R12 || destination == TargetRegister.LR));
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_THUMB_MOV32);
Builder.EmitShort(unchecked((short)0xf240));
Builder.EmitShort((short)((byte)destination << 8));
@@ -116,7 +152,7 @@ namespace ILCompiler.DependencyAnalysis.ARM
Builder.EmitShort((short)((byte)destination << 8));
}
- // b symbol
+ // b.w symbol
public void EmitJMP(ISymbolNode symbol)
{
Debug.Assert(!symbol.RepresentsIndirectionCell);
@@ -128,8 +164,10 @@ namespace ILCompiler.DependencyAnalysis.ARM
}
// bx reg
+ // reg range: [0..PC]
public void EmitJMP(Register destination)
{
+ Debug.Assert(IsValidReg(destination));
Builder.EmitShort((short)(0x4700 + ((byte)destination << 3)));
}
@@ -141,8 +179,9 @@ namespace ILCompiler.DependencyAnalysis.ARM
// bne #offset
// offset range: [-256..254]
- public void EmitBNE(short immediate)
+ public void EmitBNE(int immediate)
{
+ Debug.Assert(immediate >= -256 && immediate <= 254);
// considering the pipeline with PC
immediate -= 4;
@@ -152,8 +191,9 @@ namespace ILCompiler.DependencyAnalysis.ARM
// beq #offset
// offset range: [-256..254]
- public void EmitBEQ(short immediate)
+ public void EmitBEQ(int immediate)
{
+ Debug.Assert(immediate >= -256 && immediate <= 254);
// considering the pipeline with PC
immediate -= 4;
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs
index 93e4fd8ae..287eff2be 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunGenericHelperNode.cs
@@ -35,7 +35,7 @@ namespace ILCompiler.DependencyAnalysis
}
// Load the generic dictionary cell
- encoder.EmitLDR(result, context, ((short)(dictionarySlot * factory.Target.PointerSize)));
+ encoder.EmitLDR(result, context, dictionarySlot * factory.Target.PointerSize);
switch (lookup.LookupResultReferenceType(factory))
{
@@ -125,10 +125,10 @@ namespace ILCompiler.DependencyAnalysis
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg0, nonGcRegionLookup, relocsOnly);
int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target);
- encoder.EmitSUB(encoder.TargetRegister.Arg0, ((byte)(cctorContextSize)));
+ encoder.EmitSUB(encoder.TargetRegister.Arg0, cctorContextSize);
// cmp [r0 + ptrSize], 1
- encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg0, ((short)factory.Target.PointerSize));
- encoder.EmitCMP(encoder.TargetRegister.Arg2, ((byte)1));
+ encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg0, factory.Target.PointerSize);
+ encoder.EmitCMP(encoder.TargetRegister.Arg2, 1);
encoder.EmitRETIfEqual();
encoder.EmitMOV(encoder.TargetRegister.Arg1, encoder.TargetRegister.Result);
@@ -155,7 +155,7 @@ namespace ILCompiler.DependencyAnalysis
GenericLookupResult nonGcRegionLookup = factory.GenericLookup.TypeNonGCStaticBase(target);
EmitDictionaryLookup(factory, ref encoder, encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2, nonGcRegionLookup, relocsOnly);
int cctorContextSize = NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target);
- encoder.EmitSUB(encoder.TargetRegister.Arg2, ((byte)(cctorContextSize)));
+ encoder.EmitSUB(encoder.TargetRegister.Arg2, cctorContextSize);
encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2);
helperEntrypoint = factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase);
@@ -171,7 +171,7 @@ namespace ILCompiler.DependencyAnalysis
encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg1);
// Second arg: index of the type in the ThreadStatic section of the modules
- encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg1, ((short)(factory.Target.PointerSize)));
+ encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg1, factory.Target.PointerSize);
encoder.EmitJMP(helperEntrypoint);
}
@@ -253,7 +253,7 @@ namespace ILCompiler.DependencyAnalysis
int slotOffset = EETypeNode.GetVTableOffset(pointerSize) + (vtableSlot * pointerSize);
// Load the dictionary pointer from the VTable
- encoder.EmitLDR(contextRegister, contextRegister, ((short)(slotOffset)));
+ encoder.EmitLDR(contextRegister, contextRegister, slotOffset);
}
}
}
diff --git a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
index b45306615..aadc3a376 100644
--- a/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
+++ b/src/ILCompiler.Compiler/src/Compiler/DependencyAnalysis/Target_ARM/ARMReadyToRunHelperNode.cs
@@ -45,7 +45,7 @@ namespace ILCompiler.DependencyAnalysis
encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.Arg0, 0);
encoder.EmitLDR(encoder.TargetRegister.InterproceduralScratch, encoder.TargetRegister.InterproceduralScratch,
- (short)(EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize)));
+ EETypeNode.GetVTableOffset(pointerSize) + (slot * pointerSize));
encoder.EmitJMP(encoder.TargetRegister.InterproceduralScratch);
}
break;
@@ -89,11 +89,11 @@ namespace ILCompiler.DependencyAnalysis
{
// We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region.
encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target));
- encoder.EmitSUB(encoder.TargetRegister.Arg2, ((byte)NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target)));
+ encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target));
// cmp [r2 + ptrSize], 1
- encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize));
- encoder.EmitCMP(encoder.TargetRegister.Arg3, ((byte)1));
+ encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, factory.Target.PointerSize);
+ encoder.EmitCMP(encoder.TargetRegister.Arg3, 1);
// return if cmp
encoder.EmitRETIfEqual();
@@ -115,7 +115,7 @@ namespace ILCompiler.DependencyAnalysis
encoder.EmitLDR(encoder.TargetRegister.Arg0, encoder.TargetRegister.Arg2);
// Second arg: index of the type in the ThreadStatic section of the modules
- encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize));
+ encoder.EmitLDR(encoder.TargetRegister.Arg1, encoder.TargetRegister.Arg2, factory.Target.PointerSize);
if (!factory.TypeSystemContext.HasLazyStaticConstructor(target))
{
@@ -124,7 +124,7 @@ namespace ILCompiler.DependencyAnalysis
else
{
encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target));
- encoder.EmitSUB(encoder.TargetRegister.Arg2, (byte)(NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target)));
+ encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target));
// TODO: performance optimization - inline the check verifying whether we need to trigger the cctor
encoder.EmitJMP(factory.HelperEntrypoint(HelperEntrypoint.EnsureClassConstructorRunAndReturnThreadStaticBase));
}
@@ -146,10 +146,10 @@ namespace ILCompiler.DependencyAnalysis
// We need to trigger the cctor before returning the base. It is stored at the beginning of the non-GC statics region.
encoder.EmitMOV(encoder.TargetRegister.Arg2, factory.TypeNonGCStaticsSymbol(target));
// Get cctor pointer: offset is usually equal to the double size of the pointer, therefore we can use arm sub imm
- encoder.EmitSUB(encoder.TargetRegister.Arg2, (byte)(NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target)));
+ encoder.EmitSUB(encoder.TargetRegister.Arg2, NonGCStaticsNode.GetClassConstructorContextStorageSize(factory.Target, target));
// cmp [r2 + ptrSize], 1
- encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, ((short)factory.Target.PointerSize));
- encoder.EmitCMP(encoder.TargetRegister.Arg3, (byte)1);
+ encoder.EmitLDR(encoder.TargetRegister.Arg3, encoder.TargetRegister.Arg2, factory.Target.PointerSize);
+ encoder.EmitCMP(encoder.TargetRegister.Arg3, 1);
// return if cmp
encoder.EmitRETIfEqual();
@@ -174,7 +174,7 @@ namespace ILCompiler.DependencyAnalysis
Debug.Assert(slot != -1);
encoder.EmitLDR(encoder.TargetRegister.Arg2, encoder.TargetRegister.Arg2,
- ((short)(EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize))));
+ EETypeNode.GetVTableOffset(factory.Target.PointerSize) + (slot * factory.Target.PointerSize));
}
else
{