Issue 209093
Summary [lldb] DW_OP_bit_piece extracts stack-value fragments but does not assemble them into the composite value
Labels new issue
Assignees
Reporter firmiana402
    LLDB's `DW_OP_bit_piece` extracts the requested bits from the current scalar in place, but neither consumes the source nor appends the extracted fragment to the composite piece buffer.

[DWARF v5 Section 2.6.1.2](https://dwarfstd.org/doc/DWARF5.pdf) describes `DW_OP_piece` and `DW_OP_bit_piece` as composition operations. In particular, `DW_OP_bit_piece` describes a bit range from the preceding location description; for an implicit value or stack value, that range is taken from the least significant bits of the value. In LLVM's [A.2.5.4 DWARF Operation Expressions](https://llvm.org/docs/AMDGPUDwarfExtensionAllowLocationDescriptionOnTheDwarfExpressionStack/AMDGPUDwarfExtensionAllowLocationDescriptionOnTheDwarfExpressionStack.html#a-2-5-4), the "Composite Location Description Operations" subsection also defines `DW_OP_bit_piece` as having the same action as `DW_OP_piece`, except that the created part has a bit size and an applied bit displacement.

The scalar branch violates that composition contract directly in the evaluator: it modifies the source value in place, resets the location-description kind to `Memory`, and finishes without adding a fragment to the composite result.

## Source Evidence

In [`DWARFExpression.cpp`](https://github.com/llvm/llvm-project/blob/main/lldb/source/_expression_/DWARFExpression.cpp), `Evaluate_DW_OP_piece` consumes the current source fragment, updates it according to the current location-description kind, and appends it to `eval_ctx.pieces`. That creates an accumulated composite result.

The `DW_OP_bit_piece` handler does not follow the same composite contract for scalar sources. It updates the current top-of-stack value in place:

```cpp
case DW_OP_bit_piece:
  ...
 UpdateValueTypeFromLocationDescription(eval_ctx, eval_ctx.loc_desc_kind,
 &stack.back());
 eval_ctx.loc_desc_kind = Memory;
  ...
  case Value::ValueType::Scalar: {
 if (!stack.back().GetScalar().ExtractBitfield(piece_bit_size,
 piece_bit_offset)) {
      ...
 }
  } break;
```

That path does not pop the consumed fragment or append anything to `eval_ctx.pieces`. This differs from `Evaluate_DW_OP_piece`, which consumes the source and appends the resulting fragment to the accumulated composite value.

At the end of evaluation, LLDB returns `eval_ctx.pieces` only when the _expression_ stack is empty; otherwise it returns `stack.back()`:

```cpp
if (stack.empty()) {
  if (eval_ctx.pieces.GetBuffer().GetByteSize())
    return eval_ctx.pieces;
 return llvm::createStringError("stack empty after evaluation");
}

UpdateValueTypeFromLocationDescription(eval_ctx, eval_ctx.loc_desc_kind,
 &stack.back());
return stack.back();
```

Because the scalar `DW_OP_bit_piece` path leaves its source on the stack, `stack.empty()` is false and the evaluator returns that source after interpreting it with the reset `Memory` location kind. The extracted fragment is therefore returned as a memory location instead of becoming part of `eval_ctx.pieces`.
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to