diff options
Diffstat (limited to 'llvm/lib/CodeGen/MIRParser/MIParser.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MIRParser/MIParser.cpp | 323 |
1 files changed, 281 insertions, 42 deletions
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 46ad8769fd3..3a0e52491ca 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -90,11 +90,19 @@ public: /// This function always return true. bool error(StringRef::iterator Loc, const Twine &Msg); + bool + parseBasicBlockDefinitions(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots); + bool parseBasicBlocks(); bool parse(MachineInstr *&MI); bool parseStandaloneMBB(MachineBasicBlock *&MBB); bool parseStandaloneNamedRegister(unsigned &Reg); bool parseStandaloneVirtualRegister(unsigned &Reg); - bool parseStandaloneIRBlockReference(const BasicBlock *&BB); + + bool + parseBasicBlockDefinition(DenseMap<unsigned, MachineBasicBlock *> &MBBSlots); + bool parseBasicBlock(MachineBasicBlock &MBB); + bool parseBasicBlockLiveins(MachineBasicBlock &MBB); + bool parseBasicBlockSuccessors(MachineBasicBlock &MBB); bool parseRegister(unsigned &Reg); bool parseRegisterFlag(unsigned &Flags); @@ -149,6 +157,10 @@ private: /// Otherwise report an error and return true. bool expectAndConsume(MIToken::TokenKind TokenKind); + /// If the current token is of the given kind, consume it and return true. + /// Otherwise return false. + bool consumeIfPresent(MIToken::TokenKind TokenKind); + void initNames2InstrOpCodes(); /// Try to convert an instruction name to an opcode. Return true if the @@ -217,10 +229,17 @@ bool MIParser::error(const Twine &Msg) { return error(Token.location(), Msg); } bool MIParser::error(StringRef::iterator Loc, const Twine &Msg) { assert(Loc >= Source.data() && Loc <= (Source.data() + Source.size())); - Error = SMDiagnostic( - SM, SMLoc(), - SM.getMemoryBuffer(SM.getMainFileID())->getBufferIdentifier(), 1, - Loc - Source.data(), SourceMgr::DK_Error, Msg.str(), Source, None, None); + const MemoryBuffer &Buffer = *SM.getMemoryBuffer(SM.getMainFileID()); + if (Loc >= Buffer.getBufferStart() && Loc <= Buffer.getBufferEnd()) { + // Create an ordinary diagnostic when the source manager's buffer is the + // source string. + Error = SM.GetMessage(SMLoc::getFromPointer(Loc), SourceMgr::DK_Error, Msg); + return true; + } + // Create a diagnostic for a YAML string literal. + Error = SMDiagnostic(SM, SMLoc(), Buffer.getBufferIdentifier(), 1, + Loc - Source.data(), SourceMgr::DK_Error, Msg.str(), + Source, None, None); return true; } @@ -230,6 +249,8 @@ static const char *toString(MIToken::TokenKind TokenKind) { return "','"; case MIToken::equal: return "'='"; + case MIToken::colon: + return "':'"; case MIToken::lparen: return "'('"; case MIToken::rparen: @@ -246,9 +267,236 @@ bool MIParser::expectAndConsume(MIToken::TokenKind TokenKind) { return false; } -bool MIParser::parse(MachineInstr *&MI) { +bool MIParser::consumeIfPresent(MIToken::TokenKind TokenKind) { + if (Token.isNot(TokenKind)) + return false; + lex(); + return true; +} + +bool MIParser::parseBasicBlockDefinition( + DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) { + assert(Token.is(MIToken::MachineBasicBlockLabel)); + unsigned ID = 0; + if (getUnsigned(ID)) + return true; + auto Loc = Token.location(); + auto Name = Token.stringValue(); + lex(); + bool HasAddressTaken = false; + bool IsLandingPad = false; + unsigned Alignment = 0; + BasicBlock *BB = nullptr; + if (consumeIfPresent(MIToken::lparen)) { + do { + // TODO: Report an error when multiple same attributes are specified. + switch (Token.kind()) { + case MIToken::kw_address_taken: + HasAddressTaken = true; + lex(); + break; + case MIToken::kw_landing_pad: + IsLandingPad = true; + lex(); + break; + case MIToken::kw_align: + if (parseAlignment(Alignment)) + return true; + break; + case MIToken::IRBlock: + // TODO: Report an error when both name and ir block are specified. + if (parseIRBlock(BB, *MF.getFunction())) + return true; + lex(); + break; + default: + break; + } + } while (consumeIfPresent(MIToken::comma)); + if (expectAndConsume(MIToken::rparen)) + return true; + } + if (expectAndConsume(MIToken::colon)) + return true; + + if (!Name.empty()) { + BB = dyn_cast_or_null<BasicBlock>( + MF.getFunction()->getValueSymbolTable().lookup(Name)); + if (!BB) + return error(Loc, Twine("basic block '") + Name + + "' is not defined in the function '" + + MF.getName() + "'"); + } + auto *MBB = MF.CreateMachineBasicBlock(BB); + MF.insert(MF.end(), MBB); + bool WasInserted = MBBSlots.insert(std::make_pair(ID, MBB)).second; + if (!WasInserted) + return error(Loc, Twine("redefinition of machine basic block with id #") + + Twine(ID)); + if (Alignment) + MBB->setAlignment(Alignment); + if (HasAddressTaken) + MBB->setHasAddressTaken(); + MBB->setIsLandingPad(IsLandingPad); + return false; +} + +bool MIParser::parseBasicBlockDefinitions( + DenseMap<unsigned, MachineBasicBlock *> &MBBSlots) { + lex(); + // Skip until the first machine basic block. + while (Token.is(MIToken::Newline)) + lex(); + if (Token.isErrorOrEOF()) + return Token.isError(); + if (Token.isNot(MIToken::MachineBasicBlockLabel)) + return error("expected a basic block definition before instructions"); + do { + if (parseBasicBlockDefinition(MBBSlots)) + return true; + bool IsAfterNewline = false; + // Skip until the next machine basic block. + while (true) { + if ((Token.is(MIToken::MachineBasicBlockLabel) && IsAfterNewline) || + Token.isErrorOrEOF()) + break; + else if (Token.is(MIToken::MachineBasicBlockLabel)) + return error("basic block definition should be located at the start of " + "the line"); + if (Token.is(MIToken::Newline)) + IsAfterNewline = true; + else + IsAfterNewline = false; + lex(); + } + } while (!Token.isErrorOrEOF()); + return Token.isError(); +} + +bool MIParser::parseBasicBlockLiveins(MachineBasicBlock &MBB) { + assert(Token.is(MIToken::kw_liveins)); + lex(); + if (expectAndConsume(MIToken::colon)) + return true; + if (Token.isNewlineOrEOF()) // Allow an empty list of liveins. + return false; + do { + if (Token.isNot(MIToken::NamedRegister)) + return error("expected a named register"); + unsigned Reg = 0; + if (parseRegister(Reg)) + return true; + MBB.addLiveIn(Reg); + lex(); + } while (consumeIfPresent(MIToken::comma)); + return false; +} + +bool MIParser::parseBasicBlockSuccessors(MachineBasicBlock &MBB) { + assert(Token.is(MIToken::kw_successors)); lex(); + if (expectAndConsume(MIToken::colon)) + return true; + if (Token.isNewlineOrEOF()) // Allow an empty list of successors. + return false; + do { + if (Token.isNot(MIToken::MachineBasicBlock)) + return error("expected a machine basic block reference"); + MachineBasicBlock *SuccMBB = nullptr; + if (parseMBBReference(SuccMBB)) + return true; + lex(); + unsigned Weight = 0; + if (consumeIfPresent(MIToken::lparen)) { + if (Token.isNot(MIToken::IntegerLiteral)) + return error("expected an integer literal after '('"); + if (getUnsigned(Weight)) + return true; + lex(); + if (expectAndConsume(MIToken::rparen)) + return true; + } + MBB.addSuccessor(SuccMBB, Weight); + } while (consumeIfPresent(MIToken::comma)); + return false; +} + +bool MIParser::parseBasicBlock(MachineBasicBlock &MBB) { + // Skip the definition. + assert(Token.is(MIToken::MachineBasicBlockLabel)); + lex(); + if (consumeIfPresent(MIToken::lparen)) { + while (Token.isNot(MIToken::rparen) && !Token.isErrorOrEOF()) + lex(); + consumeIfPresent(MIToken::rparen); + } + consumeIfPresent(MIToken::colon); + + // Parse the liveins and successors. + // N.B: Multiple lists of successors and liveins are allowed and they're + // merged into one. + // Example: + // liveins: %edi + // liveins: %esi + // + // is equivalent to + // liveins: %edi, %esi + while (true) { + if (Token.is(MIToken::kw_successors)) { + if (parseBasicBlockSuccessors(MBB)) + return true; + } else if (Token.is(MIToken::kw_liveins)) { + if (parseBasicBlockLiveins(MBB)) + return true; + } else if (consumeIfPresent(MIToken::Newline)) { + continue; + } else + break; + if (!Token.isNewlineOrEOF()) + return error("expected line break at the end of a list"); + lex(); + } + + // Parse the instructions. + while (true) { + if (Token.is(MIToken::MachineBasicBlockLabel) || Token.is(MIToken::Eof)) + return false; + else if (consumeIfPresent(MIToken::Newline)) + continue; + MachineInstr *MI = nullptr; + if (parse(MI)) + return true; + MBB.insert(MBB.end(), MI); + assert(Token.isNewlineOrEOF() && "MI is not fully parsed"); + lex(); + } + return false; +} + +bool MIParser::parseBasicBlocks() { + lex(); + // Skip until the first machine basic block. + while (Token.is(MIToken::Newline)) + lex(); + if (Token.isErrorOrEOF()) + return Token.isError(); + // The first parsing pass should have verified that this token is a MBB label + // in the 'parseBasicBlockDefinitions' method. + assert(Token.is(MIToken::MachineBasicBlockLabel)); + do { + MachineBasicBlock *MBB = nullptr; + if (parseMBBReference(MBB)) + return true; + if (parseBasicBlock(*MBB)) + return true; + // The method 'parseBasicBlock' should parse the whole block until the next + // block or the end of file. + assert(Token.is(MIToken::MachineBasicBlockLabel) || Token.is(MIToken::Eof)); + } while (Token.isNot(MIToken::Eof)); + return false; +} +bool MIParser::parse(MachineInstr *&MI) { // Parse any register operands before '=' MachineOperand MO = MachineOperand::CreateImm(0); SmallVector<MachineOperandWithLocation, 8> Operands; @@ -271,13 +519,13 @@ bool MIParser::parse(MachineInstr *&MI) { // TODO: Parse the bundle instruction flags. // Parse the remaining machine operands. - while (Token.isNot(MIToken::Eof) && Token.isNot(MIToken::kw_debug_location) && + while (!Token.isNewlineOrEOF() && Token.isNot(MIToken::kw_debug_location) && Token.isNot(MIToken::coloncolon)) { auto Loc = Token.location(); if (parseMachineOperandAndTargetFlags(MO)) return true; Operands.push_back(MachineOperandWithLocation(MO, Loc, Token.location())); - if (Token.is(MIToken::Eof) || Token.is(MIToken::coloncolon)) + if (Token.isNewlineOrEOF() || Token.is(MIToken::coloncolon)) break; if (Token.isNot(MIToken::comma)) return error("expected ',' before the next machine operand"); @@ -299,12 +547,12 @@ bool MIParser::parse(MachineInstr *&MI) { SmallVector<MachineMemOperand *, 2> MemOperands; if (Token.is(MIToken::coloncolon)) { lex(); - while (Token.isNot(MIToken::Eof)) { + while (!Token.isNewlineOrEOF()) { MachineMemOperand *MemOp = nullptr; if (parseMachineMemoryOperand(MemOp)) return true; MemOperands.push_back(MemOp); - if (Token.is(MIToken::Eof)) + if (Token.isNewlineOrEOF()) break; if (Token.isNot(MIToken::comma)) return error("expected ',' before the next machine memory operand"); @@ -370,23 +618,6 @@ bool MIParser::parseStandaloneVirtualRegister(unsigned &Reg) { return false; } -bool MIParser::parseStandaloneIRBlockReference(const BasicBlock *&BB) { - lex(); - if (Token.isNot(MIToken::IRBlock)) - return error("expected an IR block reference"); - unsigned SlotNumber = 0; - if (getUnsigned(SlotNumber)) - return true; - BB = getIRBlock(SlotNumber); - if (!BB) - return error(Twine("use of undefined IR block '%ir-block.") + - Twine(SlotNumber) + "'"); - lex(); - if (Token.isNot(MIToken::Eof)) - return error("expected end of string after the IR block reference"); - return false; -} - static const char *printImplicitRegisterFlag(const MachineOperand &MO) { assert(MO.isImplicit()); return MO.isDef() ? "implicit-def" : "implicit"; @@ -621,7 +852,8 @@ bool MIParser::getUnsigned(unsigned &Result) { } bool MIParser::parseMBBReference(MachineBasicBlock *&MBB) { - assert(Token.is(MIToken::MachineBasicBlock)); + assert(Token.is(MIToken::MachineBasicBlock) || + Token.is(MIToken::MachineBasicBlockLabel)); unsigned Number; if (getUnsigned(Number)) return true; @@ -1406,11 +1638,27 @@ bool MIParser::getDirectTargetFlag(StringRef Name, unsigned &Flag) { return false; } -bool llvm::parseMachineInstr(MachineInstr *&MI, SourceMgr &SM, - MachineFunction &MF, StringRef Src, - const PerFunctionMIParsingState &PFS, - const SlotMapping &IRSlots, SMDiagnostic &Error) { - return MIParser(SM, MF, Error, Src, PFS, IRSlots).parse(MI); +bool llvm::parseMachineBasicBlockDefinitions(MachineFunction &MF, StringRef Src, + PerFunctionMIParsingState &PFS, + const SlotMapping &IRSlots, + SMDiagnostic &Error) { + SourceMgr SM; + SM.AddNewSourceBuffer( + MemoryBuffer::getMemBuffer(Src, "", /*RequiresNullTerminator=*/false), + SMLoc()); + return MIParser(SM, MF, Error, Src, PFS, IRSlots) + .parseBasicBlockDefinitions(PFS.MBBSlots); +} + +bool llvm::parseMachineInstructions(MachineFunction &MF, StringRef Src, + const PerFunctionMIParsingState &PFS, + const SlotMapping &IRSlots, + SMDiagnostic &Error) { + SourceMgr SM; + SM.AddNewSourceBuffer( + MemoryBuffer::getMemBuffer(Src, "", /*RequiresNullTerminator=*/false), + SMLoc()); + return MIParser(SM, MF, Error, Src, PFS, IRSlots).parseBasicBlocks(); } bool llvm::parseMBBReference(MachineBasicBlock *&MBB, SourceMgr &SM, @@ -1437,12 +1685,3 @@ bool llvm::parseVirtualRegisterReference(unsigned &Reg, SourceMgr &SM, return MIParser(SM, MF, Error, Src, PFS, IRSlots) .parseStandaloneVirtualRegister(Reg); } - -bool llvm::parseIRBlockReference(const BasicBlock *&BB, SourceMgr &SM, - MachineFunction &MF, StringRef Src, - const PerFunctionMIParsingState &PFS, - const SlotMapping &IRSlots, - SMDiagnostic &Error) { - return MIParser(SM, MF, Error, Src, PFS, IRSlots) - .parseStandaloneIRBlockReference(BB); -} |