diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index c4abef1a9b4..c110ffd3a77 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -537,8 +537,13 @@ namespace llvm { DwarfCompileUnitID = CUIndex; } - void setMCLineTableCompilationDir(unsigned CUID, StringRef CompilationDir) { - getMCDwarfLineTable(CUID).setCompilationDir(CompilationDir); + /// Specifies the "root" file and directory of the compilation unit. + /// These are "file 0" and "directory 0" in DWARF v5. + void setMCLineTableRootFile(unsigned CUID, StringRef CompilationDir, + StringRef Filename, MD5::MD5Result *Checksum, + Optional Source) { + getMCDwarfLineTable(CUID).setRootFile(CompilationDir, Filename, Checksum, + Source); } /// Saves the information from the currently parsed dwarf .loc directive diff --git a/include/llvm/MC/MCDwarf.h b/include/llvm/MC/MCDwarf.h index 999e3235936..5cdb176e8e2 100644 --- a/include/llvm/MC/MCDwarf.h +++ b/include/llvm/MC/MCDwarf.h @@ -214,6 +214,7 @@ struct MCDwarfLineTableHeader { SmallVector MCDwarfFiles; StringMap SourceIdMap; StringRef CompilationDir; + MCDwarfFile RootFile; bool HasMD5 = false; bool HasSource = false; @@ -241,8 +242,17 @@ class MCDwarfDwoLineTable { MCDwarfLineTableHeader Header; public: - void setCompilationDir(StringRef CompilationDir) { - Header.CompilationDir = CompilationDir; + void maybeSetRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional Source) { + if (!Header.RootFile.Name.empty()) + return; + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.HasMD5 = (Checksum != nullptr); + Header.HasSource = Source.hasValue(); } unsigned getFile(StringRef Directory, StringRef FileName, @@ -277,6 +287,17 @@ public: FileNumber)); } + void setRootFile(StringRef Directory, StringRef FileName, + MD5::MD5Result *Checksum, Optional Source) { + Header.CompilationDir = Directory; + Header.RootFile.Name = FileName; + Header.RootFile.DirIndex = 0; + Header.RootFile.Checksum = Checksum; + Header.RootFile.Source = Source; + Header.HasMD5 = (Checksum != nullptr); + Header.HasSource = Source.hasValue(); + } + MCSymbol *getLabel() const { return Header.Label; } @@ -285,10 +306,6 @@ public: Header.Label = Label; } - void setCompilationDir(StringRef CompilationDir) { - Header.CompilationDir = CompilationDir; - } - const SmallVectorImpl &getMCDwarfDirs() const { return Header.MCDwarfDirs; } diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 288bcbabc21..582a836023b 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -775,6 +775,12 @@ public: MD5::MD5Result *Checksum = nullptr, Optional Source = None, unsigned CUID = 0); + /// Specify the "root" file of the compilation, using the ".file 0" extension. + virtual void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum, + Optional Source, + unsigned CUID = 0); + /// \brief This implements the DWARF2 '.loc fileno lineno ...' assembler /// directive. virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, diff --git a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 024472db87c..0398d0f4c97 100644 --- a/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -499,8 +499,9 @@ DwarfDebug::getOrCreateDwarfCompileUnit(const DICompileUnit *DIUnit) { // explicitly describe the directory of all files, never relying on the // compilation directory. if (!Asm->OutStreamer->hasRawTextSupport() || SingleCU) - Asm->OutStreamer->getContext().setMCLineTableCompilationDir( - NewCU.getUniqueID(), CompilationDir); + Asm->OutStreamer->emitDwarfFile0Directive( + CompilationDir, FN, NewCU.getMD5AsBytes(DIUnit->getFile()), + DIUnit->getSource(), NewCU.getUniqueID()); StringRef Producer = DIUnit->getProducer(); StringRef Flags = DIUnit->getFlags(); @@ -2148,8 +2149,10 @@ void DwarfDebug::emitDebugStrDWO() { MCDwarfDwoLineTable *DwarfDebug::getDwoLineTable(const DwarfCompileUnit &CU) { if (!useSplitDwarf()) return nullptr; - if (SingleCU) - SplitTypeUnitFileTable.setCompilationDir(CU.getCUNode()->getDirectory()); + const DICompileUnit *DIUnit = CU.getCUNode(); + SplitTypeUnitFileTable.maybeSetRootFile( + DIUnit->getDirectory(), DIUnit->getFilename(), + CU.getMD5AsBytes(DIUnit->getFile()), DIUnit->getSource()); return &SplitTypeUnitFileTable; } diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp index 811112a0430..4bbfb4704e6 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.cpp +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.cpp @@ -282,8 +282,10 @@ void DwarfUnit::addSectionOffset(DIE &Die, dwarf::Attribute Attribute, addUInt(Die, Attribute, dwarf::DW_FORM_data4, Integer); } -MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) { +MD5::MD5Result *DwarfUnit::getMD5AsBytes(const DIFile *File) const { assert(File); + if (DD->getDwarfVersion() < 5) + return nullptr; Optional> Checksum = File->getChecksum(); if (!Checksum || Checksum->Kind != DIFile::CSK_MD5) return nullptr; diff --git a/lib/CodeGen/AsmPrinter/DwarfUnit.h b/lib/CodeGen/AsmPrinter/DwarfUnit.h index 328e3549e05..c1d46173567 100644 --- a/lib/CodeGen/AsmPrinter/DwarfUnit.h +++ b/lib/CodeGen/AsmPrinter/DwarfUnit.h @@ -306,6 +306,10 @@ public: const MCSymbol *Label, const MCSymbol *Sec); + /// If the \p File has an MD5 checksum, return it as an MD5Result + /// allocated in the MCContext. + MD5::MD5Result *getMD5AsBytes(const DIFile *File) const; + protected: ~DwarfUnit(); @@ -316,10 +320,6 @@ protected: /// create a new ID and insert it in the line table. virtual unsigned getOrCreateSourceID(const DIFile *File) = 0; - /// If the \p File has an MD5 checksum, return it as an MD5Result - /// allocated in the MCContext. - MD5::MD5Result *getMD5AsBytes(const DIFile *File); - /// Look in the DwarfDebug map for the MDNode that corresponds to the /// reference. template T *resolve(TypedDINodeRef Ref) const { diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index f30dd3eadbd..c1d74a0e94a 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -219,6 +219,10 @@ public: MD5::MD5Result *Checksum = 0, Optional Source = None, unsigned CUID = 0) override; + void emitDwarfFile0Directive(StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum, + Optional Source, + unsigned CUID = 0) override; void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, @@ -1077,21 +1081,12 @@ void MCAsmStreamer::EmitFileDirective(StringRef Filename) { EmitEOL(); } -Expected MCAsmStreamer::tryEmitDwarfFileDirective( - unsigned FileNo, StringRef Directory, StringRef Filename, - MD5::MD5Result *Checksum, Optional Source, unsigned CUID) { - assert(CUID == 0); - - MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); - unsigned NumFiles = Table.getMCDwarfFiles().size(); - Expected FileNoOrErr = - Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo); - if (!FileNoOrErr) - return FileNoOrErr.takeError(); - FileNo = FileNoOrErr.get(); - if (NumFiles == Table.getMCDwarfFiles().size()) - return FileNo; - +static void printDwarfFileDirective(unsigned FileNo, StringRef Directory, + StringRef Filename, + MD5::MD5Result *Checksum, + Optional Source, + bool UseDwarfDirectory, + raw_svector_ostream &OS) { SmallString<128> FullPathName; if (!UseDwarfDirectory && !Directory.empty()) { @@ -1105,31 +1100,71 @@ Expected MCAsmStreamer::tryEmitDwarfFileDirective( } } - SmallString<128> Str; - raw_svector_ostream OS1(Str); - OS1 << "\t.file\t" << FileNo << ' '; + OS << "\t.file\t" << FileNo << ' '; if (!Directory.empty()) { - PrintQuotedString(Directory, OS1); - OS1 << ' '; + PrintQuotedString(Directory, OS); + OS << ' '; } - PrintQuotedString(Filename, OS1); + PrintQuotedString(Filename, OS); if (Checksum) { - OS1 << " md5 "; - PrintQuotedString(Checksum->digest(), OS1); + OS << " md5 "; + PrintQuotedString(Checksum->digest(), OS); } if (Source) { - OS1 << " source "; - PrintQuotedString(*Source, OS1); + OS << " source "; + PrintQuotedString(*Source, OS); } - if (MCTargetStreamer *TS = getTargetStreamer()) { +} + +Expected MCAsmStreamer::tryEmitDwarfFileDirective( + unsigned FileNo, StringRef Directory, StringRef Filename, + MD5::MD5Result *Checksum, Optional Source, unsigned CUID) { + assert(CUID == 0 && "multiple CUs not supported by MCAsmStreamer"); + + MCDwarfLineTable &Table = getContext().getMCDwarfLineTable(CUID); + unsigned NumFiles = Table.getMCDwarfFiles().size(); + Expected FileNoOrErr = + Table.tryGetFile(Directory, Filename, Checksum, Source, FileNo); + if (!FileNoOrErr) + return FileNoOrErr.takeError(); + FileNo = FileNoOrErr.get(); + if (NumFiles == Table.getMCDwarfFiles().size()) + return FileNo; + + SmallString<128> Str; + raw_svector_ostream OS1(Str); + printDwarfFileDirective(FileNo, Directory, Filename, Checksum, Source, + UseDwarfDirectory, OS1); + + if (MCTargetStreamer *TS = getTargetStreamer()) TS->emitDwarfFileDirective(OS1.str()); - } else { + else EmitRawText(OS1.str()); - } return FileNo; } +void MCAsmStreamer::emitDwarfFile0Directive(StringRef Directory, + StringRef Filename, + MD5::MD5Result *Checksum, + Optional Source, + unsigned CUID) { + assert(CUID == 0); + // .file 0 is new for DWARF v5. + if (getContext().getDwarfVersion() < 5) + return; + + SmallString<128> Str; + raw_svector_ostream OS1(Str); + printDwarfFileDirective(0, Directory, Filename, Checksum, Source, + UseDwarfDirectory, OS1); + + if (MCTargetStreamer *TS = getTargetStreamer()) + TS->emitDwarfFileDirective(OS1.str()); + else + EmitRawText(OS1.str()); +} + void MCAsmStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index 2da69fe1e4e..0e0ea965d14 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -349,6 +349,34 @@ void MCDwarfLineTableHeader::emitV2FileDirTables(MCStreamer *MCOS) const { MCOS->EmitIntValue(0, 1); // Terminate the file list. } +static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile, + bool HasMD5, bool HasSource, + Optional &LineStr) { + assert(!DwarfFile.Name.empty()); + if (LineStr) + LineStr->emitRef(MCOS, DwarfFile.Name); + else { + MCOS->EmitBytes(DwarfFile.Name); // FileName and... + MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + } + MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number. + if (HasMD5) { + MD5::MD5Result *Cksum = DwarfFile.Checksum; + MCOS->EmitBinaryData( + StringRef(reinterpret_cast(Cksum->Bytes.data()), + Cksum->Bytes.size())); + } + if (HasSource) { + if (LineStr) + LineStr->emitRef(MCOS, DwarfFile.Source.getValueOr(StringRef())); + else { + MCOS->EmitBytes( + DwarfFile.Source.getValueOr(StringRef())); // Source and... + MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. + } + } +} + void MCDwarfLineTableHeader::emitV5FileDirTables( MCStreamer *MCOS, Optional &LineStr) const { // The directory format, which is just a list of the directory paths. In a @@ -397,33 +425,12 @@ void MCDwarfLineTableHeader::emitV5FileDirTables( MCOS->EmitULEB128IntValue(LineStr ? dwarf::DW_FORM_line_strp : dwarf::DW_FORM_string); } - // Then the list of file names. These start at 1. - MCOS->EmitULEB128IntValue(MCDwarfFiles.size() - 1); - for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) { - assert(!MCDwarfFiles[i].Name.empty()); - if (LineStr) - LineStr->emitRef(MCOS, MCDwarfFiles[i].Name); - else { - MCOS->EmitBytes(MCDwarfFiles[i].Name); // FileName and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - MCOS->EmitULEB128IntValue(MCDwarfFiles[i].DirIndex); // Directory number. - if (HasMD5) { - MD5::MD5Result *Cksum = MCDwarfFiles[i].Checksum; - MCOS->EmitBinaryData( - StringRef(reinterpret_cast(Cksum->Bytes.data()), - Cksum->Bytes.size())); - } - if (HasSource) { - if (LineStr) - LineStr->emitRef(MCOS, MCDwarfFiles[i].Source.getValueOr(StringRef())); - else { - MCOS->EmitBytes( - MCDwarfFiles[i].Source.getValueOr(StringRef())); // Source and... - MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator. - } - } - } + // Then the counted list of files. The root file is file #0, then emit the + // files as provide by .file directives. + MCOS->EmitULEB128IntValue(MCDwarfFiles.size()); + emitOneV5FileEntry(MCOS, RootFile, HasMD5, HasSource, LineStr); + for (unsigned i = 1; i < MCDwarfFiles.size(); ++i) + emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasMD5, HasSource, LineStr); } std::pair diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index 3042f9964ff..8de6579fe3f 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -3276,8 +3276,8 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { FileNumber = getTok().getIntVal(); Lex(); - if (FileNumber < 1) - return TokError("file number less than one"); + if (FileNumber < 0) + return TokError("negative file number"); } std::string Path = getTok().getString(); @@ -3356,11 +3356,15 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { memcpy(SourceBuf, SourceString.data(), SourceString.size()); Source = StringRef(SourceBuf, SourceString.size()); } - Expected FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( - FileNumber, Directory, Filename, CKMem, Source); - if (!FileNumOrErr) - return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); - FileNumber = FileNumOrErr.get(); + if (FileNumber == 0) + getStreamer().emitDwarfFile0Directive(Directory, Filename, CKMem, Source); + else { + Expected FileNumOrErr = getStreamer().tryEmitDwarfFileDirective( + FileNumber, Directory, Filename, CKMem, Source); + if (!FileNumOrErr) + return Error(DirectiveLoc, toString(FileNumOrErr.takeError())); + FileNumber = FileNumOrErr.get(); + } } return false; diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 7d847c67605..776569894a5 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -199,6 +199,15 @@ MCStreamer::tryEmitDwarfFileDirective(unsigned FileNo, StringRef Directory, Source, CUID); } +void MCStreamer::emitDwarfFile0Directive(StringRef Directory, + StringRef Filename, + MD5::MD5Result *Checksum, + Optional Source, + unsigned CUID) { + getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum, + Source); +} + void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, diff --git a/test/CodeGen/Generic/dwarf-md5.ll b/test/CodeGen/Generic/dwarf-md5.ll index b9977200de1..0f23b90cc85 100644 --- a/test/CodeGen/Generic/dwarf-md5.ll +++ b/test/CodeGen/Generic/dwarf-md5.ll @@ -5,31 +5,33 @@ ; XFAIL: darwin ; REQUIRES: object-emission -; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM -; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM +; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-4 +; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-5 ; RUN: %llc_dwarf -dwarf-version 4 -filetype=obj -o %t4.o %s -; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefix=OBJ-4 +; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefix=OBJ ; RUN: %llc_dwarf -dwarf-version 5 -filetype=obj -o %t5.o %s -; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefix=OBJ-5 +; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefixes=OBJ,OBJ-5 -; FIXME: Need to convey the MD5 for the primary source file. -; ASM: .file 1 ".{{/|\\\\}}t1.h" md5 "11111111111111111111111111111111" -; ASM: .file 2 ".{{/|\\\\}}t2.h" md5 "22222222222222222222222222222222" - -; OBJ-4: file_names[ 1]: -; OBJ-4-NEXT: name: "t1.h" -; OBJ-4-NEXT: dir_index: 1 -; OBJ-4: file_names[ 2]: -; OBJ-4-NEXT: name: "t2.h" -; OBJ-4-NEXT: dir_index: 1 +; ASM-4-NOT: .file 0 +; ASM-5: .file 0 "/scratch{{[/\\]}}t.c" md5 "00000000000000000000000000000000" +; ASM: .file 1 "/scratch{{[/\\]}}t1.h" +; ASM-4-NOT: md5 +; ASM-5-SAME: md5 "11111111111111111111111111111111" +; ASM: .file 2 "/scratch{{[/\\]}}t2.h" +; ASM-4-NOT: md5 +; ASM-5-SAME: md5 "22222222222222222222222222222222" ; OBJ-5: file_names[ 0]: -; OBJ-5-NEXT: name: "t1.h" -; OBJ-5-NEXT: dir_index: 1 +; OBJ-5-NEXT: name: "t.c" +; OBJ-5-NEXT: dir_index: 0 +; OBJ-5-NEXT: md5_checksum: 00000000000000000000000000000000 +; OBJ: file_names[ 1]: +; OBJ-NEXT: name: "t1.h" +; OBJ-NEXT: dir_index: 0 ; OBJ-5-NEXT: md5_checksum: 11111111111111111111111111111111 -; OBJ-5: file_names[ 1]: -; OBJ-5-NEXT: name: "t2.h" -; OBJ-5-NEXT: dir_index: 1 +; OBJ: file_names[ 2]: +; OBJ-NEXT: name: "t2.h" +; OBJ-NEXT: dir_index: 0 ; OBJ-5-NEXT: md5_checksum: 22222222222222222222222222222222 ; ModuleID = 't.c' @@ -45,14 +47,14 @@ source_filename = "t.c" !0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression()) !1 = distinct !DIGlobalVariable(name: "t1", scope: !2, file: !10, line: 1, type: !9, isLocal: false, isDefinition: true) !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3, producer: "clang version 7.0.0 (trunk 322159)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, globals: !5) -!3 = !DIFile(filename: "t.c", directory: "/home/probinson/projects/scratch", checksumkind: CSK_MD5, checksum: "00000000000000000000000000000000") +!3 = !DIFile(filename: "t.c", directory: "/scratch", checksumkind: CSK_MD5, checksum: "00000000000000000000000000000000") !4 = !{} !5 = !{!0, !6} !6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) !7 = distinct !DIGlobalVariable(name: "t2", scope: !2, file: !8, line: 1, type: !9, isLocal: false, isDefinition: true) -!8 = !DIFile(filename: "./t2.h", directory: "/home/probinson/projects/scratch", checksumkind: CSK_MD5, checksum: "22222222222222222222222222222222") +!8 = !DIFile(filename: "t2.h", directory: "/scratch", checksumkind: CSK_MD5, checksum: "22222222222222222222222222222222") !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!10 = !DIFile(filename: "./t1.h", directory: "/home/probinson/projects/scratch", checksumkind: CSK_MD5, checksum: "11111111111111111111111111111111") +!10 = !DIFile(filename: "t1.h", directory: "/scratch", checksumkind: CSK_MD5, checksum: "11111111111111111111111111111111") !11 = !{i32 2, !"Dwarf Version", i32 4} !12 = !{i32 2, !"Debug Info Version", i32 3} !13 = !{i32 1, !"wchar_size", i32 4} diff --git a/test/CodeGen/Generic/dwarf-source.ll b/test/CodeGen/Generic/dwarf-source.ll index 9c34fc5285b..3f772d32ad1 100644 --- a/test/CodeGen/Generic/dwarf-source.ll +++ b/test/CodeGen/Generic/dwarf-source.ll @@ -6,32 +6,29 @@ ; REQUIRES: object-emission ; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM -; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM +; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefixes=ASM,ASM-5 ; RUN: %llc_dwarf -dwarf-version 4 -filetype=obj -o %t4.o %s -; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefix=OBJ-4 +; RUN: llvm-dwarfdump -debug-line %t4.o | FileCheck %s --check-prefixes=OBJ,OBJ-4 ; RUN: %llc_dwarf -dwarf-version 5 -filetype=obj -o %t5.o %s -; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefix=OBJ-5 +; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefixes=OBJ,OBJ-5 -; FIXME: Need to convey the source for the primary source file. -; ASM: .file 1 ".{{/|\\\\}}t1.h" source "11111111111111111111111111111111" -; ASM: .file 2 ".{{/|\\\\}}t2.h" source "22222222222222222222222222222222" - -; OBJ-4: file_names[ 1]: -; OBJ-4-NEXT: name: "t1.h" -; OBJ-4-NEXT: dir_index: 1 -; OBJ-4-NOT: 11111111111111111111111111111111 -; OBJ-4: file_names[ 2]: -; OBJ-4-NEXT: name: "t2.h" -; OBJ-4-NEXT: dir_index: 1 -; OBJ-4-NOT: 22222222222222222222222222222222 +; ASM-5: .file 0 "/test{{[/\\]}}t.c" source "00000000000000000000000000000000" +; ASM: .file 1 "/test{{[/\\]}}t1.h" source "11111111111111111111111111111111" +; ASM: .file 2 "/test{{[/\\]}}t2.h" source "22222222222222222222222222222222" ; OBJ-5: file_names[ 0]: -; OBJ-5-NEXT: name: "t1.h" -; OBJ-5-NEXT: dir_index: 1 +; OBJ-5-NEXT: name: "t.c" +; OBJ-5-NEXT: dir_index: 0 +; OBJ-5-NEXT: source: "00000000000000000000000000000000" +; OBJ: file_names[ 1]: +; OBJ-NEXT: name: "t1.h" +; OBJ-NEXT: dir_index: 0 +; OBJ-4-NOT: 11111111111111111111111111111111 ; OBJ-5-NEXT: source: "11111111111111111111111111111111" -; OBJ-5: file_names[ 1]: -; OBJ-5-NEXT: name: "t2.h" -; OBJ-5-NEXT: dir_index: 1 +; OBJ: file_names[ 2]: +; OBJ-NEXT: name: "t2.h" +; OBJ-NEXT: dir_index: 0 +; OBJ-4-NOT: 22222222222222222222222222222222 ; OBJ-5-NEXT: source: "22222222222222222222222222222222" ; ModuleID = 't.c' @@ -52,9 +49,9 @@ source_filename = "t.c" !5 = !{!0, !6} !6 = !DIGlobalVariableExpression(var: !7, expr: !DIExpression()) !7 = distinct !DIGlobalVariable(name: "t2", scope: !2, file: !8, line: 1, type: !9, isLocal: false, isDefinition: true) -!8 = !DIFile(filename: "./t2.h", directory: "/test", source: "22222222222222222222222222222222") +!8 = !DIFile(filename: "t2.h", directory: "/test", source: "22222222222222222222222222222222") !9 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) -!10 = !DIFile(filename: "./t1.h", directory: "/test", source: "11111111111111111111111111111111") +!10 = !DIFile(filename: "t1.h", directory: "/test", source: "11111111111111111111111111111111") !11 = !{i32 2, !"Dwarf Version", i32 4} !12 = !{i32 2, !"Debug Info Version", i32 3} !13 = !{i32 1, !"wchar_size", i32 4} diff --git a/test/DebugInfo/X86/dbg-file-name.ll b/test/DebugInfo/X86/dbg-file-name.ll index 251952df191..633b9c069c5 100644 --- a/test/DebugInfo/X86/dbg-file-name.ll +++ b/test/DebugInfo/X86/dbg-file-name.ll @@ -2,7 +2,7 @@ ; Verify that the file name is relative to the directory. ; rdar://problem/8884898 -; CHECK: file 1 "simple.c" +; CHECK: file 1 "/Users/manav/one/two" "simple.c" declare i32 @printf(i8*, ...) nounwind diff --git a/test/DebugInfo/X86/inline-asm-locs.ll b/test/DebugInfo/X86/inline-asm-locs.ll index 632aa0be623..5412c7f4133 100644 --- a/test/DebugInfo/X86/inline-asm-locs.ll +++ b/test/DebugInfo/X86/inline-asm-locs.ll @@ -22,7 +22,7 @@ ; CHECK: .file 2 "B.asm" ; CHECK: .loc 1 111 ; CHECK: .loc 2 222 -; CHECK: .file 3 "test.c" +; CHECK: .file 3 "{{.*[/\\]}}test.c" ; CHECK: .loc 3 14 0 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" diff --git a/test/MC/ARM/dwarf-asm-multiple-sections.s b/test/MC/ARM/dwarf-asm-multiple-sections.s index 4c099acccd5..cff8f000731 100644 --- a/test/MC/ARM/dwarf-asm-multiple-sections.s +++ b/test/MC/ARM/dwarf-asm-multiple-sections.s @@ -54,9 +54,9 @@ b: // DWARF-DL: .debug_line contents: // DWARF-DL: version: [[DWVER]] // DWARF-DL-5: address_size: 4 -// DWARF-DL-5: include_directories[ 0] = "" +// DWARF-DL-5: include_directories[ 0] = "/tmp" // DWARF-DL: file_names[ [[DWFILE]]]: -// DWARF-DL: name: "" +// DWARF-DL: name: "{{(|-)}}" // DWARF-DL: 0x0000000000000000 17 0 1 0 0 is_stmt // DWARF-DL-NEXT: 0x0000000000000004 17 0 1 0 0 is_stmt end_sequence // DWARF-DL-NEXT: 0x0000000000000000 21 0 1 0 0 is_stmt diff --git a/test/MC/ELF/debug-file-options.s b/test/MC/ELF/debug-file-options.s index 3bcd131cc38..5c77a48ab72 100644 --- a/test/MC/ELF/debug-file-options.s +++ b/test/MC/ELF/debug-file-options.s @@ -11,25 +11,32 @@ # CHECK: debug_line[0x00000000] # CHECK: version: 5 -# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "" +# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "{{.+}}" # CHECK: include_directories[ 1] = .debug_line_str[0x[[DIR1:[0-9a-f]+]]] = "dir1" # CHECK: include_directories[ 2] = .debug_line_str[0x[[DIR2:[0-9a-f]+]]] = "dir2" # CHECK-NOT: include_directories # CHECK: file_names[ 0]: +# CHECK-NEXT: name: .debug_line_str[0x[[FILE0:[0-9a-f]+]]] = "{{.+}}" +# CHECK-NEXT: dir_index: 0 +# CHECK-NEXT: md5_checksum: +# CHECK-NEXT: source: .debug_line_str[0x[[FILE0SRC:[0-9a-f]+]]] = "" +# CHECK: file_names[ 1]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE1:[0-9a-f]+]]] = "foo" # CHECK-NEXT: dir_index: 1 # CHECK-NEXT: md5_checksum: ee87e05688663173cd6043a3a15bba6e # CHECK-NEXT: source: .debug_line_str[0x[[FILE1SRC:[0-9a-f]+]]] = "void foo() {}" -# CHECK: file_names[ 1]: +# CHECK: file_names[ 2]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE2:[0-9a-f]+]]] = "bar" # CHECK-NEXT: dir_index: 2 # CHECK-NEXT: md5_checksum: 816225a0c90ca8948b70eb58be4d522f # CHECK-NEXT: source: .debug_line_str[0x[[FILE2SRC:[0-9a-f]+]]] = "void bar() {}" # CHECK: .debug_line_str contents: -# CHECK-NEXT: 0x[[DIR0]]: "" +# CHECK-NEXT: 0x[[DIR0]]: "{{.+}}" # CHECK-NEXT: 0x[[DIR1]]: "dir1" # CHECK-NEXT: 0x[[DIR2]]: "dir2" +# CHECK-NEXT: 0x[[FILE0]]: "{{.+}}" +# CHECK-NEXT: 0x[[FILE0SRC]]: "" # CHECK-NEXT: 0x[[FILE1]]: "foo" # CHECK-NEXT: 0x[[FILE1SRC]]: "void foo() {}" # CHECK-NEXT: 0x[[FILE2]]: "bar" diff --git a/test/MC/ELF/debug-md5.s b/test/MC/ELF/debug-md5.s index f8f3bc1a362..658e02e5917 100644 --- a/test/MC/ELF/debug-md5.s +++ b/test/MC/ELF/debug-md5.s @@ -1,4 +1,4 @@ -// RUN: llvm-mc -triple x86_64-unknown-unknown -dwarf-version 5 -filetype=obj %s -o - | llvm-dwarfdump --debug-line --debug-line-str -v - | FileCheck %s +// RUN: llvm-mc -triple x86_64-unknown-unknown -dwarf-version 5 -fdebug-compilation-dir=/tmp -filetype=obj %s -o - | llvm-dwarfdump --debug-line --debug-line-str -v - | FileCheck %s .file 1 "dir1/foo" md5 "00112233445566778899aabbccddeeff" .file 2 "dir2" "bar" md5 "ffeeddccbbaa99887766554433221100" @@ -9,22 +9,26 @@ # CHECK: debug_line[0x00000000] # CHECK: version: 5 -# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "" +# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "/tmp" # CHECK: include_directories[ 1] = .debug_line_str[0x[[DIR1:[0-9a-f]+]]] = "dir1" # CHECK: include_directories[ 2] = .debug_line_str[0x[[DIR2:[0-9a-f]+]]] = "dir2" # CHECK-NOT: include_directories # CHECK: file_names[ 0]: +# CHECK-NEXT: name: .debug_line_str[0x[[FILE0:[0-9a-f]+]]] = "{{.+}}" +# CHECK-NEXT: dir_index: 0 +# CHECK: file_names[ 1]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE1:[0-9a-f]+]]] = "foo" # CHECK-NEXT: dir_index: 1 # CHECK-NEXT: md5_checksum: 00112233445566778899aabbccddeeff -# CHECK: file_names[ 1]: +# CHECK: file_names[ 2]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE2:[0-9a-f]+]]] = "bar" # CHECK-NEXT: dir_index: 2 # CHECK-NEXT: md5_checksum: ffeeddccbbaa99887766554433221100 # CHECK: .debug_line_str contents: -# CHECK-NEXT: 0x[[DIR0]]: "" +# CHECK-NEXT: 0x[[DIR0]]: "/tmp" # CHECK-NEXT: 0x[[DIR1]]: "dir1" # CHECK-NEXT: 0x[[DIR2]]: "dir2" +# CHECK-NEXT: 0x[[FILE0]]: "{{.+}}" # CHECK-NEXT: 0x[[FILE1]]: "foo" # CHECK-NEXT: 0x[[FILE2]]: "bar" diff --git a/test/MC/ELF/debug-source.s b/test/MC/ELF/debug-source.s index 0b919e15ddb..1cf39c7a9d2 100644 --- a/test/MC/ELF/debug-source.s +++ b/test/MC/ELF/debug-source.s @@ -9,23 +9,29 @@ # CHECK: debug_line[0x00000000] # CHECK: version: 5 -# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "" +# CHECK: include_directories[ 0] = .debug_line_str[0x[[DIR0:[0-9a-f]+]]] = "{{.+}}" # CHECK: include_directories[ 1] = .debug_line_str[0x[[DIR1:[0-9a-f]+]]] = "dir1" # CHECK: include_directories[ 2] = .debug_line_str[0x[[DIR2:[0-9a-f]+]]] = "dir2" # CHECK-NOT: include_directories # CHECK: file_names[ 0]: +# CHECK-NEXT: name: .debug_line_str[0x[[FILE0:[0-9a-f]+]]] = "{{.+}}" +# CHECK-NEXT: dir_index: 0 +# CHECK-NEXT: source: .debug_line_str[0x[[FILE0SRC:[0-9a-f]+]]] = "" +# CHECK: file_names[ 1]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE1:[0-9a-f]+]]] = "foo" # CHECK-NEXT: dir_index: 1 # CHECK-NEXT: source: .debug_line_str[0x[[FILE1SRC:[0-9a-f]+]]] = "void foo() {}" -# CHECK: file_names[ 1]: +# CHECK: file_names[ 2]: # CHECK-NEXT: name: .debug_line_str[0x[[FILE2:[0-9a-f]+]]] = "bar" # CHECK-NEXT: dir_index: 2 # CHECK-NEXT: source: .debug_line_str[0x[[FILE2SRC:[0-9a-f]+]]] = "void bar()\n{\n}" # CHECK: .debug_line_str contents: -# CHECK-NEXT: 0x[[DIR0]]: "" +# CHECK-NEXT: 0x[[DIR0]]: "{{.+}}" # CHECK-NEXT: 0x[[DIR1]]: "dir1" # CHECK-NEXT: 0x[[DIR2]]: "dir2" +# CHECK-NEXT: 0x[[FILE0]]: "{{.+}}" +# CHECK-NEXT: 0x[[FILE0SRC]]: "" # CHECK-NEXT: 0x[[FILE1]]: "foo" # CHECK-NEXT: 0x[[FILE1SRC]]: "void foo() {}" # CHECK-NEXT: 0x[[FILE2]]: "bar" diff --git a/test/MC/ELF/dwarf-file0.s b/test/MC/ELF/dwarf-file0.s new file mode 100644 index 00000000000..ae87df2a3f0 --- /dev/null +++ b/test/MC/ELF/dwarf-file0.s @@ -0,0 +1,19 @@ +# RUN: llvm-mc -dwarf-version 4 %s -filetype=obj -o - | llvm-dwarfdump -debug-line - | FileCheck %s --check-prefixes=CHECK,CHECK-4 +# RUN: llvm-mc -dwarf-version 5 %s -filetype=obj -o - | llvm-dwarfdump -debug-line - | FileCheck %s --check-prefixes=CHECK,CHECK-5 +# Darwin is stuck on DWARF v2. +# XFAIL: darwin + .file 0 "root.cpp" + .file 1 "header.h" + .file 2 "root.cpp" +# CHECK-5: include_directories[ 0] = "" +# CHECK-4-NOT: include_directories +# CHECK-4-NOT: file_names[ 0] +# CHECK-5: file_names[ 0]: +# CHECK-5-NEXT: name: "root.cpp" +# CHECK-5-NEXT: dir_index: 0 +# CHECK: file_names[ 1]: +# CHECK-NEXT: name: "header.h" +# CHECK-NEXT: dir_index: 0 +# CHECK: file_names[ 2]: +# CHECK-NEXT: name: "root.cpp" +# CHECK-NEXT: dir_index: 0 diff --git a/tools/llvm-mc/llvm-mc.cpp b/tools/llvm-mc/llvm-mc.cpp index 933aecce696..5d9c060dc21 100644 --- a/tools/llvm-mc/llvm-mc.cpp +++ b/tools/llvm-mc/llvm-mc.cpp @@ -390,6 +390,18 @@ int main(int argc, char **argv) { } if (!MainFileName.empty()) Ctx.setMainFileName(MainFileName); + if (DwarfVersion >= 5) { + // DWARF v5 needs the root file as well as the compilation directory. + // If we find a '.file 0' directive that will supersede these values. + MD5 Hash; + MD5::MD5Result *Cksum = + (MD5::MD5Result *)Ctx.allocate(sizeof(MD5::MD5Result), 1); + Hash.update(Buffer->getBuffer()); + Hash.final(*Cksum); + Ctx.setMCLineTableRootFile( + /*CUID=*/0, Ctx.getCompilationDir(), + !MainFileName.empty() ? MainFileName : InputFilename, Cksum, None); + } // Package up features to be passed to target/subtarget std::string FeaturesStr;