]> granicus.if.org Git - llvm/commitdiff
[codeview] Align symbol records to save 441MB during linking clang.pdb
authorReid Kleckner <rnk@google.com>
Tue, 18 Dec 2018 01:14:05 +0000 (01:14 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 18 Dec 2018 01:14:05 +0000 (01:14 +0000)
In PDBs, symbol records must be aligned to four bytes. However, in the
object file, symbol records may not be aligned. MSVC does not pad out
symbol records to make sure they are aligned. That means the linker has
to do extra work to insert the padding. Currently, LLD calculates the
required space with alignment, and copies each record one at a time
while padding them out to the correct size. It has a fast path that
avoids this copy when the records are already aligned.

This change fixes a bug in that codepath so that the copy is actually
saved, and tweaks LLVM's symbol record emission to align symbol records.
Here's how things compare when doing a plain clang Release+PDB build:
- objs are 0.65% bigger (negligible)
- link is 3.3% faster (negligible)
- saves allocating 441MB
- new LLD high water mark is ~1.05GB

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@349431 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/AsmPrinter/CodeViewDebug.cpp
test/DebugInfo/COFF/frameproc-flags.ll
test/DebugInfo/COFF/multifunction.ll
test/DebugInfo/COFF/simple.ll
test/DebugInfo/COFF/thunk.ll
test/DebugInfo/COFF/types-cvarargs.ll
test/DebugInfo/COFF/udts-complete.ll
test/DebugInfo/COFF/udts.ll
test/DebugInfo/COFF/vframe-fpo.ll

index 93b76997c0773091423b615a5d5a668499db184f..78e5f5d215b3ff1a1be5b838c8d9775873a3a490 100644 (file)
@@ -2833,6 +2833,7 @@ MCSymbol *CodeViewDebug::beginSymbolRecord(SymbolKind SymKind) {
 void CodeViewDebug::endSymbolRecord(MCSymbol *SymEnd) {
   // Symbol records in object files are not aligned, although we are considering
   // it for linker performance reasons.
+  OS.EmitValueToAlignment(4);
   OS.EmitLabel(SymEnd);
 }
 
index a9d0fe067da6e77b9019c07a95c84c701504318a..b2a1ef97cfb5a9090c6e3327fc631568b98d74d4 100644 (file)
 ; }
 ; }
 
-; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_alloca`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 52] `use_alloca`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = VFRAME, param fp reg = EBP
 ; CHECK:   flags = has alloca | secure checks | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 51] `call_setjmp`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 52] `call_setjmp`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = NONE, param fp reg = NONE
 ; CHECK:   flags = has setjmp | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 53] `use_inlineasm`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 56] `use_inlineasm`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = NONE, param fp reg = NONE
 ; CHECK:   flags = has inline asm | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 46] `cpp_eh`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 48] `cpp_eh`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = EBP, param fp reg = EBP
 ; CHECK:   flags = has eh | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 50] `use_inline`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 52] `use_inline`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = NONE, param fp reg = NONE
 ; CHECK:   flags = opt speed
 ; CHECK-LABEL: S_LPROC32_ID [size = 56] `is_marked_inline`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = NONE, param fp reg = NONE
 ; CHECK:   flags = marked inline | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 43] `seh`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 44] `seh`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = EBP, param fp reg = EBP
 ; CHECK:   flags = has seh | opt speed
-; CHECK-LABEL: S_LPROC32_ID [size = 55] `?filt$0@0@seh@@`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_LPROC32_ID [size = 56] `?filt$0@0@seh@@`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = EBP, param fp reg = EBP
 ; CHECK:   flags = opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 49] `use_naked`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 52] `use_naked`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = NONE, param fp reg = NONE
 ; CHECK:   flags = has inline asm | naked | opt speed
-; CHECK-LABEL: S_GPROC32_ID [size = 51] `stack_guard`
-; CHECK: S_FRAMEPROC [size = 30]
+; CHECK-LABEL: S_GPROC32_ID [size = 52] `stack_guard`
+; CHECK: S_FRAMEPROC [size = 32]
 ; CHECK:   local fp reg = VFRAME, param fp reg = EBP
 ; CHECK:   flags = secure checks | opt speed
 
index c74b332d8b848f7fdf84e8b3454d1e1b90374645..1c19b34ab9386685ebde0c26937b74718a2b5c14 100644 (file)
@@ -80,6 +80,7 @@
 ; X86-NEXT: .secidx _x
 ; X86-NEXT: .byte   0
 ; X86-NEXT: .asciz "x"
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[PROC_SEGMENT_END]]:
 ; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X86-NEXT: [[FPROC_BEG]]:
@@ -91,6 +92,7 @@
 ; X86-NEXT: .long   0                       # Exception handler offset
 ; X86-NEXT: .short  0                       # Exception handler section
 ; X86-NEXT: .long   0                       # Flags (defines frame register)
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[FPROC_END]]:
 ; X86-NEXT: .short  2
 ; X86-NEXT: .short  4431
 ; X86-NEXT: .secidx _y
 ; X86-NEXT: .byte   0
 ; X86-NEXT: .asciz "y"
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[PROC_SEGMENT_END]]:
 ; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X86-NEXT: [[FPROC_BEG]]:
 ; X86-NEXT: .long   0                       # Exception handler offset
 ; X86-NEXT: .short  0                       # Exception handler section
 ; X86-NEXT: .long   0                       # Flags (defines frame register)
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[FPROC_END]]:
 ; X86-NEXT: .short  2
 ; X86-NEXT: .short  4431
 ; X86-NEXT: .secidx _f
 ; X86-NEXT: .byte   0
 ; X86-NEXT: .asciz "f"
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[PROC_SEGMENT_END]]:
 ; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X86-NEXT: [[FPROC_BEG]]:
 ; X86-NEXT: .long   0                       # Exception handler offset
 ; X86-NEXT: .short  0                       # Exception handler section
 ; X86-NEXT: .long   0                       # Flags (defines frame register)
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[FPROC_END]]:
 ; X86-NEXT: .short  2
 ; X86-NEXT: .short  4431
 ; X64-NEXT: .secidx x
 ; X64-NEXT: .byte   0
 ; X64-NEXT: .asciz "x"
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[PROC_SEGMENT_END]]:
 ; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X64-NEXT: [[FPROC_BEG]]:
 ; X64-NEXT: .long   0                       # Exception handler offset
 ; X64-NEXT: .short  0                       # Exception handler section
 ; X64-NEXT: .long   81920                       # Flags (defines frame register)
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[FPROC_END]]:
 ; X64-NEXT: .short  2
 ; X64-NEXT: .short  4431
 ; X64-NEXT: .secidx y
 ; X64-NEXT: .byte   0
 ; X64-NEXT: .asciz "y"
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[PROC_SEGMENT_END]]:
 ; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X64-NEXT: [[FPROC_BEG]]:
 ; X64-NEXT: .long   0                       # Exception handler offset
 ; X64-NEXT: .short  0                       # Exception handler section
 ; X64-NEXT: .long   81920                       # Flags (defines frame register)
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[FPROC_END]]:
 ; X64-NEXT: .short  2
 ; X64-NEXT: .short  4431
 ; X64-NEXT: .secidx f
 ; X64-NEXT: .byte   0
 ; X64-NEXT: .asciz "f"
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[PROC_SEGMENT_END]]:
 ; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X64-NEXT: [[FPROC_BEG]]:
 ; X64-NEXT: .long   0                       # Exception handler offset
 ; X64-NEXT: .short  0                       # Exception handler section
 ; X64-NEXT: .long   81920                       # Flags (defines frame register)
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[FPROC_END]]:
 ; X64-NEXT: .short  2
 ; X64-NEXT: .short  4431
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x64 IMAGE_REL_AMD64_SECREL x
 ; OBJ64-NEXT:   0x68 IMAGE_REL_AMD64_SECTION x
-; OBJ64-NEXT:   0x98 IMAGE_REL_AMD64_SECREL x
-; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECTION x
-; OBJ64-NEXT:   0xFC IMAGE_REL_AMD64_SECREL y
-; OBJ64-NEXT:   0x100 IMAGE_REL_AMD64_SECTION y
-; OBJ64-NEXT:   0x130 IMAGE_REL_AMD64_SECREL y
-; OBJ64-NEXT:   0x134 IMAGE_REL_AMD64_SECTION y
-; OBJ64-NEXT:   0x194 IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT:   0x198 IMAGE_REL_AMD64_SECTION f
-; OBJ64-NEXT:   0x1C8 IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT:   0x1CC IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECREL x
+; OBJ64-NEXT:   0xA0 IMAGE_REL_AMD64_SECTION x
+; OBJ64-NEXT:   0x100 IMAGE_REL_AMD64_SECREL y
+; OBJ64-NEXT:   0x104 IMAGE_REL_AMD64_SECTION y
+; OBJ64-NEXT:   0x138 IMAGE_REL_AMD64_SECREL y
+; OBJ64-NEXT:   0x13C IMAGE_REL_AMD64_SECTION y
+; OBJ64-NEXT:   0x19C IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x1A0 IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT:   0x1D4 IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0x1D8 IMAGE_REL_AMD64_SECTION f
 ; OBJ64-NEXT: ]
 ; OBJ64:      Subsection [
 ; OBJ64-NEXT:   SubSectionType: Symbols (0xF1)
index 3c495a33b8a25770ff38371759d9609c78c7b12b..58d0f42a67ada08da8e28f6a5350df9d2f1f0747 100644 (file)
@@ -58,6 +58,7 @@
 ; X86-NEXT: .secidx _f
 ; X86-NEXT: .byte   0
 ; X86-NEXT: .asciz "f"
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[PROC_SEGMENT_END]]:
 ; X86-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X86-NEXT: [[FPROC_BEG]]:
@@ -69,6 +70,7 @@
 ; X86-NEXT: .long   0                       # Exception handler offset
 ; X86-NEXT: .short  0                       # Exception handler section
 ; X86-NEXT: .long   0                       # Flags (defines frame register)
+; X86-NEXT: .p2align 2
 ; X86-NEXT: [[FPROC_END]]:
 ; X86-NEXT: .short  2
 ; X86-NEXT: .short  4431
@@ -89,8 +91,8 @@
 ; OBJ32-NEXT:   0x44 IMAGE_REL_I386_DIR32NB _f
 ; OBJ32-NEXT:   0x90 IMAGE_REL_I386_SECREL _f
 ; OBJ32-NEXT:   0x94 IMAGE_REL_I386_SECTION _f
-; OBJ32-NEXT:   0xC4 IMAGE_REL_I386_SECREL _f
-; OBJ32-NEXT:   0xC8 IMAGE_REL_I386_SECTION _f
+; OBJ32-NEXT:   0xC8 IMAGE_REL_I386_SECREL _f
+; OBJ32-NEXT:   0xCC IMAGE_REL_I386_SECTION _f
 ; OBJ32-NEXT: ]
 ; OBJ32:      Subsection [
 ; OBJ32-NEXT:   SubSectionType: Symbols (0xF1)
 ; X64-NEXT: .secidx f
 ; X64-NEXT: .byte   0
 ; X64-NEXT: .asciz "f"
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[PROC_SEGMENT_END]]:
 ; X64-NEXT: .short  [[FPROC_END:[^ ]*]]-[[FPROC_BEG:[^ ]*]]           # Record length
 ; X64-NEXT: [[FPROC_BEG]]:
 ; X64-NEXT: .long   0                       # Exception handler offset
 ; X64-NEXT: .short  0                       # Exception handler section
 ; X64-NEXT: .long   81920                       # Flags (defines frame register)
+; X64-NEXT: .p2align 2
 ; X64-NEXT: [[FPROC_END]]:
 ; X64-NEXT: .short  2
 ; X64-NEXT: .short  4431
 ; OBJ64:      Relocations [
 ; OBJ64-NEXT:   0x64 IMAGE_REL_AMD64_SECREL f
 ; OBJ64-NEXT:   0x68 IMAGE_REL_AMD64_SECTION f
-; OBJ64-NEXT:   0x98 IMAGE_REL_AMD64_SECREL f
-; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECTION f
+; OBJ64-NEXT:   0x9C IMAGE_REL_AMD64_SECREL f
+; OBJ64-NEXT:   0xA0 IMAGE_REL_AMD64_SECTION f
 ; OBJ64-NEXT: ]
 ; OBJ64:      Subsection [
 ; OBJ64-NEXT:   SubSectionType: Symbols (0xF1)
index eac48ba1284f6541b9df1ca6b83c96c360c9a140..c8f5c5ad4367fcaca649aa2ba54b5a465c4ef904 100644 (file)
@@ -70,6 +70,7 @@
 ; ASM-NEXT:   .short  Lfunc_end{{.*}}-"[[NAME1]]" # Code size 
 ; ASM-NEXT:   .byte   0                       # Ordinal 
 ; ASM-NEXT:   .asciz  "[[NAME1]]"             # Function name 
+; ASM-NEXT:   .p2align 2
 ; ASM-NEXT: [[END1]]:
 ; ASM-NEXT:   .short  2                       # Record length 
 ; ASM-NEXT:   .short  4431                    # Record kind: S_PROC_ID_END 
@@ -88,6 +89,7 @@
 ; ASM-NEXT:   .short Lfunc_end{{.*}}-"[[NAME2]]" # Code size
 ; ASM-NEXT:   .byte 0                         # Ordinal
 ; ASM-NEXT:   .asciz "[[NAME2]]"              # Function name
+; ASM-NEXT:   .p2align 2
 ; ASM-NEXT: [[END2]]:
 ; ASM-NEXT:   .short 2                        # Record length
 ; ASM-NEXT:   .short 4431                     # Record kind: S_PROC_ID_END 
index deb3e6e365240e0f1b95cc0bdcc1539acda9f3e8..5e366f0e981f97c830ac7de4c65e630c2542898c 100644 (file)
@@ -25,7 +25,7 @@
 ; CHECK:  }
 ; CHECK:  Subsection [
 ; CHECK:    SubSectionType: Symbols (0xF1)
-; CHECK:    SubSectionSize: 0x2A
+; CHECK:    SubSectionSize:
 ; CHECK:    UDTSym {
 ; CHECK:      Kind: S_UDT (0x1108)
 ; CHECK:      Type: MemberTest::A (0x1008)
index 1683ceabd50e61baaf5d5cbc1c01becc793fb6ae..ace86ee4e668fb73b7688fb67e1a373de44134aa 100644 (file)
@@ -31,7 +31,7 @@
 ; CHECK:                           Symbols
 ; CHECK: ============================================================
 ; CHECK:   Mod 0000 | `.debug$S`:
-; CHECK:        0 | S_GDATA32 [size = 17] `gv`
+; CHECK:        0 | S_GDATA32 [size = 20] `gv`
 ; CHECK:            type = 0x1002 (Foo), addr = 0000:0000
 ; CHECK:        0 | S_UDT [size = 12] `Bar`
 ; CHECK:            original type = 0x1002
index 114e11a70e8c2d20a0908a25885e25c8dda8ee6d..d17f5cd4921b8485dee6ccfe45eb60dcfde1838f 100644 (file)
 ; PDBUTIL:                           Symbols
 ; PDBUTIL-NEXT: ============================================================
 ; PDBUTIL-NOT:   S_UDT {{.*}} `A::C`
-; PDBUTIL:       S_UDT [size = 15] `f::FOO`
-; PDBUTIL:       S_UDT [size = 15] `g::pun`
-; PDBUTIL:       S_UDT [size = 10] `S`
-; PDBUTIL:       S_UDT [size = 10] `A`
-; PDBUTIL:       S_UDT [size = 13] `A::D`
-; PDBUTIL:       S_UDT [size = 10] `U`
-; PDBUTIL:       S_UDT [size = 10] `U`
+; 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`
 
 source_filename = "test/DebugInfo/COFF/udts.ll"
 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
