Skip to content

Commit e48b82b

Browse files
committed
inlined TLS support for linux-arm64
1 parent 6065863 commit e48b82b

File tree

6 files changed

+125
-3
lines changed

6 files changed

+125
-3
lines changed

src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,14 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
307307
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
308308
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
309309
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
310+
311+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
312+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
313+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
314+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
315+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
316+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
317+
310318
case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC:
311319
case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR:
312320
Debug.Assert(delta == 0);

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,26 @@ public enum RelocType
3131
//
3232
// Relocation operators related to TLS access
3333
//
34-
IMAGE_REL_SECREL = 0x104, // 32 bit offset from base of section containing target
34+
35+
// Windows x64
36+
IMAGE_REL_SECREL = 0x104,
37+
38+
// Linux x64
39+
// GD model
3540
IMAGE_REL_TLSGD = 0x105,
41+
// LE model
3642
IMAGE_REL_TPOFF = 0x106,
3743

44+
// Linux arm64
45+
// TLSDESC (dynamic)
46+
IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21 = 0x107,
47+
IMAGE_REL_AARCH64_TLSDESC_LD64_LO12 = 0x108,
48+
IMAGE_REL_AARCH64_TLSDESC_ADD_LO12 = 0x109,
49+
IMAGE_REL_AARCH64_TLSDESC_CALL = 0x10A,
50+
// LE model
51+
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12 = 0x10B,
52+
IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC = 0x10C,
53+
3854
//
3955
// Relocations for R2R image production
4056
//
@@ -483,6 +499,20 @@ public static unsafe long ReadValue(RelocType relocType, void* location)
483499
return GetArm64Rel21((uint*)location);
484500
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
485501
return GetArm64Rel12((uint*)location);
502+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
503+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
504+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
505+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
506+
// TLS relocs do not have offsets
507+
Debug.Assert((GetArm64Rel12((uint*)location) & 0xFF) == 0);
508+
return 0;
509+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
510+
// TLS relocs do not have offsets
511+
Debug.Assert((GetArm64Rel21((uint*)location) & 0xFF) == 0);
512+
return 0;
513+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
514+
// TLS relocs do not have offsets
515+
return 0;
486516
case RelocType.IMAGE_REL_BASED_LOONGARCH64_PC:
487517
return (long)GetLoongArch64PC12((uint*)location);
488518
case RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR:

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,10 +176,18 @@ public void EmitRET()
176176

177177
public void EmitRETIfEqual()
178178
{
179+
// b.ne #8
179180
Builder.EmitUInt(0b01010100_0000000000000000010_0_0001u);
180181
EmitRET();
181182
}
182183

184+
public void EmitRETIfNotEqual()
185+
{
186+
// b.eq #8
187+
Builder.EmitUInt(0b01010100_0000000000000000010_0_0000u);
188+
EmitRET();
189+
}
190+
183191
public void EmitJE(ISymbolNode symbol)
184192
{
185193
uint offset = symbol.RepresentsIndirectionCell ? 6u : 2u;

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ObjectWriter.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,13 @@ public static void EmitObject(string objectFilePath, IReadOnlyCollection<Depende
10791079
case RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21:
10801080
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A:
10811081
case RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12L:
1082+
1083+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12:
1084+
case RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
1085+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21:
1086+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12:
1087+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12:
1088+
case RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL:
10821089
unsafe
10831090
{
10841091
fixed (void* location = &nodeContents.Data[i])

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/Target_ARM64/ARM64ReadyToRunHelperNode.cs

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,76 @@ protected override void EmitCode(NodeFactory factory, ref ARM64Emitter encoder,
231231
// may trash volatile registers. (there are calls to the slow helper and possibly to the platform's TLS support)
232232
private static void EmitInlineTLSAccess(NodeFactory factory, ref ARM64Emitter encoder)
233233
{
234-
throw new NotImplementedException();
234+
ISymbolNode getInlinedThreadStaticBaseSlow = factory.HelperEntrypoint(HelperEntrypoint.GetInlinedThreadStaticBaseSlow);
235+
ISymbolNode tlsRoot = factory.TlsRoot;
236+
// IsSingleFileCompilation is not enough to guarantee that we can use "Initial Executable" optimizations.
237+
// we need a special compiler flag analogous to /GA. Just assume "false" for now.
238+
// bool singleFileExe = factory.CompilationModuleGroup.IsSingleFileCompilation;
239+
bool singleFileExe = false;
240+
241+
if (factory.Target.OperatingSystem == TargetOS.Linux)
242+
{
243+
if (singleFileExe)
244+
{
245+
// mrs x0, tpidr_el0
246+
encoder.Builder.EmitUInt(0xd53bd040);
247+
248+
// add x0, x0, #:tprel_hi12:tlsRoot, lsl #12
249+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_HI12);
250+
encoder.Builder.EmitUInt(0x91400000);
251+
252+
// add x1, x0, #:tprel_lo12_nc:tlsRoot, lsl #0
253+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSLE_ADD_TPREL_LO12_NC);
254+
encoder.Builder.EmitUInt(0x91000001);
255+
}
256+
else
257+
{
258+
// stp x29, x30, [sp, -16]!
259+
encoder.Builder.EmitUInt(0xa9bf7bfd);
260+
// mov x29, sp
261+
encoder.Builder.EmitUInt(0x910003fd);
262+
263+
// mrs x1, tpidr_el0
264+
encoder.Builder.EmitUInt(0xd53bd041);
265+
266+
// adrp x0, :tlsdesc:tlsRoot
267+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_ADR_PAGE21);
268+
encoder.Builder.EmitUInt(0x90000000);
269+
270+
// ldr x2, [x0, #:tlsdesc_lo12:tlsRoot]
271+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_LD64_LO12);
272+
encoder.Builder.EmitUInt(0xf9400002);
273+
274+
// add x0, x0, :tlsdesc_lo12:tlsRoot
275+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_ADD_LO12);
276+
encoder.Builder.EmitUInt(0x91000000);
277+
278+
// blr :tlsdesc_call:tlsRoot:x2
279+
encoder.Builder.EmitReloc(tlsRoot, RelocType.IMAGE_REL_AARCH64_TLSDESC_CALL);
280+
encoder.Builder.EmitUInt(0xd63f0040);
281+
282+
// add x1, x1, x0
283+
encoder.Builder.EmitUInt(0x8b000021);
284+
285+
// ldp x29, x30, [sp], 16
286+
encoder.Builder.EmitUInt(0xa8c17bfd);
287+
}
288+
289+
encoder.EmitLDR(Register.X0, Register.X1);
290+
291+
// here we have:
292+
// X1: addr, X0: storage
293+
// if the storage is already allocated, just return, otherwise do slow path.
294+
295+
encoder.EmitCMP(Register.X0, 0);
296+
encoder.EmitRETIfNotEqual();
297+
encoder.EmitMOV(Register.X0, Register.X1);
298+
encoder.EmitJMP(getInlinedThreadStaticBaseSlow);
299+
}
300+
else
301+
{
302+
throw new NotImplementedException();
303+
}
235304
}
236305
}
237306
}

src/coreclr/tools/aot/ILCompiler/Program.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,7 +493,7 @@ void RunScanner()
493493

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

0 commit comments

Comments
 (0)