Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -5859,14 +5859,21 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) { MCAsmParser &Parser = getParser(); const MCExpr *IdVal; - // If the first token is '$' we may have register operand. - if (Parser.getTok().is(AsmToken::Dollar)) - return MatchOperand_NoMatch; + // If the first token is '$' we may have register operand. We have to reject + // cases where it is not a register. Complicating the matter is that + // register names are not reserved across all ABIs. + // Peek past the dollar to see if it's a register name for this ABI. SMLoc S = Parser.getTok().getLoc(); + if (Parser.getTok().is(AsmToken::Dollar)) { + return matchCPURegisterName(Parser.getLexer().peekTok().getString()) == -1 + ? MatchOperand_ParseFail + : MatchOperand_NoMatch; + } if (getParser().parseExpression(IdVal)) return MatchOperand_ParseFail; const MCConstantExpr *MCE = dyn_cast(IdVal); - assert(MCE && "Unexpected MCExpr type."); + if (!MCE) + return MatchOperand_ParseFail; int64_t Val = MCE->getValue(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(MipsOperand::CreateImm( Index: test/MC/Mips/macro-aliases-invalid.s =================================================================== --- /dev/null +++ test/MC/Mips/macro-aliases-invalid.s @@ -0,0 +1,21 @@ +# RUN: not llvm-mc -arch=mips -mcpu=mips32r2 %s 2>%t1 +# RUN: FileCheck %s < %t1 + +# Check that subu only rejects any non-constant values. + +.globl end + subu $4, $4, %lo($start) # CHECK: error: invalid operand for instruction + subu $4, $4, $start # CHECK: error: invalid operand for instruction + subu $4, $4, %hi(end) # CHECK: error: invalid operand for instruction + subu $4, $4, end + 4 # CHECK: error: invalid operand for instruction + subu $4, $4, end # CHECK: error: invalid operand for instruction + subu $4, $4, sp # CHECK: error: invalid operand for instruction + + subu $4, %lo($start) # CHECK: error: invalid operand for instruction + subu $4, $start # CHECK: error: invalid operand for instruction + subu $4, %hi(end) # CHECK: error: invalid operand for instruction + subu $4, end + 4 # CHECK: error: invalid operand for instruction + subu $4, end # CHECK: error: invalid operand for instruction + subu $4, sp # CHECK: error: invalid operand for instruction + +$start: Index: test/MC/Mips/macro-aliases.s =================================================================== --- /dev/null +++ test/MC/Mips/macro-aliases.s @@ -0,0 +1,35 @@ +# RUN: llvm-mc -arch=mips -mcpu=mips32r2 %s -show-inst | FileCheck %s + +# Test that subu accepts constant operands and inverts them when +# rendering the operand. + + subu $4, $4, 4 # CHECK: ADDiu + # CHECK; Imm:-4 + subu $gp, $gp, 4 # CHECK: ADDiu + # CHECK; Imm:-4 + subu $sp, $sp, 4 # CHECK: ADDiu + # CHECK; Imm:-4 + subu $4, $4, -4 # CHECK: ADDiu + # CHECK; Imm:4 + subu $gp, $gp, -4 # CHECK: ADDiu + # CHECK; Imm:4 + subu $sp, $sp, -4 # CHECK: ADDiu + # CHECK; Imm:4 + subu $sp, $sp, -(4 + 4) # CHECK: ADDiu + # CHECK: Imm:8 + + subu $4, 8 # CHECK: ADDiu + # CHECK; Imm:-8 + subu $gp, 8 # CHECK: ADDiu + # CHECK; Imm:-8 + subu $sp, 8 # CHECK: ADDiu + # CHECK; Imm:-8 + subu $4, -8 # CHECK: ADDiu + # CHECK; Imm:8 + subu $gp, -8 # CHECK: ADDiu + # CHECK; Imm:8 + subu $sp, -8 # CHECK: ADDiu + # CHECK; Imm:8 + subu $sp, -(4 + 4) # CHECK: ADDiu + # CHECK: Imm:8 +