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 | ||||
|   AsmPrinterInlineAsm.cpp | ||||
|   DbgValueHistoryCalculator.cpp | ||||
|   DebugLocStream.cpp | ||||
|   DIE.cpp | ||||
|   DIEHash.cpp | ||||
|   DwarfAccelTable.cpp | ||||
|   | ||||
| @@ -142,7 +142,7 @@ public: | ||||
|   } | ||||
|  | ||||
|   /// \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); | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										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" | ||||
|  | ||||
| namespace llvm { | ||||
|  | ||||
| class AsmPrinter; | ||||
| class DbgVariable; | ||||
| class DwarfCompileUnit; | ||||
| class MachineInstr; | ||||
| class MCSymbol; | ||||
|  | ||||
| /// \brief Byte stream of .debug_loc entries. | ||||
| @@ -29,10 +33,10 @@ class DebugLocStream { | ||||
| public: | ||||
|   struct List { | ||||
|     DwarfCompileUnit *CU; | ||||
|     MCSymbol *Label; | ||||
|     MCSymbol *Label = nullptr; | ||||
|     size_t EntryOffset; | ||||
|     List(DwarfCompileUnit *CU, MCSymbol *Label, size_t EntryOffset) | ||||
|         : CU(CU), Label(Label), EntryOffset(EntryOffset) {} | ||||
|     List(DwarfCompileUnit *CU, size_t EntryOffset) | ||||
|         : CU(CU), EntryOffset(EntryOffset) {} | ||||
|   }; | ||||
|   struct Entry { | ||||
|     const MCSymbol *BeginSym; | ||||
| @@ -61,18 +65,30 @@ public: | ||||
|   const List &getList(size_t LI) const { return Lists[LI]; } | ||||
|   ArrayRef<List> getLists() const { return Lists; } | ||||
|  | ||||
|   class ListBuilder; | ||||
|   class EntryBuilder; | ||||
|  | ||||
| private: | ||||
|   /// \brief Start a new .debug_loc entry list. | ||||
|   /// | ||||
|   /// Start a new .debug_loc entry list.  Return the new list's index so it can | ||||
|   /// be retrieved later via \a getList(). | ||||
|   /// | ||||
|   /// 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(); | ||||
|     Lists.emplace_back(CU, Label, Entries.size()); | ||||
|     Lists.emplace_back(CU, Entries.size()); | ||||
|     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. | ||||
|   /// | ||||
|   /// 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()); | ||||
|   } | ||||
|  | ||||
|   /// Finalize a .debug_loc entry, deleting if it's empty. | ||||
|   void finalizeEntry(); | ||||
|  | ||||
| public: | ||||
|   BufferByteStreamer getStreamer() { | ||||
|     return BufferByteStreamer(DWARFBytes, Comments, GenerateComments); | ||||
|   } | ||||
| @@ -129,5 +149,45 @@ private: | ||||
|     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 | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -908,15 +908,15 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, | ||||
|  | ||||
|     const MachineInstr *MInsn = Ranges.front().first; | ||||
|     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. | ||||
|     if (Ranges.size() == 1 && Ranges.front().second == nullptr) | ||||
|     if (Ranges.size() == 1 && Ranges.front().second == nullptr) { | ||||
|       RegVar->initializeDbgValue(MInsn); | ||||
|       continue; | ||||
|     } | ||||
|  | ||||
|     // Handle multiple DBG_VALUE instructions describing one variable. | ||||
|     RegVar->setDebugLocListIndex( | ||||
|         DebugLocs.startList(&TheCU, Asm->createTempSymbol("debug_loc"))); | ||||
|     DebugLocStream::ListBuilder List(DebugLocs, TheCU, *Asm, *RegVar, *MInsn); | ||||
|  | ||||
|     // Build the location list for this variable. | ||||
|     SmallVector<DebugLocEntry, 8> Entries; | ||||
| @@ -930,7 +930,7 @@ void DwarfDebug::collectVariableInfo(DwarfCompileUnit &TheCU, | ||||
|  | ||||
|     // Finalize the entry by lowering it into a DWARF bytestream. | ||||
|     for (auto &Entry : Entries) | ||||
|       Entry.finalize(*Asm, DebugLocs, BT); | ||||
|       Entry.finalize(*Asm, List, BT); | ||||
|   } | ||||
|  | ||||
|   // Collect info for variables that were optimized out. | ||||
| @@ -1504,10 +1504,11 @@ static void emitDebugLocValue(const AsmPrinter &AP, const DIBasicType *BT, | ||||
|   // FIXME: ^ | ||||
| } | ||||
|  | ||||
| void DebugLocEntry::finalize(const AsmPrinter &AP, DebugLocStream &Locs, | ||||
| void DebugLocEntry::finalize(const AsmPrinter &AP, | ||||
|                              DebugLocStream::ListBuilder &List, | ||||
|                              const DIBasicType *BT) { | ||||
|   Locs.startEntry(Begin, End); | ||||
|   BufferByteStreamer Streamer = Locs.getStreamer(); | ||||
|   DebugLocStream::EntryBuilder Entry(List, Begin, End); | ||||
|   BufferByteStreamer Streamer = Entry.getStreamer(); | ||||
|   const DebugLocEntry::Value &Value = Values[0]; | ||||
|   if (Value.isBitPiece()) { | ||||
|     // 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