Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit 76ee764

Browse files
committed
[codeview] Improve readability of codeview assembly output
Strictly speaking, this is not an improvement in functionality per se but a usability improvement to those debugging codeview. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@259601 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 7cec6c6 commit 76ee764

File tree

6 files changed

+200
-109
lines changed

6 files changed

+200
-109
lines changed

lib/CodeGen/AsmPrinter/CodeViewDebug.cpp

Lines changed: 81 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ void CodeViewDebug::endModule() {
182182
assert(Asm != nullptr);
183183
Asm->OutStreamer->SwitchSection(
184184
Asm->getObjFileLowering().getCOFFDebugSymbolsSection());
185+
Asm->OutStreamer->AddComment("Debug section magic");
185186
Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
186187

187188
// The COFF .debug$S section consists of several subsections, each starting
@@ -207,14 +208,11 @@ void CodeViewDebug::endModule() {
207208
clear();
208209
}
209210

210-
template <typename T> static void emitRecord(MCStreamer &OS, const T &Rec) {
211-
OS.EmitBytes(StringRef(reinterpret_cast<const char *>(&Rec), sizeof(Rec)));
212-
}
213-
214211
void CodeViewDebug::emitTypeInformation() {
215212
// Start the .debug$T section with 0x4.
216213
Asm->OutStreamer->SwitchSection(
217214
Asm->getObjFileLowering().getCOFFDebugTypesSection());
215+
Asm->OutStreamer->AddComment("Debug section magic");
218216
Asm->EmitInt32(COFF::DEBUG_SECTION_MAGIC);
219217

220218
NamedMDNode *CU_Nodes =
@@ -226,34 +224,49 @@ void CodeViewDebug::emitTypeInformation() {
226224
// frame info. All functions are assigned a simple 'void ()' type. Emit that
227225
// type here.
228226
TypeIndex ArgListIdx = getNextTypeIndex();
227+
Asm->OutStreamer->AddComment("Type record length");
229228
Asm->EmitInt16(2 + sizeof(ArgList));
229+
Asm->OutStreamer->AddComment("Leaf type: LF_ARGLIST");
230230
Asm->EmitInt16(LF_ARGLIST);
231+
Asm->OutStreamer->AddComment("Number of arguments");
231232
Asm->EmitInt32(0);
232233

233234
TypeIndex VoidProcIdx = getNextTypeIndex();
235+
Asm->OutStreamer->AddComment("Type record length");
234236
Asm->EmitInt16(2 + sizeof(ProcedureType));
237+
Asm->OutStreamer->AddComment("Leaf type: LF_PROCEDURE");
235238
Asm->EmitInt16(LF_PROCEDURE);
236-
ProcedureType Proc{}; // Zero initialize.
237-
Proc.ReturnType = TypeIndex::Void();
238-
Proc.CallConv = CallingConvention::NearC;
239-
Proc.Options = FunctionOptions::None;
240-
Proc.NumParameters = 0;
241-
Proc.ArgListType = ArgListIdx;
242-
emitRecord(*Asm->OutStreamer, Proc);
239+
Asm->OutStreamer->AddComment("Return type index");
240+
Asm->EmitInt32(TypeIndex::Void().getIndex());
241+
Asm->OutStreamer->AddComment("Calling convention");
242+
Asm->EmitInt8(char(CallingConvention::NearC));
243+
Asm->OutStreamer->AddComment("Function options");
244+
Asm->EmitInt8(char(FunctionOptions::None));
245+
Asm->OutStreamer->AddComment("# of parameters");
246+
Asm->EmitInt16(0);
247+
Asm->OutStreamer->AddComment("Argument list type index");
248+
Asm->EmitInt32(ArgListIdx.getIndex());
243249

244250
for (MDNode *N : CU_Nodes->operands()) {
245251
auto *CUNode = cast<DICompileUnit>(N);
246252
for (auto *SP : CUNode->getSubprograms()) {
247253
StringRef DisplayName = SP->getDisplayName();
254+
Asm->OutStreamer->AddComment("Type record length");
248255
Asm->EmitInt16(2 + sizeof(FuncId) + DisplayName.size() + 1);
256+
Asm->OutStreamer->AddComment("Leaf type: LF_FUNC_ID");
249257
Asm->EmitInt16(LF_FUNC_ID);
250258

251-
FuncId Func{}; // Zero initialize.
252-
Func.ParentScope = TypeIndex();
253-
Func.FunctionType = VoidProcIdx;
254-
emitRecord(*Asm->OutStreamer, Func);
255-
Asm->OutStreamer->EmitBytes(DisplayName);
256-
Asm->EmitInt8(0);
259+
Asm->OutStreamer->AddComment("Scope type index");
260+
Asm->EmitInt32(TypeIndex().getIndex());
261+
Asm->OutStreamer->AddComment("Function type");
262+
Asm->EmitInt32(VoidProcIdx.getIndex());
263+
{
264+
SmallString<32> NullTerminatedString(DisplayName);
265+
if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0')
266+
NullTerminatedString.push_back('\0');
267+
Asm->OutStreamer->AddComment("Function name");
268+
Asm->OutStreamer->EmitBytes(NullTerminatedString);
269+
}
257270

258271
TypeIndex FuncIdIdx = getNextTypeIndex();
259272
SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx));
@@ -271,23 +284,30 @@ void CodeViewDebug::emitInlineeLinesSubsection() {
271284

272285
OS.AddComment("Inlinee lines subsection");
273286
OS.EmitIntValue(unsigned(ModuleSubstreamKind::InlineeLines), 4);
287+
OS.AddComment("Subsection size");
274288
OS.emitAbsoluteSymbolDiff(InlineEnd, InlineBegin, 4);
275289
OS.EmitLabel(InlineBegin);
276290

277291
// We don't provide any extra file info.
278292
// FIXME: Find out if debuggers use this info.
293+
OS.AddComment("Inlinee lines signature");
279294
OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
280295

281296
for (const DISubprogram *SP : InlinedSubprograms) {
297+
OS.AddBlankLine();
282298
TypeIndex TypeId = SubprogramToFuncId[SP];
283299
unsigned FileId = maybeRecordFile(SP->getFile());
284300
OS.AddComment("Inlined function " + SP->getDisplayName() + " starts at " +
285301
SP->getFilename() + Twine(':') + Twine(SP->getLine()));
302+
OS.AddBlankLine();
286303
// The filechecksum table uses 8 byte entries for now, and file ids start at
287304
// 1.
288305
unsigned FileOffset = (FileId - 1) * 8;
306+
OS.AddComment("Type index of inlined function");
289307
OS.EmitIntValue(TypeId.getIndex(), 4);
308+
OS.AddComment("Offset into filechecksum table");
290309
OS.EmitIntValue(FileOffset, 4);
310+
OS.AddComment("Starting line number");
291311
OS.EmitIntValue(SP->getLine(), 4);
292312
}
293313

@@ -330,14 +350,18 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
330350
TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee];
331351

332352
// SymbolRecord
353+
Asm->OutStreamer->AddComment("Record length");
333354
EmitLabelDiff(OS, InlineBegin, InlineEnd, 2); // RecordLength
334355
OS.EmitLabel(InlineBegin);
356+
Asm->OutStreamer->AddComment("Record kind: S_INLINESITE");
335357
Asm->EmitInt16(SymbolRecordKind::S_INLINESITE); // RecordKind
336358

337-
InlineSiteSym SiteBytes{};
338-
SiteBytes.Inlinee = InlineeIdx;
339-
Asm->OutStreamer->EmitBytes(
340-
StringRef(reinterpret_cast<const char *>(&SiteBytes), sizeof(SiteBytes)));
359+
Asm->OutStreamer->AddComment("PtrParent");
360+
Asm->OutStreamer->EmitIntValue(0, 4);
361+
Asm->OutStreamer->AddComment("PtrEnd");
362+
Asm->OutStreamer->EmitIntValue(0, 4);
363+
Asm->OutStreamer->AddComment("Inlinee type index");
364+
Asm->EmitInt32(InlineeIdx.getIndex());
341365

342366
unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
343367
unsigned StartLineNum = Site.Inlinee->getLine();
@@ -358,7 +382,9 @@ void CodeViewDebug::emitInlinedCallSite(const FunctionInfo &FI,
358382
}
359383

360384
// Close the scope.
385+
Asm->OutStreamer->AddComment("Record length");
361386
Asm->EmitInt16(2); // RecordLength
387+
Asm->OutStreamer->AddComment("Record kind: S_INLINESITE_END");
362388
Asm->EmitInt16(SymbolRecordKind::S_INLINESITE_END); // RecordKind
363389
}
364390

@@ -382,30 +408,51 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
382408
*SymbolsEnd = Asm->MMI->getContext().createTempSymbol();
383409
Asm->OutStreamer->AddComment("Symbol subsection for " + Twine(FuncName));
384410
Asm->EmitInt32(unsigned(ModuleSubstreamKind::Symbols));
411+
Asm->OutStreamer->AddComment("Subsection size");
385412
EmitLabelDiff(*Asm->OutStreamer, SymbolsBegin, SymbolsEnd);
386413
Asm->OutStreamer->EmitLabel(SymbolsBegin);
387414
{
388-
MCSymbol *ProcSegmentBegin = Asm->MMI->getContext().createTempSymbol(),
389-
*ProcSegmentEnd = Asm->MMI->getContext().createTempSymbol();
390-
EmitLabelDiff(*Asm->OutStreamer, ProcSegmentBegin, ProcSegmentEnd, 2);
391-
Asm->OutStreamer->EmitLabel(ProcSegmentBegin);
415+
MCSymbol *ProcRecordBegin = Asm->MMI->getContext().createTempSymbol(),
416+
*ProcRecordEnd = Asm->MMI->getContext().createTempSymbol();
417+
Asm->OutStreamer->AddComment("Record length");
418+
EmitLabelDiff(*Asm->OutStreamer, ProcRecordBegin, ProcRecordEnd, 2);
419+
Asm->OutStreamer->EmitLabel(ProcRecordBegin);
392420

421+
Asm->OutStreamer->AddComment("Record kind: S_GPROC32_ID");
393422
Asm->EmitInt16(unsigned(SymbolRecordKind::S_GPROC32_ID));
394423

395-
// Some bytes of this segment don't seem to be required for basic debugging,
396-
// so just fill them with zeroes.
397-
Asm->OutStreamer->EmitFill(12, 0);
424+
// These fields are filled in by tools like CVPACK which run after the fact.
425+
Asm->OutStreamer->AddComment("PtrParent");
426+
Asm->OutStreamer->EmitIntValue(0, 4);
427+
Asm->OutStreamer->AddComment("PtrEnd");
428+
Asm->OutStreamer->EmitIntValue(0, 4);
429+
Asm->OutStreamer->AddComment("PtrNext");
430+
Asm->OutStreamer->EmitIntValue(0, 4);
398431
// This is the important bit that tells the debugger where the function
399432
// code is located and what's its size:
433+
Asm->OutStreamer->AddComment("Code size");
400434
EmitLabelDiff(*Asm->OutStreamer, Fn, FI.End);
401-
Asm->OutStreamer->EmitFill(12, 0);
435+
Asm->OutStreamer->AddComment("Offset after prologue");
436+
Asm->OutStreamer->EmitIntValue(0, 4);
437+
Asm->OutStreamer->AddComment("Offset before epilogue");
438+
Asm->OutStreamer->EmitIntValue(0, 4);
439+
Asm->OutStreamer->AddComment("Function type index");
440+
Asm->OutStreamer->EmitIntValue(0, 4);
441+
Asm->OutStreamer->AddComment("Function section relative address");
402442
Asm->OutStreamer->EmitCOFFSecRel32(Fn);
443+
Asm->OutStreamer->AddComment("Function section index");
403444
Asm->OutStreamer->EmitCOFFSectionIndex(Fn);
445+
Asm->OutStreamer->AddComment("Flags");
404446
Asm->EmitInt8(0);
405447
// Emit the function display name as a null-terminated string.
406-
Asm->OutStreamer->EmitBytes(FuncName);
407-
Asm->EmitInt8(0);
408-
Asm->OutStreamer->EmitLabel(ProcSegmentEnd);
448+
Asm->OutStreamer->AddComment("Function name");
449+
{
450+
SmallString<32> NullTerminatedString(FuncName);
451+
if (NullTerminatedString.empty() || NullTerminatedString.back() != '\0')
452+
NullTerminatedString.push_back('\0');
453+
Asm->OutStreamer->EmitBytes(NullTerminatedString);
454+
}
455+
Asm->OutStreamer->EmitLabel(ProcRecordEnd);
409456

410457
// Emit inlined call site information. Only emit functions inlined directly
411458
// into the parent function. We'll emit the other sites recursively as part
@@ -417,7 +464,9 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
417464
}
418465

419466
// We're done with this function.
467+
Asm->OutStreamer->AddComment("Record length");
420468
Asm->EmitInt16(0x0002);
469+
Asm->OutStreamer->AddComment("Record kind: S_PROC_ID_END");
421470
Asm->EmitInt16(unsigned(SymbolRecordKind::S_PROC_ID_END));
422471
}
423472
Asm->OutStreamer->EmitLabel(SymbolsEnd);

test/DebugInfo/COFF/asm.ll

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,22 @@
2525
; X86-NEXT: .long 4
2626
; Symbol subsection
2727
; X86-NEXT: .long 241
28-
; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
28+
; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] #
2929
; X86-NEXT: [[F1_START]]:
30-
; X86-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]]
30+
; X86-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]] #
3131
; X86-NEXT: [[PROC_SEGMENT_START]]:
3232
; X86-NEXT: .short 4423
33-
; X86-NEXT: .zero 12
33+
; X86-NEXT: .long 0
34+
; X86-NEXT: .long 0
35+
; X86-NEXT: .long 0
3436
; X86-NEXT: .long [[END_OF_F]]-_f
35-
; X86-NEXT: .zero 12
37+
; X86-NEXT: .long 0
38+
; X86-NEXT: .long 0
39+
; X86-NEXT: .long 0
3640
; X86-NEXT: .secrel32 _f
3741
; X86-NEXT: .secidx _f
3842
; X86-NEXT: .byte 0
39-
; X86-NEXT: .byte 102
40-
; X86-NEXT: .byte 0
43+
; X86-NEXT: .asciz "f"
4144
; X86-NEXT: [[PROC_SEGMENT_END]]:
4245
; X86-NEXT: .short 2
4346
; X86-NEXT: .short 4431
@@ -113,19 +116,22 @@
113116
; X64-NEXT: .long 4
114117
; Symbol subsection
115118
; X64-NEXT: .long 241
116-
; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
119+
; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] #
117120
; X64-NEXT: [[F1_START]]:
118-
; X64-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]]
121+
; X64-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]] #
119122
; X64-NEXT: [[PROC_SEGMENT_START]]:
120123
; X64-NEXT: .short 4423
121-
; X64-NEXT: .zero 12
124+
; X64-NEXT: .long 0
125+
; X64-NEXT: .long 0
126+
; X64-NEXT: .long 0
122127
; X64-NEXT: .long [[END_OF_F]]-f
123-
; X64-NEXT: .zero 12
128+
; X64-NEXT: .long 0
129+
; X64-NEXT: .long 0
130+
; X64-NEXT: .long 0
124131
; X64-NEXT: .secrel32 f
125132
; X64-NEXT: .secidx f
126133
; X64-NEXT: .byte 0
127-
; X64-NEXT: .byte 102
128-
; X64-NEXT: .byte 0
134+
; X64-NEXT: .asciz "f"
129135
; X64-NEXT: [[PROC_SEGMENT_END]]:
130136
; X64-NEXT: .short 2
131137
; X64-NEXT: .short 4431

