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 @@ -107,6 +107,8 @@ uint64_t &ErrorInfo, bool MatchingInlineAsm) override; + AsmToken peekNextNext(); + bool parseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; OperandMatchResultTy tryParseRegister(MCRegister &RegNo, SMLoc &StartLoc, @@ -1577,10 +1579,36 @@ if (!RegNo) return MatchOperand_NoMatch; - getParser().Lex(); // Eat identifier token. + Lex(); // Eat identifier token. return MatchOperand_Success; } +/// Peek next after next token +/// +/// This function looks ahead for the next after the next token, discarding +/// comments in the process. Proper handling of the discarded comments will +/// happen on the next Lex() call. +AsmToken RISCVAsmParser::peekNextNext() { + AsmToken NextNextToken; + size_t NonComments = 0; + size_t ReadCount; + do { + AsmToken Buf[10]; + ReadCount = getLexer().peekTokens(Buf); + for (size_t index = 0; index < ReadCount; ++index) { + AsmToken Token = Buf[index]; + if (Token.getKind() != AsmToken::Comment) { + NonComments++; + if (NonComments == 2) { + NextNextToken = Token; + break; + } + } + } + } while (NonComments < 2 && ReadCount > 0); + return NextNextToken; +} + OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands, bool AllowParens) { SMLoc FirstS = getLoc(); @@ -1590,12 +1618,11 @@ // If this is an LParen and a parenthesised register name is allowed, parse it // atomically. if (AllowParens && getLexer().is(AsmToken::LParen)) { - AsmToken Buf[2]; - size_t ReadCount = getLexer().peekTokens(Buf); - if (ReadCount == 2 && Buf[1].getKind() == AsmToken::RParen) { + AsmToken NextNextToken = peekNextNext(); + if (NextNextToken.getKind() == AsmToken::RParen) { HadParens = true; LParen = getParser().getTok(); - getParser().Lex(); // Eat '(' + Lex(); // Eat '(' } } @@ -1617,12 +1644,12 @@ Operands.push_back(RISCVOperand::createToken("(", FirstS)); SMLoc S = getLoc(); SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); - getLexer().Lex(); + Lex(); Operands.push_back(RISCVOperand::createReg(RegNo, S, E)); } if (HadParens) { - getParser().Lex(); // Eat ')' + Lex(); // Eat ')' Operands.push_back(RISCVOperand::createToken(")", getLoc())); } @@ -1925,7 +1952,7 @@ return MatchOperand_ParseFail; } - getParser().Lex(); // Eat the identifier + Lex(); // Eat the identifier if (parseToken(AsmToken::LParen, "expected '('")) return MatchOperand_ParseFail; @@ -1978,11 +2005,11 @@ return MatchOperand_Success; case AsmToken::Plus: Opcode = MCBinaryExpr::Add; - getLexer().Lex(); + Lex(); break; case AsmToken::Minus: Opcode = MCBinaryExpr::Sub; - getLexer().Lex(); + Lex(); break; } @@ -2131,11 +2158,11 @@ MaskAgnostic)) return MatchOperand_NoMatch; - getLexer().Lex(); + Lex(); while (getLexer().is(AsmToken::Comma)) { // Consume comma. - getLexer().Lex(); + Lex(); if (getLexer().isNot(AsmToken::Identifier)) break; @@ -2146,7 +2173,7 @@ MaskAgnostic)) break; - getLexer().Lex(); + Lex(); } if (getLexer().is(AsmToken::EndOfStatement) && State == VTypeState_Done) { @@ -2186,7 +2213,7 @@ return MatchOperand_NoMatch; SMLoc S = getLoc(); SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); - getLexer().Lex(); + Lex(); Operands.push_back(RISCVOperand::createReg(RegNo, S, E)); return MatchOperand_Success; } @@ -2202,7 +2229,7 @@ return MatchOperand_NoMatch; SMLoc S = getLoc(); SMLoc E = SMLoc::getFromPointer(S.getPointer() + Name.size()); - getLexer().Lex(); + Lex(); Operands.push_back(RISCVOperand::createReg( RegNo, S, E, !getSTI().hasFeature(RISCV::FeatureStdExtF))); return MatchOperand_Success; @@ -2391,11 +2418,11 @@ Error(getLoc(), "register list must start from 'ra' or 'x1'"); return MatchOperand_ParseFail; } - getLexer().Lex(); + Lex(); // parse case like ,s0 if (getLexer().is(AsmToken::Comma)) { - getLexer().Lex(); + Lex(); if (getLexer().isNot(AsmToken::Identifier)) { Error(getLoc(), "invalid register"); return MatchOperand_ParseFail; @@ -2410,12 +2437,12 @@ Error(getLoc(), "continuous register list must start from 's0' or 'x8'"); return MatchOperand_ParseFail; } - getLexer().Lex(); // eat reg + Lex(); // eat reg } // parse case like -s1 if (getLexer().is(AsmToken::Minus)) { - getLexer().Lex(); + Lex(); StringRef EndName = getLexer().getTok().getIdentifier(); // FIXME: the register mapping and checks of EABI is wrong RegEnd = matchRegisterNameHelper(IsEABI, EndName); @@ -2428,7 +2455,7 @@ "'x8-x9' pair"); return MatchOperand_ParseFail; } - getLexer().Lex(); + Lex(); } if (!IsEABI) { @@ -2442,7 +2469,7 @@ } // parse ', x18' for extra part - getLexer().Lex(); + Lex(); if (getLexer().isNot(AsmToken::Identifier)) { Error(getLoc(), "invalid register"); return MatchOperand_ParseFail; @@ -2453,11 +2480,11 @@ "must start from 'x18'"); return MatchOperand_ParseFail; } - getLexer().Lex(); + Lex(); // parse '-x20' for extra part if (getLexer().is(AsmToken::Minus)) { - getLexer().Lex(); + Lex(); if (getLexer().isNot(AsmToken::Identifier)) { Error(getLoc(), "invalid register"); return MatchOperand_ParseFail; @@ -2467,7 +2494,7 @@ Error(getLoc(), "invalid register"); return MatchOperand_ParseFail; } - getLexer().Lex(); + Lex(); } RegEnd = MatchRegisterName(EndName); } @@ -2497,7 +2524,7 @@ OperandMatchResultTy RISCVAsmParser::parseZcmpSpimm(OperandVector &Operands) { if (getLexer().is(AsmToken::Minus)) - getLexer().Lex(); + Lex(); SMLoc S = getLoc(); int64_t StackAdjustment = getLexer().getTok().getIntVal(); @@ -2508,7 +2535,7 @@ if (!RISCVZC::getSpimm(RlistVal, Spimm, StackAdjustment, isRV64(), IsEABI)) return MatchOperand_NoMatch; Operands.push_back(RISCVOperand::createSpimm(Spimm << 4, S)); - getLexer().Lex(); + Lex(); return MatchOperand_Success; } @@ -2565,7 +2592,7 @@ // If there are no more operands, then finish if (getLexer().is(AsmToken::EndOfStatement)) { - getParser().Lex(); // Consume the EndOfStatement. + Lex(); // Consume the EndOfStatement. return false; } @@ -2576,7 +2603,7 @@ // Parse until end of statement, consuming commas between operands while (getLexer().is(AsmToken::Comma)) { // Consume comma token - getLexer().Lex(); + Lex(); // Parse next operand if (parseOperand(Operands, Name)) @@ -2733,7 +2760,7 @@ StringRef Arch = Parser.getTok().getString(); SMLoc Loc = Parser.getTok().getLoc(); - Parser.Lex(); + Lex(); if (Type == RISCVOptionArchArgType::Full) { std::string Result; @@ -2879,7 +2906,7 @@ return false; } Tag = *Ret; - Parser.Lex(); + Lex(); } else { const MCExpr *AttrExpr; @@ -2921,7 +2948,7 @@ return Error(Parser.getTok().getLoc(), "expected string constant"); StringValue = Parser.getTok().getStringContents(); - Parser.Lex(); + Lex(); } if (Parser.parseEOL()) diff --git a/llvm/test/MC/RISCV/comments-zdinx.ll b/llvm/test/MC/RISCV/comments-zdinx.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/comments-zdinx.ll @@ -0,0 +1,4 @@ +# RUN: llvm-mc -triple=riscv64 --preserve-comments --mattr=+zdinx %s | FileCheck %s + +/*c0*/ fmadd.d /*c1*/ x10 /*c2*/ , /*c3*/ x12 /*c4*/ , /*c5*/ x14 /*c6*/ , /*c7*/ x16 /*c8*/ , /*c9*/ dyn /*c10*/ +// CHECK: fmadd.d a0, a2, a4, a6 #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 #c8 #c9 #c10 \ No newline at end of file diff --git a/llvm/test/MC/RISCV/comments.ll b/llvm/test/MC/RISCV/comments.ll new file mode 100644 --- /dev/null +++ b/llvm/test/MC/RISCV/comments.ll @@ -0,0 +1,70 @@ +# RUN: llvm-mc -triple=riscv64 --preserve-comments \ +# RUN: --mattr=+v,+experimental-zfa,+experimental-zcmp,+experimental-ztso %s \ +# RUN: | FileCheck %s + +/*c0*/ li /*c1*/ a0 /*c2*/ , /*c3*/ 0 /*c4*/ +# CHECK: li a0, 0 # c0 # c1 # c2 # c3 + +/*c0*/ lw /*c1*/ a0 /*c2*/ , /*c3*/ 0 /*c4*/ ( /*c5*/ a1 /*c6*/ ) /*c7*/ +# CHECK: lw a0, 0(a1) #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 + +/*c0*/ lw /*c1*/ a0 /*c2*/ , /*c3*/ ( /*c4*/ a1 /*c5*/ ) /*c6*/ +# CHECK: lw a0, 0(a1) #c0 #c1 #c2 #c3 #c4 #c5 #c6 + +/*c0*/ fli.s /*c1*/ ft0 /*c2*/ , /*c3*/ nan /*c4*/ +# CHECK: fli.s ft0, nan #c0 #c1 #c2 #c3 #c4 + +/*c0*/ fli.s /*c1*/ ft0 /*c2*/ , /*c3*/ 1.0 /*c4*/ +# CHECK: fli.s ft0, 1.0 #c0 #c1 #c2 #c3 #c4 + +/*c0*/ auipc /*c1*/ a0 /*c2*/ , /*c3*/ %pcrel_hi /*c4*/ ( /*c5*/ a1 /*c6*/ ) /*c7*/ +# CHECK: auipc a0, %pcrel_hi(a1) #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 + +/*c0*/ la /*c1*/ s0 /*c2*/ , /*c3*/ symbol /*c4*/ + /*c5*/ 10 /*c6*/ +# CHECK: .Lpcrel_hi0: #c0 #c1 #c2 #c3 #c4 #c5 #c6 +# CHECK: auipc s0, %pcrel_hi(symbol+10) +# CHECK: addi s0, s0, %pcrel_lo(.Lpcrel_hi0) + +/*c0*/ la /*c1*/ s0 /*c2*/ , /*c3*/ symbol /*c4*/ - /*c5*/ 10 +# CHECK: .Lpcrel_hi1: #c0 #c1 #c2 #c3 #c4 #c5 +# CHECK: auipc s0, %pcrel_hi(symbol-10) +# CHECK: addi s0, s0, %pcrel_lo(.Lpcrel_hi1) + +/*c0*/ vsetivli /*c1*/ a2 /*c2*/ , /*c3*/ 31 /*c4*/ , /*c5*/ e32 /*c6*/ , /*c7*/ m1 /*c8*/ , /*c9*/ ta /*c10*/ , /*c11*/ ma /*c12*/ +# CHECK: vsetivli a2, 31, e32, m1, ta, ma #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 #c8 #c9 #c10 #c11 #c12 + +/*c0*/ vadd.vv /*c1*/ v1 /*c2*/ , /*c3*/ v2 /*c4*/ , /*c5*/ v3 /*c6*/ , /*c7*/ v0.t /*c8*/ +# CHECK: vadd.vv v1, v2, v3, v0.t #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 #c8 + +/*c0*/ cm.push /*c1*/ { /*c2*/ ra /*c3*/ , /*c4*/ s0 /*c5*/ - /*c6*/ s1 /*c7*/ } /*c8*/ , /*c9*/ - /*c10*/ 32 /*c11*/ +# CHECK: cm.push {ra, s0-s1}, -32 #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 #c8 #c9 #c10 #c11 + +/*c0*/ cm.popret /*c0*/ { /*c1*/ x1 /*c2*/ , /*c3*/ x8 /*c4*/ - /*c5*/ x9 /*c6*/ , /*c7*/ x18 /*c8*/ - /*c9*/ x20 /*c10*/ } /*c11*/ , /*c12*/ 64 /*c13*/ +# CHECK: cm.popret {ra, s0-s4}, 64 #c0 #c0 #c1 #c2 #c3 #c4 #c5 #c6 #c7 #c8 #c9 #c10 #c11 #c12 #c13 + +/*c0*/ fence /*c1*/ 0 /*c2*/ , /*c3*/ 0 /*c4*/ +# CHECK: fence 0, 0 #c0 #c1 #c2 #c3 #c4 + +/*c0*/ fence /*c1*/ iorw /*c2*/ , /*c3*/ iorw /*c4*/ +# CHECK: fence #c0 #c1 #c2 #c3 #c4 + +/*c0*/ fence.tso /*c1*/ +# CHECK: fence.tso #c0 #c1 + +/*c0*/ fence.i /*c1*/ +# CHECK: fence.i #c0 #c1 + +/*c0*/ nop /*c1*/ +# CHECK: nop #c0 #c1 + +/*c0*/ .option /*c1*/ arch /*c2*/ , /*c3*/ rv64gc /*c4*/ +# CHECK: #c0 #c1 #c2 #c3 #c4 +# CHECK-NEXT: .option arch, rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0 + +/*c0*/ .attribute /*c1*/ priv_spec /*c2*/ , /*c3*/ 2 /*c4*/ +# CHECK: .attribute 8, 2 +# CHECK-NEXT: #c0 #c1 #c2 #c3 #c4 + +/*c0*/ .attribute /*c1*/ arch /*c2*/ , /*c3*/ "rv32i_zvfbfmin0p6" /*c4*/ +# CHECK: .attribute 5, "rv32i2p1_f2p2_zicsr2p0_zve32f1p0_zve32x1p0_zvfbfmin0p6_zvl32b1p0" +# CHECK-NEXT: #c0 #c1 #c2 #c3 #c4 \ No newline at end of file