<div dir="ltr">Looks like this should also be done for ThinLTO, and your changes to gold-plugin and llvm-link cover the ThinLTO case through those tools. I think to cover the rest of the ThinLTO cases we need to call <span style="font-size:12.8px">ensureDITypeMap() in these cases:</span><div><span style="font-size:12.8px">1) For libLTO via ThinLTOCodeGenerator.cpp: where the backend threads are creat</span>ed with new contexts in ThinLTOCodeGenerator::run</div><div>2) For opt, which can add the function import pass (maybe the same way you have this done in llvm-link, by default with an option to disable?).</div><div>3) When launching backend threads in separate processes for distributed builds, via the clang -fthinlto-index= option. I think we would call your new routine in BackendUtil.cpp where it checks if CodeGenOpts.ThinLTOIndexFile.empty and if so build the index.</div><div><br></div><div>Let me know if that sounds right, I can add the calls.</div><div><br></div><div>Thanks,</div><div>Teresa</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Apr 16, 2016 at 8:58 PM, Duncan P. N. Exon Smith via llvm-commits <span dir="ltr"><<a href="mailto:llvm-commits@lists.llvm.org" target="_blank">llvm-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: dexonsmith<br>
Date: Sat Apr 16 22:58:21 2016<br>
New Revision: 266549<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=266549&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=266549&view=rev</a><br>
Log:<br>
IR: Use an explicit map for debug info type uniquing<br>
<br>
Rather than relying on the structural equivalence of DICompositeType to<br>
merge type definitions, use an explicit map on the LLVMContext that<br>
LLParser and BitcodeReader consult when constructing new nodes.<br>
Each non-forward-declaration DICompositeType with a non-empty<br>
'identifier:' field is stored/loaded from the type map, and the first<br>
definiton will "win".<br>
<br>
This map is opt-in: clients that expect ODR types from different modules<br>
to be merged must call LLVMContext::ensureDITypeMap.<br>
<br>
  - Clients that just happen to load more than one Module in the same<br>
    LLVMContext won't magically merge types.<br>
<br>
  - Clients (like LTO) that want to continue to merge types based on ODR<br>
    identifiers should opt-in immediately.<br>
<br>
I have updated LTOCodeGenerator.cpp, the two "linking" spots in<br>
gold-plugin.cpp, and llvm-link (unless -disable-debug-info-type-map) to<br>
set this.<br>
<br>
With this in place, it will be straightforward to remove the DITypeRef<br>
concept (i.e., referencing types by their 'identifier:' string rather<br>
than pointing at them directly).<br>
<br>
Added:<br>
    llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll<br>
    llvm/trunk/test/Linker/dicompositetype-unique.ll<br>
    llvm/trunk/unittests/IR/LLVMContextTest.cpp<br>
Modified:<br>
    llvm/trunk/docs/LangRef.rst<br>
    llvm/trunk/include/llvm/IR/LLVMContext.h<br>
    llvm/trunk/lib/AsmParser/LLParser.cpp<br>
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
    llvm/trunk/lib/IR/DebugInfoMetadata.cpp<br>
    llvm/trunk/lib/IR/LLVMContext.cpp<br>
    llvm/trunk/lib/IR/LLVMContextImpl.h<br>
    llvm/trunk/lib/LTO/LTOCodeGenerator.cpp<br>
    llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp<br>
    llvm/trunk/tools/gold/gold-plugin.cpp<br>
    llvm/trunk/tools/llvm-link/llvm-link.cpp<br>
    llvm/trunk/unittests/IR/CMakeLists.txt<br>
<br>
Modified: llvm/trunk/docs/LangRef.rst<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/docs/LangRef.rst?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/docs/LangRef.rst (original)<br>
+++ llvm/trunk/docs/LangRef.rst Sat Apr 16 22:58:21 2016<br>
@@ -4006,6 +4006,11 @@ identifier used for type merging between<br>
 can refer to composite types indirectly via a :ref:`metadata string<br>
 <metadata-string>` that matches their identifier.<br>
<br>
+For a given ``identifier:``, there should only be a single composite type that<br>
+does not have  ``flags: DIFlagFwdDecl`` set.  LLVM tools that link modules<br>
+together will unique such definitions at parse time via the ``identifier:``<br>
+field, even if the nodes are ``distinct``.<br>
+<br>
 .. code-block:: llvm<br>