test/DebugInfo/COFF/inlining.ll

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,30 @@
4141

4242
; ASM: .section .debug$S,"dr"
4343
; ASM: .long 246 # Inlinee lines subsection
44-
; ASM: .long [[inline_end:.*]]-[[inline_beg:.*]]
44+
; ASM: .long [[inline_end:.*]]-[[inline_beg:.*]] #
4545
; ASM: [[inline_beg]]:
4646
; ASM: .long 0
47-
; ASM: .long 4099 # Inlined function bar starts at t.cpp:8
47+
; ASM: # Inlined function bar starts at t.cpp:8
48+
; ASM: .long 4099
4849
; ASM: .long 0
4950
; ASM: .long 8
50-
; ASM: .long 4100 # Inlined function foo starts at t.cpp:2
51+
; ASM: # Inlined function foo starts at t.cpp:2
52+
; ASM: .long 4100
5153
; ASM: .long 0
5254
; ASM: .long 2
5355
; ASM: [[inline_end]]:
5456

5557
; ASM: .long 241 # Symbol subsection for baz
5658
; ASM: .long Ltmp3-Ltmp2
5759
; ASM: .short 4429
58-
; ASM: .asciz
60+
; ASM: .long
61+
; ASM: .long
62+
; ASM: .long
5963
; ASM: .cv_inline_linetable 1 1 8 Lfunc_begin0 Lfunc_end0 contains 2
6064
; ASM: .short 4429
61-
; ASM: .asciz
65+
; ASM: .long
66+
; ASM: .long
67+
; ASM: .long
6268
; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0 Lfunc_end0
6369
; ASM: .short 4430
6470
; ASM: .short 4430

