diff options
| author | Simon Atanasyan <simon@atanasyan.com> | 2019-08-23 13:36:14 +0000 |
|---|---|---|
| committer | Simon Atanasyan <simon@atanasyan.com> | 2019-08-23 13:36:14 +0000 |
| commit | 58492b1895e23869253592544ae87f58742013e3 (patch) | |
| tree | c853c979734c2bd1b7a0a55e58ce952c00080d88 /llvm/lib | |
| parent | 57ae79d7a25cbb9f542bea55b9cb629abb80174e (diff) | |
| download | bcm5719-llvm-58492b1895e23869253592544ae87f58742013e3.tar.gz bcm5719-llvm-58492b1895e23869253592544ae87f58742013e3.zip | |
[mips] Do not include offset into `%got` expression for global symbols
Now pseudo instruction `la $6, symbol+8($6)` is expanding into the following
chain of commands:
```
lw $1, %got(symbol+8)($gp)
addiu $1, $1, 8
addu $6, $1, $6
```
This is incorrect. When a linker handles the `R_MIPS_GOT16` relocation,
it does not expect to get any addend and breaks on assertion. Otherwise
it has to create new GOT entry for each unique "sym + offset" pair.
Offset for a global symbol should be added to result of loading GOT
entry by a separate `add` command.
The patch fixes the problem by stripping off an offset from the expression
passed to the `%got`. That's interesting that even current code inserts
a separate `add` command.
Differential Revision: https://reviews.llvm.org/D66552
llvm-svn: 369755
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 32 |
1 files changed, 18 insertions, 14 deletions
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 54c88ab5781..09dc73b061e 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -2884,16 +2884,18 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, return true; } + bool IsLocalSym = + Res.getSymA()->getSymbol().isInSection() || + Res.getSymA()->getSymbol().isTemporary() || + (Res.getSymA()->getSymbol().isELF() && + cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() == + ELF::STB_LOCAL); + // 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. 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))) { + Res.getConstant() == 0 && !IsLocalSym) { const MCExpr *CallExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr), @@ -2902,8 +2904,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, } // The remaining cases are: - // External GOT: lw $tmp, %got(symbol+offset)($gp) - // >addiu $tmp, $tmp, %lo(offset) + // 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) @@ -2911,17 +2913,19 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, // 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 = - MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext()); + const MipsMCExpr *GotExpr = nullptr; const MCExpr *LoExpr = nullptr; - if (Res.getSymA()->getSymbol().isInSection() || - Res.getSymA()->getSymbol().isTemporary()) + if (IsLocalSym) { + GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext()); LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); - else if (Res.getConstant() != 0) { + } 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. - LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); + GotExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(), getContext()); + if (Res.getConstant() != 0) + LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); } unsigned TmpReg = DstReg; |