<br>
     !0 = !DIEnumerator(name: "SixKind", value: 7)<br>
<br>
Modified: llvm/trunk/include/llvm/IR/LLVMContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LLVMContext.h?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/LLVMContext.h?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/include/llvm/IR/LLVMContext.h (original)<br>
+++ llvm/trunk/include/llvm/IR/LLVMContext.h Sat Apr 16 22:58:21 2016<br>
@@ -25,6 +25,8 @@ class StringRef;<br>
 class Twine;<br>
 class Instruction;<br>
 class Module;<br>
+class MDString;<br>
+class DIType;<br>
 class SMDiagnostic;<br>
 class DiagnosticInfo;<br>
 template <typename T> class SmallVectorImpl;<br>
@@ -113,6 +115,23 @@ public:<br>
   /// especially in release mode.<br>
   void setDiscardValueNames(bool Discard);<br>
<br>
+  /// Whether there is a string map for uniquing debug info types with<br>
+  /// identifiers across the context.  Off by default.<br>
+  bool hasDITypeMap() const;<br>
+  void ensureDITypeMap();<br>
+  void destroyDITypeMap();<br>
+<br>
+  /// Get or insert the DIType mapped to the given string.<br>
+  ///<br>
+  /// Returns the address of the current \a DIType pointer mapped to \c S,<br>
+  /// inserting a mapping to \c nullptr if \c S was not previously mapped.<br>
+  /// This method has no effect (and returns \c nullptr instead of a valid<br>
+  /// address) if \a hasDITypeMap() is \c false.<br>
+  ///<br>
+  /// \post If \a hasDITypeMap(), \c S will have a (possibly null) mapping.<br>
+  /// \note The returned address is only valid until the next call.<br>
+  DIType **getOrInsertDITypeMapping(const MDString &S);<br>
+<br>
   typedef void (*InlineAsmDiagHandlerTy)(const SMDiagnostic&, void *Context,<br>
                                          unsigned LocCookie);<br>
<br>
<br>
Modified: llvm/trunk/lib/AsmParser/LLParser.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/AsmParser/LLParser.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/AsmParser/LLParser.cpp (original)<br>
+++ llvm/trunk/lib/AsmParser/LLParser.cpp Sat Apr 16 22:58:21 2016<br>
@@ -3839,11 +3839,25 @@ bool LLParser::ParseDICompositeType(MDNo<br>
   PARSE_MD_FIELDS();<br>
 #undef VISIT_MD_FIELDS<br>
<br>
+  // If this isn't a forward declaration and it has a UUID, check for it in the<br>
+  // type map in the context.<br>
+  DIType **MappedT = nullptr;<br>
+  if (!(flags.Val & DINode::FlagFwdDecl) && identifier.Val &&<br>
+      (MappedT = Context.getOrInsertDITypeMapping(*identifier.Val)) &&<br>
+      *MappedT) {<br>
+    Result = *MappedT;<br>
+    return false;<br>
+  }<br>
+<br>
+  // Create a new node, and save it in the context if it belongs in the type<br>
+  // map.<br>
   Result = GET_OR_DISTINCT(<br>
       DICompositeType,<br>
       (Context, tag.Val, name.Val, file.Val, line.Val, scope.Val, baseType.Val,<br>
        size.Val, align.Val, offset.Val, flags.Val, elements.Val,<br>
        runtimeLang.Val, vtableHolder.Val, templateParams.Val, identifier.Val));<br>
+  if (MappedT)<br>
+    *MappedT = cast<DIType>(Result);<br>
   return false;<br>
 }<br>
<br>
<br>
Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)<br>
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sat Apr 16 22:58:21 2016<br>
@@ -2188,16 +2188,29 @@ std::error_code BitcodeReader::parseMeta<br>
       if (Record.size() != 16)<br>
         return error("Invalid record");<br>
