Issue 251017.1: Compound Storage as a Generalization of Composite Storage and Multiple Locations

Author: Cary Coutant
Champion:
Date submitted: 2025-10-17
Date revised: 2026-03-12
Date closed:
Type: Enhancement
Status: Open
DWARF version: 6

This proposal depends on Issue 251120.1, “DWARF Operation to Create Runtime Overlay Composite Location Description”.

This proposal was originally titled “Incremental Location Lists Using Overlays,” but has been split into two separate proposals. This proposal covers the concept of compound storage as a generalization of composite storage and multiple locations; Issue 252017.2 covers the idea of using location lists to build up a compound location incrementally.

Background

Composite storage is currently defined as a sequence of contiguous pieces, whose size is the sum of the sizes of those pieces. With Issue 251120.1, composites can be created by new overlay operations, but are still described in terms of contiguous pieces; i.e., an overlay operation might split one large piece into three pieces.

A composite location is typically used to describe the location of a composite object that has been decomposed, such that one or more of its components are located in different storage (e.g., a field promoted to a register). But it can also be used to represent a whole object that is split across several kinds of storage (e.g., a large scalar stored in a register pair).

In addition, an object (or parts of an object) may sometimes need to be described as live in two (or more) locations at the same time, as when it gets promoted to a register but never modified or spilled back to its original location. In such a case, a debugger would need to know about both such locations, so that a user-initiated modification of the object can be written to both. Currently, DWARF can describe this situation using a location list with overlapping bounded location expressions, but few (if any) compilers currently use this feature.

These “multiple locations” are not well integrated into the storage model, and essentially introduce a higher-level concept, where the several locations are described by several independent location expressions. This has the disadvantage that, for a PC range where an object is live in two locations, two location list entries are required, one for each location, even when one of those locations is the same as the default location (because the default location entry is used only when no bounded location list entry matches the current PC). A further disadvantage is that, if a field of a structure (or a slice of an array) is promoted to a register, the location description for the entire structure (or array) must be repeated for each, changing only the sub-location of the one promoted piece.

This proposal removes that higher-level concept, and generalizes composite storage as “compound storage.” Compound storage can describe an aggregate object whose components live in different storage, but can also describe data objects (or components of those objects) that are live in multiple locations at the same time.

The earlier concept of composite storage, built as a series of contiguous pieces, is a special case of compound storage.

A “multiple location” is now created via a new kind of overlay operator that represents a “copy” operation rather than a “move” operation — i.e., when the original location remains live while the data has been promoted to a register, we call it a “copy”; when the original location is dead, we call it a “move”.

As a simple example, consider the location of a variable of a struct type with three 32-bit fields, whose default location is on the stack at offset 0x40 relative to the frame base FB:

+--------------------------+
|    a   |    b   |    c   |  (Memory at FB + 0x40)
+--------------------------+
 +0       +4       +8

DW_AT_location: [ DW_OP_fbreg(0x40) ]

Now suppose that field b is promoted to a register but is not modified while in the register, and therefore never spilled back to the original location. That field of the structure is thus live in both locations while the PC is in the range pc1..pc2. To describe this case, we would use a new DW_OP_overlay_copy operator instead of the “move” operator:

         +--------+
         | b(copy)|           (reg1)
+--------------------------+
|    a   |    b   |    c   |  (Memory at FB + 0x40)
+--------------------------+
 +0       +4       +8

DW_AT_location: <loclist1>

loclist1:
  DW_LLE_start_end(pc1..pc2)
    [
      DW_OP_fbreg(0x40)  # default location
      DW_OP_reg1         # new location
      DW_OP_lit4         # offset
      DW_OP_lit4         # length
      DW_OP_overlay_copy
    ]
  DW_LLE_default_location
    [
      DW_OP_fbreg(0x40)  # default location
    ]

The result of evaluating this expression is a location in compound storage that describes the field b (the 4 bytes starting at offset 4) as located both at FB + 0x44 and in reg1.

For scalars and aggregates that are copied to a new location as a whole, a new DW_OP_copy operation is also added (this could be expressed as a DW_OP_overlay_copy operation, but less succinctly).

Comparison with multiloc storage proposal

With proposal 260227.1, which treats composites and multilocs as two separate storage kinds, you’d have to have either a composite of multilocs, or a multiloc of composites. If you consider the case of a field or array slice being promoted to a register for read-only purposes, that forces you to conceptualize it as either (a) or (b) below, rather than the more natural (c). It's about the model matching the real world: Any of (a), (b), or (c) would work, but (c) is much more natural.

+----------------+--------+----------------+
| memory ...     | reg1   | memory ...     |
+----------------+--------+----------------+
| memory ...                               |
+------------------------------------------+
    (a) multiloc with a composite

+----------------+--------+----------------+
|                | reg1   |                |
|                |--------|                |
| memory ...     | memory | memory ...     |
+----------------+--------+----------------+
    (b) composite with a multiloc

                 +--------+
                 | reg1   |
+----------------+--------+----------------+
| memory ...                               |
+------------------------------------------+
    (c) just another kind of overlay

Proposal

In Section 2.5 Values and Locations, remove the paragraphs about location lists (see below for replacement text):

A location list (see Section 3.19 on page 66), encoded using class loclist, describes objects that have a limited lifetime or that change their location during their lifetime. A location list is a list of location expressions, each associated with a range of program counter values.

