[lld] Fix type server merging with PDBs without IPI stream

PDBs may not necessarily contain an IPI stream. Handle this case
gracefully.

The test case was verified to work with MS link.exe.

Patch by Vladimir Panteleev, with a small simplification

Reviewed By: rnk

Differential Revision: https://reviews.llvm.org/D63178

git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@363213 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index 6ea4c34..43714e6 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -434,9 +434,13 @@
   Expected<pdb::TpiStream &> ExpectedTpi = PDBFile.getPDBTpiStream();
   if (auto E = ExpectedTpi.takeError())
     fatal("Type server does not have TPI stream: " + toString(std::move(E)));
-  Expected<pdb::TpiStream &> ExpectedIpi = PDBFile.getPDBIpiStream();
-  if (auto E = ExpectedIpi.takeError())
-    fatal("Type server does not have TPI stream: " + toString(std::move(E)));
+  pdb::TpiStream *MaybeIpi = nullptr;
+  if (PDBFile.hasPDBIpiStream()) {
+    Expected<pdb::TpiStream &> ExpectedIpi = PDBFile.getPDBIpiStream();
+    if (auto E = ExpectedIpi.takeError())
+      fatal("Error getting type server IPI stream: " + toString(std::move(E)));
+    MaybeIpi = &*ExpectedIpi;
+  }
 
   if (Config->DebugGHashes) {
     // PDBs do not actually store global hashes, so when merging a type server
@@ -445,9 +449,6 @@
     // synthesize hashes for the IPI stream, using the hashes for the TPI stream
     // as inputs.
     auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray());
-    auto IpiHashes =
-        GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes);
-
     Optional<uint32_t> EndPrecomp;
     // Merge TPI first, because the IPI stream will reference type indices.
     if (auto Err =
@@ -456,10 +457,14 @@
       fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
 
     // Merge IPI.
-    if (auto Err = mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap,
-                                  IndexMap.IPIMap, ExpectedIpi->typeArray(),
-                                  IpiHashes))
-      fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+    if (MaybeIpi) {
+      auto IpiHashes =
+          GloballyHashedType::hashIds(MaybeIpi->typeArray(), TpiHashes);
+      if (auto Err =
+              mergeIdRecords(TMerger.GlobalIDTable, IndexMap.TPIMap,
+                             IndexMap.IPIMap, MaybeIpi->typeArray(), IpiHashes))
+        fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+    }
   } else {
     // Merge TPI first, because the IPI stream will reference type indices.
     if (auto Err = mergeTypeRecords(TMerger.TypeTable, IndexMap.TPIMap,
@@ -467,9 +472,11 @@
       fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));
 
     // Merge IPI.
-    if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap,
-                                  IndexMap.IPIMap, ExpectedIpi->typeArray()))
-      fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+    if (MaybeIpi) {
+      if (auto Err = mergeIdRecords(TMerger.IDTable, IndexMap.TPIMap,
+                                    IndexMap.IPIMap, MaybeIpi->typeArray()))
+        fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));
+    }
   }
 
   return IndexMap;
diff --git a/test/COFF/Inputs/no-ipi-stream-obj.obj.yaml b/test/COFF/Inputs/no-ipi-stream-obj.obj.yaml
new file mode 100644
index 0000000..b244b50
--- /dev/null
+++ b/test/COFF/Inputs/no-ipi-stream-obj.obj.yaml
@@ -0,0 +1,13 @@
+--- !COFF
+header:          
+  Machine:         IMAGE_FILE_MACHINE_I386
+sections:        
+  - Name:            '.debug$T'
+    Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+    Types:           
+      - Kind:            LF_TYPESERVER2
+        TypeServer2:     
+          Guid:            '{01234567-0123-0123-0123-0123456789AB}'
+          Age:             1
+          Name:            'no-ipi-stream-pdb.pdb'
+symbols:         
diff --git a/test/COFF/Inputs/no-ipi-stream-pdb.pdb.yaml b/test/COFF/Inputs/no-ipi-stream-pdb.pdb.yaml
new file mode 100644
index 0000000..f3ac693
--- /dev/null
+++ b/test/COFF/Inputs/no-ipi-stream-pdb.pdb.yaml
@@ -0,0 +1,2 @@
+PdbStream:       
+  Guid:            '{01234567-0123-0123-0123-0123456789AB}'
diff --git a/test/COFF/no-ipi-stream.test b/test/COFF/no-ipi-stream.test
new file mode 100644
index 0000000..246c359
--- /dev/null
+++ b/test/COFF/no-ipi-stream.test
@@ -0,0 +1,4 @@
+# RUN: rm -rf %t && mkdir %t
+# RUN: yaml2obj < %p/Inputs/no-ipi-stream-obj.obj.yaml > %t/no-ipi-stream-obj.obj
+# RUN: llvm-pdbutil yaml2pdb %p/Inputs/no-ipi-stream-pdb.pdb.yaml -pdb=%t/no-ipi-stream-pdb.pdb
+# RUN: lld-link /dll /noentry /debug %t/no-ipi-stream-obj.obj