Source);
}
+ /// Reports whether MD5 checksum usage is consistent (all-or-none).
+ bool isDwarfMD5UsageConsistent(unsigned CUID) const {
+ return getMCDwarfLineTable(CUID).isMD5UsageConsistent();
+ }
+
/// Saves the information from the currently parsed dwarf .loc directive
/// and sets DwarfLocSeen. When the next instruction is assembled an entry
/// in the line number table with this information and the address of the
StringMap<unsigned> SourceIdMap;
StringRef CompilationDir;
MCDwarfFile RootFile;
- bool HasMD5 = false;
bool HasSource = false;
+private:
+ bool HasAllMD5 = true;
+ bool HasAnyMD5 = false;
+public:
MCDwarfLineTableHeader() = default;
Expected<unsigned> tryGetFile(StringRef &Directory, StringRef &FileName,
Emit(MCStreamer *MCOS, MCDwarfLineTableParams Params,
ArrayRef<char> SpecialOpcodeLengths,
Optional<MCDwarfLineStr> &LineStr) const;
+ void resetMD5Usage() {
+ HasAllMD5 = true;
+ HasAnyMD5 = false;
+ }
+ void trackMD5Usage(bool MD5Used) {
+ HasAllMD5 &= MD5Used;
+ HasAnyMD5 |= MD5Used;
+ }
+ bool isMD5UsageConsistent() const {
+ return MCDwarfFiles.empty() || (HasAllMD5 == HasAnyMD5);
+ }
private:
void emitV2FileDirTables(MCStreamer *MCOS) const;
Header.RootFile.DirIndex = 0;
Header.RootFile.Checksum = Checksum;
Header.RootFile.Source = Source;
- Header.HasMD5 = (Checksum != nullptr);
+ Header.trackMD5Usage(Checksum);
Header.HasSource = Source.hasValue();
}
Header.RootFile.DirIndex = 0;
Header.RootFile.Checksum = Checksum;
Header.RootFile.Source = Source;
- Header.HasMD5 = (Checksum != nullptr);
+ Header.trackMD5Usage(Checksum);
Header.HasSource = Source.hasValue();
}
+ void resetRootFile() {
+ assert(Header.MCDwarfFiles.empty());
+ Header.resetMD5Usage();
+ Header.HasSource = false;
+ }
+
+ // Report whether MD5 usage has been consistent (all-or-none).
+ bool isMD5UsageConsistent() const { return Header.isMD5UsageConsistent(); }
+
MCSymbol *getLabel() const {
return Header.Label;
}
// .file 0 is new for DWARF v5.
if (getContext().getDwarfVersion() < 5)
return;
+ // Inform MCDwarf about the root file.
+ getContext().setMCLineTableRootFile(CUID, Directory, Filename, Checksum,
+ Source);
SmallString<128> Str;
raw_svector_ostream OS1(Str);
}
static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
- bool HasMD5, bool HasSource,
+ bool EmitMD5, bool HasSource,
Optional<MCDwarfLineStr> &LineStr) {
assert(!DwarfFile.Name.empty());
if (LineStr)
MCOS->EmitBytes(StringRef("\0", 1)); // its null terminator.
}
MCOS->EmitULEB128IntValue(DwarfFile.DirIndex); // Directory number.
- if (HasMD5) {
+ if (EmitMD5) {
MD5::MD5Result *Cksum = DwarfFile.Checksum;
MCOS->EmitBinaryData(
StringRef(reinterpret_cast<const char *>(Cksum->Bytes.data()),
// directory index. We don't track file size/timestamp so don't emit them
// in the v5 table. Emit MD5 checksums and source if we have them.
uint64_t Entries = 2;
- if (HasMD5)
+ if (HasAllMD5)
Entries += 1;
if (HasSource)
Entries += 1;
: dwarf::DW_FORM_string);
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_directory_index);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_udata);
- if (HasMD5) {
+ if (HasAllMD5) {
MCOS->EmitULEB128IntValue(dwarf::DW_LNCT_MD5);
MCOS->EmitULEB128IntValue(dwarf::DW_FORM_data16);
}
// explicitly, replicate file #1.
MCOS->EmitULEB128IntValue(MCDwarfFiles.size());
emitOneV5FileEntry(MCOS, RootFile.Name.empty() ? MCDwarfFiles[1] : RootFile,
- HasMD5, HasSource, LineStr);
+ HasAllMD5, HasSource, LineStr);
for (unsigned i = 1; i < MCDwarfFiles.size(); ++i)
- emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasMD5, HasSource, LineStr);
+ emitOneV5FileEntry(MCOS, MCDwarfFiles[i], HasAllMD5, HasSource, LineStr);
}
std::pair<MCSymbol *, MCSymbol *>
Directory = "";
}
assert(!FileName.empty());
- // If any files have an MD5 checksum or embedded source, they all must.
+ // Keep track of whether any or all files have an MD5 checksum.
+ // If any files have embedded source, they all must.
if (MCDwarfFiles.empty()) {
- HasMD5 = (Checksum != nullptr);
+ trackMD5Usage(Checksum);
HasSource = (Source != None);
}
if (FileNumber == 0) {
return make_error<StringError>("file number already allocated",
inconvertibleErrorCode());
- // If any files have an MD5 checksum, they all must.
- if (HasMD5 != (Checksum != nullptr))
- return make_error<StringError>("inconsistent use of MD5 checksums",
- inconvertibleErrorCode());
// If any files have embedded source, they all must.
if (HasSource != (Source != None))
return make_error<StringError>("inconsistent use of embedded source",
File.Name = FileName;
File.DirIndex = DirIndex;
File.Checksum = Checksum;
- if (Checksum)
- HasMD5 = true;
+ trackMD5Usage(Checksum);
File.Source = Source;
if (Source)
HasSource = true;
/// Are we parsing ms-style inline assembly?
bool ParsingInlineAsm = false;
+ /// Did we already inform the user about inconsistent MD5 usage?
+ bool ReportedInconsistentMD5 = false;
+
public:
AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
const MCAsmInfo &MAI, unsigned CB);
// In case there is a -g option as well as debug info from directive .file,
// we turn off the -g option, directly use the existing debug info instead.
- getContext().setGenDwarfForAssembly(false);
+ // Also reset any implicit ".file 0" for the assembler source.
+ if (Ctx.getGenDwarfForAssembly()) {
+ Ctx.getMCDwarfLineTable(0).resetRootFile();
+ Ctx.setGenDwarfForAssembly(false);
+ }
if (FileNumber == -1)
getStreamer().EmitFileDirective(Filename);
return Error(DirectiveLoc, toString(FileNumOrErr.takeError()));
FileNumber = FileNumOrErr.get();
}
+ // Alert the user if there are some .file directives with MD5 and some not.
+ // But only do that once.
+ if (!ReportedInconsistentMD5 && !Ctx.isDwarfMD5UsageConsistent(0)) {
+ ReportedInconsistentMD5 = true;
+ return Warning(DirectiveLoc, "inconsistent use of MD5 checksums");
+ }
}
return false;
; XFAIL: darwin
; REQUIRES: object-emission
-; 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=asm -o - %s | FileCheck %s --check-prefix=ASM-4
+; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=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
; RUN: %llc_dwarf -dwarf-version 5 -filetype=obj -o %t5.o %s
; RUN: llvm-dwarfdump -debug-line %t5.o | FileCheck %s --check-prefixes=OBJ,OBJ-5
; ASM-4-NOT: .file 0
-; ASM-5: .file 0 "/scratch{{.*[/\\]}}t.c" md5 0x00000000000000000000000000000000
-; ASM: .file 1 "/scratch{{.*[/\\]}}t1.h"
+; ASM-4: .file 1 "/scratch{{.*[/\\]}}t1.h"
; ASM-4-NOT: md5
-; ASM-5-SAME: md5 0x11111111111111111111111111111111
-; ASM: .file 2 "/scratch{{.*[/\\]}}t2.h"
+; ASM-4: .file 2 "/scratch{{.*[/\\]}}t2.h"
; ASM-4-NOT: md5
-; ASM-5-SAME: md5 0x22222222222222222222222222222222
+; ASM-5: .file 0 "/scratch{{.*[/\\]}}t.c" md5 0x00000000000000000000000000000000
+; ASM-5: .file 1 "t1.h" md5 0x11111111111111111111111111111111
+; ASM-5: .file 2 "t2.h" md5 0x22222222222222222222222222222222
; OBJ-5: file_names[ 0]:
; OBJ-5-NEXT: name: "t.c"
; 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-prefixes=ASM,ASM-5
+; RUN: %llc_dwarf -dwarf-version 4 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-4
+; RUN: %llc_dwarf -dwarf-version 5 -filetype=asm -o - %s | FileCheck %s --check-prefix=ASM-5
; RUN: %llc_dwarf -dwarf-version 4 -filetype=obj -o %t4.o %s
; 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-prefixes=OBJ,OBJ-5
+; ASM-4: .file 1 "/test{{.*[/\\]}}t1.h" source "11111111111111111111111111111111"
+; ASM-4: .file 2 "/test{{.*[/\\]}}t2.h" source "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"
+; ASM-5: .file 1 "t1.h" source "11111111111111111111111111111111"
+; ASM-5: .file 2 "t2.h" source "22222222222222222222222222222222"
; OBJ-5: file_names[ 0]:
; OBJ-5-NEXT: name: "t.c"
.file "baz" md5 0xffeeddccbbaa99887766554433221100
# Inconsistent use of MD5 option. Note: .file 1 did not supply one.
-# CHECK: [[@LINE+1]]:{{[0-9]+}}: error: inconsistent use of MD5 checksums
+# CHECK: [[@LINE+1]]:{{[0-9]+}}: warning: inconsistent use of MD5 checksums
.file 5 "bax" md5 0xffeeddccbbaa99887766554433221100
--- /dev/null
+; RUN: %llc_dwarf -filetype=asm -dwarf-version=5 %s -o - | FileCheck %s -check-prefix=ASM
+; RUN: %llc_dwarf -filetype=obj -dwarf-version=5 %s -o - | llvm-dwarfdump -debug-line - | FileCheck %s -check-prefix=OBJ
+; ASM: .file 0 "{{.+}}" md5
+; ASM: .file 1 "{{.+}}" md5
+; ASM: .file 2 "t1.cpp"
+; ASM-NOT: md5
+; OBJ: file_names[ 0]:
+; OBJ-NOT: md5
+;
+; Generated from this source (see PR37623):
+;
+; #define a(...) template __VA_ARGS__;
+; template <class> class b {};
+; a(class b<int>)
+; # 1 ""
+; int c;
+
+; ModuleID = 't1.cpp'
+source_filename = "t1.cpp"
+target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+@c = global i32 0, align 4, !dbg !0
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!12, !13, !14}
+!llvm.ident = !{!15}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "c", scope: !2, file: !3, line: 1, type: !10, isLocal: false, isDefinition: true)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, file: !3, producer: "clang version 7.0.0 ", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !11)
+!3 = !DIFile(filename: "<stdin>", directory: "/home/probinson/projects/scratch", checksumkind: CSK_MD5, checksum: "9252ff18ee25a08c2b4216b21b5d66d4")
+!4 = !{}
+!5 = !{!6}
+!6 = distinct !DICompositeType(tag: DW_TAG_class_type, name: "b<int>", file: !7, line: 3, size: 8, flags: DIFlagTypePassByValue, elements: !4, templateParams: !8, identifier: "_ZTS1bIiE")
+!7 = !DIFile(filename: "t1.cpp", directory: "/home/probinson/projects/scratch")
+!8 = !{!9}
+!9 = !DITemplateTypeParameter(type: !10)
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!0}
+!12 = !{i32 2, !"Dwarf Version", i32 5}
+!13 = !{i32 2, !"Debug Info Version", i32 3}
+!14 = !{i32 1, !"wchar_size", i32 4}
+!15 = !{!"clang version 7.0.0 "}