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 @@ -6045,39 +6045,54 @@ case AsmToken::LCurly: return parseRegisterList(Operands, !Mnemonic.startswith("clr")); case AsmToken::Dollar: - case AsmToken::Hash: - // #42 -> immediate. - S = Parser.getTok().getLoc(); - Parser.Lex(); - - if (Parser.getTok().isNot(AsmToken::Colon)) { - 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) - ImmVal = MCConstantExpr::create(std::numeric_limits::min(), - getContext()); - } - E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); - - // There can be a trailing '!' on operands that we want as a separate - // '!' Token operand. Handle that here. For example, the compatibility - // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. - if (Parser.getTok().is(AsmToken::Exclaim)) { - Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), - Parser.getTok().getLoc())); - Parser.Lex(); // Eat exclaim token + case AsmToken::Hash: { + // #42 -> immediate + // $ 42 -> immediate + // $foo -> symbol name + // $42 -> symbol name + S = Parser.getTok().getLoc(); + + // 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::String) || + AdjacentToken.is(AsmToken::Integer)); + if (!ExpectIdentifier) { + // Token is not part of identifier. Drop leading $ or # before parsing expression. + Parser.Lex(); } - return false; - } - // w/ a ':' after the '#', it's just like a plain ':'. - LLVM_FALLTHROUGH; + if (Parser.getTok().isNot(AsmToken::Colon)) { + 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) + ImmVal = MCConstantExpr::create(std::numeric_limits::min(), + getContext()); + } + E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); + Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E)); + + // There can be a trailing '!' on operands that we want as a separate + // '!' Token operand. Handle that here. For example, the compatibility + // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'. + if (Parser.getTok().is(AsmToken::Exclaim)) { + Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(), + Parser.getTok().getLoc())); + Parser.Lex(); // Eat exclaim token + } + return false; + } + // 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]