Index: include/llvm/CodeGen/MIRYamlMapping.h =================================================================== --- include/llvm/CodeGen/MIRYamlMapping.h +++ include/llvm/CodeGen/MIRYamlMapping.h @@ -55,10 +55,28 @@ static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } }; +struct FlowStringValue : StringValue { + FlowStringValue() {} + FlowStringValue(std::string Value) : StringValue(Value) {} +}; + +template <> struct ScalarTraits { + static void output(const FlowStringValue &S, void *, llvm::raw_ostream &OS) { + return ScalarTraits::output(S, nullptr, OS); + } + + static StringRef input(StringRef Scalar, void *Ctx, FlowStringValue &S) { + return ScalarTraits::input(Scalar, Ctx, S); + } + + static bool mustQuote(StringRef Scalar) { return needsQuotes(Scalar); } +}; + } // end namespace yaml } // end namespace llvm LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::StringValue) +LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::FlowStringValue) namespace llvm { namespace yaml { @@ -69,7 +87,8 @@ unsigned Alignment = 0; bool IsLandingPad = false; bool AddressTaken = false; - // TODO: Serialize the successors and liveins. + // TODO: Serialize the successor weights and liveins. + std::vector Successors; std::vector Instructions; }; @@ -82,6 +101,7 @@ YamlIO.mapOptional("alignment", MBB.Alignment); YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad); YamlIO.mapOptional("addressTaken", MBB.AddressTaken); + YamlIO.mapOptional("successors", MBB.Successors); YamlIO.mapOptional("instructions", MBB.Instructions); } }; Index: lib/CodeGen/MIRParser/MIParser.h =================================================================== --- lib/CodeGen/MIRParser/MIParser.h +++ lib/CodeGen/MIRParser/MIParser.h @@ -31,6 +31,11 @@ const DenseMap &MBBSlots, const SlotMapping &IRSlots, SMDiagnostic &Error); +MachineBasicBlock * +parseMBBReference(SourceMgr &SM, MachineFunction &MF, StringRef Src, + const DenseMap &MBBMapping, + const SlotMapping &IRSlots, SMDiagnostic &Error); + } // end namespace llvm #endif Index: lib/CodeGen/MIRParser/MIParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIParser.cpp +++ lib/CodeGen/MIRParser/MIParser.cpp @@ -64,10 +64,12 @@ bool error(StringRef::iterator Loc, const Twine &Msg); MachineInstr *parse(); + MachineBasicBlock *parseMBB(); bool parseRegister(unsigned &Reg); bool parseRegisterOperand(MachineOperand &Dest, bool IsDef = false); bool parseImmediateOperand(MachineOperand &Dest); + MachineBasicBlock *parseMBBReference(); bool parseMBBOperand(MachineOperand &Dest); bool parseGlobalAddressOperand(MachineOperand &Dest); bool parseMachineOperand(MachineOperand &Dest); @@ -190,6 +192,21 @@ return MI; } +MachineBasicBlock *MIParser::parseMBB() { + lex(); + if (Token.isNot(MIToken::MachineBasicBlock)) { + error("expected a machine basic block reference"); + return nullptr; + } + auto *MBB = parseMBBReference(); + lex(); + if (Token.is(MIToken::Eof)) + return MBB; + if (MBB) // Report this error only when MBB was parsed successfully. + error("expected end of string after the machine basic block reference"); + return nullptr; +} + bool MIParser::parseInstruction(unsigned &OpCode) { if (Token.isNot(MIToken::Identifier)) return error("expected a machine instruction"); @@ -250,22 +267,32 @@ return false; } -bool MIParser::parseMBBOperand(MachineOperand &Dest) { +MachineBasicBlock *MIParser::parseMBBReference() { assert(Token.is(MIToken::MachineBasicBlock)); unsigned Number; if (getUnsigned(Number)) - return true; + return nullptr; auto MBBInfo = MBBSlots.find(Number); - if (MBBInfo == MBBSlots.end()) - return error(Twine("use of undefined machine basic block #") + - Twine(Number)); + if (MBBInfo == MBBSlots.end()) { + error(Twine("use of undefined machine basic block #") + Twine(Number)); + return nullptr; + } MachineBasicBlock *MBB = MBBInfo->second; - if (!Token.stringValue().empty() && Token.stringValue() != MBB->getName()) - return error(Twine("the name of machine basic block #") + Twine(Number) + - " isn't '" + Token.stringValue() + "'"); - Dest = MachineOperand::CreateMBB(MBB); - lex(); - return false; + if (!Token.stringValue().empty() && Token.stringValue() != MBB->getName()) { + error(Twine("the name of machine basic block #") + Twine(Number) + + " isn't '" + Token.stringValue() + "'"); + return nullptr; + } + return MBB; +} + +bool MIParser::parseMBBOperand(MachineOperand &Dest) { + if (auto *MBB = parseMBBReference()) { + Dest = MachineOperand::CreateMBB(MBB); + lex(); + return false; + } + return true; } bool MIParser::parseGlobalAddressOperand(MachineOperand &Dest) { @@ -396,3 +423,10 @@ const SlotMapping &IRSlots, SMDiagnostic &Error) { return MIParser(SM, MF, Error, Src, MBBSlots, IRSlots).parse(); } + +MachineBasicBlock *llvm::parseMBBReference( + SourceMgr &SM, MachineFunction &MF, StringRef Src, + const DenseMap &MBBMapping, + const SlotMapping &IRSlots, SMDiagnostic &Error) { + return MIParser(SM, MF, Error, Src, MBBMapping, IRSlots).parseMBB(); +} Index: lib/CodeGen/MIRParser/MIRParser.cpp =================================================================== --- lib/CodeGen/MIRParser/MIRParser.cpp +++ lib/CodeGen/MIRParser/MIRParser.cpp @@ -262,9 +262,21 @@ if (YamlMBB.AddressTaken) MBB.setHasAddressTaken(); MBB.setIsLandingPad(YamlMBB.IsLandingPad); + SMDiagnostic Error; + // Parse the successors. + for (const auto &MBBSource : YamlMBB.Successors) { + if (auto *SuccMBB = parseMBBReference(SM, MF, MBBSource.Value, MBBSlots, + IRSlots, Error)) { + // TODO: Report an error when the successor is self. + // TODO: Report an error when adding the same successor more than once. + MBB.addSuccessor(SuccMBB); + continue; + } + reportDiagnostic(diagFromMIStringDiag(Error, MBBSource.SourceRange)); + return true; + } // Parse the instructions. for (const auto &MISource : YamlMBB.Instructions) { - SMDiagnostic Error; if (auto *MI = parseMachineInstr(SM, MF, MISource.Value, MBBSlots, IRSlots, Error)) { MBB.insert(MBB.end(), MI); Index: lib/CodeGen/MIRPrinter.cpp =================================================================== --- lib/CodeGen/MIRPrinter.cpp +++ lib/CodeGen/MIRPrinter.cpp @@ -61,6 +61,7 @@ : M(M), OS(OS), RegisterMaskIds(RegisterMaskIds) {} void print(const MachineInstr &MI); + void printMBBReference(const MachineBasicBlock &MBB); void print(const MachineOperand &Op, const TargetRegisterInfo *TRI); }; @@ -130,6 +131,12 @@ YamlMBB.Alignment = MBB.getAlignment(); YamlMBB.AddressTaken = MBB.hasAddressTaken(); YamlMBB.IsLandingPad = MBB.isLandingPad(); + for (const auto *MBB : MBB.successors()) { + std::string Str; + raw_string_ostream StrOS(Str); + MIPrinter(M, StrOS, RegisterMaskIds).printMBBReference(*MBB); + YamlMBB.Successors.push_back(StrOS.str()); + } // Print the machine instructions. YamlMBB.Instructions.reserve(MBB.size()); @@ -193,6 +200,14 @@ llvm_unreachable("Can't print this kind of register yet"); } +void MIPrinter::printMBBReference(const MachineBasicBlock &MBB) { + OS << "%bb." << MBB.getNumber(); + if (const auto *BB = MBB.getBasicBlock()) { + if (BB->hasName()) + OS << '.' << BB->getName(); + } +} + void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI) { switch (Op.getType()) { case MachineOperand::MO_Register: @@ -204,11 +219,7 @@ OS << Op.getImm(); break; case MachineOperand::MO_MachineBasicBlock: - OS << "%bb." << Op.getMBB()->getNumber(); - if (const auto *BB = Op.getMBB()->getBasicBlock()) { - if (BB->hasName()) - OS << '.' << BB->getName(); - } + printMBBReference(*Op.getMBB()); break; case MachineOperand::MO_GlobalAddress: // FIXME: Make this faster - print as operand will create a slot tracker to Index: test/CodeGen/MIR/expected-eof-after-successor-mbb.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/expected-eof-after-successor-mbb.mir @@ -0,0 +1,29 @@ +# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + define i32 @foo(i32 %a) { + entry: + %0 = icmp sle i32 %a, 10 + br i1 %0, label %less, label %exit + + less: + ret i32 0 + + exit: + ret i32 %a + } + +... +--- +name: foo +body: + - id: 0 + name: entry + # CHECK: [[@LINE+1]]:46: expected end of string after the machine basic block reference + successors: [ '%bb.1.less', '%bb.2.exit 2' ] + - id: 1 + name: less + - id: 2 + name: exit +... Index: test/CodeGen/MIR/expected-mbb-reference-for-successor-mbb.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/expected-mbb-reference-for-successor-mbb.mir @@ -0,0 +1,29 @@ +# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s + +--- | + + define i32 @foo(i32 %a) { + entry: + %0 = icmp sle i32 %a, 10 + br i1 %0, label %less, label %exit + + less: + ret i32 0 + + exit: + ret i32 %a + } + +... +--- +name: foo +body: + - id: 0 + name: entry + # CHECK: [[@LINE+1]]:35: expected a machine basic block reference + successors: [ '%bb.1.less', '2' ] + - id: 1 + name: less + - id: 2 + name: exit +... Index: test/CodeGen/MIR/successor-basic-blocks.mir =================================================================== --- /dev/null +++ test/CodeGen/MIR/successor-basic-blocks.mir @@ -0,0 +1,58 @@ +# RUN: llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the MIR parser parses basic block successors correctly. + +--- | + + define i32 @foo(i32 %a) { + entry: + %0 = icmp sle i32 %a, 10 + br i1 %0, label %less, label %exit + + less: + ret i32 0 + + exit: + ret i32 %a + } + + define i32 @bar(i32 %a) { + entry: + %b = icmp sle i32 %a, 10 + br i1 %b, label %0, label %1 + + ;