Skip to content

Commit

Permalink
[mips] Use MipsMCExpr instead of MCSymbolRefExpr for all relocations.
Browse files Browse the repository at this point in the history
Summary:
This is much closer to the way MIPS relocation expressions work
(%hi(foo + 2) rather than %hi(foo) + 2) and removes the need for the
various bodges in MipsAsmParser::evaluateRelocExpr().

Removing those bodges ensures that the constant stored in MCValue is the
full 32 or 64-bit (depending on ABI) offset from the symbol. This will be used
to correct the %hi/%lo matching needed to sort the relocation table correctly.

As part of this:
* Gave MCExpr::print() the ability to omit parenthesis when emitting a
  symbol reference inside a MipsMCExpr operator like %hi(X). Without this
  we print things like %lo(($L1)).
* %hi(%neg(%gprel(X))) is now three MipsMCExpr's instead of one. Most of
  the related special cases have been removed or moved to MipsMCExpr. We
  can remove the rest as we gain support for the less common relocations
  when they are not part of this specific combination.
* Renamed MipsMCExpr::VariantKind and the enum prefix ('VK_') to avoid confusion
  with MCSymbolRefExpr::VariantKind and its prefix (also 'VK_').
* fixup_Mips_GOT_Local and fixup_Mips_GOT_Global were found to be identical
  and merged into fixup_Mips_GOT.
* MO_GOT16 and MO_GOT turned out to be identical and have been merged into
  MO_GOT.
* VK_Mips_GOT and VK_Mips_GOT16 turned out to be the same thing so they
  have been merged into MEK_GOT

Reviewers: sdardis

Subscribers: dsanders, sdardis, llvm-commits

Differential Revision: http://reviews.llvm.org/D19716

llvm-svn: 268379
  • Loading branch information
