mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	AsmPrinter: Don't emit empty .debug_loc entries
If we don't know how to represent a .debug_loc entry, skip the entry entirely rather than emitting an empty one. Similarly, if a .debug_loc list has no entries, don't create the list. We still want to create the variables, just in an optimized-out form that doesn't have a DW_AT_location. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@240244 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
		| @@ -5,6 +5,7 @@ add_llvm_library(LLVMAsmPrinter | |||||||
|   AsmPrinterDwarf.cpp |   AsmPrinterDwarf.cpp | ||||||
|   AsmPrinterInlineAsm.cpp |   AsmPrinterInlineAsm.cpp | ||||||
|   DbgValueHistoryCalculator.cpp |   DbgValueHistoryCalculator.cpp | ||||||
|  |   DebugLocStream.cpp | ||||||
|   DIE.cpp |   DIE.cpp | ||||||
|   DIEHash.cpp |   DIEHash.cpp | ||||||
|   DwarfAccelTable.cpp |   DwarfAccelTable.cpp | ||||||
|   | |||||||
| @@ -142,7 +142,7 @@ public: | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /// \brief Lower this entry into a DWARF expression. |   /// \brief Lower this entry into a DWARF expression. | ||||||
|   void finalize(const AsmPrinter &AP, DebugLocStream &Locs, |   void finalize(const AsmPrinter &AP, DebugLocStream::ListBuilder &List, | ||||||
|                 const DIBasicType *BT); |                 const DIBasicType *BT); | ||||||
| }; | }; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										46
									
								
								lib/CodeGen/AsmPrinter/DebugLocStream.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								lib/CodeGen/AsmPrinter/DebugLocStream.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | |||||||
