cranelift: Implement TLS on aarch64 Mach-O (Apple Silicon) (#5434)

* Implement TLS on Aarch64 Mach-O

* Add aarch64 macho TLS filetest

* Address review comments

- `Aarch64` instead of `AArch64` in comments
- Remove unnecessary guard in tls_value lowering
- Remove unnecessary regalloc metadata in emission

* Use x1 as temporary register in emission

- Instead of passing in a temporary register to use when emitting
the TLS code, just use `x1`, as it's already in the clobber set.
This also keeps the size of `aarch64::inst::Inst` at 32 bytes.
- Update filetest accordingly

* Update aarch64 mach-o TLS filetest
This commit is contained in:
Nathan Whitaker
2023-03-24 10:54:01 -07:00
committed by GitHub
parent d0570a77ce
commit c3decdf910
7 changed files with 173 additions and 4 deletions

View File

@@ -3458,6 +3458,54 @@ impl MachInstEmit for Inst {
sink.put4(0xd503201f);
}
&Inst::MachOTlsGetAddr { ref symbol, rd } => {
// Each thread local variable gets a descriptor, where the first xword of the descriptor is a pointer
// to a function that takes the descriptor address in x0, and after the function returns x0
// contains the address for the thread local variable
//
// what we want to emit is basically:
//
// adrp x0, <label>@TLVPPAGE ; Load the address of the page of the thread local variable pointer (TLVP)
// ldr x0, [x0, <label>@TLVPPAGEOFF] ; Load the descriptor's address into x0
// ldr x1, [x0] ; Load the function pointer (the first part of the descriptor)
// blr x1 ; Call the function pointer with the descriptor address in x0
// ; x0 now contains the TLV address
let rd = allocs.next_writable(rd);
assert_eq!(xreg(0), rd.to_reg());
let rtmp = writable_xreg(1);
// adrp x0, <label>@TLVPPAGE
sink.add_reloc(Reloc::MachOAarch64TlsAdrPage21, symbol, 0);
sink.put4(0x90000000);
// ldr x0, [x0, <label>@TLVPPAGEOFF]
sink.add_reloc(Reloc::MachOAarch64TlsAdrPageOff12, symbol, 0);
sink.put4(0xf9400000);
// load [x0] into temp register
Inst::ULoad64 {
rd: rtmp,
mem: AMode::reg(rd.to_reg()),
flags: MemFlags::trusted(),
}
.emit(&[], sink, emit_info, state);
// call function pointer in temp register
Inst::CallInd {
info: crate::isa::Box::new(CallIndInfo {
rn: rtmp.to_reg(),
uses: smallvec![],
defs: smallvec![],
clobbers: PRegSet::empty(),
opcode: Opcode::CallIndirect,
caller_callconv: CallConv::AppleAarch64,
callee_callconv: CallConv::AppleAarch64,
}),
}
.emit(&[], sink, emit_info, state);
}
&Inst::Unwind { ref inst } => {
sink.add_unwind(inst.clone());
}