Skip to content

Commit fae31e2

Browse files
[DebugInfo] Change handling of structured bindings of bitfields (#94632)
Currently we use DW_OP_plus_uconst to handle the bitfield offset and handle the bitfield size by choosing a type size that matches, but this doesn't work if either offset or size aren't byte-aligned. Extracting the bits using DW_OP_LLVM_extract_bits means we can handle any kind of offset or size.
1 parent b6476e5 commit fae31e2

File tree

3 files changed

+122
-108
lines changed

3 files changed

+122
-108
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4874,40 +4874,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
48744874
return D;
48754875
}
48764876

4877-
llvm::DIType *CGDebugInfo::CreateBindingDeclType(const BindingDecl *BD) {
4878-
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
4879-
4880-
// If the declaration is bound to a bitfield struct field, its type may have a
4881-
// size that is different from its deduced declaration type's.
4882-
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
4883-
if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
4884-
if (FD->isBitField()) {
4885-
ASTContext &Context = CGM.getContext();
4886-
const CGRecordLayout &RL =
4887-
CGM.getTypes().getCGRecordLayout(FD->getParent());
4888-
const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
4889-
4890-
// Find an integer type with the same bitwidth as the bitfield size. If
4891-
// no suitable type is present in the target, give up on producing debug
4892-
// information as it would be wrong. It is certainly possible to produce
4893-
// correct debug info, but the logic isn't currently implemented.
4894-
uint64_t BitfieldSizeInBits = Info.Size;
4895-
QualType IntTy =
4896-
Context.getIntTypeForBitwidth(BitfieldSizeInBits, Info.IsSigned);
4897-
if (IntTy.isNull())
4898-
return nullptr;
4899-
Qualifiers Quals = BD->getType().getQualifiers();
4900-
QualType FinalTy = Context.getQualifiedType(IntTy, Quals);
4901-
llvm::DIType *Ty = getOrCreateType(FinalTy, Unit);
4902-
assert(Ty);
4903-
return Ty;
4904-
}
4905-
}
4906-
}
4907-
4908-
return getOrCreateType(BD->getType(), Unit);
4909-
}
4910-
49114877
llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49124878
llvm::Value *Storage,
49134879
std::optional<unsigned> ArgNo,
@@ -4922,7 +4888,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49224888
if (isa<DeclRefExpr>(BD->getBinding()))
49234889
return nullptr;
49244890

4925-
llvm::DIType *Ty = CreateBindingDeclType(BD);
4891+
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
4892+
llvm::DIType *Ty = getOrCreateType(BD->getType(), Unit);
49264893

49274894
// If there is no debug info for this type then do not emit debug info
49284895
// for this variable.
@@ -4948,7 +4915,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49484915
unsigned Column = getColumnNumber(BD->getLocation());
49494916
StringRef Name = BD->getName();
49504917
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
4951-
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
49524918
// Create the descriptor for the variable.
49534919
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
49544920
Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize,
@@ -4962,13 +4928,29 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49624928
const ASTRecordLayout &layout =
49634929
CGM.getContext().getASTRecordLayout(parent);
49644930
const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex);
4965-
4966-
if (fieldOffset != 0) {
4967-
// Currently if the field offset is not a multiple of byte, the produced
4968-
// location would not be accurate. Therefore give up.
4969-
if (fieldOffset % CGM.getContext().getCharWidth() != 0)
4970-
return nullptr;
4971-
4931+
if (FD->isBitField()) {
4932+
const CGRecordLayout &RL =
4933+
CGM.getTypes().getCGRecordLayout(FD->getParent());
4934+
const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
4935+
// Use DW_OP_plus_uconst to adjust to the start of the bitfield
4936+
// storage.
4937+
if (!Info.StorageOffset.isZero()) {
4938+
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
4939+
Expr.push_back(Info.StorageOffset.getQuantity());
4940+
}
4941+
// Use LLVM_extract_bits to extract the appropriate bits from this
4942+
// bitfield.
4943+
Expr.push_back(Info.IsSigned
4944+
? llvm::dwarf::DW_OP_LLVM_extract_bits_sext
4945+
: llvm::dwarf::DW_OP_LLVM_extract_bits_zext);
4946+
Expr.push_back(Info.Offset);
4947+
// If we have an oversized bitfield then the value won't be more than
4948+
// the size of the type.
4949+
const uint64_t TypeSize = CGM.getContext().getTypeSize(BD->getType());
4950+
Expr.push_back(std::min((uint64_t)Info.Size, TypeSize));
4951+
} else if (fieldOffset != 0) {
4952+
assert(fieldOffset % CGM.getContext().getCharWidth() == 0 &&
4953+
"Unexpected non-bitfield with non-byte-aligned offset");
49724954
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
49734955
Expr.push_back(
49744956
CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity());

clang/lib/CodeGen/CGDebugInfo.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -338,9 +338,6 @@ class CGDebugInfo {
338338
llvm::DIScope *RecordTy,
339339
const RecordDecl *RD);
340340

341-
/// Create type for binding declarations.
342-
llvm::DIType *CreateBindingDeclType(const BindingDecl *BD);
343-
344341
/// Create an anonnymous zero-size separator for bit-field-decl if needed on
345342
/// the target.
346343
llvm::DIDerivedType *createBitFieldSeparatorIfNeeded(

0 commit comments

Comments
 (0)