Changeset View
Changeset View
Standalone View
Standalone View
llvm/include/llvm/IR/DebugInfoMetadata.h
Show First 20 Lines • Show All 592 Lines • ▼ Show 20 Lines | bool operator==(const ChecksumInfo<T> &X) const { | ||||
return Kind == X.Kind && Value == X.Value; | return Kind == X.Kind && Value == X.Value; | ||||
} | } | ||||
bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | bool operator!=(const ChecksumInfo<T> &X) const { return !(*this == X); } | ||||
StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | StringRef getKindAsString() const { return getChecksumKindAsString(Kind); } | ||||
}; | }; | ||||
private: | private: | ||||
std::optional<ChecksumInfo<MDString *>> Checksum; | std::optional<ChecksumInfo<MDString *>> Checksum; | ||||
std::optional<MDString *> Source; | /// An optional source. A nullptr means none. | ||||
MDString *Source; | |||||
DIFile(LLVMContext &C, StorageType Storage, | DIFile(LLVMContext &C, StorageType Storage, | ||||
std::optional<ChecksumInfo<MDString *>> CS, | std::optional<ChecksumInfo<MDString *>> CS, MDString *Src, | ||||
std::optional<MDString *> Src, ArrayRef<Metadata *> Ops); | ArrayRef<Metadata *> Ops); | ||||
~DIFile() = default; | ~DIFile() = default; | ||||
static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | static DIFile *getImpl(LLVMContext &Context, StringRef Filename, | ||||
StringRef Directory, | StringRef Directory, | ||||
std::optional<ChecksumInfo<StringRef>> CS, | std::optional<ChecksumInfo<StringRef>> CS, | ||||
std::optional<StringRef> Source, StorageType Storage, | std::optional<StringRef> Source, StorageType Storage, | ||||
bool ShouldCreate = true) { | bool ShouldCreate = true) { | ||||
std::optional<ChecksumInfo<MDString *>> MDChecksum; | std::optional<ChecksumInfo<MDString *>> MDChecksum; | ||||
if (CS) | if (CS) | ||||
MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | MDChecksum.emplace(CS->Kind, getCanonicalMDString(Context, CS->Value)); | ||||
return getImpl(Context, getCanonicalMDString(Context, Filename), | return getImpl(Context, getCanonicalMDString(Context, Filename), | ||||
getCanonicalMDString(Context, Directory), MDChecksum, | getCanonicalMDString(Context, Directory), MDChecksum, | ||||
Source ? std::optional<MDString *>( | Source ? MDString::get(Context, *Source) : nullptr, Storage, | ||||
dblaikie: I think we can't use `getCanonicalMDString` here, because it collapses the empty case into the… | |||||
getCanonicalMDString(Context, *Source)) | ShouldCreate); | ||||
: std::nullopt, | |||||
Storage, ShouldCreate); | |||||
} | } | ||||
static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | static DIFile *getImpl(LLVMContext &Context, MDString *Filename, | ||||
MDString *Directory, | MDString *Directory, | ||||
std::optional<ChecksumInfo<MDString *>> CS, | std::optional<ChecksumInfo<MDString *>> CS, | ||||
std::optional<MDString *> Source, StorageType Storage, | MDString *Source, StorageType Storage, | ||||
bool ShouldCreate = true); | bool ShouldCreate = true); | ||||
TempDIFile cloneImpl() const { | TempDIFile cloneImpl() const { | ||||
return getTemporary(getContext(), getFilename(), getDirectory(), | return getTemporary(getContext(), getFilename(), getDirectory(), | ||||
getChecksum(), getSource()); | getChecksum(), getSource()); | ||||
} | } | ||||
public: | public: | ||||
DEFINE_MDNODE_GET(DIFile, | DEFINE_MDNODE_GET(DIFile, | ||||
(StringRef Filename, StringRef Directory, | (StringRef Filename, StringRef Directory, | ||||
std::optional<ChecksumInfo<StringRef>> CS = std::nullopt, | std::optional<ChecksumInfo<StringRef>> CS = std::nullopt, | ||||
std::optional<StringRef> Source = std::nullopt), | std::optional<StringRef> Source = std::nullopt), | ||||
(Filename, Directory, CS, Source)) | (Filename, Directory, CS, Source)) | ||||
DEFINE_MDNODE_GET(DIFile, | DEFINE_MDNODE_GET(DIFile, | ||||
(MDString * Filename, MDString *Directory, | (MDString * Filename, MDString *Directory, | ||||
std::optional<ChecksumInfo<MDString *>> CS = std::nullopt, | std::optional<ChecksumInfo<MDString *>> CS = std::nullopt, | ||||
std::optional<MDString *> Source = std::nullopt), | MDString *Source = nullptr), | ||||
(Filename, Directory, CS, Source)) | (Filename, Directory, CS, Source)) | ||||
TempDIFile clone() const { return cloneImpl(); } | TempDIFile clone() const { return cloneImpl(); } | ||||
StringRef getFilename() const { return getStringOperand(0); } | StringRef getFilename() const { return getStringOperand(0); } | ||||
StringRef getDirectory() const { return getStringOperand(1); } | StringRef getDirectory() const { return getStringOperand(1); } | ||||
std::optional<ChecksumInfo<StringRef>> getChecksum() const { | std::optional<ChecksumInfo<StringRef>> getChecksum() const { | ||||
std::optional<ChecksumInfo<StringRef>> StringRefChecksum; | std::optional<ChecksumInfo<StringRef>> StringRefChecksum; | ||||
if (Checksum) | if (Checksum) | ||||
StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | StringRefChecksum.emplace(Checksum->Kind, Checksum->Value->getString()); | ||||
return StringRefChecksum; | return StringRefChecksum; | ||||
} | } | ||||
std::optional<StringRef> getSource() const { | std::optional<StringRef> getSource() const { | ||||
return Source ? std::optional<StringRef>((*Source)->getString()) | return Source ? std::optional<StringRef>(Source->getString()) | ||||
: std::nullopt; | : std::nullopt; | ||||
} | } | ||||
Not Done ReplyInline ActionsHow is this different from the previous code? Optional::operator* would have an assert in it, right? So the previous code would've been asserting in the same places/ways, I think? dblaikie: How is this different from the previous code? Optional::operator* would have an assert in it… | |||||
Yes, there is an assert in OptionalStorage::value, but it only checks that there is a value. nullptr is a valid value inside a Optional<MDString *>, but the expectation of this class is that Source is either None or contains a non-null pointer. (Side remark: It may be possible to change Source to just a MDString * and make nullptr mean that there is no source. That's equally fine with me, but requires changing the signature of getRawSource. Let me know if you prefer that.) Hahnfeld: Yes, there is an `assert` in `OptionalStorage::value`, but it only checks that there is a value. | |||||
MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | MDString *getRawFilename() const { return getOperandAs<MDString>(0); } | ||||
MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | MDString *getRawDirectory() const { return getOperandAs<MDString>(1); } | ||||
std::optional<ChecksumInfo<MDString *>> getRawChecksum() const { | std::optional<ChecksumInfo<MDString *>> getRawChecksum() const { | ||||
return Checksum; | return Checksum; | ||||
} | } | ||||
std::optional<MDString *> getRawSource() const { return Source; } | MDString *getRawSource() const { return Source; } | ||||
static StringRef getChecksumKindAsString(ChecksumKind CSKind); | static StringRef getChecksumKindAsString(ChecksumKind CSKind); | ||||
static std::optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | static std::optional<ChecksumKind> getChecksumKind(StringRef CSKindStr); | ||||
static bool classof(const Metadata *MD) { | static bool classof(const Metadata *MD) { | ||||
return MD->getMetadataID() == DIFileKind; | return MD->getMetadataID() == DIFileKind; | ||||
} | } | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 3,076 Lines • Show Last 20 Lines |
I think we can't use getCanonicalMDString here, because it collapses the empty case into the null case, when they were intended to be differentiated. So this'll need to be manually expanded to the MDString::get(Context, S) without the empty->nullptr part. Then empty -> empty MDString, None -> null, non-empty -> non-empty MDString.
And the test case can be updated to demonstrate that the difference between empty and null is preserved.