[llvm] r242847 - [dsymutil] Implement ODR uniquing for C++ code.
David Blaikie
dblaikie at gmail.com
Tue Jul 21 16:05:19 PDT 2015
On Tue, Jul 21, 2015 at 3:41 PM, Frederic Riss <friss at apple.com> wrote:
> Author: friss
> Date: Tue Jul 21 17:41:43 2015
> New Revision: 242847
>
> URL: http://llvm.org/viewvc/llvm-project?rev=242847&view=rev
> Log:
> [dsymutil] Implement ODR uniquing for C++ code.
>
> This optimization allows the DWARF linker to reuse definition of
> types it has emitted in previous CUs rather than reemitting them
> in each CU that references them. The size and link time gains are
> huge. For example when linking the DWARF for a debug build of
> clang, this generates a ~150M dwarf file instead of a ~700M one
> (the numbers date back a bit and must not be totally accurate
> these days).
>
> As with all the other parts of the llvm-dsymutil codebase, the
> goal is to keep bit-for-bit compatibility with dsymutil-classic.
> The code is littered with a lot of FIXMEs that should be
> addressed once we can get rid of the compatibilty goal.
>
Did dsymutil-classic do this ODR uniquing too? (not quite clear to me from
your description here - where you mention compatibility, etc) How does its
implementation compare?
>
> Added:
> llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h
> llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll
>
Might be useful to have more distinguishing names for the test files here?
(I assume each ODR test only needs two files - or do some need more than
that?)
I see it's all in odr-1.test - it's a bit monolithic, isn't it? I'm not
sure I understand the motivation for 7 different inputs and then checking
all together. Could you explain it?
- Dave
> llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll
> llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll
> llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll
> llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll
> llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll
> llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp
> llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll
> llvm/trunk/test/tools/dsymutil/X86/odr-1.test
> Modified:
> llvm/trunk/tools/dsymutil/DwarfLinker.cpp
> llvm/trunk/tools/dsymutil/dsymutil.cpp
> llvm/trunk/tools/dsymutil/dsymutil.h
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr-types.h Tue Jul 21 17:41:43
> 2015
> @@ -0,0 +1,51 @@
> +struct S {
> + int I;
> +
> + void incr() __attribute__((always_inline)) { I++; }
> + void incr(int Add) __attribute__((always_inline)) { I += Add; }
> +
> + typedef int SInt;
> +
> + struct Nested {
> + double D;
> +
> + template<typename T> void init(T Val) { D = double(Val); }
> + };
> +
> + Nested D;
> +
> +public:
> + int foo() { return I; }
> +};
> +
> +typedef S AliasForS;
> +
> +namespace N {
> +class C {
> + AliasForS S;
> +};
> +}
> +
> +namespace N {
> +namespace N {
> +class C {
> + int S;
> +};
> +}
> +}
> +
> +namespace {
> + class AnonC {
> + };
> +}
> +
> +union U {
> + class C {} C;
> + struct S {} S;
> +};
> +
> +inline int func() {
> + struct CInsideFunc { int i; };
> + auto functor = []() { CInsideFunc dummy; return dummy.i; };
> + return functor();
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr1.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,11 @@
> +#include "odr-types.h"
> +
> +int foo() {
> + AliasForS s;
> + N::C nc;
> + N::N::C nnc;
> + AnonC ac;
> + U u;
> +
> + return func();
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr1.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,153 @@
> +; Generated from odr1.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr1.cpp
> +; ModuleID = 'odr1.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%struct.S = type { i32, %"struct.S::Nested" }
> +%"struct.S::Nested" = type { double }
> +%"class.N::C" = type { %struct.S }
> +%"class.N::N::C" = type { i32 }
> +%"class.(anonymous namespace)::AnonC" = type { i8 }
> +%union.U = type { %"class.U::C" }
> +%"class.U::C" = type { i8 }
> +%class.anon = type { i8 }
> +%struct.CInsideFunc = type { i32 }
> +
> +; Function Attrs: ssp uwtable
> +define i32 @_Z3foov() #0 {
> +entry:
> + %s = alloca %struct.S, align 8
> + %nc = alloca %"class.N::C", align 8
> + %nnc = alloca %"class.N::N::C", align 4
> + %ac = alloca %"class.(anonymous namespace)::AnonC", align 1
> + %u = alloca %union.U, align 1
> + call void @llvm.dbg.declare(metadata %struct.S* %s, metadata !59,
> metadata !60), !dbg !61
> + call void @llvm.dbg.declare(metadata %"class.N::C"* %nc, metadata !62,
> metadata !60), !dbg !63
> + call void @llvm.dbg.declare(metadata %"class.N::N::C"* %nnc, metadata
> !64, metadata !60), !dbg !65
> + call void @llvm.dbg.declare(metadata %"class.(anonymous
> namespace)::AnonC"* %ac, metadata !66, metadata !60), !dbg !69
> + call void @llvm.dbg.declare(metadata %union.U* %u, metadata !70,
> metadata !60), !dbg !71
> + %call = call i32 @_Z4funcv(), !dbg !72
> + ret i32 %call, !dbg !73
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: inlinehint ssp uwtable
> +define linkonce_odr i32 @_Z4funcv() #2 {
> +entry:
> + %functor = alloca %class.anon, align 1
> + call void @llvm.dbg.declare(metadata %class.anon* %functor, metadata
> !74, metadata !60), !dbg !75
> + %call = call i32 @_ZZ4funcvENKUlvE_clEv(%class.anon* %functor), !dbg !76
> + ret i32 %call, !dbg !77
> +}
> +
> +; Function Attrs: inlinehint nounwind ssp uwtable
> +define linkonce_odr i32 @_ZZ4funcvENKUlvE_clEv(%class.anon* %this) #3
> align 2 {
> +entry:
> + %this.addr = alloca %class.anon*, align 8
> + %dummy = alloca %struct.CInsideFunc, align 4
> + store %class.anon* %this, %class.anon** %this.addr, align 8
> + call void @llvm.dbg.declare(metadata %class.anon** %this.addr, metadata
> !78, metadata !60), !dbg !80
> + %this1 = load %class.anon*, %class.anon** %this.addr
> + call void @llvm.dbg.declare(metadata %struct.CInsideFunc* %dummy,
> metadata !81, metadata !60), !dbg !82
> + %i = getelementptr inbounds %struct.CInsideFunc, %struct.CInsideFunc*
> %dummy, i32 0, i32 0, !dbg !83
> + %0 = load i32, i32* %i, align 4, !dbg !83
> + ret i32 %0, !dbg !84
> +}
> +
> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +attributes #2 = { inlinehint ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #3 = { inlinehint nounwind ssp uwtable
> "disable-tail-calls"="false" "less-precise-fpmad"="false"
> "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf"
> "no-infs-fp-math"="false" "no-nans-fp-math"="false"
> "stack-protector-buffer-size"="8" "target-cpu"="core2"
> "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false"
> "use-soft-float"="false" }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!55, !56, !57}
> +!llvm.ident = !{!58}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !52)
> +!1 = !DIFile(filename: "odr1.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20, !24, !29, !33, !37, !38, !39, !49}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope: !25,
> file: !5, line: 24, size: 128, align: 64, elements: !26, identifier:
> "_ZTSN1N1CE")
> +!25 = !DINamespace(name: "N", scope: null, file: !5, line: 23)
> +!26 = !{!27}
> +!27 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope: !"_ZTSN1N1CE",
> file: !5, line: 25, baseType: !28, size: 128, align: 64)
> +!28 = !DIDerivedType(tag: DW_TAG_typedef, name: "AliasForS", file: !5,
> line: 21, baseType: !"_ZTS1S")
> +!29 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope: !30,
> file: !5, line: 31, size: 32, align: 32, elements: !31, identifier:
> "_ZTSN1N1N1CE")
> +!30 = !DINamespace(name: "N", scope: !25, file: !5, line: 30)
> +!31 = !{!32}
> +!32 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope:
> !"_ZTSN1N1N1CE", file: !5, line: 32, baseType: !8, size: 32, align: 32)
> +!33 = !DICompositeType(tag: DW_TAG_union_type, name: "U", file: !5, line:
> 42, size: 8, align: 8, elements: !34, identifier: "_ZTS1U")
> +!34 = !{!35, !36}
> +!35 = !DIDerivedType(tag: DW_TAG_member, name: "C", scope: !"_ZTS1U",
> file: !5, line: 43, baseType: !"_ZTSN1U1CE", size: 8, align: 8)
> +!36 = !DIDerivedType(tag: DW_TAG_member, name: "S", scope: !"_ZTS1U",
> file: !5, line: 44, baseType: !"_ZTSN1U1SE", size: 8, align: 8)
> +!37 = !DICompositeType(tag: DW_TAG_class_type, name: "C", scope:
> !"_ZTS1U", file: !5, line: 43, size: 8, align: 8, elements: !2, identifier:
> "_ZTSN1U1CE")
> +!38 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", scope:
> !"_ZTS1U", file: !5, line: 44, size: 8, align: 8, elements: !2, identifier:
> "_ZTSN1U1SE")
> +!39 = !DICompositeType(tag: DW_TAG_class_type, scope: !40, file: !5,
> line: 49, size: 8, align: 8, elements: !43, identifier: "_ZTSZ4funcvEUlvE_")
> +!40 = !DISubprogram(name: "func", linkageName: "_Z4funcv", scope: !5,
> file: !5, line: 47, type: !41, isLocal: false, isDefinition: true,
> scopeLine: 47, flags: DIFlagPrototyped, isOptimized: false, function: i32
> ()* @_Z4funcv, variables: !2)
> +!41 = !DISubroutineType(types: !42)
> +!42 = !{!8}
> +!43 = !{!44}
> +!44 = !DISubprogram(name: "operator()", scope: !"_ZTSZ4funcvEUlvE_",
> file: !5, line: 49, type: !45, isLocal: false, isDefinition: false,
> scopeLine: 49, flags: DIFlagPublic | DIFlagPrototyped, isOptimized: false)
> +!45 = !DISubroutineType(types: !46)
> +!46 = !{!8, !47}
> +!47 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !48, size: 64,
> align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!48 = !DIDerivedType(tag: DW_TAG_const_type, baseType:
> !"_ZTSZ4funcvEUlvE_")
> +!49 = !DICompositeType(tag: DW_TAG_structure_type, name: "CInsideFunc",
> scope: !40, file: !5, line: 48, size: 32, align: 32, elements: !50,
> identifier: "_ZTSZ4funcvE11CInsideFunc")
> +!50 = !{!51}
> +!51 = !DIDerivedType(tag: DW_TAG_member, name: "i", scope:
> !"_ZTSZ4funcvE11CInsideFunc", file: !5, line: 48, baseType: !8, size: 32,
> align: 32)
> +!52 = !{!53, !40, !54}
> +!53 = !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file:
> !1, line: 3, type: !41, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: i32 ()* @_Z3foov,
> variables: !2)
> +!54 = !DISubprogram(name: "operator()", linkageName:
> "_ZZ4funcvENKUlvE_clEv", scope: !"_ZTSZ4funcvEUlvE_", file: !5, line: 49,
> type: !45, isLocal: false, isDefinition: true, scopeLine: 49, flags:
> DIFlagPrototyped, isOptimized: false, function: i32 (%class.anon*)*
> @_ZZ4funcvENKUlvE_clEv, declaration: !44, variables: !2)
> +!55 = !{i32 2, !"Dwarf Version", i32 2}
> +!56 = !{i32 2, !"Debug Info Version", i32 3}
> +!57 = !{i32 1, !"PIC Level", i32 2}
> +!58 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!59 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s", scope: !53,
> file: !1, line: 4, type: !28)
> +!60 = !DIExpression()
> +!61 = !DILocation(line: 4, column: 12, scope: !53)
> +!62 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "nc", scope: !53,
> file: !1, line: 5, type: !"_ZTSN1N1CE")
> +!63 = !DILocation(line: 5, column: 7, scope: !53)
> +!64 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "nnc", scope:
> !53, file: !1, line: 6, type: !"_ZTSN1N1N1CE")
> +!65 = !DILocation(line: 6, column: 10, scope: !53)
> +!66 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "ac", scope: !53,
> file: !1, line: 7, type: !67)
> +!67 = !DICompositeType(tag: DW_TAG_class_type, name: "AnonC", scope: !68,
> file: !5, line: 38, size: 8, align: 8, elements: !2)
> +!68 = !DINamespace(scope: null, file: !5, line: 37)
> +!69 = !DILocation(line: 7, column: 8, scope: !53)
> +!70 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "u", scope: !53,
> file: !1, line: 8, type: !"_ZTS1U")
> +!71 = !DILocation(line: 8, column: 4, scope: !53)
> +!72 = !DILocation(line: 10, column: 9, scope: !53)
> +!73 = !DILocation(line: 10, column: 2, scope: !53)
> +!74 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "functor", scope:
> !40, file: !5, line: 49, type: !"_ZTSZ4funcvEUlvE_")
> +!75 = !DILocation(line: 49, column: 7, scope: !40)
> +!76 = !DILocation(line: 50, column: 9, scope: !40)
> +!77 = !DILocation(line: 50, column: 2, scope: !40)
> +!78 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !54, type: !79, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!79 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !48, size: 64,
> align: 64)
> +!80 = !DILocation(line: 0, scope: !54)
> +!81 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "dummy", scope:
> !54, file: !5, line: 49, type: !"_ZTSZ4funcvE11CInsideFunc")
> +!82 = !DILocation(line: 49, column: 36, scope: !54)
> +!83 = !DILocation(line: 49, column: 56, scope: !54)
> +!84 = !DILocation(line: 49, column: 43, scope: !54)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr2.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,7 @@
> +#include "odr-types.h"
> +
> +int bar() {
> + S s;
> + s.incr();
> + return s.foo();
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr2.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,99 @@
> +; Generated from odr2.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr2.cpp
> +; ModuleID = 'odr2.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%struct.S = type { i32, %"struct.S::Nested" }
> +%"struct.S::Nested" = type { double }
> +
> +; Function Attrs: ssp uwtable
> +define i32 @_Z3barv() #0 {
> +entry:
> + %this.addr.i = alloca %struct.S*, align 8
> + %s = alloca %struct.S, align 8
> + call void @llvm.dbg.declare(metadata %struct.S* %s, metadata !34,
> metadata !35), !dbg !36
> + store %struct.S* %s, %struct.S** %this.addr.i, align 8, !dbg !37
> + %this1.i = load %struct.S*, %struct.S** %this.addr.i, !dbg !37
> + %I.i = getelementptr inbounds %struct.S, %struct.S* %this1.i, i32 0,
> i32 0, !dbg !38
> + %0 = load i32, i32* %I.i, align 4, !dbg !40
> + %inc.i = add nsw i32 %0, 1, !dbg !40
> + store i32 %inc.i, i32* %I.i, align 4, !dbg !40
> + %call = call i32 @_ZN1S3fooEv(%struct.S* %s), !dbg !41
> + call void @llvm.dbg.declare(metadata %struct.S** %this.addr.i, metadata
> !42, metadata !35), !dbg !44
> + ret i32 %call, !dbg !45
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind ssp uwtable
> +define linkonce_odr i32 @_ZN1S3fooEv(%struct.S* %this) #2 align 2 {
> +entry:
> + %this.addr = alloca %struct.S*, align 8
> + store %struct.S* %this, %struct.S** %this.addr, align 8
> + call void @llvm.dbg.declare(metadata %struct.S** %this.addr, metadata
> !46, metadata !35), !dbg !47
> + %this1 = load %struct.S*, %struct.S** %this.addr
> + %I = getelementptr inbounds %struct.S, %struct.S* %this1, i32 0, i32 0,
> !dbg !48
> + %0 = load i32, i32* %I, align 4, !dbg !48
> + ret i32 %0, !dbg !49
> +}
> +
> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +attributes #2 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!30, !31, !32}
> +!llvm.ident = !{!33}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !24)
> +!1 = !DIFile(filename: "odr2.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !{!25, !28, !29}
> +!25 = !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file:
> !1, line: 3, type: !26, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: i32 ()* @_Z3barv,
> variables: !2)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{!8}
> +!28 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> true, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false,
> declaration: !10, variables: !2)
> +!29 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false, function:
> i32 (%struct.S*)* @_ZN1S3fooEv, declaration: !17, variables: !2)
> +!30 = !{i32 2, !"Dwarf Version", i32 2}
> +!31 = !{i32 2, !"Debug Info Version", i32 3}
> +!32 = !{i32 1, !"PIC Level", i32 2}
> +!33 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!34 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s", scope: !25,
> file: !1, line: 4, type: !"_ZTS1S")
> +!35 = !DIExpression()
> +!36 = !DILocation(line: 4, column: 4, scope: !25)
> +!37 = !DILocation(line: 5, column: 2, scope: !25)
> +!38 = !DILocation(line: 4, column: 47, scope: !28, inlinedAt: !39)
> +!39 = distinct !DILocation(line: 5, column: 2, scope: !25)
> +!40 = !DILocation(line: 4, column: 48, scope: !28, inlinedAt: !39)
> +!41 = !DILocation(line: 6, column: 9, scope: !25)
> +!42 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !28, type: !43, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!43 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64)
> +!44 = !DILocation(line: 0, scope: !28, inlinedAt: !39)
> +!45 = !DILocation(line: 6, column: 2, scope: !25)
> +!46 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !29, type: !43, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!47 = !DILocation(line: 0, scope: !29)
> +!48 = !DILocation(line: 18, column: 21, scope: !29)
> +!49 = !DILocation(line: 18, column: 14, scope: !29)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr3.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,7 @@
> +#include "odr-types.h"
> +
> +int bar() {
> + S s;
> + s.incr(42);
> + return s.foo();
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr3.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,106 @@
> +; Generated from odr3.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr3.cpp
> +; ModuleID = 'odr3.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%struct.S = type { i32, %"struct.S::Nested" }
> +%"struct.S::Nested" = type { double }
> +
> +; Function Attrs: ssp uwtable
> +define i32 @_Z3barv() #0 {
> +entry:
> + %this.addr.i = alloca %struct.S*, align 8
> + %Add.addr.i = alloca i32, align 4
> + %s = alloca %struct.S, align 8
> + call void @llvm.dbg.declare(metadata %struct.S* %s, metadata !34,
> metadata !35), !dbg !36
> + store %struct.S* %s, %struct.S** %this.addr.i, align 8, !dbg !37
> + store i32 42, i32* %Add.addr.i, align 4, !dbg !37
> + %this1.i = load %struct.S*, %struct.S** %this.addr.i, !dbg !37
> + %0 = load i32, i32* %Add.addr.i, align 4, !dbg !38
> + %I.i = getelementptr inbounds %struct.S, %struct.S* %this1.i, i32 0,
> i32 0, !dbg !40
> + %1 = load i32, i32* %I.i, align 4, !dbg !41
> + %add.i = add nsw i32 %1, %0, !dbg !41
> + store i32 %add.i, i32* %I.i, align 4, !dbg !41
> + %call = call i32 @_ZN1S3fooEv(%struct.S* %s), !dbg !42
> + call void @llvm.dbg.declare(metadata %struct.S** %this.addr.i, metadata
> !43, metadata !35), !dbg !45
> + call void @llvm.dbg.declare(metadata i32* %Add.addr.i, metadata !46,
> metadata !35), !dbg !47
> + ret i32 %call, !dbg !48
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind ssp uwtable
> +define linkonce_odr i32 @_ZN1S3fooEv(%struct.S* %this) #2 align 2 {
> +entry:
> + %this.addr = alloca %struct.S*, align 8
> + store %struct.S* %this, %struct.S** %this.addr, align 8
> + call void @llvm.dbg.declare(metadata %struct.S** %this.addr, metadata
> !49, metadata !35), !dbg !50
> + %this1 = load %struct.S*, %struct.S** %this.addr
> + %I = getelementptr inbounds %struct.S, %struct.S* %this1, i32 0, i32 0,
> !dbg !51
> + %0 = load i32, i32* %I, align 4, !dbg !51
> + ret i32 %0, !dbg !52
> +}
> +
> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +attributes #2 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!30, !31, !32}
> +!llvm.ident = !{!33}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !24)
> +!1 = !DIFile(filename: "odr3.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !{!25, !28, !29}
> +!25 = !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !1, file:
> !1, line: 3, type: !26, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: i32 ()* @_Z3barv,
> variables: !2)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{!8}
> +!28 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false,
> declaration: !14, variables: !2)
> +!29 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> true, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false, function:
> i32 (%struct.S*)* @_ZN1S3fooEv, declaration: !17, variables: !2)
> +!30 = !{i32 2, !"Dwarf Version", i32 2}
> +!31 = !{i32 2, !"Debug Info Version", i32 3}
> +!32 = !{i32 1, !"PIC Level", i32 2}
> +!33 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!34 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "s", scope: !25,
> file: !1, line: 4, type: !"_ZTS1S")
> +!35 = !DIExpression()
> +!36 = !DILocation(line: 4, column: 4, scope: !25)
> +!37 = !DILocation(line: 5, column: 2, scope: !25)
> +!38 = !DILocation(line: 5, column: 59, scope: !28, inlinedAt: !39)
> +!39 = distinct !DILocation(line: 5, column: 2, scope: !25)
> +!40 = !DILocation(line: 5, column: 54, scope: !28, inlinedAt: !39)
> +!41 = !DILocation(line: 5, column: 56, scope: !28, inlinedAt: !39)
> +!42 = !DILocation(line: 6, column: 9, scope: !25)
> +!43 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !28, type: !44, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!44 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64)
> +!45 = !DILocation(line: 0, scope: !28, inlinedAt: !39)
> +!46 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "Add", arg: 2,
> scope: !28, file: !5, line: 5, type: !8)
> +!47 = !DILocation(line: 5, column: 16, scope: !28, inlinedAt: !39)
> +!48 = !DILocation(line: 6, column: 2, scope: !25)
> +!49 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !29, type: !44, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!50 = !DILocation(line: 0, scope: !29)
> +!51 = !DILocation(line: 18, column: 21, scope: !29)
> +!52 = !DILocation(line: 18, column: 14, scope: !29)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr4.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,8 @@
> +namespace {
> + class AnonC {
> + };
> +}
> +
> +void baz() {
> + AnonC ac;
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr4.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,43 @@
> +; Generated from odr4.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr4.cpp
> +; ModuleID = 'odr4.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%"class.(anonymous namespace)::AnonC" = type { i8 }
> +
> +; Function Attrs: nounwind ssp uwtable
> +define void @_Z3bazv() #0 {
> +entry:
> + %ac = alloca %"class.(anonymous namespace)::AnonC", align 1
> + call void @llvm.dbg.declare(metadata %"class.(anonymous
> namespace)::AnonC"* %ac, metadata !11, metadata !14), !dbg !15
> + ret void, !dbg !16
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!7, !8, !9}
> +!llvm.ident = !{!10}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, subprograms: !3)
> +!1 = !DIFile(filename: "odr4.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4}
> +!4 = !DISubprogram(name: "baz", linkageName: "_Z3bazv", scope: !1, file:
> !1, line: 6, type: !5, isLocal: false, isDefinition: true, scopeLine: 6,
> flags: DIFlagPrototyped, isOptimized: false, function: void ()* @_Z3bazv,
> variables: !2)
> +!5 = !DISubroutineType(types: !6)
> +!6 = !{null}
> +!7 = !{i32 2, !"Dwarf Version", i32 2}
> +!8 = !{i32 2, !"Debug Info Version", i32 3}
> +!9 = !{i32 1, !"PIC Level", i32 2}
> +!10 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!11 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "ac", scope: !4,
> file: !1, line: 7, type: !12)
> +!12 = !DICompositeType(tag: DW_TAG_class_type, name: "AnonC", scope: !13,
> file: !1, line: 2, size: 8, align: 8, elements: !2)
> +!13 = !DINamespace(scope: null, file: !1, line: 1)
> +!14 = !DIExpression()
> +!15 = !DILocation(line: 7, column: 8, scope: !4)
> +!16 = !DILocation(line: 8, column: 1, scope: !4)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr5.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,7 @@
> +#include "odr-types.h"
> +
> +double baz() {
> + S::Nested d;
> + d.init(0);
> + return d.D;
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr5.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,101 @@
> +; Generated from odr5.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr5.cpp
> +; ModuleID = 'odr5.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%"struct.S::Nested" = type { double }
> +
> +; Function Attrs: ssp uwtable
> +define double @_Z3bazv() #0 {
> +entry:
> + %d = alloca %"struct.S::Nested", align 8
> + call void @llvm.dbg.declare(metadata %"struct.S::Nested"* %d, metadata
> !39, metadata !40), !dbg !41
> + call void @_ZN1S6Nested4initIiEEvT_(%"struct.S::Nested"* %d, i32 0),
> !dbg !42
> + %D = getelementptr inbounds %"struct.S::Nested", %"struct.S::Nested"*
> %d, i32 0, i32 0, !dbg !43
> + %0 = load double, double* %D, align 8, !dbg !43
> + ret double %0, !dbg !44
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind ssp uwtable
> +define linkonce_odr void @_ZN1S6Nested4initIiEEvT_(%"struct.S::Nested"*
> %this, i32 %Val) #2 align 2 {
> +entry:
> + %this.addr = alloca %"struct.S::Nested"*, align 8
> + %Val.addr = alloca i32, align 4
> + store %"struct.S::Nested"* %this, %"struct.S::Nested"** %this.addr,
> align 8
> + call void @llvm.dbg.declare(metadata %"struct.S::Nested"** %this.addr,
> metadata !45, metadata !40), !dbg !47
> + store i32 %Val, i32* %Val.addr, align 4
> + call void @llvm.dbg.declare(metadata i32* %Val.addr, metadata !48,
> metadata !40), !dbg !49
> + %this1 = load %"struct.S::Nested"*, %"struct.S::Nested"** %this.addr
> + %0 = load i32, i32* %Val.addr, align 4, !dbg !50
> + %conv = sitofp i32 %0 to double, !dbg !50
> + %D = getelementptr inbounds %"struct.S::Nested", %"struct.S::Nested"*
> %this1, i32 0, i32 0, !dbg !51
> + store double %conv, double* %D, align 8, !dbg !52
> + ret void, !dbg !53
> +}
> +
> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +attributes #2 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!35, !36, !37}
> +!llvm.ident = !{!38}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !24)
> +!1 = !DIFile(filename: "odr5.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20, !23}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !{!25, !28}
> +!25 = !DISubprogram(name: "baz", linkageName: "_Z3bazv", scope: !1, file:
> !1, line: 3, type: !26, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: double ()* @_Z3bazv,
> variables: !2)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{!23}
> +!28 = !DISubprogram(name: "init<int>", linkageName:
> "_ZN1S6Nested4initIiEEvT_", scope: !"_ZTSN1S6NestedE", file: !5, line: 12,
> type: !29, isLocal: false, isDefinition: true, scopeLine: 12, flags:
> DIFlagPrototyped, isOptimized: false, function: void (%"struct.S::Nested"*,
> i32)* @_ZN1S6Nested4initIiEEvT_, templateParams: !32, declaration: !34,
> variables: !2)
> +!29 = !DISubroutineType(types: !30)
> +!30 = !{null, !31, !8}
> +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
> !"_ZTSN1S6NestedE", size: 64, align: 64, flags: DIFlagArtificial |
> DIFlagObjectPointer)
> +!32 = !{!33}
> +!33 = !DITemplateTypeParameter(name: "T", type: !8)
> +!34 = !DISubprogram(name: "init<int>", linkageName:
> "_ZN1S6Nested4initIiEEvT_", scope: !"_ZTSN1S6NestedE", file: !5, line: 12,
> type: !29, isLocal: false, isDefinition: false, scopeLine: 12, flags:
> DIFlagPrototyped, isOptimized: false, templateParams: !32)
> +!35 = !{i32 2, !"Dwarf Version", i32 2}
> +!36 = !{i32 2, !"Debug Info Version", i32 3}
> +!37 = !{i32 1, !"PIC Level", i32 2}
> +!38 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!39 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "d", scope: !25,
> file: !1, line: 4, type: !"_ZTSN1S6NestedE")
> +!40 = !DIExpression()
> +!41 = !DILocation(line: 4, column: 12, scope: !25)
> +!42 = !DILocation(line: 5, column: 2, scope: !25)
> +!43 = !DILocation(line: 6, column: 11, scope: !25)
> +!44 = !DILocation(line: 6, column: 2, scope: !25)
> +!45 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !28, type: !46, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
> !"_ZTSN1S6NestedE", size: 64, align: 64)
> +!47 = !DILocation(line: 0, scope: !28)
> +!48 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "Val", arg: 2,
> scope: !28, file: !5, line: 12, type: !8)
> +!49 = !DILocation(line: 12, column: 36, scope: !28)
> +!50 = !DILocation(line: 12, column: 54, scope: !28)
> +!51 = !DILocation(line: 12, column: 43, scope: !28)
> +!52 = !DILocation(line: 12, column: 45, scope: !28)
> +!53 = !DILocation(line: 12, column: 60, scope: !28)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr6.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,7 @@
> +#include "odr-types.h"
> +
> +double baz() {
> + S::Nested d;
> + d.init(0.0);
> + return d.D;
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr6.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,100 @@
> +; Generated from odr6.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr6.cpp
> +; ModuleID = 'odr6.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%"struct.S::Nested" = type { double }
> +
> +; Function Attrs: ssp uwtable
> +define double @_Z3bazv() #0 {
> +entry:
> + %d = alloca %"struct.S::Nested", align 8
> + call void @llvm.dbg.declare(metadata %"struct.S::Nested"* %d, metadata
> !39, metadata !40), !dbg !41
> + call void @_ZN1S6Nested4initIdEEvT_(%"struct.S::Nested"* %d, double
> 0.000000e+00), !dbg !42
> + %D = getelementptr inbounds %"struct.S::Nested", %"struct.S::Nested"*
> %d, i32 0, i32 0, !dbg !43
> + %0 = load double, double* %D, align 8, !dbg !43
> + ret double %0, !dbg !44
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +; Function Attrs: nounwind ssp uwtable
> +define linkonce_odr void @_ZN1S6Nested4initIdEEvT_(%"struct.S::Nested"*
> %this, double %Val) #2 align 2 {
> +entry:
> + %this.addr = alloca %"struct.S::Nested"*, align 8
> + %Val.addr = alloca double, align 8
> + store %"struct.S::Nested"* %this, %"struct.S::Nested"** %this.addr,
> align 8
> + call void @llvm.dbg.declare(metadata %"struct.S::Nested"** %this.addr,
> metadata !45, metadata !40), !dbg !47
> + store double %Val, double* %Val.addr, align 8
> + call void @llvm.dbg.declare(metadata double* %Val.addr, metadata !48,
> metadata !40), !dbg !49
> + %this1 = load %"struct.S::Nested"*, %"struct.S::Nested"** %this.addr
> + %0 = load double, double* %Val.addr, align 8, !dbg !50
> + %D = getelementptr inbounds %"struct.S::Nested", %"struct.S::Nested"*
> %this1, i32 0, i32 0, !dbg !51
> + store double %0, double* %D, align 8, !dbg !52
> + ret void, !dbg !53
> +}
> +
> +attributes #0 = { ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +attributes #2 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!35, !36, !37}
> +!llvm.ident = !{!38}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !24)
> +!1 = !DIFile(filename: "odr6.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20, !23}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !{!25, !28}
> +!25 = !DISubprogram(name: "baz", linkageName: "_Z3bazv", scope: !1, file:
> !1, line: 3, type: !26, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: double ()* @_Z3bazv,
> variables: !2)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{!23}
> +!28 = !DISubprogram(name: "init<double>", linkageName:
> "_ZN1S6Nested4initIdEEvT_", scope: !"_ZTSN1S6NestedE", file: !5, line: 12,
> type: !29, isLocal: false, isDefinition: true, scopeLine: 12, flags:
> DIFlagPrototyped, isOptimized: false, function: void (%"struct.S::Nested"*,
> double)* @_ZN1S6Nested4initIdEEvT_, templateParams: !32, declaration: !34,
> variables: !2)
> +!29 = !DISubroutineType(types: !30)
> +!30 = !{null, !31, !23}
> +!31 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
> !"_ZTSN1S6NestedE", size: 64, align: 64, flags: DIFlagArtificial |
> DIFlagObjectPointer)
> +!32 = !{!33}
> +!33 = !DITemplateTypeParameter(name: "T", type: !23)
> +!34 = !DISubprogram(name: "init<double>", linkageName:
> "_ZN1S6Nested4initIdEEvT_", scope: !"_ZTSN1S6NestedE", file: !5, line: 12,
> type: !29, isLocal: false, isDefinition: false, scopeLine: 12, flags:
> DIFlagPrototyped, isOptimized: false, templateParams: !32)
> +!35 = !{i32 2, !"Dwarf Version", i32 2}
> +!36 = !{i32 2, !"Debug Info Version", i32 3}
> +!37 = !{i32 1, !"PIC Level", i32 2}
> +!38 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!39 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "d", scope: !25,
> file: !1, line: 4, type: !"_ZTSN1S6NestedE")
> +!40 = !DIExpression()
> +!41 = !DILocation(line: 4, column: 12, scope: !25)
> +!42 = !DILocation(line: 5, column: 2, scope: !25)
> +!43 = !DILocation(line: 6, column: 11, scope: !25)
> +!44 = !DILocation(line: 6, column: 2, scope: !25)
> +!45 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "this", arg: 1,
> scope: !28, type: !46, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!46 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType:
> !"_ZTSN1S6NestedE", size: 64, align: 64)
> +!47 = !DILocation(line: 0, scope: !28)
> +!48 = !DILocalVariable(tag: DW_TAG_arg_variable, name: "Val", arg: 2,
> scope: !28, file: !5, line: 12, type: !23)
> +!49 = !DILocation(line: 12, column: 36, scope: !28)
> +!50 = !DILocation(line: 12, column: 54, scope: !28)
> +!51 = !DILocation(line: 12, column: 43, scope: !28)
> +!52 = !DILocation(line: 12, column: 45, scope: !28)
> +!53 = !DILocation(line: 12, column: 60, scope: !28)
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr7.cpp Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,5 @@
> +#include "odr-types.h"
> +
> +void foo() {
> + S::Nested N;
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/odr7.ll Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,62 @@
> +; Generated from odr7.cpp and odr-types.h by running:
> +; clang -emit-llvm -g -S -std=c++11 odr7.cpp
> +; ModuleID = 'odr7.cpp'
> +target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> +target triple = "x86_64-apple-macosx10.11.0"
> +
> +%"struct.S::Nested" = type { double }
> +
> +; Function Attrs: nounwind ssp uwtable
> +define void @_Z3foov() #0 {
> +entry:
> + %N = alloca %"struct.S::Nested", align 8
> + call void @llvm.dbg.declare(metadata %"struct.S::Nested"* %N, metadata
> !32, metadata !33), !dbg !34
> + ret void, !dbg !35
> +}
> +
> +; Function Attrs: nounwind readnone
> +declare void @llvm.dbg.declare(metadata, metadata, metadata) #1
> +
> +attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false"
> "less-precise-fpmad"="false" "no-frame-pointer-elim"="true"
> "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false"
> "no-nans-fp-math"="false" "stack-protector-buffer-size"="8"
> "target-cpu"="core2" "target-features"="+cx16,+sse,+sse2,+sse3,+ssse3"
> "unsafe-fp-math"="false" "use-soft-float"="false" }
> +attributes #1 = { nounwind readnone }
> +
> +!llvm.dbg.cu = !{!0}
> +!llvm.module.flags = !{!28, !29, !30}
> +!llvm.ident = !{!31}
> +
> +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1,
> producer: "clang version 3.8.0 (trunk 242534)", isOptimized: false,
> runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !3,
> subprograms: !24)
> +!1 = !DIFile(filename: "odr7.cpp", directory: "/Inputs")
> +!2 = !{}
> +!3 = !{!4, !20}
> +!4 = !DICompositeType(tag: DW_TAG_structure_type, name: "S", file: !5,
> line: 1, size: 128, align: 64, elements: !6, identifier: "_ZTS1S")
> +!5 = !DIFile(filename: "./odr-types.h", directory: "/Inputs")
> +!6 = !{!7, !9, !10, !14, !17}
> +!7 = !DIDerivedType(tag: DW_TAG_member, name: "I", scope: !"_ZTS1S",
> file: !5, line: 2, baseType: !8, size: 32, align: 32)
> +!8 = !DIBasicType(name: "int", size: 32, align: 32, encoding:
> DW_ATE_signed)
> +!9 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope: !"_ZTS1S",
> file: !5, line: 15, baseType: !"_ZTSN1S6NestedE", size: 64, align: 64,
> offset: 64)
> +!10 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEv", scope:
> !"_ZTS1S", file: !5, line: 4, type: !11, isLocal: false, isDefinition:
> false, scopeLine: 4, flags: DIFlagPrototyped, isOptimized: false)
> +!11 = !DISubroutineType(types: !12)
> +!12 = !{null, !13}
> +!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1S", size:
> 64, align: 64, flags: DIFlagArtificial | DIFlagObjectPointer)
> +!14 = !DISubprogram(name: "incr", linkageName: "_ZN1S4incrEi", scope:
> !"_ZTS1S", file: !5, line: 5, type: !15, isLocal: false, isDefinition:
> false, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false)
> +!15 = !DISubroutineType(types: !16)
> +!16 = !{null, !13, !8}
> +!17 = !DISubprogram(name: "foo", linkageName: "_ZN1S3fooEv", scope:
> !"_ZTS1S", file: !5, line: 18, type: !18, isLocal: false, isDefinition:
> false, scopeLine: 18, flags: DIFlagPrototyped, isOptimized: false)
> +!18 = !DISubroutineType(types: !19)
> +!19 = !{!8, !13}
> +!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nested", scope:
> !"_ZTS1S", file: !5, line: 9, size: 64, align: 64, elements: !21,
> identifier: "_ZTSN1S6NestedE")
> +!21 = !{!22}
> +!22 = !DIDerivedType(tag: DW_TAG_member, name: "D", scope:
> !"_ZTSN1S6NestedE", file: !5, line: 10, baseType: !23, size: 64, align: 64)
> +!23 = !DIBasicType(name: "double", size: 64, align: 64, encoding:
> DW_ATE_float)
> +!24 = !{!25}
> +!25 = !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file:
> !1, line: 3, type: !26, isLocal: false, isDefinition: true, scopeLine: 3,
> flags: DIFlagPrototyped, isOptimized: false, function: void ()* @_Z3foov,
> variables: !2)
> +!26 = !DISubroutineType(types: !27)
> +!27 = !{null}
> +!28 = !{i32 2, !"Dwarf Version", i32 2}
> +!29 = !{i32 2, !"Debug Info Version", i32 3}
> +!30 = !{i32 1, !"PIC Level", i32 2}
> +!31 = !{!"clang version 3.8.0 (trunk 242534)"}
> +!32 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "N", scope: !25,
> file: !1, line: 4, type: !"_ZTSN1S6NestedE")
> +!33 = !DIExpression()
> +!34 = !DILocation(line: 4, column: 12, scope: !25)
> +!35 = !DILocation(line: 5, column: 1, scope: !25)
>
> Added: llvm/trunk/test/tools/dsymutil/X86/odr-1.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/X86/odr-1.test?rev=242847&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/X86/odr-1.test (added)
> +++ llvm/trunk/test/tools/dsymutil/X86/odr-1.test Tue Jul 21 17:41:43 2015
> @@ -0,0 +1,423 @@
> +# REQUIRES: object-emission
> +# RUN: rm -rf %t
> +# RUN: mkdir -p %t
> +# RUN: llc -filetype=obj %p/../Inputs/odr1.ll -o %t/odr1.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr2.ll -o %t/odr2.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr3.ll -o %t/odr3.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr4.ll -o %t/odr4.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr5.ll -o %t/odr5.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr6.ll -o %t/odr6.o
> +# RUN: llc -filetype=obj %p/../Inputs/odr7.ll -o %t/odr7.o
> +# RUN: llvm-dsymutil -oso-prepend-path=%t -y %s -o - | llvm-dwarfdump
> -debug-dump=info - | FileCheck -check-prefix=ODR -check-prefix=CHECK %s
> +# RUN: llvm-dsymutil -oso-prepend-path=%t -y %s -no-odr -o - |
> llvm-dwarfdump -debug-dump=info - | FileCheck -check-prefix=NOODR
> -check-prefix=CHECK %s
> +
> +# Totally made up debug map to test ODR uniquing
> +
> +---
> +triple: 'x86_64-unknown-unknown-macho'
> +objects:
> + - filename: odr1.o
> + symbols:
> + - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x1000, size: 0x12 }
> + - { sym: __Z4funcv, objAddr: 0x0, binAddr: 0x2000, size: 0x12 }
> + - { sym: __ZZ4funcvENKUlvE_clEv, objAddr: 0x0, binAddr: 0x3000,
> size: 0x12 }
> +
> +# Check that all our types are in the first CU.
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr1.cpp"
> +
> +# This is "struct S"
> +
> +# CHECK: 0x[[S:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"S"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[NESTED:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: DW_AT_name{{.*}}"Nested"
> +# CHECK: NULL
> +# CHECK: DW_TAG_subprogram
> +# CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S4incrEv"
> +# CHECK: NULL
> +# CHECK: DW_TAG_subprogram
> +# CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S4incrEi"
> +# CHECK: NULL
> +# CHECK: DW_TAG_subprogram
> +# CHECK: DW_AT_MIPS_linkage_name{{.*}}"_ZN1S3fooEv"
> +# CHECK: NULL
> +# CHECK: NULL
> +
> +# This is "class N::C"
> +
> +# CHECK: DW_TAG_namespace
> +# CHECK-NEXT: DW_AT_name{{.*}}"N"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[NC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"C"
> +# CHECK: NULL
> +
> +# This is "class N::N::C"
> +
> +# CHECK: DW_TAG_namespace
> +# CHECK-NEXT: DW_AT_name{{.*}}"N"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[NNC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"C"
> +# CHECK: NULL
> +# CHECK: NULL
> +# CHECK: NULL
> +
> +# This is "AliasForS"
> +# CHECK: 0x[[ALIASFORS:[0-9a-f]*]]:{{.*}}DW_TAG_typedef
> +# CHECK-NEXT: DW_AT_type{{.*}}[[S]]
> +# CHECK-NEXT: DW_AT_name{{.*}}"AliasForS"
> +
> +# This is "union U"
> +
> +# CHECK: 0x[[U:[0-9a-f]*]]:{{.*}}DW_TAG_union_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"U"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[UC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[US:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK: NULL
> +
> +# This is "func" free function
> +
> +# CHECK: DW_TAG_subprogram
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: DW_AT_name{{.*}}"func"
> +# CHECK: 0x[[CINSIDEFUNC:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"CInsideFunc"
> +
> +# This is "(anonymous namespace)::AnonC"
> +
> +# CHECK: DW_TAG_namespace
> +# CHECK-NOT: {{DW_AT_name|NULL|DW_TAG}}
> +# CHECK: 0x[[ANONC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"AnonC"
> +
> + - filename: odr1.o
> + symbols:
> + - { sym: __Z3foov, objAddr: 0x0, binAddr: 0x4000, size: 0x12 }
> + - { sym: __Z4funcv, objAddr: 0x0, binAddr: 0x5000, size: 0x12 }
> + - { sym: __ZZ4funcvENKUlvE_clEv, objAddr: 0x0, binAddr: 0x6000,
> size: 0x12 }
> +
> +# We relink the same file a second time. In the ODR case, everything
> (except for the
> +# union for now) should be uniqued. In the non-ODR case, we should get
> every type
> +# duplicated.
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr1.cpp"
> +
> +# ODR: DW_TAG_union_type
> +# ODR-NEXT: DW_AT_name{{.*}}"U"
> +# Types defined inside the union should be uniqued:
> +# ODR: DW_TAG_member
> +# ODR-NEXT: DW_AT_name{{.*}}"C"
> +# ODR-NOT: {{NULL|DW_TAG}}
> +# ODR: DW_AT_type{{.*}}[[UC]]
> +# ODR: DW_TAG_member
> +# ODR-NEXT: DW_AT_name{{.*}}"S"
> +# ODR-NOT: {{NULL|DW_TAG}}
> +# ODR: DW_AT_type{{.*}}[[US]]
> +
> +# Skip func
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: {{NULL|DW_TAG}}
> +# ODR: DW_AT_name{{.*}}"func"
> +# ODR: NULL
> +
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: {{NULL|DW_TAG}}
> +# ODR: DW_AT_name{{.*}}"foo"
> +# ODR-NOT: NULL
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"s"
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[ALIASFORS]]
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"nc"
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[NC]]
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"nnc"
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[NNC]]
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"ac"
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[ANONC]]
> +
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: {{NULL|DW_TAG}}
> +# ODR: linkage_name{{.*}}"_ZZ4funcvENKUlvE_clEv"
> +# ODR-NOT: NULL
> +# ODR: DW_TAG_variable
> +# ODR-NOT: DW_TAG
> +# ODR: DW_AT_name{{.*}}"dummy"
> +# ODR-NOT: NULL
> +# ODR: DW_AT_type{{.*}}[[CINSIDEFUNC]]
> +
> +# With no ODR uniquing, we should get copies of all the types:
> +
> +# This is "struct S"
> +# NOODR: 0x[[DUP_S:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"S"
> +
> +# This is "class N::C"
> +# NOODR: DW_TAG_namespace
> +# NOODR-NEXT: DW_AT_name{{.*}}"N"
> +# NOODR: 0x[[DUP_NC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"C"
> +
> +# This is "class N::N::C"
> +# NOODR: DW_TAG_namespace
> +# NOODR-NEXT: DW_AT_name{{.*}}"N"
> +# NOODR: 0x[[DUP_NNC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"C"
> +
> +# This is "AliasForS"
> +# NOODR: 0x[[DUP_ALIASFORS:[0-9a-f]*]]:{{.*}}DW_TAG_typedef
> +# NOODR-NOT: {{NULL|DW_TAG}}
> +# NOODR: DW_AT_name{{.*}}"AliasForS"
> +
> +# This is "union U"
> +
> +# NOODR: 0x[[U:[0-9a-f]*]]:{{.*}}DW_TAG_union_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"U"
> +# NOODR-NOT: NULL
> +# NOODR: 0x[[DUP_UC:[0-9a-f]*]]:{{.*}}DW_TAG_class_type
> +# NOODR-NOT: NULL
> +# NOODR: 0x[[DUP_US:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# NOODR: NULL
> +
> +# This is "func" free function
> +
> +# NOODR: DW_TAG_subprogram
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_name{{.*}}"func"
> +# NOODR: 0x[[DUP_CINSIDEFUNC:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"CInsideFunc"
> +
> +# NOODR: DW_TAG_subprogram
> +# NOODR-NOT: {{NULL|DW_TAG}}
> +# NOODR: DW_AT_name{{.*}}"foo"
> +# NOODR-NOT: NULL
> +# NOODR: DW_TAG_variable
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_name{{.*}}"s"
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_type{{.*}}[[DUP_ALIASFORS]]
> +# NOODR: DW_TAG_variable
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_name{{.*}}"nc"
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_type{{.*}}[[DUP_NC]]
> +# NOODR: DW_TAG_variable
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_name{{.*}}"nnc"
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_type{{.*}}[[DUP_NNC]]
> +# NOODR: DW_TAG_variable
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_name{{.*}}"ac"
> +# NOODR-NOT: {{DW_TAG|NULL}}
> +# NOODR: DW_AT_type{{.*}}0x[[DUP_ANONC:[0-9a-f]*]]
> +
> +# This is the lanbda inside func
> +
> +# NOODR: DW_TAG_subprogram
> +# NOODR-NOT: {{NULL|DW_TAG}}
> +# NOODR: linkage_name{{.*}}"_ZZ4funcvENKUlvE_clEv"
> +# NOODR-NOT: NULL
> +# NOODR: DW_TAG_variable
> +# NOODR-NOT: DW_TAG
> +# NOODR: DW_AT_name{{.*}}"dummy"
> +# NOODR-NOT: NULL
> +# NOODR: DW_AT_type{{.*}}[[DUP_CINSIDEFUNC]]
> +
> +# This is "(anonymous namespace)::AnonC"
> +
> +# NOODR: DW_TAG_namespace
> +# NOODR-NOT: {{DW_AT_name|NULL|DW_TAG}}
> +# NOODR: 0x[[DUP_ANONC]]:{{.*}}DW_TAG_class_type
> +# NOODR-NEXT: DW_AT_name{{.*}}"AnonC"
> +
> + - filename: odr2.o
> + symbols:
> + - { sym: __ZN1S3fooEv, objAddr: 0x0, binAddr: 0x7000, size: 0x12 }
> + - { sym: __Z3barv, objAddr: 0x0, binAddr: 0x8000, size: 0x12 }
> + - filename: odr3.o
> + symbols:
> + - { sym: __ZN1S3fooEv, objAddr: 0x0, binAddr: 0x8000, size: 0x12 }
> + - { sym: __Z3barv, objAddr: 0x0, binAddr: 0x9000, size: 0x12 }
> +
> +# odr2.cpp and odr3.cpp test that a simple overloaded function doesn't
> break the
> +# uniquing (contrary to what we'll see with template/artificial)
> functions.
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr2.cpp"
> +
> +# NO-ODR: DW_TAG_structure_type
> +# ODR-NOT: DW_TAG_structure_type
> +
> +# ODR: DW_TAG_subprogram
> +# ODR: DW_AT_specification{{.*}}4incr
> +# ODR: DW_TAG_formal_parameter
> +# ODR-NEXT: DW_AT_name{{.*}}"this"
> +# ODR-NEXT: DW_AT_type{{.*}}0x00000000[[S_PTR:[0-9a-f]*]]
> +# ODR: 0x[[S_PTR]]:{{.*}}DW_TAG_pointer_type
> +# ODR-NEXT: DW_AT_type{{.*}}[[S]]
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"bar"
> +# ODR-NOT: NULL
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[S]]
> +# ODR-NOT NULL
> +# DOR: DW_TAG_inlined_subroutine
> +# ODR-NOT NULL
> +# ODR: DW_TAG_formal_parameter
> +# ODR-NOT {{NULL|DW_TAG}}
> +# ODR: DW_AT_type{{.*}}[[S_PTR]]
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr3.cpp"
> +
> +# NO-ODR: DW_TAG_structure_type
> +# ODR-NOT: DW_TAG_structure_type
> +
> +# ODR: DW_TAG_subprogram
> +# ODR: DW_AT_specification{{.*}}4incr
> +# ODR: DW_TAG_formal_parameter
> +# ODR-NEXT: DW_AT_name{{.*}}"this"
> +# ODR-NEXT: DW_AT_type{{.*}}0x00000000[[S_PTR2:[0-9a-f]*]]
> +# ODR: 0x[[S_PTR2]]:{{.*}}DW_TAG_pointer_type
> +# ODR-NEXT: DW_AT_type{{.*}}[[S]]
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_name{{.*}}"bar"
> +# ODR-NOT: NULL
> +# ODR: DW_TAG_variable
> +# ODR-NOT: {{DW_TAG|NULL}}
> +# ODR: DW_AT_type{{.*}}[[S]]
> +# ODR-NOT NULL
> +# DOR: DW_TAG_inlined_subroutine
> +# ODR-NOT NULL
> +# ODR: DW_TAG_formal_parameter
> +# ODR-NOT {{NULL|DW_TAG}}
> +# ODR: DW_AT_type{{.*}}[[S_PTR2]]
> +
> + - filename: odr4.o
> + symbols:
> + - { sym: __Z3bazv, objAddr: 0x0, binAddr: 0xa000, size: 0x12 }
> +
> +# odr4.cpp helps check that anonymous namespaces with similarly named
> contents do
> +# not get uniqued.
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr4.cpp"
> +
> +# CHECK: DW_TAG_subprogram
> +# CHECK-NOT: NULL
> +# CHECK: DW_TAG_variable
> +# CHECK-NOT: DW_TAG
> +# ODR: DW_AT_type{{.*}}[[LOCALANONC:........]])
> +# NOODR: DW_AT_type{{.*}}[[LOCALANONC:........]]})
> +
> +# CHECK: DW_TAG_namespace
> +# CHECK-NOT: DW_AT_name
> +# CHECK: [[LOCALANONC]]{{.*}}DW_TAG_class_type
> +# CHECK-NOT: {{NULL|DW_TAG}}
> +# CHECK: DW_AT_name{{.*}}"AnonC"
> +
> + - filename: odr5.o
> + symbols:
> + - { sym: __Z3bazv, objAddr: 0x0, binAddr: 0xb000, size: 0x12 }
> + - { sym: __ZN1S6Nested4initIiEEvT_, objAddr: 0x0, binAddr: 0xc000,
> size: 0x12 }
> + - filename: odr6.o
> + symbols:
> + - { sym: __Z3bazv, objAddr: 0x0, binAddr: 0xd000, size: 0x12 }
> + - { sym: __ZN1S6Nested4initIdEEvT_, objAddr: 0x0, binAddr: 0xe000,
> size: 0x12 }
> +
> +# odr5.cpp and odr6.cpp instanciate a template member function of the S
> class.
> +# They instanciate it with different types. As DWARF only describes the
> actual
> +# intances, these members aren't described in the uniqued class
> definition of
> +# odr1.cpp. Both these files should contain a new copy of S' definition
> with
> +# the template instance included.
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr5.cpp"
> +
> +# CHECK: 0x{{[0-9a-f]*}}:{{.*}}DW_TAG_structure_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"S"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[NESTED2:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: DW_AT_name{{.*}}"Nested"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[INITTEMPLATE:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
> +# CHECK-NEXT:{{.*}}"_ZN1S6Nested4init
> +
> +# CHECK: DW_AT_specification{{.*}}[[INITTEMPLATE]]
> +# CHECK: DW_TAG_formal_parameter
> +# CHECK-NOT: DW_TAG
> +# CHECK: DW_AT_type{{.*}}[[NESTED_PTR:[0-9a-f]{8}]]{{[}]?}})
> +
> +# CHECK: 0x[[NESTED_PTR]]{{.*}}DW_TAG_pointer_type
> +# ODR-NEXT: DW_AT_type{{.*}}[[NESTED]]
> +# NOODR-NEXT: DW_AT_type{{.*}}[[NESTED2]]
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr6.cpp"
> +
> +# CHECK: 0x{{[0-9a-f]*}}:{{.*}}DW_TAG_structure_type
> +# CHECK-NEXT: DW_AT_name{{.*}}"S"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[NESTED3:[0-9a-f]*]]:{{.*}}DW_TAG_structure_type
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: DW_AT_name{{.*}}"Nested"
> +# CHECK-NOT: NULL
> +# CHECK: 0x[[INITTEMPLATE2:[0-9a-f]*]]:{{.*}}DW_TAG_subprogram
> +# CHECK-NEXT:{{.*}}"_ZN1S6Nested4init
> +
> +# CHECK: DW_AT_specification{{.*}}[[INITTEMPLATE2]]
> +# CHECK: DW_TAG_formal_parameter
> +# CHECK-NOT: DW_TAG
> +# CHECK: DW_AT_type{{.*}}[[NESTED_PTR2:[0-9a-f]{8}]]{{[}]?}})
> +
> +# CHECK: 0x[[NESTED_PTR2]]{{.*}}DW_TAG_pointer_type
> +# ODR-NEXT: DW_AT_type{{.*}}[[NESTED]]
> +# NOODR-NEXT: DW_AT_type{{.*}}[[NESTED3]]
> +
> + - filename: odr7.o
> + symbols:
> + - { sym: __Z3foov, objAddr: 0x0, binAddr: 0xf000, size: 0x12 }
> +
> +# Check that a reference to a nested class correctly refers to the
> original
> +# definition
> +
> +# CHECK: TAG_compile_unit
> +# CHECK-NOT: {{DW_TAG|NULL}}
> +# CHECK: AT_name{{.*}}"odr7.cpp"
> +
> +# ODR: DW_TAG_subprogram
> +# ODR-NOT: NULL
> +# ODR: DW_TAG_variable
> +# ODR-NOT: DW_TAG
> +# ODR: DW_AT_type{{.*}}[[NESTED]]
> +...
> +
>
> Modified: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=242847&r1=242846&r2=242847&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (original)
> +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Tue Jul 21 17:41:43 2015
> @@ -15,6 +15,7 @@
> #include "llvm/ADT/STLExtras.h"
> #include "llvm/CodeGen/AsmPrinter.h"
> #include "llvm/CodeGen/DIE.h"
> +#include "llvm/Config/config.h"
> #include "llvm/DebugInfo/DWARF/DWARFContext.h"
> #include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
> #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
> @@ -80,6 +81,112 @@ struct PatchLocation {
> }
> };
>
> +class CompileUnit;
> +struct DeclMapInfo;
> +class NonRelocatableStringpool;
> +
> +/// A DeclContext is a named program scope that is used for ODR
> +/// uniquing of types.
> +/// The set of DeclContext for the ODR-subject parts of a Dwarf link
> +/// is expanded (and uniqued) with each new object file processed. We
> +/// need to determine the context of each DIE in an linked object file
> +/// to see if the corresponding type has already been emitted.
> +///
> +/// The contexts are conceptually organised as a tree (eg. a function
> +/// scope is contained in a namespace scope that contains other
> +/// scopes), but storing/accessing them in an actual tree is too
> +/// inefficient: we need to be able to very quickly query a context
> +/// for a given child context by name. Storing a StringMap in each
> +/// DeclContext would be too space inefficient.
> +/// The solution here is to give each DeclContext a link to its parent
> +/// (this allows to walk up the tree), but to query the existance of a
> +/// specific DeclContext using a separate DenseMap keyed on the hash
> +/// of the fully qualified name of the context.
> +class DeclContext {
> + unsigned QualifiedNameHash;
> + uint32_t Line;
> + uint32_t ByteSize;
> + uint16_t Tag;
> + StringRef Name;
> + StringRef File;
> + const DeclContext &Parent;
> + const DWARFDebugInfoEntryMinimal *LastSeenDIE;
> + uint32_t LastSeenCompileUnitID;
> + uint32_t CanonicalDIEOffset;
> +
> + friend DeclMapInfo;
> +
> +public:
> + typedef DenseSet<DeclContext *, DeclMapInfo> Map;
> +
> + DeclContext()
> + : QualifiedNameHash(0), Line(0), ByteSize(0),
> + Tag(dwarf::DW_TAG_compile_unit), Name(), File(), Parent(*this),
> + LastSeenDIE(nullptr), LastSeenCompileUnitID(0),
> CanonicalDIEOffset(0) {}
> +
> + DeclContext(unsigned Hash, uint32_t Line, uint32_t ByteSize, uint16_t
> Tag,
> + StringRef Name, StringRef File, const DeclContext &Parent,
> + const DWARFDebugInfoEntryMinimal *LastSeenDIE = nullptr,
> + unsigned CUId = 0)
> + : QualifiedNameHash(Hash), Line(Line), ByteSize(ByteSize), Tag(Tag),
> + Name(Name), File(File), Parent(Parent), LastSeenDIE(LastSeenDIE),
> + LastSeenCompileUnitID(CUId), CanonicalDIEOffset(0) {}
> +
> + uint32_t getQualifiedNameHash() const { return QualifiedNameHash; }
> +
> + bool setLastSeenDIE(CompileUnit &U, const DWARFDebugInfoEntryMinimal
> *Die);
> +
> + uint32_t getCanonicalDIEOffset() const { return CanonicalDIEOffset; }
> + void setCanonicalDIEOffset(uint32_t Offset) { CanonicalDIEOffset =
> Offset; }
> +
> + uint16_t getTag() const { return Tag; }
> + StringRef getName() const { return Name; }
> +};
> +
> +/// Info type for the DenseMap storing the DeclContext pointers.
> +struct DeclMapInfo : private DenseMapInfo<DeclContext *> {
> + using DenseMapInfo<DeclContext *>::getEmptyKey;
> + using DenseMapInfo<DeclContext *>::getTombstoneKey;
> +
> + static unsigned getHashValue(const DeclContext *Ctxt) {
> + return Ctxt->QualifiedNameHash;
> + }
> +
> + static bool isEqual(const DeclContext *LHS, const DeclContext *RHS) {
> + if (RHS == getEmptyKey() || RHS == getTombstoneKey())
> + return RHS == LHS;
> + return LHS->QualifiedNameHash == RHS->QualifiedNameHash &&
> + LHS->Line == RHS->Line && LHS->ByteSize == RHS->ByteSize &&
> + LHS->Name.data() == RHS->Name.data() &&
> + LHS->File.data() == RHS->File.data() &&
> + LHS->Parent.QualifiedNameHash == RHS->Parent.QualifiedNameHash;
> + }
> +};
> +
> +/// This class gives a tree-like API to the DenseMap that stores the
> +/// DeclContext objects. It also holds the BumpPtrAllocator where
> +/// these objects will be allocated.
> +class DeclContextTree {
> + BumpPtrAllocator Allocator;
> + DeclContext Root;
> + DeclContext::Map Contexts;
> +
> +public:
> + /// Get the child of \a Context described by \a DIE in \a Unit. The
> + /// required strings will be interned in \a StringPool.
> + /// \returns The child DeclContext along with one bit that is set if
> + /// this context is invalid.
> + /// FIXME: the invalid bit along the return value is to emulate some
> + /// dsymutil-classic functionality. See the fucntion definition for
> + /// a more thorough discussion of its use.
> + PointerIntPair<DeclContext *, 1>
> + getChildDeclContext(DeclContext &Context,
> + const DWARFDebugInfoEntryMinimal *DIE, CompileUnit
> &Unit,
> + NonRelocatableStringpool &StringPool);
> +
> + DeclContext &getRoot() { return Root; }
> +};
> +
> /// \brief Stores all information relating to a compile unit, be it in
> /// its original instance in the object file to its brand new cloned
> /// and linked DIE tree.
> @@ -88,16 +195,26 @@ public:
> /// \brief Information gathered about a DIE in the object file.
> struct DIEInfo {
> int64_t AddrAdjust; ///< Address offset to apply to the described
> entity.
> + DeclContext *Ctxt; ///< ODR Declaration context.
> DIE *Clone; ///< Cloned version of that DIE.
> uint32_t ParentIdx; ///< The index of this DIE's parent.
> bool Keep; ///< Is the DIE part of the linked output?
> bool InDebugMap; ///< Was this DIE's entity found in the map?
> };
>
> - CompileUnit(DWARFUnit &OrigUnit, unsigned ID)
> + CompileUnit(DWARFUnit &OrigUnit, unsigned ID, bool CanUseODR)
> : OrigUnit(OrigUnit), ID(ID), LowPc(UINT64_MAX), HighPc(0),
> RangeAlloc(),
> Ranges(RangeAlloc) {
> Info.resize(OrigUnit.getNumDIEs());
> +
> + const auto *CUDie = OrigUnit.getUnitDIE(false);
> + unsigned Lang = CUDie->getAttributeValueAsUnsignedConstant(
> + &OrigUnit, dwarf::DW_AT_language, 0);
> + HasODR = CanUseODR && (Lang == dwarf::DW_LANG_C_plus_plus ||
> + Lang == dwarf::DW_LANG_C_plus_plus_03 ||
> + Lang == dwarf::DW_LANG_C_plus_plus_11 ||
> + Lang == dwarf::DW_LANG_C_plus_plus_14 ||
> + Lang == dwarf::DW_LANG_ObjC_plus_plus);
> }
>
> CompileUnit(CompileUnit &&RHS)
> @@ -116,6 +233,8 @@ public:
> DIE *getOutputUnitDIE() const { return CUDie; }
> void setOutputUnitDIE(DIE *Die) { CUDie = Die; }
>
> + bool hasODR() const { return HasODR; }
> +
> DIEInfo &getInfo(unsigned Idx) { return Info[Idx]; }
> const DIEInfo &getInfo(unsigned Idx) const { return Info[Idx]; }
>
> @@ -147,9 +266,10 @@ public:
>
> /// \brief Keep track of a forward reference to DIE \p Die in \p
> /// RefUnit by \p Attr. The attribute should be fixed up later to
> - /// point to the absolute offset of \p Die in the debug_info section.
> + /// point to the absolute offset of \p Die in the debug_info section
> + /// or to the canonical offset of \p Ctxt if it is non-null.
> void noteForwardReference(DIE *Die, const CompileUnit *RefUnit,
> - PatchLocation Attr);
> + DeclContext *Ctxt, PatchLocation Attr);
>
> /// \brief Apply all fixups recored by noteForwardReference().
> void fixupForwardReferences();
> @@ -190,11 +310,27 @@ public:
> const std::vector<AccelInfo> &getPubnames() const { return Pubnames; }
> const std::vector<AccelInfo> &getPubtypes() const { return Pubtypes; }
>
> + /// Get the full path for file \a FileNum in the line table
> + const char *getResolvedPath(unsigned FileNum) {
> + if (FileNum >= ResolvedPaths.size())
> + return nullptr;
> + return ResolvedPaths[FileNum].size() ? ResolvedPaths[FileNum].c_str()
> + : nullptr;
> + }
> +
> + /// Set the fully resolved path for the line-table's file \a FileNum
> + /// to \a Path.
> + void setResolvedPath(unsigned FileNum, const std::string &Path) {
> + if (ResolvedPaths.size() <= FileNum)
> + ResolvedPaths.resize(FileNum + 1);
> + ResolvedPaths[FileNum] = Path;
> + }
> +
> private:
> DWARFUnit &OrigUnit;
> unsigned ID;
> - std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
> - DIE *CUDie; ///< Root of the linked DIE tree.
> + std::vector<DIEInfo> Info; ///< DIE info indexed by DIE index.
> + DIE *CUDie; ///< Root of the linked DIE tree.
>
> uint64_t StartOffset;
> uint64_t NextUnitOffset;
> @@ -208,8 +344,8 @@ private:
> /// The offsets for the attributes in this array couldn't be set while
> /// cloning because for cross-cu forward refences the target DIE's
> /// offset isn't known you emit the reference attribute.
> - std::vector<std::tuple<DIE *, const CompileUnit *, PatchLocation>>
> - ForwardDIEReferences;
> + std::vector<std::tuple<DIE *, const CompileUnit *, DeclContext *,
> + PatchLocation>> ForwardDIEReferences;
>
> FunctionIntervals::Allocator RangeAlloc;
> /// \brief The ranges in that interval map are the PC ranges for
> @@ -236,6 +372,12 @@ private:
> std::vector<AccelInfo> Pubnames;
> std::vector<AccelInfo> Pubtypes;
> /// @}
> +
> + /// Cached resolved paths from the line table.
> + std::vector<std::string> ResolvedPaths;
> +
> + /// Is this unit subject to the ODR rule?
> + bool HasODR;
> };
>
> uint64_t CompileUnit::computeNextUnitOffset() {
> @@ -251,8 +393,8 @@ uint64_t CompileUnit::computeNextUnitOff
> /// \brief Keep track of a forward cross-cu reference from this unit
> /// to \p Die that lives in \p RefUnit.
> void CompileUnit::noteForwardReference(DIE *Die, const CompileUnit
> *RefUnit,
> - PatchLocation Attr) {
> - ForwardDIEReferences.emplace_back(Die, RefUnit, Attr);
> + DeclContext *Ctxt, PatchLocation
> Attr) {
> + ForwardDIEReferences.emplace_back(Die, RefUnit, Ctxt, Attr);
> }
>
> /// \brief Apply all fixups recorded by noteForwardReference().
> @@ -261,8 +403,12 @@ void CompileUnit::fixupForwardReferences
> DIE *RefDie;
> const CompileUnit *RefUnit;
> PatchLocation Attr;
> - std::tie(RefDie, RefUnit, Attr) = Ref;
> - Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
> + DeclContext *Ctxt;
> + std::tie(RefDie, RefUnit, Ctxt, Attr) = Ref;
> + if (Ctxt && Ctxt->getCanonicalDIEOffset())
> + Attr.set(Ctxt->getCanonicalDIEOffset());
> + else
> + Attr.set(RefDie->getOffset() + RefUnit->getStartOffset());
> }
> }
>
> @@ -324,6 +470,12 @@ public:
> /// one.
> uint32_t getStringOffset(StringRef S);
>
> + /// \brief Get permanent storage for \p S (but do not necessarily
> + /// emit \p S in the output section).
> + /// \returns The StringRef that points to permanent storage to use
> + /// in place of \p S.
> + StringRef internString(StringRef S);
> +
> // \brief Return the first entry of the string table.
> const MapTy::MapEntryTy *getFirstEntry() const {
> return getNextEntry(&Sentinel);
> @@ -367,6 +519,16 @@ uint32_t NonRelocatableStringpool::getSt
> return It->getValue().first;
> }
>
> +/// \brief Put \p S into the StringMap so that it gets permanent
> +/// storage, but do not actually link it in the chain of elements
> +/// that go into the output section. A latter call to
> +/// getStringOffset() with the same string will chain it though.
> +StringRef NonRelocatableStringpool::internString(StringRef S) {
> + std::pair<uint32_t, StringMapEntryBase *> Entry(0, nullptr);
> + auto InsertResult = Strings.insert(std::make_pair(S, Entry));
> + return InsertResult.first->getKey();
> +};
> +
> /// \brief The Dwarf streaming logic
> ///
> /// All interactions with the MC layer that is used to build the debug
> @@ -1089,6 +1251,7 @@ private:
> TF_InFunctionScope = 1 << 1, ///< Current scope is a fucntion scope.
> TF_DependencyWalk = 1 << 2, ///< Walking the dependencies of a kept
> DIE.
> TF_ParentWalk = 1 << 3, ///< Walking up the parents of a kept
> DIE.
> + TF_ODR = 1 << 4, ///< Use the ODR whhile keeping
> dependants.
> };
>
> /// \brief Mark the passed DIE as well as all the ones it depends on
> @@ -1096,7 +1259,7 @@ private:
> void keepDIEAndDenpendencies(const DWARFDebugInfoEntryMinimal &DIE,
> CompileUnit::DIEInfo &MyInfo,
> const DebugMapObject &DMO, CompileUnit &CU,
> - unsigned Flags);
> + bool UseODR);
>
> unsigned shouldKeepDIE(const DWARFDebugInfoEntryMinimal &DIE,
> CompileUnit &Unit, CompileUnit::DIEInfo &MyInfo,
> @@ -1227,11 +1390,14 @@ private:
> BumpPtrAllocator DIEAlloc;
> /// @}
>
> + /// ODR Contexts for that link.
> + DeclContextTree ODRContexts;
> +
> /// \defgroup Helpers Various helper methods.
> ///
> /// @{
> const DWARFDebugInfoEntryMinimal *
> - resolveDIEReference(DWARFFormValue &RefValue, const DWARFUnit &Unit,
> + resolveDIEReference(const DWARFFormValue &RefValue, const DWARFUnit
> &Unit,
> const DWARFDebugInfoEntryMinimal &DIE,
> CompileUnit *&ReferencedCU);
>
> @@ -1296,7 +1462,7 @@ CompileUnit *DwarfLinker::getUnitForOffs
> /// CompileUnit which is stored into \p ReferencedCU.
> /// \returns null if resolving fails for any reason.
> const DWARFDebugInfoEntryMinimal *DwarfLinker::resolveDIEReference(
> - DWARFFormValue &RefValue, const DWARFUnit &Unit,
> + const DWARFFormValue &RefValue, const DWARFUnit &Unit,
> const DWARFDebugInfoEntryMinimal &DIE, CompileUnit *&RefCU) {
> assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
> uint64_t RefOffset = *RefValue.getAsReference(&Unit);
> @@ -1309,6 +1475,220 @@ const DWARFDebugInfoEntryMinimal *DwarfL
> return nullptr;
> }
>
> +/// \returns whether the passed \a Attr type might contain a DIE
> +/// reference suitable for ODR uniquing.
> +static bool isODRAttribute(uint16_t Attr) {
> + switch (Attr) {
> + default:
> + return false;
> + case dwarf::DW_AT_type:
> + case dwarf::DW_AT_containing_type:
> + case dwarf::DW_AT_specification:
> + case dwarf::DW_AT_abstract_origin:
> + case dwarf::DW_AT_import:
> + return true;
> + }
> + llvm_unreachable("Improper attribute.");
> +}
> +
> +/// Set the last DIE/CU a context was seen in and, possibly invalidate
> +/// the context if it is ambiguous.
> +///
> +/// In the current implementation, we don't handle overloaded
> +/// functions well, because the argument types are not taken into
> +/// account when computing the DeclContext tree.
> +///
> +/// Some of this is mitigated byt using mangled names that do contain
> +/// the arguments types, but sometimes (eg. with function templates)
> +/// we don't have that. In that case, just do not unique anything that
> +/// refers to the contexts we are not able to distinguish.
> +///
> +/// If a context that is not a namespace appears twice in the same CU,
> +/// we know it is ambiguous. Make it invalid.
> +bool DeclContext::setLastSeenDIE(CompileUnit &U,
> + const DWARFDebugInfoEntryMinimal *Die) {
> + if (LastSeenCompileUnitID == U.getUniqueID()) {
> + DWARFUnit &OrigUnit = U.getOrigUnit();
> + uint32_t FirstIdx = OrigUnit.getDIEIndex(LastSeenDIE);
> + U.getInfo(FirstIdx).Ctxt = nullptr;
> + return false;
> + }
> +
> + LastSeenCompileUnitID = U.getUniqueID();
> + LastSeenDIE = Die;
> + return true;
> +}
> +
> +/// Get the child context of \a Context corresponding to \a DIE.
> +///
> +/// \returns the child context or null if we shouldn't track children
> +/// contexts. It also returns an additional bit meaning 'invalid'. An
> +/// invalid context means it shouldn't be considered for uniquing, but
> +/// its not returning null, because some children of that context
> +/// might be uniquing candidates.
> +/// FIXME: this is for dsymutil-classic compatibility, I don't think
> +/// it buys us much.
> +PointerIntPair<DeclContext *, 1> DeclContextTree::getChildDeclContext(
> + DeclContext &Context, const DWARFDebugInfoEntryMinimal *DIE,
> CompileUnit &U,
> + NonRelocatableStringpool &StringPool) {
> + unsigned Tag = DIE->getTag();
> +
> + // FIXME: dsymutil-classic compat: We should bail out here if we
> + // have a specification or an abstract_origin. We will get the
> + // parent context wrong here.
> +
> + switch (Tag) {
> + default:
> + // By default stop gathering child contexts.
> + return PointerIntPair<DeclContext *, 1>(nullptr);
> + case dwarf::DW_TAG_compile_unit:
> + // FIXME: Add support for DW_TAG_module.
> + return PointerIntPair<DeclContext *, 1>(&Context);
> + case dwarf::DW_TAG_subprogram:
> + // Do not unique anything inside CU local functions.
> + if ((Context.getTag() == dwarf::DW_TAG_namespace ||
> + Context.getTag() == dwarf::DW_TAG_compile_unit) &&
> + !DIE->getAttributeValueAsUnsignedConstant(&U.getOrigUnit(),
> + dwarf::DW_AT_external,
> 0))
> + return PointerIntPair<DeclContext *, 1>(nullptr);
> + // Fallthrough
> + case dwarf::DW_TAG_member:
> + case dwarf::DW_TAG_namespace:
> + case dwarf::DW_TAG_structure_type:
> + case dwarf::DW_TAG_class_type:
> + case dwarf::DW_TAG_union_type:
> + case dwarf::DW_TAG_enumeration_type:
> + case dwarf::DW_TAG_typedef:
> + // Artificial things might be ambiguous, because they might be
> + // created on demand. For example implicitely defined constructors
> + // are ambiguous because of the way we identify contexts, and they
> + // won't be generated everytime everywhere.
> + if (DIE->getAttributeValueAsUnsignedConstant(&U.getOrigUnit(),
> + dwarf::DW_AT_artificial,
> 0))
> + return PointerIntPair<DeclContext *, 1>(nullptr);
> + break;
> + }
> +
> + const char *Name = DIE->getName(&U.getOrigUnit(),
> DINameKind::LinkageName);
> + const char *ShortName = DIE->getName(&U.getOrigUnit(),
> DINameKind::ShortName);
> + StringRef NameRef;
> + StringRef ShortNameRef;
> + StringRef FileRef;
> +
> + if (Name)
> + NameRef = StringPool.internString(Name);
> + else if (Tag == dwarf::DW_TAG_namespace)
> + // FIXME: For dsymutil-classic compatibility. I think uniquing
> + // within anonymous namespaces is wrong. There is no ODR guarantee
> + // there.
> + NameRef = StringPool.internString("(anonymous namespace)");
> +
> + if (ShortName && ShortName != Name)
> + ShortNameRef = StringPool.internString(ShortName);
> + else
> + ShortNameRef = NameRef;
> +
> + if (Tag != dwarf::DW_TAG_class_type && Tag !=
> dwarf::DW_TAG_structure_type &&
> + Tag != dwarf::DW_TAG_union_type &&
> + Tag != dwarf::DW_TAG_enumeration_type && NameRef.empty())
> + return PointerIntPair<DeclContext *, 1>(nullptr);
> +
> + std::string File;
> + unsigned Line = 0;
> + unsigned ByteSize = 0;
> +
> + // Gather some discriminating data about the DeclContext we will be
> + // creating: File, line number and byte size. This shouldn't be
> + // necessary, because the ODR is just about names, but given that we
> + // do some approximations with overloaded functions and anonymous
> + // namespaces, use these additional data points to make the process
> safer.
> + ByteSize = DIE->getAttributeValueAsUnsignedConstant(
> + &U.getOrigUnit(), dwarf::DW_AT_byte_size, UINT64_MAX);
> + if (Tag != dwarf::DW_TAG_namespace || !Name) {
> + if (unsigned FileNum = DIE->getAttributeValueAsUnsignedConstant(
> + &U.getOrigUnit(), dwarf::DW_AT_decl_file, 0)) {
> + if (const auto *LT =
> U.getOrigUnit().getContext().getLineTableForUnit(
> + &U.getOrigUnit())) {
> + // FIXME: dsymutil-classic compatibility. I'd rather not
> + // unique anything in anonymous namespaces, but if we do, then
> + // verify that the file and line correspond.
> + if (!Name && Tag == dwarf::DW_TAG_namespace)
> + FileNum = 1;
> +
> + // FIXME: Passing U.getOrigUnit().getCompilationDir()
> + // instead of "" would allow more uniquing, but for now, do
> + // it this way to match dsymutil-classic.
> + if (LT->getFileNameByIndex(
> + FileNum, "",
> + DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
> + File)) {
> + Line = DIE->getAttributeValueAsUnsignedConstant(
> + &U.getOrigUnit(), dwarf::DW_AT_decl_line, 0);
> +#ifdef HAVE_REALPATH
> + // Cache the resolved paths, because calling realpath is
> expansive.
> + if (const char *ResolvedPath = U.getResolvedPath(FileNum)) {
> + File = ResolvedPath;
> + } else {
> + char RealPath[PATH_MAX + 1];
> + RealPath[PATH_MAX] = 0;
> + if (::realpath(File.c_str(), RealPath))
> + File = RealPath;
> + U.setResolvedPath(FileNum, File);
> + }
> +#endif
> + FileRef = StringPool.internString(File);
> + }
> + }
> + }
> + }
> +
> + if (!Line && NameRef.empty())
> + return PointerIntPair<DeclContext *, 1>(nullptr);
> +
> + // FIXME: dsymutil-classic compat won't unique the same type
> + // presented once as a struct and once as a class. Use the Tag in
> + // the fully qualified name hash to get the same effect.
> + // We hash NameRef, which is the mangled name, in order to get most
> + // overloaded functions resolvec correctly.
> + unsigned Hash = hash_combine(Context.getQualifiedNameHash(), Tag,
> NameRef);
> +
> + // FIXME: dsymutil-classic compatibility: when we don't have a name,
> + // use the filename.
> + if (Tag == dwarf::DW_TAG_namespace && NameRef == "(anonymous
> namespace)")
> + Hash = hash_combine(Hash, FileRef);
> +
> + // Now look if this context already exists.
> + DeclContext Key(Hash, Line, ByteSize, Tag, NameRef, FileRef, Context);
> + auto ContextIter = Contexts.find(&Key);
> +
> + if (ContextIter == Contexts.end()) {
> + // The context wasn't found.
> + bool Inserted;
> + DeclContext *NewContext =
> + new (Allocator) DeclContext(Hash, Line, ByteSize, Tag, NameRef,
> FileRef,
> + Context, DIE, U.getUniqueID());
> + std::tie(ContextIter, Inserted) = Contexts.insert(NewContext);
> + assert(Inserted && "Failed to insert DeclContext");
> + (void)Inserted;
> + } else if (Tag != dwarf::DW_TAG_namespace &&
> + !(*ContextIter)->setLastSeenDIE(U, DIE)) {
> + // The context was found, but it is ambiguous with another context
> + // in the same file. Mark it invalid.
> + return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */
> 1);
> + }
> +
> + assert(ContextIter != Contexts.end());
> + // FIXME: dsymutil-classic compatibility. Union types aren't
> + // uniques, but their children might be.
> + if ((Tag == dwarf::DW_TAG_subprogram &&
> + Context.getTag() != dwarf::DW_TAG_structure_type &&
> + Context.getTag() != dwarf::DW_TAG_class_type) ||
> + (Tag == dwarf::DW_TAG_union_type))
> + return PointerIntPair<DeclContext *, 1>(*ContextIter, /* Invalid= */
> 1);
> +
> + return PointerIntPair<DeclContext *, 1>(*ContextIter);
> +}
> +
> /// \brief Get the potential name and mangled name for the entity
> /// described by \p Die and store them in \Info if they are not
> /// already there.
> @@ -1355,14 +1735,30 @@ bool DwarfLinker::createStreamer(Triple
> /// \brief Recursive helper to gather the child->parent relationships in
> the
> /// original compile unit.
> static void gatherDIEParents(const DWARFDebugInfoEntryMinimal *DIE,
> - unsigned ParentIdx, CompileUnit &CU) {
> + unsigned ParentIdx, CompileUnit &CU,
> + DeclContext *CurrentDeclContext,
> + NonRelocatableStringpool &StringPool,
> + DeclContextTree &Contexts) {
> unsigned MyIdx = CU.getOrigUnit().getDIEIndex(DIE);
> - CU.getInfo(MyIdx).ParentIdx = ParentIdx;
> + CompileUnit::DIEInfo &Info = CU.getInfo(MyIdx);
> +
> + Info.ParentIdx = ParentIdx;
> + if (CU.hasODR()) {
> + if (CurrentDeclContext) {
> + auto PtrInvalidPair =
> Contexts.getChildDeclContext(*CurrentDeclContext,
> + DIE, CU,
> StringPool);
> + CurrentDeclContext = PtrInvalidPair.getPointer();
> + Info.Ctxt =
> + PtrInvalidPair.getInt() ? nullptr : PtrInvalidPair.getPointer();
> + } else
> + Info.Ctxt = CurrentDeclContext = nullptr;
> + }
>
> if (DIE->hasChildren())
> for (auto *Child = DIE->getFirstChild(); Child && !Child->isNULL();
> Child = Child->getSibling())
> - gatherDIEParents(Child, MyIdx, CU);
> + gatherDIEParents(Child, MyIdx, CU, CurrentDeclContext, StringPool,
> + Contexts);
> }
>
> static bool dieNeedsChildrenToBeMeaningful(uint32_t Tag) {
> @@ -1380,6 +1776,12 @@ static bool dieNeedsChildrenToBeMeaningf
> llvm_unreachable("Invalid Tag");
> }
>
> +static unsigned getRefAddrSize(const DWARFUnit &U) {
> + if (U.getVersion() == 2)
> + return U.getAddressByteSize();
> + return 4;
> +}
> +
> void DwarfLinker::startDebugObject(DWARFContext &Dwarf, DebugMapObject
> &Obj) {
> Units.reserve(Dwarf.getNumCompileUnits());
> NextValidReloc = 0;
> @@ -1686,15 +2088,16 @@ unsigned DwarfLinker::shouldKeepDIE(cons
> void DwarfLinker::keepDIEAndDenpendencies(const
> DWARFDebugInfoEntryMinimal &DIE,
> CompileUnit::DIEInfo &MyInfo,
> const DebugMapObject &DMO,
> - CompileUnit &CU, unsigned
> Flags) {
> + CompileUnit &CU, bool UseODR) {
> const DWARFUnit &Unit = CU.getOrigUnit();
> MyInfo.Keep = true;
>
> // First mark all the parent chain as kept.
> unsigned AncestorIdx = MyInfo.ParentIdx;
> while (!CU.getInfo(AncestorIdx).Keep) {
> + unsigned ODRFlag = UseODR ? TF_ODR : 0;
> lookForDIEsToKeep(*Unit.getDIEAtIndex(AncestorIdx), DMO, CU,
> - TF_ParentWalk | TF_Keep | TF_DependencyWalk);
> + TF_ParentWalk | TF_Keep | TF_DependencyWalk |
> ODRFlag);
> AncestorIdx = CU.getInfo(AncestorIdx).ParentIdx;
> }
>
> @@ -1715,9 +2118,27 @@ void DwarfLinker::keepDIEAndDenpendencie
>
> Val.extractValue(Data, &Offset, &Unit);
> CompileUnit *ReferencedCU;
> - if (const auto *RefDIE = resolveDIEReference(Val, Unit, DIE,
> ReferencedCU))
> + if (const auto *RefDIE =
> + resolveDIEReference(Val, Unit, DIE, ReferencedCU)) {
> + uint32_t RefIdx = ReferencedCU->getOrigUnit().getDIEIndex(RefDIE);
> + CompileUnit::DIEInfo &Info = ReferencedCU->getInfo(RefIdx);
> + // If the referenced DIE has a DeclContext that has already been
> + // emitted, then do not keep the one in this CU. We'll link to
> + // the canonical DIE in cloneDieReferenceAttribute.
> + // FIXME: compatibility with dsymutil-classic. UseODR shouldn't
> + // be necessary and could be advantageously replaced by
> + // ReferencedCU->hasODR() && CU.hasODR().
> + // FIXME: compatibility with dsymutil-classic. There is no
> + // reason not to unique ref_addr references.
> + if (AttrSpec.Form != dwarf::DW_FORM_ref_addr && UseODR && Info.Ctxt
> &&
> + Info.Ctxt != ReferencedCU->getInfo(Info.ParentIdx).Ctxt &&
> + Info.Ctxt->getCanonicalDIEOffset() &&
> isODRAttribute(AttrSpec.Attr))
> + continue;
> +
> + unsigned ODRFlag = UseODR ? TF_ODR : 0;
> lookForDIEsToKeep(*RefDIE, DMO, *ReferencedCU,
> - TF_Keep | TF_DependencyWalk);
> + TF_Keep | TF_DependencyWalk | ODRFlag);
> + }
> }
> }
>
> @@ -1752,9 +2173,10 @@ void DwarfLinker::lookForDIEsToKeep(cons
> Flags = shouldKeepDIE(DIE, CU, MyInfo, Flags);
>
> // If it is a newly kept DIE mark it as well as all its dependencies as
> kept.
> - if (!AlreadyKept && (Flags & TF_Keep))
> - keepDIEAndDenpendencies(DIE, MyInfo, DMO, CU, Flags);
> -
> + if (!AlreadyKept && (Flags & TF_Keep)) {
> + bool UseOdr = (Flags & TF_DependencyWalk) ? (Flags & TF_ODR) :
> CU.hasODR();
> + keepDIEAndDenpendencies(DIE, MyInfo, DMO, CU, UseOdr);
> + }
> // The TF_ParentWalk flag tells us that we are currently walking up
> // the parent chain of a required DIE, and we don't want to mark all
> // the children of the parents as kept (consider for example a
> @@ -1823,24 +2245,34 @@ unsigned DwarfLinker::cloneDieReferenceA
> DIE &Die, const DWARFDebugInfoEntryMinimal &InputDIE,
> AttributeSpec AttrSpec, unsigned AttrSize, const DWARFFormValue &Val,
> CompileUnit &Unit) {
> - uint32_t Ref = *Val.getAsReference(&Unit.getOrigUnit());
> + const DWARFUnit &U = Unit.getOrigUnit();
> + uint32_t Ref = *Val.getAsReference(&U);
> DIE *NewRefDie = nullptr;
> CompileUnit *RefUnit = nullptr;
> - const DWARFDebugInfoEntryMinimal *RefDie = nullptr;
> + DeclContext *Ctxt = nullptr;
>
> - if (!(RefUnit = getUnitForOffset(Ref)) ||
> - !(RefDie = RefUnit->getOrigUnit().getDIEForOffset(Ref))) {
> - const char *AttributeString = dwarf::AttributeString(AttrSpec.Attr);
> - if (!AttributeString)
> - AttributeString = "DW_AT_???";
> - reportWarning(Twine("Missing DIE for ref in attribute ") +
> AttributeString +
> - ". Dropping.",
> - &Unit.getOrigUnit(), &InputDIE);
> + const DWARFDebugInfoEntryMinimal *RefDie =
> + resolveDIEReference(Val, U, InputDIE, RefUnit);
> +
> + // If the referenced DIE is not found, drop the attribute.
> + if (!RefDie)
> return 0;
> - }
>
> unsigned Idx = RefUnit->getOrigUnit().getDIEIndex(RefDie);
> CompileUnit::DIEInfo &RefInfo = RefUnit->getInfo(Idx);
> +
> + // If we already have emitted an equivalent DeclContext, just point
> + // at it.
> + if (isODRAttribute(AttrSpec.Attr)) {
> + Ctxt = RefInfo.Ctxt;
> + if (Ctxt && Ctxt->getCanonicalDIEOffset()) {
> + DIEInteger Attr(Ctxt->getCanonicalDIEOffset());
> + Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
> + dwarf::DW_FORM_ref_addr, Attr);
> + return getRefAddrSize(U);
> + }
> + }
> +
> if (!RefInfo.Clone) {
> assert(Ref > InputDIE.getOffset());
> // We haven't cloned this DIE yet. Just create an empty one and
> @@ -1849,7 +2281,8 @@ unsigned DwarfLinker::cloneDieReferenceA
> }
> NewRefDie = RefInfo.Clone;
>
> - if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) {
> + if (AttrSpec.Form == dwarf::DW_FORM_ref_addr ||
> + (Unit.hasODR() && isODRAttribute(AttrSpec.Attr))) {
> // We cannot currently rely on a DIEEntry to emit ref_addr
> // references, because the implementation calls back to DwarfDebug
> // to find the unit offset. (We don't have a DwarfDebug)
> @@ -1867,11 +2300,11 @@ unsigned DwarfLinker::cloneDieReferenceA
> // A forward reference. Note and fixup later.
> Attr = 0xBADDEF;
> Unit.noteForwardReference(
> - NewRefDie, RefUnit,
> + NewRefDie, RefUnit, Ctxt,
> Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
> dwarf::DW_FORM_ref_addr, DIEInteger(Attr)));
> }
> - return AttrSize;
> + return getRefAddrSize(U);
> }
>
> Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
> @@ -2150,6 +2583,14 @@ DIE *DwarfLinker::cloneDIE(const DWARFDe
> Die = Info.Clone = DIE::get(DIEAlloc, dwarf::Tag(InputDIE.getTag()));
> assert(Die->getTag() == InputDIE.getTag());
> Die->setOffset(OutOffset);
> + if (Unit.hasODR() && Die->getTag() != dwarf::DW_TAG_namespace &&
> Info.Ctxt &&
> + Info.Ctxt != Unit.getInfo(Info.ParentIdx).Ctxt &&
> + !Info.Ctxt->getCanonicalDIEOffset()) {
> + // We are about to emit a DIE that is the root of its own valid
> + // DeclContext tree. Make the current offset the canonical offset
> + // for this context.
> + Info.Ctxt->setCanonicalDIEOffset(OutOffset + Unit.getStartOffset());
> + }
>
> // Extract and clone every attribute.
> DataExtractor Data = U.getDebugInfoExtractor();
> @@ -2611,8 +3052,9 @@ bool DwarfLinker::link(const DebugMap &M
> outs() << "Input compilation unit:";
> CUDie->dump(outs(), CU.get(), 0);
> }
> - Units.emplace_back(*CU, UnitID++);
> - gatherDIEParents(CUDie, 0, Units.back());
> + Units.emplace_back(*CU, UnitID++, !Options.NoODR);
> + gatherDIEParents(CUDie, 0, Units.back(), &ODRContexts.getRoot(),
> + StringPool, ODRContexts);
> }
>
> // Then mark all the DIEs that need to be present in the linked
>
> Modified: llvm/trunk/tools/dsymutil/dsymutil.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.cpp?rev=242847&r1=242846&r2=242847&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/dsymutil.cpp (original)
> +++ llvm/trunk/tools/dsymutil/dsymutil.cpp Tue Jul 21 17:41:43 2015
> @@ -47,6 +47,11 @@ static opt<bool>
> desc("Do the link in memory, but do not emit the result
> file."),
> init(false));
>
> +static opt<bool>
> + NoODR("no-odr",
> + desc("Do not use ODR (One Definition Rule) for type uniquing."),
> + init(false));
> +
> static opt<bool> DumpDebugMap(
> "dump-debug-map",
> desc("Parse and dump the debug map to standard output. Not DWARF link
> "
> @@ -71,6 +76,7 @@ int main(int argc, char **argv) {
>
> Options.Verbose = Verbose;
> Options.NoOutput = NoOutput;
> + Options.NoODR = NoODR;
>
> llvm::InitializeAllTargetInfos();
> llvm::InitializeAllTargetMCs();
>
> Modified: llvm/trunk/tools/dsymutil/dsymutil.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.h?rev=242847&r1=242846&r2=242847&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/dsymutil.h (original)
> +++ llvm/trunk/tools/dsymutil/dsymutil.h Tue Jul 21 17:41:43 2015
> @@ -27,6 +27,7 @@ namespace dsymutil {
> struct LinkOptions {
> bool Verbose; ///< Verbosity
> bool NoOutput; ///< Skip emitting output
> + bool NoODR; ///< Do not unique types according to ODR
>
> LinkOptions() : Verbose(false), NoOutput(false) {}
> };
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150721/2af3bc18/attachment.html>
More information about the llvm-commits
mailing list