A location list may have overlapping PC ranges, and thus may yield multiple locations at a given PC. In this case, the consumer may assume that the object value stored is the same in all locations, excluding bits of the object that serve as padding. Non-padding bits that are undefined (for example, as a result of optimization) must be undefined in all the locations.

A location list that yields multiple locations can be used to describe objects that reside in more than one piece of storage at the same time. An object may have more than one location as a result of optimization. For example, a value that is only read may be promoted from memory to a register for some region of code, but later code may revert to reading the value from memory as the register may be used for other purposes.

At the end of the section, replace the "Composite storage" bullet with the following:

  • Compound storage. A hybrid form of storage where different pieces of a program object map to different locations, as when a field of a structure or a slice of an array is promoted to a register while the rest remains in memory. Compound storage consists of a set of mappings: each mapping covers a piece of the object, defined by a bit range matching the object’s in-memory layout, and maps that piece to a location where the contents of that piece are stored.

    Compound storage is created by pieced composite operations (see Section 3.12.1) and by overlay operations (see Section 3.12.2). The pieced composite operations create a compound storage that consists of a contiguous sequence of non-overlapping mappings. The storage resulting from a piece operation has a size equal to that of the base plus the size of the new piece. Overlay operations create a compound storage where the new mapping is overlaid on top of the base storage. The resulting storage has a size equal to the maximum extent of the base storage and the overlay. If the starting bit offset of the overlay is greater than the size of the base storage, the gap is filled with undefined storage. Pieced composite operations and overlay operations may both be used to form a compound storage.

    Pieced composite operations, if used alone, produce a compound location like the composite locations in earlier versions of DWARF. Legacy composite locations are a special case of compound locations, where the mappings are all contiguous and non-overlapping.

    The size of a block of compound storage may not be larger than the size of the largest memory address space or register.

    Mappings may overlap earlier mappings, and may be either “opaque” or “transparent.” An opaque mapping overrides all earlier mappings of the same bit range, while a transparent mapping represents a location where the corresponding piece of the object is live at both the newly-mapped location and at the location (or locations) mapped earlier. Opaque mappings are created by the DW_OP_overlay operation, while transparent mappings are created by the DW_OP_overlay_copy and DW_OP_copy operations (see Section 3.12.2).

    When an object, or a piece of an object, is live in two or more locations, the consumer may assume that the object value stored is the same in all locations, excluding bits of the object that serve as padding. Non-padding bits that are undefined (for example, as a result of optimization) must be undefined in all the locations. In order to modify the contents of an object, the consumer must write the new value to each of the locations.

After the list of kinds of storage, add the following:

A location list (see Section 3.19 on page 66), encoded using class loclist, describes objects that have a limited lifetime or that change their location during their lifetime. A location list is a list of location expressions, each associated with a range of program counter values.

A location list may have overlapping PC ranges. In previous versions of DWARF, this could yield two or more separate locations for a given PC, and the object was considered live in each of those locations. In DWARF Version 6, a single location with transparent mappings is used to indicate that an object is live in multiple locations.

[For now, we could choose to disallow overlapping PC ranges, or we could say the first matching range is the result. Issue 251017.2, if also passed, would make this moot.]

Rename Section 3.12 from “Composite Locations” to “Compound Locations”.

In Section 3.12, modify the introductory paragraphs as follows:

A compound 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 compound location may overlap. The maximum size of a block of composite storage is the size of the largest address space or register.

Typically, the size of a compound storage is at least as large as the object it describes. If the compound 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 compound location, the consumer may need to fetch and assemble bits from more than one piece.

Compound locations can be formed by two methods: pieced composite operations, which operate as in previous versions of DWARF, and overlay operations.

Rename Section 3.12.1 from “Piece Operations” to “Pieced Composite Operations”.

In Section 3.12.2, “Overlay Operations” (added by Issue 251120.1), add the following operations:

  1. DW_OP_overlay_copy

    The DW_OP_overlay_copy operation works like the DW_OP_overlay operation, except that it creates a multiple location where the region being overlayed remains live in its original (base) location while also being live in the new location.

  2. DW_OP_bit_overlay_copy

    The DW_OP_bit_overlay_copy operation works like the DW_OP_bit_overlay operation, except that it creates a multiple location where the region being overlayed remains live in its original (base) location while also being live in the new location.

  3. DW_OP_copy

    The DW_OP_copy operation consumes the top two elements of the stack. The top-of-stack (first) entry is the location that is being overlayed on the base location. The second from the top element is the base location. These two elements are popped and a new compound location is pushed, which represents a multiple location where the entire data object remains live in both the original (base) location and in the new location.

    DW_OP_copy is equivalent to a DW_OP_overlay_copy operation with an offset of 0 and a width equal to the size of the data object.

In Section 7.7.1 DWARF Expressions, add the following rows to Table 7.9 (all with no operands):


2025-10-23: Revised. Restored original names of the overlay operations in the GPU working group proposal; added DW_OP_copy operation; clarified what text is placeholder from the other proposal and what text is to be added.

2025-11-21: Added dependency on overlay proposal; removed descriptions of the overlay operations added by that proposal.

2026-02-24: Renamed and split concept of incremental location lists into separate proposal 252017.2.

2026-02-28: Added comparison to multiloc proposal 260227.1.

2026-03-12: Fixed typo, where DW_OP_copy referred to “composite” instead of “compound” location.