Skip to content

Commit

Permalink
inlined TLS support for linux-arm64
Browse files Browse the repository at this point in the history
  • Loading branch information
VSadov committed Jun 22, 2023
1 parent 6065863 commit e48b82b
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:

case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:

case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC:
case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR:
Debug.Assert(delta == 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,26 @@ public enum RelocType
//
// Relocation operators related to TLS access
//
IMAGE_REL_SECREL = 0x104, // 32 bit offset from base of section containing target

// Windows x64
IMAGE_REL_SECREL = 0x104,

// Linux x64
// GD model
IMAGE_REL_TLSGD = 0x105,
// LE model
IMAGE_REL_TPOFF = 0x106,

// Linux arm64
// TLSDESC (dynamic)
IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21 = 0x107,
IMAGE_REL_AARCH64_TLSDESC_LD64_LO12 = 0x108,
IMAGE_REL_AARCH64_TLSDESC_ADD_LO12 = 0x109,
IMAGE_REL_AARCH64_TLSDESC_CALL = 0x10A,
// LE model
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x10B,
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x10C,

//
// Relocations for R2R image production
//
Expand Down Expand Up @@ -483,6 +499,20 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
return GetArm64Rel21((uint*)location);
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
return GetArm64Rel12((uint*)location);
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
// TLS relocs do not have offsets
Debug.Assert((GetArm64Rel12((uint*)location) & 0xFF) == 0);
return 0;
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
// TLS relocs do not have offsets
Debug.Assert((GetArm64Rel21((uint*)location) & 0xFF) == 0);
return 0;
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
// TLS relocs do not have offsets
return 0;
case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC:
return (long)GetLoongArch64PC12((uint*)location);
case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,18 @@ public void EmitRET()

public void EmitRETIfEqual()
{
// b.ne #8
Builder.EmitUInt(0b01010100_0000000000000000010_0_0001u);
EmitRET();
}

public void EmitRETIfNotEqual()
{
// b.eq #8
Builder.EmitUInt(0b01010100_0000000000000000010_0_0000u);
EmitRET();
}

public void EmitJE(ISymbolNode symbol)
{
uint offset = symbol.RepresentsIndirectionCell ? 6u : 2u;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,13 @@ public static void EmitObject(string objectFilePath, IReadOnlyCollection<Depende
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:

case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
unsafe
{
fixed (void* location = &nodeContents.Data[i])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,76 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder,
// may trash volatile registers. (there are calls to the slow helper and possibly to the platform's TLS support)
private static void EmitInlineTLSAccess(NodeFactory factory, ref ARM64Emitter encoder)
{
throw new NotImplementedException();
ISymbolNode getInlinedThreadStaticBaseSlow = factory.HelperEntrypoint(HelperEntrypoint.GetInlinedThreadStaticBaseSlow);
ISymbolNode tlsRoot = factory.TlsRoot;
// IsSingleFileCompilation is not enough to guarantee that we can use "Initial Executable" optimizations.
// we need a special compiler flag analogous to /GA. Just assume "false" for now.
// bool singleFileExe = factory.CompilationModuleGroup.IsSingleFileCompilation;
bool singleFileExe = false;

if (factory.Target.OperatingSystem == TargetOS.Linux)
{
if (singleFileExe)
{
// mrs x0, tpidr_el0
encoder.Builder.EmitUInt(0xd53bd040);

// add x0, x0, #:tprel_hi12:tlsRoot, lsl #12
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12);
encoder.Builder.EmitUInt(0x91400000);

// add x1, x0, #:tprel_lo12_nc:tlsRoot, lsl #0
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC);
encoder.Builder.EmitUInt(0x91000001);
}
else
{
// stp x29, x30, [sp, -16]!
encoder.Builder.EmitUInt(0xa9bf7bfd);
// mov x29, sp
encoder.Builder.EmitUInt(0x910003fd);

// mrs x1, tpidr_el0
encoder.Builder.EmitUInt(0xd53bd041);

// adrp x0, :tlsdesc:tlsRoot
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21);
encoder.Builder.EmitUInt(0x90000000);

// ldr x2, [x0, #:tlsdesc_lo12:tlsRoot]
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12);
encoder.Builder.EmitUInt(0xf9400002);

// add x0, x0, :tlsdesc_lo12:tlsRoot
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12);
encoder.Builder.EmitUInt(0x91000000);

// blr :tlsdesc_call:tlsRoot:x2
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL);
encoder.Builder.EmitUInt(0xd63f0040);

// add x1, x1, x0
encoder.Builder.EmitUInt(0x8b000021);

// ldp x29, x30, [sp], 16
encoder.Builder.EmitUInt(0xa8c17bfd);
}

encoder.EmitLDR(Register.X0, Register.X1);

// here we have:
// X1: addr, X0: storage
// if the storage is already allocated, just return, otherwise do slow path.

encoder.EmitCMP(Register.X0, 0);
encoder.EmitRETIfNotEqual();
encoder.EmitMOV(Register.X0, Register.X1);
encoder.EmitJMP(getInlinedThreadStaticBaseSlow);
}
else
{
throw new NotImplementedException();
}
}
}
}
2 changes: 1 addition & 1 deletion src/coreclr/tools/aot/ILCompiler/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ void RunScanner()

// If we have a scanner, we can inline threadstatics storage using the information we collected at scanning time.
if (!Get(_command.NoInlineTls) &&
(targetArchitecture == TargetArchitecture.X64 && (targetOS == TargetOS.Windows || targetOS == TargetOS.Linux)))
(targetOS == TargetOS.Linux || (targetArchitecture == TargetArchitecture.X64 && targetOS == TargetOS.Windows)))
{
builder.UseInlinedThreadStatics(scanResults.GetInlinedThreadStatics());
}
Expand Down

0 comments on commit e48b82b

Please sign in to comment.