Skip to content

Commit f7d42cb

Browse files
[DebugInfo] Change handling of structured bindings of bitfields
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. TODO: test signed type, nonzero StorageOffset, oversized bitfield
1 parent 342011f commit f7d42cb

File tree

3 files changed

+73
-108
lines changed

3 files changed

+73
-108
lines changed

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -4865,40 +4865,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
48654865
return D;
48664866
}
48674867

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

4916-
llvm::DIType *Ty = CreateBindingDeclType(BD);
4882+
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
4883+
llvm::DIType *Ty = getOrCreateType(BD->getType(), Unit);
49174884

49184885
// If there is no debug info for this type then do not emit debug info
49194886
// for this variable.
@@ -4939,7 +4906,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49394906
unsigned Column = getColumnNumber(BD->getLocation());
49404907
StringRef Name = BD->getName();
49414908
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
4942-
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
49434909
// Create the descriptor for the variable.
49444910
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
49454911
Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize,
@@ -4953,13 +4919,21 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
49534919
const ASTRecordLayout &layout =
49544920
CGM.getContext().getASTRecordLayout(parent);
49554921
const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex);
4956-
4957-
if (fieldOffset != 0) {
4958-
// Currently if the field offset is not a multiple of byte, the produced
4959-
// location would not be accurate. Therefore give up.
4960-
if (fieldOffset % CGM.getContext().getCharWidth() != 0)
4961-
return nullptr;
4962-
4922+
if (FD->isBitField()) {
4923+
const CGRecordLayout &RL =
4924+
CGM.getTypes().getCGRecordLayout(FD->getParent());
4925+
const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
4926+
if (!Info.StorageOffset.isZero()) {
4927+
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
4928+
Expr.push_back(Info.StorageOffset.getQuantity());
4929+
}
4930+
Expr.push_back(Info.IsSigned ? llvm::dwarf::DW_OP_LLVM_extract_bits_sext
4931+
: llvm::dwarf::DW_OP_LLVM_extract_bits_zext);
4932+
Expr.push_back(Info.Offset);
4933+
Expr.push_back(Info.Size);
4934+
} else if (fieldOffset != 0) {
4935+
assert(fieldOffset % CGM.getContext().getCharWidth() == 0 &&
4936+
"Unexpected non-bitfield with non-byte-aligned offset");
49634937
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
49644938
Expr.push_back(
49654939
CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity());

clang/lib/CodeGen/CGDebugInfo.h

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

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

0 commit comments

Comments
 (0)