mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-08 12:21:04 +00:00
[RISCV] Support assembling TLS LA pseudo instructions
This patch adds the pseudo instructions la.tls.ie and la.tls.gd, used in the initial-exec and global-dynamic TLS models respectively when addressing a global. The pseudo instructions are expanded in the assembly parser. llvm-svn: 361499
This commit is contained in:
parent
89d96c0ab3
commit
cb0e54a9ab
@ -93,6 +93,14 @@ class RISCVAsmParser : public MCTargetAsmParser {
|
||||
// Helper to emit pseudo instruction "la" used in GOT/PC-rel addressing.
|
||||
void emitLoadAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
|
||||
|
||||
// Helper to emit pseudo instruction "la.tls.ie" used in initial-exec TLS
|
||||
// addressing.
|
||||
void emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
|
||||
|
||||
// Helper to emit pseudo instruction "la.tls.gd" used in global-dynamic TLS
|
||||
// addressing.
|
||||
void emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out);
|
||||
|
||||
// Helper to emit pseudo load/store instruction with a symbol.
|
||||
void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc,
|
||||
MCStreamer &Out, bool HasTmpReg);
|
||||
@ -1590,6 +1598,35 @@ void RISCVAsmParser::emitLoadAddress(MCInst &Inst, SMLoc IDLoc,
|
||||
emitAuipcInstPair(DestReg, DestReg, Symbol, VKHi, SecondOpcode, IDLoc, Out);
|
||||
}
|
||||
|
||||
void RISCVAsmParser::emitLoadTLSIEAddress(MCInst &Inst, SMLoc IDLoc,
|
||||
MCStreamer &Out) {
|
||||
// The load TLS IE address pseudo-instruction "la.tls.ie" is used in
|
||||
// initial-exec TLS model addressing of global symbols:
|
||||
// la.tls.ie rdest, symbol
|
||||
// expands to
|
||||
// TmpLabel: AUIPC rdest, %tls_ie_pcrel_hi(symbol)
|
||||
// Lx rdest, %pcrel_lo(TmpLabel)(rdest)
|
||||
MCOperand DestReg = Inst.getOperand(0);
|
||||
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
|
||||
unsigned SecondOpcode = isRV64() ? RISCV::LD : RISCV::LW;
|
||||
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GOT_HI,
|
||||
SecondOpcode, IDLoc, Out);
|
||||
}
|
||||
|
||||
void RISCVAsmParser::emitLoadTLSGDAddress(MCInst &Inst, SMLoc IDLoc,
|
||||
MCStreamer &Out) {
|
||||
// The load TLS GD address pseudo-instruction "la.tls.gd" is used in
|
||||
// global-dynamic TLS model addressing of global symbols:
|
||||
// la.tls.gd rdest, symbol
|
||||
// expands to
|
||||
// TmpLabel: AUIPC rdest, %tls_gd_pcrel_hi(symbol)
|
||||
// ADDI rdest, rdest, %pcrel_lo(TmpLabel)
|
||||
MCOperand DestReg = Inst.getOperand(0);
|
||||
const MCExpr *Symbol = Inst.getOperand(1).getExpr();
|
||||
emitAuipcInstPair(DestReg, DestReg, Symbol, RISCVMCExpr::VK_RISCV_TLS_GD_HI,
|
||||
RISCV::ADDI, IDLoc, Out);
|
||||
}
|
||||
|
||||
void RISCVAsmParser::emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode,
|
||||
SMLoc IDLoc, MCStreamer &Out,
|
||||
bool HasTmpReg) {
|
||||
@ -1657,6 +1694,12 @@ bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
|
||||
case RISCV::PseudoLA:
|
||||
emitLoadAddress(Inst, IDLoc, Out);
|
||||
return false;
|
||||
case RISCV::PseudoLA_TLS_IE:
|
||||
emitLoadTLSIEAddress(Inst, IDLoc, Out);
|
||||
return false;
|
||||
case RISCV::PseudoLA_TLS_GD:
|
||||
emitLoadTLSGDAddress(Inst, IDLoc, Out);
|
||||
return false;
|
||||
case RISCV::PseudoLB:
|
||||
emitLoadStoreSymbol(Inst, RISCV::LB, IDLoc, Out, /*HasTmpReg=*/false);
|
||||
return false;
|
||||
|
@ -926,6 +926,16 @@ let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
|
||||
def PseudoLA : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
|
||||
"la", "$dst, $src">;
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
|
||||
isAsmParserOnly = 1 in
|
||||
def PseudoLA_TLS_IE : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
|
||||
"la.tls.ie", "$dst, $src">;
|
||||
|
||||
let hasSideEffects = 0, mayLoad = 1, mayStore = 0, isCodeGenOnly = 0,
|
||||
isAsmParserOnly = 1 in
|
||||
def PseudoLA_TLS_GD : Pseudo<(outs GPR:$dst), (ins bare_symbol:$src), [],
|
||||
"la.tls.gd", "$dst, $src">;
|
||||
|
||||
/// Loads
|
||||
|
||||
multiclass LdPat<PatFrag LoadOp, RVInst Inst> {
|
||||
|
@ -1,9 +1,11 @@
|
||||
# RUN: llvm-mc %s -triple=riscv32 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC
|
||||
# RUN: llvm-mc %s -triple=riscv64 | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC
|
||||
# RUN: llvm-mc %s -triple=riscv32 \
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC,CHECK-RV32
|
||||
# RUN: llvm-mc %s -triple=riscv64 \
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-NOPIC,CHECK-RV64
|
||||
# RUN: llvm-mc %s -triple=riscv32 -position-independent \
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV32
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-RV32,CHECK-PIC-RV32
|
||||
# RUN: llvm-mc %s -triple=riscv64 -position-independent \
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-PIC-RV64
|
||||
# RUN: | FileCheck %s --check-prefixes=CHECK,CHECK-PIC,CHECK-RV64,CHECK-PIC-RV64
|
||||
|
||||
# CHECK: .Lpcrel_hi0:
|
||||
# CHECK: auipc a0, %pcrel_hi(a_symbol)
|
||||
@ -73,47 +75,104 @@ la a3, ra
|
||||
la a4, f1
|
||||
|
||||
# CHECK: .Lpcrel_hi10:
|
||||
# CHECK: auipc a0, %pcrel_hi(a_symbol)
|
||||
# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi10)(a0)
|
||||
lb a0, a_symbol
|
||||
# CHECK: auipc a0, %tls_ie_pcrel_hi(a_symbol)
|
||||
# CHECK-RV32: lw a0, %pcrel_lo(.Lpcrel_hi10)(a0)
|
||||
# CHECK-RV64: ld a0, %pcrel_lo(.Lpcrel_hi10)(a0)
|
||||
la.tls.ie a0, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi11:
|
||||
# CHECK: auipc a1, %pcrel_hi(a_symbol)
|
||||
# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi11)(a1)
|
||||
lh a1, a_symbol
|
||||
# CHECK: auipc a1, %tls_ie_pcrel_hi(another_symbol)
|
||||
# CHECK-RV32: lw a1, %pcrel_lo(.Lpcrel_hi11)(a1)
|
||||
# CHECK-RV64: ld a1, %pcrel_lo(.Lpcrel_hi11)(a1)
|
||||
la.tls.ie a1, another_symbol
|
||||
|
||||
# Check that we can load the address of symbols that are spelled like a register
|
||||
# CHECK: .Lpcrel_hi12:
|
||||
# CHECK: auipc a2, %pcrel_hi(a_symbol)
|
||||
# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi12)(a2)
|
||||
lhu a2, a_symbol
|
||||
# CHECK: auipc a2, %tls_ie_pcrel_hi(zero)
|
||||
# CHECK-RV32: lw a2, %pcrel_lo(.Lpcrel_hi12)(a2)
|
||||
# CHECK-RV64: ld a2, %pcrel_lo(.Lpcrel_hi12)(a2)
|
||||
la.tls.ie a2, zero
|
||||
|
||||
# CHECK: .Lpcrel_hi13:
|
||||
# CHECK: auipc a3, %pcrel_hi(a_symbol)
|
||||
# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3)
|
||||
lw a3, a_symbol
|
||||
# CHECK: auipc a3, %tls_ie_pcrel_hi(ra)
|
||||
# CHECK-RV32: lw a3, %pcrel_lo(.Lpcrel_hi13)(a3)
|
||||
# CHECK-RV64: ld a3, %pcrel_lo(.Lpcrel_hi13)(a3)
|
||||
la.tls.ie a3, ra
|
||||
|
||||
# CHECK: .Lpcrel_hi14:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi14)(a4)
|
||||
sb a3, a_symbol, a4
|
||||
# CHECK: auipc a4, %tls_ie_pcrel_hi(f1)
|
||||
# CHECK-RV32: lw a4, %pcrel_lo(.Lpcrel_hi14)(a4)
|
||||
# CHECK-RV64: ld a4, %pcrel_lo(.Lpcrel_hi14)(a4)
|
||||
la.tls.ie a4, f1
|
||||
|
||||
# CHECK: .Lpcrel_hi15:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi15)(a4)
|
||||
sh a3, a_symbol, a4
|
||||
# CHECK: auipc a0, %tls_gd_pcrel_hi(a_symbol)
|
||||
# CHECK: addi a0, a0, %pcrel_lo(.Lpcrel_hi15)
|
||||
la.tls.gd a0, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi16:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi16)(a4)
|
||||
sw a3, a_symbol, a4
|
||||
# CHECK: auipc a1, %tls_gd_pcrel_hi(another_symbol)
|
||||
# CHECK: addi a1, a1, %pcrel_lo(.Lpcrel_hi16)
|
||||
la.tls.gd a1, another_symbol
|
||||
|
||||
# Check that we can load the address of symbols that are spelled like a register
|
||||
# CHECK: .Lpcrel_hi17:
|
||||
# CHECK: auipc a2, %pcrel_hi(zero)
|
||||
# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi17)(a2)
|
||||
lw a2, zero
|
||||
# CHECK: auipc a2, %tls_gd_pcrel_hi(zero)
|
||||
# CHECK: addi a2, a2, %pcrel_lo(.Lpcrel_hi17)
|
||||
la.tls.gd a2, zero
|
||||
|
||||
# CHECK: .Lpcrel_hi18:
|
||||
# CHECK: auipc a3, %tls_gd_pcrel_hi(ra)
|
||||
# CHECK: addi a3, a3, %pcrel_lo(.Lpcrel_hi18)
|
||||
la.tls.gd a3, ra
|
||||
|
||||
# CHECK: .Lpcrel_hi19:
|
||||
# CHECK: auipc a4, %tls_gd_pcrel_hi(f1)
|
||||
# CHECK: addi a4, a4, %pcrel_lo(.Lpcrel_hi19)
|
||||
la.tls.gd a4, f1
|
||||
|
||||
# CHECK: .Lpcrel_hi20:
|
||||
# CHECK: auipc a0, %pcrel_hi(a_symbol)
|
||||
# CHECK: lb a0, %pcrel_lo(.Lpcrel_hi20)(a0)
|
||||
lb a0, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi21:
|
||||
# CHECK: auipc a1, %pcrel_hi(a_symbol)
|
||||
# CHECK: lh a1, %pcrel_lo(.Lpcrel_hi21)(a1)
|
||||
lh a1, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi22:
|
||||
# CHECK: auipc a2, %pcrel_hi(a_symbol)
|
||||
# CHECK: lhu a2, %pcrel_lo(.Lpcrel_hi22)(a2)
|
||||
lhu a2, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi23:
|
||||
# CHECK: auipc a3, %pcrel_hi(a_symbol)
|
||||
# CHECK: lw a3, %pcrel_lo(.Lpcrel_hi23)(a3)
|
||||
lw a3, a_symbol
|
||||
|
||||
# CHECK: .Lpcrel_hi24:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sb a3, %pcrel_lo(.Lpcrel_hi24)(a4)
|
||||
sb a3, a_symbol, a4
|
||||
|
||||
# CHECK: .Lpcrel_hi25:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sh a3, %pcrel_lo(.Lpcrel_hi25)(a4)
|
||||
sh a3, a_symbol, a4
|
||||
|
||||
# CHECK: .Lpcrel_hi26:
|
||||
# CHECK: auipc a4, %pcrel_hi(a_symbol)
|
||||
# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi26)(a4)
|
||||
sw a3, a_symbol, a4
|
||||
|
||||
# Check that we can load the address of symbols that are spelled like a register
|
||||
# CHECK: .Lpcrel_hi27:
|
||||
# CHECK: auipc a2, %pcrel_hi(zero)
|
||||
# CHECK: lw a2, %pcrel_lo(.Lpcrel_hi27)(a2)
|
||||
lw a2, zero
|
||||
|
||||
# CHECK: .Lpcrel_hi28:
|
||||
# CHECK: auipc a4, %pcrel_hi(zero)
|
||||
# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi18)(a4)
|
||||
# CHECK: sw a3, %pcrel_lo(.Lpcrel_hi28)(a4)
|
||||
sw a3, zero, a4
|
||||
|
Loading…
Reference in New Issue
Block a user