2017-09-02 04:06:56 +08:00
; RUN: llc < %s -filetype=obj > %t.obj
2019-05-01 13:27:20 +08:00
; RUN: llvm-readobj --codeview %t.obj | FileCheck --check-prefix=READOBJ %s
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; RUN: llvm-pdbutil dump -symbols %t.obj | FileCheck --check-prefix=PDBUTIL %s
2017-09-02 04:06:56 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; C++ to regenerate:
; $ clang -g -gcodeview -m64 -S -emit-llvm t.cpp
2016-06-16 02:00:01 +08:00
; $ cat t.cpp
; void f() {
; typedef int FOO;
; FOO f;
; }
2016-06-24 06:57:25 +08:00
;
; struct S { int x; };
; float g(S *s) {
; union pun { int x; float f; } p;
; p.x = s->x;
; return p.f;
; }
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; struct A {
; // We should not output S_UDT for nested typedef.
; typedef S C;
; C c;
; // We should output S_UDT for typedef of nested unnamed struct
; typedef struct { long X; } D;
; D d;
; };
; A a;
;
2016-07-02 06:24:51 +08:00
; typedef struct { int x; } U;
; U u;
2016-06-16 02:00:01 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; READOBJ-NOT: UDTName: A::C
2017-09-02 04:06:56 +08:00
; READOBJ: {{.*}}Proc{{.*}}Sym {
; READOBJ: DisplayName: f
; READOBJ: LinkageName: ?f@@YAXXZ
; READOBJ: }
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: int (0x74)
; READOBJ-NEXT: UDTName: f::FOO
; READOBJ-NEXT: }
; READOBJ-NEXT: ProcEnd {
; READOBJ: {{.*}}Proc{{.*}}Sym {
; READOBJ: DisplayName: g
; READOBJ: LinkageName: ?g@@YAMPEAUS@@@Z
; READOBJ: }
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: g::pun (0x{{[0-9A-F]+}})
; READOBJ-NEXT: UDTName: g::pun
; READOBJ-NEXT: }
; READOBJ-NEXT: ProcEnd {
2016-06-16 02:00:01 +08:00
2017-09-02 04:06:56 +08:00
; READOBJ: Subsection
; READOBJ-NOT: {{.*}}Proc{{.*}}Sym
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: S (0x{{[0-9A-F]+}})
; READOBJ-NEXT: UDTName: S
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; READOBJ-NEXT: Type: A (0x{{[0-9A-F]+}})
; READOBJ-NEXT: UDTName: A
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: A::D (0x{{[0-9A-F]+}})
; READOBJ-NEXT: UDTName: A::D
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: U (0x{{[0-9A-F]+}})
2017-09-02 04:06:56 +08:00
; READOBJ-NEXT: UDTName: U
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; READOBJ: UDTSym {
; READOBJ-NEXT: Kind: S_UDT (0x1108)
; READOBJ-NEXT: Type: U (0x{{[0-9A-F]+}})
; READOBJ-NEXT: UDTName: U
; READOBJ-NOT: UDTSym
2016-06-24 06:57:25 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; PDBUTIL: Symbols
2017-09-02 04:06:56 +08:00
; PDBUTIL-NEXT: ============================================================
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; PDBUTIL-NOT: S_UDT {{.*}} `A::C`
2018-12-18 09:14:05 +08:00
; PDBUTIL: S_UDT [size = 16] `f::FOO`
; PDBUTIL: S_UDT [size = 16] `g::pun`
; PDBUTIL: S_UDT [size = 12] `S`
; PDBUTIL: S_UDT [size = 12] `A`
; PDBUTIL: S_UDT [size = 16] `A::D`
; PDBUTIL: S_UDT [size = 12] `U`
; PDBUTIL: S_UDT [size = 12] `U`
2016-06-24 06:57:25 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
source_filename = "test/DebugInfo/COFF/udts.ll"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc19.11.25506"
%struct.A = type { %struct.S , %"struct.A::D" }
2016-06-24 06:57:25 +08:00
%struct.S = type { i32 }
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
%"struct.A::D" = type { i32 }
%struct.U = type { i32 }
2016-06-24 06:57:25 +08:00
%union.pun = type { i32 }
2016-06-16 02:00:01 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
@"\01?a@@3UA@@A" = global %struct.A zeroinitializer , align 4 , !dbg !0
@"\01?u@@3UU@@A" = global %struct.U zeroinitializer , align 4 , !dbg !6
2016-07-02 06:24:51 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; Function Attrs: noinline nounwind optnone uwtable
define void @"\01?f@@YAXXZ" ( ) #0 !dbg !31 {
%1 = alloca i32 , align 4
call void @llvm.dbg.declare ( metadata i32 * %1 , metadata !34 , metadata !DIExpression ( ) ) , !dbg !36
ret void , !dbg !37
2016-06-16 02:00:01 +08:00
}
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; Function Attrs: nounwind readnone speculatable
2016-06-16 02:00:01 +08:00
declare void @llvm.dbg.declare ( metadata , metadata , metadata ) #1
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
; Function Attrs: noinline nounwind optnone uwtable
define float @"\01?g@@YAMPEAUS@@@Z" ( %struct.S * ) #0 !dbg !38 {
%2 = alloca %struct.S * , align 8
%3 = alloca %union.pun , align 4
store %struct.S * %0 , %struct.S * * %2 , align 8
call void @llvm.dbg.declare ( metadata %struct.S * * %2 , metadata !43 , metadata !DIExpression ( ) ) , !dbg !44
call void @llvm.dbg.declare ( metadata %union.pun * %3 , metadata !45 , metadata !DIExpression ( ) ) , !dbg !50
%4 = load %struct.S * , %struct.S * * %2 , align 8 , !dbg !51
%5 = getelementptr inbounds %struct.S , %struct.S * %4 , i32 0 , i32 0 , !dbg !52
%6 = load i32 , i32 * %5 , align 4 , !dbg !52
%7 = bitcast %union.pun * %3 to i32 * , !dbg !53
store i32 %6 , i32 * %7 , align 4 , !dbg !54
%8 = bitcast %union.pun * %3 to float * , !dbg !55
%9 = load float , float * %8 , align 4 , !dbg !55
ret float %9 , !dbg !56
2016-06-24 06:57:25 +08:00
}
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math" = "false" "disable-tail-calls" = "false" "less-precise-fpmad" = "false" "no-frame-pointer-elim" = "false" "no-infs-fp-math" = "false" "no-jump-tables" = "false" "no-nans-fp-math" = "false" "no-signed-zeros-fp-math" = "false" "no-trapping-math" = "false" "stack-protector-buffer-size" = "8" "target-cpu" = "x86-64" "target-features" = "+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math" = "false" "use-soft-float" = "false" }
attributes #1 = { nounwind readnone s p e c u l a t a b l e }
2016-06-16 02:00:01 +08:00
2016-12-22 08:45:21 +08:00
!llvm.dbg.cu = ! { !2 }
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
!llvm.module.flags = ! { !26 , !27 , !28 , !29 }
!llvm.ident = ! { !30 }
2016-12-22 08:45:21 +08:00
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
!0 = !DIGlobalVariableExpression ( var: !1 , expr: !DIExpression ( ) )
!1 = distinct !DIGlobalVariable ( name: "a" , linkageName: "\01?a@@3UA@@A" , scope: !2 , file: !3 , line: 21 , type: !13 , isLocal: false , isDefinition: true )
!2 = distinct !DICompileUnit ( language: D W _ L A N G _ C _ p l u s _ p l u s , file: !3 , producer: "clang version 6.0.0 " , isOptimized: false , runtimeVersion: 0 , emissionKind: F u l l D e b u g , enums: !4 , globals: !5 )
!3 = !DIFile ( filename: "t.cpp" , directory: "D:\5Csrc\5Cllvmbuild\5Cninja-release" , checksumkind: C S K _ M D 5 , checksum: "e894de94ed2e0d503ebb5dbcc550c544" )
2016-12-22 08:45:21 +08:00
!4 = ! { }
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
!5 = ! { !0 , !6 }
!6 = !DIGlobalVariableExpression ( var: !7 , expr: !DIExpression ( ) )
!7 = distinct !DIGlobalVariable ( name: "u" , linkageName: "\01?u@@3UU@@A" , scope: !2 , file: !3 , line: 24 , type: !8 , isLocal: false , isDefinition: true )
!8 = !DIDerivedType ( tag: D W _ T A G _ t y p e d e f , name: "U" , file: !3 , line: 23 , baseType: !9 )
!9 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "U" , file: !3 , line: 23 , size: 32 , elements: !10 , identifier: ".?AUU@@" )
!10 = ! { !11 }
!11 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "x" , scope: !9 , file: !3 , line: 23 , baseType: !12 , size: 32 )
!12 = !DIBasicType ( name: "int" , size: 32 , encoding: D W _ A T E _ s i g n e d )
!13 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "A" , file: !3 , line: 13 , size: 64 , elements: !14 , identifier: ".?AUA@@" )
!14 = ! { !15 , !19 , !20 , !24 , !25 }
!15 = !DIDerivedType ( tag: D W _ T A G _ t y p e d e f , name: "C" , scope: !13 , file: !3 , line: 15 , baseType: !16 )
!16 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "S" , file: !3 , line: 6 , size: 32 , elements: !17 , identifier: ".?AUS@@" )
!17 = ! { !18 }
!18 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "x" , scope: !16 , file: !3 , line: 6 , baseType: !12 , size: 32 )
!19 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "c" , scope: !13 , file: !3 , line: 16 , baseType: !15 , size: 32 )
!20 = distinct !DICompositeType ( tag: D W _ T A G _ s t r u c t u r e _ type , name: "D" , scope: !13 , file: !3 , line: 18 , size: 32 , elements: !21 , identifier: ".?AUD@A@@" )
!21 = ! { !22 }
!22 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "X" , scope: !20 , file: !3 , line: 18 , baseType: !23 , size: 32 )
!23 = !DIBasicType ( name: "long int" , size: 32 , encoding: D W _ A T E _ s i g n e d )
!24 = !DIDerivedType ( tag: D W _ T A G _ t y p e d e f , name: "D" , scope: !13 , file: !3 , line: 18 , baseType: !20 )
!25 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "d" , scope: !13 , file: !3 , line: 19 , baseType: !24 , size: 32 , offset: 32 )
!26 = ! { i32 2 , !"CodeView" , i32 1 }
!27 = ! { i32 2 , !"Debug Info Version" , i32 3 }
!28 = ! { i32 1 , !"wchar_size" , i32 2 }
!29 = ! { i32 7 , !"PIC Level" , i32 2 }
!30 = ! { !"clang version 6.0.0 " }
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 10:40:45 +08:00
!31 = distinct !DISubprogram ( name: "f" , linkageName: "\01?f@@YAXXZ" , scope: !3 , file: !3 , line: 1 , type: !32 , isLocal: false , isDefinition: true , scopeLine: 1 , flags: D I F l a g P r o t o t y p e d , isOptimized: false , unit: !2 , retainedNodes: !4 )
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
!32 = !DISubroutineType ( types: !33 )
!33 = ! { null }
!34 = !DILocalVariable ( name: "f" , scope: !31 , file: !3 , line: 3 , type: !35 )
!35 = !DIDerivedType ( tag: D W _ T A G _ t y p e d e f , name: "FOO" , scope: !31 , file: !3 , line: 2 , baseType: !12 )
!36 = !DILocation ( line: 3 , column: 7 , scope: !31 )
!37 = !DILocation ( line: 4 , column: 1 , scope: !31 )
[DebugInfo] Add DILabel metadata and intrinsic llvm.dbg.label.
In order to set breakpoints on labels and list source code around
labels, we need collect debug information for labels, i.e., label
name, the function label belong, line number in the file, and the
address label located. In order to keep these information in LLVM
IR and to allow backend to generate debug information correctly.
We create a new kind of metadata for labels, DILabel. The format
of DILabel is
!DILabel(scope: !1, name: "foo", file: !2, line: 3)
We hope to keep debug information as much as possible even the
code is optimized. So, we create a new kind of intrinsic for label
metadata to avoid the metadata is eliminated with basic block.
The intrinsic will keep existing if we keep it from optimized out.
The format of the intrinsic is
llvm.dbg.label(metadata !1)
It has only one argument, that is the DILabel metadata. The
intrinsic will follow the label immediately. Backend could get the
label metadata through the intrinsic's parameter.
We also create DIBuilder API for labels to be used by Frontend.
Frontend could use createLabel() to allocate DILabel objects, and use
insertLabel() to insert llvm.dbg.label intrinsic in LLVM IR.
Differential Revision: https://reviews.llvm.org/D45024
Patch by Hsiangkai Wang.
llvm-svn: 331841
2018-05-09 10:40:45 +08:00
!38 = distinct !DISubprogram ( name: "g" , linkageName: "\01?g@@YAMPEAUS@@@Z" , scope: !3 , file: !3 , line: 7 , type: !39 , isLocal: false , isDefinition: true , scopeLine: 7 , flags: D I F l a g P r o t o t y p e d , isOptimized: false , unit: !2 , retainedNodes: !4 )
[CodeView] Don't output S_UDTs for nested typedefs.
S_UDT records are basically the "bridge" between the debugger's
expression evaluator and the type information. If you type
(Foo*)nullptr into the watch window, the debugger looks for an
S_UDT record named Foo. If it can find one, it displays your type.
Otherwise you get an error.
We have always understood this to mean that if you have code like
this:
struct A {
int X;
};
struct B {
typedef A AT;
AT Member;
};
that you will get 3 S_UDT records. "A", "B", and "B::AT". Because
if you were to type (B::AT*)nullptr into the debugger, it would
need to find an S_UDT record named "B::AT".
But "B::AT" is actually the S_UDT record that would be generated
if B were a namespace, not a struct. So the debugger needs to be
able to distinguish this case. So what it does is:
1. Look for an S_UDT named "B::AT". If it finds one, it knows
that AT is in a namespace.
2. If it doesn't find one, split at the scope resolution operator,
and look for an S_UDT named B. If it finds one, look up the type
for B, and then look for AT as one of its members.
With this algorithm, S_UDT records for nested typedefs are not just
unnecessary, but actually wrong!
The results of implementing this in clang are dramatic. It cuts
our /DEBUG:FASTLINK PDB sizes by more than 50%, and we go from
being ~20% larger than MSVC PDBs on average, to ~40% smaller.
It also slightly speeds up link time. We get about 10% faster
links than without this patch.
Differential Revision: https://reviews.llvm.org/D37410
llvm-svn: 312583
2017-09-06 06:06:39 +08:00
!39 = !DISubroutineType ( types: !40 )
!40 = ! { !41 , !42 }
!41 = !DIBasicType ( name: "float" , size: 32 , encoding: D W _ A T E _ float )
!42 = !DIDerivedType ( tag: D W _ T A G _ p o i n t e r _ type , baseType: !16 , size: 64 )
!43 = !DILocalVariable ( name: "s" , arg: 1 , scope: !38 , file: !3 , line: 7 , type: !42 )
!44 = !DILocation ( line: 7 , column: 12 , scope: !38 )
!45 = !DILocalVariable ( name: "p" , scope: !38 , file: !3 , line: 8 , type: !46 )
!46 = distinct !DICompositeType ( tag: D W _ T A G _ u n i o n _ type , name: "pun" , scope: !38 , file: !3 , line: 8 , size: 32 , elements: !47 )
!47 = ! { !48 , !49 }
!48 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "x" , scope: !46 , file: !3 , line: 8 , baseType: !12 , size: 32 )
!49 = !DIDerivedType ( tag: D W _ T A G _ m e m b e r , name: "f" , scope: !46 , file: !3 , line: 8 , baseType: !41 , size: 32 )
!50 = !DILocation ( line: 8 , column: 33 , scope: !38 )
!51 = !DILocation ( line: 9 , column: 9 , scope: !38 )
!52 = !DILocation ( line: 9 , column: 12 , scope: !38 )
!53 = !DILocation ( line: 9 , column: 5 , scope: !38 )
!54 = !DILocation ( line: 9 , column: 7 , scope: !38 )
!55 = !DILocation ( line: 10 , column: 12 , scope: !38 )
2018-12-18 09:14:05 +08:00
!56 = !DILocation ( line: 10 , column: 3 , scope: !38 )