[clang] [llvm] [DebugInfo] Fix endianness in DW_AT_const_value for constexpr arrays (PR #184804)
Shivam Kunwar via cfe-commits
cfe-commits at lists.llvm.org
Thu Mar 5 20:55:27 PST 2026
https://github.com/phyBrackets updated https://github.com/llvm/llvm-project/pull/184804
>From 94218e0815c4552e3ff9949e752f18aeb16bdd08 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Fri, 20 Feb 2026 11:51:31 +0530
Subject: [PATCH 1/5] [DebugInfo] Emit DW_AT_const_value for constexpr array
static members
---
clang/lib/CodeGen/CGDebugInfo.cpp | 47 ++++++++++++
.../CodeGenCXX/debug-info-constexpr-array.cpp | 23 ++++++
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 11 ++-
.../X86/debug-info-constexpr-array.ll | 73 +++++++++++++++++++
4 files changed, 153 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CodeGenCXX/debug-info-constexpr-array.cpp
create mode 100644 llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 5e452245ee627..951cb3d6b5b7e 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2092,6 +2092,53 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
if (Value->isFloat())
C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
+ if (Value->isArray()) {
+ // Handle constexpr array constants for debug info
+ // We handle arrays of integer types (char, short, int, long),
+ // which covers the most common and useful cases.
+ if (const auto *ArrayTy =
+ CGM.getContext().getAsArrayType(Var->getType())) {
+ QualType ElemQTy = ArrayTy->getElementType();
+ if (ElemQTy->isIntegerType()) {
+ unsigned ElemBitWidth = CGM.getContext().getTypeSize(ElemQTy);
+ unsigned NumElts = Value->getArraySize();
+ unsigned NumInits = Value->getArrayInitializedElts();
+ SmallVector<uint64_t, 64> Vals;
+ Vals.reserve(NumElts);
+ bool Success = true;
+ for (unsigned I = 0; I < NumInits && Success; ++I) {
+ const APValue &Elt = Value->getArrayInitializedElt(I);
+ if (Elt.isInt())
+ Vals.push_back(Elt.getInt().getZExtValue());
+ else
+ Success = false;
+ }
+ // Fill remaining elements with the filler value (e.g., the
+ // null terminator region for strings).
+ if (Success && NumInits < NumElts) {
+ const APValue &Filler = Value->getArrayFiller();
+ if (Filler.isInt())
+ Vals.resize(NumElts, Filler.getInt().getZExtValue());
+ else
+ Success = false;
+ }
+ if (Success && Vals.size() == NumElts) {
+ if (ElemBitWidth == 8) {
+ SmallVector<uint8_t, 64> Bytes(Vals.begin(), Vals.end());
+ C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Bytes);
+ } else if (ElemBitWidth == 16) {
+ SmallVector<uint16_t, 64> Elts(Vals.begin(), Vals.end());
+ C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
+ } else if (ElemBitWidth == 32) {
+ SmallVector<uint32_t, 32> Elts(Vals.begin(), Vals.end());
+ C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
+ } else if (ElemBitWidth == 64) {
+ C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Vals);
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/clang/test/CodeGenCXX/debug-info-constexpr-array.cpp b/clang/test/CodeGenCXX/debug-info-constexpr-array.cpp
new file mode 100644
index 0000000000000..289eb9f7e7a9c
--- /dev/null
+++ b/clang/test/CodeGenCXX/debug-info-constexpr-array.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++17 -emit-llvm \
+// RUN: -debug-info-kind=standalone -o - %s | FileCheck %s
+
+struct Test {
+ static inline constexpr char STR[] = "Hello";
+ static inline constexpr int NUMS[] = {1, 2, 3};
+ static inline constexpr unsigned char BYTES[] = {0xDE, 0xAD};
+};
+
+void use() {
+ (void)Test::STR;
+ (void)Test::NUMS;
+ (void)Test::BYTES;
+}
+
+// "Hello\0" as [6 x i8]
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "STR"{{.*}}extraData: [6 x i8] c"Hello\00"
+
+// {1, 2, 3} as [3 x i32]
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "NUMS"{{.*}}extraData: [3 x i32] [i32 1, i32 2, i32 3]
+
+// {0xDE, 0xAD} as [2 x i8]
+// CHECK-DAG: !DIDerivedType(tag: DW_TAG_member, name: "BYTES"{{.*}}extraData: [2 x i8] c"\DE\AD"
\ No newline at end of file
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index baffd81b4f336..d3a03429f82f4 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -2036,8 +2036,17 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
if (const ConstantInt *CI = dyn_cast_or_null<ConstantInt>(DT->getConstant()))
addConstantValue(StaticMemberDIE, CI, Ty);
- if (const ConstantFP *CFP = dyn_cast_or_null<ConstantFP>(DT->getConstant()))
+ else if (const ConstantFP *CFP =
+ dyn_cast_or_null<ConstantFP>(DT->getConstant()))
addConstantFPValue(StaticMemberDIE, CFP);
+ else if (auto *CDS =
+ dyn_cast_or_null<ConstantDataSequential>(DT->getConstant())) {
+ StringRef RawData = CDS->getRawDataValues();
+ auto *Block = new (DIEValueAllocator) DIEBlock;
+ for (unsigned char Byte : RawData)
+ addUInt(*Block, dwarf::DW_FORM_data1, Byte);
+ addBlock(StaticMemberDIE, dwarf::DW_AT_const_value, Block);
+ }
if (uint32_t AlignInBytes = DT->getAlignInBytes())
addUInt(StaticMemberDIE, dwarf::DW_AT_alignment, dwarf::DW_FORM_udata,
diff --git a/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll b/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
new file mode 100644
index 0000000000000..ef699f7e8a6c1
--- /dev/null
+++ b/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
@@ -0,0 +1,73 @@
+; RUN: llc -mtriple=x86_64-linux-gnu -filetype=obj %s -o %t.o
+; RUN: llvm-dwarfdump --debug-info %t.o | FileCheck %s
+;
+; Reduced from clang output for:
+; struct Test {
+; static inline constexpr char STR[] = "Hello";
+; static inline constexpr int NUMS[] = {1, 2, 3};
+; static inline constexpr unsigned char BYTES[] = {0xDE, 0xAD};
+; };
+; void use() { (void)Test::STR; (void)Test::NUMS; (void)Test::BYTES; }
+
+; CHECK: DW_TAG_structure_type
+; CHECK: DW_AT_name ("Test")
+;
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name ("STR")
+; CHECK: DW_AT_const_value (<0x06> 48 65 6c 6c 6f 00 )
+;
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name ("NUMS")
+; CHECK: DW_AT_const_value (<0x0c> 01 00 00 00 02 00 00 00 03 00 00 00 )
+;
+; CHECK: DW_TAG_member
+; CHECK: DW_AT_name ("BYTES")
+; CHECK: DW_AT_const_value (<0x02> de ad )
+
+ at _ZN4Test3STRE = linkonce_odr constant [6 x i8] c"Hello\00", align 1, !dbg !0
+ at _ZN4Test4NUMSE = linkonce_odr constant [3 x i32] [i32 1, i32 2, i32 3], align 4, !dbg !5
+ at _ZN4Test5BYTESE = linkonce_odr constant [2 x i8] c"\DE\AD", align 1, !dbg !28
+
+define dso_local void @_Z3usev() !dbg !33 {
+ ret void, !dbg !36
+}
+
+!llvm.dbg.cu = !{!2}
+!llvm.module.flags = !{!30, !31}
+
+!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
+!1 = distinct !DIGlobalVariable(name: "STR", linkageName: "_ZN4Test3STRE", scope: !2, file: !7, line: 5, type: !17, isLocal: false, isDefinition: true, declaration: !16)
+!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false, nameTableKind: None)
+!3 = !DIFile(filename: "test.cpp", directory: "")
+!4 = !{!0, !5, !28}
+!5 = !DIGlobalVariableExpression(var: !6, expr: !DIExpression())
+!6 = distinct !DIGlobalVariable(name: "NUMS", linkageName: "_ZN4Test4NUMSE", scope: !2, file: !7, line: 6, type: !8, isLocal: false, isDefinition: true, declaration: !13)
+!7 = !DIFile(filename: "test.cpp", directory: "")
+!8 = !DICompositeType(tag: DW_TAG_array_type, baseType: !9, size: 96, elements: !11)
+!9 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !10)
+!10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!11 = !{!12}
+!12 = !DISubrange(count: 3)
+!13 = !DIDerivedType(tag: DW_TAG_member, name: "NUMS", scope: !14, file: !7, line: 6, baseType: !8, flags: DIFlagStaticMember, extraData: [3 x i32] [i32 1, i32 2, i32 3])
+!14 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "Test", file: !7, line: 4, size: 8, flags: DIFlagTypePassByValue, elements: !15, identifier: "_ZTS4Test")
+!15 = !{!16, !13, !22}
+!16 = !DIDerivedType(tag: DW_TAG_member, name: "STR", scope: !14, file: !7, line: 5, baseType: !17, flags: DIFlagStaticMember, extraData: [6 x i8] c"Hello\00")
+!17 = !DICompositeType(tag: DW_TAG_array_type, baseType: !18, size: 48, elements: !20)
+!18 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !19)
+!19 = !DIBasicType(name: "char", size: 8, encoding: DW_ATE_signed_char)
+!20 = !{!21}
+!21 = !DISubrange(count: 6)
+!22 = !DIDerivedType(tag: DW_TAG_member, name: "BYTES", scope: !14, file: !7, line: 7, baseType: !23, flags: DIFlagStaticMember, extraData: [2 x i8] c"\DE\AD")
+!23 = !DICompositeType(tag: DW_TAG_array_type, baseType: !24, size: 16, elements: !26)
+!24 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !25)
+!25 = !DIBasicType(name: "unsigned char", size: 8, encoding: DW_ATE_unsigned_char)
+!26 = !{!27}
+!27 = !DISubrange(count: 2)
+!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
+!29 = distinct !DIGlobalVariable(name: "BYTES", linkageName: "_ZN4Test5BYTESE", scope: !2, file: !7, line: 7, type: !23, isLocal: false, isDefinition: true, declaration: !22)
+!30 = !{i32 2, !"Debug Info Version", i32 3}
+!31 = !{i32 1, !"wchar_size", i32 4}
+!33 = distinct !DISubprogram(name: "use", linkageName: "_Z3usev", scope: !7, file: !7, line: 10, type: !34, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2)
+!34 = !DISubroutineType(types: !35)
+!35 = !{null}
+!36 = !DILocation(line: 14, column: 1, scope: !33)
\ No newline at end of file
>From 9201793a108abb73ce115e7d8d18d4aad7a044a2 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Mon, 23 Feb 2026 12:12:16 +0530
Subject: [PATCH 2/5] refactored based on the review comments
---
clang/lib/CodeGen/CGDebugInfo.cpp | 104 ++++++++++--------
.../X86/debug-info-constexpr-array.ll | 10 +-
2 files changed, 58 insertions(+), 56 deletions(-)
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 951cb3d6b5b7e..41903f90a7ddb 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -2070,6 +2070,61 @@ void CGDebugInfo::CollectRecordLambdaFields(
}
}
+/// Try to create an llvm::Constant for a constexpr array of integer elements.
+/// Handles arrays of char, short, int, long with element width up to 64 bits.
+/// Returns nullptr if the array cannot be represented.
+static llvm::Constant *tryEmitConstexprArrayAsConstant(CodeGenModule &CGM,
+ const VarDecl *Var,
+ const APValue *Value) {
+ const auto *ArrayTy = CGM.getContext().getAsConstantArrayType(Var->getType());
+ if (!ArrayTy)
+ return nullptr;
+
+ const QualType ElemQTy = ArrayTy->getElementType();
+ if (ElemQTy.isNull() || !ElemQTy->isIntegerType())
+ return nullptr;
+
+ const unsigned ElemBitWidth = CGM.getContext().getTypeSize(ElemQTy);
+ // ConstantDataArray only supports 8/16/32/64-bit elements, and
+ // getZExtValue() asserts on wider types (e.g. __int128).
+ if (ElemBitWidth > 64)
+ return nullptr;
+
+ const unsigned NumElts = Value->getArraySize();
+ const unsigned NumInits = Value->getArrayInitializedElts();
+
+ // Preallocate with filler value, then overwrite initialized elements.
+ uint64_t FillVal = 0;
+ if (Value->hasArrayFiller()) {
+ const APValue &Filler = Value->getArrayFiller();
+ if (!Filler.isInt())
+ return nullptr;
+ FillVal = Filler.getInt().getZExtValue();
+ }
+
+ SmallVector<uint64_t, 64> Vals(NumElts, FillVal);
+ for (unsigned I = 0; I < NumInits; ++I) {
+ const APValue &Elt = Value->getArrayInitializedElt(I);
+ if (!Elt.isInt())
+ return nullptr;
+ Vals[I] = Elt.getInt().getZExtValue();
+ }
+
+ if (ElemBitWidth == 8) {
+ SmallVector<uint8_t, 64> Bytes(Vals.begin(), Vals.end());
+ return llvm::ConstantDataArray::get(CGM.getLLVMContext(), Bytes);
+ } else if (ElemBitWidth == 16) {
+ SmallVector<uint16_t, 64> Elts(Vals.begin(), Vals.end());
+ return llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
+ } else if (ElemBitWidth == 32) {
+ SmallVector<uint32_t, 32> Elts(Vals.begin(), Vals.end());
+ return llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
+ } else if (ElemBitWidth == 64) {
+ return llvm::ConstantDataArray::get(CGM.getLLVMContext(), Vals);
+ }
+ return nullptr;
+}
+
llvm::DIDerivedType *
CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
const RecordDecl *RD) {
@@ -2092,53 +2147,8 @@ CGDebugInfo::CreateRecordStaticField(const VarDecl *Var, llvm::DIType *RecordTy,
C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value->getInt());
if (Value->isFloat())
C = llvm::ConstantFP::get(CGM.getLLVMContext(), Value->getFloat());
- if (Value->isArray()) {
- // Handle constexpr array constants for debug info
- // We handle arrays of integer types (char, short, int, long),
- // which covers the most common and useful cases.
- if (const auto *ArrayTy =
- CGM.getContext().getAsArrayType(Var->getType())) {
- QualType ElemQTy = ArrayTy->getElementType();
- if (ElemQTy->isIntegerType()) {
- unsigned ElemBitWidth = CGM.getContext().getTypeSize(ElemQTy);
- unsigned NumElts = Value->getArraySize();
- unsigned NumInits = Value->getArrayInitializedElts();
- SmallVector<uint64_t, 64> Vals;
- Vals.reserve(NumElts);
- bool Success = true;
- for (unsigned I = 0; I < NumInits && Success; ++I) {
- const APValue &Elt = Value->getArrayInitializedElt(I);
- if (Elt.isInt())
- Vals.push_back(Elt.getInt().getZExtValue());
- else
- Success = false;
- }
- // Fill remaining elements with the filler value (e.g., the
- // null terminator region for strings).
- if (Success && NumInits < NumElts) {
- const APValue &Filler = Value->getArrayFiller();
- if (Filler.isInt())
- Vals.resize(NumElts, Filler.getInt().getZExtValue());
- else
- Success = false;
- }
- if (Success && Vals.size() == NumElts) {
- if (ElemBitWidth == 8) {
- SmallVector<uint8_t, 64> Bytes(Vals.begin(), Vals.end());
- C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Bytes);
- } else if (ElemBitWidth == 16) {
- SmallVector<uint16_t, 64> Elts(Vals.begin(), Vals.end());
- C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
- } else if (ElemBitWidth == 32) {
- SmallVector<uint32_t, 32> Elts(Vals.begin(), Vals.end());
- C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Elts);
- } else if (ElemBitWidth == 64) {
- C = llvm::ConstantDataArray::get(CGM.getLLVMContext(), Vals);
- }
- }
- }
- }
- }
+ if (Value->isArray())
+ C = tryEmitConstexprArrayAsConstant(CGM, Var, Value);
}
}
diff --git a/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll b/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
index ef699f7e8a6c1..ceffe69a22097 100644
--- a/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
+++ b/llvm/test/DebugInfo/X86/debug-info-constexpr-array.ll
@@ -28,10 +28,6 @@
@_ZN4Test4NUMSE = linkonce_odr constant [3 x i32] [i32 1, i32 2, i32 3], align 4, !dbg !5
@_ZN4Test5BYTESE = linkonce_odr constant [2 x i8] c"\DE\AD", align 1, !dbg !28
-define dso_local void @_Z3usev() !dbg !33 {
- ret void, !dbg !36
-}
-
!llvm.dbg.cu = !{!2}
!llvm.module.flags = !{!30, !31}
@@ -66,8 +62,4 @@ define dso_local void @_Z3usev() !dbg !33 {
!28 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
!29 = distinct !DIGlobalVariable(name: "BYTES", linkageName: "_ZN4Test5BYTESE", scope: !2, file: !7, line: 7, type: !23, isLocal: false, isDefinition: true, declaration: !22)
!30 = !{i32 2, !"Debug Info Version", i32 3}
-!31 = !{i32 1, !"wchar_size", i32 4}
-!33 = distinct !DISubprogram(name: "use", linkageName: "_Z3usev", scope: !7, file: !7, line: 10, type: !34, scopeLine: 10, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !2)
-!34 = !DISubroutineType(types: !35)
-!35 = !{null}
-!36 = !DILocation(line: 14, column: 1, scope: !33)
\ No newline at end of file
+!31 = !{i32 1, !"wchar_size", i32 4}
\ No newline at end of file
>From 1cfbfe77e10de95fdf6401031de263c7519346f8 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Thu, 5 Mar 2026 20:12:16 +0530
Subject: [PATCH 3/5] [DebugInfo] Fix endianness in DW_AT_const_value for
constexpr arrays
---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 71dbcc383c0f7..6344e4a37fcaf 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -2041,10 +2041,22 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
addConstantFPValue(StaticMemberDIE, CFP);
else if (auto *CDS =
dyn_cast_or_null<ConstantDataSequential>(DT->getConstant())) {
- StringRef RawData = CDS->getRawDataValues();
+ // Emit each element byte-by-byte in target byte order. We avoid
+ // getRawDataValues() because it exposes host endianness, which
+ // produces incorrect DWARF on big-endian hosts cross-compiling
+ // for little-endian targets (and vice versa).
auto *Block = new (DIEValueAllocator) DIEBlock;
- for (unsigned char Byte : RawData)
- addUInt(*Block, dwarf::DW_FORM_data1, Byte);
+ unsigned NumElts = CDS->getNumElements();
+ unsigned ElemByteSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8;
+ bool IsLE = Asm->getDataLayout().isLittleEndian();
+ for (unsigned I = 0; I < NumElts; ++I) {
+ APInt Val = CDS->getElementAsAPInt(I);
+ for (unsigned J = 0; J < ElemByteSize; ++J) {
+ unsigned BitOff = IsLE ? (J * 8) : ((ElemByteSize - 1 - J) * 8);
+ addUInt(*Block, dwarf::DW_FORM_data1,
+ Val.extractBitsAsZExtValue(8, BitOff));
+ }
+ }
Block->computeSize(Asm->getDwarfFormParams());
addBlock(StaticMemberDIE, dwarf::DW_AT_const_value, Block->BestForm(),
Block);
>From 0e376f1743db69bc0bcdcf81aee8f4f5a98d49be Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Thu, 5 Mar 2026 20:36:04 +0530
Subject: [PATCH 4/5] use addIntAsBlock
---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 26 +++++++----------------
1 file changed, 8 insertions(+), 18 deletions(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 6344e4a37fcaf..266a78f58d8c2 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -2041,25 +2041,15 @@ DIE *DwarfUnit::getOrCreateStaticMemberDIE(const DIDerivedType *DT) {
addConstantFPValue(StaticMemberDIE, CFP);
else if (auto *CDS =
dyn_cast_or_null<ConstantDataSequential>(DT->getConstant())) {
- // Emit each element byte-by-byte in target byte order. We avoid
- // getRawDataValues() because it exposes host endianness, which
- // produces incorrect DWARF on big-endian hosts cross-compiling
- // for little-endian targets (and vice versa).
- auto *Block = new (DIEValueAllocator) DIEBlock;
+ // Concatenate all array elements into a single APInt and emit using
+ // addIntAsBlock, which handles target endianness correctly.
unsigned NumElts = CDS->getNumElements();
- unsigned ElemByteSize = CDS->getElementType()->getPrimitiveSizeInBits() / 8;
- bool IsLE = Asm->getDataLayout().isLittleEndian();
- for (unsigned I = 0; I < NumElts; ++I) {
- APInt Val = CDS->getElementAsAPInt(I);
- for (unsigned J = 0; J < ElemByteSize; ++J) {
- unsigned BitOff = IsLE ? (J * 8) : ((ElemByteSize - 1 - J) * 8);
- addUInt(*Block, dwarf::DW_FORM_data1,
- Val.extractBitsAsZExtValue(8, BitOff));
- }
- }
- Block->computeSize(Asm->getDwarfFormParams());
- addBlock(StaticMemberDIE, dwarf::DW_AT_const_value, Block->BestForm(),
- Block);
+ unsigned ElemBits = CDS->getElementType()->getPrimitiveSizeInBits();
+ unsigned TotalBits = NumElts * ElemBits;
+ APInt Combined(TotalBits, 0);
+ for (unsigned I = 0; I < NumElts; ++I)
+ Combined.insertBits(CDS->getElementAsAPInt(I), I * ElemBits);
+ addIntAsBlock(StaticMemberDIE, dwarf::DW_AT_const_value, Combined);
}
if (uint32_t AlignInBytes = DT->getAlignInBytes())
>From 9d2270d65c6a2843c8cddce4dd869c9bccb90d0e Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Thu, 5 Mar 2026 21:38:23 +0530
Subject: [PATCH 5/5] Fix addIntAsBlock to call computeSize before BestForm
---
llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
index 266a78f58d8c2..47641136a4e39 100644
--- a/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
@@ -250,7 +250,8 @@ void DwarfUnit::addIntAsBlock(DIE &Die, dwarf::Attribute Attribute, const APInt
addUInt(*Block, dwarf::DW_FORM_data1, c);
}
- addBlock(Die, Attribute, Block);
+ Block->computeSize(Asm->getDwarfFormParams());
+ addBlock(Die, Attribute, Block->BestForm(), Block);
}
void DwarfUnit::addInt(DIE &Die, dwarf::Attribute Attribute,
More information about the cfe-commits
mailing list