Skip to content

[DebugInfo] Change handling of structured bindings of bitfields #94632

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 25 additions & 43 deletions clang/lib/CodeGen/CGDebugInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4874,40 +4874,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
return D;
}

llvm::DIType *CGDebugInfo::CreateBindingDeclType(const BindingDecl *BD) {
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());

// If the declaration is bound to a bitfield struct field, its type may have a
// size that is different from its deduced declaration type's.
if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
if (FD->isBitField()) {
ASTContext &Context = CGM.getContext();
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(FD->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);

// Find an integer type with the same bitwidth as the bitfield size. If
// no suitable type is present in the target, give up on producing debug
// information as it would be wrong. It is certainly possible to produce
// correct debug info, but the logic isn't currently implemented.
uint64_t BitfieldSizeInBits = Info.Size;
QualType IntTy =
Context.getIntTypeForBitwidth(BitfieldSizeInBits, Info.IsSigned);
if (IntTy.isNull())
return nullptr;
Qualifiers Quals = BD->getType().getQualifiers();
QualType FinalTy = Context.getQualifiedType(IntTy, Quals);
llvm::DIType *Ty = getOrCreateType(FinalTy, Unit);
assert(Ty);
return Ty;
}
}
}

return getOrCreateType(BD->getType(), Unit);
}

llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
llvm::Value *Storage,
std::optional<unsigned> ArgNo,
Expand All @@ -4922,7 +4888,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
if (isa<DeclRefExpr>(BD->getBinding()))
return nullptr;

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

// If there is no debug info for this type then do not emit debug info
// for this variable.
Expand All @@ -4948,7 +4915,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
unsigned Column = getColumnNumber(BD->getLocation());
StringRef Name = BD->getName();
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
// Create the descriptor for the variable.
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize,
Expand All @@ -4962,13 +4928,29 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
const ASTRecordLayout &layout =
CGM.getContext().getASTRecordLayout(parent);
const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex);

if (fieldOffset != 0) {
// Currently if the field offset is not a multiple of byte, the produced
// location would not be accurate. Therefore give up.
if (fieldOffset % CGM.getContext().getCharWidth() != 0)
return nullptr;

if (FD->isBitField()) {
const CGRecordLayout &RL =
CGM.getTypes().getCGRecordLayout(FD->getParent());
const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
// Use DW_OP_plus_uconst to adjust to the start of the bitfield
// storage.
if (!Info.StorageOffset.isZero()) {
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
Expr.push_back(Info.StorageOffset.getQuantity());
}
// Use LLVM_extract_bits to extract the appropriate bits from this
// bitfield.
Expr.push_back(Info.IsSigned
? llvm::dwarf::DW_OP_LLVM_extract_bits_sext
: llvm::dwarf::DW_OP_LLVM_extract_bits_zext);
Expr.push_back(Info.Offset);
// If we have an oversized bitfield then the value won't be more than
// the size of the type.
const uint64_t TypeSize = CGM.getContext().getTypeSize(BD->getType());
Expr.push_back(std::min((uint64_t)Info.Size, TypeSize));
} else if (fieldOffset != 0) {
assert(fieldOffset % CGM.getContext().getCharWidth() == 0 &&
"Unexpected non-bitfield with non-byte-aligned offset");
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
Expr.push_back(
CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity());
Expand Down
3 changes: 0 additions & 3 deletions clang/lib/CodeGen/CGDebugInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -338,9 +338,6 @@ class CGDebugInfo {
llvm::DIScope *RecordTy,
const RecordDecl *RD);

/// Create type for binding declarations.
llvm::DIType *CreateBindingDeclType(const BindingDecl *BD);

/// Create an anonnymous zero-size separator for bit-field-decl if needed on
/// the target.
llvm::DIDerivedType *createBitFieldSeparatorIfNeeded(
Expand Down
Loading
Loading