dsandersllvm committed May 3, 2016
1 parent 32e78c3 commit fe98b2f
Show file tree
Hide file tree
Showing 29 changed files with 710 additions and 599 deletions.
30 changes: 2 additions & 28 deletions llvm/include/llvm/MC/MCExpr.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ class MCExpr {
/// \name Utility Methods
/// @{

void print(raw_ostream &OS, const MCAsmInfo *MAI) const;
void print(raw_ostream &OS, const MCAsmInfo *MAI,
bool InParens = false) const;
void dump() const;

/// @}
Expand Down Expand Up @@ -250,33 +251,6 @@ class MCSymbolRefExpr : public MCExpr {
VK_PPC_TLSLD, // symbol@tlsld
VK_PPC_LOCAL, // symbol@local

VK_Mips_GPREL,
VK_Mips_GOT_CALL,
VK_Mips_GOT16,
VK_Mips_GOT,
VK_Mips_ABS_HI,
VK_Mips_ABS_LO,
VK_Mips_TLSGD,
VK_Mips_TLSLDM,
VK_Mips_DTPREL_HI,
VK_Mips_DTPREL_LO,
VK_Mips_GOTTPREL,
VK_Mips_TPREL_HI,
VK_Mips_TPREL_LO,
VK_Mips_GPOFF_HI,
VK_Mips_GPOFF_LO,
VK_Mips_GOT_DISP,
VK_Mips_GOT_PAGE,
VK_Mips_GOT_OFST,
VK_Mips_HIGHER,
VK_Mips_HIGHEST,
VK_Mips_GOT_HI16,
VK_Mips_GOT_LO16,
VK_Mips_CALL_HI16,
VK_Mips_CALL_LO16,
VK_Mips_PCREL_HI16,
VK_Mips_PCREL_LO16,

VK_COFF_IMGREL32, // symbol@imgrel (image-relative)

VK_Hexagon_PCREL,
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/MC/ELFObjectWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,6 @@ bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm,
case MCSymbolRefExpr::VK_GOT:
case MCSymbolRefExpr::VK_PLT:
case MCSymbolRefExpr::VK_GOTPCREL:
case MCSymbolRefExpr::VK_Mips_GOT:
case MCSymbolRefExpr::VK_PPC_GOT_LO:
case MCSymbolRefExpr::VK_PPC_GOT_HI:
case MCSymbolRefExpr::VK_PPC_GOT_HA:
Expand Down
4 changes: 0 additions & 4 deletions llvm/lib/MC/MCELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -412,10 +412,6 @@ void MCELFStreamer::fixSymbolsInTLSFixups(const MCExpr *expr) {
case MCSymbolRefExpr::VK_TPREL:
case MCSymbolRefExpr::VK_DTPOFF:
case MCSymbolRefExpr::VK_DTPREL:
case MCSymbolRefExpr::VK_Mips_TLSGD:
case MCSymbolRefExpr::VK_Mips_GOTTPREL:
case MCSymbolRefExpr::VK_Mips_TPREL_HI:
case MCSymbolRefExpr::VK_Mips_TPREL_LO:
case MCSymbolRefExpr::VK_PPC_DTPMOD:
case MCSymbolRefExpr::VK_PPC_TPREL_LO:
case MCSymbolRefExpr::VK_PPC_TPREL_HI:
Expand Down
31 changes: 3 additions & 28 deletions llvm/lib/MC/MCExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ STATISTIC(MCExprEvaluate, "Number of MCExpr evaluations");
}
}

void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI, bool InParens) const {
switch (getKind()) {
case MCExpr::Target:
return cast<MCTargetExpr>(this)->printImpl(OS, MAI);
Expand All @@ -43,7 +43,8 @@ void MCExpr::print(raw_ostream &OS, const MCAsmInfo *MAI) const {
const MCSymbol &Sym = SRE.getSymbol();
// Parenthesize names that start with $ so that they don't look like
// absolute names.
bool UseParens = Sym.getName().size() && Sym.getName()[0] == '$';
bool UseParens =
!InParens && Sym.getName().size() && Sym.getName()[0] == '$';
if (UseParens) {
OS << '(';
Sym.print(OS, MAI);
Expand Down Expand Up @@ -264,32 +265,6 @@ StringRef MCSymbolRefExpr::getVariantKindName(VariantKind Kind) {
case VK_PPC_GOT_TLSLD_HA: return "got@tlsld@ha";
case VK_PPC_TLSLD: return "tlsld";
case VK_PPC_LOCAL: return "local";
case VK_Mips_GPREL: return "GPREL";
case VK_Mips_GOT_CALL: return "GOT_CALL";
case VK_Mips_GOT16: return "GOT16";
case VK_Mips_GOT: return "GOT";
case VK_Mips_ABS_HI: return "ABS_HI";
case VK_Mips_ABS_LO: return "ABS_LO";
case VK_Mips_TLSGD: return "TLSGD";
case VK_Mips_TLSLDM: return "TLSLDM";
case VK_Mips_DTPREL_HI: return "DTPREL_HI";
case VK_Mips_DTPREL_LO: return "DTPREL_LO";
case VK_Mips_GOTTPREL: return "GOTTPREL";
case VK_Mips_TPREL_HI: return "TPREL_HI";
case VK_Mips_TPREL_LO: return "TPREL_LO";
case VK_Mips_GPOFF_HI: return "GPOFF_HI";
case VK_Mips_GPOFF_LO: return "GPOFF_LO";
case VK_Mips_GOT_DISP: return "GOT_DISP";
case VK_Mips_GOT_PAGE: return "GOT_PAGE";
case VK_Mips_GOT_OFST: return "GOT_OFST";
case VK_Mips_HIGHER: return "HIGHER";
case VK_Mips_HIGHEST: return "HIGHEST";
case VK_Mips_GOT_HI16: return "GOT_HI16";
case VK_Mips_GOT_LO16: return "GOT_LO16";
case VK_Mips_CALL_HI16: return "CALL_HI16";
case VK_Mips_CALL_LO16: return "CALL_LO16";
case VK_Mips_PCREL_HI16: return "PCREL_HI16";
case VK_Mips_PCREL_LO16: return "PCREL_LO16";
case VK_COFF_IMGREL32: return "IMGREL";
case VK_Hexagon_PCREL: return "PCREL";
case VK_Hexagon_LO16: return "LO16";
Expand Down
179 changes: 60 additions & 119 deletions llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,8 +303,6 @@ class MipsAsmParser : public MCTargetAsmParser {

bool parseInternalDirectiveReallowModule();

MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);

bool eatComma(StringRef ErrorStr);

int matchCPURegisterName(StringRef Symbol);
Expand Down Expand Up @@ -1631,9 +1629,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");

// FIXME: This is checking the expression can be handled by the later stages
// of the assembler. We ought to leave it to those later stages but
// we can't do that until we stop evaluateRelocExpr() rewriting the
// expressions into non-equivalent forms.
// of the assembler. We ought to leave it to those later stages.
const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);

// FIXME: Add support for label+offset operands (currently causes an error).
Expand All @@ -1647,8 +1643,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// addiu $25, $25, 0
// R_(MICRO)MIPS_LO16 label
// jalr $25
const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
const MCExpr *Got16RelocExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
const MCExpr *Lo16RelocExpr =
MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());

TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
Expand All @@ -1660,7 +1658,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_GOT_DISP label
// jalr $25
const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
const MCExpr *GotDispRelocExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());

TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
Expand All @@ -1671,7 +1670,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_CALL16 label
// jalr $25
const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
const MCExpr *Call16RelocExpr =
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());

TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
Expand Down Expand Up @@ -2337,10 +2337,10 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
warnIfNoMacro(IDLoc);

const MCExpr *Symbol = cast<MCExpr>(SymExpr);
const MipsMCExpr *HiExpr = MipsMCExpr::create(
MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
const MipsMCExpr *LoExpr = MipsMCExpr::create(
MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
const MipsMCExpr *HiExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HI, Symbol, getContext());
const MipsMCExpr *LoExpr =
MipsMCExpr::create(MipsMCExpr::MEK_LO, Symbol, getContext());

bool UseSrcReg = SrcReg != Mips::NoRegister;

Expand All @@ -2352,10 +2352,10 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
if (!ATReg)
return true;

const MipsMCExpr *HighestExpr = MipsMCExpr::create(
MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
const MipsMCExpr *HigherExpr = MipsMCExpr::create(
MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
const MipsMCExpr *HighestExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, Symbol, getContext());
const MipsMCExpr *HigherExpr =
MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, Symbol, getContext());

if (UseSrcReg &&
getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
Expand Down Expand Up @@ -2575,10 +2575,10 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}

const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
MCOperand LoOperand =
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
MCOperand HiOperand =
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
MCOperand LoOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
MCOperand HiOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));