test/DebugInfo/COFF/multifile.ll

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,22 @@
3434
; X86-NEXT: .long 4
3535
; Symbol subsection
3636
; X86-NEXT: .long 241
37-
; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
37+
; X86-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] #
3838
; X86-NEXT: [[F1_START]]:
39-
; X86-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]]
39+
; X86-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]] #
4040
; X86-NEXT: [[PROC_SEGMENT_START]]:
4141
; X86-NEXT: .short 4423
42-
; X86-NEXT: .zero 12
42+
; X86-NEXT: .long 0
43+
; X86-NEXT: .long 0
44+
; X86-NEXT: .long 0
4345
; X86-NEXT: .long [[END_OF_F]]-_f
44-
; X86-NEXT: .zero 12
46+
; X86-NEXT: .long 0
47+
; X86-NEXT: .long 0
48+
; X86-NEXT: .long 0
4549
; X86-NEXT: .secrel32 _f
4650
; X86-NEXT: .secidx _f
4751
; X86-NEXT: .byte 0
48-
; X86-NEXT: .byte 102
49-
; X86-NEXT: .byte 0
52+
; X86-NEXT: .asciz "f"
5053
; X86-NEXT: [[PROC_SEGMENT_END]]:
5154
; X86-NEXT: .short 2
5255
; X86-NEXT: .short 4431
@@ -137,19 +140,22 @@
137140
; X64-NEXT: .long 4
138141
; Symbol subsection
139142
; X64-NEXT: .long 241
140-
; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]]
143+
; X64-NEXT: .long [[F1_END:.*]]-[[F1_START:.*]] #
141144
; X64-NEXT: [[F1_START]]:
142-
; X64-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]]
145+
; X64-NEXT: .short [[PROC_SEGMENT_END:.*]]-[[PROC_SEGMENT_START:.*]] #
143146
; X64-NEXT: [[PROC_SEGMENT_START]]:
144147
; X64-NEXT: .short 4423
145-
; X64-NEXT: .zero 12
148+
; X64-NEXT: .long 0
149+
; X64-NEXT: .long 0
150+
; X64-NEXT: .long 0
146151
; X64-NEXT: .long [[END_OF_F]]-f
147-
; X64-NEXT: .zero 12
152+
; X64-NEXT: .long 0
153+
; X64-NEXT: .long 0
154+
; X64-NEXT: .long 0
148155
; X64-NEXT: .secrel32 f
149156
; X64-NEXT: .secidx f
150157
; X64-NEXT: .byte 0
151-
; X64-NEXT: .byte 102
152-
; X64-NEXT: .byte 0
158+
; X64-NEXT: .asciz "f"
153159
; X64-NEXT: [[PROC_SEGMENT_END]]:
154160
; X64-NEXT: .short 2
155161
; X64-NEXT: .short 4431

0 commit comments

Comments
 (0)