diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp --- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp +++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp @@ -157,6 +157,7 @@ bool AllowParens = false); OperandMatchResultTy parseMemOpBaseReg(OperandVector &Operands); OperandMatchResultTy parseAtomicMemOp(OperandVector &Operands); + OperandMatchResultTy parseFenceArg(OperandVector &Operands); OperandMatchResultTy parseOperandWithModifier(OperandVector &Operands); OperandMatchResultTy parseBareSymbol(OperandVector &Operands); OperandMatchResultTy parseCallSymbol(OperandVector &Operands); @@ -416,29 +417,17 @@ bool isVTypeI() const { return isVType(); } - /// Return true if the operand is a valid for the fence instruction e.g. - /// ('iorw'). bool isFenceArg() const { + int64_t Imm; + RISCVMCExpr::VariantKind VK = RISCVMCExpr::VK_RISCV_None; if (!isImm()) return false; - const MCExpr *Val = getImm(); - auto *SVal = dyn_cast(Val); - if (!SVal || SVal->getKind() != MCSymbolRefExpr::VK_None) + bool IsConstantImm = evaluateConstantImm(getImm(), Imm, VK); + if (!IsConstantImm) return false; - - StringRef Str = SVal->getSymbol().getName(); - // Letters must be unique, taken from 'iorw', and in ascending order. This - // holds as long as each individual character is one of 'iorw' and is - // greater than the previous character. - char Prev = '\0'; - for (char c : Str) { - if (c != 'i' && c != 'o' && c != 'r' && c != 'w') - return false; - if (c <= Prev) - return false; - Prev = c; - } - return true; + int64_t Mask = RISCVFenceField::I | RISCVFenceField::O | + RISCVFenceField::R | RISCVFenceField::W; + return (Imm & ~Mask) == 0; } /// Return true if the operand is a valid floating point rounding mode. @@ -831,25 +820,6 @@ addExpr(Inst, getImm()); } - void addFenceArgOperands(MCInst &Inst, unsigned N) const { - assert(N == 1 && "Invalid number of operands!"); - // isFenceArg has validated the operand, meaning this cast is safe - auto SE = cast(getImm()); - - unsigned Imm = 0; - for (char c : SE->getSymbol().getName()) { - switch (c) { - default: - llvm_unreachable("FenceArg must contain only [iorw]"); - case 'i': Imm |= RISCVFenceField::I; break; - case 'o': Imm |= RISCVFenceField::O; break; - case 'r': Imm |= RISCVFenceField::R; break; - case 'w': Imm |= RISCVFenceField::W; break; - } - } - Inst.addOperand(MCOperand::createImm(Imm)); - } - void addCSRSystemRegisterOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); Inst.addOperand(MCOperand::createImm(SysReg.Encoding)); @@ -1121,12 +1091,6 @@ "operand must be a valid system register " "name or an integer in the range"); } - case Match_InvalidFenceArg: { - SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); - return Error( - ErrorLoc, - "operand must be formed of letters selected in-order from 'iorw'"); - } case Match_InvalidFRMArg: { SMLoc ErrorLoc = ((RISCVOperand &)*Operands[ErrorInfo]).getStartLoc(); return Error( @@ -1719,6 +1683,58 @@ return MatchOperand_Success; } +OperandMatchResultTy RISCVAsmParser::parseFenceArg(OperandVector &Operands) { + SMLoc S = getLoc(); + SMLoc E = SMLoc::getFromPointer(S.getPointer() - 1); + const MCExpr *Res; + + if (getLexer().getKind() != AsmToken::Identifier) { + Error(S, "operand must be formed of letters selected in-order from 'iorw'"); + return MatchOperand_ParseFail; + } + + StringRef Identifier = getParser().getTok().getIdentifier(); + getParser().Lex(); + + // Letters must be unique, taken from 'iorw', and in ascending order. This + // holds as long as each individual character is one of 'iorw' and is + // greater than the previous character. + char Prev = '\0'; + unsigned Imm = 0; + for (char c : Identifier) { + switch (c) { + case 'i': + Imm |= RISCVFenceField::I; + break; + case 'o': + Imm |= RISCVFenceField::O; + break; + case 'r': + Imm |= RISCVFenceField::R; + break; + case 'w': + Imm |= RISCVFenceField::W; + break; + default: + Error(S, "letters must be selected from 'iorw'"); + return MatchOperand_ParseFail; + } + + if (c <= Prev) { + if (c == Prev) + Error(S, "letters must not be duplicated"); + else + Error(S, "letters must be in the order 'iorw'"); + return MatchOperand_ParseFail; + } + Prev = c; + } + + Res = MCConstantExpr::create(Imm, getContext()); + Operands.push_back(RISCVOperand::createImm(Res, S, E, isRV64())); + return MatchOperand_Success; +} + /// Looks at a token type and creates the relevant operand from this /// information, adding to Operands. If operand was parsed, returns false, else /// true. diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.td b/llvm/lib/Target/RISCV/RISCVInstrInfo.td --- a/llvm/lib/Target/RISCV/RISCVInstrInfo.td +++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.td @@ -90,8 +90,8 @@ def FenceArg : AsmOperandClass { let Name = "FenceArg"; - let RenderMethod = "addFenceArgOperands"; - let DiagnosticType = "InvalidFenceArg"; + let RenderMethod = "addImmOperands"; + let ParserMethod = "parseFenceArg"; } def fencearg : Operand { diff --git a/llvm/test/MC/RISCV/rv32i-invalid.s b/llvm/test/MC/RISCV/rv32i-invalid.s --- a/llvm/test/MC/RISCV/rv32i-invalid.s +++ b/llvm/test/MC/RISCV/rv32i-invalid.s @@ -2,11 +2,11 @@ # Out of range immediates ## fencearg -fence iorw, iore # CHECK: :[[@LINE]]:13: error: operand must be formed of letters selected in-order from 'iorw' -fence wr, wr # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' -fence rw, rr # CHECK: :[[@LINE]]:11: error: operand must be formed of letters selected in-order from 'iorw' +fence iorw, iore # CHECK: :[[@LINE]]:13: error: letters must be selected from 'iorw' +fence wr, wr # CHECK: :[[@LINE]]:7: error: letters must be in the order 'iorw' +fence rw, rr # CHECK: :[[@LINE]]:11: error: letters must not be duplicated fence 1, rw # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' -fence unknown, unknown # CHECK: :[[@LINE]]:7: error: operand must be formed of letters selected in-order from 'iorw' +fence unknown, unknown # CHECK: :[[@LINE]]:7: error: letters must be selected from 'iorw' ## uimm5 slli a0, a0, 32 # CHECK: :[[@LINE]]:14: error: immediate must be an integer in the range [0, 31]