aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/AsmParser/LLParser.cpp29
-rw-r--r--llvm/lib/IR/AsmWriter.cpp5
-rw-r--r--llvm/lib/MC/MCDwarf.cpp11
-rw-r--r--llvm/test/Assembler/difile-empty-source.ll12
-rw-r--r--llvm/test/DebugInfo/Generic/mixed-source.ll58
5 files changed, 89 insertions, 26 deletions
diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp
index 0027775..13bef1f 100644
--- a/llvm/lib/AsmParser/LLParser.cpp
+++ b/llvm/lib/AsmParser/LLParser.cpp
@@ -4786,9 +4786,13 @@ struct MDField : public MDFieldImpl<Metadata *> {
};
struct MDStringField : public MDFieldImpl<MDString *> {
- bool AllowEmpty;
- MDStringField(bool AllowEmpty = true)
- : ImplTy(nullptr), AllowEmpty(AllowEmpty) {}
+ enum class EmptyIs {
+ Null, //< Allow empty input string, map to nullptr
+ Empty, //< Allow empty input string, map to an empty MDString
+ Error, //< Disallow empty string, map to an error
+ } EmptyIs;
+ MDStringField(enum EmptyIs EmptyIs = EmptyIs::Null)
+ : ImplTy(nullptr), EmptyIs(EmptyIs) {}
};
struct MDFieldList : public MDFieldImpl<SmallVector<Metadata *, 4>> {
@@ -5260,10 +5264,19 @@ bool LLParser::parseMDField(LocTy Loc, StringRef Name, MDStringField &Result) {
if (parseStringConstant(S))
return true;
- if (!Result.AllowEmpty && S.empty())
- return error(ValueLoc, "'" + Name + "' cannot be empty");
+ if (S.empty()) {
+ switch (Result.EmptyIs) {
+ case MDStringField::EmptyIs::Null:
+ Result.assign(nullptr);
+ return false;
+ case MDStringField::EmptyIs::Empty:
+ break;
+ case MDStringField::EmptyIs::Error:
+ return error(ValueLoc, "'" + Name + "' cannot be empty");
+ }
+ }
- Result.assign(S.empty() ? nullptr : MDString::get(Context, S));
+ Result.assign(MDString::get(Context, S));
return false;
}
@@ -5781,7 +5794,7 @@ bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) {
REQUIRED(directory, MDStringField, ); \
OPTIONAL(checksumkind, ChecksumKindField, (DIFile::CSK_MD5)); \
OPTIONAL(checksum, MDStringField, ); \
- OPTIONAL(source, MDStringField, );
+ OPTIONAL(source, MDStringField, (MDStringField::EmptyIs::Empty));
PARSE_MD_FIELDS();
#undef VISIT_MD_FIELDS
@@ -6065,7 +6078,7 @@ bool LLParser::parseDITemplateValueParameter(MDNode *&Result, bool IsDistinct) {
/// declaration: !4, align: 8)
bool LLParser::parseDIGlobalVariable(MDNode *&Result, bool IsDistinct) {
#define VISIT_MD_FIELDS(OPTIONAL, REQUIRED) \
- OPTIONAL(name, MDStringField, (/* AllowEmpty */ false)); \
+ OPTIONAL(name, MDStringField, (MDStringField::EmptyIs::Error)); \
OPTIONAL(scope, MDField, ); \
OPTIONAL(linkageName, MDStringField, ); \
OPTIONAL(file, MDField, ); \
diff --git a/llvm/lib/IR/AsmWriter.cpp b/llvm/lib/IR/AsmWriter.cpp
index 3e40915..e5a4e1e 100644
--- a/llvm/lib/IR/AsmWriter.cpp
+++ b/llvm/lib/IR/AsmWriter.cpp
@@ -2401,8 +2401,9 @@ static void writeDIFile(raw_ostream &Out, const DIFile *N, AsmWriterContext &) {
// Print all values for checksum together, or not at all.
if (N->getChecksum())
Printer.printChecksum(*N->getChecksum());
- Printer.printString("source", N->getSource().value_or(StringRef()),
- /* ShouldSkipEmpty */ true);
+ if (N->getSource())
+ Printer.printString("source", *N->getSource(),
+ /* ShouldSkipEmpty */ false);
Out << ")";
}
diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp
index b1dced7..e7c0d37 100644
--- a/llvm/lib/MC/MCDwarf.cpp
+++ b/llvm/lib/MC/MCDwarf.cpp
@@ -447,10 +447,17 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile,
StringRef(reinterpret_cast<const char *>(Cksum.data()), Cksum.size()));
}
if (HasAnySource) {
+ // From https://dwarfstd.org/issues/180201.1.html
+ // * The value is an empty null-terminated string if no source is available
+ StringRef Source = DwarfFile.Source.value_or(StringRef());
+ // * If the source is available but is an empty file then the value is a
+ // null-terminated single "\n".
+ if (DwarfFile.Source && DwarfFile.Source->empty())
+ Source = "\n";
if (LineStr)
- LineStr->emitRef(MCOS, DwarfFile.Source.value_or(StringRef()));
+ LineStr->emitRef(MCOS, Source);
else {
- MCOS->emitBytes(DwarfFile.Source.value_or(StringRef())); // Source and...
+ MCOS->emitBytes(Source); // Source and...
MCOS->emitBytes(StringRef("\0", 1)); // its null terminator.
}
}
diff --git a/llvm/test/Assembler/difile-empty-source.ll b/llvm/test/Assembler/difile-empty-source.ll
new file mode 100644
index 0000000..11587d8
--- /dev/null
+++ b/llvm/test/Assembler/difile-empty-source.ll
@@ -0,0 +1,12 @@
+; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
+; RUN: verify-uselistorder
+
+; CHECK: !DIFile({{.*}}, source: "")
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!2, !3}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, emissionKind: FullDebug)
+!1 = !DIFile(filename: "-", directory: "/", checksumkind: CSK_MD5, checksum: "d41d8cd98f00b204e9800998ecf8427e", source: "")
+!2 = !{i32 7, !"Dwarf Version", i32 5}
+!3 = !{i32 2, !"Debug Info Version", i32 3}
diff --git a/llvm/test/DebugInfo/Generic/mixed-source.ll b/llvm/test/DebugInfo/Generic/mixed-source.ll
index d5586f8..ee3598f 100644
--- a/llvm/test/DebugInfo/Generic/mixed-source.ll
+++ b/llvm/test/DebugInfo/Generic/mixed-source.ll
@@ -5,36 +5,66 @@
; CHECK: include_directories[ 0] = "dir"
; CHECK-NEXT: file_names[ 0]:
+; CHECK-NEXT: name: "main.c"
+; CHECK-NEXT: dir_index: 0
+; CHECK-NOT: source:
+; CHECK-NEXT: file_names[ 1]:
; CHECK-NEXT: name: "foo.c"
; CHECK-NEXT: dir_index: 0
; CHECK-NEXT: source: "void foo() { }\n"
-; CHECK-NEXT: file_names[ 1]:
-; CHECK-NEXT: name: "bar.h"
+; CHECK-NEXT: file_names[ 2]:
+; CHECK-NEXT: name: "newline.h"
+; CHECK-NEXT: dir_index: 0
+; CHECK-NEXT: source: "\n"
+; CHECK-NEXT: file_names[ 3]:
+; CHECK-NEXT: name: "empty.h"
+; CHECK-NEXT: dir_index: 0
+; CHECK-NEXT: source: "\n"
+; CHECK-NEXT: file_names[ 4]:
+; CHECK-NEXT: name: "absent.h"
; CHECK-NEXT: dir_index: 0
; CHECK-NOT: source:
; Test that DIFiles mixing source and no-source within a DICompileUnit works.
-define dso_local void @foo() !dbg !5 {
+define dso_local void @foo() !dbg !6 {
ret void, !dbg !7
}
-define dso_local void @bar() !dbg !6 {
- ret void, !dbg !8
+define dso_local void @newline() !dbg !9 {
+ ret void, !dbg !10
}
-!llvm.dbg.cu = !{!4}
+define dso_local void @empty() !dbg !12 {
+ ret void, !dbg !13
+}
+
+define dso_local void @absent() !dbg !15 {
+ ret void, !dbg !16
+}
+
+!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!0, !1}
!0 = !{i32 2, !"Dwarf Version", i32 5}
!1 = !{i32 2, !"Debug Info Version", i32 3}
-!2 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
-!3 = !DIFile(filename: "bar.h", directory: "dir")
+!2 = distinct !DICompileUnit(language: DW_LANG_C99, emissionKind: FullDebug, file: !4)
+!3 = !DISubroutineType(types: !{})
+!4 = !DIFile(filename: "main.c", directory: "dir")
+
+!5 = !DIFile(filename: "foo.c", directory: "dir", source: "void foo() { }\0A")
+!6 = distinct !DISubprogram(name: "foo", file: !5, line: 1, type: !3, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+!7 = !DILocation(line: 1, scope: !6)
+
+!8 = !DIFile(filename: "newline.h", directory: "dir", source: "\0A")
+!9 = distinct !DISubprogram(name: "newline", file: !8, line: 1, type: !3, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+!10 = !DILocation(line: 1, scope: !9)
+
+!11 = !DIFile(filename: "empty.h", directory: "dir", source: "")
+!12 = distinct !DISubprogram(name: "empty", file: !11, line: 1, type: !3, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+!13 = !DILocation(line: 1, scope: !12)
-!4 = distinct !DICompileUnit(language: DW_LANG_C99, emissionKind: FullDebug, file: !2)
-!5 = distinct !DISubprogram(name: "foo", file: !2, line: 1, type: !9, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !4)
-!6 = distinct !DISubprogram(name: "bar", file: !3, line: 1, type: !9, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !4)
-!7 = !DILocation(line: 1, scope: !5)
-!8 = !DILocation(line: 1, scope: !6)
-!9 = !DISubroutineType(types: !{})
+!14 = !DIFile(filename: "absent.h", directory: "dir")
+!15 = distinct !DISubprogram(name: "absent", file: !14, line: 1, type: !3, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2)
+!16 = !DILocation(line: 1, scope: !15)