|  | //===- DebugLocStream.cpp - DWARF debug_loc stream --------------*- C++ -*-===// | ||||||
|  | // | ||||||
|  | //                     The LLVM Compiler Infrastructure | ||||||
|  | // | ||||||
|  | // This file is distributed under the University of Illinois Open Source | ||||||
|  | // License. See LICENSE.TXT for details. | ||||||
|  | // | ||||||
|  | //===----------------------------------------------------------------------===// | ||||||
|  |  | ||||||
|  | #include "DebugLocStream.h" | ||||||
|  | #include "DwarfDebug.h" | ||||||
|  | #include "llvm/CodeGen/AsmPrinter.h" | ||||||
|  |  | ||||||
|  | using namespace llvm; | ||||||
|  |  | ||||||
|  | bool DebugLocStream::finalizeList(AsmPrinter &Asm) { | ||||||
|  |   if (Lists.back().EntryOffset == Entries.size()) { | ||||||
|  |     // Empty list.  Delete it. | ||||||
|  |     Lists.pop_back(); | ||||||
|  |     return false; | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   // Real list.  Generate a label for it. | ||||||
|  |   Lists.back().Label = Asm.createTempSymbol("debug_loc"); | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void DebugLocStream::finalizeEntry() { | ||||||
|  |   if (Entries.back().ByteOffset != DWARFBytes.size()) | ||||||
|  |     return; | ||||||
|  |  | ||||||
|  |   // The last entry was empty.  Delete it. | ||||||
|  |   Comments.erase(Comments.begin() + Entries.back().CommentOffset, | ||||||
|  |                  Comments.end()); | ||||||
|  |   Entries.pop_back(); | ||||||
|  |  | ||||||
|  |   assert(Lists.back().EntryOffset <= Entries.size() && | ||||||
|  |          "Popped off more entries than are in the list"); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | DebugLocStream::ListBuilder::~ListBuilder() { | ||||||
|  |   if (!Locs.finalizeList(Asm)) | ||||||
|  |     return; | ||||||
|  |   V.initializeDbgValue(&MI); | ||||||
|  |   V.setDebugLocListIndex(ListIndex); | ||||||
|  | } | ||||||
| @@ -15,7 +15,11 @@ | |||||||
| #include "ByteStreamer.h" | #include "ByteStreamer.h" | ||||||
|  |  | ||||||
| namespace llvm { | namespace llvm { | ||||||
|  |  | ||||||
|  | class AsmPrinter; | ||||||
|  | class DbgVariable; | ||||||
| class DwarfCompileUnit; | class DwarfCompileUnit; | ||||||
|  | class MachineInstr; | ||||||
| class MCSymbol; | class MCSymbol; | ||||||
|  |  | ||||||
| /// \brief Byte stream of .debug_loc entries. | /// \brief Byte stream of .debug_loc entries. | ||||||
| @@ -29,10 +33,10 @@ class DebugLocStream { | |||||||
| public: | public: | ||||||
|   struct List { |   struct List { | ||||||
|     DwarfCompileUnit *CU; |     DwarfCompileUnit *CU; | ||||||
|     MCSymbol *Label; |     MCSymbol *Label = nullptr; | ||||||
|     size_t EntryOffset; |     size_t EntryOffset; | ||||||
|     List(DwarfCompileUnit *CU, MCSymbol *Label, size_t EntryOffset) |     List(DwarfCompileUnit *CU, size_t EntryOffset) | ||||||
|         : CU(CU), Label(Label), EntryOffset(EntryOffset) {} |         : CU(CU), EntryOffset(EntryOffset) {} | ||||||
|   }; |   }; | ||||||
|   struct Entry { |   struct Entry { | ||||||
|     const MCSymbol *BeginSym; |     const MCSymbol *BeginSym; | ||||||
| @@ -61,18 +65,30 @@ public: | |||||||
|   const List &getList(size_t LI) const { return Lists[LI]; } |   const List &getList(size_t LI) const { return Lists[LI]; } | ||||||
|   ArrayRef<List> getLists() const { return Lists; } |   ArrayRef<List> getLists() const { return Lists; } | ||||||
|  |  | ||||||
|  |   class ListBuilder; | ||||||
|  |   class EntryBuilder; | ||||||
|  |  | ||||||
|  | private: | ||||||
|   /// \brief Start a new .debug_loc entry list. |   /// \brief Start a new .debug_loc entry list. | ||||||
|   /// |   /// | ||||||
|   /// Start a new .debug_loc entry list.  Return the new list's index so it can |   /// Start a new .debug_loc entry list.  Return the new list's index so it can | ||||||
|   /// be retrieved later via \a getList(). |   /// be retrieved later via \a getList(). | ||||||
|   /// |   /// | ||||||
|   /// Until the next call, \a startEntry() will add entries to this list. |   /// Until the next call, \a startEntry() will add entries to this list. | ||||||
|   size_t startList(DwarfCompileUnit *CU, MCSymbol *Label) { |   size_t startList(DwarfCompileUnit *CU) { | ||||||
|     size_t LI = Lists.size(); |     size_t LI = Lists.size(); | ||||||
|     Lists.emplace_back(CU, Label, Entries.size()); |     Lists.emplace_back(CU, Entries.size()); | ||||||
|     return LI; |     return LI; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /// Finalize a .debug_loc entry list. | ||||||
|  |   /// | ||||||
|  |   /// If there are no entries in this list, delete it outright.  Otherwise, | ||||||
|  |   /// create a label with \a Asm. | ||||||
|  |   /// | ||||||
|  |   /// \return false iff the list is deleted. | ||||||
|  |   bool finalizeList(AsmPrinter &Asm); | ||||||
|  |  | ||||||
|   /// \brief Start a new .debug_loc entry. |   /// \brief Start a new .debug_loc entry. | ||||||
|   /// |   /// | ||||||
|   /// Until the next call, bytes added to the stream will be added to this |   /// Until the next call, bytes added to the stream will be added to this | ||||||
| @@ -81,6 +97,10 @@ public: | |||||||
|     Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size()); |     Entries.emplace_back(BeginSym, EndSym, DWARFBytes.size(), Comments.size()); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   /// Finalize a .debug_loc entry, deleting if it's empty. | ||||||
|  |   void finalizeEntry(); | ||||||
|  |  | ||||||
|  | public: | ||||||
|   BufferByteStreamer getStreamer() { |   BufferByteStreamer getStreamer() { | ||||||
|     return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); |     return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); | ||||||
|   } |   } | ||||||
| @@ -129,5 +149,45 @@ private: | |||||||
|     return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset; |     return Entries[EI + 1].CommentOffset - Entries[EI].CommentOffset; | ||||||
|   } |   } | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | /// Builder for DebugLocStream lists. | ||||||
|  | class DebugLocStream::ListBuilder { | ||||||
|  |   DebugLocStream &Locs; | ||||||
|  |   AsmPrinter &Asm; | ||||||
|  |   DbgVariable &V; | ||||||
|  |   const MachineInstr &MI; | ||||||
|  |   size_t ListIndex; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |   ListBuilder(DebugLocStream &Locs, DwarfCompileUnit &CU, AsmPrinter &Asm, | ||||||
|  |               DbgVariable &V, const MachineInstr &MI) | ||||||
|  |       : Locs(Locs), Asm(Asm), V(V), MI(MI), ListIndex(Locs.startList(&CU)) {} | ||||||
|  |  | ||||||
|  |   /// Finalize the list. | ||||||
|  |   /// | ||||||
|  |   /// If the list is empty, delete it.  Otherwise, finalize it by creating a | ||||||
|  |   /// temp symbol in \a Asm and setting up the \a DbgVariable. | ||||||
|  |   ~ListBuilder(); | ||||||
|  |  | ||||||
|  |   DebugLocStream &getLocs() { return Locs; } | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | /// Builder for DebugLocStream entries. | ||||||
|  | class DebugLocStream::EntryBuilder { | ||||||
|  |   DebugLocStream &Locs; | ||||||
|  |  | ||||||
|  | public: | ||||||
|  |   EntryBuilder(ListBuilder &List, const MCSymbol *Begin, const MCSymbol *End) | ||||||
|  |       : Locs(List.getLocs()) { | ||||||
|  |     Locs.startEntry(Begin, End); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   /// Finalize the entry, deleting it if it's empty. | ||||||
|  |   ~EntryBuilder() { Locs.finalizeEntry(); } | ||||||
|  |  | ||||||
|  |   BufferByteStreamer getStreamer() { return Locs.getStreamer(); } | ||||||
|  | }; | ||||||
|  |  | ||||||
| } // namespace llvm | } // namespace llvm | ||||||
|  |  | ||||||
| #endif | #endif | ||||||
|   | |||||||
| @@ -908,15 +908,15 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, | |||||||
|  |  | ||||||
|     const MachineInstr *MInsn = Ranges.front().first; |     const MachineInstr *MInsn = Ranges.front().first; | ||||||
|     assert(MInsn->isDebugValue() && "History must begin with debug value"); |     assert(MInsn->isDebugValue() && "History must begin with debug value"); | ||||||
|     RegVar->initializeDbgValue(MInsn); |  | ||||||
|  |  | ||||||
|     // Check if the first DBG_VALUE is valid for the rest of the function. |     // Check if the first DBG_VALUE is valid for the rest of the function. | ||||||
|     if (Ranges.size() == 1 && Ranges.front().second == nullptr) |     if (Ranges.size() == 1 && Ranges.front().second == nullptr) { | ||||||
|  |       RegVar->initializeDbgValue(MInsn); | ||||||
|       continue; |       continue; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     // Handle multiple DBG_VALUE instructions describing one variable. |     // Handle multiple DBG_VALUE instructions describing one variable. | ||||||
|     RegVar->setDebugLocListIndex( |     DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn); | ||||||
|         DebugLocs.startList(&TheCU, Asm->createTempSymbol("debug_loc"))); |  | ||||||
|  |  | ||||||
|     // Build the location list for this variable. |     // Build the location list for this variable. | ||||||
|     SmallVector<DebugLocEntry, 8> Entries; |     SmallVector<DebugLocEntry, 8> Entries; | ||||||
| @@ -930,7 +930,7 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, | |||||||
|  |  | ||||||
|     // Finalize the entry by lowering it into a DWARF bytestream. |     // Finalize the entry by lowering it into a DWARF bytestream. | ||||||
|     for (auto &Entry : Entries) |     for (auto &Entry : Entries) | ||||||
|       Entry.finalize(*Asm, DebugLocs, BT); |       Entry.finalize(*Asm, List, BT); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Collect info for variables that were optimized out. |   // Collect info for variables that were optimized out. | ||||||
| @@ -1504,10 +1504,11 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, | |||||||
|   // FIXME: ^ |   // FIXME: ^ | ||||||
| } | } | ||||||
|  |  | ||||||
| void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream &Locs, | void DebugLocEntry::finalize(const AsmPrinter &AP, | ||||||
|  |                              DebugLocStream::ListBuilder &List, | ||||||
|                              const DIBasicType *BT) { |                              const DIBasicType *BT) { | ||||||
|   Locs.startEntry(Begin, End); |   DebugLocStream::EntryBuilder Entry(List, Begin, End); | ||||||
|   BufferByteStreamer Streamer = Locs.getStreamer(); |   BufferByteStreamer Streamer = Entry.getStreamer(); | ||||||
|   const DebugLocEntry::Value &Value = Values[0]; |   const DebugLocEntry::Value &Value = Values[0]; | ||||||
|   if (Value.isBitPiece()) { |   if (Value.isBitPiece()) { | ||||||
|     // Emit all pieces that belong to the same variable and range. |     // Emit all pieces that belong to the same variable and range. | ||||||
|   | |||||||
							
								
								
									
										66
									
								
								test/DebugInfo/X86/debug-loc-empty-entries.ll
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								test/DebugInfo/X86/debug-loc-empty-entries.ll
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | |||||||
|  | ; RUN: llc -mtriple=x86_64-apple-macosx <%s | FileCheck %s | ||||||
|  | ; Test that we don't generate empty .debug_loc entries.  Originally, there were | ||||||
|  | ; two empty .debug_loc entries for 'a' in an otherwise empty .debug_loc list. | ||||||
|  | ; | ||||||
|  | ; CHECK:      .section __DWARF,__debug_loc,regular,debug | ||||||
|  | ; CHECK-NEXT: Lsection_debug_loc: | ||||||
|  | ; CHECK-NEXT: .section __DWARF,__debug_abbrev,regular,debug | ||||||
|  | ; | ||||||
|  | ; Test that the variable stuck around. | ||||||
|  | ; CHECK:      .section __DWARF,__debug_info,regular,debug | ||||||
|  | ; CHECK:      DW_TAG_variable | ||||||
|  | ; CHECK-NOT:  DW_AT_location | ||||||
|  |  | ||||||
|  | ; Generated using clang -cc1 with the following args: | ||||||
|  | ; | ||||||
|  | ;   -triple x86_64-apple-macosx -emit-llvm -gdwarf-4 -O1 | ||||||
|  | ; | ||||||
|  | ; From this testcase: | ||||||
|  | ; | ||||||
|  | ;;   void fn1() { | ||||||
|  | ;;     float a = 1; | ||||||
|  | ;;     for (;;) | ||||||
|  | ;;       a = 0; | ||||||
|  | ;;   } | ||||||
|  |  | ||||||
|  | ; Function Attrs: noreturn nounwind readnone | ||||||
|  | define void @_Z3fn1v() #0 { | ||||||
|  | entry: | ||||||
|  |   tail call void @llvm.dbg.value(metadata float 1.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15 | ||||||
|  |   br label %for.cond, !dbg !16 | ||||||
|  |  | ||||||
|  | for.cond:                                         ; preds = %for.cond, %entry | ||||||
|  |   tail call void @llvm.dbg.value(metadata float 0.000000e+00, i64 0, metadata !9, metadata !14), !dbg !15 | ||||||
|  |   br label %for.cond, !dbg !17 | ||||||
|  | } | ||||||
|  |  | ||||||
|  | ; Function Attrs: nounwind readnone | ||||||
|  | declare void @llvm.dbg.value(metadata, i64, metadata, metadata) #1 | ||||||
|  |  | ||||||
|  | attributes #0 = { noreturn nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" } | ||||||
|  | attributes #1 = { nounwind readnone } | ||||||
|  |  | ||||||
|  | !llvm.dbg.cu = !{!0} | ||||||
|  | !llvm.module.flags = !{!11, !12} | ||||||
|  | !llvm.ident = !{!13} | ||||||
|  |  | ||||||
|  | !0 = !DICompileUnit(language: DW_LANG_C_plus_plus, file: !1, producer: "clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)", isOptimized: true, runtimeVersion: 0, emissionKind: 1, enums: !2, retainedTypes: !2, subprograms: !3, globals: !2, imports: !2) | ||||||
|  | !1 = !DIFile(filename: "<stdin>", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase") | ||||||
|  | !2 = !{} | ||||||
|  | !3 = !{!4} | ||||||
|  | !4 = !DISubprogram(name: "fn1", linkageName: "_Z3fn1v", scope: !5, file: !5, line: 1, type: !6, isLocal: false, isDefinition: true, scopeLine: 1, flags: DIFlagPrototyped, isOptimized: true, function: void ()* @_Z3fn1v, variables: !8) | ||||||
|  | !5 = !DIFile(filename: "t.cpp", directory: "/Users/dexonsmith/data/llvm/bootstrap/play/delta2/testcase") | ||||||
|  | !6 = !DISubroutineType(types: !7) | ||||||
|  | !7 = !{null} | ||||||
|  | !8 = !{!9} | ||||||
|  | !9 = !DILocalVariable(tag: DW_TAG_auto_variable, name: "a", scope: !4, file: !5, line: 2, type: !10) | ||||||
|  | !10 = !DIBasicType(name: "float", size: 32, align: 32, encoding: DW_ATE_float) | ||||||
|  | !11 = !{i32 2, !"Dwarf Version", i32 4} | ||||||
|  | !12 = !{i32 2, !"Debug Info Version", i32 3} | ||||||
|  | !13 = !{!"clang version 3.7.0 (trunk 238517) (llvm/trunk 238524)"} | ||||||
|  | !14 = !DIExpression() | ||||||
|  | !15 = !DILocation(line: 2, scope: !4) | ||||||
|  | !16 = !DILocation(line: 3, scope: !4) | ||||||
|  | !17 = !DILocation(line: 3, scope: !18) | ||||||
|  | !18 = distinct !DILexicalBlock(scope: !19, file: !5, line: 3) | ||||||
|  | !19 = distinct !DILexicalBlock(scope: !4, file: !5, line: 3) | ||||||
		Reference in New Issue
	
	Block a user