Index: llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ llvm/trunk/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -96,11 +96,18 @@ void emitLoadStoreSymbol(MCInst &Inst, unsigned Opcode, SMLoc IDLoc, MCStreamer &Out, bool HasTmpReg); + // Checks that a PseudoAddTPRel is using x4/tp in its second input operand. + // Enforcing this using a restricted register class for the second input + // operand of PseudoAddTPRel results in a poor diagnostic due to the fact + // 'add' is an overloaded mnemonic. + bool checkPseudoAddTPRel(MCInst &Inst, OperandVector &Operands); + /// Helper for processing MC instructions that have been successfully matched /// by MatchAndEmitInstruction. Modifications to the emitted instructions, /// like the expansion of pseudo instructions (e.g., "li"), can be performed /// in this method. - bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out); + bool processInstruction(MCInst &Inst, SMLoc IDLoc, OperandVector &Operands, + MCStreamer &Out); // Auto-generated instruction matching functions #define GET_ASSEMBLER_HEADER @@ -794,7 +801,7 @@ default: break; case Match_Success: - return processInstruction(Inst, IDLoc, Out); + return processInstruction(Inst, IDLoc, Operands, Out); case Match_MissingFeature: return Error(IDLoc, "instruction use requires an option to be enabled"); case Match_MnemonicFail: @@ -1596,7 +1603,21 @@ Opcode, IDLoc, Out); } +bool RISCVAsmParser::checkPseudoAddTPRel(MCInst &Inst, + OperandVector &Operands) { + assert(Inst.getOpcode() == RISCV::PseudoAddTPRel && "Invalid instruction"); + assert(Inst.getOperand(2).isReg() && "Unexpected second operand kind"); + if (Inst.getOperand(2).getReg() != RISCV::X4) { + SMLoc ErrorLoc = ((RISCVOperand &)*Operands[3]).getStartLoc(); + return Error(ErrorLoc, "the second input operand must be tp/x4 when using " + "%tprel_add modifier"); + } + + return false; +} + bool RISCVAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, + OperandVector &Operands, MCStreamer &Out) { Inst.setLoc(IDLoc); @@ -1675,6 +1696,9 @@ case RISCV::PseudoFSD: emitLoadStoreSymbol(Inst, RISCV::FSD, IDLoc, Out, /*HasTmpReg=*/true); return false; + case RISCV::PseudoAddTPRel: + if (checkPseudoAddTPRel(Inst, Operands)) + return true; } emitToStreamer(Out, Inst); Index: llvm/trunk/test/MC/RISCV/rv32i-invalid.s =================================================================== --- llvm/trunk/test/MC/RISCV/rv32i-invalid.s +++ llvm/trunk/test/MC/RISCV/rv32i-invalid.s @@ -133,6 +133,7 @@ # TP-relative symbol names require a %tprel_add modifier. add a0, a0, tp, zero # CHECK: :[[@LINE]]:17: error: expected '%' for operand modifier add a0, a0, tp, %hi(foo) # CHECK: :[[@LINE]]:17: error: operand must be a symbol with %tprel_add modifier +add a0, tp, a0, %tprel_add(foo) # CHECK: :[[@LINE]]:13: error: the second input operand must be tp/x4 when using %tprel_add modifier # Unrecognized operand modifier addi t0, sp, %modifer(255) # CHECK: :[[@LINE]]:15: error: unrecognized operand modifier