================
@@ -3251,10 +3252,39 @@ void DwarfDebug::emitDebugLocValue(const AsmPrinter
&AP, const DIBasicType *BT,
&AP](const DbgValueLocEntry &Entry,
DIExpressionCursor &Cursor) -> bool {
if (Entry.isInt()) {
- if (BT && (BT->getEncoding() == dwarf::DW_ATE_boolean))
+ if (BT && (BT->getEncoding() == dwarf::DW_ATE_boolean)) {
DwarfExpr.addBooleanConstant(Entry.getInt());
- else if (BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
- BT->getEncoding() == dwarf::DW_ATE_signed_char))
+ return true;
+ }
+
+ bool IsSigned = BT && (BT->getEncoding() == dwarf::DW_ATE_signed ||
+ BT->getEncoding() == dwarf::DW_ATE_signed_char);
+ if (BT && AP.getDwarfVersion() >= 4 &&
+ !AP.getDwarfDebug()->tuneForSCE() && !Cursor) {
+ // DW_OP_const* pushes a generic, address-sized value. For a wider
+ // source integer value that cannot fit in the generic type, use
+ // DW_OP_implicit_value to preserve the source bytes instead. Keep this
+ // limited to complete constant values: SCE tuning already avoids
+ // DW_OP_implicit_value for compatibility, and expressions with
+ // remaining operations may need a scalar stack value rather than an
+ // implicit value block.
+ unsigned GenericBitSize = AP.MAI.getCodePointerSize() * 8;
+ uint64_t TypeBitSize = BT->getSizeInBits();
+ bool IsByteSized = TypeBitSize % 8 == 0;
+ bool IsOutOfRange =
+ IsSigned ? !isIntN(GenericBitSize, Entry.getInt())
+ : !isUIntN(GenericBitSize,
+ static_cast<uint64_t>(Entry.getInt()));
+ if (TypeBitSize > GenericBitSize && IsByteSized && IsOutOfRange) {
+ DwarfExpr.addImplicitValue(
+ APInt(static_cast<unsigned>(TypeBitSize),
+ static_cast<uint64_t>(Entry.getInt()), IsSigned),
----------------
firmiana402 wrote:
Thanks for the reproducer. I can reproduce the assertion locally.
One thing I noticed is that the debug info in the reduced test case looks
inconsistent: the type name is `_BitInt(48)`, which is signed in C unless
written as `unsigned _BitInt(48)`, but the `DIBasicType` uses
`DW_ATE_unsigned`. If the type were marked as signed, this particular assertion
would likely not trigger, because `-4294967296` is representable as a signed
48-bit value.
That said, the reproducer does expose a real robustness issue in my patch. As I
mentioned earlier, a variable of some basic type can be assigned a constant
whose carrier value contains bits outside the representable range of that type.
In practice, when emitting source-sized `DW_OP_implicit_value` bytes, that
value should be wrapped/truncated to the declared basic type width instead of
asserting in `APInt`.
The fix should be small: construct the source-width `APInt` with explicit
truncation enabled when building the implicit value. That should also handle
this reproducer by truncating the `int64_t` debug-value carrier to the declared
type width before emitting the bytes.
Since the original PR has already landed, would you like me to open a small
follow-up PR for this with a regression test based on your reproducer?
https://github.com/llvm/llvm-project/pull/204353
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits