Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Support for ARM64 on UNIX like systems compiler and runtime #8271

Merged
merged 42 commits into from
Aug 27, 2020
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
a056f09
Merge pull request #1 from dotnet/master
RalfKornmannEnvision Jul 17, 2020
a8d26b2
CoreRT-ARM64: Helper node asm code generation
RalfKornmannEnvision Jul 20, 2020
6c4b87b
CoreRT ARM64: Add additional relocation support
RalfKornmannEnvision Jul 21, 2020
404f4ed
CoreRT ARM64: Use alternative functions for write Barriers
RalfKornmannEnvision Jul 21, 2020
9d4c4cb
ARM64 code generation
RalfKornmannEnvision Aug 3, 2020
20021cb
unwind use only the dwarf index option
RalfKornmannEnvision Aug 3, 2020
39c6ceb
ARM64 runtime assembler functions
RalfKornmannEnvision Aug 3, 2020
6c9e235
ARM64 unix stack walk
RalfKornmannEnvision Aug 4, 2020
aba22ac
ARM64 Exception Handling
RalfKornmannEnvision Aug 4, 2020
5b6bea5
ARM64: Fix EH data decodeing
RalfKornmannEnvision Aug 6, 2020
86a4b8b
Move nattive layout signature from read only to data section on non W…
RalfKornmannEnvision Aug 14, 2020
f98ba02
Fix exception handling macro call
RalfKornmannEnvision Aug 14, 2020
f289d85
ARM64 thunk helpers
RalfKornmannEnvision Aug 14, 2020
986f61a
ARM64 process cfi data for elf
RalfKornmannEnvision Aug 17, 2020
b1481d6
ARM64 missing assembler macro
RalfKornmannEnvision Aug 17, 2020
5f3bb34
ARM64 port more assembler helpers
RalfKornmannEnvision Aug 17, 2020
2fe1f65
ARM64: Add missing case for the gemeric helper node
RalfKornmannEnvision Aug 17, 2020
11817b2
ARM64 intrinsic support
RalfKornmannEnvision Aug 18, 2020
08e0d52
ARM64 object writer for ELF object files
RalfKornmannEnvision Aug 18, 2020
083ee8c
ARM64 llvm patches for object writer
RalfKornmannEnvision Aug 18, 2020
b8d0123
ARM64 include untested helper code with debug break
RalfKornmannEnvision Aug 18, 2020
e70d94e
ARM64 reenable scanning fail exception
RalfKornmannEnvision Aug 19, 2020
ee068b2
Arm64 Support (#2)
RalfKornmannEnvision Aug 19, 2020
7f19a17
Merge pull request #3 from dotnet/master
RalfKornmannEnvision Aug 19, 2020
996d034
Merge pull request #4 from RalfKornmannEnvision/master
RalfKornmannEnvision Aug 19, 2020
d5766e0
ARM64 formating
RalfKornmannEnvision Aug 20, 2020
c0afb01
ARM64: revert using alternative JIT
RalfKornmannEnvision Aug 20, 2020
7c79156
Merge branch 'ARM64' of https://github.com/RalfKornmannEnvision/corer…
RalfKornmannEnvision Aug 20, 2020
2bf04e1
Arm64 (#5)
RalfKornmannEnvision Aug 20, 2020
c68cea1
Revert "ARM64 unix stack walk"
RalfKornmannEnvision Aug 20, 2020
bbecadc
Arm64 (#6)
RalfKornmannEnvision Aug 20, 2020
37ce540
Revert "Revert "ARM64 unix stack walk""
RalfKornmannEnvision Aug 20, 2020
d1cf628
Revert "Revert "Revert "ARM64 unix stack walk"""
RalfKornmannEnvision Aug 20, 2020
be9d9e6
ARM64 review reworks
RalfKornmannEnvision Aug 20, 2020
bc488c3
Arm64 (#7)
RalfKornmannEnvision Aug 20, 2020
d9d12f7
ARM64 Fix wrong function call for invoke return
RalfKornmannEnvision Aug 24, 2020
30b59ef
Merge pull request #8 from RalfKornmannEnvision/ARM64
RalfKornmannEnvision Aug 24, 2020
2bc790b
ARM64: Ensure module fixup node data is aligned
RalfKornmannEnvision Aug 25, 2020
d0836ec
Merge pull request #9 from RalfKornmannEnvision/ARM64
RalfKornmannEnvision Aug 25, 2020
65f6dff
Arm64: review reworks (#10)
RalfKornmannEnvision Aug 27, 2020
ca7d15a
Arm64 (#11)
RalfKornmannEnvision Aug 27, 2020
a83496e
Update src/Native/Runtime/arm64/WriteBarriers.S
jkotas Aug 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,16 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)

public int Offset => 0;
protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler);
public override ObjectNodeSection Section => ObjectNodeSection.ReadOnlyDataSection;
public override ObjectNodeSection Section
{
get
{
if (_identity.Context.Target.IsWindows)
return ObjectNodeSection.ReadOnlyDataSection;
else
return ObjectNodeSection.DataSection;
}
}
public override bool IsShareable => false;
public override bool StaticDependenciesAreComputed => true;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,7 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
// Do not vacate space for this kind of relocation, because
// the space is embedded in the instruction.
break;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1040,10 +1040,10 @@ public static void EmitObject(string objectFilePath, IEnumerable<DependencyNode>
// Build symbol definition map.
objectWriter.BuildSymbolDefinitionMap(node, nodeContents.DefinedSymbols);

// The DWARF CFI unwind is implemented for AMD64 & ARM32 only.
// The DWARF CFI unwind is only implemented for some architectures.
TargetArchitecture tarch = factory.Target.Architecture;
if (!factory.Target.IsWindows &&
(tarch == TargetArchitecture.X64 || tarch == TargetArchitecture.ARM))
(tarch == TargetArchitecture.X64 || tarch == TargetArchitecture.ARM || tarch == TargetArchitecture.ARM64))
objectWriter.BuildCFIMap(factory, node);

// Build debug location map
Expand Down Expand Up @@ -1089,17 +1089,24 @@ public static void EmitObject(string objectFilePath, IEnumerable<DependencyNode>
}
int size = objectWriter.EmitSymbolReference(reloc.Target, (int)delta, reloc.RelocType);

// Emit a copy of original Thumb2 instruction that came from RyuJIT
if (reloc.RelocType == RelocType.IMAGE_REL_BASED_THUMB_MOV32 ||
reloc.RelocType == RelocType.IMAGE_REL_BASED_THUMB_BRANCH24)
// Emit a copy of original Thumb2/ARM64 instruction that came from RyuJIT

switch (reloc.RelocType)
{
unsafe
{
fixed (void* location = &nodeContents.Data[i])
case RelocType.IMAGE_REL_BASED_THUMB_MOV32:
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
unsafe
{
objectWriter.EmitBytes((IntPtr)location, size);
fixed (void* location = &nodeContents.Data[i])
{
objectWriter.EmitBytes((IntPtr)location, size);
}
}
}
break;
}

// Update nextRelocIndex/Offset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb)
public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
{
ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly);
builder.RequireInitialPointerAlignment();

builder.AddSymbol(this);

ISymbolNode nameSymbol = factory.ConstantUtf8String(_pInvokeModuleData.ModuleName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,45 @@ private static unsafe void PutArm64Rel12(uint* pCode, int imm12)
Debug.Assert(GetArm64Rel12(pCode) == imm12);
}

private static unsafe int GetArm64Rel28(uint* pCode)
{
uint branchInstr = *pCode;

// first shift 6 bits left to set the sign bit,
// then arithmetic shift right by 4 bits
int imm28 = (((int)(branchInstr & 0x03FFFFFF)) << 6) >> 4;

return imm28;
}

private static bool FitsInArm64Rel28(long imm28)
{
return (imm28 >= -0x08000000L) && (imm28 < 0x08000000L);
}

private static unsafe void PutArm64Rel28(uint* pCode, long imm28)
{
// Verify that we got a valid offset
Debug.Assert(FitsInArm64Rel28(imm28));

Debug.Assert((imm28 & 0x3) == 0); // the low two bits must be zero

uint branchInstr = *pCode;

branchInstr &= 0xFC000000; // keep bits 31-26

Debug.Assert((branchInstr & 0x7FFFFFFF) == 0x14000000); // Must be B or BL

// Assemble the pc-relative delta 'imm28' into the branch instruction
branchInstr |= (uint)(((imm28 >> 2) & 0x03FFFFFFU));

*pCode = branchInstr; // write the assembled instruction

Debug.Assert(GetArm64Rel28(pCode) == imm28);
}



public Relocation(RelocType relocType, int offset, ISymbolNode target)
{
RelocType = relocType;
Expand Down Expand Up @@ -286,6 +325,9 @@ public static unsafe void WriteValue(RelocType relocType, void* location, long v
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
PutThumb2BlRel24((ushort*)location, (uint)value);
break;
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
PutArm64Rel28((uint*)location, value);
break;
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
PutArm64Rel21((uint*)location, (int)value);
break;
Expand Down Expand Up @@ -318,6 +360,8 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return (long)GetThumb2Mov32((ushort*)location);
case RelocType.IMAGE_REL_BASED_THUMB_BRANCH24:
return (long)GetThumb2BlRel24((ushort*)location);
case RelocType.IMAGE_REL_BASED_ARM64_BRANCH26:
return (long)GetArm64Rel28((uint*)location);
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
return GetArm64Rel21((uint*)location);
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public void EmitMOV(Register regDst, ref AddrMode memory)

public void EmitMOV(Register regDst, Register regSrc)
{
throw new NotImplementedException();
Builder.EmitUInt((uint)(0b1_0_1_01010_000_00000_000000_11111_00000u | ((uint)regSrc << 16) | (uint)regDst));
}

public void EmitMOV(Register regDst, ushort imm16)
Expand All @@ -35,6 +35,17 @@ public void EmitMOV(Register regDst, ushort imm16)
Builder.EmitUInt(instruction);
}

public void EmitMOV(Register regDst, ISymbolNode symbol)
{
// ADRP regDst, [symbol (21bit ADRP thing)]
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21);
Builder.EmitUInt(0x90000000u | (byte)regDst);

// Add regDst, (12bit LDR page offset reloc)
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A);
Builder.EmitUInt((uint)(0b1_0_0_100010_0_000000000000_00000_00000 | ((byte)regDst << 5) | (byte)regDst));
}

// ldr regDst, [PC + imm19]
public void EmitLDR(Register regDst, short offset)
{
Expand All @@ -54,6 +65,25 @@ public void EmitLDR(Register regDst, Register regAddr)
Builder.EmitUInt(instruction);
}

public void EmitLDR(Register regDst, Register regSrc, int offset)
{
Debug.Assert(offset >= -255 && offset <= 4095);
if (offset >= 0)
{
Debug.Assert(offset % 8 == 0);

offset /= 8;

Builder.EmitUInt((uint)(0b11_1110_0_1_0_1_000000000000_00000_00000u | ((uint)offset << 10) | ((uint)regSrc << 5) | (uint)regDst));
}
else
{
uint o = (uint)offset & 0x1FF;

Builder.EmitUInt((uint)(0b11_1110_0_0_010_000000000_1_1_00000_00000u | (o << 12) | ((uint)regSrc << 5) | (uint)regDst));
}
}

public void EmitLEAQ(Register reg, ISymbolNode symbol, int delta = 0)
{
throw new NotImplementedException();
Expand All @@ -69,12 +99,38 @@ public void EmitCMP(ref AddrMode addrMode, sbyte immediate)
throw new NotImplementedException();
}

public void EmitCMP(Register reg, sbyte immediate)
{
if (immediate >= 0)
{
Builder.EmitUInt((uint)(0b1_1_1_100010_0_000000000000_00000_11111u | immediate << 10) | ((uint)reg << 5));
}
else
{
throw new NotImplementedException();
}
}

// add reg, immediate
public void EmitADD(Register reg, byte immediate)
{
Builder.EmitInt((int)(0x91 << 24) | (immediate << 10) | ((byte)reg << 5) | (byte) reg);
}

public void EmitSUB(Register reg, int immediate)
{
if (immediate >= 0)
{
Debug.Assert(immediate % 4 == 0);

Builder.EmitUInt((uint)(0b1_1_0_100010_0_000000000000_00000_00000u | immediate << 10) | ((uint)reg << 5) | (uint)reg);
}
else
{
throw new NotImplementedException();
}
}

public void EmitJMP(ISymbolNode symbol)
{
if (symbol.RepresentsIndirectionCell)
Expand All @@ -100,9 +156,14 @@ public void EmitJMP(ISymbolNode symbol)
}
}

public void EmitJMP(Register reg)
{
Builder.EmitUInt((uint)(0b11010110_0_0_0_11111_00000_0_00000_00000u | ((uint)reg << 5)));
}

public void EmitINT3()
{
throw new NotImplementedException();
Builder.EmitUInt(0b11010100_001_1111111111111111_000_0_0);
}

public void EmitJmpToAddrMode(ref AddrMode addrMode)
Expand All @@ -112,12 +173,13 @@ public void EmitJmpToAddrMode(ref AddrMode addrMode)

public void EmitRET()
{
throw new NotImplementedException();
Builder.EmitUInt(0b11010110_0_1_0_11111_00000_0_11110_00000);
}

public void EmitRETIfEqual()
{
throw new NotImplementedException();
Builder.EmitUInt(0b01010100_0000000000000000010_0_0001u);
EmitRET();
}

private bool InSignedByteRange(int i)
Expand Down
Loading