[llvm][DebugInfo] Add support for _BitInt in DWARFTypePrinter (#168382)

As of recent, LLVM includes the bit-size as a `DW_AT_bit_size` (and as
part of `DW_AT_name`) of `_BitInt`s in DWARF. This allows us to mark
`_BitInt`s as "reconstitutable" when compiling with
`-gsimple-template-names`. However, before doing so we need to make sure
the `DWARFTypePrinter` can reconstruct template parameter values that
have `_BitInt` type. This patch adds support for printing
`DW_TAG_template_value_parameter`s that have `_BitInt` type. Since
`-gsimple-template-names` only omits template parameters that are `<=
64` bit wide, we don't support `_BitInt`s larger than 64 bits.
This commit is contained in:
Michael Buch 2025-11-19 22:57:39 +00:00 committed by GitHub
parent 19fe9b477b
commit e99c83ff38
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 7432 additions and 7093 deletions

View File

@ -95,6 +95,8 @@ struct t12 {
template <decltype(ns::AnonEnum1)> void f10() {}
template <typename T, T V> void f11() {}
int main() {
struct {
} A;
@ -239,8 +241,10 @@ int main() {
f1<void(t8)>();
operator_not_really<int>();
t12 v4;
f1<_BitInt(3)>();
f1<const unsigned _BitInt(5)>();
f11<_BitInt(3), 2>();
f11<const unsigned _BitInt(5), 2>();
f11<_BitInt(65), 2>();
f11<const unsigned _BitInt(65), 2>();
f1<void(t1<>, t1<>)>();
f1<int t1<>::*>();
void fcc() __attribute__((swiftcall));

View File

@ -78,6 +78,12 @@ private:
}
return false;
}
/// If FormValue is a valid constant Form, print into \c OS the integral value
/// casted to the type referred to by \c Cast.
template <typename FormValueType>
void appendCastedValue(const FormValueType &FormValue, DieType Cast,
bool IsUnsigned);
};
template <typename DieType>
@ -413,6 +419,31 @@ DieType DWARFTypePrinter<DieType>::appendQualifiedNameBefore(DieType D) {
return appendUnqualifiedNameBefore(D);
}
template <typename DieType>
template <typename FormValueType>
void DWARFTypePrinter<DieType>::appendCastedValue(
const FormValueType &FormValue, DieType Cast, bool IsUnsigned) {
std::string ValStr;
if (IsUnsigned) {
std::optional<uint64_t> UVal = FormValue.getAsUnsignedConstant();
if (!UVal)
return;
ValStr = std::to_string(*UVal);
} else {
std::optional<int64_t> SVal = FormValue.getAsSignedConstant();
if (!SVal)
return;
ValStr = std::to_string(*SVal);
}
OS << '(';
appendQualifiedName(Cast);
OS << ')';
OS << std::move(ValStr);
}
template <typename DieType>
bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
bool *FirstParameter) {
@ -438,13 +469,11 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
DieType T = detail::resolveReferencedType(C);
Sep();
if (T.getTag() == dwarf::DW_TAG_enumeration_type) {
OS << '(';
appendQualifiedName(T);
OS << ')';
auto V = C.find(dwarf::DW_AT_const_value);
OS << std::to_string(*V->getAsSignedConstant());
appendCastedValue(*V, T, /*IsUnsigned=*/false);
continue;
}
// /Maybe/ we could do pointer/reference type parameters, looking for the
// symbol in the ELF symbol table to get back to the variable...
// but probably not worth it.
@ -539,6 +568,12 @@ bool DWARFTypePrinter<DieType>::appendTemplateParameters(DieType D,
else
OS << llvm::format("'\\U%08" PRIx64 "'", Val);
}
// FIXME: Handle _BitInt's larger than 64-bits which are emitted as
// block data.
} else if (Name.starts_with("_BitInt")) {
appendCastedValue(*V, T, /*IsUnsigned=*/false);
} else if (Name.starts_with("unsigned _BitInt")) {
appendCastedValue(*V, T, /*IsUnsigned=*/true);
}
continue;
}

File diff suppressed because it is too large Load Diff