Skip to content

Commit 48cc435

Browse files
authored
Reland "[PowerPC] Add error for incorrect use of memory operands (#114277)" (#115958)
Commit 9358905 was reverted because it caused a failure with test `lld :: ELF/ppc64-local-exec-tls.s`. This relands the commit with a fix for the test.
1 parent f407dff commit 48cc435

File tree

12 files changed

+84
-27
lines changed

12 files changed

+84
-27
lines changed

lld/test/ELF/ppc64-local-exec-tls.s

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ test_ds:
6262
addi 2, 2, .TOC.-.Lfunc_gep3@l
6363
.Lfunc_lep3:
6464
.localentry test_ds, .Lfunc_lep3-.Lfunc_gep3
65-
ld 3, b@tprel, 13
65+
ld 3, b@tprel(13)
6666
blr
6767

6868
test_lo_ds:
@@ -71,7 +71,7 @@ test_lo_ds:
7171
addi 2, 2, .TOC.-.Lfunc_gep4@l
7272
.Lfunc_lep4:
7373
.localentry test_lo_ds, .Lfunc_lep4-.Lfunc_gep4
74-
ld 3, b@tprel@l, 13
74+
ld 3, b@tprel@l(13)
7575
blr
7676

7777
test_highest_a:

llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "MCTargetDesc/PPCMCExpr.h"
1010
#include "MCTargetDesc/PPCMCTargetDesc.h"
11+
#include "PPCInstrInfo.h"
1112
#include "PPCTargetStreamer.h"
1213
#include "TargetInfo/PowerPCTargetInfo.h"
1314
#include "llvm/ADT/STLExtras.h"
@@ -182,6 +183,7 @@ struct PPCOperand : public MCParsedAsmOperand {
182183

183184
struct ImmOp {
184185
int64_t Val;
186+
bool IsMemOpBase;
185187
};
186188

187189
struct ExprOp {
@@ -242,6 +244,9 @@ struct PPCOperand : public MCParsedAsmOperand {
242244
/// isPPC64 - True if this operand is for an instruction in 64-bit mode.
243245
bool isPPC64() const { return IsPPC64; }
244246

247+
/// isMemOpBase - True if this operand is the base of a memory operand.
248+
bool isMemOpBase() const { return Kind == Immediate && Imm.IsMemOpBase; }
249+
245250
int64_t getImm() const {
246251
assert(Kind == Immediate && "Invalid access!");
247252
return Imm.Val;
@@ -694,9 +699,11 @@ struct PPCOperand : public MCParsedAsmOperand {
694699
}
695700

696701
static std::unique_ptr<PPCOperand> CreateImm(int64_t Val, SMLoc S, SMLoc E,
697-
bool IsPPC64) {
702+
bool IsPPC64,
703+
bool IsMemOpBase = false) {
698704
auto Op = std::make_unique<PPCOperand>(Immediate);
699705
Op->Imm.Val = Val;
706+
Op->Imm.IsMemOpBase = IsMemOpBase;
700707
Op->StartLoc = S;
701708
Op->EndLoc = E;
702709
Op->IsPPC64 = IsPPC64;
@@ -1250,14 +1257,29 @@ void PPCAsmParser::processInstruction(MCInst &Inst,
12501257
static std::string PPCMnemonicSpellCheck(StringRef S, const FeatureBitset &FBS,
12511258
unsigned VariantID = 0);
12521259

1260+
// Check that the register+immediate memory operand is in the right position and
1261+
// is expected by the instruction. Returns true if the memory operand syntax is
1262+
// valid; otherwise, returns false.
1263+
static bool validateMemOp(const OperandVector &Operands, bool isMemriOp) {
1264+
for (size_t idx = 0; idx < Operands.size(); ++idx) {
1265+
const PPCOperand &Op = static_cast<const PPCOperand &>(*Operands[idx]);
1266+
if (Op.isMemOpBase() != (idx == 3 && isMemriOp))
1267+
return false;
1268+
}
1269+
return true;
1270+
}
1271+
12531272
bool PPCAsmParser::matchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
12541273
OperandVector &Operands,
12551274
MCStreamer &Out, uint64_t &ErrorInfo,
12561275
bool MatchingInlineAsm) {
12571276
MCInst Inst;
1277+
const PPCInstrInfo *TII = static_cast<const PPCInstrInfo *>(&MII);
12581278

12591279
switch (MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm)) {
12601280
case Match_Success:
1281+
if (!validateMemOp(Operands, TII->isMemriOp(Inst.getOpcode())))
1282+
return Error(IDLoc, "invalid operand for instruction");
12611283
// Post-process instructions (typically extended mnemonics)
12621284
processInstruction(Inst, Operands);
12631285
Inst.setLoc(IDLoc);
@@ -1615,7 +1637,8 @@ bool PPCAsmParser::parseOperand(OperandVector &Operands) {
16151637
E = Parser.getTok().getLoc();
16161638
if (parseToken(AsmToken::RParen, "missing ')'"))
16171639
return true;
1618-
Operands.push_back(PPCOperand::CreateImm(IntVal, S, E, isPPC64()));
1640+
Operands.push_back(
1641+
PPCOperand::CreateImm(IntVal, S, E, isPPC64(), /*IsMemOpBase=*/true));
16191642
}
16201643

16211644
return false;

llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCTargetDesc.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,9 @@ enum {
171171
/// This instruction produced a sign extended result.
172172
SExt32To64 = 0x1 << (NewDef_Shift + 2),
173173
/// This instruction produced a zero extended result.
174-
ZExt32To64 = 0x1 << (NewDef_Shift + 3)
174+
ZExt32To64 = 0x1 << (NewDef_Shift + 3),
175+
/// This instruction takes a register+immediate memory operand.
176+
MemriOp = 0x1 << (NewDef_Shift + 4)
175177
};
176178
} // end namespace PPCII
177179

llvm/lib/Target/PowerPC/PPCInstr64Bit.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -777,7 +777,7 @@ def ADDIS8 : DForm_2<15, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s17imm64:$D),
777777
def LA8 : DForm_2<14, (outs g8rc:$RST), (ins g8rc_nox0:$RA, s16imm64:$D),
778778
"la $RST, $D($RA)", IIC_IntGeneral,
779779
[(set i64:$RST, (add i64:$RA,
780-
(PPClo tglobaladdr:$D, 0)))]>;
780+
(PPClo tglobaladdr:$D, 0)))]>, MemriOp;
781781

782782
let Defs = [CARRY] in {
783783
def SUBFIC8: DForm_2< 8, (outs g8rc:$RST), (ins g8rc:$RA, s16imm64:$D),

llvm/lib/Target/PowerPC/PPCInstrFormats.td

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ class I<bits<6> opcode, dag OOL, dag IOL, string asmstr, InstrItinClass itin>
5555
bits<1> ZExt32To64 = 0;
5656
let TSFlags{9} = ZExt32To64;
5757

58+
// Indicate that this instruction takes a register+immediate memory operand.
59+
bits<1> MemriOp = 0;
60+
let TSFlags{10} = MemriOp;
61+
5862
// Fields used for relation models.
5963
string BaseName = "";
6064

@@ -82,6 +86,7 @@ class PPC970_Unit_BRU { bits<3> PPC970_Unit = 7; }
8286
class XFormMemOp { bits<1> XFormMemOp = 1; }
8387
class SExt32To64 { bits<1> SExt32To64 = 1; }
8488
class ZExt32To64 { bits<1> ZExt32To64 = 1; }
89+
class MemriOp { bits<1> MemriOp = 1; }
8590

8691
// Two joined instructions; used to emit two adjacent instructions as one.
8792
// 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,
250255

251256
class DForm_1<bits<6> opcode, dag OOL, dag IOL, string asmstr,
252257
InstrItinClass itin, list<dag> pattern>
253-
: DForm_base<opcode, OOL, IOL, asmstr, itin, pattern> {
258+
: DForm_base<opcode, OOL, IOL, asmstr, itin, pattern>, MemriOp {
254259
}
255260

256261
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,
295300
let RST = 0;
296301
let RA = 0;
297302
let D = 0;
303+
let MemriOp = 0;
298304
}
299305

300306
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,
372378
// 1.7.5 DS-Form
373379
class DSForm_1<bits<6> opcode, bits<2> xo, dag OOL, dag IOL, string asmstr,
374380
InstrItinClass itin, list<dag> pattern>
375-
: I<opcode, OOL, IOL, asmstr, itin> {
381+
: I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
376382
bits<5> RST;
377383
bits<5> RA;
378384
bits<14> D;
@@ -404,7 +410,7 @@ class DXForm<bits<6> opcode, bits<5> xo, dag OOL, dag IOL, string asmstr,
404410
// DQ-Form: [PO T RA DQ TX XO] or [PO S RA DQ SX XO]
405411
class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
406412
string asmstr, InstrItinClass itin, list<dag> pattern>
407-
: I<opcode, OOL, IOL, asmstr, itin> {
413+
: I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
408414
bits<6> XT;
409415
bits<5> RA;
410416
bits<12> DQ;
@@ -421,7 +427,7 @@ class DQ_RD6_RS5_DQ12<bits<6> opcode, bits<3> xo, dag OOL, dag IOL,
421427
class DQForm_RTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
422428
string asmstr, InstrItinClass itin,
423429
list<dag> pattern>
424-
: I<opcode, OOL, IOL, asmstr, itin> {
430+
: I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
425431
bits<5> RTp;
426432
bits<5> RA;
427433
bits<12> DQ;
@@ -1246,7 +1252,7 @@ class XX2_RD6_DCMX7_RS6<bits<6> opcode, bits<4> xo1, bits<3> xo2,
12461252

12471253
class XForm_XD6_RA5_RB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
12481254
string asmstr, InstrItinClass itin, list<dag> pattern>
1249-
: I<opcode, OOL, IOL, asmstr, itin> {
1255+
: I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
12501256
bits<5> RA;
12511257
bits<6> D;
12521258
bits<5> RB;

llvm/lib/Target/PowerPC/PPCInstrInfo.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,9 @@ class PPCInstrInfo : public PPCGenInstrInfo {
286286
bool isZExt32To64(unsigned Opcode) const {
287287
return get(Opcode).TSFlags & PPCII::ZExt32To64;
288288
}
289+
bool isMemriOp(unsigned Opcode) const {
290+
return get(Opcode).TSFlags & PPCII::MemriOp;
291+
}
289292

290293
static bool isSameClassPhysRegCopy(unsigned Opcode) {
291294
unsigned CopyOpcodes[] = {PPC::OR, PPC::OR8, PPC::FMR,

llvm/lib/Target/PowerPC/PPCInstrInfo.td

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2303,7 +2303,7 @@ let isCodeGenOnly = 1 in
23032303
def LA : DForm_2<14, (outs gprc:$RST), (ins gprc_nor0:$RA, s16imm:$D),
23042304
"la $RST, $D($RA)", IIC_IntGeneral,
23052305
[(set i32:$RST, (add i32:$RA,
2306-
(PPClo tglobaladdr:$D, 0)))]>;
2306+
(PPClo tglobaladdr:$D, 0)))]>, MemriOp;
23072307
def MULLI : DForm_2< 7, (outs gprc:$RST), (ins gprc:$RA, s16imm:$D),
23082308
"mulli $RST, $RA, $D", IIC_IntMulLI,
23092309
[(set i32:$RST, (mul i32:$RA, imm32SExt16:$D))]>;
@@ -3466,6 +3466,10 @@ class PPCAsmPseudo<string asm, dag iops>
34663466
let isAsmParserOnly = 1;
34673467
let isPseudo = 1;
34683468
let hasNoSchedulingInfo = 1;
3469+
3470+
// Indicate that this instruction takes a register+immediate memory operand.
3471+
bits<1> MemriOp = 0;
3472+
let TSFlags{10} = MemriOp;
34693473
}
34703474

34713475
// 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)>,
47144718
Requires<[IsBookE]>;
47154719
def : InstAlias<"tlbilxva $RB", (TLBILX 3, R0, gprc:$RB)>, Requires<[IsBookE]>;
47164720

4717-
def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>;
4721+
def LAx : PPCAsmPseudo<"la $rA, $addr", (ins gprc:$rA, memri:$addr)>, MemriOp;
47184722

47194723
def SUBI : PPCAsmPseudo<"subi $rA, $rB, $imm",
47204724
(ins gprc:$rA, gprc:$rB, s16imm:$imm)>;

llvm/lib/Target/PowerPC/PPCInstrP10.td

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ class PI<bits<6> pref, bits<6> opcode, dag OOL, dag IOL, string asmstr,
138138
bits<1> Prefixed = 1; // This is a prefixed instruction.
139139
let TSFlags{7} = Prefixed;
140140

141+
// Indicate that this instruction takes a register+immediate memory operand.
142+
bits<1> MemriOp = 0;
143+
let TSFlags{10} = MemriOp;
144+
141145
// For cases where multiple instruction definitions really represent the
142146
// same underlying instruction but with one definition for 64-bit arguments
143147
// 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,
183187

184188
class MLS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
185189
InstrItinClass itin, list<dag> pattern>
186-
: PI<1, opcode, OOL, IOL, asmstr, itin> {
190+
: PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
187191
bits<5> RST;
188192
bits<5> RA;
189193
bits<34> D;
@@ -257,7 +261,7 @@ multiclass MLS_DForm_R_SI34_RTA5_p<bits<6> opcode, dag OOL, dag IOL,
257261

258262
class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
259263
InstrItinClass itin, list<dag> pattern>
260-
: PI<1, opcode, OOL, IOL, asmstr, itin> {
264+
: PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
261265
bits<5> RST;
262266
bits<5> RA;
263267
bits<34> D;
@@ -281,7 +285,7 @@ class 8LS_DForm_R_SI34_RTA5_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
281285
class 8LS_DForm_R_SI34_XT6_RA5_MEM<bits<5> opcode, dag OOL, dag IOL,
282286
string asmstr, InstrItinClass itin,
283287
list<dag> pattern>
284-
: PI<1, { opcode, ? }, OOL, IOL, asmstr, itin> {
288+
: PI<1, { opcode, ? }, OOL, IOL, asmstr, itin>, MemriOp {
285289
bits<6> XST;
286290
bits<5> RA;
287291
bits<34> D;
@@ -585,7 +589,7 @@ multiclass MLS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
585589
isPCRel;
586590
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
587591
def nopc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
588-
let RA = 0 in
592+
let RA = 0, MemriOp = 0 in
589593
def onlypc : MLS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
590594
asmstr_pcext, itin, []>, isPCRel;
591595
}
@@ -602,7 +606,7 @@ multiclass 8LS_DForm_R_SI34_RTA5_MEM_p<bits<6> opcode, dag OOL, dag IOL,
602606
isPCRel;
603607
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
604608
def nopc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
605-
let RA = 0 in
609+
let RA = 0, MemriOp = 0 in
606610
def onlypc : 8LS_DForm_R_SI34_RTA5_MEM<opcode, OOL, PCRelOnly_IOL,
607611
asmstr_pcext, itin, []>, isPCRel;
608612
}
@@ -619,7 +623,7 @@ multiclass 8LS_DForm_R_SI34_XT6_RA5_MEM_p<bits<5> opcode, dag OOL, dag IOL,
619623
isPCRel;
620624
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
621625
def nopc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, IOL, asmstr, itin, []>;
622-
let RA = 0 in
626+
let RA = 0, MemriOp = 0 in
623627
def onlypc : 8LS_DForm_R_SI34_XT6_RA5_MEM<opcode, OOL, PCRelOnly_IOL,
624628
asmstr_pcext, itin, []>, isPCRel;
625629
}
@@ -847,7 +851,7 @@ let Predicates = [PrefixInstrs, HasP10Vector] in {
847851

848852
class DQForm_XTp5_RA17_MEM<bits<6> opcode, bits<4> xo, dag OOL, dag IOL,
849853
string asmstr, InstrItinClass itin, list<dag> pattern>
850-
: I<opcode, OOL, IOL, asmstr, itin> {
854+
: I<opcode, OOL, IOL, asmstr, itin>, MemriOp {
851855
bits<5> XTp;
852856
bits<5> RA;
853857
bits<12> DQ;
@@ -879,7 +883,7 @@ class XForm_XTp5_XAB5<bits<6> opcode, bits<10> xo, dag OOL, dag IOL,
879883

880884
class 8LS_DForm_R_XTp5_SI34_MEM<bits<6> opcode, dag OOL, dag IOL, string asmstr,
881885
InstrItinClass itin, list<dag> pattern>
882-
: PI<1, opcode, OOL, IOL, asmstr, itin> {
886+
: PI<1, opcode, OOL, IOL, asmstr, itin>, MemriOp {
883887
bits<5> XTp;
884888
bits<5> RA;
885889
bits<34> D;
@@ -910,7 +914,7 @@ multiclass 8LS_DForm_R_XTp5_SI34_MEM_p<bits<6> opcode, dag OOL,
910914
isPCRel;
911915
let isAsmParserOnly = 1, hasNoSchedulingInfo = 1 in {
912916
def nopc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, IOL, asmstr, itin, []>;
913-
let RA = 0 in
917+
let RA = 0, MemriOp = 0 in
914918
def onlypc : 8LS_DForm_R_XTp5_SI34_MEM<opcode, OOL, PCRelOnly_IOL,
915919
asmstr_pcext, itin, []>, isPCRel;
916920
}
@@ -2506,7 +2510,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
25062510
let Interpretation64Bit = 1 in {
25072511
def PLA8 : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
25082512
(ins g8rc_nox0:$RA, s34imm:$SI),
2509-
"pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
2513+
"pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
25102514
def PLA8pc : MLS_DForm_SI34_RT5<14, (outs g8rc:$RT),
25112515
(ins s34imm_pcrel:$SI),
25122516
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;
@@ -2517,7 +2521,7 @@ let Predicates = [IsISA3_1, PrefixInstrs], isAsmParserOnly = 1, hasNoSchedulingI
25172521

25182522
def PLA : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
25192523
(ins gprc_nor0:$RA, s34imm:$SI),
2520-
"pla $RT, ${SI} ${RA}", IIC_IntSimple, []>;
2524+
"pla $RT, ${SI} ${RA}", IIC_IntSimple, []>, MemriOp;
25212525
def PLApc : MLS_DForm_SI34_RT5<14, (outs gprc:$RT),
25222526
(ins s34imm_pcrel:$SI),
25232527
"pla $RT, $SI", IIC_IntSimple, []>, isPCRel;

llvm/lib/Target/PowerPC/PPCInstrSPE.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ class EVXForm_4<bits<8> xo, dag OOL, dag IOL, string asmstr,
114114

115115
class EVXForm_D<bits<11> xo, dag OOL, dag IOL, string asmstr,
116116
InstrItinClass itin, list<dag> pattern> :
117-
I<4, OOL, IOL, asmstr, itin> {
117+
I<4, OOL, IOL, asmstr, itin>, MemriOp {
118118
bits<5> RT;
119119
bits<5> RA;
120120
bits<5> D;

llvm/test/CodeGen/PowerPC/2007-01-31-InlineAsmAddrMode.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ define void @test1() {
1111
entry:
1212
%Out = alloca %struct.A, align 4 ; <ptr> [#uses=1]
1313
%tmp2 = getelementptr %struct.A, ptr %Out, i32 0, i32 1
14-
%tmp5 = call i32 asm "lwbrx $0, $1", "=r,m"(ptr %tmp2 )
14+
%tmp5 = call i32 asm "lbz $0, $1", "=r,m"(ptr %tmp2 )
1515
ret void
1616
}
1717

llvm/test/CodeGen/PowerPC/2009-07-16-InlineAsm-M-Operand.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ define void @memory_asm_operand(i32 %a) {
1010
; "m" operand will be represented as:
1111
; INLINEASM fake $0, 10, %R2, 20, -4, %R1
1212
; It is difficult to find the flag operand (20) when starting from %R1
13-
call i32 asm "lbzx $0, $1", "=r,m" (i32 %a)
13+
call i32 asm "lbz $0, $1", "=r,m" (i32 %a)
1414
ret void
1515
}
1616

llvm/test/MC/PowerPC/ppc64-errors.s

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,3 +143,18 @@
143143
# CHECK: error: invalid operand for instruction
144144
# CHECK-NEXT: lwarx 1, 2, 3, a
145145
lwarx 1, 2, 3, a
146+
147+
# Instruction requires memory operand
148+
# CHECK: error: invalid operand for instruction
149+
# CHECK-NEXT: la 3, 3, 10
150+
la 3, 3, 10
151+
152+
# Instruction doesn't support memory operands
153+
# CHECK: error: invalid operand for instruction
154+
# CHECK-NEXT: addi 3, 10(3)
155+
addi 3, 10(3)
156+
157+
# Invalid memory operand position
158+
# CHECK: error: invalid operand for instruction
159+
# CHECK-NEXT: la 0(3), 3
160+
la 0(3), 3

0 commit comments

Comments
 (0)