<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Sun, Apr 17, 2016 at 4:15 PM, Duncan P. N. Exon Smith <span dir="ltr"><<a href="mailto:dexonsmith@apple.com" target="_blank">dexonsmith@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class=""><br>
> On 2016-Apr-17, at 15:17, David Blaikie <<a href="mailto:dblaikie@gmail.com">dblaikie@gmail.com</a>> wrote:<br>
><br>
><br>
><br>
>> On Sat, Apr 16, 2016 at 8:58 PM, Duncan P. N. Exon Smith via llvm-commits <<a href="mailto:llvm-commits@lists.llvm.org">llvm-commits@lists.llvm.org</a>> wrote:<br>
>> 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>
> Any better name? "forceODRDebugTypeUniquing"? (just open to ideas)<br>
<br>
</span>I like that better, but then I can't come up with a good name for<br>
the current "destroyDITypeMap".<br>
<br>
Maybe enable/disableODRDebugTypeUniquing?<br></blockquote><div><br></div><div>I haven't looked at the code at all, but just judging by the name I assume 'destroy' resets the uniquing scope, as it were? So "resetODRDebugTypeUniquing" (maybe including 'scope' at the end, but not sure)</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<span class=""><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>
> This does seem to make the API a bit awkward - is there any reasonable way to introduce a separate scope for this sort of possibly-non-semantics-preserving merge scope? (non-preserving in the sense that if the content does have differences (line numbers, or worse) they won't be preserved)<br>
<br>
</span>There may be a way to create a MetadataContext of some sort.  I'll think<br>
about it a bit more.<br>
<span class=""><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>
> That'll be nice, but probably immediately reintroduced by Reid to handle referencing opaque type descriptions for CodeView.<br>
<br>
</span>IIUC, Reid's type descriptions will be more explicit.  What I'm removing<br>
looks like this:<br>
--<br>
!0 = !DICompileUnit(retainedTypes: !1)<br>
!1 = !{!2}<br>
!2 = !DICompositeType(identifier: "uuid")<br>
<br>
// The type is a string.<br>
!3 = !DILocalVariable(type: !"uuid", scope: ...)<br>
--<br>
The benefit of this model was that it broke cycles in a cyclic graph,<br>
allowing LTO to unique things structurally.<br>
<br>
My understanding is that CodeView doesn't have cycles.  I've been<br>
imagining something more like this:<br>
--<br>
!0 = !DITypeRef(identifier: "uuid")<br>
<br>
// The type is a type.<br>
!1 = !DILocalVariable(type: !0, scope: ...)<br>
--<br></blockquote><div><br></div><div>Yeah, possible we could do something more like that (that might add more metadata though, than just having 'type:' be a string (the string's already uniqued anyway, so the extra node just adds overhead, right?))<br><br>- Dave</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div class="HOEnZb"><div class="h5"><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>
<br>
</div></div></blockquote></div><br></div></div>