forked from OSchip/llvm-project
[mips] Reduce code duplication in the `loadAndAddSymbolAddress`. NFC
llvm-svn: 372218
This commit is contained in:
parent
4b8b7f249c
commit
59d0cc82b5
|
@ -2877,7 +2877,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||
SrcReg != Mips::ZERO_64;
|
||||
warnIfNoMacro(IDLoc);
|
||||
|
||||
if (inPicMode() && ABI.IsO32()) {
|
||||
if (inPicMode()) {
|
||||
MCValue Res;
|
||||
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
||||
Error(IDLoc, "expected relocatable expression");
|
||||
|
@ -2888,6 +2888,7 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool IsPtr64 = ABI.ArePtrs64bit();
|
||||
bool IsLocalSym =
|
||||
Res.getSymA()->getSymbol().isInSection() ||
|
||||
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
|
||||
// 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 &&
|
||||
Res.getConstant() == 0 && !IsLocalSym) {
|
||||
const MCExpr *CallExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
||||
IDLoc, STI);
|
||||
TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, DstReg, GPReg,
|
||||
MCOperand::createExpr(CallExpr), IDLoc, STI);
|
||||
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 MCExpr *LoExpr = nullptr;
|
||||
if (IsLocalSym) {
|
||||
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
||||
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||
} else {
|
||||
// External symbols fully resolve the symbol with just the %got(symbol)
|
||||
// but we must still account for any offset to the symbol for expressions
|
||||
// like symbol+8.
|
||||
GotExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(), getContext());
|
||||
if (Res.getConstant() != 0)
|
||||
if (IsPtr64) {
|
||||
// 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.
|
||||
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, Res.getSymA(),
|
||||
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());
|
||||
}
|
||||
|
||||
unsigned TmpReg = DstReg;
|
||||
if (UseSrcReg &&
|
||||
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
|
||||
SrcReg)) {
|
||||
// If $rs is the same as $rd, we need to use AT.
|
||||
// If it is not available we exit.
|
||||
unsigned ATReg = getATReg(IDLoc);
|
||||
if (!ATReg)
|
||||
return true;
|
||||
TmpReg = ATReg;
|
||||
}
|
||||
|
||||
TOut.emitRRX(Mips::LW, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
||||
STI);
|
||||
|
||||
if (LoExpr)
|
||||
TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
||||
IDLoc, STI);
|
||||
|
||||
if (UseSrcReg)
|
||||
TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (inPicMode() && ABI.ArePtrs64bit()) {
|
||||
MCValue Res;
|
||||
if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
|
||||
Error(IDLoc, "expected relocatable expression");
|
||||
return true;
|
||||
}
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 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.
|
||||
if (IsLocalSym) {
|
||||
GotExpr =
|
||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
||||
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||
} else {
|
||||
// External symbols fully resolve the symbol with just the %got(symbol)
|
||||
// but we must still account for any offset to the symbol for
|
||||
// expressions like symbol+8.
|
||||
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(),
|
||||
getContext());
|
||||
if (Res.getConstant() != 0)
|
||||
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3023,15 +2973,16 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||
TmpReg = ATReg;
|
||||
}
|
||||
|
||||
TOut.emitRRX(Mips::LD, TmpReg, GPReg, MCOperand::createExpr(GotExpr), IDLoc,
|
||||
STI);
|
||||
TOut.emitRRX(IsPtr64 ? Mips::LD : Mips::LW, TmpReg, GPReg,
|
||||
MCOperand::createExpr(GotExpr), IDLoc, STI);
|
||||
|
||||
if (LoExpr)
|
||||
TOut.emitRRX(Mips::DADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
|
||||
IDLoc, STI);
|
||||
TOut.emitRRX(IsPtr64 ? Mips::DADDiu : Mips::ADDiu, TmpReg, TmpReg,
|
||||
MCOperand::createExpr(LoExpr), IDLoc, STI);
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue