Skip to content

Commit

Permalink
[DebugInfo] Store optional DIFile::Source as pointer
Browse files Browse the repository at this point in the history
getCanonicalMDString() also returns a nullptr for empty strings, which
tripped over the getSource() method. Solve the ambiguity of no source
versus an optional containing a nullptr by simply storing a pointer.

Differential Revision: https://reviews.llvm.org/D138658
  • Loading branch information
hahnjo committed Dec 8, 2022
1 parent 61318fa commit c9cb4fc
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 31 deletions.
21 changes: 10 additions & 11 deletions llvm/include/llvm/IR/DebugInfoMetadata.h
Expand Up @@ -598,11 +598,12 @@ class DIFile : public DIScope {

private:
std::optional<ChecksumInfo<MDString *>> Checksum;
std::optional<MDString *> Source;
/// An optional source. A nullptr means none.
MDString *Source;

DIFile(LLVMContext &C, StorageType Storage,
std::optional<ChecksumInfo<MDString *>> CS,
std::optional<MDString *> Src, ArrayRef<Metadata *> Ops);
std::optional<ChecksumInfo<MDString *>> CS, MDString *Src,
ArrayRef<Metadata *> Ops);
~DIFile() = default;

static DIFile *getImpl(LLVMContext &Context, StringRef Filename,
Expand All @@ -615,15 +616,13 @@ class DIFile : public DIScope {
MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value));
return getImpl(Context, getCanonicalMDString(Context, Filename),
getCanonicalMDString(Context, Directory), MDChecksum,
Source ? std::optional<MDString *>(
getCanonicalMDString(Context, *Source))
: std::nullopt,
Storage, ShouldCreate);
Source ? MDString::get(Context, *Source) : nullptr, Storage,
ShouldCreate);
}
static DIFile *getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory,
std::optional<ChecksumInfo<MDString *>> CS,
std::optional<MDString *> Source, StorageType Storage,
MDString *Source, StorageType Storage,
bool ShouldCreate = true);

TempDIFile cloneImpl() const {
Expand All @@ -640,7 +639,7 @@ class DIFile : public DIScope {
DEFINE_MDNODE_GET(DIFile,
(MDString * Filename, MDString *Directory,
std::optional<ChecksumInfo<MDString *>> CS = std::nullopt,
std::optional<MDString *> Source = std::nullopt),
MDString *Source = nullptr),
(Filename, Directory, CS, Source))

TempDIFile clone() const { return cloneImpl(); }
Expand All @@ -654,7 +653,7 @@ class DIFile : public DIScope {
return StringRefChecksum;
}
std::optional<StringRef> getSource() const {
return Source ? std::optional<StringRef>((*Source)->getString())
return Source ? std::optional<StringRef>(Source->getString())
: std::nullopt;
}

Expand All @@ -663,7 +662,7 @@ class DIFile : public DIScope {
std::optional<ChecksumInfo<MDString *>> getRawChecksum() const {
return Checksum;
}
std::optional<MDString *> getRawSource() const { return Source; }
MDString *getRawSource() const { return Source; }

static StringRef getChecksumKindAsString(ChecksumKind CSKind);
static std::optional<ChecksumKind> getChecksumKind(StringRef CSKindStr);
Expand Down
8 changes: 4 additions & 4 deletions llvm/lib/AsmParser/LLParser.cpp
Expand Up @@ -4996,11 +4996,11 @@ bool LLParser::parseDIFile(MDNode *&Result, bool IsDistinct) {
else if (checksumkind.Seen || checksum.Seen)
return Lex.Error("'checksumkind' and 'checksum' must be provided together");

std::optional<MDString *> OptSource;
MDString *Source = nullptr;
if (source.Seen)
OptSource = source.Val;
Result = GET_OR_DISTINCT(DIFile, (Context, filename.Val, directory.Val,
OptChecksum, OptSource));
Source = source.Val;
Result = GET_OR_DISTINCT(
DIFile, (Context, filename.Val, directory.Val, OptChecksum, Source));
return false;
}

Expand Down
9 changes: 4 additions & 5 deletions llvm/lib/Bitcode/Reader/MetadataLoader.cpp
Expand Up @@ -1621,11 +1621,10 @@ Error MetadataLoader::MetadataLoaderImpl::parseOneMetadata(
Checksum.emplace(static_cast<DIFile::ChecksumKind>(Record[3]),
getMDString(Record[4]));
MetadataList.assignValue(
GET_OR_DISTINCT(DIFile, (Context, getMDString(Record[1]),
getMDString(Record[2]), Checksum,
Record.size() > 5 ? std::optional<MDString *>(
getMDString(Record[5]))
: std::nullopt)),
GET_OR_DISTINCT(DIFile,
(Context, getMDString(Record[1]),
getMDString(Record[2]), Checksum,
Record.size() > 5 ? getMDString(Record[5]) : nullptr)),
NextMetadataNo);
NextMetadataNo++;
break;
Expand Down
2 changes: 1 addition & 1 deletion llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
Expand Up @@ -1808,7 +1808,7 @@ void ModuleBitcodeWriter::writeDIFile(const DIFile *N,
}
auto Source = N->getRawSource();
if (Source)
Record.push_back(VE.getMetadataOrNullID(*Source));
Record.push_back(VE.getMetadataOrNullID(Source));

Stream.EmitRecord(bitc::METADATA_FILE, Record, Abbrev);
Record.clear();
Expand Down
12 changes: 6 additions & 6 deletions llvm/lib/IR/DebugInfoMetadata.cpp
Expand Up @@ -801,8 +801,8 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
}

DIFile::DIFile(LLVMContext &C, StorageType Storage,
std::optional<ChecksumInfo<MDString *>> CS,
std::optional<MDString *> Src, ArrayRef<Metadata *> Ops)
std::optional<ChecksumInfo<MDString *>> CS, MDString *Src,
ArrayRef<Metadata *> Ops)
: DIScope(C, DIFileKind, Storage, dwarf::DW_TAG_file_type, Ops),
Checksum(CS), Source(Src) {}

Expand Down Expand Up @@ -834,15 +834,15 @@ DIFile::getChecksumKind(StringRef CSKindStr) {
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
MDString *Directory,
std::optional<DIFile::ChecksumInfo<MDString *>> CS,
std::optional<MDString *> Source, StorageType Storage,
MDString *Source, StorageType Storage,
bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString");
assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
assert((!Source || isCanonical(*Source)) && "Expected canonical MDString");
// We do *NOT* expect Source to be a canonical MDString because nullptr
// means none, so we need something to represent the empty file.
DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr,
Source.value_or(nullptr)};
Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr, Source};
DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
}
DICompileUnit::DICompileUnit(LLVMContext &C, StorageType Storage,
Expand Down
7 changes: 3 additions & 4 deletions llvm/lib/IR/LLVMContextImpl.h
Expand Up @@ -668,11 +668,11 @@ template <> struct MDNodeKeyImpl<DIFile> {
MDString *Filename;
MDString *Directory;
std::optional<DIFile::ChecksumInfo<MDString *>> Checksum;
std::optional<MDString *> Source;
MDString *Source;

MDNodeKeyImpl(MDString *Filename, MDString *Directory,
std::optional<DIFile::ChecksumInfo<MDString *>> Checksum,
std::optional<MDString *> Source)
MDString *Source)
: Filename(Filename), Directory(Directory), Checksum(Checksum),
Source(Source) {}
MDNodeKeyImpl(const DIFile *N)
Expand All @@ -687,8 +687,7 @@ template <> struct MDNodeKeyImpl<DIFile> {

unsigned getHashValue() const {
return hash_combine(Filename, Directory, Checksum ? Checksum->Kind : 0,
Checksum ? Checksum->Value : nullptr,
Source.value_or(nullptr));
Checksum ? Checksum->Value : nullptr, Source);
}
};