// Try to use DstReg as the temporary.
if (IsGPR && (BaseReg != DstReg)) {
Expand Down Expand Up @@ -2616,10 +2616,10 @@ void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
}

const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
MCOperand LoOperand =
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo"));
MCOperand HiOperand =
MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi"));
MCOperand LoOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
MCOperand HiOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
LoOperand, ATReg, IDLoc, STI);
}
Expand Down Expand Up @@ -4073,64 +4073,41 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {

const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
StringRef RelocStr) {
const MCExpr *Res;
// Check the type of the expression.
if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
// It's a constant, evaluate reloc value.
int16_t Val;
switch (getVariantKind(RelocStr)) {
case MCSymbolRefExpr::VK_Mips_ABS_LO:
// Get the 1st 16-bits.
Val = MCE->getValue() & 0xffff;
break;
case MCSymbolRefExpr::VK_Mips_ABS_HI:
case MCSymbolRefExpr::VK_Mips_GOT:
// Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
// 16 bits being negative.
Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
break;
case MCSymbolRefExpr::VK_Mips_HIGHER:
// Get the 3rd 16-bits.
Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
break;
case MCSymbolRefExpr::VK_Mips_HIGHEST:
// Get the 4th 16-bits.
Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
break;
default:
report_fatal_error("unsupported reloc value");
}
return MCConstantExpr::create(Val, getContext());
}

if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
// It's a symbol, create a symbolic expression from the symbol.
const MCSymbol *Symbol = &MSRE->getSymbol();
MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
return Res;
}

if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);

// Try to create target expression.
if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
return MipsMCExpr::create(VK, Expr, getContext());

const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
return Res;
}

if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
return Res;
}
// Just return the original expression.
return Expr;
if (RelocStr == "hi(%neg(%gp_rel")
return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
else if (RelocStr == "lo(%neg(%gp_rel")
return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());

MipsMCExpr::MipsExprKind Kind =
StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
.Case("call16", MipsMCExpr::MEK_GOT_CALL)
.Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
.Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
.Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
.Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
.Case("got", MipsMCExpr::MEK_GOT)
.Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
.Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
.Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
.Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
.Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
.Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
.Case("gp_rel", MipsMCExpr::MEK_GPREL)
.Case("hi", MipsMCExpr::MEK_HI)
.Case("higher", MipsMCExpr::MEK_HIGHER)
.Case("highest", MipsMCExpr::MEK_HIGHEST)
.Case("lo", MipsMCExpr::MEK_LO)
.Case("neg", MipsMCExpr::MEK_NEG)
.Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
.Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
.Case("tlsgd", MipsMCExpr::MEK_TLSGD)
.Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
.Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
.Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
.Default(MipsMCExpr::MEK_None);

assert(Kind != MipsMCExpr::MEK_None);
return MipsMCExpr::create(Kind, Expr, getContext());
}

bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
Expand Down Expand Up @@ -4733,42 +4710,6 @@ MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
return MatchOperand_Success;
}

MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {

MCSymbolRefExpr::VariantKind VK =
StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
.Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
.Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
.Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
.Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
.Case("got", MCSymbolRefExpr::VK_Mips_GOT)
.Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
.Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
.Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
.Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
.Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
.Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
.Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
.Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
.Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
.Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
.Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
.Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
.Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
.Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
.Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
.Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
.Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
.Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
.Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
.Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
.Default(MCSymbolRefExpr::VK_None);

assert(VK != MCSymbolRefExpr::VK_None);

return VK;
}

/// Sometimes (i.e. load/stores) the operand may be followed immediately by
/// either this.
/// ::= '(', register, ')'
Expand Down
Loading

0 comments on commit fe98b2f

Please sign in to comment.