mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-30 05:29:47 +00:00
My original support for the general dynamic and local dynamic TLS models contained some fairly obtuse hacks to generate calls to __tls_get_addr when lowering a TargetGlobalAddress. Rather than generating real calls, special GET_TLS_ADDR nodes were used to wrap the calls and only reveal them at assembly time. I attempted to provide correct parameter and return values by chaining CopyToReg and CopyFromReg nodes onto the GET_TLS_ADDR nodes, but this was also not fully correct. Problems were seen with two back-to-back stores to TLS variables, where the call sequences ended up overlapping with unhappy results. Additionally, since these weren't real calls, the proper register side effects of a call were not recorded, so clobbered values were kept live across the calls. The proper thing to do is to lower these into calls in the first place. This is relatively straightforward; see the changes to PPCTargetLowering::LowerGlobalTLSAddress() in PPCISelLowering.cpp. The changes here are standard call lowering, except that we need to track the fact that these calls will require a relocation. This is done by adding a machine operand flag of MO_TLSLD or MO_TLSGD to the TargetGlobalAddress operand that appears earlier in the sequence. The calls to LowerCallTo() eventually find their way to LowerCall_64SVR4() or LowerCall_32SVR4(), which call FinishCall(), which calls PrepareCall(). In PrepareCall(), we detect the calls to __tls_get_addr and immediately snag the TargetGlobalTLSAddress with the annotated relocation information. This becomes an extra operand on the call following the callee, which is expected for nodes of type tlscall. We change the call opcode to CALL_TLS for this case. Back in FinishCall(), we change it again to CALL_NOP_TLS for 64-bit only, since we require a TOC-restore nop following the call for the 64-bit ABIs. During selection, patterns in PPCInstrInfo.td and PPCInstr64Bit.td convert the CALL_TLS nodes into BL_TLS nodes, and convert the CALL_NOP_TLS nodes into BL8_NOP_TLS nodes. This replaces the code removed from PPCAsmPrinter.cpp, as the BL_TLS or BL8_NOP_TLS nodes can now be emitted normally using their patterns and the associated printTLSCall print method. Finally, as a result of these changes, all references to get-tls-addr in its various guises are no longer used, so they have been removed. There are existing TLS tests to verify the changes haven't messed anything up). I've added one new test that verifies that the problem with the original code has been fixed. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@221703 91177308-0d34-0410-b5e6-96231b3b80d8
34 lines
1.0 KiB
LLVM
34 lines
1.0 KiB
LLVM
; RUN: llc -march=ppc64 -mcpu=pwr7 -O2 -relocation-model=pic < %s | FileCheck %s
|
|
|
|
target datalayout = "e-m:e-i64:64-n32:64"
|
|
target triple = "powerpc64le-unknown-linux-gnu"
|
|
|
|
; Test back-to-back stores of TLS variables to ensure call sequences no
|
|
; longer overlap.
|
|
|
|
@__once_callable = external thread_local global i8**
|
|
@__once_call = external thread_local global void ()*
|
|
|
|
define i64 @call_once(i64 %flag, i8* %ptr) {
|
|
entry:
|
|
%var = alloca i8*, align 8
|
|
store i8* %ptr, i8** %var, align 8
|
|
store i8** %var, i8*** @__once_callable, align 8
|
|
store void ()* @__once_call_impl, void ()** @__once_call, align 8
|
|
ret i64 %flag
|
|
}
|
|
|
|
; CHECK-LABEL: call_once:
|
|
; CHECK: addis 3, 2, __once_callable@got@tlsgd@ha
|
|
; CHECK: addi 3, 3, __once_callable@got@tlsgd@l
|
|
; CHECK: bl __tls_get_addr(__once_callable@tlsgd)
|
|
; CHECK-NEXT: nop
|
|
; CHECK: std {{[0-9]+}}, 0(3)
|
|
; CHECK: addis 3, 2, __once_call@got@tlsgd@ha
|
|
; CHECK: addi 3, 3, __once_call@got@tlsgd@l
|
|
; CHECK: bl __tls_get_addr(__once_call@tlsgd)
|
|
; CHECK-NEXT: nop
|
|
; CHECK: std {{[0-9]+}}, 0(3)
|
|
|
|
declare void @__once_call_impl()
|