<br>
-      MetadataList.assignValue(<br>
-          GET_OR_DISTINCT(DICompositeType, Record[0],<br>
-                          (Context, Record[1], getMDString(Record[2]),<br>
-                           getMDOrNull(Record[3]), Record[4],<br>
-                           getMDOrNull(Record[5]), getMDOrNull(Record[6]),<br>
-                           Record[7], Record[8], Record[9], Record[10],<br>
-                           getMDOrNull(Record[11]), Record[12],<br>
-                           getMDOrNull(Record[13]), getMDOrNull(Record[14]),<br>
-                           getMDString(Record[15]))),<br>
-          NextMetadataNo++);<br>
+      // If we have a UUID and this is not a forward declaration, lookup the<br>
+      // mapping.<br>
+      unsigned Flags = Record[10];<br>
+      auto *Identifier = getMDString(Record[15]);<br>
+      DIType **MappedT = nullptr;<br>
+      if (!(Flags & DINode::FlagFwdDecl) && Identifier)<br>
+        MappedT = Context.getOrInsertDITypeMapping(*Identifier);<br>
+<br>
+      // Use the mapped type node, or create a new one if necessary.<br>
+      DIType *CT = MappedT ? *MappedT : nullptr;<br>
+      if (!CT) {<br>
+        CT = GET_OR_DISTINCT(<br>
+            DICompositeType, Record[0],<br>
+            (Context, Record[1], getMDString(Record[2]), getMDOrNull(Record[3]),<br>
+             Record[4], getMDOrNull(Record[5]), getMDOrNull(Record[6]),<br>
+             Record[7], Record[8], Record[9], Flags, getMDOrNull(Record[11]),<br>
+             Record[12], getMDOrNull(Record[13]), getMDOrNull(Record[14]),<br>
+             Identifier));<br>
+        if (MappedT)<br>
+          *MappedT = CT;<br>
+      }<br>
+<br>
+      MetadataList.assignValue(CT, NextMetadataNo++);<br>
       break;<br>
     }<br>
     case bitc::METADATA_SUBROUTINE_TYPE: {<br>
<br>
Modified: llvm/trunk/lib/IR/DebugInfoMetadata.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/DebugInfoMetadata.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/DebugInfoMetadata.cpp (original)<br>
+++ llvm/trunk/lib/IR/DebugInfoMetadata.cpp Sat Apr 16 22:58:21 2016<br>
@@ -254,6 +254,7 @@ DICompositeType *DICompositeType::getImp<br>
     Metadata *TemplateParams, MDString *Identifier, StorageType Storage,<br>
     bool ShouldCreate) {<br>
   assert(isCanonical(Name) && "Expected canonical MDString");<br>
+<br>
   DEFINE_GETIMPL_LOOKUP(<br>
       DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits,<br>
                         AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,<br>
<br>
Modified: llvm/trunk/lib/IR/LLVMContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContext.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContext.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/LLVMContext.cpp (original)<br>
+++ llvm/trunk/lib/IR/LLVMContext.cpp Sat Apr 16 22:58:21 2016<br>
@@ -311,6 +311,23 @@ bool LLVMContext::shouldDiscardValueName<br>
   return pImpl->DiscardValueNames;<br>
 }<br>
<br>
+bool LLVMContext::hasDITypeMap() const { return !!pImpl->DITypeMap; }<br>
+<br>
+void LLVMContext::ensureDITypeMap() {<br>
+  if (pImpl->DITypeMap)<br>
+    return;<br>
+<br>
+  pImpl->DITypeMap = llvm::make_unique<DenseMap<const MDString *, DIType *>>();<br>
+}<br>
+<br>
+void LLVMContext::destroyDITypeMap() { pImpl->DITypeMap.reset(); }<br>
+<br>
+DIType **LLVMContext::getOrInsertDITypeMapping(const MDString &S) {<br>
+  if (!hasDITypeMap())<br>
+    return nullptr;<br>
+  return &(*pImpl->DITypeMap)[&S];<br>
+}<br>
+<br>
 void LLVMContext::setDiscardValueNames(bool Discard) {<br>
   pImpl->DiscardValueNames = Discard;<br>
 }<br>
<br>
Modified: llvm/trunk/lib/IR/LLVMContextImpl.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/LLVMContextImpl.h?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/IR/LLVMContextImpl.h (original)<br>
+++ llvm/trunk/lib/IR/LLVMContextImpl.h Sat Apr 16 22:58:21 2016<br>
@@ -1022,6 +1022,9 @@ public:<br>
   DenseSet<CLASS *, CLASS##Info> CLASS##s;<br>
 #include "llvm/IR/Metadata.def"<br>
<br>
+  // Optional map for looking up composite types by identifier.<br>
+  std::unique_ptr<DenseMap<const MDString *, DIType *>> DITypeMap;<br>
+<br>
   // MDNodes may be uniqued or not uniqued.  When they're not uniqued, they<br>
   // aren't in the MDNodeSet, but they're still shared between objects, so no<br>
   // one object can destroy them.  This set allows us to at least destroy them<br>
<br>
Modified: llvm/trunk/lib/LTO/LTOCodeGenerator.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/LTO/LTOCodeGenerator.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/LTO/LTOCodeGenerator.cpp (original)<br>
+++ llvm/trunk/lib/LTO/LTOCodeGenerator.cpp Sat Apr 16 22:58:21 2016<br>
@@ -84,6 +84,7 @@ LTOCodeGenerator::LTOCodeGenerator(LLVMC<br>
     : Context(Context), MergedModule(new Module("ld-temp.o", Context)),<br>
       TheLinker(new Linker(*MergedModule)) {<br>
   Context.setDiscardValueNames(LTODiscardValueNames);<br>
+  Context.ensureDITypeMap();<br>
   initializeLTOPasses();<br>
 }<br>
<br>
<br>
Modified: llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp (original)<br>
+++ llvm/trunk/lib/Transforms/Utils/ValueMapper.cpp Sat Apr 16 22:58:21 2016<br>
@@ -15,6 +15,7 @@<br>
 #include "llvm/Transforms/Utils/ValueMapper.h"<br>
 #include "llvm/IR/CallSite.h"<br>
 #include "llvm/IR/Constants.h"<br>
+#include "llvm/IR/DebugInfoMetadata.h"<br>
 #include "llvm/IR/Function.h"<br>
 #include "llvm/IR/GlobalAlias.h"<br>
 #include "llvm/IR/GlobalVariable.h"<br>
<br>
Added: llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll?rev=266549&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll?rev=266549&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll (added)<br>
+++ llvm/trunk/test/Linker/Inputs/dicompositetype-unique.ll Sat Apr 16 22:58:21 2016<br>
@@ -0,0 +1,4 @@<br>
+!named = !{!0, !1}<br>
+<br>
+!0 = !DIFile(filename: "abc", directory: "/path/to")<br>
+!1 = !DICompositeType(tag: DW_TAG_class_type, name: "T2", identifier: "T", file: !0)<br>
<br>
Added: llvm/trunk/test/Linker/dicompositetype-unique.ll<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/dicompositetype-unique.ll?rev=266549&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Linker/dicompositetype-unique.ll?rev=266549&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/test/Linker/dicompositetype-unique.ll (added)<br>
+++ llvm/trunk/test/Linker/dicompositetype-unique.ll Sat Apr 16 22:58:21 2016<br>
@@ -0,0 +1,42 @@<br>
+; RUN: llvm-link -S -o - %s %S/Inputs/dicompositetype-unique.ll \<br>
+; RUN:   | FileCheck %s<br>
+; RUN: llvm-link -S -o - %S/Inputs/dicompositetype-unique.ll %s \<br>
+; RUN:   | FileCheck %s -check-prefix REVERSE<br>
+; RUN: llvm-link -disable-debug-info-type-map -S -o - %s %S/Inputs/dicompositetype-unique.ll \<br>
+; RUN:   | FileCheck %s -check-prefix NOMAP<br>
+<br>
+; Check that the bitcode reader handles this too.<br>
+; RUN: llvm-as -o %t1.bc <%s<br>
+; RUN: llvm-as -o %t2.bc <%S/Inputs/dicompositetype-unique.ll<br>
+; RUN: llvm-link -S -o - %t1.bc %t2.bc | FileCheck %s<br>
+; RUN: llvm-link -S -o - %t2.bc %t1.bc | FileCheck %s -check-prefix REVERSE<br>
+; RUN: llvm-link -disable-debug-info-type-map -S -o - %t1.bc %t2.bc \<br>
+; RUN:   | FileCheck %s -check-prefix NOMAP<br>
+<br>
+; Check that the type map will unique two DICompositeTypes.<br>
+<br>
+; CHECK:   !named = !{!0, !1, !0, !1}<br>
+; REVERSE: !named = !{!0, !1, !0, !1}<br>
+; NOMAP:   !named = !{!0, !1, !0, !2}<br>
+!named = !{!0, !1}<br>
+<br>
+; Check both directions.<br>
+; CHECK:        !1 = !DICompositeType(<br>
+; CHECK-SAME:                         name: "T1"<br>
+; CHECK-SAME:                         identifier: "T"<br>
+; CHECK-NOT:       identifier: "T"<br>
+; REVERSE:      !1 = !DICompositeType(<br>
+; REVERSE-SAME:                       name: "T2"<br>
+; REVERSE-SAME:                       identifier: "T"<br>
+; REVERSE-NOT:     identifier: "T"<br>
+<br>
+; These types are different, so we should get both copies when there is no map.<br>
+; NOMAP:        !1 = !DICompositeType(<br>
+; NOMAP-SAME:                         name: "T1"<br>
+; NOMAP-SAME:                         identifier: "T"<br>
+; NOMAP:        !2 = !DICompositeType(<br>
+; NOMAP-SAME:                         name: "T2"<br>
+; NOMAP-SAME:                         identifier: "T"<br>
+; NOMAP-NOT:       identifier: "T"<br>
+!0 = !DIFile(filename: "abc", directory: "/path/to")<br>
+!1 = !DICompositeType(tag: DW_TAG_class_type, name: "T1", identifier: "T", file: !0)<br>
<br>
Modified: llvm/trunk/tools/gold/gold-plugin.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/gold/gold-plugin.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/gold/gold-plugin.cpp (original)<br>
+++ llvm/trunk/tools/gold/gold-plugin.cpp Sat Apr 16 22:58:21 2016<br>
@@ -1110,6 +1110,7 @@ static void thinLTOBackendTask(claimed_f<br>
                                raw_fd_ostream *OS, unsigned TaskID) {<br>
   // Need to use a separate context for each task<br>
   LLVMContext Context;<br>
+  Context.ensureDITypeMap(); // Merge debug info types.<br>
   Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true);<br>
<br>
   std::unique_ptr<llvm::Module> NewModule(new llvm::Module(File.name, Context));<br>
@@ -1231,6 +1232,7 @@ static ld_plugin_status allSymbolsReadHo<br>
   }<br>
<br>
   LLVMContext Context;<br>
+  Context.ensureDITypeMap(); // Merge debug info types.<br>
   Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true);<br>
<br>
   std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context));<br>
<br>
Modified: llvm/trunk/tools/llvm-link/llvm-link.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/llvm-link.cpp?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-link/llvm-link.cpp?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/tools/llvm-link/llvm-link.cpp (original)<br>
+++ llvm/trunk/tools/llvm-link/llvm-link.cpp Sat Apr 16 22:58:21 2016<br>
@@ -71,6 +71,10 @@ static cl::opt<bool><br>
 Internalize("internalize", cl::desc("Internalize linked symbols"));<br>
<br>
 static cl::opt<bool><br>
+    DisableDITypeMap("disable-debug-info-type-map",<br>
+                     cl::desc("Don't use a uniquing type map for debug info"));<br>
+<br>
+static cl::opt<bool><br>
 OnlyNeeded("only-needed", cl::desc("Link only needed symbols"));<br>
<br>
 static cl::opt<bool><br>
@@ -337,6 +341,9 @@ int main(int argc, char **argv) {<br>
   llvm_shutdown_obj Y;  // Call llvm_shutdown() on exit.<br>
   cl::ParseCommandLineOptions(argc, argv, "llvm linker\n");<br>
<br>
+  if (!DisableDITypeMap)<br>
+    Context.ensureDITypeMap();<br>
+<br>
   auto Composite = make_unique<Module>("llvm-link", Context);<br>
   Linker L(*Composite);<br>
<br>
<br>
Modified: llvm/trunk/unittests/IR/CMakeLists.txt<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=266549&r1=266548&r2=266549&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/CMakeLists.txt?rev=266549&r1=266548&r2=266549&view=diff</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/IR/CMakeLists.txt (original)<br>
+++ llvm/trunk/unittests/IR/CMakeLists.txt Sat Apr 16 22:58:21 2016<br>
@@ -16,6 +16,7 @@ set(IRSources<br>
   IRBuilderTest.cpp<br>
   InstructionsTest.cpp<br>
   IntrinsicsTest.cpp<br>
+  LLVMContextTest.cpp<br>
   LegacyPassManagerTest.cpp<br>
   MDBuilderTest.cpp<br>
   MetadataTest.cpp<br>
<br>
Added: llvm/trunk/unittests/IR/LLVMContextTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/LLVMContextTest.cpp?rev=266549&view=auto" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/IR/LLVMContextTest.cpp?rev=266549&view=auto</a><br>
==============================================================================<br>
--- llvm/trunk/unittests/IR/LLVMContextTest.cpp (added)<br>
+++ llvm/trunk/unittests/IR/LLVMContextTest.cpp Sat Apr 16 22:58:21 2016<br>
@@ -0,0 +1,57 @@<br>
+//===- LLVMContextTest.cpp - LLVMContext unit tests -----------------------===//<br>
+//<br>
+//                     The LLVM Compiler Infrastructure<br>
+//<br>
+// This file is distributed under the University of Illinois Open Source<br>
+// License. See LICENSE.TXT for details.<br>
+//<br>
+//===----------------------------------------------------------------------===//<br>
+<br>
+#include "llvm/IR/LLVMContext.h"<br>
+#include "llvm/IR/DebugInfoMetadata.h"<br>
+#include "gtest/gtest.h"<br>
+using namespace llvm;<br>
+<br>
+namespace {<br>
+<br>
+TEST(LLVMContextTest, ensureDITypeMap) {<br>
+  LLVMContext Context;<br>
+  EXPECT_FALSE(Context.hasDITypeMap());<br>
+  Context.ensureDITypeMap();<br>
+  EXPECT_TRUE(Context.hasDITypeMap());<br>
+  Context.destroyDITypeMap();<br>
+  EXPECT_FALSE(Context.hasDITypeMap());<br>
+}<br>
+<br>
+TEST(LLVMContextTest, getOrInsertDITypeMapping) {<br>
+  LLVMContext Context;<br>
+  const MDString &S = *MDString::get(Context, "string");<br>
+<br>
+  // Without a type map, this should return null.<br>
+  EXPECT_FALSE(Context.getOrInsertDITypeMapping(S));<br>
+<br>
+  // Get the mapping.<br>
+  Context.ensureDITypeMap();<br>
+  DIType **Mapping = Context.getOrInsertDITypeMapping(S);<br>
+  ASSERT_TRUE(Mapping);<br>
+<br>
+  // Create some type and add it to the mapping.<br>
+  auto &BT =<br>
+      *DIBasicType::get(Context, dwarf::DW_TAG_unspecified_type, S.getString());<br>
+  *Mapping = &BT;<br>
+<br>
+  // Check that we get it back.<br>
+  Mapping = Context.getOrInsertDITypeMapping(S);<br>
+  ASSERT_TRUE(Mapping);<br>
+  EXPECT_EQ(&BT, *Mapping);<br>
+<br>
+  // Check that it's discarded with the type map.<br>
+  Context.destroyDITypeMap();<br>
+  EXPECT_FALSE(Context.getOrInsertDITypeMapping(S));<br>
+<br>
+  // And it shouldn't magically reappear...<br>
+  Context.ensureDITypeMap();<br>
+  EXPECT_FALSE(*Context.getOrInsertDITypeMapping(S));<br>
+}<br>
+<br>
+} // end namespace<br>
<br>
<br>
_______________________________________________<br>
llvm-commits mailing list<br>
<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature"><span style="font-family:Times;font-size:medium"><table cellspacing="0" cellpadding="0"><tbody><tr style="color:rgb(85,85,85);font-family:sans-serif;font-size:small"><td nowrap style="border-top-style:solid;border-top-color:rgb(213,15,37);border-top-width:2px">Teresa Johnson |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(51,105,232);border-top-width:2px"> Software Engineer |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(0,153,57);border-top-width:2px"> <a href="mailto:tejohnson@google.com" target="_blank">tejohnson@google.com</a> |</td><td nowrap style="border-top-style:solid;border-top-color:rgb(238,178,17);border-top-width:2px"> 408-460-2413</td></tr></tbody></table></span></div>
</div>