-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[PowerPC] Add error for incorrect use of memory operands #114277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-backend-powerpc @llvm/pr-subscribers-mc Author: Jake Egan (jakeegan) ChangesIf an instruction doesn't support memory operands, but one is provided, an error should be raised. And conversely, if an instruction requires a memory operand, but none is given, an error should be raised. Full diff: https://github.com/llvm/llvm-project/pull/114277.diff 11 Files Affected:
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)
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
Addressed review comments |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems we still don't catch cases where the memory operand is in the wrong position, e.g.:
la 0(3),3
Would trying to enforce that the memory operand is the last one work?
There are cases where the memory operand isn't the last one, for example:
I think I could enforce that the memory operand is the second one though. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is basically ready. Not sure if other reviewers have comments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/174/builds/8286 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/153/builds/14374 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/60/builds/12474 Here is the relevant piece of the build log for the reference
|
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/33/builds/6306 Here is the relevant piece of the build log for the reference
|
If an instruction doesn't support memory operands, but one is provided, an error should be raised. And conversely, if an instruction requires a memory operand, but none is given, an error should be raised. (cherry picked from commit 9358905)
If an instruction doesn't support memory operands, but one is provided, an error should be raised. And conversely, if an instruction requires a memory operand, but none is given, an error should be raised.
If an instruction doesn't support memory operands, but one is provided, an error should be raised. And conversely, if an instruction requires a memory operand, but none is given, an error should be raised.