[PECOFF] Parse /merge command line option.

/merge:<from>=<to> option makes the linker to combine "from" section to "to"
section. This patch is to parse the option. The actual feature will be
implemented in a subsequent patch.

llvm-svn: 193454
diff --git a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
index 22edee7..8aacf3a 100644
--- a/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
@@ -23,6 +23,7 @@
 #include "lld/ReaderWriter/Writer.h"
 
 #include <bitset>
+#include <set>
 
 namespace lld {
 
@@ -101,6 +102,58 @@
   return true;
 }
 
+/// Returns the section name in the resulting executable.
+///
+/// Sections in object files are usually output to the executable with the same
+/// name, but you can rename by command line option. /merge:from=to makes the
+/// linker to combine "from" section contents to "to" section in the
+/// executable. We have a mapping for the renaming. This method looks up the
+/// table and returns a new section name if renamed.
+StringRef
+PECOFFLinkingContext::getFinalSectionName(StringRef sectionName) const {
+  auto it = _renamedSections.find(sectionName);
+  if (it == _renamedSections.end())
+    return sectionName;
+  return getFinalSectionName(it->second);
+}
+
+/// Adds a mapping to the section renaming table. This method will be used for
+/// /merge command line option.
+bool PECOFFLinkingContext::addSectionRenaming(raw_ostream &diagnostics,
+                                              StringRef from, StringRef to) {
+  auto it = _renamedSections.find(from);
+  if (it != _renamedSections.end()) {
+    if (it->second == to)
+      // There's already the same mapping.
+      return true;
+    diagnostics << "Section \"" << from << "\" is already mapped to \""
+                << it->second << ", so it cannot be mapped to \"" << to << "\".";
+    return true;
+  }
+
+  // Add a mapping, and check if there's no cycle in the renaming mapping. The
+  // cycle detection algorithm we use here is naive, but that's OK because the
+  // number of mapping is usually less than 10.
+  _renamedSections[from] = to;
+  for (auto elem : _renamedSections) {
+    StringRef sectionName = elem.first;
+    std::set<StringRef> visited;
+    visited.insert(sectionName);
+    for (;;) {
+      auto it = _renamedSections.find(sectionName);
+      if (it == _renamedSections.end())
+        break;
+      if (visited.count(it->second)) {
+        diagnostics << "/merge:" << from << "=" << to << " makes a cycle";
+        return false;
+      }
+      sectionName = it->second;
+      visited.insert(sectionName);
+    }
+  }
+  return true;
+}
+
 /// Try to find the input library file from the search paths and append it to
 /// the input file list. Returns true if the library file is found.
 StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const {