diff options
| author | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2022-02-22 09:52:19 -0600 |
|---|---|---|
| committer | Nemanja Ivanovic <nemanja.i.ibm@gmail.com> | 2022-02-22 09:53:08 -0600 |
| commit | 2aaba44b5c2265f90ac9f0ae188417ef79201c82 (patch) | |
| tree | 8aae82410155b22aaf08d85316332e891583536b /llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | |
| parent | fee4a9712f58caa9f1c3fc6c76ac46c5407475b6 (diff) | |
[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
Diffstat (limited to 'llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp')
| -rw-r--r-- | llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 63 |
1 files changed, 24 insertions, 39 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. |
