summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNemanja Ivanovic <nemanja.i.ibm@gmail.com>2022-02-22 09:52:19 -0600
committerTom Stellard <tstellar@redhat.com>2022-04-18 17:02:51 -0700
commit33504b3bbe10d5d4caae13efcb99bd159c126070 (patch)
tree1bcea8368aa969a6f9bd79af884a7ab5574090ed
parent3400d0293a14d385a7b8e39e65be72f0c6adecb8 (diff)
downloadllvm-33504b3bbe10d5d4caae13efcb99bd159c126070.tar.gz
[PowerPC] Allow absolute expressions in relocations
The Linux kernel build uses absolute expressions suffixed with @lo/@ha relocations. This currently doesn't work for DS/DQ form instructions and there is no reason for it not to. It also works with GAS. This patch allows this as long as the value is a multiple of 4/16 for DS/DQ form. Differential revision: https://reviews.llvm.org/D115419 (cherry picked from commit 2aaba44b5c2265f90ac9f0ae188417ef79201c82)
-rw-r--r--llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp63
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp2
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp2
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h4
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp4
-rw-r--r--llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp13
-rw-r--r--llvm/lib/Target/PowerPC/PPCInstrInfo.td4
-rw-r--r--llvm/test/MC/PowerPC/ppc64-abs-reloc.s22
8 files changed, 69 insertions, 45 deletions
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 715cff72dcab..7113fe33b5d7 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -341,31 +341,11 @@ public:
bool isU10Imm() const { return Kind == Immediate && isUInt<10>(getImm()); }
bool isU12Imm() const { return Kind == Immediate && isUInt<12>(getImm()); }
- bool isU16Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isUInt<16>(getImmU16Context());
- default:
- return false;
- }
- }
- bool isS16Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isInt<16>(getImmS16Context());
- default:
- return false;
- }
- }
- bool isS16ImmX4() const { return Kind == Expression ||
- (Kind == Immediate && isInt<16>(getImm()) &&
- (getImm() & 3) == 0); }
+ bool isU16Imm() const { return isExtImm<16>(/*Signed*/ false, 1); }
+ bool isS16Imm() const { return isExtImm<16>(/*Signed*/ true, 1); }
+ bool isS16ImmX4() const { return isExtImm<16>(/*Signed*/ true, 4); }
+ bool isS16ImmX16() const { return isExtImm<16>(/*Signed*/ true, 16); }
+ bool isS17Imm() const { return isExtImm<17>(/*Signed*/ true, 1); }
bool isHashImmX8() const {
// The Hash Imm form is used for instructions that check or store a hash.
@@ -375,9 +355,6 @@ public:
(getImm() & 7) == 0);
}
- bool isS16ImmX16() const { return Kind == Expression ||
- (Kind == Immediate && isInt<16>(getImm()) &&
- (getImm() & 15) == 0); }
bool isS34ImmX16() const {
return Kind == Expression ||
(Kind == Immediate && isInt<34>(getImm()) && (getImm() & 15) == 0);
@@ -388,17 +365,6 @@ public:
return Kind == Expression || (Kind == Immediate && isInt<34>(getImm()));
}
- bool isS17Imm() const {
- switch (Kind) {
- case Expression:
- return true;
- case Immediate:
- case ContextImmediate:
- return isInt<17>(getImmS16Context());
- default:
- return false;
- }
- }
bool isTLSReg() const { return Kind == TLSRegister; }
bool isDirectBr() const {
if (Kind == Expression)
@@ -712,6 +678,25 @@ public:
return CreateExpr(Val, S, E, IsPPC64);
}
+
+private:
+ template <unsigned Width>
+ bool isExtImm(bool Signed, unsigned Multiple) const {
+ switch (Kind) {
+ default:
+ return false;
+ case Expression:
+ return true;
+ case Immediate:
+ case ContextImmediate:
+ if (Signed)
+ return isInt<Width>(getImmS16Context()) &&
+ (getImmS16Context() & (Multiple - 1)) == 0;
+ else
+ return isUInt<Width>(getImmU16Context()) &&
+ (getImmU16Context() & (Multiple - 1)) == 0;
+ }
+ }
};
} // end anonymous namespace.
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
index 9df94edc8cdf..2e678ffd58c2 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCAsmBackend.cpp
@@ -44,6 +44,7 @@ static uint64_t adjustFixupValue(unsigned Kind, uint64_t Value) {
case PPC::fixup_ppc_half16:
return Value & 0xffff;
case PPC::fixup_ppc_half16ds:
+ case PPC::fixup_ppc_half16dq:
return Value & 0xfffc;
case PPC::fixup_ppc_pcrel34:
case PPC::fixup_ppc_imm34:
@@ -60,6 +61,7 @@ static unsigned getFixupKindNumBytes(unsigned Kind) {
case FK_Data_2:
case PPC::fixup_ppc_half16:
case PPC::fixup_ppc_half16ds:
+ case PPC::fixup_ppc_half16dq:
return 2;
case FK_Data_4:
case PPC::fixup_ppc_brcond14:
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
index 94ef7b45434f..1e58039582c2 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFObjectWriter.cpp
@@ -125,6 +125,7 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}
break;
case PPC::fixup_ppc_half16ds:
+ case PPC::fixup_ppc_half16dq:
Target.print(errs());
errs() << '\n';
report_fatal_error("Invalid PC-relative half16ds relocation");
@@ -349,6 +350,7 @@ unsigned PPCELFObjectWriter::getRelocType(MCContext &Ctx, const MCValue &Target,
}
break;
case PPC::fixup_ppc_half16ds:
+ case PPC::fixup_ppc_half16dq:
switch (Modifier) {
default: llvm_unreachable("Unsupported Modifier");
case MCSymbolRefExpr::VK_None:
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
index 73292f7b7938..df0c666f5b11 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCFixupKinds.h
@@ -51,6 +51,10 @@ enum Fixups {
/// register number.
fixup_ppc_nofixup,
+ /// A 16-bit fixup corresponding to lo16(_foo) with implied 3 zero bits for
+ /// instrs like 'lxv'. Produces the same relocation as fixup_ppc_half16ds.
+ fixup_ppc_half16dq,
+
// Marker
LastTargetFixupKind,
NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index 4dfa7d5e600c..d76795fcebc4 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -198,8 +198,8 @@ unsigned PPCMCCodeEmitter::getMemRIX16Encoding(const MCInst &MI, unsigned OpNo,
}
// Otherwise add a fixup for the displacement field.
- Fixups.push_back(MCFixup::create(IsLittleEndian? 0 : 2, MO.getExpr(),
- (MCFixupKind)PPC::fixup_ppc_half16ds));
+ Fixups.push_back(MCFixup::create(IsLittleEndian ? 0 : 2, MO.getExpr(),
+ (MCFixupKind)PPC::fixup_ppc_half16dq));
return RegBits;
}
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp
index abff44449131..6cd04ee018fd 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCExpr.cpp
@@ -110,9 +110,18 @@ PPCMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
if (Value.isAbsolute()) {
int64_t Result = evaluateAsInt64(Value.getConstant());
- if ((Fixup == nullptr || (unsigned)Fixup->getKind() != PPC::fixup_ppc_half16) &&
- (Result >= 0x8000))
+ bool IsHalf16 = Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16;
+ bool IsHalf16DS =
+ Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16ds;
+ bool IsHalf16DQ =
+ Fixup && Fixup->getTargetKind() == PPC::fixup_ppc_half16dq;
+ bool IsHalf = IsHalf16 || IsHalf16DS || IsHalf16DQ;
+
+ if (!IsHalf && Result >= 0x8000)
return false;
+ if ((IsHalf16DS && (Result & 0x3)) || (IsHalf16DQ && (Result & 0xf)))
+ return false;
+
Res = MCValue::get(Result);
} else {
if (!Layout)
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index c26b4f6ceb7d..53e73e33b003 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1016,7 +1016,7 @@ def dispRI : Operand<iPTR> {
}
def PPCDispRIXOperand : AsmOperandClass {
let Name = "DispRIX"; let PredicateMethod = "isS16ImmX4";
- let RenderMethod = "addImmOperands";
+ let RenderMethod = "addS16ImmOperands";
}
def dispRIX : Operand<iPTR> {
let ParserMatchClass = PPCDispRIXOperand;
@@ -1030,7 +1030,7 @@ def dispRIHash : Operand<iPTR> {
}
def PPCDispRIX16Operand : AsmOperandClass {
let Name = "DispRIX16"; let PredicateMethod = "isS16ImmX16";
- let RenderMethod = "addImmOperands";
+ let RenderMethod = "addS16ImmOperands";
}
def dispRIX16 : Operand<iPTR> {
let ParserMatchClass = PPCDispRIX16Operand;
diff --git a/llvm/test/MC/PowerPC/ppc64-abs-reloc.s b/llvm/test/MC/PowerPC/ppc64-abs-reloc.s
new file mode 100644
index 000000000000..8b0d0b447178
--- /dev/null
+++ b/llvm/test/MC/PowerPC/ppc64-abs-reloc.s
@@ -0,0 +1,22 @@
+# RUN: llvm-mc -triple powerpc64le-unknown-linux-gnu %s -filetype=obj -o - | \
+# RUN: llvm-objdump -D -r - | FileCheck %s
+ .text
+test: # @test
+ add 5, 3, 4
+ extsw 3, 5
+ .space 32776
+lab2:
+ lxv 5, (lab2-test)@l(4)
+ ld 5, (lab2-test)@l(4)
+ lwz 5, (lab2-test)@l(4)
+ lxv 5, 8389632@l(4)
+ ld 5, 8389632@l(4)
+ lwz 5, 8389632@l(4)
+ blr
+
+# CHECK: lxv 5, -32752(4)
+# CHECK: ld 5, -32752(4)
+# CHECK: lwz 5, -32752(4)
+# CHECK: lxv 5, 1024(4)
+# CHECK: ld 5, 1024(4)
+# CHECK: lwz 5, 1024(4)