Expand Down
18 changes: 18 additions & 0 deletions llvm/unittests/IR/DebugInfoTest.cpp
Expand Up @@ -190,6 +190,24 @@ TEST(MetadataTest, DeleteInstUsedByDbgValue) {
EXPECT_TRUE(isa<UndefValue>(DVIs[0]->getValue(0)));
}

TEST(DIBuiler, CreateFile) {
LLVMContext Ctx;
std::unique_ptr<Module> M(new Module("MyModule", Ctx));
DIBuilder DIB(*M);

DIFile *F = DIB.createFile("main.c", "/");
EXPECT_EQ(std::nullopt, F->getSource());

std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = std::nullopt;
std::optional<StringRef> Source = std::nullopt;
F = DIB.createFile("main.c", "/", Checksum, Source);
EXPECT_EQ(Source, F->getSource());

Source = "";
F = DIB.createFile("main.c", "/", Checksum, Source);
EXPECT_EQ(Source, F->getSource());
}

TEST(DIBuilder, CreateFortranArrayTypeWithAttributes) {
LLVMContext Ctx;
std::unique_ptr<Module> M(new Module("MyModule", Ctx));
Expand Down
14 changes: 14 additions & 0 deletions llvm/unittests/IR/MetadataTest.cpp
Expand Up @@ -2221,6 +2221,20 @@ TEST_F(DIFileTest, get) {
EXPECT_EQ(N, MDNode::replaceWithUniqued(std::move(Temp)));
}

TEST_F(DIFileTest, EmptySource) {
DIFile *N = DIFile::get(Context, "file", "dir");
EXPECT_EQ(std::nullopt, N->getSource());

std::optional<DIFile::ChecksumInfo<StringRef>> Checksum = std::nullopt;
std::optional<StringRef> Source = std::nullopt;
N = DIFile::get(Context, "file", "dir", Checksum, Source);
EXPECT_EQ(Source, N->getSource());

Source = "";
N = DIFile::get(Context, "file", "dir", Checksum, Source);
EXPECT_EQ(Source, N->getSource());
}

TEST_F(DIFileTest, ScopeGetFile) {
// Ensure that DIScope::getFile() returns itself.
DIScope *N = DIFile::get(Context, "file", "dir");
Expand Down

0 comments on commit c9cb4fc

Please sign in to comment.