[clang] [llvm] [DebugInfo] Use DW_op_bit_piece for structured bindings of bitfields (PR #85665)
John Brawn via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 18 10:04:47 PDT 2024
https://github.com/john-brawn-arm created https://github.com/llvm/llvm-project/pull/85665
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. Using DW_op_bit_piece means we can handle any offset and size.
>From 665d4034a1428d9b5cf1c4d4e89a16fa00b94fb5 Mon Sep 17 00:00:00 2001
From: John Brawn <john.brawn at arm.com>
Date: Thu, 14 Mar 2024 16:17:03 +0000
Subject: [PATCH] [DebugInfo] Use DW_op_bit_piece for 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. Using
DW_op_bit_piece means we can handle any offset and size.
---
clang/lib/CodeGen/CGDebugInfo.cpp | 52 ++------
clang/lib/CodeGen/CGDebugInfo.h | 3 -
...debug-info-structured-binding-bitfield.cpp | 118 +++++++++---------
.../CodeGen/AsmPrinter/DwarfExpression.cpp | 3 +
llvm/lib/IR/DebugInfoMetadata.cpp | 2 +
5 files changed, 70 insertions(+), 108 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index c2c01439f2dc99..bf142bdbbe0f99 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -4777,40 +4777,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,
@@ -4825,7 +4791,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.
@@ -4851,7 +4818,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,
@@ -4865,13 +4831,13 @@ 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()) {
+ Expr.push_back(llvm::dwarf::DW_OP_bit_piece);
+ Expr.push_back(FD->getBitWidthValue(CGM.getContext()));
+ Expr.push_back(fieldOffset);
+ } 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());
diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h
index 7b60e94555d060..af58ccdb5b35d2 100644
--- a/clang/lib/CodeGen/CGDebugInfo.h
+++ b/clang/lib/CodeGen/CGDebugInfo.h
@@ -337,9 +337,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(
diff --git a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp
index d9f5e3eacac37d..0cecf74c4bc6f9 100644
--- a/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp
+++ b/clang/test/CodeGenCXX/debug-info-structured-binding-bitfield.cpp
@@ -8,8 +8,8 @@ struct S0 {
// CHECK-LABEL: define dso_local void @_Z3fS0v
// CHECK: alloca %struct.S0, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S0, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S0_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S0_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 2))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S0_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S0_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 16))
//
void fS0() {
S0 s0;
@@ -24,8 +24,8 @@ struct S1 {
// CHECK-LABEL: define dso_local void @_Z3fS1v
// CHECK: alloca %struct.S1, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S1, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S1_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S1_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 2))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S1_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S1_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 16))
//
void fS1() {
S1 s1;
@@ -40,8 +40,8 @@ struct S2 {
// CHECK-LABEL: define dso_local void @_Z3fS2v
// CHECK: alloca %struct.S2, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S2, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S2_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S2_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 1))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S2_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S2_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 8))
//
void fS2() {
S2 s2;
@@ -56,8 +56,8 @@ struct S3 {
// CHECK-LABEL: define dso_local void @_Z3fS3v
// CHECK: alloca %struct.S3, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S3, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S3_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S3_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 1))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S3_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S3_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 8))
//
void fS3() {
S3 s3;
@@ -72,8 +72,8 @@ struct S4 {
// CHECK-LABEL: define dso_local void @_Z3fS4v
// CHECK: alloca %struct.S4, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S4, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S4_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S4_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 1))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S4_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S4_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 8))
//
void fS4() {
S4 s4;
@@ -88,8 +88,8 @@ struct S5 {
// CHECK-LABEL: define dso_local void @_Z3fS5v
// CHECK: alloca %struct.S5, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S5, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S5_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S5_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 1))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S5_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S5_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 8))
//
void fS5() {
S5 s5;
@@ -104,8 +104,8 @@ struct S6 {
// CHECK-LABEL: define dso_local void @_Z3fS6v
// CHECK: alloca %struct.S6, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S6, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S6_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S6_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 2))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S6_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S6_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 16))
//
void fS6() {
S6 s6;
@@ -120,8 +120,8 @@ struct S7 {
// CHECK-LABEL: define dso_local void @_Z3fS7v
// CHECK: alloca %struct.S7, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S7, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S7_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S7_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 2))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S7_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S7_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 16))
//
void fS7() {
S7 s7;
@@ -136,8 +136,8 @@ struct S8 {
// CHECK-LABEL: define dso_local void @_Z3fS8v
// CHECK: alloca %struct.S8, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S8, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S8_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S8_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 2))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S8_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S8_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 16))
//
void fS8() {
S8 s8;
@@ -152,8 +152,8 @@ struct S9 {
// CHECK-LABEL: define dso_local void @_Z3fS9v
// CHECK: alloca %struct.S9, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S9, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S9_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S9_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 4))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S9_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S9_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 32, 32))
//
void fS9() {
S9 s9;
@@ -167,8 +167,8 @@ struct S10 {
// CHECK-LABEL: define dso_local void @_Z4fS10v
// CHECK: alloca %struct.S10, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S10, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S10_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S10_B:![0-9]+]], metadata !DIExpression(DW_OP_plus_uconst, 1))
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S10_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S10_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 8, 8))
//
S10() : x(0), y(0) {}
};
@@ -178,9 +178,6 @@ void fS10() {
auto [a, b] = s10;
}
-// It's currently not possible to produce complete debug information for the following cases.
-// Confirm that no wrong debug info is output.
-// Once this is implemented, these tests should be amended.
struct S11 {
unsigned int x : 15;
unsigned int y : 16;
@@ -189,7 +186,8 @@ struct S11 {
// CHECK-LABEL: define dso_local void @_Z4fS11v
// CHECK: alloca %struct.S11, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S11, align 4
-// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]]
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S11_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 15, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S11_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 15))
//
void fS11() {
S11 s11;
@@ -204,8 +202,8 @@ struct S12 {
// CHECK-LABEL: define dso_local void @_Z4fS12v
// CHECK: alloca %struct.S12, align 4
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S12, align 4
-// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_A:![0-9]+]], metadata !DIExpression())
-// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]]
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S12_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 17, 32))
//
void fS12() {
S12 s12;
@@ -220,7 +218,8 @@ struct __attribute__((packed)) S13 {
// CHECK-LABEL: define dso_local void @_Z4fS13v
// CHECK: alloca %struct.S13, align 1
// CHECK-NEXT: [[TMP0:%.*]] = alloca %struct.S13, align 1
-// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr [[TMP0]]
+// CHECK: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S13_A:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 15, 0))
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[TMP0]], metadata [[S13_B:![0-9]+]], metadata !DIExpression(DW_OP_bit_piece, 16, 15))
//
void fS13() {
S13 s13;
@@ -228,55 +227,50 @@ void fS13() {
}
// CHECK: [[UINT_TY:![0-9]+]] = !DIBasicType(name: "unsigned int", size: 32, encoding: DW_ATE_unsigned)
-// CHECK: [[S0_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY:![0-9]+]])
-// CHECK: [[USHORT_TY]] = !DIBasicType(name: "unsigned short", size: 16, encoding: DW_ATE_unsigned)
-// CHECK: [[S0_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
+// CHECK: [[S0_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S0_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
// CHECK: [[VOLATILE_UINT_TY:![0-9]+]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: [[UINT_TY]])
-// CHECK: [[S1_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_USHORT_TY:![0-9]+]])
-// CHECK: [[VOLATILE_USHORT_TY]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: [[USHORT_TY]])
-// CHECK: [[S1_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_USHORT_TY]])
+// CHECK: [[S1_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY:![0-9]+]])
+// CHECK: [[S1_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
-// CHECK: [[S2_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UCHAR_TY:![0-9]+]])
-// CHECK: [[UCHAR_TY]] = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
-// CHECK: [[S2_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UCHAR_TY]])
+// CHECK: [[S2_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S2_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
-// CHECK: [[S3_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UCHAR_TY:![0-9]+]])
-// CHECK: [[VOLATILE_UCHAR_TY]] = !DIDerivedType(tag: DW_TAG_volatile_type, baseType: [[UCHAR_TY]])
-// CHECK: [[S3_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UCHAR_TY]])
+// CHECK: [[S3_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
+// CHECK: [[S3_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
-// CHECK: [[S4_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UCHAR_TY]])
-// CHECK: [[S4_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
+// CHECK: [[S4_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S4_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
-// CHECK: [[S5_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UCHAR_TY]])
-// CHECK: [[S5_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_USHORT_TY]])
+// CHECK: [[S5_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
+// CHECK: [[S5_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
-// CHECK: [[S6_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
-// CHECK: [[S6_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UCHAR_TY]])
+// CHECK: [[S6_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S6_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
-// CHECK: [[S7_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_USHORT_TY]])
-// CHECK: [[S7_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UCHAR_TY]])
+// CHECK: [[S7_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
+// CHECK: [[S7_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
-// CHECK: [[S8_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
-// CHECK: [[S8_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_USHORT_TY]])
+// CHECK: [[S8_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S8_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[VOLATILE_UINT_TY]])
-// CHECK: [[S9_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
+// CHECK: [[S9_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
// CHECK: [[S9_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
// CHECK: [[CONST_UINT_TY:![0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[UINT_TY]])
-// CHECK: [[S10_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[CONST_UCHAR_TY:![0-9]+]])
-// CHECK: [[CONST_UCHAR_TY]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[UCHAR_TY]])
-// CHECK: [[S10_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[CONST_VOLATILE_UCHAR_TY:![0-9]+]])
-// CHECK: [[CONST_VOLATILE_UCHAR_TY]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[VOLATILE_UCHAR_TY]])
+// CHECK: [[CONST_VOLATILE_UINT_TY:![0-9]+]] = !DIDerivedType(tag: DW_TAG_const_type, baseType: [[VOLATILE_UINT_TY]])
+// CHECK: [[S10_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[CONST_UINT_TY]])
+// CHECK: [[S10_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[CONST_VOLATILE_UINT_TY]])
// S11
-// CHECK-NOT: !DILocalVariable(name: "a"
-// CHECK-NOT: !DILocalVariable(name: "b"
+// CHECK: [[S11_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S11_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
// S12
-// CHECK: [[S12_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[USHORT_TY]])
-// CHECK-NOT: !DILocalVariable(name: "b"
+// CHECK: [[S12_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S12_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
// S13
-// CHECK-NOT: !DILocalVariable(name: "a"
-// CHECK-NOT: !DILocalVariable(name: "b"
\ No newline at end of file
+// CHECK: [[S13_A]] = !DILocalVariable(name: "a", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
+// CHECK: [[S13_B]] = !DILocalVariable(name: "b", scope: {{.*}}, file: {{.*}}, line: {{.*}}, type: [[UINT_TY]])
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
index a74d43897d45b3..5a54c4b761a65e 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfExpression.cpp
@@ -645,6 +645,9 @@ bool DwarfExpression::addExpression(
emitUnsigned(Op->getArg(0));
emitSigned(Op->getArg(1));
break;
+ case dwarf::DW_OP_bit_piece:
+ addOpPiece(Op->getArg(0), Op->getArg(1));
+ break;
default:
llvm_unreachable("unhandled opcode found in expression");
}
diff --git a/llvm/lib/IR/DebugInfoMetadata.cpp b/llvm/lib/IR/DebugInfoMetadata.cpp
index f37add2120f13b..28d8c45c43167a 100644
--- a/llvm/lib/IR/DebugInfoMetadata.cpp
+++ b/llvm/lib/IR/DebugInfoMetadata.cpp
@@ -1395,6 +1395,7 @@ unsigned DIExpression::ExprOperand::getSize() const {
case dwarf::DW_OP_LLVM_convert:
case dwarf::DW_OP_LLVM_fragment:
case dwarf::DW_OP_bregx:
+ case dwarf::DW_OP_bit_piece:
return 3;
case dwarf::DW_OP_constu:
case dwarf::DW_OP_consts:
@@ -1494,6 +1495,7 @@ bool DIExpression::isValid() const {
case dwarf::DW_OP_ge:
case dwarf::DW_OP_lt:
case dwarf::DW_OP_le:
+ case dwarf::DW_OP_bit_piece:
break;
}
}
More information about the cfe-commits
mailing list