llvm.org GIT mirror llvm / a868bb3
[codeview] Only emit function ids for inlined functions We aren't referencing any other kind of function currently. Should save a bit on our debug info size. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@263817 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 4 years ago
7 changed file(s) with 126 addition(s) and 72 deletion(s). Raw diff Collapse all Expand all
107107 CodeViewDebug::InlineSite &
108108 CodeViewDebug::getInlineSite(const DILocation *InlinedAt,
109109 const DISubprogram *Inlinee) {
110 auto Insertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
111 InlineSite *Site = &Insertion.first->second;
112 if (Insertion.second) {
110 auto SiteInsertion = CurFn->InlineSites.insert({InlinedAt, InlineSite()});
111 InlineSite *Site = &SiteInsertion.first->second;
112 if (SiteInsertion.second) {
113113 Site->SiteFuncId = NextFuncId++;
114114 Site->Inlinee = Inlinee;
115 InlinedSubprograms.insert(Inlinee);
115 auto InlineeInsertion =
116 SubprogramIndices.insert({Inlinee, InlinedSubprograms.size()});
117 if (InlineeInsertion.second)
118 InlinedSubprograms.push_back(Inlinee);
116119 }
117120 return *Site;
118121 }
213216 // aligned.
214217
215218 // Make a subsection for all the inlined subprograms.
216 emitInlineeLinesSubsection();
219 emitInlineeFuncIdsAndLines();
217220
218221 // Emit per-function debug information.
219222 for (auto &P : FnDebugInfo)
240243 }
241244
242245 void CodeViewDebug::emitTypeInformation() {
246 // Do nothing if we have no debug info or no inlined subprograms. The types
247 // we currently emit exist only to support inlined call site info.
248 NamedMDNode *CU_Nodes =
249 MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
250 if (!CU_Nodes)
251 return;
252 if (InlinedSubprograms.empty())
253 return;
254
243255 // Start the .debug$T section with 0x4.
244256 OS.SwitchSection(Asm->getObjFileLowering().getCOFFDebugTypesSection());
245257 OS.AddComment("Debug section magic");
246258 OS.EmitIntValue(COFF::DEBUG_SECTION_MAGIC, 4);
247259
248 NamedMDNode *CU_Nodes =
249 MMI->getModule()->getNamedMetadata("llvm.dbg.cu");
250 if (!CU_Nodes)
251 return;
252
253260 // This type info currently only holds function ids for use with inline call
254261 // frame info. All functions are assigned a simple 'void ()' type. Emit that
255262 // type here.
256 TypeIndex ArgListIdx = getNextTypeIndex();
263 unsigned ArgListIndex = getNextTypeIndex();
257264 OS.AddComment("Type record length");
258265 OS.EmitIntValue(2 + sizeof(ArgList), 2);
259266 OS.AddComment("Leaf type: LF_ARGLIST");
261268 OS.AddComment("Number of arguments");
262269 OS.EmitIntValue(0, 4);
263270
264 TypeIndex VoidProcIdx = getNextTypeIndex();
271 unsigned VoidFnTyIdx = getNextTypeIndex();
265272 OS.AddComment("Type record length");
266273 OS.EmitIntValue(2 + sizeof(ProcedureType), 2);
267274 OS.AddComment("Leaf type: LF_PROCEDURE");
275282 OS.AddComment("# of parameters");
276283 OS.EmitIntValue(0, 2);
277284 OS.AddComment("Argument list type index");
278 OS.EmitIntValue(ArgListIdx.getIndex(), 4);
279
280 for (MDNode *N : CU_Nodes->operands()) {
281 auto *CUNode = cast(N);
282 for (auto *SP : CUNode->getSubprograms()) {
283 StringRef DisplayName = SP->getDisplayName();
284 OS.AddComment("Type record length");
285 MCSymbol *FuncBegin = MMI->getContext().createTempSymbol(),
286 *FuncEnd = MMI->getContext().createTempSymbol();
287 OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 2);
288 OS.EmitLabel(FuncBegin);
289 OS.AddComment("Leaf type: LF_FUNC_ID");
290 OS.EmitIntValue(LF_FUNC_ID, 2);
291
292 OS.AddComment("Scope type index");
293 OS.EmitIntValue(TypeIndex().getIndex(), 4);
294 OS.AddComment("Function type");
295 OS.EmitIntValue(VoidProcIdx.getIndex(), 4);
296 {
297 OS.AddComment("Function name");
298 emitNullTerminatedSymbolName(OS, DisplayName);
299 }
300 OS.EmitLabel(FuncEnd);
301
302 TypeIndex FuncIdIdx = getNextTypeIndex();
303 SubprogramToFuncId.insert(std::make_pair(SP, FuncIdIdx));
285 OS.EmitIntValue(ArgListIndex, 4);
286
287 // Emit LF_FUNC_ID records for all inlined subprograms to the type stream.
288 // Allocate one type index for each func id.
289 unsigned NextIdx = getNextTypeIndex(InlinedSubprograms.size());
290 assert(NextIdx == FuncIdTypeIndexStart && "func id type indices broken");
291 for (auto *SP : InlinedSubprograms) {
292 StringRef DisplayName = SP->getDisplayName();
293 OS.AddComment("Type record length");
294 MCSymbol *FuncBegin = MMI->getContext().createTempSymbol(),
295 *FuncEnd = MMI->getContext().createTempSymbol();
296 OS.emitAbsoluteSymbolDiff(FuncEnd, FuncBegin, 2);
297 OS.EmitLabel(FuncBegin);
298 OS.AddComment("Leaf type: LF_FUNC_ID");
299 OS.EmitIntValue(LF_FUNC_ID, 2);
300
301 OS.AddComment("Scope type index");
302 OS.EmitIntValue(0, 4);
303 OS.AddComment("Function type");
304 OS.EmitIntValue(VoidFnTyIdx, 4);
305 {
306 OS.AddComment("Function name");
307 emitNullTerminatedSymbolName(OS, DisplayName);
304308 }
305 }
306 }
307
308 void CodeViewDebug::emitInlineeLinesSubsection() {
309 OS.EmitLabel(FuncEnd);
310 }
311 }
312
313 void CodeViewDebug::emitInlineeFuncIdsAndLines() {
309314 if (InlinedSubprograms.empty())
310315 return;
311316
323328 OS.AddComment("Inlinee lines signature");
324329 OS.EmitIntValue(unsigned(InlineeLinesSignature::Normal), 4);
325330
331 unsigned InlineeIndex = FuncIdTypeIndexStart;
326332 for (const DISubprogram *SP : InlinedSubprograms) {
327333 OS.AddBlankLine();
328 TypeIndex TypeId = SubprogramToFuncId[SP];
329334 unsigned FileId = maybeRecordFile(SP->getFile());
330335 OS.AddComment("Inlined function " + SP->getDisplayName() + " starts at " +
331336 SP->getFilename() + Twine(':') + Twine(SP->getLine()));
334339 // 1.
335340 unsigned FileOffset = (FileId - 1) * 8;
336341 OS.AddComment("Type index of inlined function");
337 OS.EmitIntValue(TypeId.getIndex(), 4);
342 OS.EmitIntValue(InlineeIndex, 4);
338343 OS.AddComment("Offset into filechecksum table");
339344 OS.EmitIntValue(FileOffset, 4);
340345 OS.AddComment("Starting line number");
341346 OS.EmitIntValue(SP->getLine(), 4);
347
348 // The next inlined subprogram has the next function id.
349 InlineeIndex++;
342350 }
343351
344352 OS.EmitLabel(InlineEnd);
361369 MCSymbol *InlineBegin = MMI->getContext().createTempSymbol(),
362370 *InlineEnd = MMI->getContext().createTempSymbol();
363371
364 assert(SubprogramToFuncId.count(Site.Inlinee));
365 TypeIndex InlineeIdx = SubprogramToFuncId[Site.Inlinee];
372 assert(SubprogramIndices.count(Site.Inlinee));
373 unsigned InlineeIdx = FuncIdTypeIndexStart + SubprogramIndices[Site.Inlinee];
366374
367375 // SymbolRecord
368376 OS.AddComment("Record length");
376384 OS.AddComment("PtrEnd");
377385 OS.EmitIntValue(0, 4);
378386 OS.AddComment("Inlinee type index");
379 OS.EmitIntValue(InlineeIdx.getIndex(), 4);
387 OS.EmitIntValue(InlineeIdx, 4);
380388
381389 unsigned FileId = maybeRecordFile(Site.Inlinee->getFile());
382390 unsigned StartLineNum = Site.Inlinee->getLine();
9898 };
9999 FunctionInfo *CurFn;
100100
101 /// The next available function index for use with our .cv_* directives. Not
102 /// to be confused with type indices for LF_FUNC_ID records.
101103 unsigned NextFuncId = 0;
104
105 /// The next available type index.
106 unsigned NextTypeIndex = llvm::codeview::TypeIndex::FirstNonSimpleIndex;
107
108 /// Get the next type index and reserve it. Can be used to reserve more than
109 /// one type index.
110 unsigned getNextTypeIndex(unsigned NumRecords = 1) {
111 unsigned Result = NextTypeIndex;
112 NextTypeIndex += NumRecords;
113 return Result;
114 }
102115
103116 InlineSite &getInlineSite(const DILocation *InlinedAt,
104117 const DISubprogram *Inlinee);
114127 /// Map from DIFile to .cv_file id.
115128 DenseMap FileIdMap;
116129
117 SmallSetVector InlinedSubprograms;
130 /// Map from subprogram to index in InlinedSubprograms.
131 DenseMap SubprogramIndices;
118132
119 DenseMap SubprogramToFuncId;
133 /// All inlined subprograms in the order they should be emitted.
134 SmallVector InlinedSubprograms;
120135
121 unsigned TypeCount = 0;
122
123 /// Gets the next type index and increments the count of types streamed so
124 /// far.
125 codeview::TypeIndex getNextTypeIndex() {
126 return codeview::TypeIndex(codeview::TypeIndex::FirstNonSimpleIndex + TypeCount++);
127 }
136 /// The first type index that refers to an LF_FUNC_ID record. We have one
137 /// record per inlined subprogram.
138 /// FIXME: Keep in sync with emitTypeInformation until we buffer type records
139 /// on the side as we go. Once we buffer type records, we can allocate type
140 /// indices on demand without interleaving our assembly output.
141 unsigned FuncIdTypeIndexStart = NextTypeIndex + 2;
128142
129143 typedef std::map FileToFilepathMapTy;
130144 FileToFilepathMapTy FileToFilepathMap;
143157
144158 void emitTypeInformation();
145159
146 void emitInlineeLinesSubsection();
160 void emitInlineeFuncIdsAndLines();
147161
148162 void emitDebugInfoForFunction(const Function *GV, FunctionInfo &FI);
149163
2323 ; OBJ: InlineSite {
2424 ; OBJ: PtrParent: 0x0
2525 ; OBJ: PtrEnd: 0x0
26 ; OBJ: Inlinee: file_change (0x1003)
26 ; OBJ: Inlinee: file_change (0x1002)
2727 ; OBJ: BinaryAnnotations [
2828 ; OBJ: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x6, LineOffset: 1}
2929 ; OBJ: ChangeFile: D:\src\llvm\build\t.inc (0x8)
1919 ; OBJ: SubSectionType: Symbols (0xF1)
2020 ; OBJ: ProcStart {
2121 ; OBJ: InlineSite {
22 ; OBJ: Inlinee: h (0x1003)
22 ; OBJ: Inlinee: h (0x1004)
2323 ; OBJ: }
2424 ; OBJ: InlineSite {
25 ; OBJ: Inlinee: g (0x1004)
25 ; OBJ: Inlinee: g (0x1003)
2626 ; OBJ: }
2727 ; OBJ: InlineSite {
28 ; OBJ: Inlinee: f (0x1005)
28 ; OBJ: Inlinee: f (0x1002)
2929 ; OBJ: }
3030 ; OBJ: InlineSiteEnd {
3131 ; OBJ: }
4444 ; ASM: [[inline_beg]]:
4545 ; ASM: .long 0
4646 ; ASM: # Inlined function bar starts at t.cpp:8
47 ; ASM: .long 4098 # Type index of inlined function
48 ; ASM: .long 0 # Offset into filechecksum table
49 ; ASM: .long 8 # Starting line number
50 ; ASM: # Inlined function foo starts at t.cpp:2
4751 ; ASM: .long 4099
48 ; ASM: .long 0
49 ; ASM: .long 8
50 ; ASM: # Inlined function foo starts at t.cpp:2
51 ; ASM: .long 4100
5252 ; ASM: .long 0
5353 ; ASM: .long 2
5454 ; ASM: [[inline_end]]:
6767 ; ASM: .cv_inline_linetable 2 1 2 Lfunc_begin0 Lfunc_end0
6868 ; ASM: .short 4430
6969 ; ASM: .short 4430
70
71 ; We should only the LF_FUNC_ID records that we needed to reference.
72 ; OBJ: CodeViewTypes [
73 ; OBJ: Section: .debug$T (4)
74 ; OBJ: ArgList {
75 ; OBJ: TypeLeafKind: LF_ARGLIST (0x1201)
76 ; OBJ: TypeIndex: 0x1000
77 ; OBJ: NumArgs: 0
78 ; OBJ: }
79 ; OBJ: ProcedureType {
80 ; OBJ: TypeLeafKind: LF_PROCEDURE (0x1008)
81 ; OBJ: TypeIndex: 0x1001
82 ; OBJ: ReturnType: void (0x3)
83 ; OBJ: NumParameters: 0
84 ; OBJ: ArgListType: () (0x1000)
85 ; OBJ: }
86 ; OBJ: FuncId {
87 ; OBJ: TypeLeafKind: LF_FUNC_ID (0x1601)
88 ; OBJ: TypeIndex: 0x1002
89 ; OBJ: ParentScope: 0x0
90 ; OBJ: FunctionType: void () (0x1001)
91 ; OBJ: Name: bar
92 ; OBJ: }
93 ; OBJ: FuncId {
94 ; OBJ: TypeLeafKind: LF_FUNC_ID (0x1601)
95 ; OBJ: TypeIndex: 0x1003
96 ; OBJ: ParentScope: 0x0
97 ; OBJ: FunctionType: void () (0x1001)
98 ; OBJ: Name: foo
99 ; OBJ: }
100 ; OBJ-NOT: TypeLeafKind: LF_FUNC_ID
101 ; OBJ: ]
70102
71103 ; OBJ: Subsection [
72104 ; OBJ: SubSectionType: InlineeLines (0xF6)
73105 ; OBJ: SubSectionSize: 0x1C
74106 ; OBJ: InlineeSourceLine {
75 ; OBJ: Inlinee: bar (0x1003)
107 ; OBJ: Inlinee: bar (0x1002)
76108 ; OBJ: FileID: D:\src\llvm\build\t.cpp (0x0)
77109 ; OBJ: SourceLineNum: 8
78110 ; OBJ: }
79111 ; OBJ: InlineeSourceLine {
80 ; OBJ: Inlinee: foo (0x1004)
112 ; OBJ: Inlinee: foo (0x1003)
81113 ; OBJ: FileID: D:\src\llvm\build\t.cpp (0x0)
82114 ; OBJ: SourceLineNum: 2
83115 ; OBJ: }
102134 ; OBJ: InlineSite {
103135 ; OBJ: PtrParent: 0x0
104136 ; OBJ: PtrEnd: 0x0
105 ; OBJ: Inlinee: bar (0x1003)
137 ; OBJ: Inlinee: bar (0x1002)
106138 ; OBJ: BinaryAnnotations [
107139 ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0x8, LineOffset: 1}
108140 ; OBJ-NEXT: ChangeLineOffset: -6
118150 ; OBJ: InlineSite {
119151 ; OBJ: PtrParent: 0x0
120152 ; OBJ: PtrEnd: 0x0
121 ; OBJ: Inlinee: foo (0x1004)
153 ; OBJ: Inlinee: foo (0x1003)
122154 ; OBJ: BinaryAnnotations [
123155 ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xF, LineOffset: 1}
124156 ; OBJ-NEXT: ChangeCodeOffsetAndLineOffset: {CodeOffset: 0xA, LineOffset: 1}
161161 ; OBJ: InlineSite {
162162 ; OBJ: PtrParent: 0x0
163163 ; OBJ: PtrEnd: 0x0
164 ; OBJ: Inlinee: will_be_inlined (0x1003)
164 ; OBJ: Inlinee: will_be_inlined (0x1002)
165165 ; OBJ: BinaryAnnotations [
166166 ; OBJ: ChangeLineOffset: 1
167167 ; OBJ: ChangeCodeOffset: 0x14
191191 ; OBJ: InlineSite {
192192 ; OBJ: PtrParent: 0x0
193193 ; OBJ: PtrEnd: 0x0
194 ; OBJ: Inlinee: will_be_inlined (0x1003)
194 ; OBJ: Inlinee: will_be_inlined (0x1002)
195195 ; OBJ: BinaryAnnotations [
196196 ; OBJ: ChangeLineOffset: 1
197197 ; OBJ: ChangeCodeOffset: 0x35
151151 ; OBJ: InlineSite {
152152 ; OBJ: PtrParent: 0x0
153153 ; OBJ: PtrEnd: 0x0
154 ; OBJ: Inlinee: inlineinc (0x1003)
154 ; OBJ: Inlinee: inlineinc (0x1002)
155155 ; OBJ: }
156156 ; OBJ: Local {
157157 ; OBJ: Type: int (0x74)