diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6119,20 +6119,35 @@ case AsmToken::LCurly: return parseRegisterList(Operands, !Mnemonic.startswith("clr")); case AsmToken::Dollar: - case AsmToken::Hash: - // #42 -> immediate. + case AsmToken::Hash: { + // #42 -> immediate + // $ 42 -> immediate + // $foo -> symbol name + // $42 -> symbol name S = Parser.getTok().getLoc(); - Parser.Lex(); + + // Favor the interpretation of $-prefixed operands as symbol names. + // Cases where immediates are explicitly expected are handled by their + // specific ParseMethod implementations. + auto AdjacentToken = getLexer().peekTok(/*ShouldSkipSpace=*/false); + bool ExpectIdentifier = Parser.getTok().is(AsmToken::Dollar) && + (AdjacentToken.is(AsmToken::Identifier) || + AdjacentToken.is(AsmToken::Integer)); + if (!ExpectIdentifier) { + // Token is not part of identifier. Drop leading $ or # before parsing + // expression. + Parser.Lex(); + } if (Parser.getTok().isNot(AsmToken::Colon)) { - bool isNegative = Parser.getTok().is(AsmToken::Minus); + bool IsNegative = Parser.getTok().is(AsmToken::Minus); const MCExpr *ImmVal; if (getParser().parseExpression(ImmVal)) return true; const MCConstantExpr *CE = dyn_cast(ImmVal); if (CE) { int32_t Val = CE->getValue(); - if (isNegative && Val == 0) + if (IsNegative && Val == 0) ImmVal = MCConstantExpr::create(std::numeric_limits::min(), getContext()); } @@ -6151,7 +6166,7 @@ } // w/ a ':' after the '#', it's just like a plain ':'. LLVM_FALLTHROUGH; - + } case AsmToken::Colon: { S = Parser.getTok().getLoc(); // ":lower16:" and ":upper16:" expression prefixes diff --git a/llvm/test/MC/ARM/arm-branches.s b/llvm/test/MC/ARM/arm-branches.s --- a/llvm/test/MC/ARM/arm-branches.s +++ b/llvm/test/MC/ARM/arm-branches.s @@ -13,3 +13,32 @@ @ CHECK: bl #4 @ encoding: [0x01,0x00,0x00,0xeb] @ CHECK: beq #4 @ encoding: [0x01,0x00,0x00,0x0a] @ CHECK: blx #2 @ encoding: [0x00,0x00,0x00,0xfb] + +@------------------------------------------------------------------------------ +@ Leading '$' on branch targets must not be dropped if part of symbol names +@------------------------------------------------------------------------------ + + .global $foo + b $foo + bl $foo + beq $foo + blx $foo + b $foo + 4 + +@ CHECK: b ($foo) @ encoding: [A,A,A,0xea] +@ CHECK: bl ($foo) @ encoding: [A,A,A,0xeb] +@ CHECK: beq ($foo) @ encoding: [A,A,A,0x0a] +@ CHECK: blx ($foo) @ encoding: [A,A,A,0xfa] +@ CHECK: b #($foo)+4 @ encoding: [A,A,A,0xea] + +@------------------------------------------------------------------------------ +@ Leading '$' should be allowed to introduce an expression +@------------------------------------------------------------------------------ + + .global bar + b $ 4 + bl $ bar + 4 + blx $ bar +@ CHECK: b #4 @ encoding: [0x01,0x00,0x00,0xea] +@ CHECK: bl #bar+4 @ encoding: [A,A,A,0xeb] +@ CHECK: blx bar @ encoding: [A,A,A,0xfa]