1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[mips] Reduce code duplication in the loadAndAddSymbolAddress. NFC

llvm-svn: 372218
This commit is contained in:
Simon Atanasyan 2019-09-18 12:24:23 +00:00
parent 5b325c0c9d
commit fa04b58fc7

View File

@ -2877,7 +2877,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
SrcReg != Mips::ZERO_64; SrcReg != Mips::ZERO_64;
warnIfNoMacro(IDLoc); warnIfNoMacro(IDLoc);
if (inPicMode() && ABI.IsO32()) { if (inPicMode()) {
MCValue Res; MCValue Res;
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
Error(IDLoc, "expected relocatable expression"); Error(IDLoc, "expected relocatable expression");
@ -2888,6 +2888,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
return true; return true;
} }
bool IsPtr64 = ABI.ArePtrs64bit();
bool IsLocalSym = bool IsLocalSym =
Res.getSymA()->getSymbol().isInSection() || Res.getSymA()->getSymbol().isInSection() ||
Res.getSymA()->getSymbol().isTemporary() || Res.getSymA()->getSymbol().isTemporary() ||
@ -2897,117 +2898,66 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
// The case where the result register is $25 is somewhat special. If the // The case where the result register is $25 is somewhat special. If the
// symbol in the final relocation is external and not modified with a // symbol in the final relocation is external and not modified with a
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16. // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16
// or R_MIPS_CALL16 instead of R_MIPS_GOT_DISP in 64-bit case.
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg && if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Res.getConstant() == 0 && !IsLocalSym) { Res.getConstant() == 0 && !IsLocalSym) {
const MCExpr *CallExpr = const MCExpr *CallExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr), TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
IDLoc, STI); MCOperand::createExpr(CallExpr), IDLoc, STI);
return false; return false;
} }
// The remaining cases are:
// External GOT: lw $tmp, %got(symbol)($gp)
// >addiu $tmp, $tmp, offset
// >addiu $rd, $tmp, $rs
// Local GOT: lw $tmp, %got(symbol+offset)($gp)
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
// >addiu $rd, $tmp, $rs
// The addiu's marked with a '>' may be omitted if they are redundant. If
// this happens then the last instruction must use $rd as the result
// register.
const MipsMCExpr *GotExpr = nullptr; const MipsMCExpr *GotExpr = nullptr;
const MCExpr *LoExpr = nullptr; const MCExpr *LoExpr = nullptr;
if (IsLocalSym) { if (IsPtr64) {
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext()); // The remaining cases are:
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); // Small offset: ld $tmp, %got_disp(symbol)($gp)
} else { // >daddiu $tmp, $tmp, offset
// External symbols fully resolve the symbol with just the %got(symbol) // >daddu $rd, $tmp, $rs
// but we must still account for any offset to the symbol for expressions // The daddiu's marked with a '>' may be omitted if they are redundant. If
// like symbol+8. // this happens then the last instruction must use $rd as the result
GotExpr = // register.
MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(), getContext()); GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
if (Res.getConstant() != 0) getContext());
if (Res.getConstant() != 0) {
// Symbols fully resolve with just the %got_disp(symbol) but we
// must still account for any offset to the symbol for
// expressions like symbol+8.
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
}
unsigned TmpReg = DstReg; // FIXME: Offsets greater than 16 bits are not yet implemented.
if (UseSrcReg && // FIXME: The correct range is a 32-bit sign-extended number.
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
SrcReg)) { Error(IDLoc, "macro instruction uses large offset, which is not "
// If $rs is the same as $rd, we need to use AT. "currently supported");
// If it is not available we exit. return true;
unsigned ATReg = getATReg(IDLoc); }
if (!ATReg) }
return true; } else {
TmpReg = ATReg; // The remaining cases are:
} // External GOT: lw $tmp, %got(symbol)($gp)
// >addiu $tmp, $tmp, offset
TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, // >addiu $rd, $tmp, $rs
STI); // Local GOT: lw $tmp, %got(symbol+offset)($gp)
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
if (LoExpr) // >addiu $rd, $tmp, $rs
TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), // The addiu's marked with a '>' may be omitted if they are redundant. If
IDLoc, STI); // this happens then the last instruction must use $rd as the result
// register.
if (UseSrcReg) if (IsLocalSym) {
TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); GotExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
return false; LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
} } else {
// External symbols fully resolve the symbol with just the %got(symbol)
if (inPicMode() && ABI.ArePtrs64bit()) { // but we must still account for any offset to the symbol for
MCValue Res; // expressions like symbol+8.
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
Error(IDLoc, "expected relocatable expression"); getContext());
return true; if (Res.getConstant() != 0)
} LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
if (Res.getSymB() != nullptr) {
Error(IDLoc, "expected relocatable expression with only one symbol");
return true;
}
// The case where the result register is $25 is somewhat special. If the
// symbol in the final relocation is external and not modified with a
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT_DISP.
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
Res.getConstant() == 0 &&
!(Res.getSymA()->getSymbol().isInSection() ||
Res.getSymA()->getSymbol().isTemporary() ||
(Res.getSymA()->getSymbol().isELF() &&
cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
ELF::STB_LOCAL))) {
const MCExpr *CallExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
TOut.emitRRX(Mips::LD, DstReg, GPReg, MCOperand::createExpr(CallExpr),
IDLoc, STI);
return false;
}
// The remaining cases are:
// Small offset: ld $tmp, %got_disp(symbol)($gp)
// >daddiu $tmp, $tmp, offset
// >daddu $rd, $tmp, $rs
// The daddiu's marked with a '>' may be omitted if they are redundant. If
// this happens then the last instruction must use $rd as the result
// register.
const MipsMCExpr *GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP,
Res.getSymA(),
getContext());
const MCExpr *LoExpr = nullptr;
if (Res.getConstant() != 0) {
// Symbols fully resolve with just the %got_disp(symbol) but we
// must still account for any offset to the symbol for
// expressions like symbol+8.
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
// FIXME: Offsets greater than 16 bits are not yet implemented.
// FIXME: The correct range is a 32-bit sign-extended number.
if (Res.getConstant() < -0x8000 || Res.getConstant() > 0x7fff) {
Error(IDLoc, "macro instruction uses large offset, which is not "
"currently supported");
return true;
} }
} }
@ -3023,15 +2973,16 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
TmpReg = ATReg; TmpReg = ATReg;
} }
TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc, TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
STI); MCOperand::createExpr(GotExpr), IDLoc, STI);
if (LoExpr) if (LoExpr)
TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
IDLoc, STI); MCOperand::createExpr(LoExpr), IDLoc, STI);
if (UseSrcReg) if (UseSrcReg)
TOut.emitRRR(Mips::DADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); TOut.emitRRR(IsPtr64 ? Mips::DADDu : Mips::ADDu, DstReg, TmpReg, SrcReg,
IDLoc, STI);
return false; return false;
} }