| 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