From 493b163f5d025db6a88b1dfec187c2cc9cd518a0 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Fri, 23 Aug 2019 13:36:14 +0000 Subject: [PATCH] [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 --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp | 32 ++++++++++++--------- test/MC/Mips/macro-la-pic.s | 28 ++++++++++-------- test/MC/Mips/mips-expansions.s | 8 +++--- 3 files changed, 38 insertions(+), 30 deletions(-) diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 54c88ab5781..09dc73b061e 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/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(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(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; diff --git a/test/MC/Mips/macro-la-pic.s b/test/MC/Mips/macro-la-pic.s index 5516518ba61..da8cbde0871 100644 --- a/test/MC/Mips/macro-la-pic.s +++ b/test/MC/Mips/macro-la-pic.s @@ -14,13 +14,15 @@ la $5, symbol($6) # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x8 la $6, symbol($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A] # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21] -la $5, symbol+8 # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT -la $5, symbol+8($6) # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +la $5, symbol+8 # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT + # CHECK: addiu $5, $5, 8 # encoding: [0x24,0xa5,0x00,0x08] +la $5, symbol+8($6) # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT + # CHECK: addiu $5, $5, 8 # encoding: [0x24,0xa5,0x00,0x08] # CHECK: addu $5, $5, $6 # encoding: [0x00,0xa6,0x28,0x21] -la $6, symbol+8($6) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +la $6, symbol+8($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08] # CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21] la $5, 1f # CHECK: lw $5, %got($tmp0)($gp) # encoding: [0x8f,0x85,A,A] @@ -38,13 +40,15 @@ la $25, symbol($6) # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x la $25, symbol($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A] # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21] -la $25, symbol+8 # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT -la $25, symbol+8($6) # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +la $25, symbol+8 # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x99,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT + # CHECK: addiu $25, $25, 8 # encoding: [0x27,0x39,0x00,0x08] +la $25, symbol+8($6) # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x99,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT + # CHECK: addiu $25, $25, 8 # encoding: [0x27,0x39,0x00,0x08] # CHECK: addu $25, $25, $6 # encoding: [0x03,0x26,0xc8,0x21] -la $25, symbol+8($25) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A] - # CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +la $25, symbol+8($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A] + # CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08] # CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21] la $25, 1f # CHECK: lw $25, %got($tmp1)($gp) # encoding: [0x8f,0x99,A,A] diff --git a/test/MC/Mips/mips-expansions.s b/test/MC/Mips/mips-expansions.s index 798461c5f99..cd5002cfca7 100644 --- a/test/MC/Mips/mips-expansions.s +++ b/test/MC/Mips/mips-expansions.s @@ -144,13 +144,13 @@ # CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac] lw $8, symbol+8 -# CHECK-LE: lw $8, %got(symbol+8)($gp) # encoding: [A,A,0x88,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: lw $8, %got(symbol)($gp) # encoding: [A,A,0x88,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25] # CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d] sw $8, symbol+8 -# CHECK-LE: lw $1, %got(symbol+8)($gp) # encoding: [A,A,0x81,0x8f] -# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT +# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f] +# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT # CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24] # CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]