forked from OSchip/llvm-project
[X86] Add REX prefix for GOTTPOFF/TLSDESC relocs in x32 mode
The REX prefix is needed to allow linker relaxations: even if the instruction we emit may not need it, the linker may change it to a different instruction which does need it.
This commit is contained in:
parent
e9cda7c5a0
commit
2aae2136d5
|
@ -93,7 +93,8 @@ private:
|
|||
bool emitOpcodePrefix(int MemOperand, const MCInst &MI,
|
||||
const MCSubtargetInfo &STI, raw_ostream &OS) const;
|
||||
|
||||
bool emitREXPrefix(int MemOperand, const MCInst &MI, raw_ostream &OS) const;
|
||||
bool emitREXPrefix(int MemOperand, const MCInst &MI,
|
||||
const MCSubtargetInfo &STI, raw_ostream &OS) const;
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
@ -1201,6 +1202,7 @@ void X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
|
|||
///
|
||||
/// \returns true if REX prefix is used, otherwise returns false.
|
||||
bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
|
||||
const MCSubtargetInfo &STI,
|
||||
raw_ostream &OS) const {
|
||||
uint8_t REX = [&, MemOperand]() {
|
||||
uint8_t REX = 0;
|
||||
|
@ -1221,15 +1223,28 @@ bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
|
|||
// If it accesses SPL, BPL, SIL, or DIL, then it requires a 0x40 REX prefix.
|
||||
for (unsigned i = CurOp; i != NumOps; ++i) {
|
||||
const MCOperand &MO = MI.getOperand(i);
|
||||
if (!MO.isReg())
|
||||
continue;
|
||||
unsigned Reg = MO.getReg();
|
||||
if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
|
||||
UsesHighByteReg = true;
|
||||
if (X86II::isX86_64NonExtLowByteReg(Reg))
|
||||
// FIXME: The caller of determineREXPrefix slaps this prefix onto
|
||||
// anything that returns non-zero.
|
||||
REX |= 0x40; // REX fixed encoding prefix
|
||||
if (MO.isReg()) {
|
||||
unsigned Reg = MO.getReg();
|
||||
if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH ||
|
||||
Reg == X86::DH)
|
||||
UsesHighByteReg = true;
|
||||
if (X86II::isX86_64NonExtLowByteReg(Reg))
|
||||
// FIXME: The caller of determineREXPrefix slaps this prefix onto
|
||||
// anything that returns non-zero.
|
||||
REX |= 0x40; // REX fixed encoding prefix
|
||||
} else if (MO.isExpr() &&
|
||||
STI.getTargetTriple().getEnvironment() == Triple::GNUX32) {
|
||||
// GOTTPOFF and TLSDESC relocations require a REX prefix to allow
|
||||
// linker optimizations: even if the instructions we see may not require
|
||||
// any prefix, they may be replaced by instructions that do. This is
|
||||
// handled as a special case here so that it also works for hand-written
|
||||
// assembly without the user needing to write REX, as with GNU as.
|
||||
const auto *Ref = dyn_cast<MCSymbolRefExpr>(MO.getExpr());
|
||||
if (Ref && (Ref->getKind() == MCSymbolRefExpr::VK_GOTTPOFF ||
|
||||
Ref->getKind() == MCSymbolRefExpr::VK_TLSDESC)) {
|
||||
REX |= 0x40; // REX fixed encoding prefix
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch (TSFlags & X86II::FormMask) {
|
||||
|
@ -1352,7 +1367,7 @@ bool X86MCCodeEmitter::emitOpcodePrefix(int MemOperand, const MCInst &MI,
|
|||
assert((STI.hasFeature(X86::Mode64Bit) || !(TSFlags & X86II::REX_W)) &&
|
||||
"REX.W requires 64bit mode.");
|
||||
bool HasREX = STI.hasFeature(X86::Mode64Bit)
|
||||
? emitREXPrefix(MemOperand, MI, OS)
|
||||
? emitREXPrefix(MemOperand, MI, STI, OS)
|
||||
: false;
|
||||
|
||||
// 0x0F escape code must be emitted just before the opcode.
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
# RUN: llvm-mc -triple x86_64-pc-linux-gnux32 %s | FileCheck --check-prefix=PRINT %s
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnux32 %s -o %t
|
||||
# RUN: llvm-readelf -s %t | FileCheck --check-prefix=SYM %s
|
||||
# RUN: llvm-objdump -d -r %t | FileCheck --match-full-lines %s
|
||||
|
||||
# PRINT: leal a@tlsdesc(%rip), %eax
|
||||
# PRINT-NEXT: callq *a@tlscall(%eax)
|
||||
|
||||
# SYM: TLS GLOBAL DEFAULT UND a
|
||||
|
||||
# CHECK: 0: 40 8d 05 00 00 00 00 leal (%rip), %eax # 7 <{{.*}}>
|
||||
# CHECK-NEXT: 00000003: R_X86_64_GOTPC32_TLSDESC a-0x4
|
||||
# CHECK-NEXT: 7: 67 ff 10 callq *(%eax)
|
||||
# CHECK-NEXT: 00000007: R_X86_64_TLSDESC_CALL a
|
||||
# CHECK-NEXT: a: 8d 05 34 12 00 00 leal 4660(%rip), %eax # {{.*}}
|
||||
|
||||
lea a@tlsdesc(%rip), %eax
|
||||
call *a@tlscall(%eax)
|
||||
lea 0x1234(%rip), %eax
|
Loading…
Reference in New Issue