Issue 250504.1: Composite Location Generalization

Author: Ron Brender
Champion: Ron Brender
Date submitted: 2025-05-04
Date revised: 2025-10-13
Date closed:
Type: Enhancement
Status: Open
DWARF version: 6

This proposal is designed to provide substantially the same functionality as the proposal in Issue 250408.1, “Replace Composite Locations & DW_OP_overlay with mapping lists”. The major change is to recast it into the syntactic framework of composite and piece operations. However, this does impose some limitations that are inherent in the concept of composite locations.

The primary limitation of this proposal is that there is no way to provide an implicit "interior" piece that maps every location of the piece to itself, the composite address space concept, every piece must be explicitly defined. It also lacks the ability to describe unrelated pieces (mappings) independently of each other, which allows substantial space savings.

This proposal is based on the text for (new) Section 3.12 found in Issue 230524.1 as of 2025-09-25. Highlighted text indicates changes relative to that text. Change indications in that text relative to Version 5 are omitted.

Proposal

Replace (new) Section 3.12 Composite Locations in total with the following:

2.6.1.2 in V5 3.12 Composite Locations

A composite location represents the location of an object or value that does not exist in a single block of contiguous storage (e.g., as the result of compiler optimization where part of the object is promoted to a register). It consists of a (possibly empty) sequence of pieces, where each piece maps a fixed range of bits from the object onto a corresponding range of bits at a new (sub-)location.

The pieces of a composite location are contiguous, so that the size of the composite storage is the sum of the sizes of the individual pieces, and each piece covers a range of bits immediately following the previous piece. A composite location has the same address space as the object or value it describes, possibly the default address space.

The maximum size of a block of composite storage is, therefore, the size of the largest address space or register.

Typically, the size of a composite storage is the same as that of the object it describes. If the composite storage is smaller than the object, the remaining bits of the object are treated as undefined.

In the process of fetching a value from a composite location, the consumer may need to fetch and assemble bits from more than one piece.

The following operation is used to form a new, empty, composite location:

  1. DW_OP_composite_stk
    The DW_OP_composite_stk operator has no one stack operands., which specifies the first location where pieces will be inserted. The operation pops the location from the stack, It pushes a new, empty, composite location onto the stack, with an the offset of 0 equal to that of the operand. It also establishes the implicit initial and final pieces that are part of every composite, both before and after, respectively, the pieces specified by piece operations.

    The initial implicit piece extends from offset 0 to the offset of the new composite location. The final implicit piece extends from the offset of the new composite to the size of the composite address space.

    The implicit initial piece is used to map any location that precedes the object or value to itself. The implicit final piece is used to map any location that follows the object or value to itself. This latter property is especially valuable for describing vectors of indefinite size.

    This operator is provided so that a new series of piece operations can be started to form a composite location when the state of the stack is unknown (e.g., following a DW_OP_call* operation), or when a new composite is to be started (e.g., rather than add to a previous composite location on the stack).

    A new DW_OP_composite_stk operation is required to start each and every new composite location.

The following operations are used to build a composite location in storage order, one piece at a time. Each piece operation expects a sub-location, L, at the top of the stack, and the composite location under construction, C, in the preceding element on the stack. It pops those two locations and extends the non-implicit pieces of C by adding a new piece that maps the given number of bytes or bits to the sub-location L. The offset of the new location within C is the same as that of C the implicit final piece, whose offset is increased and whose size is then decreased by the number of bytes or bits added. The new composite location is pushed onto the stack.

  1. DW_OP_piece_stk
    The DW_OP_piece_stk operation takes a single operand, which is an unsigned LEB128 number. The number describes the size, in bytes, of the piece of the object to be appended added to the composite C.

    If the sub-location L is a register location, but the piece does not occupy the entire register, the placement of the piece within that register is defined by the ABI.

  2. DW_OP_bit_piece_stk
    The DW_OP_bit_piece_stk operation takes two operands. The first is an unsigned LEB128 number N that gives the size, in bits, of the piece to be appended. The second is an unsigned LEB128 number O that gives the offset in bits to be applied to the sub-location L.

    Interpretation of the offset depends on the location. If the location is an undefined location (see Section {undefinedlocations}), the DW_OP_bit_piece_stk operation describes a piece consisting of the given number of bits whose values are undefined, and the offset is ignored. If the location is a memory location (see Section {memorylocationdescriptions}), the DW_OP_bit_piece_stk operation describes a sequence of bits relative to the location whose address is on the top of the DWARF stack using the bit numbering and direction conventions that are appropriate to the current language on the target system. In all other cases, the source of the piece is given by either a register location (see Section {registerlocationdescriptions}) or an implicit value location (see Section {implicitlocationdescriptions}); the offset is from the least significant bit of the source value.

    DW_OP_bit_piece_stk is used instead of DW_OP_piece_stk when the piece to be assembled into a value or assigned to is not byte-sized or is not at the start of a register or addressable unit of memory.

    Whether or not a DW_OP_piece_stk operation is equivalent to any DW_OP_bit_piece_stk operation with an offset of 0 is ABI dependent.

For compatibility with DWARF Version 5 and earlier, the following exceptions apply to the piece operations: the DW_OP_composite operation is defined for use along with DW_OP_piece and DW_OP_bit_piece. The following additional rules apply:`

  • A DW_OP_composite operation pushes a new, empty, composite location on the stack, with an offset of 0. This operation omits the implicit initial and final pieces provided by the DW_OP_composite_stk operation. This operator is provided so that a new series of piece operations can be started to form a DWARF Version 5-compatible composite location when the start of the stack is unknown (e.g. following a DW_OP_call operation), or when a new composite is to be started (e.g., rather than add to a previous composite location.

  • If L is a non-composite location (or convertible to one) and is the only element on the stack, the result is a new composite location with the single piece L (as if DW_OP_composite DW_OP_swap had been processed immediately prior to the piece operation). This rule supports the first piece operation in a DWARF 5 expression.

  • If a piece operation is processed while the stack is empty, a new empty composite and an undefined location are pushed implicitly (as if DW_OP_composite DW_OP_undefined had been processed immediately prior to the piece operation). The result is a composite with a single undefined piece. This rule supports the empty piece operation in DWARF 5 when it is the first piece of a composite.

  • If the top of the stack is a composite location, and is the only element on the stack, an undefined location is pushed implicitly (as if DW_OP_undefined had been processed immediately prior to the piece operation), whereupon the composite on top of the stack is taken as C and the undefined location is L. The result is the addition of an undefined piece to the existing composite location. This rule supports the empty piece operation in DWARF 5 when it is not the first piece of a composite.