MIR Serialization: Serialize the unnamed basic block references.
authorAlex Lorenz <arphaman@gmail.com>
Mon, 27 Jul 2015 22:42:41 +0000 (22:42 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Mon, 27 Jul 2015 22:42:41 +0000 (22:42 +0000)
This commit serializes the references from the machine basic blocks to the
unnamed basic blocks.

This commit adds a new attribute to the machine basic block's YAML mapping
called 'ir-block'. This attribute contains the actual reference to the
basic block.

Reviewers: Duncan P. N. Exon Smith
llvm-svn: 243340

llvm/include/llvm/CodeGen/MIRYamlMapping.h
llvm/lib/CodeGen/MIRParser/MILexer.cpp
llvm/lib/CodeGen/MIRParser/MILexer.h
llvm/lib/CodeGen/MIRParser/MIParser.cpp
llvm/lib/CodeGen/MIRParser/MIParser.h
llvm/lib/CodeGen/MIRParser/MIRParser.cpp
llvm/lib/CodeGen/MIRPrinter.cpp
llvm/test/CodeGen/MIR/machine-basic-block-expected-ir-block.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/machine-basic-block-ir-block-reference.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/machine-basic-block-undefined-ir-block.mir [new file with mode: 0644]

index e14a1fd..903ba28 100644 (file)
@@ -135,6 +135,7 @@ template <> struct MappingTraits<MachineFunctionLiveIn> {
 struct MachineBasicBlock {
   unsigned ID;
   StringValue Name;
+  StringValue IRBlock;
   unsigned Alignment = 0;
   bool IsLandingPad = false;
   bool AddressTaken = false;
@@ -149,6 +150,8 @@ template <> struct MappingTraits<MachineBasicBlock> {
     YamlIO.mapRequired("id", MBB.ID);
     YamlIO.mapOptional("name", MBB.Name,
                        StringValue()); // Don't print out an empty name.
+    YamlIO.mapOptional("ir-block", MBB.IRBlock,
+                       StringValue()); // Don't print out an empty BB reference.
     YamlIO.mapOptional("alignment", MBB.Alignment);
     YamlIO.mapOptional("isLandingPad", MBB.IsLandingPad);
     YamlIO.mapOptional("addressTaken", MBB.AddressTaken);
index 2f038ff..d730dce 100644 (file)
@@ -219,6 +219,10 @@ static Cursor maybeLexConstantPoolItem(Cursor C, MIToken &Token) {
   return maybeLexIndex(C, Token, "%const.", MIToken::ConstantPoolItem);
 }
 
+static Cursor maybeLexIRBlock(Cursor C, MIToken &Token) {
+  return maybeLexIndex(C, Token, "%ir-block.", MIToken::IRBlock);
+}
+
 static Cursor lexVirtualRegister(Cursor C, MIToken &Token) {
   auto Range = C;
   C.advance(); // Skip '%'
@@ -351,6 +355,8 @@ StringRef llvm::lexMIToken(
     return R.remaining();
   if (Cursor R = maybeLexConstantPoolItem(C, Token))
     return R.remaining();
+  if (Cursor R = maybeLexIRBlock(C, Token))
+    return R.remaining();
   if (Cursor R = maybeLexRegister(C, Token))
     return R.remaining();
   if (Cursor R = maybeLexGlobalValue(C, Token, ErrorCallback))
index b84fb74..06fa1f2 100644 (file)
@@ -66,7 +66,8 @@ struct MIToken {
     IntegerLiteral,
     VirtualRegister,
     ConstantPoolItem,
-    JumpTableIndex
+    JumpTableIndex,
+    IRBlock,
   };
 
 private:
@@ -132,7 +133,8 @@ public:
     return Kind == IntegerLiteral || Kind == MachineBasicBlock ||
            Kind == StackObject || Kind == FixedStackObject ||
            Kind == GlobalValue || Kind == VirtualRegister ||
-           Kind == ConstantPoolItem || Kind == JumpTableIndex;
+           Kind == ConstantPoolItem || Kind == JumpTableIndex ||
+           Kind == IRBlock;
   }
 };
 
index c46adf5..1bdaedb 100644 (file)
@@ -23,6 +23,7 @@
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include "llvm/IR/Instructions.h"
 #include "llvm/IR/Module.h"
+#include "llvm/IR/ModuleSlotTracker.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/SourceMgr.h"
 #include "llvm/Target/TargetSubtargetInfo.h"
@@ -77,6 +78,8 @@ class MIParser {
   StringMap<const uint32_t *> Names2RegMasks;
   /// Maps from subregister names to subregister indices.
   StringMap<unsigned> Names2SubRegIndices;
+  /// Maps from slot numbers to function's unnamed basic blocks.
+  DenseMap<unsigned, const BasicBlock *> Slots2BasicBlocks;
 
 public:
   MIParser(SourceMgr &SM, MachineFunction &MF, SMDiagnostic &Error,
@@ -99,6 +102,7 @@ public:
   bool parseStandaloneMBB(MachineBasicBlock *&MBB);
   bool parseStandaloneNamedRegister(unsigned &Reg);
   bool parseStandaloneVirtualRegister(unsigned &Reg);
+  bool parseStandaloneIRBlockReference(const BasicBlock *&BB);
 
   bool parseRegister(unsigned &Reg);
   bool parseRegisterFlag(unsigned &Flags);
@@ -160,6 +164,10 @@ private:
   ///
   /// Return 0 if the name isn't a subregister index class.
   unsigned getSubRegIndex(StringRef Name);
+
+  void initSlots2BasicBlocks();
+
+  const BasicBlock *getIRBlock(unsigned Slot);
 };
 
 } // end anonymous namespace
@@ -302,6 +310,23 @@ 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";
@@ -842,6 +867,30 @@ unsigned MIParser::getSubRegIndex(StringRef Name) {
   return SubRegInfo->getValue();
 }
 
+void MIParser::initSlots2BasicBlocks() {
+  if (!Slots2BasicBlocks.empty())
+    return;
+  const auto &F = *MF.getFunction();
+  ModuleSlotTracker MST(F.getParent());
+  MST.incorporateFunction(F);
+  for (auto &BB : F) {
+    if (BB.hasName())
+      continue;
+    int Slot = MST.getLocalSlot(&BB);
+    if (Slot == -1)
+      continue;
+    Slots2BasicBlocks.insert(std::make_pair(unsigned(Slot), &BB));
+  }
+}
+
+const BasicBlock *MIParser::getIRBlock(unsigned Slot) {
+  initSlots2BasicBlocks();
+  auto BlockInfo = Slots2BasicBlocks.find(Slot);
+  if (BlockInfo == Slots2BasicBlocks.end())
+    return nullptr;
+  return BlockInfo->second;
+}
+
 bool llvm::parseMachineInstr(MachineInstr *&MI, SourceMgr &SM,
                              MachineFunction &MF, StringRef Src,
                              const PerFunctionMIParsingState &PFS,
@@ -873,3 +922,12 @@ 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);
+}
index 49530f1..92698f6 100644 (file)
@@ -19,6 +19,7 @@
 
 namespace llvm {
 
+class BasicBlock;
 class MachineBasicBlock;
 class MachineInstr;
 class MachineFunction;
@@ -56,6 +57,11 @@ bool parseVirtualRegisterReference(unsigned &Reg, SourceMgr &SM,
                                    const SlotMapping &IRSlots,
                                    SMDiagnostic &Error);
 
+bool parseIRBlockReference(const BasicBlock *&BB, SourceMgr &SM,
+                           MachineFunction &MF, StringRef Src,
+                           const PerFunctionMIParsingState &PFS,
+                           const SlotMapping &IRSlots, SMDiagnostic &Error);
+
 } // end namespace llvm
 
 #endif
index 45b4019..f733d63 100644 (file)
@@ -292,6 +292,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
   for (const auto &YamlMBB : YamlMF.BasicBlocks) {
     const BasicBlock *BB = nullptr;
     const yaml::StringValue &Name = YamlMBB.Name;
+    const yaml::StringValue &IRBlock = YamlMBB.IRBlock;
     if (!Name.Value.empty()) {
       BB = dyn_cast_or_null<BasicBlock>(
           F.getValueSymbolTable().lookup(Name.Value));
@@ -301,6 +302,12 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
                          "' is not defined in the function '" + MF.getName() +
                          "'");
     }
+    if (!IRBlock.Value.empty()) {
+      // TODO: Report an error when both name and ir block are specified.
+      SMDiagnostic Error;
+      if (parseIRBlockReference(BB, SM, MF, IRBlock.Value, PFS, IRSlots, Error))
+        return error(Error, IRBlock.SourceRange);
+    }
     auto *MBB = MF.CreateMachineBasicBlock(BB);
     MF.insert(MF.end(), MBB);
     bool WasInserted =
index 3db6368..cb20df8 100644 (file)
@@ -163,6 +163,7 @@ void MIRPrinter::print(const MachineFunction &MF) {
     convert(YamlMF, *ConstantPool);
 
   ModuleSlotTracker MST(MF.getFunction()->getParent());
+  MST.incorporateFunction(*MF.getFunction());
   if (const auto *JumpTableInfo = MF.getJumpTableInfo())
     convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
   int I = 0;
@@ -336,11 +337,17 @@ void MIRPrinter::convert(ModuleSlotTracker &MST,
                          const MachineBasicBlock &MBB) {
   assert(MBB.getNumber() >= 0 && "Invalid MBB number");
   YamlMBB.ID = (unsigned)MBB.getNumber();
-  // TODO: Serialize unnamed BB references.
-  if (const auto *BB = MBB.getBasicBlock())
-    YamlMBB.Name.Value = BB->hasName() ? BB->getName() : "<unnamed bb>";
-  else
-    YamlMBB.Name.Value = "";
+  if (const auto *BB = MBB.getBasicBlock()) {
+    if (BB->hasName()) {
+      YamlMBB.Name.Value = BB->getName();
+    } else {
+      int Slot = MST.getLocalSlot(BB);
+      if (Slot == -1)
+        YamlMBB.IRBlock.Value = "<badref>";
+      else
+        YamlMBB.IRBlock.Value = (Twine("%ir-block.") + Twine(Slot)).str();
+    }
+  }
   YamlMBB.Alignment = MBB.getAlignment();
   YamlMBB.AddressTaken = MBB.hasAddressTaken();
   YamlMBB.IsLandingPad = MBB.isLandingPad();
diff --git a/llvm/test/CodeGen/MIR/machine-basic-block-expected-ir-block.mir b/llvm/test/CodeGen/MIR/machine-basic-block-expected-ir-block.mir
new file mode 100644 (file)
index 0000000..2f3d40a
--- /dev/null
@@ -0,0 +1,16 @@
+# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+  define i32 @foo() {
+    ret i32 0
+  }
+
+...
+---
+name:            foo
+body:
+ - id:           0
+# CHECK: [[@LINE+1]]:19: expected an IR block reference
+   ir-block:     '0'
+...
diff --git a/llvm/test/CodeGen/MIR/machine-basic-block-ir-block-reference.mir b/llvm/test/CodeGen/MIR/machine-basic-block-ir-block-reference.mir
new file mode 100644 (file)
index 0000000..ccbab53
--- /dev/null
@@ -0,0 +1,19 @@
+# RUN: llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser preserves unnamed LLVM IR block
+# references.
+
+--- |
+
+  define i32 @foo() {
+    ret i32 0
+  }
+
+...
+---
+name:            foo
+body:
+# CHECK: id: 0
+# CHECK: ir-block: '%ir-block.0'
+ - id:           0
+   ir-block:     '%ir-block.0'
+...
diff --git a/llvm/test/CodeGen/MIR/machine-basic-block-undefined-ir-block.mir b/llvm/test/CodeGen/MIR/machine-basic-block-undefined-ir-block.mir
new file mode 100644 (file)
index 0000000..76d561e
--- /dev/null
@@ -0,0 +1,16 @@
+# RUN: not llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+  define i32 @foo() {
+    ret i32 0
+  }
+
+...
+---
+name:            foo
+body:
+ - id:           0
+# CHECK: [[@LINE+1]]:19: use of undefined IR block '%ir-block.10'
+   ir-block:     '%ir-block.10'
+...