[llvm-dev] 'invalid subroutine type ref' when linking custom metadata

Mehdi Amini via llvm-dev llvm-dev at lists.llvm.org
Mon Jul 25 23:22:11 PDT 2016


+CC Duncan``` 

> On Jul 25, 2016, at 8:53 PM, Robin Sommer via llvm-dev <llvm-dev at lists.llvm.org> wrote:
> 
> 
> With 3.9, llvm-link tells me 'invalid subroutine type ref' when
> linking the two code pieces below, and I don't quite understand why.
> It looks like it merges the debug information with the custom
> metadata. I've filed a ticket already [1] but as I'm not sure if this
> is indeed a bug or if I'm misunderstanding something, I thought I'd
> ask here.
> 
> Any ideas?

This is a bug, and I believe it is caused by r266579.

It seems that:

1) The module for a.ll is created.
2) "!3 = !{void ()* @a}" is a MDTuple, and MDTuple nodes are leaking to the context and survive module deletion.
3) "void ()* @a” which is the only element in this MDTuple is a “ConstantAsMetadata”, this does not leak and will be deleted with the module.
4) a.ll is linked into an empty module, using an IRMover. This process will involved populating a map of Metadata -> mapped Metadata. One entry will be created with this MDTuple !3.
5) a.ll is destroyed, including the “ConstantAsMetadata”.
6) b.ll is parsed, the “null” constant will get the same pointer as the previously deleted constant from a.ll.
7) "!22 = !{null}” is parsed. Since this is a “uniqued” node, we are looking in the context for a MDTuple with the null constant as a single operand. We find the previously "!3 = !{void ()* @a}”, and this is fine since it nows point to the new “null” constant”.
8) We reuse the map of metadata to link b.ll, however this map is no longer valid since the MDTuple entry for !3 is outdated and will map to the moved constant "void ()* @a”.

Duncan: can you confirm that this analysis makes sense to you?
Is it an oversight of your commit in r266579?

Thanks,

— 
Mehdi


> 
>> cat a.ll
>    define void @a() {
>      ret void
>    }
> 
>    !bar = !{!3}
> 
>    !3 = !{void ()* @a}
> 
>> cat b.ll
>    define void @foo() !dbg !20 {
>      ret void
>    }
> 
>    !llvm.module.flags = !{!17, !18}
> 
>    !0 = distinct !DICompileUnit(language: DW_LANG_C89, file: !1)
>    !1 = !DIFile(filename: "x.c", directory: "/tmp")
>    !17 = !{i32 2, !"Dwarf Version", i32 4}
>    !18 = !{i32 2, !"Debug Info Version", i32 3}
>    !20 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 92, type: !21, unit: !0)
>    !21 = !DISubroutineType(types: !22)
>    !22 = !{null}
>    !23 = !{}
> 
>> llvm-link -o out a.ll b.ll
>    invalid subroutine type ref
>    !5 = !DISubroutineType(types: !0)
>    !0 = !{void ()* @a}
>    void ()* @a
>    All DICompileUnits must be listed in llvm.dbg.cu
>    llvm-link: error: linked module is broken!
> 
> (The *.ll files are stripped down from much larger files to find a
> minimal example. I suppose the message about llvm.dbg.cu is just
> because I removed a bit too much).

Just adding:


— 
Mehdi

> 
> Robin
> 
> [1] https://llvm.org/bugs/show_bug.cgi?id=28697
> 
> -- 
> Robin Sommer * ICSI/LBNL * robin at icir.org * www.icir.org/robin
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev



More information about the llvm-dev mailing list