summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2019-08-22 15:52:41 +0000
committerHans Wennborg <hans@hanshq.net>2019-08-22 15:52:41 +0000
commit81058a8a649b22bc6506ba26166960c579d6a101 (patch)
tree82ebef2199cf1f07724fef8b9b1783e96be96644
parent2fcd2ae8a82e222d31e37bac540eb0a40854c334 (diff)
downloadllvm-81058a8a649b22bc6506ba26166960c579d6a101.tar.gz
Merging r367580:
------------------------------------------------------------------------ r367580 | atanasyan | 2019-08-01 18:04:29 +0200 (Thu, 01 Aug 2019) | 18 lines [mips] Fix lowering load/store instruction in PIC case If an operand of the `lw/sw` instructions is a symbol, these instructions incorrectly lowered using not-position-independent chain of commands. For PIC code we should use `lw/addiu` instructions with the `R_MIPS_GOT16` and `R_MIPS_LO16` relocations respectively. Instead of that LLVM generates position dependent code with the `R_MIPS_HI16` and `R_MIPS_LO16` relocations. This patch provides a fix for the bug by handling PIC case separately in the `MipsAsmParser::expandMemInst`. The main idea is to generate a chain of PIC instructions to load a symbol address into a register and then load the address content. The fix is not optimal and does not fix all PIC-related problems. This is a task for subsequent patches. Differential Revision: https://reviews.llvm.org/D65524 ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_90@369663 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp19
-rw-r--r--test/MC/Mips/mips-expansions.s59
-rw-r--r--test/MC/Mips/mips64-expansions.s53
3 files changed, 130 insertions, 1 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 1f7d095bf49b..aee434cb0067 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -3625,8 +3625,25 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg,
BaseReg, IDLoc, STI);
TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI);
+ return;
+ }
+
+ assert(OffsetOp.isExpr() && "expected expression operand kind");
+ if (inPicMode()) {
+ // FIXME:
+ // a) Fix lw/sw $reg, symbol($reg) instruction expanding.
+ // b) If expression includes offset (sym + number), do not
+ // encode the offset into a relocation. Take it in account
+ // in the last load/store instruction.
+ // c) Check that immediates of R_MIPS_GOT16/R_MIPS_LO16 relocations
+ // do not exceed 16-bit.
+ // d) Use R_MIPS_GOT_PAGE/R_MIPS_GOT_OFST relocations instead
+ // of R_MIPS_GOT_DISP in appropriate cases to reduce number
+ // of GOT entries.
+ expandLoadAddress(TmpReg, Mips::NoRegister, OffsetOp, !ABI.ArePtrs64bit(),
+ IDLoc, Out, STI);
+ TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, 0, IDLoc, STI);
} else {
- assert(OffsetOp.isExpr() && "expected expression operand kind");
const MCExpr *ExprOffset = OffsetOp.getExpr();
MCOperand LoOperand = MCOperand::createExpr(
MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
diff --git a/test/MC/Mips/mips-expansions.s b/test/MC/Mips/mips-expansions.s
index 91a637bfe221..798461c5f99c 100644
--- a/test/MC/Mips/mips-expansions.s
+++ b/test/MC/Mips/mips-expansions.s
@@ -50,6 +50,7 @@
# CHECK-LE: lhu $4, 4($4)
# LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst():
+# NON-PIC code
.set noat
lw $10, symbol($4)
# CHECK-LE: lui $10, %hi(symbol) # encoding: [A,A,0x0a,0x3c]
@@ -105,6 +106,64 @@
# CHECK-LE: lui $1, %hi(symbol)
# CHECK-LE: sdc1 $f0, %lo(symbol)($1)
+# PIC code
+ .option pic2
+ .set noat
+ lw $10, symbol($4)
+# CHECK-LE: lw $10, %got(symbol)($gp) # encoding: [A,A,0x8a,0x8f]
+# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
+# CHECK-LE-FIXME: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01]
+# CHECK-LE: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d]
+ .set at
+ sw $10, symbol($9)
+# 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-FIXME: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00]
+# CHECK-LE: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac]
+
+ lw $8, 1f+8
+# CHECK-LE: lw $8, %got(($tmp0)+8)($gp) # encoding: [A,A,0x88,0x8f]
+# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT
+# CHECK-LE: addiu $8, $8, %lo(($tmp0)+8) # encoding: [A,A,0x08,0x25]
+# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16
+# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d]
+ sw $8, 1f+8
+# CHECK-LE: lw $1, %got(($tmp0)+8)($gp) # encoding: [A,A,0x81,0x8f]
+# CHECK-LE: # fixup A - offset: 0, value: %got(($tmp0)+8), kind: fixup_Mips_GOT
+# CHECK-LE: addiu $1, $1, %lo(($tmp0)+8) # encoding: [A,A,0x21,0x24]
+# CHECK-LE: # fixup A - offset: 0, value: %lo(($tmp0)+8), kind: fixup_Mips_LO16
+# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
+
+ lw $10, 655483($4)
+# CHECK-LE: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c]
+# CHECK-LE: addu $10, $10, $4 # encoding: [0x21,0x50,0x44,0x01]
+# CHECK-LE: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d]
+ sw $10, 123456($9)
+# CHECK-LE: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c]
+# CHECK-LE: addu $1, $1, $9 # encoding: [0x21,0x08,0x29,0x00]
+# 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: 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: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24]
+# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
+
+ ldc1 $f0, symbol
+# 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: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4]
+ sdc1 $f0, symbol
+# 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: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4]
+ .option pic0
+
# Test BNE with an immediate as the 2nd operand.
bne $2, 0, 1332
# CHECK-LE: bnez $2, 1332 # encoding: [0x4d,0x01,0x40,0x14]
diff --git a/test/MC/Mips/mips64-expansions.s b/test/MC/Mips/mips64-expansions.s
index 4f0d3f15773c..4c24379f2dde 100644
--- a/test/MC/Mips/mips64-expansions.s
+++ b/test/MC/Mips/mips64-expansions.s
@@ -466,3 +466,56 @@ sym:
# CHECK-NEXT: dsll $4, $4, 16
# CHECK-NEXT: daddu $4, $4, $3
# CHECK-NEXT: lhu $4, -32764($4)
+
+# LW/SW and LDC1/SDC1 of symbol address, done by MipsAsmParser::expandMemInst():
+ .option pic2
+ lw $10, symbol($4)
+# CHECK: ld $10, %got_disp(symbol)($gp) # encoding: [A,A,0x8a,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK-FIXME: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01]
+# CHECK: lw $10, 0($10) # encoding: [0x00,0x00,0x4a,0x8d]
+ sw $10, symbol($9)
+# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK-FIXME: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00]
+# CHECK: sw $10, 0($1) # encoding: [0x00,0x00,0x2a,0xac]
+
+ lw $8, sym+8
+# CHECK: ld $8, %got_disp(sym)($gp) # encoding: [A,A,0x88,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP
+# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65]
+# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d]
+ sw $8, sym+8
+# CHECK: ld $1, %got_disp(sym)($gp) # encoding: [A,A,0x81,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(sym), kind: fixup_Mips_GOT_DISP
+# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64]
+# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
+
+ lw $10, 655483($4)
+# CHECK: lui $10, 10 # encoding: [0x0a,0x00,0x0a,0x3c]
+# CHECK: daddu $10, $10, $4 # encoding: [0x2d,0x50,0x44,0x01]
+# CHECK: lw $10, 123($10) # encoding: [0x7b,0x00,0x4a,0x8d]
+ sw $10, 123456($9)
+# CHECK: lui $1, 2 # encoding: [0x02,0x00,0x01,0x3c]
+# CHECK: daddu $1, $1, $9 # encoding: [0x2d,0x08,0x29,0x00]
+# CHECK: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac]
+
+ lw $8, symbol+8
+# CHECK: ld $8, %got_disp(symbol)($gp) # encoding: [A,A,0x88,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK: daddiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x65]
+# CHECK: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d]
+ sw $8, symbol+8
+# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK: daddiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x64]
+# CHECK: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
+
+ ldc1 $f0, symbol
+# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK: ldc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xd4]
+ sdc1 $f0, symbol
+# CHECK: ld $1, %got_disp(symbol)($gp) # encoding: [A,A,0x81,0xdf]
+# CHECK: # fixup A - offset: 0, value: %got_disp(symbol), kind: fixup_Mips_GOT_DISP
+# CHECK: sdc1 $f0, 0($1) # encoding: [0x00,0x00,0x20,0xf4]