@@ -190,4 +190,4 @@ attributes #1 = { nounwind readnone speculatable }
 !53 = !DILocation(line: 9, column: 5, scope: !38)
 !54 = !DILocation(line: 9, column: 7, scope: !38)
 !55 = !DILocation(line: 10, column: 12, scope: !38)
-!56 = !DILocation(line: 10, column: 3, scope: !38)
\ No newline at end of file
+!56 = !DILocation(line: 10, column: 3, scope: !38)
index b3b71530214cf2970ac353d9673c2950eea52f8d..27273cd5c00121517d7a66ca07604629781b3b9a 100644 (file)
 ; CODEVIEW-NEXT:   Magic: 0x4
 ; CODEVIEW-NEXT:   Subsection [
 ; CODEVIEW-NEXT:     SubSectionType: Symbols (0xF1)
-; CODEVIEW-NEXT:     SubSectionSize: 0x2F
+; CODEVIEW-NEXT:     SubSectionSize:
 ; CODEVIEW-NEXT:     Compile3Sym {
 ; CODEVIEW-NEXT:       Kind: S_COMPILE3 (0x113C)
 ; CODEVIEW:          }
 ; CODEVIEW:        ]
 ; CODEVIEW:        Subsection [
 ; CODEVIEW-NEXT:     SubSectionType: FrameData (0xF5)
-; CODEVIEW-NEXT:     SubSectionSize: 0xA4
+; CODEVIEW-NEXT:     SubSectionSize:
 ; CODEVIEW-NEXT:     LinkageName: _main
 ; CODEVIEW:          FrameData {
 ; CODEVIEW:          }
 
 ; CODEVIEW:      Subsection [
 ; CODEVIEW-NEXT:   SubSectionType: Symbols (0xF1)
-; CODEVIEW-NEXT:   SubSectionSize: 0xA2
+; CODEVIEW-NEXT:   SubSectionSize:
 ; CODEVIEW-NEXT:   GlobalProcIdSym {
 ; CODEVIEW-NEXT:     Kind: S_GPROC32_ID (0x1147)
 ; CODEVIEW:          DisplayName: main