Skip to content

Commit 5da8013

Browse files
authored
[AArch64AsmParser] Allow branch target symbol to have a shift/extend modifier name (#80571)
Shift and extend modifiers are parsed as separate operands. When a symbol operand of a branch instruction has such a "bad" name, AArch64AsmParser will report an error. ``` % cat a.c void lsl(); void lsr(); void asr(); void ror(); void uxtb(); void sxtx(); void foo() { lsl(); asr(); asr(); ror(); uxtb(); sxtx(); } % clang --target=aarch64 -c -save-temps a.c a.s:15:8: error: expected #imm after shift specifier bl lsl ^ a.s:16:8: error: expected #imm after shift specifier bl asr ^ a.s:17:8: error: expected #imm after shift specifier bl asr ^ a.s:18:8: error: expected #imm after shift specifier bl ror ^ a.s:19:5: error: expected label or encodable integer pc offset bl uxtb ^ a.s:20:5: error: expected label or encodable integer pc offset bl sxtx ^ ``` In contrast, gas correctly parses these instructions. Fix #79729 by parsing shift/extend modifier after an immediate value/register
1 parent 1a98886 commit 5da8013

File tree

4 files changed

+54
-7
lines changed

4 files changed

+54
-7
lines changed

llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4809,20 +4809,30 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
48094809
return parseCondCode(Operands, invertCondCode);
48104810

48114811
// If it's a register name, parse it.
4812-
if (!parseRegister(Operands))
4812+
if (!parseRegister(Operands)) {
4813+
// Parse an optional shift/extend modifier.
4814+
AsmToken SavedTok = getTok();
4815+
if (parseOptionalToken(AsmToken::Comma)) {
4816+
// The operand after the register may be a label (e.g. ADR/ADRP). Check
4817+
// such cases and don't report an error when <label> happens to match a
4818+
// shift/extend modifier.
4819+
ParseStatus Res = MatchOperandParserImpl(Operands, Mnemonic,
4820+
/*ParseForAllFeatures=*/true);
4821+
if (!Res.isNoMatch())
4822+
return Res.isFailure();
4823+
Res = tryParseOptionalShiftExtend(Operands);
4824+
if (!Res.isNoMatch())
4825+
return Res.isFailure();
4826+
getLexer().UnLex(SavedTok);
4827+
}
48134828
return false;
4829+
}
48144830

48154831
// See if this is a "mul vl" decoration or "mul #<int>" operand used
48164832
// by SVE instructions.
48174833
if (!parseOptionalMulOperand(Operands))
48184834
return false;
48194835

4820-
// This could be an optional "shift" or "extend" operand.
4821-
ParseStatus GotShift = tryParseOptionalShiftExtend(Operands);
4822-
// We can only continue if no tokens were eaten.
4823-
if (!GotShift.isNoMatch())
4824-
return GotShift.isFailure();
4825-
48264836
// If this is a two-word mnemonic, parse its special keyword
48274837
// operand as an identifier.
48284838
if (Mnemonic == "brb" || Mnemonic == "smstart" || Mnemonic == "smstop" ||
@@ -4883,6 +4893,15 @@ bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
48834893

48844894
E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
48854895
Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
4896+
4897+
// Parse an optional shift/extend modifier.
4898+
AsmToken SavedTok = Tok;
4899+
if (parseOptionalToken(AsmToken::Comma)) {
4900+
ParseStatus Res = tryParseOptionalShiftExtend(Operands);
4901+
if (!Res.isNoMatch())
4902+
return Res.isFailure();
4903+
getLexer().UnLex(SavedTok);
4904+
}
48864905
return false;
48874906
}
48884907
case AsmToken::Equal: {

llvm/test/MC/AArch64/arm64-adr.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,16 @@ adrp x0, foo
2323
// CHECK: adrp x0, foo // encoding: [A,A,A,0x90'A']
2424
// CHECK-NEXT: // fixup A - offset: 0, value: foo, kind: fixup_aarch64_pcrel_adrp_imm21
2525

26+
// CHECK: adrp x0, lsl // encoding: [A,A,A,0x90'A']
27+
// CHECK-NEXT: // fixup A - offset: 0, value: lsl, kind: fixup_aarch64_pcrel_adrp_imm21
28+
// CHECK-NEXT: adrp x0, ror // encoding: [A,A,A,0x90'A']
29+
// CHECK-NEXT: // fixup A - offset: 0, value: ror, kind: fixup_aarch64_pcrel_adrp_imm21
30+
// CHECK-NEXT: adr x0, uxtb // encoding: [A,A,A,0x10'A']
31+
// CHECK-NEXT: // fixup A - offset: 0, value: uxtb, kind: fixup_aarch64_pcrel_adr_imm21
32+
adrp x0, lsl
33+
adrp x0, ror
34+
adr x0, uxtb
35+
2636
adr x0, #0xffffffff
2737
adrp x0, #0xffffffff
2838
adrp x0, #1

llvm/test/MC/AArch64/arm64-branch-encoding.s

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,3 +157,13 @@ L1:
157157
; CHECK: dcps2 ; encoding: [0x02,0x00,0xa0,0xd4]
158158
; CHECK: dcps3 ; encoding: [0x03,0x00,0xa0,0xd4]
159159

160+
;; Test "bad" names
161+
bl lsl
162+
b.eq lsr
163+
b.ne uxth
164+
; CHECK: bl lsl ; encoding: [A,A,A,0b100101AA]
165+
; CHECK-NEXT: fixup A - offset: 0, value: lsl, kind: fixup_aarch64_pcrel_call26
166+
; CHECK-NEXT: b.eq lsr ; encoding: [0bAAA00000,A,A,0x54]
167+
; CHECK-NEXT: fixup A - offset: 0, value: lsr, kind: fixup_aarch64_pcrel_branch19
168+
; CHECK-NEXT: b.ne uxth ; encoding: [0bAAA00001,A,A,0x54]
169+
; CHECK-NEXT: fixup A - offset: 0, value: uxth, kind: fixup_aarch64_pcrel_branch19

llvm/test/MC/AArch64/basic-a64-diagnostics.s

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,10 @@
11491149
// CHECK-ERROR-NEXT: cbz x29, #1
11501150
// CHECK-ERROR-NEXT: ^
11511151

1152+
/// Test "bad" names
1153+
cbz w1, lsl
1154+
// CHECK-ERROR: [[#@LINE-1]]:12: error: expected #imm after shift specifier
1155+
11521156
//------------------------------------------------------------------------------
11531157
// Conditional branch (immediate)
11541158
//------------------------------------------------------------------------------
@@ -1343,6 +1347,7 @@
13431347
csel sp, x2, x3, ne
13441348
csel x10, x11, sp, ge
13451349
csel x1, x2, x3, #3
1350+
csel x1, x2, x3, lsl #1, eq
13461351
// CHECK-ERROR: error: invalid operand for instruction
13471352
// CHECK-ERROR-NEXT: csel w4, wsp, w9, eq
13481353
// CHECK-ERROR-NEXT: ^
@@ -1366,6 +1371,9 @@
13661371
// CHECK-ERROR-NEXT: ^
13671372
// CHECK-ERROR-NEXT: error: expected AArch64 condition code
13681373
// CHECK-ERROR-NEXT: csel x1, x2, x3, #3
1374+
// CHECK-ERROR-NEXT: ^
1375+
// CHECK-ERROR-NEXT: error: expected AArch64 condition code
1376+
// CHECK-ERROR-NEXT: csel x1, x2, x3, lsl #1, eq
13691377
// CHECK-ERROR-NEXT: ^
13701378

13711379
csinc w20, w21, wsp, mi

0 commit comments

Comments
 (0)