[pdbdump] Print out New FPO stream contents.

The data strucutre in the new FPO stream is described in the
PE/COFF spec. There is one record per function if frame pointer
is omitted.

Differential Revision: http://reviews.llvm.org/D20999

llvm-svn: 271926
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
index 2c3dabf..1707454 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -669,3 +669,28 @@
   }
   return Error::success();
 }
+
+Error LLVMOutputStyle::dumpFpoStream() {
+  if (!opts::DumpFpo)
+    return Error::success();
+
+  auto DbiS = File.getPDBDbiStream();
+  if (auto EC = DbiS.takeError())
+    return EC;
+  DbiStream &DS = DbiS.get();
+
+  ListScope D(P, "New FPO");
+  for (const object::FpoData &Fpo : DS.getFpoRecords()) {
+    DictScope DD(P, "");
+    P.printNumber("Offset", Fpo.Offset);
+    P.printNumber("Size", Fpo.Size);
+    P.printNumber("Number of locals", Fpo.NumLocals);
+    P.printNumber("Number of params", Fpo.NumParams);
+    P.printNumber("Size of Prolog", Fpo.getPrologSize());
+    P.printNumber("Number of Saved Registers", Fpo.getNumSavedRegs());
+    P.printBoolean("Has SEH", Fpo.hasSEH());
+    P.printBoolean("Use BP", Fpo.useBP());
+    P.printNumber("Frame Pointer", Fpo.getFP());
+  }
+  return Error::success();
+}
diff --git a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
index 1643b42..0c601c9 100644
--- a/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
+++ b/llvm/tools/llvm-pdbdump/LLVMOutputStyle.h
@@ -33,6 +33,7 @@
   Error dumpSectionMap() override;
   Error dumpPublicsStream() override;
   Error dumpSectionHeaders() override;
+  Error dumpFpoStream() override;
 
 private:
   PDBFile &File;
diff --git a/llvm/tools/llvm-pdbdump/OutputStyle.h b/llvm/tools/llvm-pdbdump/OutputStyle.h
index d8ab0d4..c42f7d2 100644
--- a/llvm/tools/llvm-pdbdump/OutputStyle.h
+++ b/llvm/tools/llvm-pdbdump/OutputStyle.h
@@ -31,6 +31,7 @@
   virtual Error dumpSectionMap() = 0;
   virtual Error dumpPublicsStream() = 0;
   virtual Error dumpSectionHeaders() = 0;
+  virtual Error dumpFpoStream() = 0;
 };
 }
 }
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
index 4396c0d..b798929 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -154,6 +154,8 @@
 cl::opt<bool> DumpSectionHeaders("raw-section-headers",
                                  cl::desc("dump section headers"),
                                  cl::cat(NativeOptions));
+cl::opt<bool> DumpFpo("raw-fpo", cl::desc("dump FPO records"),
+                      cl::cat(NativeOptions));
 
 cl::opt<bool>
     RawAll("raw-all",
@@ -251,6 +253,9 @@
 
   if (auto EC = O->dumpSectionHeaders())
     return EC;
+
+  if (auto EC = O->dumpFpoStream())
+    return EC;
   return Error::success();
 }
 
@@ -291,6 +296,8 @@
     return true;
   if (opts::DumpLineInfo)
     return true;
+  if (opts::DumpFpo)
+    return true;
   return false;
 }
 
@@ -460,6 +467,7 @@
     opts::DumpSectionMap = true;
     opts::DumpSectionContribs = true;
     opts::DumpLineInfo = true;
+    opts::DumpFpo = true;
   }
 
   // When adding filters for excluded compilands and types, we need to remember
diff --git a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
index 4c12bea..4a6afae 100644
--- a/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
+++ b/llvm/tools/llvm-pdbdump/llvm-pdbdump.h
@@ -43,6 +43,7 @@
 extern llvm::cl::opt<bool> DumpSectionMap;
 extern llvm::cl::opt<bool> DumpSymRecordBytes;
 extern llvm::cl::opt<bool> DumpSectionHeaders;
+extern llvm::cl::opt<bool> DumpFpo;
 
 extern llvm::cl::opt<bool> ExcludeCompilerGenerated;