Skip to content

Allow 128-bit discriminants in DWARF variants #125578

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 1 commit into from
Feb 4, 2025
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
64 changes: 39 additions & 25 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,42 @@ void DwarfUnit::addUInt(DIEValueList &Block, dwarf::Form Form,
addUInt(Block, (dwarf::Attribute)0, Form, Integer);
}

void DwarfUnit::addIntAsBlock(DIE &Die, dwarf::Attribute Attribute, const APInt &Val) {
DIEBlock *Block = new (DIEValueAllocator) DIEBlock;

// Get the raw data form of the large APInt.
const uint64_t *Ptr64 = Val.getRawData();

int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte.
bool LittleEndian = Asm->getDataLayout().isLittleEndian();

// Output the constant to DWARF one byte at a time.
for (int i = 0; i < NumBytes; i++) {
uint8_t c;
if (LittleEndian)
c = Ptr64[i / 8] >> (8 * (i & 7));
else
c = Ptr64[(NumBytes - 1 - i) / 8] >> (8 * ((NumBytes - 1 - i) & 7));
addUInt(*Block, dwarf::DW_FORM_data1, c);
}

addBlock(Die, Attribute, Block);
}

void DwarfUnit::addInt(DIE &Die, dwarf::Attribute Attribute,
const APInt &Val, bool Unsigned) {
unsigned CIBitWidth = Val.getBitWidth();
if (CIBitWidth <= 64) {
if (Unsigned)
addUInt(Die, Attribute, std::nullopt, Val.getZExtValue());
else
addSInt(Die, Attribute, std::nullopt, Val.getSExtValue());
return;
}

addIntAsBlock(Die, Attribute, Val);
}

void DwarfUnit::addSInt(DIEValueList &Die, dwarf::Attribute Attribute,
std::optional<dwarf::Form> Form, int64_t Integer) {
if (!Form)
Expand Down Expand Up @@ -484,25 +520,7 @@ void DwarfUnit::addConstantValue(DIE &Die, const APInt &Val, bool Unsigned) {
return;
}

DIEBlock *Block = new (DIEValueAllocator) DIEBlock;

// Get the raw data form of the large APInt.
const uint64_t *Ptr64 = Val.getRawData();

int NumBytes = Val.getBitWidth() / 8; // 8 bits per byte.
bool LittleEndian = Asm->getDataLayout().isLittleEndian();

// Output the constant to DWARF one byte at a time.
for (int i = 0; i < NumBytes; i++) {
uint8_t c;
if (LittleEndian)
c = Ptr64[i / 8] >> (8 * (i & 7));
else
c = Ptr64[(NumBytes - 1 - i) / 8] >> (8 * ((NumBytes - 1 - i) & 7));
addUInt(*Block, dwarf::DW_FORM_data1, c);
}

addBlock(Die, dwarf::DW_AT_const_value, Block);
addIntAsBlock(Die, dwarf::DW_AT_const_value, Val);
}

void DwarfUnit::addLinkageName(DIE &Die, StringRef LinkageName) {
Expand Down Expand Up @@ -972,12 +990,8 @@ void DwarfUnit::constructTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
DIE &Variant = createAndAddDIE(dwarf::DW_TAG_variant, Buffer);
if (const ConstantInt *CI =
dyn_cast_or_null<ConstantInt>(DDTy->getDiscriminantValue())) {
if (DD->isUnsignedDIType(Discriminator->getBaseType()))
addUInt(Variant, dwarf::DW_AT_discr_value, std::nullopt,
CI->getZExtValue());
else
addSInt(Variant, dwarf::DW_AT_discr_value, std::nullopt,
CI->getSExtValue());
addInt(Variant, dwarf::DW_AT_discr_value, CI->getValue(),
DD->isUnsignedDIType(Discriminator->getBaseType()));
}
constructMemberDIE(Variant, DDTy);
} else {
Expand Down
8 changes: 8 additions & 0 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class DwarfUnit : public DIEUnit {

void addSInt(DIELoc &Die, std::optional<dwarf::Form> Form, int64_t Integer);

/// Add an integer attribute data and value; value may be any width.
void addInt(DIE &Die, dwarf::Attribute Attribute, const APInt &Integer,
bool Unsigned);

/// Add a string attribute data and value.
///
/// We always emit a reference to the string pool instead of immediate
Expand Down Expand Up @@ -334,6 +338,10 @@ class DwarfUnit : public DIEUnit {
void emitCommonHeader(bool UseOffsets, dwarf::UnitType UT);

private:
/// A helper to add a wide integer constant to a DIE using a block
/// form.
void addIntAsBlock(DIE &Die, dwarf::Attribute Attribute, const APInt &Val);

void constructTypeDIE(DIE &Buffer, const DIBasicType *BTy);
void constructTypeDIE(DIE &Buffer, const DIStringType *BTy);
void constructTypeDIE(DIE &Buffer, const DIDerivedType *DTy);
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/DebugInfo/Generic/discriminated-union.ll
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
; CHECK: DW_AT_alignment
; CHECK: DW_AT_data_member_location [DW_FORM_data1] (0x00)
; CHECK: DW_TAG_variant
; CHECK: DW_AT_discr_value [DW_FORM_data1] (0x00)
; CHECK: DW_AT_discr_value [DW_FORM_block1] (<0x10> 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 )
; CHECK: DW_TAG_member
; CHECK: DW_AT_type
; CHECK: DW_AT_alignment
Expand Down Expand Up @@ -71,7 +71,7 @@ attributes #0 = { nounwind uwtable }
!21 = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned)
!22 = !DIDerivedType(tag: DW_TAG_member, name: "__1", scope: !18, file: !7, baseType: !23, size: 64, align: 64)
!23 = !DIDerivedType(tag: DW_TAG_pointer_type, name: "&u8", baseType: !21, size: 64, align: 64)
!24 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !25, size: 128, align: 64, extraData: i64 0)
!24 = !DIDerivedType(tag: DW_TAG_member, scope: !14, file: !7, baseType: !25, size: 128, align: 64, extraData: i128 18446744073709551616)
!25 = !DICompositeType(tag: DW_TAG_structure_type, name: "Nope", scope: !12, file: !7, size: 128, align: 64, elements: !4, identifier: "7ce1efff6b82281ab9ceb730566e7e20::Nope")
!27 = !DIBasicType(name: "u64", size: 64, encoding: DW_ATE_unsigned)
!28 = !DIExpression()
Expand Down