[llvm] [PowerPC] Add error for incorrect use of memory operands (PR #114277)
Jake Egan via llvm-commits
llvm-commits at lists.llvm.org
Thu Nov 7 10:28:10 PST 2024
https://github.com/jakeegan updated https://github.com/llvm/llvm-project/pull/114277
>From e7ee0206c194092e2bdf86ad3be75d3a2cfc4d0d Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Wed, 30 Oct 2024 13:14:01 -0400
Subject: [PATCH 1/6] [PowerPC] Add error for incorrect use of memory operands
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 12 +++++++-
.../PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 4 ++-
llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 8 +++---
llvm/lib/Target/PowerPC/PPCInstrFormats.td | 14 +++++++---
llvm/lib/Target/PowerPC/PPCInstrInfo.h | 3 ++
llvm/lib/Target/PowerPC/PPCInstrInfo.td | 12 +++++---
llvm/lib/Target/PowerPC/PPCInstrP10.td | 28 +++++++++++--------
llvm/lib/Target/PowerPC/PPCInstrSPE.td | 2 +-
.../PowerPC/2007-01-31-InlineAsmAddrMode.ll | 2 +-
.../PowerPC/2009-07-16-InlineAsm-M-Operand.ll | 2 +-
llvm/test/MC/PowerPC/ppc64-errors.s | 10 +++++++
11 files changed, 68 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index bf512481cf6460..5ed41844bfbf9b 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -9,6 +9,7 @@
#include "MCTargetDesc/PPCMCExpr.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
#include "PPCTargetStreamer.h"
+#include "PPCInstrInfo.h"
#include "TargetInfo/PowerPCTargetInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
@@ -99,10 +100,14 @@ struct PPCOperand;
class PPCAsmParser : public MCTargetAsmParser {
bool IsPPC64;
+ bool UsesMemOp;
+
void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
bool isPPC64() const { return IsPPC64; }
+ bool usesMemOp() const { return UsesMemOp; }
+
MCRegister matchRegisterName(int64_t &IntVal);
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
@@ -146,6 +151,7 @@ class PPCAsmParser : public MCTargetAsmParser {
// Check for 64-bit vs. 32-bit pointer mode.
const Triple &TheTriple = STI.getTargetTriple();
IsPPC64 = TheTriple.isPPC64();
+ UsesMemOp = false;
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
@@ -1257,9 +1263,11 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
MCStreamer &Out, uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
-
+ const PPCInstrInfo *TII = static_cast<const PPCInstrInfo*>(&MII);
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
case Match_Success:
+ if (usesMemOp() != TII->isMemOp(Inst.getOpcode()))
+ return Error(IDLoc, "invalid operand for instruction");
// Post-process instructions (typically extended mnemonics)
processInstruction(Inst, Operands);
Inst.setLoc(IDLoc);
@@ -1595,6 +1603,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
// Otherwise, check for D-form memory operands
if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
+ UsesMemOp = true;
S = Parser.getTok().getLoc();
int64_t IntVal;
@@ -1626,6 +1635,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
/// Parse an instruction mnemonic followed by its operands.
bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
+ UsesMemOp = false;
// The first operand is the token for the instruction name.
// If the next character is a '+' or '-', we need to add it to the
// instruction name, to match what TableGen is doing.
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index 16777725990aa1..caa3ad0d22e3bd 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -171,7 +171,9 @@ enum {
/// This instruction produced a sign extended result.
SExt32To64 = 0x1 << (NewDef_Shift + 2),
/// This instruction produced a zero extended result.
- ZExt32To64 = 0x1 << (NewDef_Shift + 3)
+ ZExt32To64 = 0x1 << (NewDef_Shift + 3),
+ /// This instruction uses a memory operand.
+ MemOp = 0x1 << (NewDef_Shift + 4)
};
} // end namespace PPCII
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index ae25f5c78a0e2d..99f945a92b5cf5 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -218,7 +218,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
(ins (memrix $D, $RA):$src),
"bctrl\n\tld 2, $src", IIC_BrB,
[(PPCbctrl_load_toc iaddrX4:$src)]>,
- Requires<[In64BitMode]>;
+ Requires<[In64BitMode]>, MemOp;
}
let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
@@ -228,7 +228,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
(ins (memrix $D, $RA):$src),
"bctrl\n\tld 2, $src", IIC_BrB,
[(PPCbctrl_load_toc_rm iaddrX4:$src)]>,
- Requires<[In64BitMode]>;
+ Requires<[In64BitMode]>, MemOp;
}
} // Interpretation64Bit
@@ -777,7 +777,7 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s17imm64:$D),
def LA8 : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D),
"la $RST, $D($RA)", IIC_IntGeneral,
[(set i64:$RST, (add i64:$RA,
- (PPClo tglobaladdr:$D, 0)))]>;
+ (PPClo tglobaladdr:$D, 0)))]>, MemOp;
let Defs = [CARRY] in {
def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D),
@@ -1457,7 +1457,7 @@ def LQ : DQForm_RTp5_RA17_MEM<56, 0,
"lq $RTp, $addr", IIC_LdStLQ,
[]>,
RegConstraint<"@earlyclobber $RTp">,
- isPPC64;
+ isPPC64, MemOp;
// We don't really have LQX in the ISA, make a pseudo one so that we can
// handle x-form during isel. Make it pre-ra may expose
// oppotunities to some opts(CSE, LICM and etc.) for the result of adding
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 5389f42a325ce6..45fd0112b2bfdf 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -55,6 +55,10 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
bits<1> ZExt32To64 = 0;
let TSFlags{9} = ZExt32To64;
+ // Indicate that this instruction uses a memory operand.
+ bits<1> MemOp = 0;
+ let TSFlags{10} = MemOp;
+
// Fields used for relation models.
string BaseName = "";
@@ -82,6 +86,7 @@ class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; }
class XFormMemOp { bits<1> XFormMemOp = 1; }
class SExt32To64 { bits<1> SExt32To64 = 1; }
class ZExt32To64 { bits<1> ZExt32To64 = 1; }
+class MemOp { bits<1> MemOp = 1; }
// Two joined instructions; used to emit two adjacent instructions as one.
// The itinerary from the first instruction is used for scheduling and
@@ -250,7 +255,7 @@ class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr,
class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern> {
+ : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemOp {
}
class DForm_2<bits<6> opcode, dag OOL, dag IOL, string asmstr,
@@ -295,6 +300,7 @@ class DForm_4_zero<bits<6> opcode, dag OOL, dag IOL, string asmstr,
let RST = 0;
let RA = 0;
let D = 0;
+ let MemOp = 0;
}
class DForm_4_fixedreg_zero<bits<6> opcode, bits<5> R, dag OOL, dag IOL,
@@ -372,7 +378,7 @@ class DForm_6_ext<bits<6> opcode, dag OOL, dag IOL, string asmstr,
// 1.7.5 DS-Form
class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin> {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RST;
bits<5> RA;
bits<14> D;
@@ -404,7 +410,7 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr,
// DQ-Form: [PO T RA DQ TX XO] or [PO S RA DQ SX XO]
class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin> {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<6> XT;
bits<5> RA;
bits<12> DQ;
@@ -1246,7 +1252,7 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin> {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RA;
bits<6> D;
bits<5> RB;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index 40996f6fbb75e1..0c9b9207f5fe75 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -285,6 +285,9 @@ class PPCInstrInfo : public PPCGenInstrInfo {
bool isZExt32To64(unsigned Opcode) const {
return get(Opcode).TSFlags & PPCII::ZExt32To64;
}
+ bool isMemOp(unsigned Opcode) const {
+ return get(Opcode).TSFlags & PPCII::MemOp;
+ }
static bool isSameClassPhysRegCopy(unsigned Opcode) {
unsigned CopyOpcodes[] = {PPC::OR, PPC::OR8, PPC::FMR,
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index b4a5e41c0107a3..b79c5f79efeb1c 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1584,7 +1584,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
def BCTRL_LWZinto_toc:
XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
(ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
- [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>;
+ [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
}
@@ -1593,7 +1593,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
def BCTRL_LWZinto_toc_RM:
XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
(ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
- [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>;
+ [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
}
@@ -2303,7 +2303,7 @@ let isCodeGenOnly = 1 in
def LA : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D),
"la $RST, $D($RA)", IIC_IntGeneral,
[(set i32:$RST, (add i32:$RA,
- (PPClo tglobaladdr:$D, 0)))]>;
+ (PPClo tglobaladdr:$D, 0)))]>, MemOp;
def MULLI : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D),
"mulli $RST, $RA, $D", IIC_IntMulLI,
[(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>;
@@ -3466,6 +3466,10 @@ class PPCAsmPseudo<string asm, dag iops>
let isAsmParserOnly = 1;
let isPseudo = 1;
let hasNoSchedulingInfo = 1;
+
+ // Indicate that this instruction uses a memory operand.
+ bits<1> MemOp = 0;
+ let TSFlags{10} = MemOp;
}
// Prefixed instructions may require access to the above defs at a later
@@ -4714,7 +4718,7 @@ def : InstAlias<"tlbilxva $RA, $RB", (TLBILX 3, gprc:$RA, gprc:$RB)>,
Requires<[IsBookE]>;
def : InstAlias<"tlbilxva $RB", (TLBILX 3, R0, gprc:$RB)>, Requires<[IsBookE]>;
-def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>;
+def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemOp;
def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",
(ins gprc:$rA, gprc:$rB, s16imm:$imm)>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index c4b8597b1df9ff..1dd9a44f9e0b32 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -138,6 +138,10 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr,
bits<1> Prefixed = 1; // This is a prefixed instruction.
let TSFlags{7} = Prefixed;
+ // Indicate that this instruction uses a memory operand.
+ bits<1> MemOp = 0;
+ let TSFlags{10} = MemOp;
+
// For cases where multiple instruction definitions really represent the
// same underlying instruction but with one definition for 64-bit arguments
// and one for 32-bit arguments, this bit breaks the degeneracy between
@@ -183,7 +187,7 @@ multiclass VXForm_VTB5_RCr<bits<10> xo, bits<5> R, dag OOL, dag IOL,
class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin> {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RST;
bits<5> RA;
bits<34> D;
@@ -257,7 +261,7 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin> {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RST;
bits<5> RA;
bits<34> D;
@@ -281,7 +285,7 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL,
string asmstr, InstrItinClass itin,
list<dag> pattern>
- : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin> {
+ : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemOp {
bits<6> XST;
bits<5> RA;
bits<34> D;
@@ -585,7 +589,7 @@ multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0 in
+ let RA = 0, MemOp = 0 in
def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -602,7 +606,7 @@ multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0 in
+ let RA = 0, MemOp = 0 in
def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -619,7 +623,7 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0 in
+ let RA = 0, MemOp = 0 in
def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -847,7 +851,7 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin> {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> XTp;
bits<5> RA;
bits<12> DQ;
@@ -879,7 +883,7 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin> {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> XTp;
bits<5> RA;
bits<34> D;
@@ -910,7 +914,7 @@ multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0 in
+ let RA = 0, MemOp = 0 in
def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -2506,7 +2510,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
let Interpretation64Bit = 1 in {
def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
(ins g8rc_nox0:$RA, s34imm:$SI),
- "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
(ins s34imm_pcrel:$SI),
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2514,10 +2518,10 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI",
(ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
-
def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins gprc_nor0:$RA, s34imm:$SI),
- "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
+
def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins s34imm_pcrel:$SI),
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
index 5adfbad6ca1186..b7e670413d4ff2 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
@@ -114,7 +114,7 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr,
class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern> :
- I<4, OOL, IOL, asmstr, itin> {
+ I<4, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RT;
bits<5> RA;
bits<5> D;
diff --git a/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll b/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
index 24db84c0fb86e6..8dff7c9ecd1e37 100644
--- a/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
+++ b/llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll
@@ -11,7 +11,7 @@ define void @test1() {
entry:
%Out = alloca %struct.A, align 4 ; <ptr> [#uses=1]
%tmp2 = getelementptr %struct.A, ptr %Out, i32 0, i32 1
- %tmp5 = call i32 asm "lwbrx $0, $1", "=r,m"(ptr %tmp2 )
+ %tmp5 = call i32 asm "lbz $0, $1", "=r,m"(ptr %tmp2 )
ret void
}
diff --git a/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll b/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
index 76468f63ee741c..537a7ae78a5a2f 100644
--- a/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
+++ b/llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll
@@ -10,7 +10,7 @@ define void @memory_asm_operand(i32 %a) {
; "m" operand will be represented as:
; INLINEASM fake $0, 10, %R2, 20, -4, %R1
; It is difficult to find the flag operand (20) when starting from %R1
- call i32 asm "lbzx $0, $1", "=r,m" (i32 %a)
+ call i32 asm "lbz $0, $1", "=r,m" (i32 %a)
ret void
}
diff --git a/llvm/test/MC/PowerPC/ppc64-errors.s b/llvm/test/MC/PowerPC/ppc64-errors.s
index 1c03dc084acdff..85b98d07540a47 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -143,3 +143,13 @@
# CHECK: error: invalid operand for instruction
# CHECK-NEXT: lwarx 1, 2, 3, a
lwarx 1, 2, 3, a
+
+# Instruction requires memory operand
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: la 3, 3, 10
+ la 3, 3, 10
+
+# Instruction doesn't support memory operands
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: addi 3, 10(3)
+ addi 3, 10(3)
>From b8e3233b281775e2b3847f6d1a930161ef08a2df Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Fri, 1 Nov 2024 22:23:33 -0400
Subject: [PATCH 2/6] Address comments
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 36 ++++++++++++-------
llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 6 ++--
llvm/lib/Target/PowerPC/PPCInstrFormats.td | 10 ++++--
llvm/lib/Target/PowerPC/PPCInstrInfo.td | 4 +--
llvm/lib/Target/PowerPC/PPCInstrP10.td | 4 +--
5 files changed, 38 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 5ed41844bfbf9b..beae1935a046b4 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -8,8 +8,8 @@
#include "MCTargetDesc/PPCMCExpr.h"
#include "MCTargetDesc/PPCMCTargetDesc.h"
-#include "PPCTargetStreamer.h"
#include "PPCInstrInfo.h"
+#include "PPCTargetStreamer.h"
#include "TargetInfo/PowerPCTargetInfo.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
@@ -100,14 +100,10 @@ struct PPCOperand;
class PPCAsmParser : public MCTargetAsmParser {
bool IsPPC64;
- bool UsesMemOp;
-
void Warning(SMLoc L, const Twine &Msg) { getParser().Warning(L, Msg); }
bool isPPC64() const { return IsPPC64; }
- bool usesMemOp() const { return UsesMemOp; }
-
MCRegister matchRegisterName(int64_t &IntVal);
bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
@@ -135,6 +131,8 @@ class PPCAsmParser : public MCTargetAsmParser {
void processInstruction(MCInst &Inst, const OperandVector &Ops);
+ bool hasMemOp(const OperandVector &Ops);
+
/// @name Auto-generated Match Functions
/// {
@@ -151,7 +149,6 @@ class PPCAsmParser : public MCTargetAsmParser {
// Check for 64-bit vs. 32-bit pointer mode.
const Triple &TheTriple = STI.getTargetTriple();
IsPPC64 = TheTriple.isPPC64();
- UsesMemOp = false;
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
}
@@ -190,6 +187,7 @@ struct PPCOperand : public MCParsedAsmOperand {
struct ImmOp {
int64_t Val;
+ bool IsMemOp;
};
struct ExprOp {
@@ -250,6 +248,11 @@ struct PPCOperand : public MCParsedAsmOperand {
/// isPPC64 - True if this operand is for an instruction in 64-bit mode.
bool isPPC64() const { return IsPPC64; }
+ /// isMemOp - True if this operand is a memory operand.
+ bool isMemOp() const {
+ return Kind == Immediate && Imm.IsMemOp;
+ }
+
int64_t getImm() const {
assert(Kind == Immediate && "Invalid access!");
return Imm.Val;
@@ -702,9 +705,10 @@ struct PPCOperand : public MCParsedAsmOperand {
}
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
- bool IsPPC64) {
+ bool IsPPC64, bool IsMemOp = false) {
auto Op = std::make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
+ Op->Imm.IsMemOp = IsMemOp;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
@@ -1263,10 +1267,11 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
MCStreamer &Out, uint64_t &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
- const PPCInstrInfo *TII = static_cast<const PPCInstrInfo*>(&MII);
+ const PPCInstrInfo *TII = static_cast<const PPCInstrInfo *>(&MII);
+
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
case Match_Success:
- if (usesMemOp() != TII->isMemOp(Inst.getOpcode()))
+ if (hasMemOp(Operands) != TII->isMemOp(Inst.getOpcode()))
return Error(IDLoc, "invalid operand for instruction");
// Post-process instructions (typically extended mnemonics)
processInstruction(Inst, Operands);
@@ -1603,7 +1608,6 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
// Otherwise, check for D-form memory operands
if (!TlsCall && parseOptionalToken(AsmToken::LParen)) {
- UsesMemOp = true;
S = Parser.getTok().getLoc();
int64_t IntVal;
@@ -1626,7 +1630,7 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
E = Parser.getTok().getLoc();
if (parseToken(AsmToken::RParen, "missing ')'"))
return true;
- Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
+ Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOp=*/true));
}
return false;
@@ -1635,7 +1639,6 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
/// Parse an instruction mnemonic followed by its operands.
bool PPCAsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name,
SMLoc NameLoc, OperandVector &Operands) {
- UsesMemOp = false;
// The first operand is the token for the instruction name.
// If the next character is a '+' or '-', we need to add it to the
// instruction name, to match what TableGen is doing.
@@ -1915,3 +1918,12 @@ PPCAsmParser::applyModifierToExpr(const MCExpr *E,
return nullptr;
}
}
+
+bool PPCAsmParser::hasMemOp(const OperandVector &Operands) {
+ for (const auto &Operand : Operands) {
+ const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
+ if (Op.isMemOp())
+ return true;
+ }
+ return false;
+}
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 99f945a92b5cf5..9bee26307fc420 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -218,7 +218,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
(ins (memrix $D, $RA):$src),
"bctrl\n\tld 2, $src", IIC_BrB,
[(PPCbctrl_load_toc iaddrX4:$src)]>,
- Requires<[In64BitMode]>, MemOp;
+ Requires<[In64BitMode]>;
}
let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
@@ -228,7 +228,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
(ins (memrix $D, $RA):$src),
"bctrl\n\tld 2, $src", IIC_BrB,
[(PPCbctrl_load_toc_rm iaddrX4:$src)]>,
- Requires<[In64BitMode]>, MemOp;
+ Requires<[In64BitMode]>;
}
} // Interpretation64Bit
@@ -1457,7 +1457,7 @@ def LQ : DQForm_RTp5_RA17_MEM<56, 0,
"lq $RTp, $addr", IIC_LdStLQ,
[]>,
RegConstraint<"@earlyclobber $RTp">,
- isPPC64, MemOp;
+ isPPC64;
// We don't really have LQX in the ISA, make a pseudo one so that we can
// handle x-form during isel. Make it pre-ra may expose
// oppotunities to some opts(CSE, LICM and etc.) for the result of adding
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 45fd0112b2bfdf..99ef4fbfdd1ffb 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -120,6 +120,10 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr,
let TSFlags{2} = PPC970_Cracked;
let TSFlags{5-3} = PPC970_Unit;
+ // Indicate that this instruction uses a memory operand.
+ bits<1> MemOp = 0;
+ let TSFlags{10} = MemOp;
+
// Fields used for relation models.
string BaseName = "";
bit Interpretation64Bit = 0;
@@ -427,7 +431,7 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin,
list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin> {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RTp;
bits<5> RA;
bits<12> DQ;
@@ -1661,7 +1665,7 @@ class XLForm_2_ext_and_DSForm_1<bits<6> opcode1, bits<10> xo1,
dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
: XLForm_2_and_DSForm_1<opcode1, xo1, lk, opcode2, xo2,
- OOL, IOL, asmstr, itin, pattern> {
+ OOL, IOL, asmstr, itin, pattern>, MemOp {
let BO = bo;
let BI = bi;
let BH = 0;
@@ -1671,7 +1675,7 @@ class XLForm_2_ext_and_DForm_1<bits<6> opcode1, bits<10> xo1, bits<5> bo,
bits<5> bi, bit lk, bits<6> opcode2, dag OOL,
dag IOL, string asmstr, InstrItinClass itin,
list<dag> pattern>
- : I2<opcode1, opcode2, OOL, IOL, asmstr, itin> {
+ : I2<opcode1, opcode2, OOL, IOL, asmstr, itin>, MemOp {
bits<5> RST;
bits<5> RA;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index b79c5f79efeb1c..f896ca5a551e2a 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -1584,7 +1584,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
def BCTRL_LWZinto_toc:
XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
(ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
- [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
+ [(PPCbctrl_load_toc iaddr:$addr)]>, Requires<[In32BitMode]>;
}
@@ -1593,7 +1593,7 @@ let isCall = 1, PPC970_Unit = 7, isCodeGenOnly = 1,
def BCTRL_LWZinto_toc_RM:
XLForm_2_ext_and_DForm_1<19, 528, 20, 0, 1, 32, (outs),
(ins (memri $D, $RA):$addr), "bctrl\n\tlwz 2, $addr", IIC_BrB,
- [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>, MemOp;
+ [(PPCbctrl_load_toc_rm iaddr:$addr)]>, Requires<[In32BitMode]>;
}
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index 1dd9a44f9e0b32..cb3532f892cb15 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -2518,10 +2518,10 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
def PSUBI : PPCAsmPseudo<"psubi $RT, $RA, $SI",
(ins g8rc:$RT, g8rc_nox0:$RA, s34imm:$SI)>;
+
def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins gprc_nor0:$RA, s34imm:$SI),
- "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
-
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins s34imm_pcrel:$SI),
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
>From 6aa4468e3abbc4f60a454aa4504ba066b97ef5ef Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 11:51:09 -0500
Subject: [PATCH 3/6] Address comments
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 38 +++++++++----------
1 file changed, 17 insertions(+), 21 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index beae1935a046b4..ca1b97506a2032 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -131,8 +131,6 @@ class PPCAsmParser : public MCTargetAsmParser {
void processInstruction(MCInst &Inst, const OperandVector &Ops);
- bool hasMemOp(const OperandVector &Ops);
-
/// @name Auto-generated Match Functions
/// {
@@ -187,7 +185,7 @@ struct PPCOperand : public MCParsedAsmOperand {
struct ImmOp {
int64_t Val;
- bool IsMemOp;
+ bool IsMemOpBase;
};
struct ExprOp {
@@ -248,10 +246,8 @@ struct PPCOperand : public MCParsedAsmOperand {
/// isPPC64 - True if this operand is for an instruction in 64-bit mode.
bool isPPC64() const { return IsPPC64; }
- /// isMemOp - True if this operand is a memory operand.
- bool isMemOp() const {
- return Kind == Immediate && Imm.IsMemOp;
- }
+ /// isMemOpBase - True if this operand is the base of a memory operand.
+ bool isMemOpBase() const { return Kind == Immediate && Imm.IsMemOpBase; }
int64_t getImm() const {
assert(Kind == Immediate && "Invalid access!");
@@ -703,12 +699,11 @@ struct PPCOperand : public MCParsedAsmOperand {
Op->IsPPC64 = IsPPC64;
return Op;
}
-
- static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
- bool IsPPC64, bool IsMemOp = false) {
+ static std::unique_ptr<PPCOperand>
+ CreateImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, bool IsMemOpBase = false) {
auto Op = std::make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
- Op->Imm.IsMemOp = IsMemOp;
+ Op->Imm.IsMemOpBase = IsMemOpBase;
Op->StartLoc = S;
Op->EndLoc = E;
Op->IsPPC64 = IsPPC64;
@@ -1262,6 +1257,15 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
unsigned VariantID = 0);
+static bool hasMemOp(const OperandVector &Operands) {
+ for (const auto &Operand : Operands) {
+ const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
+ if (Op.isMemOpBase())
+ return true;
+ }
+ return false;
+}
+
bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
OperandVector &Operands,
MCStreamer &Out, uint64_t &ErrorInfo,
@@ -1630,7 +1634,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
E = Parser.getTok().getLoc();
if (parseToken(AsmToken::RParen, "missing ')'"))
return true;
- Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOp=*/true));
+ Operands.push_back(
+ PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOpBase=*/true));
}
return false;
@@ -1918,12 +1923,3 @@ PPCAsmParser::applyModifierToExpr(const MCExpr *E,
return nullptr;
}
}
-
-bool PPCAsmParser::hasMemOp(const OperandVector &Operands) {
- for (const auto &Operand : Operands) {
- const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
- if (Op.isMemOp())
- return true;
- }
- return false;
-}
>From e8b839fe0a7d2da80491bca562d7d3f7fbc141aa Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 11:58:43 -0500
Subject: [PATCH 4/6] Formatting
---
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index ca1b97506a2032..8b03fef5c1c5e5 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -699,8 +699,9 @@ struct PPCOperand : public MCParsedAsmOperand {
Op->IsPPC64 = IsPPC64;
return Op;
}
- static std::unique_ptr<PPCOperand>
- CreateImm(int64_t Val, SMLoc S, SMLoc E, bool IsPPC64, bool IsMemOpBase = false) {
+ static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
+ bool IsPPC64,
+ bool IsMemOpBase = false) {
auto Op = std::make_unique<PPCOperand>(Immediate);
Op->Imm.Val = Val;
Op->Imm.IsMemOpBase = IsMemOpBase;
>From 15e252ff070c72188c6954c2f25bd64a13c3c010 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Tue, 5 Nov 2024 12:00:28 -0500
Subject: [PATCH 5/6] Add space back
---
llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index 8b03fef5c1c5e5..e1596a4c381169 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -699,6 +699,7 @@ struct PPCOperand : public MCParsedAsmOperand {
Op->IsPPC64 = IsPPC64;
return Op;
}
+
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
bool IsPPC64,
bool IsMemOpBase = false) {
>From 42fbf347bc383b742f628f64a3cb4aae4942c6b2 Mon Sep 17 00:00:00 2001
From: Jake Egan <jake.egan at ibm.com>
Date: Thu, 7 Nov 2024 13:27:50 -0500
Subject: [PATCH 6/6] Address comments
---
.../Target/PowerPC/AsmParser/PPCAsmParser.cpp | 18 +++++++-----
.../PowerPC/MCTargetDesc/PPCMCTargetDesc.h | 4 +--
llvm/lib/Target/PowerPC/PPCInstr64Bit.td | 2 +-
llvm/lib/Target/PowerPC/PPCInstrFormats.td | 28 ++++++++-----------
llvm/lib/Target/PowerPC/PPCInstrInfo.h | 4 +--
llvm/lib/Target/PowerPC/PPCInstrInfo.td | 10 +++----
llvm/lib/Target/PowerPC/PPCInstrP10.td | 28 +++++++++----------
llvm/lib/Target/PowerPC/PPCInstrSPE.td | 2 +-
llvm/test/MC/PowerPC/ppc64-errors.s | 5 ++++
9 files changed, 53 insertions(+), 48 deletions(-)
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
index e1596a4c381169..e7cd255d5d34ca 100644
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -1259,13 +1259,17 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
unsigned VariantID = 0);
-static bool hasMemOp(const OperandVector &Operands) {
- for (const auto &Operand : Operands) {
- const PPCOperand &Op = static_cast<const PPCOperand &>(*Operand);
- if (Op.isMemOpBase())
- return true;
+// Check that the register+immediate memory operand is in the right position and
+// is expected by the instruction
+static bool validateMemOp(const OperandVector &Operands, bool isMemriOp) {
+ for (size_t idx = 0; idx < Operands.size(); ++idx) {
+ const PPCOperand &Op = static_cast<const PPCOperand &>(*Operands[idx]);
+ if ((idx == 3 && Op.isMemOpBase() != isMemriOp) ||
+ (idx != 3 && Op.isMemOpBase())) {
+ return false;
+ }
}
- return false;
+ return true;
}
bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
@@ -1277,7 +1281,7 @@ bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
case Match_Success:
- if (hasMemOp(Operands) != TII->isMemOp(Inst.getOpcode()))
+ if (!validateMemOp(Operands, TII->isMemriOp(Inst.getOpcode())))
return Error(IDLoc, "invalid operand for instruction");
// Post-process instructions (typically extended mnemonics)
processInstruction(Inst, Operands);
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
index caa3ad0d22e3bd..579ee5e8facb60 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h
@@ -172,8 +172,8 @@ enum {
SExt32To64 = 0x1 << (NewDef_Shift + 2),
/// This instruction produced a zero extended result.
ZExt32To64 = 0x1 << (NewDef_Shift + 3),
- /// This instruction uses a memory operand.
- MemOp = 0x1 << (NewDef_Shift + 4)
+ /// This instruction takes a register+immediate memory operand.
+ MemriOp = 0x1 << (NewDef_Shift + 4)
};
} // end namespace PPCII
diff --git a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
index 9bee26307fc420..68d1209d741c08 100644
--- a/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
+++ b/llvm/lib/Target/PowerPC/PPCInstr64Bit.td
@@ -777,7 +777,7 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s17imm64:$D),
def LA8 : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D),
"la $RST, $D($RA)", IIC_IntGeneral,
[(set i64:$RST, (add i64:$RA,
- (PPClo tglobaladdr:$D, 0)))]>, MemOp;
+ (PPClo tglobaladdr:$D, 0)))]>, MemriOp;
let Defs = [CARRY] in {
def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D),
diff --git a/llvm/lib/Target/PowerPC/PPCInstrFormats.td b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
index 99ef4fbfdd1ffb..2ced3fe80ea991 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrFormats.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrFormats.td
@@ -55,9 +55,9 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
bits<1> ZExt32To64 = 0;
let TSFlags{9} = ZExt32To64;
- // Indicate that this instruction uses a memory operand.
- bits<1> MemOp = 0;
- let TSFlags{10} = MemOp;
+ // Indicate that this instruction takes a register+immediate memory operand.
+ bits<1> MemriOp = 0;
+ let TSFlags{10} = MemriOp;
// Fields used for relation models.
string BaseName = "";
@@ -86,7 +86,7 @@ class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; }
class XFormMemOp { bits<1> XFormMemOp = 1; }
class SExt32To64 { bits<1> SExt32To64 = 1; }
class ZExt32To64 { bits<1> ZExt32To64 = 1; }
-class MemOp { bits<1> MemOp = 1; }
+class MemriOp { bits<1> MemriOp = 1; }
// Two joined instructions; used to emit two adjacent instructions as one.
// The itinerary from the first instruction is used for scheduling and
@@ -120,10 +120,6 @@ class I2<bits<6> opcode1, bits<6> opcode2, dag OOL, dag IOL, string asmstr,
let TSFlags{2} = PPC970_Cracked;
let TSFlags{5-3} = PPC970_Unit;
- // Indicate that this instruction uses a memory operand.
- bits<1> MemOp = 0;
- let TSFlags{10} = MemOp;
-
// Fields used for relation models.
string BaseName = "";
bit Interpretation64Bit = 0;
@@ -259,7 +255,7 @@ class DForm_base<bits<6> opcode, dag OOL, dag IOL, string asmstr,
class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemOp {
+ : DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemriOp {
}
class DForm_2<bits<6> opcode, dag OOL, dag IOL, string asmstr,
@@ -304,7 +300,7 @@ class DForm_4_zero<bits<6> opcode, dag OOL, dag IOL, string asmstr,
let RST = 0;
let RA = 0;
let D = 0;
- let MemOp = 0;
+ let MemriOp = 0;
}
class DForm_4_fixedreg_zero<bits<6> opcode, bits<5> R, dag OOL, dag IOL,
@@ -382,7 +378,7 @@ class DForm_6_ext<bits<6> opcode, dag OOL, dag IOL, string asmstr,
// 1.7.5 DS-Form
class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RST;
bits<5> RA;
bits<14> D;
@@ -414,7 +410,7 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr,
// DQ-Form: [PO T RA DQ TX XO] or [PO S RA DQ SX XO]
class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<6> XT;
bits<5> RA;
bits<12> DQ;
@@ -431,7 +427,7 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin,
list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RTp;
bits<5> RA;
bits<12> DQ;
@@ -1256,7 +1252,7 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RA;
bits<6> D;
bits<5> RB;
@@ -1665,7 +1661,7 @@ class XLForm_2_ext_and_DSForm_1<bits<6> opcode1, bits<10> xo1,
dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
: XLForm_2_and_DSForm_1<opcode1, xo1, lk, opcode2, xo2,
- OOL, IOL, asmstr, itin, pattern>, MemOp {
+ OOL, IOL, asmstr, itin, pattern> {
let BO = bo;
let BI = bi;
let BH = 0;
@@ -1675,7 +1671,7 @@ class XLForm_2_ext_and_DForm_1<bits<6> opcode1, bits<10> xo1, bits<5> bo,
bits<5> bi, bit lk, bits<6> opcode2, dag OOL,
dag IOL, string asmstr, InstrItinClass itin,
list<dag> pattern>
- : I2<opcode1, opcode2, OOL, IOL, asmstr, itin>, MemOp {
+ : I2<opcode1, opcode2, OOL, IOL, asmstr, itin> {
bits<5> RST;
bits<5> RA;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index 0c9b9207f5fe75..d45f481f7b9be7 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -285,8 +285,8 @@ class PPCInstrInfo : public PPCGenInstrInfo {
bool isZExt32To64(unsigned Opcode) const {
return get(Opcode).TSFlags & PPCII::ZExt32To64;
}
- bool isMemOp(unsigned Opcode) const {
- return get(Opcode).TSFlags & PPCII::MemOp;
+ bool isMemriOp(unsigned Opcode) const {
+ return get(Opcode).TSFlags & PPCII::MemriOp;
}
static bool isSameClassPhysRegCopy(unsigned Opcode) {
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.td b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
index f896ca5a551e2a..1d8a372fe7632d 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.td
@@ -2303,7 +2303,7 @@ let isCodeGenOnly = 1 in
def LA : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D),
"la $RST, $D($RA)", IIC_IntGeneral,
[(set i32:$RST, (add i32:$RA,
- (PPClo tglobaladdr:$D, 0)))]>, MemOp;
+ (PPClo tglobaladdr:$D, 0)))]>, MemriOp;
def MULLI : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D),
"mulli $RST, $RA, $D", IIC_IntMulLI,
[(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>;
@@ -3467,9 +3467,9 @@ class PPCAsmPseudo<string asm, dag iops>
let isPseudo = 1;
let hasNoSchedulingInfo = 1;
- // Indicate that this instruction uses a memory operand.
- bits<1> MemOp = 0;
- let TSFlags{10} = MemOp;
+ // Indicate that this instruction takes a register+immediate memory operand.
+ bits<1> MemriOp = 0;
+ let TSFlags{10} = MemriOp;
}
// Prefixed instructions may require access to the above defs at a later
@@ -4718,7 +4718,7 @@ def : InstAlias<"tlbilxva $RA, $RB", (TLBILX 3, gprc:$RA, gprc:$RB)>,
Requires<[IsBookE]>;
def : InstAlias<"tlbilxva $RB", (TLBILX 3, R0, gprc:$RB)>, Requires<[IsBookE]>;
-def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemOp;
+def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemriOp;
def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",
(ins gprc:$rA, gprc:$rB, s16imm:$imm)>;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrP10.td b/llvm/lib/Target/PowerPC/PPCInstrP10.td
index cb3532f892cb15..9e3b38fe02dd06 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrP10.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrP10.td
@@ -138,9 +138,9 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr,
bits<1> Prefixed = 1; // This is a prefixed instruction.
let TSFlags{7} = Prefixed;
- // Indicate that this instruction uses a memory operand.
- bits<1> MemOp = 0;
- let TSFlags{10} = MemOp;
+ // Indicate that this instruction takes a register+immediate memory operand.
+ bits<1> MemriOp = 0;
+ let TSFlags{10} = MemriOp;
// For cases where multiple instruction definitions really represent the
// same underlying instruction but with one definition for 64-bit arguments
@@ -187,7 +187,7 @@ multiclass VXForm_VTB5_RCr<bits<10> xo, bits<5> R, dag OOL, dag IOL,
class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RST;
bits<5> RA;
bits<34> D;
@@ -261,7 +261,7 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RST;
bits<5> RA;
bits<34> D;
@@ -285,7 +285,7 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL,
string asmstr, InstrItinClass itin,
list<dag> pattern>
- : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemOp {
+ : PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemriOp {
bits<6> XST;
bits<5> RA;
bits<34> D;
@@ -589,7 +589,7 @@ multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0, MemOp = 0 in
+ let RA = 0, MemriOp = 0 in
def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -606,7 +606,7 @@ multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0, MemOp = 0 in
+ let RA = 0, MemriOp = 0 in
def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -623,7 +623,7 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0, MemOp = 0 in
+ let RA = 0, MemriOp = 0 in
def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -851,7 +851,7 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
string asmstr, InstrItinClass itin, list<dag> pattern>
- : I<opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> XTp;
bits<5> RA;
bits<12> DQ;
@@ -883,7 +883,7 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern>
- : PI<1, opcode, OOL, IOL, asmstr, itin>, MemOp {
+ : PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> XTp;
bits<5> RA;
bits<34> D;
@@ -914,7 +914,7 @@ multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
isPCRel;
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
- let RA = 0, MemOp = 0 in
+ let RA = 0, MemriOp = 0 in
def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
asmstr_pcext, itin, []>, isPCRel;
}
@@ -2510,7 +2510,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
let Interpretation64Bit = 1 in {
def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
(ins g8rc_nox0:$RA, s34imm:$SI),
- "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
(ins s34imm_pcrel:$SI),
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2521,7 +2521,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins gprc_nor0:$RA, s34imm:$SI),
- "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemOp;
+ "pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
(ins s34imm_pcrel:$SI),
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrSPE.td b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
index b7e670413d4ff2..e91cae349e0826 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrSPE.td
+++ b/llvm/lib/Target/PowerPC/PPCInstrSPE.td
@@ -114,7 +114,7 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr,
class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr,
InstrItinClass itin, list<dag> pattern> :
- I<4, OOL, IOL, asmstr, itin>, MemOp {
+ I<4, OOL, IOL, asmstr, itin>, MemriOp {
bits<5> RT;
bits<5> RA;
bits<5> D;
diff --git a/llvm/test/MC/PowerPC/ppc64-errors.s b/llvm/test/MC/PowerPC/ppc64-errors.s
index 85b98d07540a47..17905a396885a0 100644
--- a/llvm/test/MC/PowerPC/ppc64-errors.s
+++ b/llvm/test/MC/PowerPC/ppc64-errors.s
@@ -153,3 +153,8 @@
# CHECK: error: invalid operand for instruction
# CHECK-NEXT: addi 3, 10(3)
addi 3, 10(3)
+
+# Invalid memory operand position
+# CHECK: error: invalid operand for instruction
+# CHECK-NEXT: la 0(3), 3
+ la 0(3), 3
More information about the llvm-commits
mailing list